diff --git a/ports/run/noux_shell_script.run b/ports/run/noux_shell_script.run
new file mode 100644
index 0000000000..e6cf6b6873
--- /dev/null
+++ b/ports/run/noux_shell_script.run
@@ -0,0 +1,171 @@
+set build_components {
+ core init drivers/timer noux/minimal lib/libc_noux
+ drivers/framebuffer drivers/pci drivers/input
+ server/terminal server/ram_fs
+ test/libports/ncurses
+}
+
+#
+# Build Noux packages only once
+#
+set noux_pkgs {bash coreutils make}
+
+foreach pkg $noux_pkgs {
+ lappend_if [expr ![file exists bin/$pkg]] build_components noux-pkg/$pkg }
+
+build $build_components
+
+# strip all binaries prior archiving
+set find_args ""
+foreach pkg $noux_pkgs { append find_args " bin/$pkg/" }
+exec sh -c "find $find_args -type f | (xargs [cross_dev_prefix]strip || true) 2>/dev/null"
+
+# create '/bin/sh' symlink
+exec sh -c "ln -sf bash bin/bash/bin/sh"
+
+foreach pkg $noux_pkgs {
+ exec tar cfv bin/$pkg.tar -h -C bin/$pkg . }
+
+create_boot_directory
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+append_if [have_spec sdl] config {
+
+
+
+
+
+
+ }
+
+append_if [have_spec pci] config {
+
+
+
+ }
+
+append_if [have_spec vesa] config {
+
+
+
+ }
+
+append_if [have_spec pl11x] config {
+
+
+
+ }
+
+append_if [have_spec ps2] config {
+
+
+
+ }
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /home/test_script correct
+ #!/bin/make -f
+wrong:
+ @echo "wrong target"
+correct:
+ @echo "correct target"
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+foreach pkg $noux_pkgs {
+ append config " " }
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+
+#
+# Boot modules
+#
+
+# generic modules
+set boot_modules {
+ core init timer ld.lib.so noux terminal ram_fs
+ libc.lib.so libm.lib.so libc_noux.lib.so ncurses.lib.so }
+
+foreach pkg $noux_pkgs {
+ lappend boot_modules "$pkg.tar" }
+
+# platform-specific modules
+lappend_if [have_spec linux] boot_modules fb_sdl
+lappend_if [have_spec pci] boot_modules pci_drv
+lappend_if [have_spec vesa] boot_modules vesa_drv
+lappend_if [have_spec ps2] boot_modules ps2_drv
+lappend_if [have_spec pl11x] boot_modules pl11x_drv
+
+build_boot_image $boot_modules
+
+append qemu_args " -m 300 "
+
+run_genode_until forever
+
+exec rm bin/bash.tar
diff --git a/ports/src/noux/child_env.h b/ports/src/noux/child_env.h
new file mode 100644
index 0000000000..1c81fe8109
--- /dev/null
+++ b/ports/src/noux/child_env.h
@@ -0,0 +1,191 @@
+/*
+ * \brief Noux child environment
+ * \author Christian Prochaska
+ * \author Norman Feske
+ * \date 2012-07-19
+ */
+
+/*
+ * Copyright (C) 2012 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _NOUX__CHILD_ENV_H_
+#define _NOUX__CHILD_ENV_H_
+
+/* Genode includes */
+#include
+
+/* Noux includes */
+#include
+#include
+
+namespace Noux {
+
+ using namespace Genode;
+
+ /**
+ * \param ARGS_SIZE size of the argument buffer given
+ * to the constructor
+ */
+ template
+ class Child_env
+ {
+ private:
+
+ enum { MAX_LEN_INTERPRETER_LINE = 128 };
+
+ char const *_binary_name;
+ char _args[ARGS_SIZE + MAX_LEN_INTERPRETER_LINE];
+ char _env[Sysio::ENV_MAX_LEN];
+
+ /**
+ * Deserialize environment variable buffer into a
+ * null-terminated string. The source env buffer contains a
+ * list of strings separated by single 0 characters. Each
+ * string has the form "name=value" (w/o the quotes). The end
+ * of the list is marked by an additional 0 character. The
+ * resulting string is a null-terminated string containing a
+ * comma-separated list of environment variables.
+ */
+ void _process_env(Sysio::Env env)
+ {
+ /**
+ * In the following loop, 'i' is the index into the source
+ * buffer, 'j' is the index into the destination buffer, 'env'
+ * is the destination.
+ */
+ for (unsigned i = 0, j = 0; i < Sysio::ENV_MAX_LEN && env[i]; )
+ {
+ char const *src = &env[i];
+
+ /* prepend a comma in front of each entry except for the first one */
+ if (i) {
+ snprintf(env + j, sizeof(env) - j, ",");
+ j++;
+ }
+
+ snprintf(env + j, sizeof(env) - j, "%s", src);
+
+ /* skip null separator in source string */
+ i += strlen(src) + 1;
+ j += strlen(src);
+ }
+ }
+
+
+ /**
+ * Handle the case that the given binary needs an interpreter
+ */
+ void _process_binary_name_and_args(const char *binary_name,
+ Dataspace_capability binary_ds,
+ const char *args)
+ {
+ bool interpretable = true;
+
+ const size_t binary_size = Dataspace_client(binary_ds).size();
+
+ if (binary_size < 4)
+ interpretable = false;
+
+ const char *binary_addr = 0;
+ if (interpretable)
+ try {
+ binary_addr = Genode::env()->rm_session()->attach(binary_ds);
+ } catch(...) {
+ PWRN("could not attach dataspace");
+ interpretable = false;
+ }
+
+ if (interpretable &&
+ ((binary_addr[0] != '#') || (binary_addr[1] != '!')))
+ interpretable = false;
+
+ if (!interpretable) {
+ Genode::env()->rm_session()->detach(binary_addr);
+ _binary_name = binary_name;
+ Genode::memcpy(_args, args, ARGS_SIZE);
+ return;
+ }
+
+ /* find end of line */
+ Range_checked_index
+ eol(2, min(binary_size, MAX_LEN_INTERPRETER_LINE));
+
+ try {
+ while (binary_addr[eol] != '\n') eol++;
+ } catch (Index_out_of_range) { }
+
+ /* skip leading spaces */
+ Range_checked_index
+ interpreter_line_cursor(2, eol);
+
+ try {
+ while (binary_addr[interpreter_line_cursor] == ' ')
+ interpreter_line_cursor++;
+ } catch (Index_out_of_range) { }
+
+ /* no interpreter name found */
+ if (interpreter_line_cursor == eol)
+ throw Child::Binary_does_not_exist();
+
+ int interpreter_name_start = interpreter_line_cursor;
+
+ /* find end of interpreter name */
+ try {
+ while (binary_addr[interpreter_line_cursor] != ' ')
+ interpreter_line_cursor++;
+ } catch (Index_out_of_range) { }
+
+ size_t interpreter_name_len =
+ interpreter_line_cursor - interpreter_name_start;
+
+ /* copy interpreter name into argument buffer */
+ unsigned int args_buf_cursor = 0;
+ Genode::strncpy(&_args[args_buf_cursor],
+ &binary_addr[interpreter_name_start],
+ interpreter_name_len + 1);
+ _binary_name = &_args[args_buf_cursor];
+ args_buf_cursor += interpreter_name_len + 1;
+
+ /* skip more spaces */
+ try {
+ while (binary_addr[interpreter_line_cursor] == ' ')
+ interpreter_line_cursor++;
+ } catch (Index_out_of_range) { }
+
+ /* append interpreter arguments to argument buffer */
+ size_t interpreter_args_len = eol - interpreter_line_cursor;
+ Genode::strncpy(&_args[args_buf_cursor],
+ &binary_addr[interpreter_line_cursor],
+ interpreter_args_len + 1);
+ args_buf_cursor += interpreter_args_len + 1;
+
+ /* append script arguments to argument buffer */
+ Genode::memcpy(&_args[args_buf_cursor],
+ args, ARGS_SIZE);
+
+ Genode::env()->rm_session()->detach(binary_addr);
+ }
+
+ public:
+
+ Child_env(const char *binary_name, Dataspace_capability binary_ds,
+ const char *args, Sysio::Env env)
+ {
+ _process_env(env);
+ _process_binary_name_and_args(binary_name, binary_ds, args);
+ }
+
+ char const *binary_name() const { return _binary_name; }
+
+ Args args() { return Args(_args, sizeof(_args)); }
+
+ char const *env() const { return _env; }
+ };
+
+}
+
+#endif /* _NOUX__CHILD_ENV_H_ */
diff --git a/ports/src/noux/main.cc b/ports/src/noux/main.cc
index 37ac92339b..87a9c23f1e 100644
--- a/ports/src/noux/main.cc
+++ b/ports/src/noux/main.cc
@@ -45,6 +45,7 @@
/* Noux includes */
#include
+#include
#include
#include
#include
@@ -203,46 +204,23 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
{
Absolute_path absolute_path(_sysio->execve_in.filename, _env.pwd());
- /*
- * Deserialize environment variable buffer into a
- * null-terminated string. The source env buffer contains a
- * list of strings separated by single 0 characters. Each
- * string has the form "name=value" (w/o the quotes). The end
- * of the list is marked by an additional 0 character. The
- * resulting string is a null-terminated string containing a
- * comma-separated list of environment variables.
- *
- * In the following loop, 'i' is the index into the source
- * buffer, 'j' is the index into the destination buffer, 'env'
- * is the destination.
- */
- char env[Sysio::ENV_MAX_LEN];
- for (unsigned i = 0, j = 0; i < Sysio::ENV_MAX_LEN && _sysio->execve_in.env[i]; )
- {
- char const *src = &_sysio->execve_in.env[i];
+ Dataspace_capability binary_ds = _root_dir->dataspace(absolute_path.base());
- /* prepend a comma in front of each entry except for the first one */
- if (i) {
- snprintf(env + j, sizeof(env) - j, ",");
- j++;
- }
+ if (!binary_ds.valid())
+ throw Child::Binary_does_not_exist();
- snprintf(env + j, sizeof(env) - j, "%s", src);
-
- /* skip null separator in source string */
- i += strlen(src) + 1;
- j += strlen(src);
- }
+ Child_envexecve_in.args)> child_env(
+ absolute_path.base(), binary_ds, _sysio->execve_in.args,
+ _sysio->execve_in.env);
try {
- Child *child = new Child(absolute_path.base(),
+ Child *child = new Child(child_env.binary_name(),
parent(),
pid(),
_sig_rec,
_root_dir,
- Args(_sysio->execve_in.args,
- sizeof(_sysio->execve_in.args)),
- env,
+ child_env.args(),
+ child_env.env(),
_env.pwd(),
_cap_session,
_parent_services,