Index: uspace/app/bdsh/exec.c
===================================================================
--- uspace/app/bdsh/exec.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/app/bdsh/exec.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -101,6 +101,5 @@
 	char *tmp;
 	int rc, retval, i;
-	int file_handles[3];
-	int *file_handles_p[4];
+	int file_handles[3] = { -1, -1, -1 };
 	FILE *files[3];
 
@@ -113,14 +112,9 @@
 	
 	for (i = 0; i < 3 && files[i] != NULL; i++) {
-		if (vfs_fhandle(files[i], &file_handles[i]) == EOK) {
-			file_handles_p[i] = &file_handles[i];
-		}
-		else {
-			file_handles_p[i] = NULL;
-		}
+		vfs_fhandle(files[i], &file_handles[i]);
 	}
-	file_handles_p[i] = NULL;
 
-	rc = task_spawnvf(&tid, &twait, tmp, (const char **) argv, file_handles_p);
+	rc = task_spawnvf(&tid, &twait, tmp, (const char **) argv,
+	    file_handles[0], file_handles[1], file_handles[2]);
 	free(tmp);
 
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/app/trace/trace.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -513,5 +513,5 @@
 
 	/* Send program pathname */
-	rc = loader_set_pathname(ldr, path);
+	rc = loader_set_program_path(ldr, path);
 	if (rc != EOK)
 		goto error;
@@ -523,30 +523,26 @@
 
 	/* Send default files */
-	int *files[4];
 	int fd_stdin;
 	int fd_stdout;
 	int fd_stderr;
 	
-	if ((stdin != NULL) && (vfs_fhandle(stdin, &fd_stdin) == EOK))
-		files[0] = &fd_stdin;
-	else
-		files[0] = NULL;
-	
-	if ((stdout != NULL) && (vfs_fhandle(stdout, &fd_stdout) == EOK))
-		files[1] = &fd_stdout;
-	else
-		files[1] = NULL;
-	
-	if ((stderr != NULL) && (vfs_fhandle(stderr, &fd_stderr) == EOK))
-		files[2] = &fd_stderr;
-	else
-		files[2] = NULL;
-	
-	files[3] = NULL;
-	
-	rc = loader_set_files(ldr, files);
-	if (rc != EOK)
-		goto error;
-
+	if ((stdin != NULL) && (vfs_fhandle(stdin, &fd_stdin) == EOK)) {
+		rc = loader_add_inbox(ldr, "stdin", fd_stdin);
+		if (rc != EOK)
+			goto error;
+	}
+	
+	if ((stdout != NULL) && (vfs_fhandle(stdout, &fd_stdout) == EOK)) {
+		rc = loader_add_inbox(ldr, "stdout", fd_stdout);
+		if (rc != EOK)
+			goto error;
+	}
+	
+	if ((stderr != NULL) && (vfs_fhandle(stderr, &fd_stderr) == EOK)) {
+		rc = loader_add_inbox(ldr, "stderr", fd_stderr);
+		if (rc != EOK)
+			goto error;
+	}
+	
 	/* Load the program. */
 	rc = loader_load_program(ldr);
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/Makefile	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -151,4 +151,5 @@
 	generic/rcu.c \
 	generic/setjmp.c \
+	generic/vfs/inbox.c \
 	generic/stack.c \
 	generic/stacktrace.c \
Index: uspace/lib/c/generic/elf/elf_load.c
===================================================================
--- uspace/lib/c/generic/elf/elf_load.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/generic/elf/elf_load.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -41,4 +41,5 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <vfs/vfs.h>
 
 #ifdef CONFIG_RTLD
@@ -50,9 +51,9 @@
 /** Load ELF program.
  *
- * @param file_name File name
+ * @param file File handle 
  * @param info Place to store ELF program information
  * @return EOK on success or non-zero error code
  */
