Hi

This is the big one, bringing all lib functionality over.

If you want this split up, please mention in which way ;)

Please apply the cheetah patch before this one.

- Lauri
>From 11305663f1e331b1dfd4a68d159dcb4795172a2c Mon Sep 17 00:00:00 2001
From: Lauri Kasanen <[email protected]>
Date: Tue, 7 Aug 2012 16:35:09 +0300
Subject: [PATCH] lib: Bring the bulk of lib over

Some mime functions get exported, config init & reading is separated, and some 
functions are
moved around so that they can be ifdef'd out, to create a smaller library.

Signed-off-by: Lauri Kasanen <[email protected]>
---
 configure                   |  118 +++++++--
 src/include/mk_lib.h        |   45 +++
 src/include/mk_mimetype.h   |   10 +-
 src/include/mk_plugin.h     |    2 +
 src/include/mk_scheduler.h  |    9 +-
 src/include/public/monkey.h |  191 +++++++++++++
 src/mk_clock.c              |    2 +-
 src/mk_config.c             |   70 +++---
 src/mk_lib.c                |  624 +++++++++++++++++++++++++++++++++++++++++++
 src/mk_mimetype.c           |   34 ++--
 src/mk_plugin.c             |  121 ++++++++-
 src/mk_scheduler.c          |   14 +-
 src/mk_server.c             |    6 +-
 src/mk_signals.c            |    5 +
 src/mk_user.c               |    4 +
 src/mk_utils.c              |   70 +++---
 src/monkey.c                |    3 +
 17 files changed, 1209 insertions(+), 119 deletions(-)
 create mode 100644 src/include/mk_lib.h
 create mode 100644 src/include/public/monkey.h
 create mode 100644 src/mk_lib.c

diff --git a/configure b/configure
index e1ea409..04a0556 100755
--- a/configure
+++ b/configure
@@ -23,6 +23,7 @@ __MONKEY_MINOR__="1"
 __MONKEY_PATCHLEVEL__="0"
 
 VERSION="$__MONKEY__.$__MONKEY_MINOR__.$__MONKEY_PATCHLEVEL__"
+SONAME="libmonkey.so.$__MONKEY__.$__MONKEY_MINOR__"
 SYSNAME=`uname -s`
 SYSINFO=`uname -sr`
 INCDIR="src/include/"
@@ -160,8 +161,8 @@ main()
 
         echo
         echo -e "\033[1m=== Monkey Configuration ===\033[0m"
-        echo -e "PLATFORM\t= $platform"
-        echo -e "COMPILER\t= $CC"
+        echo -e "Platform\t= $platform"
+        echo -e "Compiler\t= $CC"
         echo -e "CFLAGS\t\t= $CFLAGS"
         echo -e "LDFLAGS\t\t= $LDFLAGS"
 
@@ -169,16 +170,26 @@ main()
             echo -e "DEFS\t\t= $DEFS"
         fi
 
+       echo
+
+       echo -en "Shared library\t= "
+       [ -n "$sharedlib" ] && echo "enabled" || echo "disabled"
+
+       echo -en "Relaxed plugins\t= "
+       [ -n "$relaxed_plugins" ] && echo "enabled" || echo "disabled"
+
         echo
-        echo -e "PREFIX\t\t= $prefix"
-        echo -e "BINDIR\t\t= $bindir"
-        echo -e "SYSCONFDIR\t= $sysconfdir"
-        echo -e "DATADIR\t\t= $datadir"
-        echo -e "MANDIR\t\t= $mandir"
-        echo -e "LOGDIR\t\t= $logdir"
+        echo -e "Prefix\t\t= $prefix"
+        echo -e "Bindir\t\t= $bindir"
+        echo -e "Libdir\t\t= $libdir"
+        echo -e "Incdir\t\t= $incdir"
+        echo -e "Sysconfdir\t= $sysconfdir"
+        echo -e "Datadir\t\t= $datadir"
+        echo -e "Mandir\t\t= $mandir"
+        echo -e "Logdir\t\t= $logdir"
 
        if [ "$plugdir" != "" ]; then
-            echo -e "PLUGDIR\t\t= $plugdir"
+            echo -e "Plugdir\t\t= $plugdir"
         fi
 
         echo
@@ -323,19 +334,26 @@ done;
 plgconf=`cat plugins.conf`
 rm -rf plugins.conf
 
+if [ -n "$sharedlib" ]; then
+    incinstall="       install -m 644 src/include/public/* \$(INCDIR)"
+fi
+
 cat > Makefile <<EOF
 # Monkey HTTP Daemon: Makefile
 # ============================
 export monkey_root=\$(CURDIR)
 PREFIX=\$(DESTDIR)${prefix}
 BINDIR=\$(DESTDIR)${bindir}
+LIBDIR=\$(DESTDIR)${libdir}
+INCDIR=\$(DESTDIR)${incdir}
 MANDIR=\$(DESTDIR)${mandir}
 SYSCONFDIR=\$(DESTDIR)${sysconfdir}
 DATADIR=\$(DESTDIR)${datadir}
 LOGDIR=\$(DESTDIR)${logdir}
 PLUGINDIR=\$(DESTDIR)${plugdir}
+VERSION=$VERSION
 
-all:
+all: monkey.pc
        @\$(MAKE) -s -C src all
        @\$(MAKE) -s -C plugins all
        @echo "  DONE"
@@ -343,6 +361,7 @@ all:
 clean:
        @(cd src; \$(MAKE) clean)
        @(cd plugins; \$(MAKE) clean)
+       @rm -f monkey.pc
 
 distclean:
        @(cd src; \$(MAKE) distclean)
@@ -350,6 +369,8 @@ distclean:
 install:
        \$(MAKE) -C src all
        install -d \$(BINDIR)
+       install -d \$(LIBDIR)/pkgconfig
+       install -d \$(INCDIR)
        install -d \$(MANDIR)/man1
        install -d \$(MANDIR)/man3
        install -d \$(SYSCONFDIR)
