diff --git a/README b/README
index ac329266e7cf26d3555624a8c69957a7f473b6c5..328f34ba90e9ba7e0f46d274b0e0dea0fda3d8b6 100644
--- a/README
+++ b/README
@@ -56,7 +56,7 @@ Features
 
 * Testsuite included:
 	
-	This package includes a testsuite to automatically asses whether the compiled 
+  This package includes a testsuite to automatically asses whether the compiled 
   sieve engine works correctly. The testsuite is an extension to the Sieve 
   language and is therefore easily extended with new tests. Currently, the 
   testsuite is limited to testing script processing. The performed actions are 
@@ -133,7 +133,7 @@ that no other files are written and no permission to do so is necessary for the
 global script directories. 
 
 To test the sieve engine outside deliver it is useful to execute the binaries 
-that exist in the src/sieve-bin/ directory of this package. After installation, 
+that exist in the src/sieve-tools/ directory of this package. After installation, 
 these scripts are available in the dovecot lib directory. The following commands
 are available:
 
@@ -176,7 +176,8 @@ Options:
 
 sieve-exec
 
-Currently undocumented (will be merged with sieve-test).
+Currently undocumented (will evolve into sieve-filter which can process existing
+mail stores).
 
 --
 
diff --git a/TODO b/TODO
index c87114919cb0ea34e34653a247bad0a5b8eab534..1f0b5e61b5e0f43d808f030242e2d06591ca1825 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,5 @@
 Next (in order of descending priority/precedence):
 
-* Fix code duplication between command line tools and the testsuite. 
 * Fix remaining RFC deviations:
 	- Fix issues listed in doc/rfc/RFC-questions.txt when answers arrive
 	- Allow for the existance of dynamic comparators (i.e. specified by 
diff --git a/configure.in b/configure.in
index 57b901dedc84e2cf30b9caa940952203ee5c701a..ef7e681bb2c067ccb5262c9818f012aec09eb3f1 100644
--- a/configure.in
+++ b/configure.in
@@ -86,10 +86,10 @@ src/lib-sieve/plugins/include/Makefile
 src/lib-sieve/plugins/body/Makefile
 src/lib-sieve/plugins/variables/Makefile
 src/lib-sieve/plugins/enotify/Makefile
-src/lib-util/Makefile
+src/lib-sieve-tool/Makefile
 src/plugins/Makefile
 src/plugins/lda-sieve/Makefile
-src/sieve-bin/Makefile
+src/sieve-tools/Makefile
 src/testsuite/Makefile
 stamp.h])
 
diff --git a/src/Makefile.am b/src/Makefile.am
index f70c0f9bb771bc2a604f1612c48dfcbbd7eafcdd..6cefe1d780b71124d7e473c28016e85887ace271 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,2 +1,2 @@
-SUBDIRS = lib-sieve lib-util sieve-bin plugins testsuite
+SUBDIRS = lib-sieve lib-sieve-tool sieve-tools plugins testsuite
 
diff --git a/src/lib-sieve-tool/Makefile.am b/src/lib-sieve-tool/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..ab965c5a52a2e64656845601f7b9e38716d801cd
--- /dev/null
+++ b/src/lib-sieve-tool/Makefile.am
@@ -0,0 +1,19 @@
+noinst_LTLIBRARIES = libsieve-tool.la
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/lib-sieve \
+	-I$(dovecot_incdir) \
+	-I$(dovecot_incdir)/src/lib \
+	-I$(dovecot_incdir)/src/lib-mail \
+	-I$(dovecot_incdir)/src/lib-index \
+	-I$(dovecot_incdir)/src/lib-storage \
+	-I$(dovecot_incdir)/src/lib-storage/index \
+	-I$(dovecot_incdir)/src/lib-storage/index/raw
+
+libsieve_tool_la_SOURCES = \
+	sieve-tool.c \
+	mail-raw.c
+
+noinst_HEADERS = \
+	sieve-tool.h \
+	mail-raw.h
diff --git a/src/lib-util/mail-raw.c b/src/lib-sieve-tool/mail-raw.c
similarity index 100%
rename from src/lib-util/mail-raw.c
rename to src/lib-sieve-tool/mail-raw.c
diff --git a/src/lib-util/mail-raw.h b/src/lib-sieve-tool/mail-raw.h
similarity index 100%
rename from src/lib-util/mail-raw.h
rename to src/lib-sieve-tool/mail-raw.h
diff --git a/src/sieve-bin/bin-common.c b/src/lib-sieve-tool/sieve-tool.c
similarity index 75%
rename from src/sieve-bin/bin-common.c
rename to src/lib-sieve-tool/sieve-tool.c
index b9968508354f2416d853e582a678b9a8050c90e4..6c0274a785fb4012286712b30cc196d8f2476cbe 100644
--- a/src/sieve-bin/bin-common.c
+++ b/src/lib-sieve-tool/sieve-tool.c
@@ -9,7 +9,7 @@
 #include "mail-storage.h"
 
 #include "sieve.h"
