mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
qt5_component: support arguments and environment from config
Fixes #3049
This commit is contained in:
parent
f03917ab7c
commit
66063e5137
130
repos/libports/include/libc/args.h
Normal file
130
repos/libports/include/libc/args.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* \brief Populate arguments and environment from config
|
||||
* \author Christian Prochaska
|
||||
* \date 2020-08-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__LIBC__ARGS_H_
|
||||
#define _INCLUDE__LIBC__ARGS_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <libc/component.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <stdlib.h> /* 'malloc' */
|
||||
|
||||
static void populate_args_and_env(Libc::Env &env, int &argc, char **&argv, char **&envp)
|
||||
{
|
||||
using Genode::Xml_node;
|
||||
using Genode::Xml_attribute;
|
||||
|
||||
env.config([&] (Xml_node const &node) {
|
||||
|
||||
int envc = 0;
|
||||
|
||||
/* count the number of arguments and environment variables */
|
||||
node.for_each_sub_node([&] (Xml_node const &node) {
|
||||
/* check if the 'value' attribute exists */
|
||||
if (node.has_type("arg") && node.has_attribute("value"))
|
||||
++argc;
|
||||
else
|
||||
if (node.has_type("env") && node.has_attribute("key") && node.has_attribute("value"))
|
||||
++envc;
|
||||
});
|
||||
|
||||
if (argc == 0 && envc == 0)
|
||||
return; /* from lambda */
|
||||
|
||||
/* arguments and environment are a contiguous array (but don't count on it) */
|
||||
argv = (char**)malloc((argc + envc + 1) * sizeof(char*));
|
||||
envp = &argv[argc];
|
||||
|
||||
/* read the arguments */
|
||||
int arg_i = 0;
|
||||
int env_i = 0;
|
||||
node.for_each_sub_node([&] (Xml_node const &node) {
|
||||
|
||||
/* insert an argument */
|
||||
if (node.has_type("arg")) {
|
||||
|
||||
Xml_attribute attr = node.attribute("value");
|
||||
attr.with_raw_value([&] (char const *start, size_t length) {
|
||||
|
||||
size_t const size = length + 1; /* for null termination */
|
||||
|
||||
argv[arg_i] = (char *)malloc(size);
|
||||
|
||||
Genode::copy_cstring(argv[arg_i], start, size);
|
||||
});
|
||||
|
||||
++arg_i;
|
||||
}
|
||||
else
|
||||
|
||||
/* insert an environment variable */
|
||||
if (node.has_type("env")) try {
|
||||
|
||||
auto check_attr = [] (Xml_node node, auto key) {
|
||||
if (!node.has_attribute(key))
|
||||
Genode::warning("<env> node lacks '", key, "' attribute"); };
|
||||
|
||||
check_attr(node, "key");
|
||||
check_attr(node, "value");
|
||||
|
||||
Xml_attribute const key = node.attribute("key");
|
||||
Xml_attribute const value = node.attribute("value");
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/*
|
||||
* An environment variable has the form <key>=<value>, followed
|
||||
* by a terminating zero.
|
||||
*/
|
||||
size_t const var_size = key .value_size() + 1
|
||||
+ value.value_size() + 1;
|
||||
|
||||
envp[env_i] = (char*)malloc(var_size);
|
||||
|
||||
size_t pos = 0;
|
||||
|
||||
/* append characters to env variable with zero termination */
|
||||
auto append = [&] (char const *s, size_t len) {
|
||||
|
||||
if (pos + len >= var_size) {
|
||||
/* this should never happen */
|
||||
warning("truncated environment variable: ", node);
|
||||
return;
|
||||
}
|
||||
|
||||
copy_cstring(envp[env_i] + pos, s, len + 1);
|
||||
pos += len;
|
||||
};
|
||||
|
||||
key.with_raw_value([&] (char const *start, size_t length) {
|
||||
append(start, length); });
|
||||
|
||||
append("=", 1);
|
||||
|
||||
value.with_raw_value([&] (char const *start, size_t length) {
|
||||
append(start, length); });
|
||||
|
||||
++env_i;
|
||||
|
||||
}
|
||||
catch (Xml_node::Nonexistent_sub_node) { }
|
||||
catch (Xml_node::Nonexistent_attribute) { }
|
||||
});
|
||||
|
||||
envp[env_i] = NULL;
|
||||
});
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__LIBC__ARGS_H_ */
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2016-2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -15,133 +15,26 @@
|
||||
#include <libc/component.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <stdlib.h> /* 'malloc' */
|
||||
#include <libc/args.h>
|
||||
#include <stdlib.h> /* 'exit' */
|
||||
|
||||
extern char **genode_argv;
|
||||
extern int genode_argc;
|
||||
extern char **genode_envp;
|
||||
|
||||
/* initial environment for the FreeBSD libc implementation */
|
||||
extern char **environ;
|
||||
|
||||
/* provided by the application */
|
||||
extern "C" int main(int argc, char ** argv, char **envp);
|
||||
|
||||
extern "C" int main(int argc, char **argv, char **envp);
|
||||
|
||||
static void construct_component(Libc::Env &env)
|
||||
{
|
||||
using Genode::Xml_node;
|
||||
using Genode::Xml_attribute;
|
||||
int argc = 0;
|
||||
char **argv = nullptr;
|
||||
char **envp = nullptr;
|
||||
|
||||
env.config([&] (Xml_node const &node) {
|
||||
int argc = 0;
|
||||
int envc = 0;
|
||||
char **argv;
|
||||
char **envp;
|
||||
populate_args_and_env(env, argc, argv, envp);
|
||||
|
||||
/* count the number of arguments and environment variables */
|
||||
node.for_each_sub_node([&] (Xml_node const &node) {
|
||||
/* check if the 'value' attribute exists */
|
||||
if (node.has_type("arg") && node.has_attribute("value"))
|
||||
++argc;
|
||||
else
|
||||
if (node.has_type("env") && node.has_attribute("key") && node.has_attribute("value"))
|
||||
++envc;
|
||||
});
|
||||
environ = envp;
|
||||
|
||||
if (argc == 0 && envc == 0)
|
||||
return; /* from lambda */
|
||||
|
||||
/* arguments and environment are a contiguous array (but don't count on it) */
|
||||
argv = (char**)malloc((argc + envc + 1) * sizeof(char*));
|
||||
envp = &argv[argc];
|
||||
|
||||
/* read the arguments */
|
||||
int arg_i = 0;
|
||||
int env_i = 0;
|
||||
node.for_each_sub_node([&] (Xml_node const &node) {
|
||||
|
||||
/* insert an argument */
|
||||
if (node.has_type("arg")) {
|
||||
|
||||
Xml_attribute attr = node.attribute("value");
|
||||
attr.with_raw_value([&] (char const *start, size_t length) {
|
||||
|
||||
size_t const size = length + 1; /* for null termination */
|
||||
|
||||
argv[arg_i] = (char *)malloc(size);
|
||||
|
||||
Genode::copy_cstring(argv[arg_i], start, size);
|
||||
});
|
||||
|
||||
++arg_i;
|
||||
}
|
||||
else
|
||||
|
||||
/* insert an environment variable */
|
||||
if (node.has_type("env")) try {
|
||||
|
||||
auto check_attr = [] (Xml_node node, auto key) {
|
||||
if (!node.has_attribute(key))
|
||||
Genode::warning("<env> node lacks '", key, "' attribute"); };
|
||||
|
||||
check_attr(node, "key");
|
||||
check_attr(node, "value");
|
||||
|
||||
Xml_attribute const key = node.attribute("key");
|
||||
Xml_attribute const value = node.attribute("value");
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/*
|
||||
* An environment variable has the form <key>=<value>, followed
|
||||
* by a terminating zero.
|
||||
*/
|
||||
size_t const var_size = key .value_size() + 1
|
||||
+ value.value_size() + 1;
|
||||
|
||||
envp[env_i] = (char*)malloc(var_size);
|
||||
|
||||
size_t pos = 0;
|
||||
|
||||
/* append characters to env variable with zero termination */
|
||||
auto append = [&] (char const *s, size_t len) {
|
||||
|
||||
if (pos + len >= var_size) {
|
||||
/* this should never happen */
|
||||
warning("truncated environment variable: ", node);
|
||||
return;
|
||||
}
|
||||
|
||||
copy_cstring(envp[env_i] + pos, s, len + 1);
|
||||
pos += len;
|
||||
};
|
||||
|
||||
key.with_raw_value([&] (char const *start, size_t length) {
|
||||
append(start, length); });
|
||||
|
||||
append("=", 1);
|
||||
|
||||
value.with_raw_value([&] (char const *start, size_t length) {
|
||||
append(start, length); });
|
||||
|
||||
++env_i;
|
||||
|
||||
}
|
||||
catch (Xml_node::Nonexistent_sub_node) { }
|
||||
catch (Xml_node::Nonexistent_attribute) { }
|
||||
});
|
||||
|
||||
envp[env_i] = NULL;
|
||||
|
||||
/* register command-line arguments at Genode's startup code */
|
||||
genode_argc = argc;
|
||||
genode_argv = argv;
|
||||
genode_envp = environ = envp;
|
||||
});
|
||||
|
||||
exit(main(genode_argc, genode_argv, genode_envp));
|
||||
exit(main(argc, argv, envp));
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <libc/args.h>
|
||||
#include <libc/component.h>
|
||||
|
||||
/* libc includes */
|
||||
@ -20,8 +21,11 @@
|
||||
/* qt5_component includes */
|
||||
#include <qt5_component/qpa_init.h>
|
||||
|
||||
/* initial environment for the FreeBSD libc implementation */
|
||||
extern char **environ;
|
||||
|
||||
/* provided by the application */
|
||||
extern "C" int main(int argc, char const **argv);
|
||||
extern "C" int main(int argc, char **argv, char **envp);
|
||||
|
||||
void Libc::Component::construct(Libc::Env &env)
|
||||
{
|
||||
@ -29,11 +33,24 @@ void Libc::Component::construct(Libc::Env &env)
|
||||
|
||||
qpa_init(env);
|
||||
|
||||
int argc = 1;
|
||||
char const *argv[] = { "qt5_app", 0 };
|
||||
int argc = 0;
|
||||
char **argv = nullptr;
|
||||
char **envp = nullptr;
|
||||
|
||||
int exit_value = main(argc, argv);
|
||||
populate_args_and_env(env, argc, argv, envp);
|
||||
|
||||
exit(exit_value);
|
||||
/* at least the executable name is required */
|
||||
|
||||
char default_argv0[] { "qt5_component" };
|
||||
char *default_argv[] { default_argv0, nullptr };
|
||||
|
||||
if (argc == 0) {
|
||||
argc = 1;
|
||||
argv = default_argv;
|
||||
}
|
||||
|
||||
environ = envp;
|
||||
|
||||
exit(main(argc, argv, envp));
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user