@@ -370,8 +391,13 @@ $plglist
        install -m 644 ./man/*.3 \$(MANDIR)/man3
        install -m 644 ./htdocs/*.* \$(DATADIR)
        install -m 644 ./htdocs/imgs/*.* \${DATADIR}/imgs
-       $STRIP \$(BINDIR)/monkey
-       $STRIP \${PLUGINDIR}/*
+$incinstall
+       -install -m 644 src/$SONAME \$(LIBDIR)
+       -install -m 644 monkey.pc \$(LIBDIR)/pkgconfig
+       -ln -sf $SONAME \$(LIBDIR)/libmonkey.so
+       -$STRIP --strip-unneeded \$(LIBDIR)/$SONAME
+       -$STRIP --strip-unneeded \$(BINDIR)/monkey
+       -$STRIP --strip-unneeded \${PLUGINDIR}/*
        @echo
        @echo  " Running Monkey :"
        @echo  " ----------------"
@@ -381,6 +407,10 @@ $plglist
        @echo  "  For more help use '-h' option"
        @echo
 
+monkey.pc:
+       @sed -e "s@PREFIX@$prefix@" -e "s@LIBDIR@$libdir@" -e 
"s@INCDIR@$incdir@" \
+           -e "s@VERSION@$VERSION@" monkey.pc.in > monkey.pc
+
 EOF
 }
 
@@ -394,12 +424,19 @@ elif [ $platform == "android" ]; then
     libs=""
 fi
 
+if [ -n "$sharedlib" ]; then
+       alltarget="../bin/monkey lib"
+else
+       alltarget="../bin/monkey"
+fi
+
 cat > src/Makefile<<EOF
 _PATH   = \$(patsubst \$(monkey_root)/%, %, \$(CURDIR))
 CC     = @echo "  CC   \$(_PATH)/\$@"; $CC
 CC_QUIET= @echo -n; $CC
 CFLAGS = $CFLAGS
-DEFS    = $DEFS
+DEFS    += $DEFS
+LIBDEFS = -DSHAREDLIB -fPIC \$(DEFS)
 INCDIR  = ./include
 LDFLAGS        = $LDFLAGS
 DESTDIR        = ../bin/monkey
@@ -409,17 +446,25 @@ OBJ       = monkey.o mk_method.o mk_mimetype.o 
mk_request.o \\
        mk_user.o mk_utils.o mk_epoll.o mk_scheduler.o \\
        mk_string.o mk_memory.o mk_connection.o mk_iov.o mk_http.o \\
        mk_file.o mk_socket.o mk_clock.o mk_cache.o \\
-       mk_server.o mk_plugin.o
+       mk_server.o mk_plugin.o mk_lib.o
+LIBOBJ  = \$(OBJ:.o=.lo)
+
+.PHONY: clean distclean lib
 
-all: ../bin/monkey
+all: $alltarget
+
+lib: $SONAME
 
 -include \$(OBJ:.o=.d)
 
 ../bin/monkey: \$(OBJ)
        \$(CC_QUIET) \$(CFLAGS) \$(DEFS) \$(LDFLAGS) -o \$@ \$(OBJ) $mod_obj 
\$(LIBS)
 
+$SONAME: \$(LIBOBJ)
+       \$(CC_QUIET) \$(CFLAGS) \$(LIBDEFS) \$(LDFLAGS) -Wl,-soname,$SONAME 
-shared -o \$@ \$(LIBOBJ) $mod_obj \$(LIBS)
+
 clean:
-       rm -rf *.[od]
+       rm -rf *.[od] $SONAME *.lo
        rm -rf ../bin/monkey
 
 distclean:
@@ -431,6 +476,10 @@ distclean:
 .c.o:
        \$(CC) -c \$(CFLAGS) \$(DEFS) -I\$(INCDIR) \$<
        \$(CC_QUIET) -MM -MP \$(CFLAGS) \$(DEFS) -I\$(INCDIR) \$*.c -o \$*.d > 
/dev/null &2>&1
+
+%.lo : %.c
+       \$(CC) -c -o \$@ \$(CFLAGS) \$(LIBDEFS) -I\$(INCDIR) \$<
+
 EOF
 }
 
@@ -589,9 +638,15 @@ cat > $INCDIR/mk_info.h <<EOF
                                 __MONKEY_PATCHLEVEL__)
 #define VERSION "$__MONKEY__.$__MONKEY_MINOR__.$__MONKEY_PATCHLEVEL__"
 #define MONKEY_PATH_CONF "$sysconfdir"
+#define PLUGDIR "$plugdir"
 
 #endif
 EOF
+
+sed -i -e "s@#define MONKEY__.*@#define MONKEY__            $__MONKEY__@" \
+-e "s@#define MONKEY_MINOR__.*@#define MONKEY_MINOR__      $__MONKEY_MINOR__@" 
\
+-e "s@#define MONKEY_PATCHLEVEL__.*@#define MONKEY_PATCHLEVEL__ 
$__MONKEY_PATCHLEVEL__@" \
+$INCDIR/public/monkey.h
 }
 
 create_conf()
@@ -600,6 +655,8 @@ cat > $INCDIR/config.path <<EOF
 #!/bin/sh
 prefix=$prefix
 bindir=$bindir
+libdir=$libdir
+incdir=$incdir
 sysconfdir=$sysconfdir
 datadir=$datadir
 logdir=$logdir
@@ -729,6 +786,8 @@ aux=`pwd`
 
 prefix="$aux"
 bindir="$aux/bin"
+libdir="$aux/lib"
+incdir=""
 mandir="$aux/man"
 sysconfdir="$aux/conf"
 datadir="$aux/htdocs"
@@ -756,6 +815,8 @@ for arg in $*; do
                --prefix*)
                        prefix=$optarg
                        bindir="$optarg/bin"
+                       libdir="$optarg/lib"
+                       incdir="$optarg/include"
                         mandir="$optarg/man"
                        sysconfdir="$optarg/conf"
                        datadir="$optarg/htdocs"
@@ -774,6 +835,12 @@ for arg in $*; do
                --datadir*)
                        datadir=$optarg
                        ;;
+               --libdir*)
+                       libdir=$optarg
+                       ;;
+               --incdir*)
+                       incdir=$optarg
+                       ;;
                --logdir*)
                        logdir=$optarg
                        ;;
@@ -786,6 +853,12 @@ for arg in $*; do
                --trace*)
                        trace=1
                        ;;
+               --enable-shared*)
+                       sharedlib=1
+                       ;;
+               --enable-relaxed-plugins*)
+                       relaxed_plugins=1
+                       ;;
                 --enable-plugins*)
                        enabled_plugins=$optarg
                         ;;
@@ -831,9 +904,16 @@ for arg in $*; do
                        echo "  --trace                 Enable trace messages 
(don't use in production)"
                         echo "  --platform=PLATFORM     Target platform: 
'generic' or 'android' (default: generic)"
                        echo
+                       echo "Shared library options:"
+                        echo "  --enable-shared         Build Monkey as a 
shared library in addition to a stand-alone server"
+                        echo "  --enable-relaxed-plugins Allow the application 
to make the library load arbitrary plugins."
+                        echo "                          WARNING security risk, 
do not enable in distro packages!"
+                       echo
                         echo "Installation Directories:"
                        echo "  --prefix=PREFIX         Root prefix directory"
                        echo "  --bindir=BINDIR         Binary files 
(executables)"
+                       echo "  --libdir=LIBDIR         Libraries"
+                       echo "  --incdir=INCDIR         Header install path"
                        echo "  --sysconfdir=SYSCONFDIR Configuration files"
                        echo "  --datadir=DATADIR       Specific Monkey data 
files"
                         echo "  --mandir=MANDIR         Manpages - 
documentation"
@@ -889,11 +969,13 @@ if test -z "$STRIP" ; then
     STRIP="strip"
 fi
 
+[ -n "$relaxed_plugins" ] && DEFS="$DEFS -DRELAXED_PLUGINS"
+
 if test -z "$debug" ; then
-    CFLAGS="$CFLAGS -O2 -Wall"
+    CFLAGS="$CFLAGS -O2 -Wall -Wextra"
 else
     DEFS="-DDEBUG -DSAFE_FREE"
-    CFLAGS="$CFLAGS -g -Wall"
+    CFLAGS="$CFLAGS -g -Wall -Wextra"
 fi
 CFLAGS="$CFLAGS -fvisibility=hidden"
 
diff --git a/src/include/mk_lib.h b/src/include/mk_lib.h
new file mode 100644
index 0000000..f57ec45
--- /dev/null
+++ b/src/include/mk_lib.h
@@ -0,0 +1,45 @@
+/*  Monkey HTTP Daemon
+ *  ------------------
+ *  Copyright (C) 2001-2012, Eduardo Silva P. <[email protected]>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 
USA.
+ */
+
+#ifndef MK_LIB_H
+#define MK_LIB_H
+
+#include "mk_macros.h"
+#include "public/monkey.h"
+
+/* Data */
+
+struct mklib_ctx_t {
+    pthread_t tid;
+    pthread_t clock;
+    pthread_t *workers;
+
+    cb_ipcheck ipf;
+    cb_urlcheck urlf;
+    cb_data dataf;
+    cb_close closef;
+
+    struct mklib_worker_info **worker_info;
+
+    const char *plugdir;
+
+    int lib_running;
+};
+
+#endif
diff --git a/src/include/mk_mimetype.h b/src/include/mk_mimetype.h
index 1d02159..a81e922 100644
--- a/src/include/mk_mimetype.h
+++ b/src/include/mk_mimetype.h
@@ -34,9 +34,17 @@ struct mimetype
     mk_pointer type;
 };
 
-struct mimetype *mimetype_default;
+/* amount of the top used mime types */
+enum {
+    MIME_COMMON=10
+};
+
+extern struct mimetype *mimetype_default;
 
+int mk_mimetype_add(const char *name, const char *type, const int common);
 void mk_mimetype_read_config(void);
 struct mimetype *mk_mimetype_find(mk_pointer * filename);
+inline struct mimetype *mk_mimetype_lookup(const char *name);
+void mk_mimearr_sort();
 
 #endif
