Index: uspace/app/bdsh/exec.c
===================================================================
--- uspace/app/bdsh/exec.c	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/app/bdsh/exec.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -41,4 +41,5 @@
 #include <fcntl.h>
 #include <str_error.h>
+#include <errno.h>
 
 #include "config.h"
@@ -116,24 +117,26 @@
 	task_exit_t texit;
 	char *tmp;
-	int retval;
+	int rc, retval;
 
 	tmp = str_dup(find_command(cmd));
 	free(found);
 
-	tid = task_spawn(tmp, (const char **) argv, &retval);
+	rc = task_spawnv(&tid, tmp, (const char **) argv);
 	free(tmp);
 
-	if (tid == 0) {
+	if (rc != 0) {
 		cli_error(CL_EEXEC, "%s: Cannot spawn `%s' (%s)", progname, cmd,
-		    str_error(retval));
+		    str_error(rc));
 		return 1;
 	}
 	
-	task_wait(tid, &texit, &retval);
-	if (texit != TASK_EXIT_NORMAL) {
+	rc = task_wait(tid, &texit, &retval);
+	if (rc != EOK) {
+		printf("%s: Failed waiting for command (%s)\n", str_error(rc));
+	} else if (texit != TASK_EXIT_NORMAL) {
 		printf("%s: Command failed (unexpectedly terminated)\n", progname);
 	} else if (retval != 0) {
-		printf("%s: Command failed (%s)\n",
-		    progname, str_error(retval));
+		printf("%s: Command failed (exit code %d)\n",
+		    progname, retval);
 	}
 
Index: uspace/app/getterm/getterm.c
===================================================================
--- uspace/app/getterm/getterm.c	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/app/getterm/getterm.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -41,4 +41,5 @@
 #include <task.h>
 #include <str_error.h>
+#include <errno.h>
 #include "version.h"
 
@@ -74,15 +75,13 @@
 static task_id_t spawn(const char *fname)
 {
-	const char *args[2];
+	task_id_t id;
+	int rc;
 	
-	args[0] = fname;
-	args[1] = NULL;
-	
-	int err;
-	task_id_t id = task_spawn(fname, args, &err);
-	
-	if (id == 0)
+	rc = task_spawnl(&id, fname, fname, NULL);
+	if (rc != EOK) {
 		printf("%s: Error spawning %s (%s)\n", APP_NAME, fname,
-		    str_error(err));
+		    str_error(rc));
+		return 0;
+	}
 	
 	return id;
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/app/init/init.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -124,5 +124,5 @@
 static void spawn(const char *fname)
 {
-	const char *argv[2];
+	int rc;
 	struct stat s;
 	
@@ -131,17 +131,13 @@
 	
 	printf("%s: Spawning %s\n", NAME, fname);
-	
-	argv[0] = fname;
-	argv[1] = NULL;
-	
-	int err;
-	if (!task_spawn(fname, argv, &err))
+	rc = task_spawnl(NULL, fname, fname, NULL);
+	if (rc != EOK) {
 		printf("%s: Error spawning %s (%s)\n", NAME, fname,
-		    str_error(err));
+		    str_error(rc));
+	}
 }
 
 static void srv_start(const char *fname)
 {
-	const char *argv[2];
 	task_id_t id;
 	task_exit_t texit;
@@ -153,12 +149,8 @@
 	
 	printf("%s: Starting %s\n", NAME, fname);
-	
-	argv[0] = fname;
-	argv[1] = NULL;
-	
-	id = task_spawn(fname, argv, &retval);
+	rc = task_spawnl(&id, fname, fname, NULL);
 	if (!id) {
 		printf("%s: Error spawning %s (%s)\n", NAME, fname,
-		    str_error(retval));
+		    str_error(rc));
 		return;
 	}
@@ -167,11 +159,17 @@
 	if (rc != EOK) {
 		printf("%s: Error waiting for %s (%s(\n", NAME, fname,
-		    str_error(retval));
-		return;
-	}
-	
-	if ((texit != TASK_EXIT_NORMAL) || (retval != 0)) {
-		printf("%s: Server %s failed to start (%s)\n", NAME,
-			fname, str_error(retval));
+		    str_error(rc));
+		return;
+	}
+	
+	if (texit != TASK_EXIT_NORMAL) {
+		printf("%s: Server %s failed to start (unexpectedly "
+		    "terminated)\n", NAME, fname);
+		return;
+	}
+
+	if (retval != 0) {
+		printf("%s: Server %s failed to start (exit code %d)\n", NAME,
+			fname, retval);
 	}
 }
