Index: benchmark/io/http/main.cfa
===================================================================
--- benchmark/io/http/main.cfa	(revision 0aec496b4b9d7e9afdb62632be73923517922a41)
+++ benchmark/io/http/main.cfa	(revision 7f389a5cebf89e197d496b8721d40a9431238077)
@@ -7,5 +7,4 @@
 extern "C" {
 	#include <sys/socket.h>
-	#include <sys/types.h>
 	#include <netinet/in.h>
 }
@@ -18,4 +17,5 @@
 #include "filecache.hfa"
 #include "options.hfa"
+#include "parseargs.hfa"
 #include "worker.hfa"
 
@@ -57,5 +57,4 @@
 int main( int argc, char * argv[] ) {
 	int port      = 8080;
-	int ret       = 0;
 	int backlog   = 10;
 	int nprocs    = 1;
@@ -66,4 +65,16 @@
 	//===================
 	// Parse args
+	static cfa_option opt[] = {
+		{'p', "port", "Port the server will listen on", port},
+		{'c', "cpus", "Number of processors to use", nprocs},
+		{'t', "threads", "Number of worker threads to use", nworkers},
+		{'b', "accept-backlog", "Maximum number of pending accepts", backlog},
+		{'B', "channel-size", "Maximum number of accepted connection pending", chan_size}
+	};
+	int opt_cnt = sizeof(opt) / sizeof(cfa_option);
+
+	char **left;
+      parse_args( argc, argv, opt, opt_cnt, "[OPTIONS] [PATH]  -- cforall http server", left );
+
 
 	//===================
@@ -80,4 +91,5 @@
 	}
 
+	int ret = 0;
 	struct sockaddr_in address;
 	int addrlen = sizeof(address);