diff --git a/src/include/mk_plugin.h b/src/include/mk_plugin.h
index 2ad7a5a..d6816ae 100644
--- a/src/include/mk_plugin.h
+++ b/src/include/mk_plugin.h
@@ -308,6 +308,7 @@ struct plugin_info {
 };
 
 void mk_plugin_init();
+void mk_plugin_read_config();
 void mk_plugin_exit_all();
 
 void mk_plugin_event_init_list();
@@ -337,6 +338,7 @@ int mk_plugin_event_error(int socket);
 int mk_plugin_event_close(int socket);
 int mk_plugin_event_timeout(int socket);
 
+void *mk_plugin_load(const char *path);
 void mk_plugin_register_to(struct plugin **st, struct plugin *p);
 void *mk_plugin_load_symbol(void *handler, const char *symbol);
 int mk_plugin_http_request_end(int socket);
diff --git a/src/include/mk_scheduler.h b/src/include/mk_scheduler.h
index b3a25f1..9a687e8 100644
--- a/src/include/mk_scheduler.h
+++ b/src/include/mk_scheduler.h
@@ -25,6 +25,7 @@
 #include <arpa/inet.h>
 
 #include "mk_list.h"
+#include "mk_lib.h"
 
 #ifndef MK_SCHEDULER_H
 #define MK_SCHEDULER_H
@@ -59,6 +60,9 @@ struct sched_list_node
     unsigned char initialized;
 
     struct client_session *request_handler;
+#ifdef SHAREDLIB
+    mklib_ctx ctx;
+#endif
 };
 
 extern struct sched_list_node *sched_list;
@@ -69,6 +73,9 @@ typedef struct
     int epoll_fd;
     int epoll_max_events;
     int max_events;
+#ifdef SHAREDLIB
+    mklib_ctx ctx;
+#endif
 } sched_thread_conf;
 
 extern pthread_key_t worker_sched_node;
@@ -76,7 +83,7 @@ extern pthread_key_t worker_sched_node;
 extern pthread_mutex_t mutex_worker_init;
 
 void mk_sched_init();
-int mk_sched_launch_thread(int max_events, pthread_t *tout);
+int mk_sched_launch_thread(int max_events, pthread_t *tout, mklib_ctx ctx);
 void *mk_sched_launch_epoll_loop(void *thread_conf);
 struct sched_list_node *mk_sched_get_handler_owner(void);
 
diff --git a/src/include/public/monkey.h b/src/include/public/monkey.h
new file mode 100644
index 0000000..b1526aa
--- /dev/null
+++ b/src/include/public/monkey.h
@@ -0,0 +1,191 @@
+/*  Monkey HTTP Daemon
+ *  ------------------
+ *  Copyright (C) 2001-2012, Eduardo Silva P. <[email protected]>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 
USA.
+ */
+
+#ifndef MK_MONKEYLIB_H
+#define MK_MONKEYLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <pthread.h>
+
+#if __GNUC__ >= 4
+ #define NULL_TERMINATED __attribute__ ((sentinel))
+#else
+ #define NULL_TERMINATED
+#endif
+
+/* For the internal build */
+#ifdef SHAREDLIB
+ #include <mk_macros.h>
+#else
+ #ifndef MK_EXPORT
+ #define MK_EXPORT
+ #endif
+#endif
+
+#define MONKEY__
+#define MONKEY_MINOR__
+#define MONKEY_PATCHLEVEL__
+
+/* ---------------------------------
+ *               Data
+ * --------------------------------- */
+
+/* Opaque pointer, not for use for the apps */
+typedef struct mklib_ctx_t* mklib_ctx;
+
+enum {
+    MKLIB_FALSE = 0,
+    MKLIB_TRUE = 1
+};
+
+struct mklib_vhost {
+    const char *name;
+    const char *document_root;
+    const char *server_names;
+};
+
+struct mklib_worker_info {
+    unsigned long long active_connections;
+    int pid;
+};
+
+struct mklib_mime {
+    const char *name;
+    const char *type;
+};
+
+/* Supported plugins, OR'ed in the init call */
+enum {
+    MKLIB_LIANA = 0x1,
+    MKLIB_LIANA_SSL = 0x2
+};
+
+/* Config options for the main config call */
+enum mklib_mkc {
+    MKC_WORKERS = 1,
+    MKC_TIMEOUT,
+    MKC_USERDIR,
+    MKC_INDEXFILE,
+    MKC_HIDEVERSION,
+    MKC_RESUME,
+    MKC_KEEPALIVE,
+    MKC_KEEPALIVETIMEOUT,
+    MKC_MAXKEEPALIVEREQUEST,
+    MKC_MAXREQUESTSIZE,
+    MKC_SYMLINK,
+    MKC_DEFAULTMIMETYPE
+};
+
+/* Config options for the vhost config call */
+enum mklib_mkv {
+    MKV_SERVERNAME = 1,
+    MKV_DOCUMENTROOT
+};
+
+/* Callbacks */
+enum mklib_cb {
+    MKCB_IPCHECK = 1,
+    MKCB_URLCHECK,
+    MKCB_DATA,
+    MKCB_CLOSE
+};
+
+/* struct session_request need not be exposed */
+typedef void mklib_session;
+
+/* Called when a new connection arrives. Return MKLIB_FALSE to reject this 
connection. */
+typedef int (*cb_ipcheck)(const char *ip);
+
+/* Called when the URL is known. Return MKLIB_FALSE to reject this connection. 
*/
+typedef int (*cb_urlcheck)(const char *url);
+
+/* The data callback. Return MKLIB_FALSE if you don't want to handle this URL
+ * (it will be checked against real files at this vhost's DocumentRoot).
+ *
+ * Set *content to point to the content memory. It must
+ * stay available until the close callback is called.
+ *
+ * *header has static storage of 256 bytes for any custom headers. */
+typedef int (*cb_data)(const mklib_session *, const char *vhost, const char 
*url,
+                       const char *get, unsigned long get_len, const char 
*post, unsigned long post_len,
+                       unsigned int *status, const char **content, unsigned 
long *clen,
+                       char *header);
+
+/* This will be called after the content has been served. If you allocated
+ * any memory, you can match that memory to the mklib_session pointer and free
+ * it in this callback. */
+typedef void (*cb_close)(const mklib_session *);
+
+
+/* ---------------------------------
+ *                API
+ * --------------------------------- */
+
+/* Returns NULL on error. All pointer arguments may be NULL and the 
port/plugins
+ * may be 0 for the defaults in each case.
+ *
+ * With no address, bind to all.
+ * With no port, use 2001.
+ * With no plugins, default to MKLIB_LIANA only.
+ * With no documentroot, the default vhost won't access files.
+ */
+mklib_ctx MK_EXPORT mklib_init(const char *address, const unsigned int port,
+                               const unsigned int plugins, const char 
*documentroot);
+
+/* Set the callbacks. */
+int MK_EXPORT mklib_callback_set(mklib_ctx, const enum mklib_cb, void *);
+
+/* NULL-terminated config call, consisting of pairs of config item and 
argument.
+ * Returns MKLIB_FALSE on failure. */
+int MK_EXPORT mklib_config(mklib_ctx, ...) NULL_TERMINATED;
+
+/* NULL-terminated config call creating a vhost with *name. Returns MKLIB_FALSE
+ * on failure. */
+int MK_EXPORT mklib_vhost_config(mklib_ctx, const char *name, ...) 
NULL_TERMINATED;
+
+/* Start the server. */
+int MK_EXPORT mklib_start(mklib_ctx);
+
+/* Stop the server and free mklib_ctx. */
+int MK_EXPORT mklib_stop(mklib_ctx);
+
+/* Return a list of existing vhosts */
+struct mklib_vhost MK_EXPORT **mklib_vhost_list(mklib_ctx);
+
+/* Return a list of the workers */
+struct mklib_worker_info MK_EXPORT **mklib_scheduler_worker_info(mklib_ctx);
+
+/* Return a list of all mimetypes */
+struct mklib_mime MK_EXPORT **mklib_mimetype_list(mklib_ctx);
+
+/* Add a new mimetype */
+int MK_EXPORT mklib_mimetype_add(mklib_ctx, const char *, const char *);
+
+#define mklib_vhost_foreach(cur, list) for(cur = *list++; cur; cur = *list++)
+#define mklib_worker_info_foreach(cur, list) mklib_vhost_foreach(cur, list)
+#define mklib_mimetype_foreach(cur, list) mklib_vhost_foreach(cur, list)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mk_clock.c b/src/mk_clock.c
index 7016864..b048a8a 100644
--- a/src/mk_clock.c
+++ b/src/mk_clock.c
@@ -81,7 +81,7 @@ static void mk_clock_header_set_time(time_t utime)
     header_current_time.data = time_string;
 }
 
