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:

<config>
	<arg value="...">
	<arg value="...">
        ...
</config>

The 'value' attribute of the first <arg> node becomes 'argv[0]' and so on.

Fixes #184.
This commit is contained in:
Christian Prochaska 2012-04-18 17:45:03 +02:00 committed by Norman Feske
parent afe996df74
commit de92956220
6 changed files with 168 additions and 0 deletions

View File

@ -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 **

3
os/lib/mk/config_args.mk Normal file
View File

@ -0,0 +1,3 @@
SRC_CC = config_args.cc
vpath %.cc $(REP_DIR)/src/lib/config_args

42
os/run/config_args.run Normal file
View File

@ -0,0 +1,42 @@
build "core init drivers/timer test/config_args"
create_boot_directory
install_config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="CPU"/>
<service name="RM"/>
<service name="CAP"/>
<service name="PD"/>
<service name="IRQ"/>
<service name="IO_PORT"/>
<service name="SIGNAL"/>
<service name="LOG"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="test-config_args">
<resource name="RAM" quantum="10M"/>
<config>
<arg value="test-config_args"/>
<arg value="-testarg"/>
</config>
</start>
</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"

View File

@ -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 <os/config.h>
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("<arg> node has no 'value' attribute, ignoring further <arg> 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;
}

View File

@ -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 <base/printf.h>
#include <util/string.h>
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;
}

View File

@ -0,0 +1,3 @@
TARGET = test-config_args
LIBS = env config_args
SRC_CC = main.cc