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,