-void *mk_clock_worker_init(void *args)
+void *mk_clock_worker_init(void *args UNUSED_PARAM)
 {
     time_t cur_time;
 
diff --git a/src/mk_config.c b/src/mk_config.c
index 16c2c34..79d230f 100644
--- a/src/mk_config.c
+++ b/src/mk_config.c
@@ -45,14 +45,6 @@
 #include "mk_plugin.h"
 #include "mk_macros.h"
 
-/* Print a specific error */
-static void mk_config_print_error_msg(char *variable, char *path)
-{
-    mk_err("Error in %s variable under %s, has an invalid value",
-           variable, path);
-    exit(EXIT_FAILURE);
-}
-
 struct server_config *config;
 
 /* Raise a configuration schema error */
@@ -363,6 +355,16 @@ void *mk_config_section_getval(struct mk_config_section 
*section, char *key, int
     return NULL;
 }
 
+#ifndef SHAREDLIB
+
+/* Print a specific error */
+static void mk_config_print_error_msg(char *variable, char *path)
+{
+    mk_err("Error in %s variable under %s, has an invalid value",
+           variable, path);
+    exit(EXIT_FAILURE);
+}
+
 /* Read configuration files */
 static void mk_config_read_files(char *path_conf, char *file_conf)
 {
@@ -710,6 +712,33 @@ struct host *mk_config_get_host(char *path)
     return host;
 }
 
+/* read main configuration from monkey.conf */
+void mk_config_start_configure(void)
+{
+    unsigned long len;
+
+    mk_config_set_init_values();
+    mk_config_read_files(config->file_config, M_DEFAULT_CONFIG_FILE);
+
+    /* Load mimes */
+    mk_mimetype_read_config();
+
+    mk_pointer_reset(&config->server_software);
+
+    /* Basic server information */
+    if (config->hideversion == MK_FALSE) {
+        mk_string_build(&config->server_software.data,
+                        &len, "Monkey/%s (%s)", VERSION, OS);
+        config->server_software.len = len;
+    }
+    else {
+        mk_string_build(&config->server_software.data, &len, "Monkey Server");
+        config->server_software.len = len;
+    }
+}
+
+#endif // !SHAREDLIB
+
 void mk_config_set_init_values(void)
 {
     /* Init values */
@@ -758,31 +787,6 @@ void mk_config_set_init_values(void)
     mk_list_init(config->plugins);
 }
 
-/* read main configuration from monkey.conf */
-void mk_config_start_configure(void)
-{
-    unsigned long len;
-
-    mk_config_set_init_values();
-    mk_config_read_files(config->file_config, M_DEFAULT_CONFIG_FILE);
-
-    /* Load mimes */
-    mk_mimetype_read_config();
-
-    mk_pointer_reset(&config->server_software);
-
-    /* Basic server information */
-    if (config->hideversion == MK_FALSE) {
-        mk_string_build(&config->server_software.data,
-                        &len, "Monkey/%s (%s)", VERSION, OS);
-        config->server_software.len = len;
-    }
-    else {
-        mk_string_build(&config->server_software.data, &len, "Monkey Server");
-        config->server_software.len = len;
-    }
-}
-
 int mk_config_host_find(mk_pointer host, struct host **vhost, struct 
host_alias **alias)
 {
     struct host *entry_host;
diff --git a/src/mk_lib.c b/src/mk_lib.c
new file mode 100644
index 0000000..274fc73
--- /dev/null
+++ b/src/mk_lib.c
@@ -0,0 +1,624 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Monkey HTTP Daemon
+ * ------------------
+ * Copyright (C) 2012, Lauri Kasanen <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 
USA.
+ */
+
+/* Only built for the library */
+#ifdef SHAREDLIB
+
+#include <stdio.h>
+#include <mk_lib.h>
+#include <mk_utils.h>
+#include <mk_memory.h>
+#include <mk_config.h>
+#include <mk_info.h>
+#include <mk_string.h>
+#include <mk_plugin.h>
+#include <dlfcn.h>
+#include <mk_clock.h>
+#include <mk_mimetype.h>
+#include <mk_server.h>
+#include <stdarg.h>
+#include <limits.h>
+
+/* These are only needed here, not public for all of monkey */
+extern int mime_nitem;
+extern struct mimetype *mimecommon, *mimearr;
+
+static struct host *mklib_host_find(const char *name)
+{
+    struct host *entry_host;
+    const struct mk_list *head_vhost;
+
+    mk_list_foreach(head_vhost, &config->hosts) {
+        entry_host = mk_list_entry(head_vhost, struct host, _head);
+
+        if (strcmp(name, entry_host->file) == 0) return entry_host;
+    }
+
+    return NULL;
+}
+
+
+static void mklib_run(void *p)
+{
+    int remote_fd, ret;
+    const mklib_ctx ctx = p;
+
+    mk_utils_worker_rename("libmonkey");
+    mk_socket_set_tcp_defer_accept(config->server_fd);
+
+    while (1) {
+
+        if (!ctx->lib_running) {
+            sleep(1);
+            continue;
+        }
+
+        remote_fd = mk_socket_accept(config->server_fd);
+        if (remote_fd == -1) continue;
+
+        ret = mk_sched_add_client(remote_fd);
+        if (ret == -1) close(remote_fd);
+    }
+}
+
+static int load_networking(const char *path)
+{
+    void *handle;
+    struct plugin *p;
+    int ret;
+
+    handle = mk_plugin_load(path);
+    if (!handle) return MKLIB_FALSE;
+
+    p = mk_plugin_alloc(handle, path);
+    if (!p) {
+        dlclose(handle);
+        return MKLIB_FALSE;
+    }
+
+    ret = p->init(&api, "");
+    if (ret < 0) {
+        mk_plugin_free(p);
+        dlclose(handle);
+        return MKLIB_FALSE;
+    }
+
+    mk_plugin_register(p);
+    return MKLIB_TRUE;
+}
+
+int mklib_callback_set(mklib_ctx ctx, const enum mklib_cb cb, void *func)
+{
+    /* Function is allowed to be NULL, to reset it) */
+    if (!ctx || !cb || ctx->lib_running) return MKLIB_FALSE;
+
+    switch(cb) {
+        case MKCB_IPCHECK:
+            ctx->ipf = func;
+        break;
+        case MKCB_URLCHECK:
+            ctx->urlf = func;
+        break;
+        case MKCB_DATA:
+            ctx->dataf = func;
+        break;
+        case MKCB_CLOSE:
+            ctx->closef = func;
+        break;
+        default:
+            return MKLIB_FALSE;
+        break;
+    }
+
+    return MKLIB_TRUE;
+}
+
+/* Returns NULL on error. All pointer arguments may be NULL and the 
port/plugins
+ * may be 0 for the defaults in each case.
+ *
+ * With no address, bind to all.
+ * With no port, use 2001.
+ * With no plugins, default to MKLIB_LIANA only.
+ * With no documentroot, the default vhost won't access files.
+ */
+mklib_ctx mklib_init(const char *address, const unsigned int port,
+                     const unsigned int plugins, const char *documentroot)
+{
+    mklib_ctx a = mk_mem_malloc_z(sizeof(struct mklib_ctx_t));
+    if (!a) return NULL;
+
+    config = mk_mem_malloc_z(sizeof(struct server_config));
+    if (!config) goto out;
+
+    config->serverconf = strdup(MONKEY_PATH_CONF);
+    mk_config_set_init_values();
+    mk_sched_init();
+    mk_plugin_init();
+
+    a->plugdir = PLUGDIR;
+
+    char tmppath[PATH_MAX];
+
+    if (plugins & MKLIB_LIANA_SSL) {
+        config->transport_layer = strdup("liana_ssl");
+        snprintf(tmppath, PATH_MAX, "%s/monkey-liana_ssl.so", a->plugdir);
+        if (!load_networking(tmppath)) goto out_config;
+    }
+    else {
+        config->transport_layer = strdup("liana");
+        snprintf(tmppath, PATH_MAX, "%s/monkey-liana.so", a->plugdir);
+        if (!load_networking(tmppath)) goto out_config;
+    }
+
+    if (!plg_netiomap) goto out_config;
+    mk_plugin_preworker_calls();
+
+    if (port) config->serverport = port;
+    if (address) config->listen_addr = strdup(address);
+    else config->listen_addr = strdup(config->listen_addr);
+
+    unsigned long len;
+    struct host *host = mk_mem_malloc_z(sizeof(struct host));
+    /* We hijack this field for the vhost name */
+    host->file = strdup("default");
+    mk_list_init(&host->error_pages);
+    mk_list_init(&host->server_names);
+    mk_string_build(&host->host_signature, &len, "libmonkey");
+    mk_string_build(&host->header_host_signature.data,
+                    &host->header_host_signature.len,
+                    "Server: %s", host->host_signature);
+
+    struct host_alias *alias = mk_mem_malloc_z(sizeof(struct host_alias));
+    alias->name = strdup(config->listen_addr);
+    alias->len = strlen(config->listen_addr);
+    mk_list_add(&alias->_head, &host->server_names);
+
+    mk_list_add(&host->_head, &config->hosts);
+    config->nhosts++;
+
+    if (documentroot) {
+        host->documentroot.data = strdup(documentroot);
+        host->documentroot.len = strlen(documentroot);
+    }
+    else {
+        host->documentroot.data = strdup("/dev/null");
+        host->documentroot.len = sizeof("/dev/null") - 1;
+    }
+
+    config->server_software.data = "";
+    config->server_software.len = 0;
+    config->default_mimetype = mk_string_dup(MIMETYPE_DEFAULT_TYPE);
+    mk_mimetype_read_config();
+
+    config->worker_capacity = mk_server_worker_capacity(config->workers);
+    config->max_load = (config->worker_capacity * config->workers);
+
+    /* Server listening socket */
+    config->server_fd = mk_socket_server(config->serverport, 
config->listen_addr);
+
+    /* Clock thread */
+    mk_clock_sequential_init();
+    a->clock = mk_utils_worker_spawn((void *) mk_clock_worker_init, NULL);
+
+    mk_mem_pointers_init();
+    mk_thread_keys_init();
+
+    return a;
+
+    out_config:
+    free(config);
+
+    out:
+    free(a);
+
+    return NULL;
+}
+
+/* NULL-terminated config call, consisting of pairs of config item and 
argument.
+ * Returns MKLIB_FALSE on failure. */
+int mklib_config(mklib_ctx ctx, ...)
+{
+    if (!ctx || ctx->lib_running) return MKLIB_FALSE;
+
+    unsigned long len;
+    int i;
+    char *s;
+    va_list va;
+
+    va_start(va, ctx);
+
+    i = va_arg(va, int);
+    while (i) {
+        const enum mklib_mkc e = i;
+
+        switch(e) {
+            case MKC_WORKERS:
+                i = va_arg(va, int);
+                config->workers = i;
+                config->worker_capacity = 
mk_server_worker_capacity(config->workers);
+                config->max_load = (config->worker_capacity * config->workers);
+
+                free(sched_list);
+                mk_sched_init();
+            break;
+            case MKC_TIMEOUT:
+                i = va_arg(va, int);
+                config->timeout = i;
+            break;
+            case MKC_USERDIR:
+                s = va_arg(va, char *);
+                if (config->user_dir) free(config->user_dir);
+                config->user_dir = strdup(s);
+            break;
+            case MKC_INDEXFILE:
+                s = va_arg(va, char *);
+                if (config->index_files) 
mk_string_split_free(config->index_files);
+                config->index_files = mk_string_split_line(s);
+            break;
+            case MKC_HIDEVERSION:
+                i = va_arg(va, int);
+                config->server_software.data = NULL;
+
+                /* Basic server information */
+                if (!i) {
+                    mk_string_build(&config->server_software.data,
+                                    &len, "libmonkey/%s (%s)", VERSION, OS);
+                }
+                else {
+                    mk_string_build(&config->server_software.data, &len, 
"libmonkey");
+                }
+                config->server_software.len = len;
+
+                /* Mark it so for the default vhost */
+                struct mk_list *hosts = &config->hosts;
+                struct host *def = mk_list_entry_first(hosts, struct host, 
_head);
+                free(def->host_signature);
+                free(def->header_host_signature.data);
+                def->header_host_signature.data = NULL;
+
+                def->host_signature = strdup(config->server_software.data);
+                mk_string_build(&def->header_host_signature.data,
+                                &def->header_host_signature.len,
+                                "Server: %s", def->host_signature);
+            break;
+            case MKC_RESUME:
+                i = va_arg(va, int);
+                config->resume = i ? MK_TRUE : MK_FALSE;
+            break;
+            case MKC_KEEPALIVE:
+                i = va_arg(va, int);
+                config->keep_alive = i ? MK_TRUE : MK_FALSE;
+            break;
+            case MKC_KEEPALIVETIMEOUT:
+                i = va_arg(va, int);
+                config->keep_alive_timeout = i;
+            break;
+            case MKC_MAXKEEPALIVEREQUEST:
+                i = va_arg(va, int);
+                config->max_keep_alive_request = i;
+            break;
+            case MKC_MAXREQUESTSIZE:
+                i = va_arg(va, int);
+                config->max_request_size = i;
+            break;
+            case MKC_SYMLINK:
+                i = va_arg(va, int);
+                config->symlink = i ? MK_TRUE : MK_FALSE;
+            break;
+            case MKC_DEFAULTMIMETYPE:
+                s = va_arg(va, char *);
+                free(config->default_mimetype);
+                config->default_mimetype = NULL;
+                mk_string_build(&config->default_mimetype, &len, "%s\r\n", s);
+                mk_pointer_set(&mimetype_default->type, 
config->default_mimetype);
+            break;
+            default:
+                mk_warn("Unknown config option");
+            break;
+        }
+
+        i = va_arg(va, int);
+    }
+
+    va_end(va);
+    return MKLIB_TRUE;
+}
+
+/* NULL-terminated config call creating a vhost with *name. Returns MKLIB_FALSE
+ * on failure. */
+int mklib_vhost_config(mklib_ctx ctx, const char *name, ...)
+{
+    if (!ctx) return MKLIB_FALSE;
+
+    /* Does it exist already? */
+    struct host *h = mklib_host_find(name);
+    if (h) return MKLIB_FALSE;
+
+    const struct host *defaulth = mklib_host_find("default");
+    if (!defaulth) return MKLIB_FALSE;
+
+
+    h = mk_mem_malloc_z(sizeof(struct host));
+    h->file = strdup(name);
+
+    h->documentroot.data = strdup("/dev/null");
+    h->documentroot.len = sizeof("/dev/null") - 1;
+
+    mk_list_init(&h->error_pages);
+    mk_list_init(&h->server_names);
+
+    char *s;
+    int i;
+    va_list va;
+
+    va_start(va, name);
+
+    i = va_arg(va, int);
+    while (i) {
+        const enum mklib_mkv e = i;
+
+        switch(e) {
+            case MKV_SERVERNAME:
+                s = va_arg(va, char *);
+
+                struct mk_list *head, *list = mk_string_split_line(s);
+
+                mk_list_foreach(head, list) {
+                    struct mk_string_line *entry = mk_list_entry(head,
+                                                                 struct 
mk_string_line,
+                                                                 _head);
+                    if (entry->len > MK_HOSTNAME_LEN - 1) {
+                        continue;
+                    }
+
+                    struct host_alias *alias = mk_mem_malloc_z(sizeof(struct 
host_alias));
+                    alias->name = mk_string_tolower(entry->val);
+                    alias->len = entry->len;
+                    mk_list_add(&alias->_head, &h->server_names);
+                }
+
+                mk_string_split_free(list);
+            break;
+            case MKV_DOCUMENTROOT:
+                s = va_arg(va, char *);
+                free(h->documentroot.data);
+                h->documentroot.data = strdup(s);
+                h->documentroot.len = strlen(s);
+            break;
+            default:
+                mk_warn("Unknown config option");
+            break;
+        }
+
+        i = va_arg(va, int);
+    }
+
+    h->host_signature = strdup(defaulth->host_signature);
+    h->header_host_signature.data = 
strdup(defaulth->header_host_signature.data);
+    h->header_host_signature.len = defaulth->header_host_signature.len;
+
+    mk_list_add(&h->_head, &config->hosts);
+    config->nhosts++;
+
+    va_end(va);
+    return MKLIB_TRUE;
+}
+
+/* Start the server. */
+int mklib_start(mklib_ctx ctx)
+{
+    if (!ctx || ctx->lib_running) return MKLIB_FALSE;
+
+    mk_plugin_core_process();
+
+    ctx->workers = mk_mem_malloc_z(sizeof(pthread_t) * config->workers);
+
+    unsigned int i;
+    const unsigned int workers = config->workers;
+    for (i = 0; i < workers; i++) {
+        mk_sched_launch_thread(config->worker_capacity, &ctx->workers[i], ctx);
+    }
+
+    /* Wait until all workers report as ready */
+    while (1) {
+        unsigned int ready = 0;
+
+        pthread_mutex_lock(&mutex_worker_init);
+        for (i = 0; i < workers; i++) {
+            if (sched_list[i].initialized)
+                ready++;
+        }
+        pthread_mutex_unlock(&mutex_worker_init);
+
+        if (ready == workers) break;
+        usleep(10000);
+    }
+
+    ctx->worker_info = mk_mem_malloc_z(sizeof(struct mklib_worker_info *) * 
(workers + 1));
+    for(i = 0; i < workers; i++) {
+        ctx->worker_info[i] = mk_mem_malloc_z(sizeof(struct 
mklib_worker_info));
+        ctx->worker_info[i]->pid = sched_list[i].pid;
+    }
+
+    ctx->lib_running = 1;
+    ctx->tid = mk_utils_worker_spawn(mklib_run, ctx);
+
+    return MKLIB_TRUE;
+}
+
+/* Stop the server and free mklib_ctx. */
+int mklib_stop(mklib_ctx ctx)
+{
+    if (!ctx || !ctx->lib_running) return MKLIB_FALSE;
+
+    ctx->lib_running = 0;
+    pthread_cancel(ctx->tid);
+
+    int i;
+    for (i = 0; i < config->workers; i++) {
+        pthread_cancel(ctx->workers[i]);
+        free(ctx->worker_info[i]);
+    }
+    free(ctx->worker_info);
+
+    mk_plugin_exit_all();
+
+#ifdef SAFE_FREE
+    mk_config_free_all();
+#else
+    free(config);
+#endif
+
+    free(ctx);
+
+    return MKLIB_TRUE;
+}
+
+struct mklib_vhost **mklib_vhost_list(mklib_ctx ctx)
+{
+    static struct mklib_vhost **lst = NULL;
+    struct host *entry_host;
+    struct host_alias *alias;
+    struct mk_list *head_vhost, *head_aliases;
+    unsigned int i, total = 0, namecount;
+    const char *names[50];
+
+    if (!ctx) return NULL;
+
+    /* Free it if it exists */
+    if (lst) {
+        for (i = 0; lst[i]; i++) {
+            free((char *) lst[i]->server_names);
+            free(lst[i]);
+        }
+
+        free(lst);
+    }
+
+    /* How many are there? */
+    mk_list_foreach(head_vhost, &config->hosts) {
+        total++;
+    }
+    total++;
+
+    lst = mk_mem_malloc_z(sizeof(struct mklib_vhost *) * total);
+
+    total = 0;
+
+    /* Set up the list to return */
+    mk_list_foreach(head_vhost, &config->hosts) {
+        entry_host = mk_list_entry(head_vhost, struct host, _head);
+
+        lst[total] = mk_mem_malloc_z(sizeof(struct mklib_vhost));
+
+        lst[total]->name = entry_host->file;
+        lst[total]->document_root = entry_host->documentroot.data;
+
+        namecount = 0;
+        unsigned int total_len = 1;
+        mk_list_foreach(head_aliases, &entry_host->server_names) {
+            alias = mk_list_entry(head_aliases, struct host_alias, _head);
+            names[namecount] = alias->name;
+            namecount++;
+            total_len += alias->len + 1;
+        }
+
+       char *servernames = mk_mem_malloc_z(total_len);
+        for (i = 0; i < namecount; i++) {
+            strcat(servernames, names[i]);
+            strcat(servernames, " ");
+        }
+
+        lst[total]->server_names = servernames;
+
+        total++;
+    }
+
+    return lst;
+}
+
+struct mklib_worker_info **mklib_scheduler_worker_info(mklib_ctx ctx)
+{
+    unsigned int i;
+    const unsigned int workers = config->workers;
+
+    if (!ctx || !ctx->lib_running) return NULL;
+
+
+    for (i = 0; i < workers; i++) {
+        ctx->worker_info[i]->active_connections = 
sched_list[i].accepted_connections -
+                                                  
sched_list[i].closed_connections;
+    }
+
+    return ctx->worker_info;
+}
+
+/* Return a list of all mimetypes */
+struct mklib_mime **mklib_mimetype_list(mklib_ctx ctx)
+{
+    if (!ctx) return NULL;
+
+    static struct mklib_mime **lst = NULL;
+    unsigned int i;
+    const unsigned int total = mime_nitem + MIME_COMMON;
+
+    if (lst) {
+        for (i = 0; i < total; i++) {
+            free(lst[i]);
+        }
+
+        free(lst);
+    }
+
+    lst = mk_mem_malloc_z((total + 1) * sizeof(struct mklib_mime *));
+
+    for (i = 0; i < total; i++) {
+        lst[i] = mk_mem_malloc_z(sizeof(struct mklib_mime));
+
+        if (i < MIME_COMMON) {
+            lst[i]->name = mimecommon[i].name;
+            lst[i]->type = mimecommon[i].type.data;
+        }
+        else {
+            const unsigned int m = i - MIME_COMMON;
+            lst[i]->name = mimearr[m].name;
+            lst[i]->type = mimearr[m].type.data;
+        }
+    }
+
+    return lst;
+}
+
+/* Add a new mimetype */
+int mklib_mimetype_add(mklib_ctx ctx, const char *name, const char *type)
+{
+    if (!ctx || !name || !type) return MKLIB_FALSE;
+
+    /* Is it added already? */
+    if (mk_mimetype_lookup(name)) return MKLIB_FALSE;
+
+    mk_mimetype_add(name, type, 0);
+    mk_mimearr_sort();
+
+    return MKLIB_TRUE;
+}
+
+#endif
diff --git a/src/mk_mimetype.c b/src/mk_mimetype.c
index c5f574c..94cea47 100644
--- a/src/mk_mimetype.c
+++ b/src/mk_mimetype.c
@@ -36,18 +36,16 @@
 #include "mk_list.h"
 #include "mk_macros.h"
 
-/* amount of the top used mime types */
-#define MIME_COMMON 10
-
-static struct mimetype *mimecommon = NULL; /* old top used mime types */
-static struct mimetype *mimearr = NULL; /* old the rest of the mime types */
-static int nitem = 0; /* amount of available mime types */
+struct mimetype *mimetype_default;
+struct mimetype *mimecommon = NULL; /* old top used mime types */
+struct mimetype *mimearr = NULL; /* old the rest of the mime types */
+int mime_nitem = 0; /* amount of available mime types */
 
 /* add an item to the mimecommon or mimearr variables */
 #define add_mime(item, m) ({                                            \
-    m = (nitem==0) ? mk_mem_malloc(sizeof(struct mimetype)) :           \
-        mk_mem_realloc(m, (nitem + 1) * (sizeof(struct mimetype)));     \
-    m[nitem++] = item;                                                  \
+    m = (mime_nitem==0) ? mk_mem_malloc(sizeof(struct mimetype)) :           \
+        mk_mem_realloc(m, (mime_nitem + 1) * (sizeof(struct mimetype)));     \
+    m[mime_nitem++] = item;                                                  \
 })
 
 static int mime_cmp(const void *m1, const void *m2)