@@ -179,5 +177,4 @@
 static void console(const char *dev)
 {
-	const char *argv[3];
 	char hid_in[DEVMAP_NAME_MAXLEN];
 	int rc;
@@ -190,21 +187,19 @@
 	dev_handle_t handle;
 	rc = devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING);
-	
-	if (rc == EOK) {
-		argv[0] = SRV_CONSOLE;
-		argv[1] = hid_in;
-		argv[2] = NULL;
-		
-		if (!task_spawn(SRV_CONSOLE, argv, &rc))
-			printf("%s: Error spawning %s %s (%s)\n", NAME, SRV_CONSOLE,
-			    hid_in, str_error(rc));
-	} else
+	if (rc != EOK) {
 		printf("%s: Error waiting on %s (%s)\n", NAME, hid_in,
 		    str_error(rc));
+		return;
+	}
+	
+	rc = task_spawnl(NULL, SRV_CONSOLE, SRV_CONSOLE, hid_in, NULL);
+	if (rc != EOK) {
+		printf("%s: Error spawning %s %s (%s)\n", NAME, SRV_CONSOLE,
+		    hid_in, str_error(rc));
+	}
 }
 
 static void getterm(const char *dev, const char *app)
 {
-	const char *argv[4];
 	char term[DEVMAP_NAME_MAXLEN];
 	int rc;
@@ -217,17 +212,15 @@
 	dev_handle_t handle;
 	rc = devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING);
-	
-	if (rc == EOK) {
-		argv[0] = APP_GETTERM;
-		argv[1] = term;
-		argv[2] = app;
-		argv[3] = NULL;
-		
-		if (!task_spawn(APP_GETTERM, argv, &rc))
-			printf("%s: Error spawning %s %s %s (%s)\n", NAME, APP_GETTERM,
-			    term, app, str_error(rc));
-	} else
+	if (rc != EOK) {
 		printf("%s: Error waiting on %s (%s)\n", NAME, term,
 		    str_error(rc));
+		return;
+	}
+	
+	rc = task_spawnl(NULL, APP_GETTERM, APP_GETTERM, term, app, NULL);
+	if (rc != EOK) {
+		printf("%s: Error spawning %s %s %s (%s)\n", NAME,
+		    APP_GETTERM, term, app, str_error(rc));
+	}
 }
 