-#include "bin-common.h"
+#include "sieve-tool.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -17,25 +17,36 @@
 #include <fcntl.h>
 #include <pwd.h>
 
-/* Functionality common to all sieve test tools */
-
-/* FIXME: this file is currently very messy */
+/*
+ * Global state
+ */
 
 static struct ioloop *ioloop;
 
+/*
+ * Signal handlers
+ */
+
 static void sig_die(int signo, void *context ATTR_UNUSED)
 {
-	/* warn about being killed because of some signal, except SIGINT (^C)
-	   which is too common at least while testing :) */
+	/* Warn about being killed because of some signal, except SIGINT (^C)
+	 * which is too common at least while testing :) 
+	 */
 	if (signo != SIGINT)
-		i_warning("Killed with signal %d", signo);
-	// io_loop_stop(ioloop); We are not running an ioloop
+		i_warning("killed with signal %d", signo);
+
+	io_loop_stop(ioloop);	
 	exit(1);
 }
 
-void bin_init(void) 
+/*
+ * Initialization
+ */
+
+void sieve_tool_init(void) 
 {
 	lib_init();
+
 	ioloop = io_loop_create();
 
 	lib_signals_init();
@@ -45,10 +56,10 @@ void bin_init(void)
 	lib_signals_ignore(SIGALRM, FALSE);
 
 	if ( !sieve_init("") ) 
-		i_fatal("Failed to initialize sieve implementation\n");
+		i_fatal("failed to initialize sieve implementation\n");
 }
 
-void bin_deinit(void)
+void sieve_tool_deinit(void)
 {
 	sieve_deinit();
 	
@@ -58,7 +69,11 @@ void bin_deinit(void)
 	lib_deinit();
 }
 
-const char *bin_get_user(void)
+/*
+ * Commonly needed functionality
+ */
+
+const char *sieve_tool_get_user(void)
 {
 	uid_t process_euid = geteuid();
 	struct passwd *pw = getpwuid(process_euid);
@@ -66,11 +81,37 @@ const char *bin_get_user(void)
 		return t_strdup(pw->pw_name);
 	} 
 		
-	i_fatal("Couldn't lookup our username (uid=%s)", dec2str(process_euid));
+	i_fatal("couldn't lookup our username (uid=%s)", dec2str(process_euid));
 	return NULL;
 }
 
-struct sieve_binary *bin_compile_sieve_script(const char *filename)
+void sieve_tool_get_envelope_data
+	(struct mail *mail, const char **recipient, const char **sender)
+{
+	/* Get recipient address */
+	if ( *recipient == NULL ) 
+		(void)mail_get_first_header(mail, "Envelope-To", recipient);
+	if ( *recipient == NULL ) 
+		(void)mail_get_first_header(mail, "To", recipient);
+	if ( *recipient == NULL ) 
+		*recipient = "recipient@example.com";
+	
+	/* Get sender address */
+	if ( *sender == NULL ) 
+		(void)mail_get_first_header(mail, "Return-path", sender);
+	if ( *sender == NULL ) 
+		(void)mail_get_first_header(mail, "Sender", sender);
+	if ( *sender == NULL ) 
+		(void)mail_get_first_header(mail, "From", sender);
+	if ( *sender == NULL ) 
+		*sender = "sender@example.com";
+}
+
+/*
+ * Sieve script handling
+ */
+
+struct sieve_binary *sieve_tool_script_compile(const char *filename)
 {
 	struct sieve_error_handler *ehandler;
 	struct sieve_binary *sbin;
@@ -80,7 +121,7 @@ struct sieve_binary *bin_compile_sieve_script(const char *filename)
 
 	if ( (sbin = sieve_compile(filename, ehandler)) == NULL ) {
 		sieve_error_handler_unref(&ehandler);
-		i_fatal("Failed to compile sieve script\n");
+		i_fatal("failed to compile sieve script\n");
 	}
 
 	sieve_error_handler_unref(&ehandler);
@@ -88,7 +129,7 @@ struct sieve_binary *bin_compile_sieve_script(const char *filename)
 	return sbin;
 }
 	