@@ -59,7 +57,7 @@ static int mime_cmp(const void *m1, const void *m2)
 }
 
 /* Match mime type for requested resource */
-static inline struct mimetype *mk_mimetype_lookup(char *name)
+inline struct mimetype *mk_mimetype_lookup(const char *name)
 {
     int i;
     struct mimetype tmp;
@@ -79,10 +77,10 @@ static inline struct mimetype *mk_mimetype_lookup(char 
*name)
     }
 
     tmp.name = name;
-    return bsearch(&tmp, mimearr, nitem, sizeof(struct mimetype), mime_cmp);
+    return bsearch(&tmp, mimearr, mime_nitem, sizeof(struct mimetype), 
mime_cmp);
 }
 
-static int mk_mimetype_add(char *name, char *type, int common)
+int mk_mimetype_add(const char *name, const char *type, const int common)
 {
     int len = strlen(type) + 3;
     struct mimetype new_mime;
@@ -131,7 +129,7 @@ void mk_mimetype_read_config()
         }
         else {
             if (i == MIME_COMMON) {
-                nitem = 0; /* reset counter */
+                mime_nitem = 0; /* reset counter */
             }
             if (mk_mimetype_add(entry->key, entry->val, 0) != 0) {
                 mk_err("Error loading Mime Types");
@@ -140,9 +138,7 @@ void mk_mimetype_read_config()
         i++;
     }
 
-
-    /* sort ascendingly for later binary search */
-    qsort(mimearr, nitem, sizeof(struct mimetype), mime_cmp);
+    mk_mimearr_sort();
 
     /* Set default mime type */
     mimetype_default = mk_mem_malloc_z(sizeof(struct mimetype));
@@ -152,6 +148,12 @@ void mk_mimetype_read_config()
     mk_config_free(cnf);
 }
 