Index: benchmark/io/http/parseargs.cfa
===================================================================
--- benchmark/io/http/parseargs.cfa	(revision 7f389a5cebf89e197d496b8721d40a9431238077)
+++ benchmark/io/http/parseargs.cfa	(revision 7f389a5cebf89e197d496b8721d40a9431238077)
@@ -0,0 +1,141 @@
+#include "parseargs.hfa"
+
+// #include <stdio.h>
+// #include <stdlib.h>
+#include <string.h>
+extern "C" {
+	#include <getopt.h>
+
+	struct FILE;
+	extern FILE * stderr;
+	extern FILE * stdout;
+
+	extern int fprintf ( FILE * stream, const char * format, ... );
+	extern long long int strtoll (const char* str, char** endptr, int base);
+}
+
+void parse_args(
+	int argc,
+	char * argv[],
+	cfa_option options[],
+	size_t opt_count,
+	const char * usage,
+	char ** & left
+) {
+	struct option optarr[opt_count + 2];
+	int width = 0;
+	{
+		int idx = 0;
+		for(i; opt_count) {
+			if(options[i].long_name) {
+				optarr[idx].name = options[i].long_name;
+				optarr[idx].flag = 0p;
+				optarr[idx].val  = options[i].short_name;
+				if(    ((intptr_t)options[i].parse) == ((intptr_t)parse_settrue)
+				    || ((intptr_t)options[i].parse) == ((intptr_t)parse_setfalse) ) {
+					optarr[idx].has_arg = no_argument;
+				} else {
+					optarr[idx].has_arg = required_argument;
+				}
+				idx++;
+
+				int w = strlen(options[i].long_name);
+				if(w > width) width = w;
+			}
+		}
+		optarr[idx+0].[name, has_arg, flag, val] = ["help", no_argument, 0p, 'h'];
+		optarr[idx+1].[name, has_arg, flag, val] = [0p, no_argument, 0p, 0];
+	}
+
+	char optstring[opt_count * 3] = { '\0' };
+	{
+		int idx = 0;
+		for(i; opt_count) {
+			optstring[idx] = options[i].short_name;
+			idx++;
+			if(    ((intptr_t)options[i].parse) != ((intptr_t)parse_settrue)
+			    && ((intptr_t)options[i].parse) != ((intptr_t)parse_setfalse) ) {
+				optstring[idx] = ':';
+				idx++;
+			}
+		}
+		optstring[idx+0] = 'h';
+		optstring[idx+1] = '\0';
+	}
+
+	FILE * out = stderr;
+	NEXT_ARG:
+	for() {
+		int idx = 0;
+		int opt = getopt_long(argc, argv, optstring, optarr, &idx);
+		switch(opt) {
+			case -1:
+				if(&left != 0p) left = argv + optind;
+				return;
+			case 'h':
+				out = stdout;
+			case '?':
+				goto USAGE;
+			default:
+				for(i; opt_count) {
+					if(opt == options[i].short_name) {
+						const char * arg = optarg ? optarg : "";
+						bool success = options[i].parse( arg, options[i].variable );
+						if(success) continue NEXT_ARG;
+
+						fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt);
+						goto USAGE;
+					}
+				}
+				abort("Internal parse arg error\n");
+		}
+
+	}
+
+	USAGE:
+	fprintf(out, "%s\n", usage);
+
+	for(i; opt_count) {
+		fprintf(out, "  -%c, --%-*s   %s\n", options[i].short_name, width, options[i].long_name, options[i].help);
+	}
+	fprintf(out, "  -%c, --%-*s   %s\n", 'h', width, "help", "print this help message");
+	exit(out == stdout ? 0 : 1);
+}
+
+bool parse_yesno(const char * arg, bool & value ) {
+	if(strcmp(arg, "yes") == 0) {
+		value = true;
+		return true;
+	}
+
+	if(strcmp(arg, "no") == 0) {
+		value = false;
+		return true;
+	}
+
+	return false;
+}
+
+bool parse_settrue (const char *, bool & value ) {
+	value = true;
+	return true;
+}
+
+bool parse_setfalse(const char *, bool & value )  {
+	value = false;
+	return true;
+}
+
+bool parse(const char * arg, const char * & value ) {
+	value = arg;
+	return true;
+}
+
+bool parse(const char * arg, int & value) {
+	char * end;
+	int r = strtoll(arg, &end, 10);
+	if(*end != '\0') return false;
+
+	value = r;
+	return true;
+}
Index: benchmark/io/http/parseargs.hfa
===================================================================
--- benchmark/io/http/parseargs.hfa	(revision 7f389a5cebf89e197d496b8721d40a9431238077)
+++ benchmark/io/http/parseargs.hfa	(revision 7f389a5cebf89e197d496b8721d40a9431238077)
@@ -0,0 +1,40 @@
+#pragma once
+
+struct cfa_option {
+      char short_name;
+      const char * long_name;
+      const char * help;
+      void * variable;
+      bool (*parse)(const char *, void * );
+};
+
+extern cfa_option last_option;
+
+static inline void ?{}( cfa_option & this ) {}
+
+forall(dtype T | { bool parse(const char *, T & ); })
+static inline void ?{}( cfa_option & this, char short_name, const char * long_name, const char * help, T & variable ) {
+      this.short_name = short_name;
+      this.long_name  = long_name;
+      this.help       = help;
+      this.variable   = (void*)&variable;
+      this.parse      = (bool (*)(const char *, void * ))parse;
+}
+
+forall(dtype T)
+static inline void ?{}( cfa_option & this, char short_name, const char * long_name, const char * help, T & variable, bool (*parse)(const char *, T & )) {
+      this.short_name = short_name;
+      this.long_name  = long_name;
+      this.help       = help;
+      this.variable   = (void*)&variable;
+      this.parse      = (bool (*)(const char *, void * ))parse;
+}
+
+void parse_args( int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, char ** & left );
+
+bool parse_yesno   (const char *, bool & );
+bool parse_settrue (const char *, bool & );
+bool parse_setfalse(const char *, bool & );
+
+bool parse(const char *, const char * & );
+bool parse(const char *, int & );
Index: benchmark/io/http/worker.cfa
===================================================================
--- benchmark/io/http/worker.cfa	(revision 0aec496b4b9d7e9afdb62632be73923517922a41)
+++ benchmark/io/http/worker.cfa	(revision 7f389a5cebf89e197d496b8721d40a9431238077)
@@ -7,8 +7,7 @@
 #include <string.h>
 extern "C" {
+	#include <fcntl.h>
 	#include <sys/socket.h>
 	#include <sys/types.h>
-	#include <linux/fcntl.h>
-	#include <linux/stat.h>
 	#include <netinet/in.h>
 }
@@ -37,5 +36,5 @@
 	ssize_t ret;
 	SPLICE1: while(count > 0) {
-		ret = cfa_splice(ans_fd, &offset, this.pipe[1], 0p, count, 5);
+		ret = cfa_splice(ans_fd, &offset, this.pipe[1], 0p, count, SPLICE_F_MOVE | SPLICE_F_MORE);
 		if( ret < 0 ) {
 			if( errno != EAGAIN && errno != EWOULDBLOCK) continue SPLICE1;
@@ -47,5 +46,5 @@
 		size_t in_pipe = ret;
 		SPLICE2: while(in_pipe > 0) {
-			ret = cfa_splice(this.pipe[0], 0p, fd, 0p, in_pipe, 5);
+			ret = cfa_splice(this.pipe[0], 0p, fd, 0p, in_pipe, SPLICE_F_MOVE | SPLICE_F_MORE);
 			if( ret < 0 ) {
 				if( errno != EAGAIN && errno != EWOULDBLOCK) continue SPLICE2;
