diff --git a/CHANGES b/CHANGES index 586ae2437e..0f951bea1a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,15 @@ +3.3.0-dev.409 | 2020-10-13 13:32:18 -0700 + + * Make it possible to pass command line options through to scripts. (Seth Hall, Corelight) + + A new ``zeek_script_args`` variable contains a list of arguments passed + to a script. E.g. either when explicitly executing Zeek like + ``zeek -- myscript.zeek -arg1 -arg2``, or when using Zeek to interpret + executable scripts that contain a hashbang line at the top like:: + + #!/usr/local/zeek/bin/zeek -- + 3.3.0-dev.403 | 2020-10-13 10:50:12 -0700 * Add new Pcap::findalldevs() BIF (Seth Hall, Corelight) diff --git a/NEWS b/NEWS index 457166c6fd..f1bc2fd1f2 100644 --- a/NEWS +++ b/NEWS @@ -37,7 +37,7 @@ New Functionality - Added a ``udp-state`` signature condition to enforce matching against either "originator" or "responder" flow direction of UDP packets. -- Improvements to catpure-loss.zeek: +- Improvements to capture-loss.zeek: - A new option, ``CaptureLoss::initial_watch_interval``. When restarting a Zeek cluster, one usually wants some immediate feedback as to the health of @@ -54,6 +54,13 @@ New Functionality capture-loss.zeek would have previously only reported that "0 gaps and 0 ACKs is 0% loss". +- A new ``zeek_script_args`` variable contains a list of arguments passed + to a script. E.g. either when explicitly executing Zeek like + ``zeek -- myscript.zeek -arg1 -arg2``, or when using Zeek to interpret + executable scripts that contain a hashbang line at the top like:: + + #!/usr/local/zeek/bin/zeek -- + Changed Functionality --------------------- diff --git a/VERSION b/VERSION index b61175c6d6..c389413630 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.3.0-dev.403 +3.3.0-dev.409 diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index fe1419fa26..635dec2cd2 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -454,6 +454,18 @@ type connection: record { inner_vlan: int &optional; }; +## Arguments given to Zeek from the command line. In order to use this, Zeek +## must use a ``--`` command line argument immediately followed by a script +## file and additional arguments after that. For example:: +## +## zeek --bare-mode -- myscript.zeek -a -b -c +## +## To use Zeek as an executable interpreter, include a line at the top of a script +## like the following and make the script executable:: +## +## #!/usr/local/zeek/bin/zeek -- +const zeek_script_args: vector of string = vector(); + ## Default amount of time a file can be inactive before the file analysis ## gives up and discards any internal state related to the file. option default_file_timeout_interval: interval = 2 mins; diff --git a/src/Options.cc b/src/Options.cc index a9e4f40db7..951c55831b 100644 --- a/src/Options.cc +++ b/src/Options.cc @@ -5,6 +5,7 @@ #include "Options.h" #include +#include #include @@ -186,8 +187,48 @@ Options parse_cmdline(int argc, char** argv) } else { - for ( auto i = 0; i < argc; ++i ) - zeek_args.emplace_back(argv[i]); + if ( argc > 1 ) + { + auto endsWith = [](const std::string& str, const std::string& suffix) + { + return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix); + }; + + auto i = 0; + for ( ; i < argc && ! endsWith(argv[i], "--"); ++i ) + { + zeek_args.emplace_back(argv[i]); + } + + if ( i < argc ) + { + // If a script is invoked with Zeek as the interpreter, the arguments provided + // directly in the interpreter line of the script won't be broken apart in the + // argv on Linux so we split it up here. + if ( endsWith(argv[i], "--") && zeek_args.size() == 1 ) + { + std::istringstream iss(argv[i]); + for ( std::string s; iss >> s; ) + { + if ( ! endsWith(s, "--") ) + { + zeek_args.emplace_back(s); + } + } + } + + // There is an additional increment here to skip over the "--" if it was found. + if ( endsWith(argv[i], "--") ) + ++i; + + // The first argument after the double hyphens in implicitly a script name. + rval.scripts_to_load.emplace_back(argv[i++]); + + // If there are more argument, grab them for script arguments + for ( ; i < argc; ++i ) + rval.script_args.emplace_back(argv[i]); + } + } } constexpr struct option long_opts[] = { diff --git a/src/Options.h b/src/Options.h index d70e37d65c..3f949e675f 100644 --- a/src/Options.h +++ b/src/Options.h @@ -74,6 +74,8 @@ struct Options { std::set plugins_to_load; std::vector scripts_to_load; std::vector script_options_to_set; + + std::vector script_args; }; /** diff --git a/src/zeek-setup.cc b/src/zeek-setup.cc index 600597988d..4d731a507c 100644 --- a/src/zeek-setup.cc +++ b/src/zeek-setup.cc @@ -660,6 +660,16 @@ SetupResult setup(int argc, char** argv, Options* zopts) init_net_var(); run_bif_initializers(); + // Assign the script_args for command line processing in Zeek scripts. + if ( ! options.script_args.empty() ) + { + auto script_args_val = id::find_val("zeek_script_args"); + for ( const string& script_arg : options.script_args ) + { + script_args_val->Assign(script_args_val->Size(), make_intrusive(script_arg)); + } + } + // Must come after plugin activation (and also after hash // initialization). binpac::FlowBuffer::Policy flowbuffer_policy; diff --git a/testing/btest/Baseline/core.script-args/out b/testing/btest/Baseline/core.script-args/out new file mode 100644 index 0000000000..e7be66720c --- /dev/null +++ b/testing/btest/Baseline/core.script-args/out @@ -0,0 +1,2 @@ +[-a, -b, -c] +[-d, -e, -f] diff --git a/testing/btest/core/script-args.zeek b/testing/btest/core/script-args.zeek new file mode 100644 index 0000000000..2e38f411cc --- /dev/null +++ b/testing/btest/core/script-args.zeek @@ -0,0 +1,14 @@ +# @TEST-EXEC: printf '#!' > test.zeek +# @TEST-EXEC: printf "$BUILD/src/zeek -b --\n" >> test.zeek +# @TEST-EXEC: cat %INPUT >> test.zeek +# @TEST-EXEC: chmod u+x test.zeek + +# @TEST-EXEC: zeek -b -- %INPUT -a -b -c >out +# @TEST-EXEC: $(dirname %INPUT)/test.zeek -d -e -f >>out + +# @TEST-EXEC: btest-diff out + +event zeek_init() + { + print zeek_script_args; + }