From de929562209cbaf33931b33cd46a3b3c4c0cfa58 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Wed, 18 Apr 2012 17:45:03 +0200 Subject: [PATCH] Read 'main()' function arguments from config file This patch reads program arguments from the config file and makes them available to the application via the 'argc' and 'argv' arguments of the 'main()' function. The configuration syntax looks like this: ... The 'value' attribute of the first node becomes 'argv[0]' and so on. Fixes #184. --- base-linux/src/platform/lx_hybrid.cc | 10 ++++ os/lib/mk/config_args.mk | 3 ++ os/run/config_args.run | 42 +++++++++++++++++ os/src/lib/config_args/config_args.cc | 68 +++++++++++++++++++++++++++ os/src/test/config_args/main.cc | 42 +++++++++++++++++ os/src/test/config_args/target.mk | 3 ++ 6 files changed, 168 insertions(+) create mode 100644 os/lib/mk/config_args.mk create mode 100644 os/run/config_args.run create mode 100644 os/src/lib/config_args/config_args.cc create mode 100644 os/src/test/config_args/main.cc create mode 100644 os/src/test/config_args/target.mk diff --git a/base-linux/src/platform/lx_hybrid.cc b/base-linux/src/platform/lx_hybrid.cc index eb0925f46a..caf3d6c268 100644 --- a/base-linux/src/platform/lx_hybrid.cc +++ b/base-linux/src/platform/lx_hybrid.cc @@ -48,6 +48,16 @@ __attribute__((constructor(101))) void lx_hybrid_init() lx_environ = environ; } +/* + * Dummy symbols to let generic tests programs (i.e., 'test-config_args') link + * successfully. Please note that such programs are not expected to work when + * built as hybrid Linux/Genode programs because when using the glibc startup + * code, we cannot manipulate argv prior executing main. However, by defining + * these symbols, we prevent the automated build bot from stumbling over such + * binaries. + */ +char **genode_argv = 0; +int genode_argc = 1; /************ ** Thread ** diff --git a/os/lib/mk/config_args.mk b/os/lib/mk/config_args.mk new file mode 100644 index 0000000000..dbf9be6a1e --- /dev/null +++ b/os/lib/mk/config_args.mk @@ -0,0 +1,3 @@ +SRC_CC = config_args.cc + +vpath %.cc $(REP_DIR)/src/lib/config_args diff --git a/os/run/config_args.run b/os/run/config_args.run new file mode 100644 index 0000000000..f6f5eee8ea --- /dev/null +++ b/os/run/config_args.run @@ -0,0 +1,42 @@ +build "core init drivers/timer test/config_args" + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +build_boot_image "core init timer test-config_args" + +append qemu_args "-nographic -m 64" + +run_genode_until {--- end of config args test ---} 10 + +puts "Test succeeded" diff --git a/os/src/lib/config_args/config_args.cc b/os/src/lib/config_args/config_args.cc new file mode 100644 index 0000000000..73ab5b7ab4 --- /dev/null +++ b/os/src/lib/config_args/config_args.cc @@ -0,0 +1,68 @@ +/* + * \brief Read program arguments from the config file + * \date 2012-04-19 + * \author Christian Prochaska + */ + +/* + * 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. + */ + +#include + +using namespace Genode; + + +/* external symbols provided by Genode's startup code */ +extern char **genode_argv; +extern int genode_argc; + + +__attribute__((constructor)) +void init_config_args(void) +{ + int argc = 0; + static char **argv; + + /* count the number of arguments */ + try { + Xml_node arg_node = config()->xml_node().sub_node("arg"); + for (;;) { + /* check if the 'value' attribute exists */ + arg_node.attribute("value"); + argc++; + arg_node = arg_node.next("arg"); + } + } + catch (Config::Invalid) { return; } + catch (Xml_node::Nonexistent_sub_node) { } + catch (Xml_node::Nonexistent_attribute) + { + PERR(" node has no 'value' attribute, ignoring further nodes"); + } + + if (argc == 0) + return; + + argv = (char**)env()->heap()->alloc(argc * sizeof(char*)); + + /* read the arguments */ + Xml_node arg_node = config()->xml_node().sub_node("arg"); + try { + for (int i = 0; i < argc; i++) { + static char buf[512]; + arg_node.attribute("value").value(buf, sizeof(buf)); + size_t arg_size = strlen(buf) + 1; + argv[i] = (char*)env()->heap()->alloc(arg_size); + strncpy(argv[i], buf, arg_size); + arg_node = arg_node.next("arg"); + } + } catch (Xml_node::Nonexistent_sub_node) { } + + /* register command-line arguments at Genode's startup code */ + genode_argc = argc; + genode_argv = argv; +} diff --git a/os/src/test/config_args/main.cc b/os/src/test/config_args/main.cc new file mode 100644 index 0000000000..e1383363af --- /dev/null +++ b/os/src/test/config_args/main.cc @@ -0,0 +1,42 @@ +/* + * \brief 'main()' arguments test + * \author Christian Prochaska + * \date 2012-04-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. + */ + +#include +#include + +using namespace Genode; + +int main(int argc, char **argv) +{ + printf("--- config args test started ---\n"); + + if (argc != 2) { + PERR("Error: argc is not as expected"); + return -1; + } + + if (strcmp(argv[0], "test-config_args") != 0) { + PERR("Error: argv[0] is not as expected"); + return -1; + } + + if (strcmp(argv[1], "-testarg") != 0) { + PERR("Error: argv[1] is not as expected"); + return -1; + } + + printf("--- end of config args test ---\n"); + + return 0; +} diff --git a/os/src/test/config_args/target.mk b/os/src/test/config_args/target.mk new file mode 100644 index 0000000000..08c6b4ccbd --- /dev/null +++ b/os/src/test/config_args/target.mk @@ -0,0 +1,3 @@ +TARGET = test-config_args +LIBS = env config_args +SRC_CC = main.cc