Index: uspace/app/netstart/netstart.c
===================================================================
--- uspace/app/netstart/netstart.c	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/app/netstart/netstart.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -57,15 +57,11 @@
 static bool spawn(const char *desc, const char *path)
 {
+	int rc;
+
 	printf("%s: Spawning %s (%s)\n", NAME, desc, path);
-	
-	const char *argv[2];
-	
-	argv[0] = path;
-	argv[1] = NULL;
-	
-	int err;
-	if (task_spawn(path, argv, &err) == 0) {
+	rc = task_spawnl(NULL, path, path, NULL);
+	if (rc != EOK) {
 		fprintf(stderr, "%s: Error spawning %s (%s)\n", NAME, path,
-		    str_error(err));
+		    str_error(rc));
 		return false;
 	}
Index: uspace/app/netstart/self_test.c
===================================================================
--- uspace/app/netstart/self_test.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
+++ uspace/app/netstart/self_test.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ * @{
+ */
+
+/** @file
+ * Networking self-tests implementation.
+ *
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+
+#include <net_checksum.h>
+#include <adt/int_map.h>
+#include <adt/char_map.h>
+#include <adt/generic_char_map.h>
+#include <adt/measured_strings.h>
+#include <adt/dynamic_fifo.h>
+
+#include "self_test.h"
+
+/** Test the statement, compare the result and evaluate.
+ *
+ * @param[in] statement The statement to test.
+ * @param[in] result    The expected result.
+ *
+ */
+#define TEST(statement, result) \
+	do { \
+		printf("\n\t%s == %s", #statement, #result); \
+		if ((statement) != (result)) { \
+			printf("\tfailed\n"); \
+			fprintf(stderr, "\nNetwork self-test failed\n"); \
+			return EINVAL; \
+		} else \
+			printf("\tOK"); \
+	} while (0)
+
+#define XMALLOC(var, type) \
+	do { \
+		(var) = (type *) malloc(sizeof(type)); \
+		if ((var) == NULL) { \
+			fprintf(stderr, "\nMemory allocation error\n"); \
+			return ENOMEM; \
+		} \
+	} while (0)
+
+GENERIC_CHAR_MAP_DECLARE(int_char_map, int);
+GENERIC_CHAR_MAP_IMPLEMENT(int_char_map, int);
+
+GENERIC_FIELD_DECLARE(int_field, int);
+GENERIC_FIELD_IMPLEMENT(int_field, int);
+
+INT_MAP_DECLARE(int_map, int);
+INT_MAP_IMPLEMENT(int_map, int);
+
+/** Self-test start function.
+ *
+ * Run all self-tests.
+ *
+ * @returns EOK on success.
+ * @returns The first error occurred.
+ *
+ */
+int self_test(void)
+{
+	printf("Running networking self-tests\n");
+	
+	printf("\nChar map test");
+	char_map_t cm;
+	
+	TEST(char_map_update(&cm, "ucho", 0, 3), EINVAL);
+	TEST(char_map_initialize(&cm), EOK);
+	TEST(char_map_exclude(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_add(&cm, "bla", 0, 1), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 1);
+	TEST(char_map_add(&cm, "bla", 0, 10), EEXISTS);
+	TEST(char_map_update(&cm, "bla", 0, 2), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 2);
+	TEST(char_map_update(&cm, "ucho", 0, 2), EOK);
+	TEST(char_map_exclude(&cm, "bla", 0), 2);
+	TEST(char_map_exclude(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "ucho", 0), 2);
+	TEST(char_map_update(&cm, "ucho", 0, 3), EOK);
+	TEST(char_map_find(&cm, "ucho", 0), 3);
+	TEST(char_map_add(&cm, "blabla", 0, 5), EOK);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "bla", 0, 6), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 6);
+	TEST(char_map_exclude(&cm, "bla", 0), 6);
+	TEST(char_map_find(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "auto", 0, 7), EOK);
+	TEST(char_map_find(&cm, "auto", 0), 7);
+	TEST(char_map_add(&cm, "kara", 0, 8), EOK);
+	TEST(char_map_find(&cm, "kara", 0), 8);
+	TEST(char_map_add(&cm, "nic", 0, 9), EOK);
+	TEST(char_map_find(&cm, "nic", 0), 9);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "micnicnic", 5, 9), EOK);
+	TEST(char_map_find(&cm, "micni", 0), 9);
+	TEST(char_map_find(&cm, "micnicn", 5), 9);
+	TEST(char_map_add(&cm, "\x10\x0\x2\x2", 4, 15), EOK);
+	TEST(char_map_find(&cm, "\x10\x0\x2\x2", 4), 15);
+	
+	TEST((char_map_destroy(&cm), EOK), EOK);
+	TEST(char_map_update(&cm, "ucho", 0, 3), EINVAL);
+	
+	printf("\nCRC computation test");
+	uint32_t value;
+	
+	TEST(value = ~compute_crc32(~0, "123456789", 8 * 9), 0xcbf43926);
+	TEST(value = ~compute_crc32(~0, "1", 8), 0x83dcefb7);
+	TEST(value = ~compute_crc32(~0, "12", 8 * 2), 0x4f5344cd);
+	TEST(value = ~compute_crc32(~0, "123", 8 * 3), 0x884863d2);
+	TEST(value = ~compute_crc32(~0, "1234", 8 * 4), 0x9be3e0a3);
+	TEST(value = ~compute_crc32(~0, "12345678", 8 * 8), 0x9ae0daaf);
+	TEST(value = ~compute_crc32(~0, "ahoj pane", 8 * 9), 0x5fc3d706);
+	
+	printf("\nDynamic fifo test");
+	dyn_fifo_t fifo;
+	
+	TEST(dyn_fifo_push(&fifo, 1, 0), EINVAL);
+	TEST(dyn_fifo_initialize(&fifo, 1), EOK);
+	TEST(dyn_fifo_push(&fifo, 1, 0), EOK);
+	TEST(dyn_fifo_pop(&fifo), 1);
+	TEST(dyn_fifo_pop(&fifo), ENOENT);
+	TEST(dyn_fifo_push(&fifo, 2, 1), EOK);
+	TEST(dyn_fifo_push(&fifo, 3, 1), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 3, 0), EOK);
+	TEST(dyn_fifo_pop(&fifo), 2);
+	TEST(dyn_fifo_pop(&fifo), 3);
+	TEST(dyn_fifo_push(&fifo, 4, 2), EOK);
+	TEST(dyn_fifo_push(&fifo, 5, 2), EOK);
+	TEST(dyn_fifo_push(&fifo, 6, 2), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 6, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 7, 5), EOK);
+	TEST(dyn_fifo_pop(&fifo), 4);
+	TEST(dyn_fifo_pop(&fifo), 5);
+	TEST(dyn_fifo_push(&fifo, 8, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 9, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 10, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 11, 6), EOK);
+	TEST(dyn_fifo_pop(&fifo), 6);
+	TEST(dyn_fifo_pop(&fifo), 7);
+	TEST(dyn_fifo_push(&fifo, 12, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 13, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 14, 6), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 14, 8), EOK);
+	TEST(dyn_fifo_pop(&fifo), 8);
+	TEST(dyn_fifo_pop(&fifo), 9);
+	TEST(dyn_fifo_pop(&fifo), 10);
+	TEST(dyn_fifo_pop(&fifo), 11);
+	TEST(dyn_fifo_pop(&fifo), 12);
+	TEST(dyn_fifo_pop(&fifo), 13);
+	TEST(dyn_fifo_pop(&fifo), 14);
+	TEST(dyn_fifo_destroy(&fifo), EOK);
+	TEST(dyn_fifo_push(&fifo, 1, 0), EINVAL);
+	
+	printf("\nGeneric char map test");
+	
+	int *x;
+	int *y;
+	int *z;
+	int *u;
+	int *v;
+	int *w;
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_char_map_t icm;
+	icm.magic = 0;
+	
+	TEST(int_char_map_add(&icm, "ucho", 0, z), EINVAL);
+	TEST(int_char_map_initialize(&icm), EOK);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), NULL);
+	TEST(int_char_map_add(&icm, "bla", 0, x), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), x);
+	TEST(int_char_map_add(&icm, "bla", 0, y), EEXISTS);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_add(&icm, "blabla", 0, v), EOK);
+	TEST(int_char_map_find(&icm, "blabla", 0), v);
+	TEST(int_char_map_add(&icm, "bla", 0, w), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), w);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), NULL);
+	TEST(int_char_map_find(&icm, "blabla", 0), v);
+	TEST(int_char_map_add(&icm, "auto", 0, u), EOK);
+	TEST(int_char_map_find(&icm, "auto", 0), u);
+	TEST((int_char_map_destroy(&icm), EOK), EOK);
+	TEST(int_char_map_add(&icm, "ucho", 0, z), EINVAL);
+	
+	printf("\nGeneric field test");
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_field_t gf;
+	gf.magic = 0;
+	
+	TEST(int_field_add(&gf, x), EINVAL);
+	TEST(int_field_count(&gf), -1);
+	TEST(int_field_initialize(&gf), EOK);
+	TEST(int_field_count(&gf), 0);
+	TEST(int_field_get_index(&gf, 1), NULL);
+	TEST(int_field_add(&gf, x), 0);
+	TEST(int_field_get_index(&gf, 0), x);
+	TEST((int_field_exclude_index(&gf, 0), EOK), EOK);
+	TEST(int_field_get_index(&gf, 0), NULL);
+	TEST(int_field_add(&gf, y), 1);
+	TEST(int_field_get_index(&gf, 1), y);
+	TEST(int_field_add(&gf, z), 2);
+	TEST(int_field_get_index(&gf, 2), z);
+	TEST(int_field_get_index(&gf, 1), y);
+	TEST(int_field_count(&gf), 3);
+	TEST(int_field_add(&gf, u), 3);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST(int_field_add(&gf, v), 4);
+	TEST(int_field_get_index(&gf, 4), v);
+	TEST(int_field_add(&gf, w), 5);
+	TEST(int_field_get_index(&gf, 5), w);
+	TEST(int_field_count(&gf), 6);
+	TEST((int_field_exclude_index(&gf, 1), EOK), EOK);
+	TEST(int_field_get_index(&gf, 1), NULL);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST((int_field_exclude_index(&gf, 7), EOK), EOK);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST(int_field_get_index(&gf, 5), w);
+	TEST((int_field_exclude_index(&gf, 4), EOK), EOK);
+	TEST(int_field_get_index(&gf, 4), NULL);
+	TEST((int_field_destroy(&gf), EOK), EOK);
+	TEST(int_field_count(&gf), -1);
+	
+	printf("\nInt map test");
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_map_t im;
+	im.magic = 0;
+	
+	TEST(int_map_add(&im, 1, x), EINVAL);
+	TEST(int_map_count(&im), -1);
+	TEST(int_map_initialize(&im), EOK);
+	TEST(int_map_count(&im), 0);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_add(&im, 1, x), 0);
+	TEST(int_map_find(&im, 1), x);
+	TEST((int_map_exclude(&im, 1), EOK), EOK);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_add(&im, 1, y), 1);
+	TEST(int_map_find(&im, 1), y);
+	TEST(int_map_add(&im, 4, z), 2);
+	TEST(int_map_get_index(&im, 2), z);
+	TEST(int_map_find(&im, 4), z);
+	TEST(int_map_find(&im, 1), y);
+	TEST(int_map_count(&im), 3);
+	TEST(int_map_add(&im, 2, u), 3);
+	TEST(int_map_find(&im, 2), u);
+	TEST(int_map_add(&im, 3, v), 4);
+	TEST(int_map_find(&im, 3), v);
+	TEST(int_map_get_index(&im, 4), v);
+	TEST(int_map_add(&im, 6, w), 5);
+	TEST(int_map_find(&im, 6), w);
+	TEST(int_map_count(&im), 6);
+	TEST((int_map_exclude(&im, 1), EOK), EOK);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_find(&im, 2), u);
+	TEST((int_map_exclude(&im, 7), EOK), EOK);
+	TEST(int_map_find(&im, 2), u);
+	TEST(int_map_find(&im, 6), w);
+	TEST((int_map_exclude_index(&im, 4), EOK), EOK);
+	TEST(int_map_get_index(&im, 4), NULL);
+	TEST(int_map_find(&im, 3), NULL);
+	TEST((int_map_destroy(&im), EOK), EOK);
+	TEST(int_map_count(&im), -1);
+	
+	printf("\nMeasured strings test");
+	
+	measured_string_ref string =
+	    measured_string_create_bulk("I am a measured string!", 0);
+	printf("\n%x, %s at %x of %d\n", string, string->value, string->value,
+	    string->length);
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/app/netstart/self_test.h
===================================================================
--- uspace/app/netstart/self_test.h	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
+++ uspace/app/netstart/self_test.h	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ * @{
+ */
+
+#ifndef __SELF_TEST_H__
+#define __SELF_TEST_H__
+
+extern int self_test(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/app/redir/redir.c
===================================================================
--- uspace/app/redir/redir.c	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/app/redir/redir.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -43,4 +43,5 @@
 #include <task.h>
 #include <str_error.h>
+#include <errno.h>
 
 #define NAME  "redir"
@@ -76,5 +77,9 @@
 static task_id_t spawn(int argc, char *argv[])
 {
-	const char **args = (const char **) calloc(argc + 1, sizeof(char *));
+	const char **args;
+	task_id_t id;
+	int rc;
+
+	args = (const char **) calloc(argc + 1, sizeof(char *));
 	if (!args) {
 		printf("No memory available\n");
@@ -88,12 +93,12 @@
 	args[argc] = NULL;
 	
-	int err;
-	task_id_t id = task_spawn(argv[0], args, &err);
+	rc = task_spawnv(&id, argv[0], args);
 	
 	free(args);
 	
-	if (id == 0)
+	if (rc != EOK) {
 		printf("%s: Error spawning %s (%s)\n", NAME, argv[0],
-		    str_error(err));
+		    str_error(rc));
+	}
 	
 	return id;
Index: uspace/app/sbi/src/os/helenos.c
===================================================================
--- uspace/app/sbi/src/os/helenos.c	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/app/sbi/src/os/helenos.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -249,15 +249,16 @@
 	task_id_t tid;
 	task_exit_t texit;
-	int retval;
-
-	tid = task_spawn(cmd[0], (char const * const *) cmd, &retval);
-	if (tid == 0) {
+	int rc, retval;
+
+	rc = task_spawnv(&tid, cmd[0], (char const * const *) cmd);
+	if (rc != EOK) {
 		printf("Error: Failed spawning '%s' (%s).\n", cmd[0],
-		    str_error(retval));
+		    str_error(rc));
 		exit(1);
 	}
 
 	/* XXX Handle exit status and return value. */
-	task_wait(tid, &texit, &retval);
+	rc = task_wait(tid, &texit, &retval);
+	(void) rc;
 
 	return EOK;
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/lib/c/generic/task.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -39,4 +39,5 @@
 #include <errno.h>
 #include <loader/loader.h>
+#include <stdarg.h>
 #include <str.h>
 #include <ipc/ns.h>
@@ -68,27 +69,25 @@
  *
  * This is really just a convenience wrapper over the more complicated
- * loader API.
- *
- * @param path Pathname of the binary to execute.
- * @param argv Command-line arguments.
- * @param err  If not NULL, the error value is stored here.
- *
- * @return ID of the newly created task or zero on error.
- *
- */
-task_id_t task_spawn(const char *path, const char *const args[], int *err)
-{
+ * loader API. Arguments are passed as a null-terminated array of strings.
+ *
+ * @param id 	If not NULL, the ID of the task is stored here on success.
+ * @param path	Pathname of the binary to execute.
+ * @param argv	Command-line arguments.
+ *
+ * @return	Zero on success or negative error code.
+ */
+int task_spawnv(task_id_t *id, const char *path, const char *const args[])
+{
+	loader_t *ldr;
+	task_id_t task_id;
+	int rc;
+
 	/* Connect to a program loader. */
-	loader_t *ldr = loader_connect();
-	if (ldr == NULL) {
-		if (err != NULL)
-			*err = EREFUSED;
-		
-		return 0;
-	}
+	ldr = loader_connect();
+	if (ldr == NULL)
+		return EREFUSED;
 	
 	/* Get task ID. */
-	task_id_t task_id;
-	int rc = loader_get_task_id(ldr, &task_id);
+	rc = loader_get_task_id(ldr, &task_id);
 	if (rc != EOK)
 		goto error;
@@ -149,8 +148,8 @@
 	free(ldr);
 	
-	if (err != NULL)
-		*err = EOK;
-	
-	return task_id;
+	if (id != NULL)
+		*id = task_id;
+	
+	return EOK;
 	
 error:
@@ -158,9 +157,54 @@
 	loader_abort(ldr);
 	free(ldr);
-	
-	if (err != NULL)
-		*err = rc;
-	
-	return 0;
+	return rc;
+}
+
+/** Create a new task by running an executable from the filesystem.
+ *
+ * This is really just a convenience wrapper over the more complicated
+ * loader API. Arguments are passed as a null-terminated list of arguments.
+ *
+ * @param id 	If not NULL, the ID of the task is stored here on success.
+ * @param path	Pathname of the binary to execute.
+ * @param ...	Command-line arguments.
+ *
+ * @return	Zero on success or negative error code.
+ */
+int task_spawnl(task_id_t *task_id, const char *path, ...)
+{
+	va_list ap;
+	int rc, cnt;
+	const char *arg;
+	const char **arglist;
+
+	/* Count the number of arguments. */
+	cnt = 0;
+	va_start(ap, path);
+	do {
+		arg = va_arg(ap, const char *);
+		cnt++;
+	} while (arg != NULL);
+	va_end(ap);
+
+	/* Allocate argument list. */
+	arglist = malloc(cnt * sizeof(const char *));
+	if (arglist == NULL)
+		return ENOMEM;
+
+	/* Fill in arguments. */
+	cnt = 0;
+	va_start(ap, path);
+	do {
+		arg = va_arg(ap, const char *);
+		arglist[cnt++] = arg;
+	} while (arg != NULL);
+	va_end(ap);
+
+	/* Spawn task. */
+	rc = task_spawnv(task_id, path, arglist);
+
+	/* Free argument list. */
+	free(arglist);
+	return rc;
 }
 
Index: uspace/lib/c/include/task.h
===================================================================
--- uspace/lib/c/include/task.h	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/lib/c/include/task.h	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -48,4 +48,7 @@
 extern int task_set_name(const char *);
 extern task_id_t task_spawn(const char *, const char *const[], int *);
+extern int task_spawnv(task_id_t *, const char *path, const char *const []);
+extern int task_spawnl(task_id_t *, const char *path, ...);
+
 extern int task_wait(task_id_t id, task_exit_t *, int *);
 extern int task_retval(int);
Index: uspace/lib/net/adt/module_map.c
===================================================================
--- uspace/lib/net/adt/module_map.c	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/lib/net/adt/module_map.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -132,12 +132,12 @@
 task_id_t spawn(const char *fname)
 {
-	const char *argv[2];
-	task_id_t res;
+	task_id_t id;
+	int rc;
 	
-	argv[0] = fname;
-	argv[1] = NULL;
-	res = task_spawn(fname, argv, NULL);
+	rc = task_spawnl(&id, fname, fname, NULL);
+	if (rc != EOK)
+		return 0;
 	
-	return res;
+	return id;
 }
 
Index: uspace/lib/packet/include/netdb.h
===================================================================
--- uspace/lib/packet/include/netdb.h	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
+++ uspace/lib/packet/include/netdb.h	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup netdb
+ *  @{
+ */
+
+/** @file
+ *  Structures and interfaces according to the BSD netdb.h file.
+ */
+
+#ifndef __NET_NETDB_H__
+#define __NET_NETDB_H__
+
+#include <sys/types.h>
+
+/** Structure returned by network data base library.
+ *  All addresses are supplied in host order, and returned in network order (suitable for use in system calls).
+ */
+struct	hostent {
+	/** Official host name.
+	 */
+	char * h_name;
+	/** Alias list.
+	 */
+	char **	h_aliases;
+	/** Host address type.
+	 */
+	int h_addrtype;
+	/** Address length.
+	 */
+	int h_length;
+	/** List of addresses from name server.
+	 */
+	char **	h_addr_list;
+	/** Address, for backward compatiblity.
+	 */
+#define	h_addr	h_addr_list[0]
+};
+
+/** @name Host entry address types definitions.
+ */
+/*@{*/
+
+/** Authoritative Answer Host not found address type.
+ */
+#define	HOST_NOT_FOUND	1
+
+/** Non-Authoritive Host not found, or SERVERFAIL address type.
+ */
+#define	TRY_AGAIN	2
+
+/** Non recoverable errors, FORMERR, REFUSED, NOTIMP address type.
+ */
+#define	NO_RECOVERY	3
+
+/** Valid name, no data record of requested type address type.
+ */
+#define	NO_DATA		4
+
+/** No address, look for MX record address type.
+ */
+#define	NO_ADDRESS	NO_DATA
+
+/*@}*/
+
+/** Returns host entry by the host address.
+ *  @param[in] address The host address.
+ *  @param[in] len The address length.
+ *  @param[in] type The address type.
+ *  @returns Host entry information.
+ */
+//struct hostent *	gethostbyaddr(const void * address, int len, int type);
+
+/** Returns host entry by the host name.
+ *  @param[in] name The host name.
+ *  @returns Host entry information.
+ */
+//struct hostent *	gethostbyname(const char * name);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/packet/include/tcp_codes.h
===================================================================
--- uspace/lib/packet/include/tcp_codes.h	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
+++ uspace/lib/packet/include/tcp_codes.h	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ *  @{
+ */
+
+/** @file
+ *  TCP options definitions.
+ */
+
+#ifndef __NET_TCP_CODES_H__
+#define __NET_TCP_CODES_H__
+
+/** End of list TCP option.
+ */
+#define TCPOPT_END_OF_LIST				0x0
+
+/** No operation TCP option.
+ */
+#define TCPOPT_NO_OPERATION				0x1
+
+/** Maximum segment size TCP option.
+ */
+#define TCPOPT_MAX_SEGMENT_SIZE			0x2
+
+/** Maximum segment size TCP option length.
+ */
+#define TCPOPT_MAX_SEGMENT_SIZE_LENGTH	4
+
+/** Window scale TCP option.
+ */
+#define TCPOPT_WINDOW_SCALE				0x3
+
+/** Window scale TCP option length.
+ */
+#define TCPOPT_WINDOW_SCALE_LENGTH		3
+
+/** Selective acknowledgement permitted TCP option.
+ */
+#define TCPOPT_SACK_PERMITTED			0x4
+
+/** Selective acknowledgement permitted TCP option length.
+ */
+#define TCPOPT_SACK_PERMITTED_LENGTH	2
+
+/** Selective acknowledgement TCP option.
+ *  Has variable length.
+ */
+#define TCPOPT_SACK						0x5
+
+/** Timestamp TCP option.
+ */
+#define TCPOPT_TIMESTAMP				0x8
+
+/** Timestamp TCP option length.
+ */
+#define TCPOPT_TIMESTAMP_LENGTH			10
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/srv/devman/devman.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -37,4 +37,5 @@
 #include <ipc/devman.h>
 #include <devmap.h>
+#include <str_error.h>
 
 #include "devman.h"
@@ -446,15 +447,12 @@
 bool start_driver(driver_t *drv)
 {
+	int rc;
+
 	printf(NAME ": start_driver '%s'\n", drv->name);
 	
-	const char *argv[2];
-	
-	argv[0] = drv->name;
-	argv[1] = NULL;
-	
-	int err;
-	if (task_spawn(drv->binary_path, argv, &err) == 0) {
-		printf(NAME ": error spawning %s, errno = %d\n",
-		    drv->name, err);
+	rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL);
+	if (rc != EOK) {
+		printf(NAME ": error spawning %s (%s)\n",
+		    drv->name, str_error(rc));
 		return false;
 	}
Index: uspace/srv/taskmon/taskmon.c
===================================================================
--- uspace/srv/taskmon/taskmon.c	(revision 0578271269331fb048f182ef5c3d26dae37c84ea)
+++ uspace/srv/taskmon/taskmon.c	(revision 0b81cad0360a509d54d5a8a7f64c14e5fb6f91e6)
@@ -50,9 +50,7 @@
 static void fault_event(ipc_callid_t callid, ipc_call_t *call)
 {
-	const char *argv[6];
 	const char *fname;
-	char *dump_fname;
 	char *s_taskid;
-	const char **s;
+	int rc;
 
 	task_id_t taskid;
@@ -67,4 +65,11 @@
 	}
 
+	printf(NAME ": Task %" PRIuTASKID " fault in thread %p.\n", taskid, thread);
+
+	fname = "/app/taskdump";
+
+#ifdef CONFIG_WRITE_CORE_FILES
+	char *dump_fname;
+
 	if (asprintf(&dump_fname, "/data/core%" PRIuTASKID, taskid) < 0) {
 		printf("Memory allocation failed.\n");
@@ -72,34 +77,15 @@
 	}
 
-	printf(NAME ": Task %" PRIuTASKID " fault in thread %p.\n", taskid, thread);
-
-#ifdef CONFIG_WRITE_CORE_FILES
-	argv[0] = "/app/taskdump";
-	argv[1] = "-c";
-	argv[2] = dump_fname;
-	argv[3] = "-t";
-	argv[4] = s_taskid;
-	argv[5] = NULL;
+	printf(NAME ": Executing %s -c %s -t %s\n", dump_fname, s_taskid);
+	rc = task_spawnl(NULL, fname, fname, "-c", dump_fname, "-t", s_taskid,
+	    NULL);
 #else
-	argv[0] = "/app/taskdump";
-	argv[1] = "-t";
-	argv[2] = s_taskid;
-	argv[3] = NULL;
+	printf(NAME ": Executing %s -t %s\n", s_taskid);
+	rc = task_spawnl(NULL, fname, fname, "-t", s_taskid, NULL);
 #endif
-	fname = argv[0];
-
-	printf(NAME ": Executing");
-	
-	s = argv;
-	while (*s != NULL) {
-		printf(" %s", *s);
-		++s;
+	if (rc != EOK) {
+		printf("%s: Error spawning %s (%s).\n", NAME, fname,
+		    str_error(rc));
 	}
-	putchar('\n');
-	
-	int err;
-	if (!task_spawn(fname, argv, &err))
-		printf("%s: Error spawning %s (%s).\n", NAME, fname,
-		    str_error(err));
 }
 