-struct sieve_binary *bin_open_sieve_script(const char *filename)
+struct sieve_binary *sieve_tool_script_open(const char *filename)
 {
 	struct sieve_error_handler *ehandler;
 	struct sieve_binary *sbin;
@@ -106,7 +147,7 @@ struct sieve_binary *bin_open_sieve_script(const char *filename)
 	return sbin;
 }
 	
-void bin_dump_sieve_binary_to(struct sieve_binary *sbin, const char *filename)	
+void sieve_tool_dump_binary_to(struct sieve_binary *sbin, const char *filename)	
 {
 	int dfd = -1;
 	struct ostream *dumpstream;
@@ -117,8 +158,7 @@ void bin_dump_sieve_binary_to(struct sieve_binary *sbin, const char *filename)
 		dumpstream = o_stream_create_fd(1, 0, FALSE);
 	else {
 		if ( (dfd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0 ) {
-			i_fatal("Failed to open dump-file for writing: %m");
-			exit(1);
+			i_fatal("failed to open dump-file for writing: %m");
 		}
 		
 		dumpstream = o_stream_create_fd(dfd, 0, FALSE);
@@ -135,32 +175,3 @@ void bin_dump_sieve_binary_to(struct sieve_binary *sbin, const char *filename)
 		close(dfd);
 }
 
-void bin_close_mail_file(int mfd)
-{
-	if ( mfd != 0 )
-		close(mfd);
-}
-
-void bin_fill_in_envelope
-	(struct mail *mail, const char **recipient, const char **sender)
-{
-	/* Get recipient address */
-	if ( *recipient == NULL ) 
-		(void)mail_get_first_header(mail, "Envelope-To", recipient);
-	if ( *recipient == NULL ) 
-		(void)mail_get_first_header(mail, "To", recipient);
-	if ( *recipient == NULL ) 
-		*recipient = "recipient@example.com";
-	
-	/* Get sender address */
-	if ( *sender == NULL ) 
-		(void)mail_get_first_header(mail, "Return-path", sender);
-	if ( *sender == NULL ) 
-		(void)mail_get_first_header(mail, "Sender", sender);
-	if ( *sender == NULL ) 
-		(void)mail_get_first_header(mail, "From", sender);
-	if ( *sender == NULL ) 
-		*sender = "sender@example.com";
-}
-
-
diff --git a/src/lib-sieve-tool/sieve-tool.h b/src/lib-sieve-tool/sieve-tool.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b402f0a2f702f2f738cb74c89fe9ffe555d9df4
--- /dev/null
+++ b/src/lib-sieve-tool/sieve-tool.h
@@ -0,0 +1,33 @@
+/* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file
+ */
+
+#ifndef __SIEVE_TOOL_H
+#define __SIEVE_TOOL_H
+
+/* Functionality common to all Sieve command line tools. */
+
+/*
+ * Initialization
+ */
+
+void sieve_tool_init(void);
+void sieve_tool_deinit(void);
+
+/*
+ * Commonly needed functionality
+ */
+
+const char *sieve_tool_get_user(void);
+
+void sieve_tool_get_envelope_data
+	(struct mail *mail, const char **recipient, const char **sender);
+
+/*
+ * Sieve script handling
+ */
+
+struct sieve_binary *sieve_tool_script_compile(const char *filename);
+struct sieve_binary *sieve_tool_script_open(const char *filename);
+void sieve_tool_dump_binary_to(struct sieve_binary *sbin, const char *filename);
+
+#endif /* __SIEVE_TOOL_H */
diff --git a/src/lib-util/Makefile.am b/src/lib-util/Makefile.am
deleted file mode 100644
index 88d8d67d2259fae6e3812ceab0d85ed1073a3124..0000000000000000000000000000000000000000
--- a/src/lib-util/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-noinst_LTLIBRARIES = libutil.la
-
-AM_CPPFLAGS = \
-	-I$(dovecot_incdir) \
-	-I$(dovecot_incdir)/src/lib \
-	-I$(dovecot_incdir)/src/lib-mail \
-        -I$(dovecot_incdir)/src/lib-index \
-        -I$(dovecot_incdir)/src/lib-storage \
-        -I$(dovecot_incdir)/src/lib-storage/index \
-        -I$(dovecot_incdir)/src/lib-storage/index/raw \
-        -I$(dovecot_incdir)/src/lib-storage/index/mbox \
-        -I$(dovecot_incdir)/src/lib-storage/index/maildir
-
-libutil_la_SOURCES = \
-	mail-raw.c
-
-noinst_HEADERS = \
-	mail-raw.h
diff --git a/src/sieve-bin/bin-common.h b/src/sieve-bin/bin-common.h
deleted file mode 100644
index 0d7076110634ab543713f9fdb53135e304fcb694..0000000000000000000000000000000000000000
--- a/src/sieve-bin/bin-common.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file
- */
-
-#ifndef __BIN_COMMON_H
-#define __BIN_COMMON_H
-
-#include "sieve.h"
-
-/* Functionality common to all sieve test tools */
-
-void bin_init(void);
-void bin_deinit(void);
-
-const char *bin_get_user(void);
-
-struct sieve_binary *bin_compile_sieve_script(const char *filename);
-struct sieve_binary *bin_open_sieve_script(const char *filename);
-void bin_dump_sieve_binary_to(struct sieve_binary *sbin, const char *filename);
-
-int bin_open_mail_file(const char *filename);
-void bin_close_mail_file(int mfd);
-
-void bin_fill_in_envelope
-	(struct mail *mail, const char **recipient, const char **sender);
-
-#endif /* __BIN_COMMON_H */
diff --git a/src/sieve-bin/Makefile.am b/src/sieve-tools/Makefile.am
similarity index 85%
rename from src/sieve-bin/Makefile.am
rename to src/sieve-tools/Makefile.am
index 650c4a8257187cf1db26f01a98c2d6e67bfb84f9..b29025ec464bd0f824ae8df07d232ad4baa3c834 100644
--- a/src/sieve-bin/Makefile.am
+++ b/src/sieve-tools/Makefile.am
@@ -4,7 +4,7 @@ bin_PROGRAMS = sievec sieved sieve-test sieve-exec
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib-sieve \
-	-I$(top_srcdir)/src/lib-util \
+	-I$(top_srcdir)/src/lib-sieve-tool \
 	-I$(dovecot_incdir) \
 	-I$(dovecot_incdir)/src/lib \
 	-I$(dovecot_incdir)/src/lib-mail \
@@ -19,10 +19,10 @@ sieve_exec_LDFLAGS = -export-dynamic -Wl,--start-group
 
 libs = \
 	$(top_srcdir)/src/lib-sieve/libsieve.la \
-	$(top_srcdir)/src/lib-util/libutil.la \
+	$(top_srcdir)/src/lib-sieve-tool/libsieve-tool.la \
 	$(dovecot_incdir)/src/lib-storage/list/libstorage_list.a \
 	$(dovecot_incdir)/src/lib-storage/register/libstorage-register.a \
-        $(STORAGE_LIBS) \
+	$(STORAGE_LIBS) \
 	$(dovecot_incdir)/src/lib-storage/libstorage.a \
 	$(dovecot_incdir)/src/lib-index/libindex.a \
 	$(dovecot_incdir)/src/lib-imap/libimap.a \
@@ -46,24 +46,16 @@ sieved_DEPENDENCIES = $(libs)
 sieve_test_DEPENDENCIES = $(libs)
 sieve_exec_DEPENDENCIES = $(libs)
 
-common_sources = \
-	bin-common.c
-
 sievec_SOURCES = \
-	$(common_sources) \
 	sievec.c 
 
 sieved_SOURCES = \
-	$(common_sources) \
 	sieved.c 
 
 sieve_test_SOURCES = \
-	$(common_sources) \
 	sieve-test.c 
 
 sieve_exec_SOURCES = \
-	$(common_sources) \
 	sieve-exec.c 
 
-noinst_HEADERS = \
-	bin-common.h
+noinst_HEADERS =
diff --git a/src/sieve-tools/sieve-exec b/src/sieve-tools/sieve-exec
new file mode 100755
index 0000000000000000000000000000000000000000..1adb34612f4b34b91cc4eb3675a2b7dea991bbad
Binary files /dev/null and b/src/sieve-tools/sieve-exec differ
diff --git a/src/sieve-bin/sieve-exec.c b/src/sieve-tools/sieve-exec.c
similarity index 91%
rename from src/sieve-bin/sieve-exec.c
rename to src/sieve-tools/sieve-exec.c
index 18c554754e178f3b665d28220d1d32dde14f8fba..bf4ac5c339dc320895036eb37d5291fe9934a777 100644
--- a/src/sieve-bin/sieve-exec.c
+++ b/src/sieve-tools/sieve-exec.c
@@ -7,11 +7,12 @@
 #include "mail-namespace.h"
 #include "env-util.h"
 
-#include "bin-common.h"
-#include "mail-raw.h"
 #include "sieve.h"
 #include "sieve-binary.h"
 
+#include "mail-raw.h"
+#include "sieve-tool.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -94,8 +95,6 @@ int main(int argc, char **argv)
 	struct sieve_exec_status estatus;
 	struct sieve_error_handler *ehandler;
 
-	bin_init();
-
 	/* Parse arguments */
 	scriptfile = recipient = sender = mailbox = dumpfile = mailfile = NULL;
 	mailloc = NULL;
@@ -150,13 +149,15 @@ int main(int argc, char **argv)
 		i_fatal("Missing <mailfile> argument");
 	}
 	
+	sieve_tool_init();
+
 	/* Compile sieve script */
-	sbin = bin_open_sieve_script(scriptfile);
+	sbin = sieve_tool_script_open(scriptfile);
 	
 	/* Dump script */
-	bin_dump_sieve_binary_to(sbin, dumpfile);
+	sieve_tool_dump_binary_to(sbin, dumpfile);
 	
-	user = bin_get_user();
+	user = sieve_tool_get_user();
 	home = getenv("HOME");
 
 	/* Initialize mail storages */
@@ -183,7 +184,7 @@ int main(int argc, char **argv)
 	mail_raw_init(user);
 	mailr = mail_raw_open_file(mailfile);
 
-	bin_fill_in_envelope(mailr->mail, &recipient, &sender);
+	sieve_tool_get_envelope_data(mailr->mail, &recipient, &sender);
 
 	if ( mailbox == NULL )
 		mailbox = "INBOX";
@@ -213,19 +214,19 @@ int main(int argc, char **argv)
 	/* Run */
 	switch ( sieve_execute(sbin, &msgdata, &scriptenv, &estatus, ehandler, NULL) ) {
 	case SIEVE_EXEC_OK:
-		i_info("Final result: success");
+		i_info("final result: success");
 		break;
 	case SIEVE_EXEC_FAILURE:
-		i_info("Final result: failed; resolved with successful implicit keep");
+		i_info("final result: failed; resolved with successful implicit keep");
 		break;
 	case SIEVE_EXEC_BIN_CORRUPT:
-		i_info("Corrupt binary deleted.");
+		i_info("corrupt binary deleted.");
 		(void) unlink(sieve_binary_path(sbin));
 	case SIEVE_EXEC_KEEP_FAILED:
-		i_info("Final result: utter failure (caller please handle implicit keep!)");
+		i_info("final result: utter failure (caller please handle implicit keep!)");
 		break;
 	default:
-		i_info("Final result: unrecognized return value?!");	
+		i_info("final result: unrecognized return value?!");	
 	}
 
 	sieve_close(&sbin);
@@ -242,7 +243,8 @@ int main(int argc, char **argv)
 	/* De-intialize mail storages */
 	mail_storage_deinit();
 
-	bin_deinit();  
+	sieve_tool_deinit();  
+	
 	return 0;
 }
 