-int elf_load(const char *file_name, elf_info_t *info)
+int elf_load(int file, elf_info_t *info)
 {
 #ifdef CONFIG_RTLD
@@ -61,5 +62,5 @@
 	int rc;
 
-	rc = elf_load_file(file_name, 0, 0, &info->finfo);
+	rc = elf_load_file(file, 0, 0, &info->finfo);
 	if (rc != EE_OK) {
 		DPRINTF("Failed to load executable '%s'.\n", file_name);
Index: uspace/lib/c/generic/elf/elf_mod.c
===================================================================
--- uspace/lib/c/generic/elf/elf_mod.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/generic/elf/elf_mod.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -92,5 +92,5 @@
  *
  */
-static int elf_load_file2(int file, size_t so_bias, eld_flags_t flags, elf_finfo_t *info)
+int elf_load_file(int file, size_t so_bias, eld_flags_t flags, elf_finfo_t *info)
 {
 	elf_ld_t elf;
@@ -112,8 +112,9 @@
 }
 
-int elf_load_file(const char *path, size_t so_bias, eld_flags_t flags, elf_finfo_t *info)
+int elf_load_file_name(const char *path, size_t so_bias, eld_flags_t flags,
+    elf_finfo_t *info)
 {
 	int file = vfs_lookup(path);
-	int rc = elf_load_file2(file, so_bias, flags, info);
+	int rc = elf_load_file(file, so_bias, flags, info);
 	close(file);
 	return rc;
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/generic/io/io.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -45,4 +45,5 @@
 #include <vfs/vfs.h>
 #include <vfs/vfs_sess.h>
+#include <vfs/inbox.h>
 #include <ipc/loc.h>
 #include <adt/list.h>
@@ -101,8 +102,16 @@
 static LIST_INITIALIZE(files);
 
-void __stdio_init(int filc)
-{
-	if (filc > 0) {
-		stdin = fdopen(0, "r");
+void __stdio_init(void)
+{
+	/* The first three standard file descriptors are assigned for compatibility.
+	 * This will probably be removed later.
+	 */
+	 
+	int infd = inbox_get("stdin");
+	if (infd >= 0) {
+		int stdinfd = vfs_clone(infd, false);
+		assert(stdinfd == 0);
+		_vfs_open(stdinfd, MODE_READ);
+		stdin = fdopen(stdinfd, "r");
 	} else {
 		stdin = &stdin_null;
@@ -110,6 +119,13 @@
 	}
 	
-	if (filc > 1) {
-		stdout = fdopen(1, "w");
+	int outfd = inbox_get("stdout");
+	if (outfd >= 0) {
+		int stdoutfd = vfs_clone(outfd, false);
+		assert(stdoutfd <= 1);
+		while (stdoutfd < 1) {
+			stdoutfd = vfs_clone(outfd, false);
+		}
+		_vfs_open(stdoutfd, MODE_APPEND);
+		stdout = fdopen(stdoutfd, "a");
 	} else {
 		stdout = &stdout_kio;
@@ -117,6 +133,13 @@
 	}
 	
-	if (filc > 2) {
-		stderr = fdopen(2, "w");
+	int errfd = inbox_get("stderr");
+	if (errfd >= 0) {
+		int stderrfd = vfs_clone(errfd, false);
+		assert(stderrfd <= 2);
+		while (stderrfd < 2) {
+			stderrfd = vfs_clone(errfd, false);
+		}
+		_vfs_open(stderrfd, MODE_APPEND);
+		stderr = fdopen(stderrfd, "a");
 	} else {
 		stderr = &stderr_kio;
Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/generic/libc.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -107,9 +107,10 @@
 		argc = 0;
 		argv = NULL;
-		__stdio_init(0);
+		__stdio_init();
 	} else {
 		argc = __pcb->argc;
 		argv = __pcb->argv;
-		__stdio_init(__pcb->filc);
+		__inbox_init(__pcb->inbox, __pcb->inbox_entries);
+		__stdio_init();
 		(void) chdir(__pcb->cwd);
 	}
Index: uspace/lib/c/generic/loader.c
===================================================================
--- uspace/lib/c/generic/loader.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/generic/loader.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -147,41 +147,65 @@
 }
 
-/** Set pathname of the program to load.
- *
- * Sets the name of the program file to load. The name can be relative
- * to the current working directory (it will be absolutized before
- * sending to the loader).
+/** Set the program to load.
  *
  * @param ldr  Loader connection structure.
- * @param path Pathname of the program file.
- *
- * @return Zero on success or negative error code.
- *
- */
-int loader_set_pathname(loader_t *ldr, const char *path)
-{
-	size_t pa_len;
-	char *pa = vfs_absolutize(path, &pa_len);
-	if (!pa)
-		return ENOMEM;
-	
-	/* Send program pathname */
-	async_exch_t *exch = async_exchange_begin(ldr->sess);
-	
+ * @param name Name to set for the spawned program.
+ * @param file Program file.
+ *
+ * @return Zero on success or negative error code.
+ *
+ */
+int loader_set_program(loader_t *ldr, const char *name, int file)
+{
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+
 	ipc_call_t answer;
-	aid_t req = async_send_0(exch, LOADER_SET_PATHNAME, &answer);
-	sysarg_t rc = async_data_write_start(exch, (void *) pa, pa_len);
-	
-	async_exchange_end(exch);
-	free(pa);
-	
+	aid_t req = async_send_0(exch, LOADER_SET_PROGRAM, &answer);
+
+	sysarg_t rc = async_data_write_start(exch, name, str_size(name) + 1);
+	if (rc == EOK) {
+		async_exch_t *vfs_exch = vfs_exchange_begin();
+		rc = vfs_pass_handle(vfs_exch, file, exch);
+		vfs_exchange_end(vfs_exch);
+	}
+
+	async_exchange_end(exch);
+
 	if (rc != EOK) {
 		async_forget(req);
 		return (int) rc;
 	}
-	
+
 	async_wait_for(req, &rc);
 	return (int) rc;
 }
+
+/** Set the program to load by path.
+ *
+ * @param ldr  Loader connection structure.
+ * @param path Program path.
+ *
+ * @return Zero on success or negative error code.
+ *
+ */
+int loader_set_program_path(loader_t *ldr, const char *path)
+{
+	const char *name = str_rchr(path, '/');
+	if (name == NULL) {
+		name = path;
+	} else {
+		name++;
+	}
+	
+	int fd = vfs_lookup(path);
+	if (fd < 0) {
+		return fd;
+	}
+	
+	int rc = loader_set_program(ldr, name, fd);
+	close(fd);
+	return rc;
+}
+
 
 /** Set command-line arguments for the program.
@@ -244,45 +268,34 @@
 }
 
-/** Set preset files for the program.
- *
- * Sets the vector of preset files to be passed to the loaded
- * program. By convention, the first three files represent stdin,
- * stdout and stderr respectively.
- *
- * @param ldr   Loader connection structure.
- * @param files NULL-terminated array of pointers to files.
- *
- * @return Zero on success or negative error code.
- *
- */
-int loader_set_files(loader_t *ldr, int * const files[])
-{
-	/* Send serialized files to the loader */
+/** Add a file to the task's inbox.
+ *
+ * @param ldr        Loader connection structure.
+ * @param name       Identification of the file.
+ * @param file       The file's descriptor.
+ *
+ * @return Zero on success or negative error code.
+ *
+ */
+int loader_add_inbox(loader_t *ldr, const char *name, int file)
+{
 	async_exch_t *exch = async_exchange_begin(ldr->sess);
 	async_exch_t *vfs_exch = vfs_exchange_begin();
 	
-	int i;
-	for (i = 0; files[i]; i++);
-
-	ipc_call_t answer;
-	aid_t req = async_send_1(exch, LOADER_SET_FILES, i, &answer);
-
-	sysarg_t rc = EOK;
-	
-	for (i = 0; files[i]; i++) {
-		rc = vfs_pass_handle(vfs_exch, *files[i], exch);
-		if (rc != EOK)
-			break;
-	}
-	
-	vfs_exchange_end(vfs_exch);
-	async_exchange_end(exch);
-
-	if (rc != EOK) {
-		async_forget(req);
-		return (int) rc;
-	}
-	
-	async_wait_for(req, &rc);
+	aid_t req = async_send_0(exch, LOADER_ADD_INBOX, NULL);
+	
+	sysarg_t rc = async_data_write_start(exch, name, str_size(name) + 1);
+	if (rc == EOK) {
+		rc = vfs_pass_handle(vfs_exch, file, exch);
+	}
+	
+	async_exchange_end(vfs_exch);
+	async_exchange_end(exch);
+	
+	if (rc == EOK) {
+		async_wait_for(req, &rc);
+	} else {
+		async_forget(req);
+	}
+	
 	return (int) rc;
 }
Index: uspace/lib/c/generic/private/io.h
===================================================================
--- uspace/lib/c/generic/private/io.h	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/generic/private/io.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -36,6 +36,10 @@
 #define LIBC_PRIVATE_IO_H_
 
-extern void __stdio_init(int);
+#include <loader/pcb.h>
+
+extern void __stdio_init(void);
 extern void __stdio_done(void);
+
+extern void __inbox_init(struct pcb_inbox_entry *entries, int count);
 
 #endif
Index: uspace/lib/c/generic/rtld/module.c
===================================================================
--- uspace/lib/c/generic/rtld/module.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/generic/rtld/module.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -196,5 +196,5 @@
 	DPRINTF("load '%s' at 0x%x\n", name_buf, m->bias);
 
-	rc = elf_load_file(name_buf, m->bias, ELDF_RW, &info);
+	rc = elf_load_file_name(name_buf, m->bias, ELDF_RW, &info);
 	if (rc != EE_OK) {
 		printf("Failed to load '%s'\n", name_buf);
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/generic/task.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -107,27 +107,23 @@
 {
 	/* Send default files */
-	int *files[4];
-	int fd_stdin;
-	int fd_stdout;
-	int fd_stderr;
-	
-	if ((stdin != NULL) && (vfs_fhandle(stdin, &fd_stdin) == EOK))
-		files[0] = &fd_stdin;
-	else
-		files[0] = NULL;
-	
-	if ((stdout != NULL) && (vfs_fhandle(stdout, &fd_stdout) == EOK))
-		files[1] = &fd_stdout;
-	else
-		files[1] = NULL;
-	
-	if ((stderr != NULL) && (vfs_fhandle(stderr, &fd_stderr) == EOK))
-		files[2] = &fd_stderr;
-	else
-		files[2] = NULL;
-	
-	files[3] = NULL;
-	
-	return task_spawnvf(id, wait, path, args, files);
+	
+	int fd_stdin = -1;
+	int fd_stdout = -1;
+	int fd_stderr = -1;
+	
+	if (stdin != NULL) {
+		(void) vfs_fhandle(stdin, &fd_stdin);
+	}
+	
+	if (stdout != NULL) {
+		(void) vfs_fhandle(stdout, &fd_stdout);
+	}
+
+	if (stderr != NULL) {
+		(void) vfs_fhandle(stderr, &fd_stderr);
+	}
+	
+	return task_spawnvf(id, wait, path, args, fd_stdin, fd_stdout,
+	    fd_stderr);
 }
 
@@ -138,10 +134,11 @@
  * Files are passed as null-terminated array of pointers to fdi_node_t.
  *
- * @param id    If not NULL, the ID of the task is stored here on success.
- * @param wait  If not NULL, setup waiting for task's return value and store
- *              the information necessary for waiting here on success.
- * @param path  Pathname of the binary to execute.
- * @param argv  Command-line arguments.
- * @param files Standard files to use.
+ * @param id      If not NULL, the ID of the task is stored here on success.
+ * @param wait    If not NULL, setup waiting for task's return value and store
+ * @param path    Pathname of the binary to execute.
+ * @param argv    Command-line arguments.
+ * @param std_in  File to use as stdin.
+ * @param std_out File to use as stdout.
+ * @param std_err File to use as stderr.
  *
  * @return Zero on success or negative error code.
@@ -149,5 +146,5 @@
  */
 int task_spawnvf(task_id_t *id, task_wait_t *wait, const char *path,
-    const char *const args[], int *const files[])
+    const char *const args[], int fd_stdin, int fd_stdout, int fd_stderr)
 {
 	/* Connect to a program loader. */
@@ -169,6 +166,6 @@
 		goto error;
 	
-	/* Send program pathname. */
-	rc = loader_set_pathname(ldr, path);
+	/* Send program binary. */
+	rc = loader_set_program_path(ldr, path);
 	if (rc != EOK)
 		goto error;
@@ -180,7 +177,21 @@
 	
 	/* Send files */
-	rc = loader_set_files(ldr, files);
-	if (rc != EOK)
-		goto error;
+	if (fd_stdin >= 0) {
+		rc = loader_add_inbox(ldr, "stdin", fd_stdin);
+		if (rc != EOK)
+			goto error;
+	}
+	
+	if (fd_stdout >= 0) {
+		rc = loader_add_inbox(ldr, "stdout", fd_stdout);
+		if (rc != EOK)
+			goto error;
+	}
+	
+	if (fd_stderr >= 0) {
+		rc = loader_add_inbox(ldr, "stderr", fd_stderr);
+		if (rc != EOK)
+			goto error;
+	}		
 	
 	/* Load the program. */
Index: uspace/lib/c/generic/vfs/inbox.c
===================================================================
--- uspace/lib/c/generic/vfs/inbox.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
+++ uspace/lib/c/generic/vfs/inbox.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -0,0 +1,131 @@
+
+#include <vfs/inbox.h>
+
+#include <adt/list.h>
+#include <str.h>
+#include <stdlib.h>
+#include <loader/pcb.h>
+#include "../private/io.h"
+#include <errno.h>
+
+/* This is an attempt at generalization of the "standard files" concept to arbitrary names.
+ * When loading a task, the parent can put arbitrary files to an "inbox" through IPC calls,
+ * every file in an inbox has a name assigned (e.g. "stdin", "stdout", "stderr", "data", "logfile",
+ * etc.). The client then retrieves those files from inbox by name. "stdin", "stdout" and "stderr"
+ * are handled automatically by libc to initialize standard <stdio.h> streams and legacy file
+ * descriptors 0, 1, 2. Other names are subject to conventions and application-specific rules.
+ */
+
+typedef struct {
+	link_t link;
+	char *name;
+	int file;
+} inbox_entry;
+
+static LIST_INITIALIZE(inb_list);
+
+/* Inserts a named file into the inbox.
+ * If a file with the same name is already present, it overwrites it and returns the original
+ * value. Otherwise, it returns -1.
+ * If the argument 'file' is -1, nothing is inserted and the file with specified name is
+ * removed and returned if present.
+ *
+ * @param name Name of the inbox entry.
+ * @param file File to insert or -1.
+ * @return Original value of the entry or -1 if not originally present.
+ */
+int inbox_set(const char *name, int file)
+{
+	inbox_entry *next = NULL;
+	
+	list_foreach(inb_list, link, inbox_entry, e) {
+		int cmp = str_cmp(e->name, name);
+		switch (cmp) {
+		case -1:
+			continue;
+		case 0:;
+			int result = e->file;
+			if (file == -1) {
+				free(e->name);
+				/* Safe because we exit immediately. */
+				list_remove(&e->link);
+			} else {
+				e->file = file;
+			}
+			return result;
+		case 1:
+			next = e;
+			goto out;
+		}
+	}
+
+out:
+	if (file == -1) {
+		return -1;
+	}
+
+	inbox_entry *entry = calloc(sizeof(inbox_entry), 1);
+	entry->name = str_dup(name);
+	entry->file = file;
+
+	if (next == NULL) {
+		list_append((link_t *)entry, &inb_list);
+	} else {
+		list_insert_before((link_t *)entry, (link_t *)next);
+	}
+	return -1;
+}
+
+/* Retrieve a file with this name.
+ *
+ * @param name Name of the entry.
+ * @return Requested file or ENOENT if not set.
+ */
+int inbox_get(const char *name)
+{
+	list_foreach(inb_list, link, inbox_entry, e) {
+		int cmp = str_cmp(e->name, name);
+		switch (cmp) {
+		case 0:
+			return e->file;
+		case 1:
+			return ENOENT;
+		} 
+	}
+
+	return ENOENT;
+}
+
+/* Writes names of entries that are currently set into and array provided by the user.
+ *
+ * @param names Array in which names are stored.
+ * @param capacity Capacity of the array.
+ * @return Number of entries written. If capacity == 0, return the total number of entries.
+ */
+int inbox_list(const char **names, int capacity)
+{
+	if (capacity == 0) {
+		return list_count(&inb_list);
+	}
+
+	int used = 0;
+
+	list_foreach(inb_list, link, inbox_entry, e) {
+		if (used == capacity) {
+			return used;
+		}
+		names[used] = e->name;
+		used++;
+	}
+
+	return used;
+}
+
+void __inbox_init(struct pcb_inbox_entry *entries, int count) {
+	for (int i = 0; i < count; i++) {
+		int original = inbox_set(entries[i].name, entries[i].file);
+		if (original >= 0) {
+			close(original);
+		}
+	}
+}
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -1162,5 +1162,5 @@
 }
 
-int vfs_receive_handle()
+int vfs_receive_handle(bool high_descriptor)
 {
 	ipc_callid_t callid;
@@ -1175,5 +1175,5 @@
 
 	sysarg_t ret;
-	sysarg_t rc = async_req_0_1(vfs_exch, VFS_IN_WAIT_HANDLE, &ret);
+	sysarg_t rc = async_req_1_1(vfs_exch, VFS_IN_WAIT_HANDLE, high_descriptor, &ret);
 
 	async_exchange_end(vfs_exch);
Index: uspace/lib/c/include/elf/elf_load.h
===================================================================
--- uspace/lib/c/include/elf/elf_load.h	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/include/elf/elf_load.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -45,5 +45,5 @@
 } elf_info_t;
 
-extern int elf_load(const char *, elf_info_t *);
+extern int elf_load(int, elf_info_t *);
 extern void elf_set_pcb(elf_info_t *, pcb_t *);
 
Index: uspace/lib/c/include/elf/elf_mod.h
===================================================================
--- uspace/lib/c/include/elf/elf_mod.h	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/include/elf/elf_mod.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -108,5 +108,6 @@
 
 extern const char *elf_error(unsigned int);
-extern int elf_load_file(const char *, size_t, eld_flags_t, elf_finfo_t *);
+extern int elf_load_file(int, size_t, eld_flags_t, elf_finfo_t *);
+extern int elf_load_file_name(const char *, size_t, eld_flags_t, elf_finfo_t *);
 
 #endif
Index: uspace/lib/c/include/ipc/loader.h
===================================================================
--- uspace/lib/c/include/ipc/loader.h	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/include/ipc/loader.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -42,7 +42,7 @@
 	LOADER_GET_TASKID,
 	LOADER_SET_CWD,
-	LOADER_SET_PATHNAME,
+	LOADER_SET_PROGRAM,
 	LOADER_SET_ARGS,
-	LOADER_SET_FILES,
+	LOADER_ADD_INBOX,
 	LOADER_LOAD,
 	LOADER_RUN
Index: uspace/lib/c/include/loader/loader.h
===================================================================
--- uspace/lib/c/include/loader/loader.h	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/include/loader/loader.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -47,7 +47,8 @@
 extern int loader_get_task_id(loader_t *, task_id_t *);
 extern int loader_set_cwd(loader_t *);
-extern int loader_set_pathname(loader_t *, const char *);
+extern int loader_set_program(loader_t *, const char *, int);
+extern int loader_set_program_path(loader_t *, const char *);
 extern int loader_set_args(loader_t *, const char *const[]);
-extern int loader_set_files(loader_t *, int *const[]);
+extern int loader_add_inbox(loader_t *, const char *, int);
 extern int loader_load_program(loader_t *);
 extern int loader_run(loader_t *);
Index: uspace/lib/c/include/loader/pcb.h
===================================================================
--- uspace/lib/c/include/loader/pcb.h	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/include/loader/pcb.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -41,4 +41,9 @@
 typedef void (*entry_point_t)(void);
 
+struct pcb_inbox_entry {
+	char *name;
+	int file;
+};
+
 /** Program Control Block.
  *
@@ -60,6 +65,7 @@
 	char **argv;
 	
-	/** Number of preset files. */
-	unsigned int filc;
+	/** List of inbox files. */
+	struct pcb_inbox_entry *inbox;
+	int inbox_entries;
 	
 	/*
Index: uspace/lib/c/include/task.h
===================================================================
--- uspace/lib/c/include/task.h	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/include/task.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -57,5 +57,5 @@
     const char *const []);
 extern int task_spawnvf(task_id_t *, task_wait_t *, const char *path,
-    const char *const [], int *const []);
+    const char *const [], int, int, int);
 extern int task_spawn(task_id_t *, task_wait_t *, const char *path, int,
     va_list ap);
Index: uspace/lib/c/include/vfs/inbox.h
===================================================================
--- uspace/lib/c/include/vfs/inbox.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
+++ uspace/lib/c/include/vfs/inbox.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -0,0 +1,14 @@
+
+#ifndef LIBC_VFS_INBOX_H_
+#define LIBC_VFS_INBOX_H_
+
+enum {
+	INBOX_MAX_ENTRIES = 256,
+};
+
+extern int inbox_set(const char *name, int file);
+extern int inbox_get(const char *name);
+
+extern int inbox_list(const char **names, int capacity);
+
+#endif
Index: uspace/lib/c/include/vfs/vfs.h
===================================================================
--- uspace/lib/c/include/vfs/vfs.h	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/c/include/vfs/vfs.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -63,13 +63,12 @@
 extern void vfs_exchange_end(async_exch_t *);
 
-extern int _vfs_walk(int parent, const char *path, int flags);
-extern int _vfs_open(int file, int mode);
-extern int vfs_lookup(const char *path);
+extern int _vfs_walk(int, const char *, int);
+extern int _vfs_open(int, int);
+extern int vfs_lookup(const char *);
 
-extern int vfs_pass_handle(async_exch_t *vfs_exch, int file, async_exch_t *exch);
-extern int vfs_receive_handle(void);
+extern int vfs_pass_handle(async_exch_t *, int, async_exch_t *);
+extern int vfs_receive_handle(bool);
 
-extern int vfs_clone(int file, bool high_descriptor);
-
+extern int vfs_clone(int, bool);
 
 #endif
Index: uspace/lib/pcut/src/os/helenos.c
===================================================================
--- uspace/lib/pcut/src/os/helenos.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/lib/pcut/src/os/helenos.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -170,11 +170,4 @@
 	snprintf(test_number_argument, MAX_TEST_NUMBER_WIDTH, "-t%d", test->id);
 
-	int *files[4];
-	int fd_stdin = fileno(stdin);
-	files[0] = &fd_stdin;
-	files[1] = &tempfile;
-	files[2] = &tempfile;
-	files[3] = NULL;
-
 	const char *const arguments[3] = {
 		self_path,
@@ -186,5 +179,6 @@
 
 	task_wait_t test_task_wait;
-	int rc = task_spawnvf(&test_task_id, &test_task_wait, self_path, arguments, files);
+	int rc = task_spawnvf(&test_task_id, &test_task_wait, self_path, arguments,
+	    fileno(stdin), tempfile, tempfile);
 	if (rc != EOK) {
 		status = TEST_OUTCOME_ERROR;
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/srv/loader/main.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -62,9 +62,11 @@
 #include <elf/elf_load.h>
 #include <vfs/vfs.h>
+#include <vfs/inbox.h>
 
 #define DPRINTF(...)
 
-/** Pathname of the file that will be loaded */
-static char *pathname = NULL;
+/** File that will be loaded */
+static char *progname = NULL;
+static int program_fd = -1;
 
 /** The Program control block */
@@ -81,6 +83,7 @@
 static char *arg_buf = NULL;
 
-/** Number of preset files */
-static unsigned int filc = 0;
+/** Inbox entries. */
+static struct pcb_inbox_entry inbox[INBOX_MAX_ENTRIES];
+static int inbox_entries = 0;
 
 static elf_info_t prog_info;
@@ -130,22 +133,34 @@
 }
 
-/** Receive a call setting pathname of the program to execute.
- *
- * @param rid
- * @param request
- */
-static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request)
-{
-	char *buf;
-	int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, NULL);
-	
-	if (rc == EOK) {
-		if (pathname != NULL)
-			free(pathname);
-		
-		pathname = buf;
-	}
-	
-	async_answer_0(rid, rc);
+/** Receive a call setting the program to execute.
+ *
+ * @param rid
+ * @param request
+ */
+static void ldr_set_program(ipc_callid_t rid, ipc_call_t *request)
+{
+	ipc_callid_t writeid;
+	size_t namesize;
+	if (!async_data_write_receive(&writeid, &namesize)) {
+		async_answer_0(rid, EINVAL);
+		return;
+	}
+
+	char* name = malloc(namesize);
+	int rc = async_data_write_finalize(writeid, name, namesize);
+	if (rc != EOK) {
+		async_answer_0(rid, EINVAL);
+		return;
+	}
+
+	int file = vfs_receive_handle(true);
+	if (file < 0) {
+		async_answer_0(rid, EINVAL);
+		return;
+	}
+	
+	progname = name;
+	program_fd = file;
+	async_answer_0(rid, EOK);
 }
 
@@ -215,21 +230,38 @@
 }
 
-/** Receive a call setting preset files of the program to execute.
- *
- * @param rid
- * @param request
- */
-static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
-{
-	size_t count = IPC_GET_ARG1(*request);
-
-	for (filc = 0; filc < count; filc++) {
-		int fd = vfs_receive_handle();
-		if (fd < 0) {
-			break;
-		}
-		assert(fd == (int) filc);
-	}
-
+/** Receive a call setting inbox files of the program to execute.
+ *
+ * @param rid
+ * @param request
+ */
+static void ldr_add_inbox(ipc_callid_t rid, ipc_call_t *request)
+{
+	if (inbox_entries == INBOX_MAX_ENTRIES) {
+		async_answer_0(rid, ERANGE);
+	}
+
+	ipc_callid_t writeid;
+	size_t namesize;
+	if (!async_data_write_receive(&writeid, &namesize)) {
+		async_answer_0(rid, EINVAL);
+		return;
+	}
+
+	char* name = malloc(namesize);
+	int rc = async_data_write_finalize(writeid, name, namesize);
+	if (rc != EOK) {
+		async_answer_0(rid, EINVAL);
+		return;
+	}
+
+	int file = vfs_receive_handle(true);
+	if (file < 0) {
+		async_answer_0(rid, EINVAL);
+		return;
+	}
+
+	inbox[inbox_entries].name = name;
+	inbox[inbox_entries].file = file;
+	inbox_entries++;
 	async_answer_0(rid, EOK);
 }
@@ -243,9 +275,7 @@
 static int ldr_load(ipc_callid_t rid, ipc_call_t *request)
 {
-	int rc;
-	
-	rc = elf_load(pathname, &prog_info);
+	int rc = elf_load(program_fd, &prog_info);
 	if (rc != EE_OK) {
-		DPRINTF("Failed to load executable '%s'.\n", pathname);
+		DPRINTF("Failed to load executable for '%s'.\n", progname);
 		async_answer_0(rid, EINVAL);
 		return 1;
@@ -259,5 +289,6 @@
 	pcb.argv = argv;
 	
-	pcb.filc = filc;
+	pcb.inbox = inbox;
+	pcb.inbox_entries = inbox_entries;
 	
 	async_answer_0(rid, rc);
@@ -273,12 +304,8 @@
 static void ldr_run(ipc_callid_t rid, ipc_call_t *request)
 {
-	const char *cp;
-	
 	DPRINTF("Set task name\n");
 
 	/* Set the task name. */
-	cp = str_rchr(pathname, '/');
-	cp = (cp == NULL) ? pathname : (cp + 1);
-	task_set_name(cp);
+	task_set_name(progname);
 	
 	/* Run program */
@@ -327,12 +354,12 @@
 			ldr_set_cwd(callid, &call);
 			continue;
-		case LOADER_SET_PATHNAME:
-			ldr_set_pathname(callid, &call);
+		case LOADER_SET_PROGRAM:
+			ldr_set_program(callid, &call);
 			continue;
 		case LOADER_SET_ARGS:
 			ldr_set_args(callid, &call);
 			continue;
-		case LOADER_SET_FILES:
-			ldr_set_files(callid, &call);
+		case LOADER_ADD_INBOX:
+			ldr_add_inbox(callid, &call);
 			continue;
 		case LOADER_LOAD:
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/srv/vfs/vfs.h	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -197,5 +197,5 @@
 
 extern void vfs_op_pass_handle(task_id_t, task_id_t, int);
-extern int vfs_wait_handle_internal(void);
+extern int vfs_wait_handle_internal(bool);
 
 extern vfs_file_t *vfs_file_get(int);
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/srv/vfs/vfs_file.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -59,5 +59,6 @@
 typedef struct {
 	link_t link;
-	int handle;
+	vfs_node_t *node;
+	int permissions;
 } vfs_boxed_handle_t;
 
@@ -365,7 +366,5 @@
 	vfs_client_data_t *acceptor_data = NULL;
 	vfs_file_t *donor_file = NULL;
-	vfs_file_t *acceptor_file = NULL;
 	vfs_boxed_handle_t *bh;
-	int acceptor_fd;
 
 	acceptor_data = async_get_client_data_by_id(acceptor_id);
@@ -377,5 +376,5 @@
 
 	link_initialize(&bh->link);
-	bh->handle = -1;
+	bh->node = NULL;
 
 	donor_data = async_get_client_data_by_id(donor_id);
@@ -386,10 +385,4 @@
 	if (!donor_file)
 		goto out;
-
-	acceptor_fd = _vfs_fd_alloc(acceptor_data, &acceptor_file, false);
-	if (acceptor_fd < 0)
-		goto out;
-
-	bh->handle = acceptor_fd;
 
 	/*
@@ -397,22 +390,6 @@
 	 */
 	vfs_node_addref(donor_file->node);
-
-	assert(acceptor_file);
-
-	/*
-	 * Inherit attributes from the donor.
-	 */
-	acceptor_file->node = donor_file->node;
-	acceptor_file->permissions = donor_file->permissions;
-	
-	// TODO: The file should not inherit its open status, but clients depend on this.
-	acceptor_file->pos = donor_file->pos;
-	acceptor_file->append = donor_file->append;
-	acceptor_file->open_read = donor_file->open_read;
-	acceptor_file->open_write = donor_file->open_write;
-
-	if (acceptor_file->open_read || acceptor_file->open_write) {
-		(void) vfs_open_node_remote(acceptor_file->node);
-	}
+	bh->node = donor_file->node;
+	bh->permissions = donor_file->permissions;
 
 out:
@@ -428,13 +405,9 @@
 	if (donor_file)
 		_vfs_file_put(donor_data, donor_file);
-	if (acceptor_file)
-		_vfs_file_put(acceptor_data, acceptor_file);
-
-}
-
-int vfs_wait_handle_internal(void)
+}
+
+int vfs_wait_handle_internal(bool high_fd)
 {
 	vfs_client_data_t *vfs_data = VFS_DATA;	
-	int fd;
 	
 	fibril_mutex_lock(&vfs_data->lock);
@@ -446,7 +419,17 @@
 
 	vfs_boxed_handle_t *bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
-	fd = bh->handle;
+
+	vfs_file_t *file;
+	int fd = _vfs_fd_alloc(vfs_data, &file, high_fd);
+	if (fd < 0) {
+		vfs_node_delref(bh->node);
+		free(bh);
+		return fd;
+	}
+	
+	file->node = bh->node;
+	file->permissions = bh->permissions;
+	vfs_file_put(file);
 	free(bh);
-
 	return fd;
 }
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision e796dc8e72167ff996dc83b98755ebf926622aed)
+++ uspace/srv/vfs/vfs_ops.c	(revision bb9ec2db4560230aeb342903a2cb929d99678366)
@@ -1248,5 +1248,6 @@
 void vfs_wait_handle(ipc_callid_t rid, ipc_call_t *request)
 {
-	int fd = vfs_wait_handle_internal();
+	bool high_fd = IPC_GET_ARG1(*request);
+	int fd = vfs_wait_handle_internal(high_fd);
 	async_answer_1(rid, EOK, fd);
 }