+void mk_mimearr_sort()
+{
+    /* sort ascendingly for later binary search */
+    qsort(mimearr, mime_nitem, sizeof(struct mimetype), mime_cmp);
+}
+
 struct mimetype *mk_mimetype_find(mk_pointer * filename)
 {
     int j, len;
diff --git a/src/mk_plugin.c b/src/mk_plugin.c
index f165dd8..4ab9f8c 100644
--- a/src/mk_plugin.c
+++ b/src/mk_plugin.c
@@ -34,6 +34,10 @@
 #include "mk_plugin.h"
 #include "mk_macros.h"
 
+enum {
+    bufsize = 256
+};
+
 pthread_key_t mk_plugin_event_k;
 
 static struct plugin_stagemap *plg_stagemap;
@@ -299,17 +303,6 @@ void mk_plugin_free(struct plugin *p)
 
 void mk_plugin_init()
 {
-    int ret;
-    char *path;
-    char *plugin_confdir = 0;
-    void *handle;
-    unsigned long len;
-    struct plugin *p;
-    struct mk_config *cnf;
-    struct mk_config_section *section;
-    struct mk_config_entry *entry;
-    struct mk_list *head;
-
     api = mk_mem_malloc_z(sizeof(struct plugin_api));
     __builtin_prefetch(api);
 
@@ -421,6 +414,24 @@ void mk_plugin_init()
     api->stacktrace = (void *) mk_utils_stacktrace;
 #endif
 
+    api->plugins = config->plugins;
+}
+
+#ifndef SHAREDLIB
+
+void mk_plugin_read_config()
+{
+    int ret;
+    char *path;
+    char *plugin_confdir = 0;
+    void *handle;
+    unsigned long len;
+    struct plugin *p;
+    struct mk_config *cnf;
+    struct mk_config_section *section;
+    struct mk_config_entry *entry;
+    struct mk_list *head;
+
     /* Read configuration file */
     path = mk_mem_malloc_z(1024);
     snprintf(path, 1024, "%s/%s", config->serverconf, MK_PLUGIN_LOAD);
@@ -491,14 +502,14 @@ void mk_plugin_init()
         exit(EXIT_FAILURE);
     }
 
-    api->plugins = config->plugins;
-
     /* Look for plugins thread key data */
     mk_plugin_preworker_calls();
     mk_mem_free(path);
     mk_config_free(cnf);
 }
 
