[xlab@mike-c7 osv]$ sudo ./scripts/run.py -nvd -e '/tests/tst-commands.so'
...
PASS: runscript multiple lines, multiple commands per line, with args
and quotes
PASS: runscript with --env
SUMMARY: 14 tests, 0 failures
/etc/qemu-ifdown: could not launch network script
[xlab@mike-c7 osv]$
So debug build on centos7 was OK. And also release build was OK.
You tested release, on fedora 25? I will retry that.
Justin
On 01/09/2017 10:28 AM, Nadav Har'El wrote:
Hi Jusin, thanks. I think this version is indeed cleaner.
However, I tried:
scripts/build image=tests
scripts/run.py -e tests/tst-commands.so
and I get a failure:
...
PASS: runscript multiple lines
PASS: runscript multiple lines, multiple commands per line, with args
and quotes
FAIL: runscript with --env
SUMMARY: 14 tests, 1 failures
Could you please look into it?
Thanks,
Nadav.
--
Nadav Har'El
[email protected] <mailto:[email protected]>
On Mon, Jan 9, 2017 at 10:11 AM, Justin Cinkelj
<[email protected] <mailto:[email protected]>> wrote:
If multiple scripts try to set the same environment variable, then the
last one wins.
Fixes #819
Signed-off-by: Justin Cinkelj <[email protected]
<mailto:[email protected]>>
# Conflicts:
# loader.cc
---
core/commands.cc | 64
+++++++++++++++++++++++++++++++++++++++++++++++++++
tests/tst-commands.cc | 52 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+)
diff --git a/core/commands.cc b/core/commands.cc
index b2b3a60..1ba6bf8 100644
--- a/core/commands.cc
+++ b/core/commands.cc
@@ -12,6 +12,8 @@
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
+#include <boost/program_options.hpp>
+#include <osv/power.hh>
#include <osv/commands.hh>
#include <osv/align.hh>
#include <sys/types.h>
@@ -90,6 +92,66 @@ parse_command_line_min(const std::string line,
bool &ok)
}
/*
+In each runscript line, first N args starting with - are options.
+Parse options and remove them from result.
+
+Options are applied immediately, just as in loader.cc
parse_options().
+So if two scripts set the same environment variable, then the
last one wins.
+Applying all options before running any command is also safer
than trying to
+apply options for each script at script execution (second script
would modify
+environment setup by the first script, causing a race).
+*/
+static void
runscript_process_options(std::vector<std::vector<std::string> >&
result) {
+ namespace bpo = boost::program_options;
+ namespace bpos = boost::program_options::command_line_style;
+ // don't allow --foo bar (require --foo=bar) so we can find
the first non-option
+ // argument
+ int style = bpos::unix_style & ~(bpos::long_allow_next |
bpos::short_allow_next);
+ bpo::options_description desc("OSv runscript options");
+ desc.add_options()
+ ("env", bpo::value<std::vector<std::string>>(), "set
Unix-like environment variable (putenv())");
+
+ for (size_t ii=0; ii<result.size(); ii++) {
+ auto cmd = result[ii];
+ bpo::variables_map vars;
+
+ std::vector<const char*> args = { "dummy-string" };
+ // due to https://svn.boost.org/trac/boost/ticket/6991
<https://svn.boost.org/trac/boost/ticket/6991>, we can't terminate
+ // command line parsing on the executable name, so we
need to look for it
+ // ourselves
+ auto ac = cmd.size();
+ auto av = std::vector<const char*>();
+ av.reserve(ac+1);
+ size_t jj = 0;
+ for (auto prm : cmd) {
+ av[jj++] = prm.c_str();
+ }
+ auto nr_options = std::find_if(av.data(), av.data() + ac,
+ [](const char* arg) {
return arg[0] != '-'; }) - av.data();
+ std::copy(av.data(), av.data() + nr_options,
std::back_inserter(args));
+
+ try {
+ bpo::store(bpo::parse_command_line(args.size(),
args.data(), desc, style), vars);
+ } catch(std::exception &e) {
+ std::cout << e.what() << '\n';
+ std::cout << desc << '\n';
+ osv::poweroff();
+ }
+ bpo::notify(vars);
+
+ if (vars.count("env")) {
+ for (auto t :
vars["env"].as<std::vector<std::string>>()) {
+ debug("Setting in environment: %s\n", t);
+ putenv(strdup(t.c_str()));
+ }
+ }
+
+ cmd.erase(cmd.begin(), cmd.begin() + nr_options);
+ result[ii] = cmd;
+ }
+}
+
+/*
If cmd starts with "runcript file", read content of file and
return vector of all programs to be run.
File can contain multiple commands per line.
@@ -125,6 +187,8 @@ std::vector<std::vector<std::string>>
runscript_expand(const std::vector<std::st
ok = false;
return result2;
}
+ // process and remove options from command
+ runscript_process_options(result3);
result2.insert(result2.end(), result3.begin(),
result3.end());
line_num++;
}
diff --git a/tests/tst-commands.cc b/tests/tst-commands.cc
index de0c143..7d0a679 100644
--- a/tests/tst-commands.cc
+++ b/tests/tst-commands.cc
@@ -625,6 +625,56 @@ static bool
test_runscript_multiline_multiple_commands_per_line_with_args_quotes
return true;
}
+static bool test_runscript_with_env()
+{
+ std::ofstream of1("/myscript", std::ios::out | std::ios::binary);
+ of1 << "--env=ASDF=ttrt /prog1 pp1a pp1b\n";
+ of1.close();
+
+ std::vector<std::vector<std::string> > result;
+ std::vector<std::string> cmd = { "/prog1" };
+ size_t expected_size[] = {4};
+ bool ok;
+
+ if (NULL != getenv("ASDF")) {
+ return false;
+ }
+
+ result = osv::parse_command_line(
+ std::string("runscript \"/myscript\"; "),
+ ok);
+
+ if (!ok) {
+ return false;
+ }
+
+ if (result.size() != 1) {
+ return false;
+ }
+
+ for (size_t i = 0; i < result.size(); i++) {
+ if (result[i].size() != expected_size[i]) {
+ return false;
+ }
+ if (result[i][0] != cmd[i]) {
+ return false;
+ }
+ }
+
+ if (result[0][1] != std::string("pp1a")) {
+ return false;
+ }
+ if (result[0][2] != std::string("pp1b")) {
+ return false;
+ }
+
+ if (std::string("ttrt") != getenv("ASDF")) {
+ return false;
+ }
+
+ return true;
+}
+
int main(int argc, char *argv[])
{
report(test_parse_simplest(), "simplest command line");
@@ -651,6 +701,8 @@ int main(int argc, char *argv[])
"runscript multiple lines");
report(test_runscript_multiline_multiple_commands_per_line_with_args_quotes(),
"runscript multiple lines, multiple commands per line,
with args and quotes");
+ report(test_runscript_with_env(),
+ "runscript with --env");
printf("SUMMARY: %d tests, %d failures\n", tests, fails);
return 0;
}
--
2.9.3
--
You received this message because you are subscribed to the Google
Groups "OSv Development" group.
To unsubscribe from this group and stop receiving emails from it,
send an email to [email protected]
<mailto:osv-dev%[email protected]>.
For more options, visit https://groups.google.com/d/optout
<https://groups.google.com/d/optout>.
--
You received this message because you are subscribed to the Google Groups "OSv
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.