diff --git a/src/sieve-tools/sieve-test b/src/sieve-tools/sieve-test
new file mode 100755
index 0000000000000000000000000000000000000000..a769fef18e23de02006f584fcca9009def41d4ca
Binary files /dev/null and b/src/sieve-tools/sieve-test differ
diff --git a/src/sieve-bin/sieve-test.c b/src/sieve-tools/sieve-test.c
similarity index 93%
rename from src/sieve-bin/sieve-test.c
rename to src/sieve-tools/sieve-test.c
index 4c952f5717ef886cffe013bc2c8e3ab3a0ada9b1..41508a1f1a6ea817210f1470b6dcf9742668b958 100644
--- a/src/sieve-bin/sieve-test.c
+++ b/src/sieve-tools/sieve-test.c
@@ -5,11 +5,12 @@
 #include "ostream.h"
 #include "mail-storage.h"
 
-#include "bin-common.h"
-#include "mail-raw.h"
 #include "sieve.h"
 #include "sieve-binary.h"
 
+#include "mail-raw.h"
+#include "sieve-tool.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -62,8 +63,6 @@ int main(int argc, char **argv)
 	bool trace = FALSE;
 	struct ostream *trace_stream = FALSE;
 
-	bin_init();
-
 	/* Parse arguments */
 	scriptfile = recipient = sender = mailbox = dumpfile = mailfile = NULL;
 	for (i = 1; i < argc; i++) {
@@ -118,19 +117,21 @@ int main(int argc, char **argv)
 		print_help();
 		i_fatal("Missing <mailfile> argument");
 	}