+#endif //!SHAREDLIB
+
 /* Invoke all plugins 'exit' hook and free resources by the plugin interface */
 void mk_plugin_exit_all()
 {
@@ -530,6 +541,30 @@ int mk_plugin_stage_run(unsigned int hook,
     int ret;
     struct plugin_stagem *stm;
 
+#ifdef SHAREDLIB
+    struct sched_list_node *thconf = mk_sched_get_thread_conf();
+    mklib_ctx ctx = thconf->ctx;
+    char buf[bufsize], *ptr = buf;
+    unsigned long len;
+
+    if (hook & MK_PLUGIN_STAGE_10 && ctx->ipf) {
+        mk_socket_ip_str(socket, &ptr, bufsize, &len);
+        ret = ctx->ipf(buf);
+        if (ret == MKLIB_FALSE) return MK_PLUGIN_RET_CLOSE_CONX;
+    }
+
+    if (hook & MK_PLUGIN_STAGE_20 && ctx->urlf) {
+        len = sr->uri.len;
+        if (len >= bufsize) len = bufsize - 1;
+        strncpy(buf, sr->uri.data, len);
+        buf[len] = '\0';
+
+        ret = ctx->urlf(buf);
+        if (ret == MKLIB_FALSE) return MK_PLUGIN_RET_CLOSE_CONX;
+    }
+
+#endif
+
     /* Connection just accept(ed) not assigned to worker thread */
     if (hook & MK_PLUGIN_STAGE_10) {
         stm = plg_stagemap->stage_10;
@@ -623,6 +658,66 @@ int mk_plugin_stage_run(unsigned int hook,
         }
     }
 
+#ifdef SHAREDLIB
+
+    if (hook & MK_PLUGIN_STAGE_30 && ctx->dataf) {
+        unsigned int status = 200;
+        unsigned long clen, get_len = 0, post_len = 0;
+        const char *content;
+        char *get = NULL, *post = NULL;
+        char header[bufsize] = "";
+
+        if (sr->query_string.data) {
+            get = mk_mem_malloc_z(sr->query_string.len + 1);
+            memcpy(get, sr->query_string.data, sr->query_string.len);
+            get_len = sr->query_string.len;
+        }
+        if (sr->data.data) {
+            post = mk_mem_malloc_z(sr->data.len + 1);
+            memcpy(post, sr->data.data, sr->data.len);
+            post_len = sr->data.len;
+        }
+
+        len = sr->uri.len;
+        if (len >= bufsize) len = bufsize - 1;
+        strncpy(buf, sr->uri.data, len);
+        buf[len] = '\0';
+
+        ret = ctx->dataf(sr, sr->host_conf->file, buf,
+                         get, get_len, post, post_len,
+                         &status, &content, &clen, header);
+       mk_mem_free(get);
+       mk_mem_free(post);
+
+        if (ret == MKLIB_FALSE) return -1;
+
+        /* Status */
+        api->header_set_http_status(sr, status);
+
+        /* Headers */
+        sr->headers.content_length = clen;
+        len = strlen(header);
+        if (len) api->header_add(sr, header, len);
+        api->header_send(socket, cs, sr);
+
+        /* Data */
+        while (clen > 0) {
+            int remaining = api->socket_send(socket, content, clen);
+            if (remaining < 0) return -1;
+
+            clen -= remaining;
+        }
+        mk_socket_set_cork_flag(socket, TCP_CORK_OFF);
+
+        if (ret == MKLIB_TRUE) return MK_PLUGIN_RET_END;
+    }
+
+    if (hook & MK_PLUGIN_STAGE_40 && ctx->closef) {
+        ctx->closef(sr);
+    }
+
+#endif
+
     return -1;
 }
 
diff --git a/src/mk_scheduler.c b/src/mk_scheduler.c
index ec52132..2569dc7 100644
--- a/src/mk_scheduler.c
+++ b/src/mk_scheduler.c
@@ -222,8 +222,10 @@ static void *mk_sched_launch_worker_loop(void *thread_conf)
     struct sched_list_node *thinfo = NULL;
     mk_epoll_handlers *handler;
 
+#ifndef SHAREDLIB
     /* Avoid SIGPIPE signals */
     mk_signal_thread_sigpipe_safe();
+#endif
 
     /* Init specific thread cache */
     mk_sched_thread_lists_init();
@@ -231,7 +233,6 @@ static void *mk_sched_launch_worker_loop(void *thread_conf)
 
     /* Register working thread */
     wid = mk_sched_register_thread(thconf->epoll_fd);
-    mk_mem_free(thread_conf);
 
     /* Plugin thread context calls */
     mk_epoll_state_init();
@@ -247,6 +248,12 @@ static void *mk_sched_launch_worker_loop(void *thread_conf)
 
     thinfo = &sched_list[wid];
 
+#ifdef SHAREDLIB
+    thinfo->ctx = thconf->ctx;
+#endif
+
+    mk_mem_free(thread_conf);
+
     /* Rename worker */
     mk_string_build(&thread_name, &len, "monkey: wrk/%i", thinfo->idx);
     mk_utils_worker_rename(thread_name);
@@ -268,7 +275,7 @@ static void *mk_sched_launch_worker_loop(void *thread_conf)
  * Create thread which will be listening
  * for incomings file descriptors
  */
-int mk_sched_launch_thread(int max_events, pthread_t *tout)
+int mk_sched_launch_thread(int max_events, pthread_t *tout, mklib_ctx ctx 
UNUSED_PARAM)
 {
     int efd;
     pthread_t tid;
@@ -285,6 +292,9 @@ int mk_sched_launch_thread(int max_events, pthread_t *tout)
     thconf->epoll_fd = efd;
     thconf->epoll_max_events = max_events*2;
     thconf->max_events = max_events;
+#ifdef SHAREDLIB
+    thconf->ctx = ctx;
+#endif
 
     pthread_attr_init(&attr);
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
diff --git a/src/mk_server.c b/src/mk_server.c
index a27a2db..88b3ffd 100644
--- a/src/mk_server.c
+++ b/src/mk_server.c
@@ -66,6 +66,8 @@ unsigned int mk_server_worker_capacity(unsigned short 
nworkers)
     return ((avl / 2) / nworkers);
 }
 
+#ifndef SHAREDLIB
+
 /* Here we launch the worker threads to attend clients */
 void mk_server_launch_workers()
 {
@@ -74,7 +76,7 @@ void mk_server_launch_workers()
 
     /* Launch workers */
     for (i = 0; i < config->workers; i++) {
-        mk_sched_launch_thread(config->worker_capacity, &skip);
+        mk_sched_launch_thread(config->worker_capacity, &skip, NULL);
     }
 }
 
@@ -119,3 +121,5 @@ void mk_server_loop(int server_fd)
         }
     }
 }