+
+	sieve_tool_init();
 	
 	/* Compile sieve script */
 	if ( force_compile ) {
-		sbin = bin_compile_sieve_script(scriptfile);
+		sbin = sieve_tool_script_compile(scriptfile);
 		(void) sieve_save(sbin, NULL);
 	} else {
-		sbin = bin_open_sieve_script(scriptfile);
+		sbin = sieve_tool_script_open(scriptfile);
 	}
 
 	/* Dump script */
-	bin_dump_sieve_binary_to(sbin, dumpfile);
+	sieve_tool_dump_binary_to(sbin, dumpfile);
 	
-	user = bin_get_user();
+	user = sieve_tool_get_user();
 
 	/* Initialize mail storages */
 	mail_storage_init();
@@ -141,7 +142,7 @@ int main(int argc, char **argv)
 	mail_raw_init(user);
 	mailr = mail_raw_open_file(mailfile);
 
-	bin_fill_in_envelope(mailr->mail, &recipient, &sender);
+	sieve_tool_get_envelope_data(mailr->mail, &recipient, &sender);
 
 	if ( mailbox == NULL )
 		mailbox = "INBOX";
@@ -188,6 +189,6 @@ int main(int argc, char **argv)
 	/* De-initialize mail storages */
 	mail_storage_deinit();
 