+
+#endif // !SHAREDLIB
diff --git a/src/mk_signals.c b/src/mk_signals.c
index 9a02edd..7955935 100644
--- a/src/mk_signals.c
+++ b/src/mk_signals.c
@@ -20,6 +20,9 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 
USA.
  */
 
+/* If a library, do not interfere with the app's signals */
+#ifndef SHAREDLIB
+
 #include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -111,3 +114,5 @@ void mk_signal_init()
     sigaction(SIGINT,  &act, NULL);
     sigaction(SIGTERM, &act, NULL);
 }
+
+#endif // !SHAREDLIB
diff --git a/src/mk_user.c b/src/mk_user.c
index 7c78f95..01bcbaa 100644
--- a/src/mk_user.c
+++ b/src/mk_user.c
@@ -96,6 +96,8 @@ int mk_user_init(struct client_session *cs, struct 
session_request *sr)
     return 0;
 }
 
+#ifndef SHAREDLIB
+
 /* Change process user */
 int mk_user_set_uidgid()
 {
@@ -153,3 +155,5 @@ int mk_user_undo_uidgid()
     }
     return 0;
 }
+
+#endif // !SHAREDLIB
diff --git a/src/mk_utils.c b/src/mk_utils.c
index ea59c18..8ad5b76 100644
--- a/src/mk_utils.c
+++ b/src/mk_utils.c
@@ -213,39 +213,6 @@ int mk_buffer_cat(mk_pointer *p, char *buf1, int len1, 
char *buf2, int len2)
     return 0;
 }
 
-/* Run current process in background mode (daemon, evil Monkey >:) */
-int mk_utils_set_daemon()
-{
-    pid_t pid;
-
-    if ((pid = fork()) < 0){
-               mk_err("Error: Failed creating to switch to daemon mode(fork 
failed)");
-        exit(EXIT_FAILURE);
-       }
-
-    if (pid > 0) /* parent */
-        exit(EXIT_SUCCESS);
-
-    /* set files mask */
-    umask(0);
-
-    /* Create new session */
-    setsid();
-
-    if (chdir("/") < 0) { /* make sure we can unmount the inherited filesystem 
*/
-        mk_err("Error: Unable to unmount the inherited filesystem in the 
daemon process");
-        exit(EXIT_FAILURE);
-       }
-
-    /* Our last STDOUT message */
-    mk_info("Background mode ON");
-
-    fclose(stderr);
-    fclose(stdout);
-
-    return 0;
-}
-
 /* Convert hexadecimal to int */
 int mk_utils_hex2int(char *hex, int len)
 {
@@ -466,6 +433,41 @@ int mk_utils_print_errno(int n)
 
 #endif
 
+#ifndef SHAREDLIB
+
+/* Run current process in background mode (daemon, evil Monkey >:) */
+int mk_utils_set_daemon()
+{
+    pid_t pid;
+
+    if ((pid = fork()) < 0){
+               mk_err("Error: Failed creating to switch to daemon mode(fork 
failed)");
+        exit(EXIT_FAILURE);
+       }
+
+    if (pid > 0) /* parent */
+        exit(EXIT_SUCCESS);
+
+    /* set files mask */
+    umask(0);
+
+    /* Create new session */
+    setsid();
+
+    if (chdir("/") < 0) { /* make sure we can unmount the inherited filesystem 
*/
+        mk_err("Error: Unable to unmount the inherited filesystem in the 
daemon process");
+        exit(EXIT_FAILURE);
+       }
+
+    /* Our last STDOUT message */
+    mk_info("Background mode ON");
+
+    fclose(stderr);
+    fclose(stdout);
+
+    return 0;
+}
+
 /* Write Monkey's PID */
 int mk_utils_register_pid()
 {
@@ -532,6 +534,8 @@ int mk_utils_remove_pid()
     return 0;
 }
 
+#endif // !SHAREDLIB
+
 void mk_print(int type, const char *format, ...)
 {
     time_t now;
diff --git a/src/monkey.c b/src/monkey.c
index a940733..bba62c8 100644
--- a/src/monkey.c
+++ b/src/monkey.c
@@ -63,6 +63,7 @@ void mk_thread_keys_init(void)
     pthread_key_create(&mk_plugin_event_k, NULL);
 }
 
+#ifndef SHAREDLIB
 static void mk_details(void)
 {
     printf("* Process ID is %i", getpid());
@@ -158,6 +159,7 @@ int main(int argc, char **argv)
     mk_config_start_configure();
     mk_sched_init();
     mk_plugin_init();
+    mk_plugin_read_config();
 
     /* Server listening socket */
     config->server_fd = mk_socket_server(config->serverport, 
config->listen_addr);
@@ -218,3 +220,4 @@ int main(int argc, char **argv)
     mk_mem_free(config);
     return 0;
 }
+#endif
-- 
1.7.2.1

_______________________________________________
Monkey mailing list
[email protected]
http://lists.monkey-project.com/listinfo/monkey

Reply via email to