-	bin_deinit();  
+	sieve_tool_deinit();  
 	return 0;
 }
diff --git a/src/sieve-tools/sievec b/src/sieve-tools/sievec
new file mode 100755
index 0000000000000000000000000000000000000000..3281282256ec398731aafa76c23e559831ac867c
Binary files /dev/null and b/src/sieve-tools/sievec differ
diff --git a/src/sieve-bin/sievec.c b/src/sieve-tools/sievec.c
similarity index 88%
rename from src/sieve-bin/sievec.c
rename to src/sieve-tools/sievec.c
index 8c00aabbed3d65e9b3181cf0a7ece55a4d14b3db..317a9402d455d607f09453cfa2363d9bc97d3bca 100644
--- a/src/sieve-bin/sievec.c
+++ b/src/sieve-tools/sievec.c
@@ -1,6 +1,11 @@
 /* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file
  */
 
+#include "lib.h"
+
+#include "sieve.h"
+#include "sieve-tool.h"
+
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -9,14 +14,10 @@
 #include <unistd.h>
 #include <stdio.h>
 
-#include "lib.h"
-#include "sieve.h"
-
-#include "bin-common.h"
-
 /*
  * Print help
  */
+
 static void print_help(void)
 {
 	printf(
@@ -34,7 +35,7 @@ int main(int argc, char **argv) {
 	bool dump = FALSE;
 	const char *scriptfile, *outfile;
 	
-	bin_init();
+	sieve_tool_init();
 	
 	scriptfile = outfile = NULL;
 	for (i = 1; i < argc; i++) {
@@ -61,11 +62,11 @@ int main(int argc, char **argv) {
 		i_fatal("Missing <outfile> argument");
 	}
 
-	sbin = bin_compile_sieve_script(scriptfile);
+	sbin = sieve_tool_script_compile(scriptfile);
 
 	if ( sbin != NULL ) {
 		if ( dump ) 
-			bin_dump_sieve_binary_to(sbin, outfile);
+			sieve_tool_dump_binary_to(sbin, outfile);
 		else {
 			sieve_save(sbin, outfile);
 		}
@@ -73,5 +74,5 @@ int main(int argc, char **argv) {
 		sieve_close(&sbin);
 	}
 		
-	bin_deinit();
+	sieve_tool_deinit();
 }
diff --git a/src/sieve-tools/sieved b/src/sieve-tools/sieved
new file mode 100755
index 0000000000000000000000000000000000000000..84660d2ef324dbfb7fd0977493a54179e84c463e
Binary files /dev/null and b/src/sieve-tools/sieved differ
diff --git a/src/sieve-bin/sieved.c b/src/sieve-tools/sieved.c
similarity index 78%
rename from src/sieve-bin/sieved.c
rename to src/sieve-tools/sieved.c
index ab6458cf3fc1aef0a32371a7d06aad09197caf06..28eb5c43af7e852a38590daa5af2db1ccf089c37 100644
--- a/src/sieve-bin/sieved.c
+++ b/src/sieve-tools/sieved.c
@@ -1,6 +1,12 @@
 /* Copyright (c) 2002-2008 Dovecot Sieve authors, see the included COPYING file
  */
 
+#include "lib.h"
+
+#include "sieve.h"
+#include "sieve-binary.h"
+#include "sieve-tool.h"
+
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -9,12 +15,6 @@
 #include <unistd.h>
 #include <stdio.h>
 
-#include "lib.h"
-#include "sieve.h"
-#include "sieve-binary.h"
-
-#include "bin-common.h"
-
 /*
  * Print help
  */
@@ -43,16 +43,16 @@ int main(int argc, char **argv) {
 			outfile = argv[i];
 		} else {
 			print_help();
-			i_fatal("Unknown argument: %s", argv[i]);
+			i_fatal("unknown argument: %s", argv[i]);
 		}
 	}
 	
 	if ( binfile == NULL ) {
 		print_help();
-		i_fatal("Missing <binfile> argument");
+		i_fatal("missing <binfile> argument");
 	}
 	
-	bin_init();
+	sieve_tool_init();
 	
 	sbin = sieve_binary_open(binfile, NULL);
 
@@ -62,12 +62,12 @@ int main(int argc, char **argv) {
 	}
 
 	if ( sbin != NULL ) {
-		bin_dump_sieve_binary_to(sbin, outfile == NULL ? "-" : outfile);
+		sieve_tool_dump_binary_to(sbin, outfile == NULL ? "-" : outfile);
 	
 		sieve_binary_unref(&sbin);
 	} else 
-		i_error("Failed to load binary: %s", binfile);
+		i_error("failed to load binary: %s", binfile);
 	
-	bin_deinit();
+	sieve_tool_deinit();
 }
 
diff --git a/src/testsuite/Makefile.am b/src/testsuite/Makefile.am
index b20e4dfbda93a58dc34c750334a9c5ddbe7fd928..61ebb99c33ef188146abdd4a99a075b1421dd42c 100644
--- a/src/testsuite/Makefile.am
+++ b/src/testsuite/Makefile.am
@@ -2,7 +2,7 @@ noinst_PROGRAMS = testsuite
 
 AM_CPPFLAGS = \
 	-I../lib-sieve \
-	-I../lib-util \
+	-I../lib-sieve-tool \
 	-I$(dovecot_incdir) \
 	-I$(dovecot_incdir)/src/lib \
 	-I$(dovecot_incdir)/src/lib-mail \
@@ -13,7 +13,7 @@ testsuite_LDFLAGS = -export-dynamic -Wl,--start-group
 
 libs = \
 	$(top_srcdir)/src/lib-sieve/libsieve.la \
-	$(top_srcdir)/src/lib-util/libutil.la \
+	$(top_srcdir)/src/lib-sieve-tool/libsieve-tool.la \
 	$(dovecot_incdir)/src/lib-storage/list/libstorage_list.a \
 	$(dovecot_incdir)/src/lib-storage/register/libstorage-register.a \
 	$(STORAGE_LIBS) \
diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c
index b4e951d4786c5d22b9c9f6d5583972595d22bdde..10c81f9ce41feadb92113e4c1bc65b74739d4540 100644
--- a/src/testsuite/testsuite.c
+++ b/src/testsuite/testsuite.c
@@ -9,8 +9,6 @@
 #include "mail-storage.h"
 #include "env-util.h"
 
-#include "mail-raw.h"
-
 #include "sieve.h"
 #include "sieve-extensions.h"
 #include "sieve-script.h"
@@ -18,6 +16,9 @@
 #include "sieve-result.h"
 #include "sieve-interpreter.h"
 
+#include "mail-raw.h"
+#include "sieve-tool.h"
+
 #include "testsuite-common.h"
 
 #include <stdio.h>
@@ -33,118 +34,30 @@
 #define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail"
 #define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON"
 
-/* FIXME: this file is currently very messy */
-
-static struct ioloop *ioloop;
-
-static void sig_die(int signo, void *context ATTR_UNUSED)
-{
-	/* warn about being killed because of some signal, except SIGINT (^C)
-	   which is too common at least while testing :) */
-	if (signo != SIGINT)
-		i_warning("Killed with signal %d", signo);
-	// io_loop_stop(ioloop); We are not running an ioloop
-	exit(1);
-}
-
 /*
  * Testsuite initialization 
  */
 
-static void testsuite_bin_init(void) 
+static void testsuite_tool_init(void) 
 {
-	lib_init();
-	ioloop = io_loop_create();
-
-	lib_signals_init();
-	lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
-	lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
-	lib_signals_ignore(SIGPIPE, TRUE);
-	lib_signals_ignore(SIGALRM, FALSE);
-
-	if ( !sieve_init("") ) 
-		i_fatal("Failed to initialize sieve implementation\n");
+	sieve_tool_init();
 
 	(void) sieve_extension_register(&testsuite_extension);
 	
 	testsuite_init();
 }
 
-static void testsuite_bin_deinit(void)
+static void testsuite_tool_deinit(void)
 {
 	testsuite_deinit();
 	
-	sieve_deinit();
-	
-	lib_signals_deinit();
-
-	io_loop_destroy(&ioloop);
-	lib_deinit();
+	sieve_tool_deinit();
 }
 
 /*
  * Testsuite execution
  */
 
-static const char *_get_user(void)
-{
-	uid_t process_euid = geteuid();
-	struct passwd *pw = getpwuid(process_euid);
-	if (pw != NULL) {
-		return t_strdup(pw->pw_name);
-	} 
-		
-	i_fatal("Couldn't lookup our username (uid=%s)", dec2str(process_euid));
-	return NULL;
-}
-
-static struct sieve_binary *_compile_sieve_script(const char *filename)
-{
-	struct sieve_error_handler *ehandler;
-	struct sieve_binary *sbin;
-	
-	ehandler = sieve_stderr_ehandler_create(0);
-	sieve_error_handler_accept_infolog(ehandler, TRUE);
-
-	if ( (sbin = sieve_compile(filename, ehandler)) == NULL ) {
-		sieve_error_handler_unref(&ehandler);
-		i_fatal("Failed to compile test script %s\n", filename);
-	}
-
-	sieve_error_handler_unref(&ehandler);
-		
-	return sbin;
-}
-		
-static void _dump_sieve_binary_to(struct sieve_binary *sbin, const char *filename)	
-{
-	int dfd = -1;
-	struct ostream *dumpstream;
-	
-	if ( filename == NULL ) return;
-	
-	if ( strcmp(filename, "-") == 0 ) 
-		dumpstream = o_stream_create_fd(1, 0, FALSE);
-	else {
-		if ( (dfd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0 ) {
-			i_fatal("Failed to open dump-file for writing: %m");
-			exit(1);
-		}
-		
-		dumpstream = o_stream_create_fd(dfd, 0, FALSE);
-	}
-	
-	if ( dumpstream != NULL ) {
-		(void) sieve_dump(sbin, dumpstream);
-		o_stream_destroy(&dumpstream);
-	} else {
-		i_fatal("Failed to create stream for sieve code dump.");
-	}
-	
-	if ( dfd != -1 )
-		close(dfd);
-}
-
 static void print_help(void)
 {
 	printf(
@@ -165,7 +78,7 @@ static int testsuite_run
 	if ( trace ) {
 		struct ostream *tstream = o_stream_create_fd(1, 0, FALSE);
 		
-		interp=sieve_interpreter_create(sbin, ehandler, tstream);
+		interp = sieve_interpreter_create(sbin, ehandler, tstream);
 		
 		if ( interp != NULL ) 
 		    ret = sieve_interpreter_run
@@ -201,9 +114,6 @@ int main(int argc, char **argv)
 	struct sieve_script_env scriptenv;
 	bool trace = FALSE;
 
-	/* Initialize testsuite */
-	testsuite_bin_init();
-
 	/* Parse arguments */
 	scriptfile = dumpfile =  NULL;
 	for (i = 1; i < argc; i++) {
@@ -233,10 +143,13 @@ int main(int argc, char **argv)
 
 	printf("Test case: %s:\n\n", scriptfile);
 
+	/* Initialize testsuite */
+	testsuite_tool_init();
+
 	/* Initialize environment */
 	sieve_dir = strrchr(scriptfile, '/');
-    if ( sieve_dir == NULL )
-        sieve_dir= "./";
+	if ( sieve_dir == NULL )
+		sieve_dir= "./";
 	else
 		sieve_dir = t_strdup_until(scriptfile, sieve_dir+1);
 
@@ -245,10 +158,10 @@ int main(int argc, char **argv)
 	env_put(t_strconcat("SIEVE_GLOBAL_DIR=", sieve_dir, "included-global", NULL));
 	
 	/* Compile sieve script */
-	sbin = _compile_sieve_script(scriptfile);
+	sbin = sieve_tool_script_compile(scriptfile);
 
 	/* Dump script */
-	_dump_sieve_binary_to(sbin, dumpfile);
+	sieve_tool_dump_binary_to(sbin, dumpfile);
 	
 	/* Initialize mail storages */
 	mail_storage_init();
@@ -256,7 +169,7 @@ int main(int argc, char **argv)
 	mailbox_list_register_all();
 
 	/* Initialize message environment */
-	user = _get_user();
+	user = sieve_tool_get_user();
 	testsuite_message_init(user);
 
 	memset(&scriptenv, 0, sizeof(scriptenv));
@@ -289,7 +202,7 @@ int main(int argc, char **argv)
 	mail_storage_deinit();
 
 	/* De-initialize testsuite */
-	testsuite_bin_deinit();  
+	testsuite_tool_deinit();  
 
 	return testsuite_testcase_result();
 }