mirror of https://github.com/Icinga/icinga2.git
parent
1a0dd27b3a
commit
4418688f34
|
@ -196,6 +196,29 @@ value of arbitrary macro expressions:
|
|||
return "Some text"
|
||||
}}
|
||||
|
||||
The `resolve_arguments` can be used to resolve a command and its arguments much in
|
||||
the same fashion Icinga does this for the `command` and `arguments` attributes for
|
||||
commands. The `by_ssh` command uses this functionality to let users specify a
|
||||
command and arguments that should be executed via SSH:
|
||||
|
||||
arguments = {
|
||||
"-C" = {{
|
||||
var command = macro("$by_ssh_command$")
|
||||
var arguments = macro("$by_ssh_arguments$")
|
||||
|
||||
if (typeof(command) == String && !arguments) {
|
||||
return command
|
||||
}
|
||||
|
||||
var escaped_args = []
|
||||
for (arg in resolve_arguments(command, arguments)) {
|
||||
escaped_args.add(escape_shell_arg(arg))
|
||||
}
|
||||
return escaped_args.join(" ")
|
||||
}}
|
||||
...
|
||||
}
|
||||
|
||||
Acessing object attributes at runtime inside these functions is described in the
|
||||
[advanced topics](5-advanced-topics.md#access-object-attributes-at-runtime) chapter.
|
||||
|
||||
|
|
|
@ -96,7 +96,8 @@ Name | Description
|
|||
----------------|--------------
|
||||
by_ssh_address | **Optional.** The host's address. Defaults to "$address$" if the host's `address` attribute is set, "$address6$" otherwise.
|
||||
by_ssh_port | **Optional.** The SSH port. Defaults to 22.
|
||||
by_ssh_command | **Optional.** The command that should be executed.
|
||||
by_ssh_command | **Required.** The command that should be executed. Can be an array if multiple arguments should be passed to `check_by_ssh`.
|
||||
by_ssh_arguments| **Optional.** A dictionary with arguments for the command. This works exactly like the 'arguments' dictionary for ordinary CheckCommands.
|
||||
by_ssh_logname | **Optional.** The SSH username.
|
||||
by_ssh_identity | **Optional.** The SSH identity.
|
||||
by_ssh_quiet | **Optional.** Whether to suppress SSH warnings. Defaults to false.
|
||||
|
|
|
@ -1277,7 +1277,20 @@ object CheckCommand "by_ssh" {
|
|||
arguments = {
|
||||
"-H" = "$by_ssh_address$"
|
||||
"-p" = "$by_ssh_port$"
|
||||
"-C" = "$by_ssh_command$"
|
||||
"-C" = {{
|
||||
var command = macro("$by_ssh_command$")
|
||||
var arguments = macro("$by_ssh_arguments$")
|
||||
|
||||
if (typeof(command) == String && !arguments) {
|
||||
return command
|
||||
}
|
||||
|
||||
var escaped_args = []
|
||||
for (arg in resolve_arguments(command, arguments)) {
|
||||
escaped_args.add(escape_shell_arg(arg))
|
||||
}
|
||||
return escaped_args.join(" ")
|
||||
}}
|
||||
"-l" = "$by_ssh_logname$"
|
||||
"-i" = "$by_ssh_identity$"
|
||||
"-q" = {
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "base/context.hpp"
|
||||
#include "base/dynamicobject.hpp"
|
||||
#include "base/scriptframe.hpp"
|
||||
#include "base/convert.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
|
@ -36,7 +38,7 @@ using namespace icinga;
|
|||
Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolvers,
|
||||
const CheckResult::Ptr& cr, String *missingMacro,
|
||||
const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros,
|
||||
bool useResolvedMacros)
|
||||
bool useResolvedMacros, int recursionLevel)
|
||||
{
|
||||
Value result;
|
||||
|
||||
|
@ -45,7 +47,7 @@ Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolv
|
|||
|
||||
if (str.IsScalar()) {
|
||||
result = InternalResolveMacros(str, resolvers, cr, missingMacro, escapeFn,
|
||||
resolvedMacros, useResolvedMacros);
|
||||
resolvedMacros, useResolvedMacros, recursionLevel + 1);
|
||||
} else if (str.IsObjectType<Array>()) {
|
||||
Array::Ptr resultArr = new Array();
|
||||
Array::Ptr arr = str;
|
||||
|
@ -55,7 +57,7 @@ Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolv
|
|||
BOOST_FOREACH(const Value& arg, arr) {
|
||||
/* Note: don't escape macros here. */
|
||||
Value value = InternalResolveMacros(arg, resolvers, cr, missingMacro,
|
||||
EscapeCallback(), resolvedMacros, useResolvedMacros);
|
||||
EscapeCallback(), resolvedMacros, useResolvedMacros, recursionLevel + 1);
|
||||
|
||||
if (value.IsObjectType<Array>())
|
||||
resultArr->Add(Utility::Join(value, ';'));
|
||||
|
@ -73,7 +75,7 @@ Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolv
|
|||
BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
|
||||
/* Note: don't escape macros here. */
|
||||
resultDict->Set(kv.first, InternalResolveMacros(kv.second, resolvers, cr, missingMacro,
|
||||
EscapeCallback(), resolvedMacros, useResolvedMacros));
|
||||
EscapeCallback(), resolvedMacros, useResolvedMacros, recursionLevel + 1));
|
||||
}
|
||||
|
||||
result = resultDict;
|
||||
|
@ -187,6 +189,17 @@ Value MacroProcessor::InternalResolveMacrosShim(const std::vector<Value>& args,
|
|||
resolvedMacros, useResolvedMacros, recursionLevel);
|
||||
}
|
||||
|
||||
Value MacroProcessor::InternalResolveArgumentsShim(const std::vector<Value>& args, const ResolverList& resolvers,
|
||||
const CheckResult::Ptr& cr, const Dictionary::Ptr& resolvedMacros,
|
||||
bool useResolvedMacros, int recursionLevel)
|
||||
{
|
||||
if (args.size() < 2)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Too few arguments for function"));
|
||||
|
||||
return MacroProcessor::ResolveArguments(args[0], args[1], resolvers, cr,
|
||||
resolvedMacros, useResolvedMacros, recursionLevel);
|
||||
}
|
||||
|
||||
Value MacroProcessor::EvaluateFunction(const Function::Ptr& func, const ResolverList& resolvers,
|
||||
const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn,
|
||||
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel)
|
||||
|
@ -200,6 +213,9 @@ Value MacroProcessor::EvaluateFunction(const Function::Ptr& func, const Resolver
|
|||
resolvers_this->Set("macro", new Function(boost::bind(&MacroProcessor::InternalResolveMacrosShim,
|
||||
_1, boost::cref(resolvers), cr, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros,
|
||||
recursionLevel + 1)));
|
||||
resolvers_this->Set("resolve_arguments", new Function(boost::bind(&MacroProcessor::InternalResolveArgumentsShim,
|
||||
_1, boost::cref(resolvers), cr, resolvedMacros, useResolvedMacros,
|
||||
recursionLevel + 1)));
|
||||
|
||||
ScriptFrame frame(resolvers_this);
|
||||
return func->Invoke();
|
||||
|
@ -250,7 +266,7 @@ Value MacroProcessor::InternalResolveMacros(const String& str, const ResolverLis
|
|||
|
||||
if (resolved_macro.IsObjectType<Function>()) {
|
||||
resolved_macro = EvaluateFunction(resolved_macro, resolvers, cr, escapeFn,
|
||||
resolvedMacros, useResolvedMacros, recursionLevel);
|
||||
resolvedMacros, useResolvedMacros, recursionLevel + 1);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
|
@ -334,3 +350,179 @@ bool MacroProcessor::ValidateMacroString(const String& macro)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroProcessor::AddArgumentHelper(const Array::Ptr& args, const String& key, const String& value,
|
||||
bool add_key, bool add_value)
|
||||
{
|
||||
if (add_key)
|
||||
args->Add(key);
|
||||
|
||||
if (add_value)
|
||||
args->Add(value);
|
||||
}
|
||||
|
||||
Value MacroProcessor::EscapeMacroShellArg(const Value& value)
|
||||
{
|
||||
String result;
|
||||
|
||||
if (value.IsObjectType<Array>()) {
|
||||
Array::Ptr arr = value;
|
||||
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const Value& arg, arr) {
|
||||
if (result.GetLength() > 0)
|
||||
result += " ";
|
||||
|
||||
result += Utility::EscapeShellArg(arg);
|
||||
}
|
||||
} else
|
||||
result = Utility::EscapeShellArg(value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct CommandArgument
|
||||
{
|
||||
int Order;
|
||||
bool SkipKey;
|
||||
bool RepeatKey;
|
||||
bool SkipValue;
|
||||
String Key;
|
||||
Value AValue;
|
||||
|
||||
CommandArgument(void)
|
||||
: Order(0), SkipKey(false), RepeatKey(true), SkipValue(false)
|
||||
{ }
|
||||
|
||||
bool operator<(const CommandArgument& rhs) const
|
||||
{
|
||||
return Order < rhs.Order;
|
||||
}
|
||||
};
|
||||
|
||||
Value MacroProcessor::ResolveArguments(const Value& command, const Dictionary::Ptr& arguments,
|
||||
const MacroProcessor::ResolverList& resolvers, const CheckResult::Ptr& cr,
|
||||
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel)
|
||||
{
|
||||
Value resolvedCommand;
|
||||
if (!arguments || command.IsObjectType<Array>() || command.IsObjectType<Function>())
|
||||
resolvedCommand = MacroProcessor::ResolveMacros(command, resolvers, cr, NULL,
|
||||
EscapeMacroShellArg, resolvedMacros, useResolvedMacros, recursionLevel + 1);
|
||||
else {
|
||||
Array::Ptr arr = new Array();
|
||||
arr->Add(command);
|
||||
resolvedCommand = arr;
|
||||
}
|
||||
|
||||
if (arguments) {
|
||||
std::vector<CommandArgument> args;
|
||||
|
||||
ObjectLock olock(arguments);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, arguments) {
|
||||
const Value& arginfo = kv.second;
|
||||
|
||||
CommandArgument arg;
|
||||
arg.Key = kv.first;
|
||||
|
||||
bool required = false;
|
||||
Value argval;
|
||||
|
||||
if (arginfo.IsObjectType<Dictionary>()) {
|
||||
Dictionary::Ptr argdict = arginfo;
|
||||
if (argdict->Contains("key"))
|
||||
arg.Key = argdict->Get("key");
|
||||
argval = argdict->Get("value");
|
||||
if (argdict->Contains("required"))
|
||||
required = argdict->Get("required");
|
||||
arg.SkipKey = argdict->Get("skip_key");
|
||||
if (argdict->Contains("repeat_key"))
|
||||
arg.RepeatKey = argdict->Get("repeat_key");
|
||||
arg.Order = argdict->Get("order");
|
||||
|
||||
Value set_if = argdict->Get("set_if");
|
||||
|
||||
if (!set_if.IsEmpty()) {
|
||||
String missingMacro;
|
||||
Value set_if_resolved = MacroProcessor::ResolveMacros(set_if, resolvers,
|
||||
cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros,
|
||||
useResolvedMacros, recursionLevel + 1);
|
||||
|
||||
if (!missingMacro.IsEmpty())
|
||||
continue;
|
||||
|
||||
int value;
|
||||
|
||||
if (set_if_resolved == "true")
|
||||
value = 1;
|
||||
else if (set_if_resolved == "false")
|
||||
value = 0;
|
||||
else {
|
||||
try {
|
||||
value = Convert::ToLong(set_if_resolved);
|
||||
} catch (const std::exception& ex) {
|
||||
/* tried to convert a string */
|
||||
Log(LogWarning, "PluginUtility")
|
||||
<< "Error evaluating set_if value '" << set_if_resolved << "': " << ex.what();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!value)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
argval = arginfo;
|
||||
|
||||
if (argval.IsEmpty())
|
||||
arg.SkipValue = true;
|
||||
|
||||
String missingMacro;
|
||||
arg.AValue = MacroProcessor::ResolveMacros(argval, resolvers,
|
||||
cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros,
|
||||
useResolvedMacros, recursionLevel + 1);
|
||||
|
||||
if (!missingMacro.IsEmpty()) {
|
||||
if (required) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Non-optional macro '" + missingMacro + "' used in argument '" +
|
||||
arg.Key + "' is missing."));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
args.push_back(arg);
|
||||
}
|
||||
|
||||
std::sort(args.begin(), args.end());
|
||||
|
||||
Array::Ptr command_arr = resolvedCommand;
|
||||
BOOST_FOREACH(const CommandArgument& arg, args) {
|
||||
|
||||
if (arg.AValue.IsObjectType<Dictionary>()) {
|
||||
Log(LogWarning, "PluginUtility", "Tried to use dictionary in argument");
|
||||
continue;
|
||||
} else if (arg.AValue.IsObjectType<Array>()) {
|
||||
bool first = true;
|
||||
Array::Ptr arr = static_cast<Array::Ptr>(arg.AValue);
|
||||
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const Value& value, arr) {
|
||||
bool add_key;
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
add_key = !arg.SkipKey;
|
||||
} else
|
||||
add_key = !arg.SkipKey && arg.RepeatKey;
|
||||
|
||||
AddArgumentHelper(command_arr, arg.Key, value, add_key, !arg.SkipValue);
|
||||
}
|
||||
} else
|
||||
AddArgumentHelper(command_arr, arg.Key, arg.AValue, !arg.SkipKey, !arg.SkipValue);
|
||||
}
|
||||
}
|
||||
|
||||
return resolvedCommand;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,11 @@ public:
|
|||
const CheckResult::Ptr& cr = CheckResult::Ptr(), String *missingMacro = NULL,
|
||||
const EscapeCallback& escapeFn = EscapeCallback(),
|
||||
const Dictionary::Ptr& resolvedMacros = Dictionary::Ptr(),
|
||||
bool useResolvedMacros = false);
|
||||
bool useResolvedMacros = false, int recursionLevel = 0);
|
||||
|
||||
static Value ResolveArguments(const Value& command, const Dictionary::Ptr& arguments,
|
||||
const MacroProcessor::ResolverList& resolvers, const CheckResult::Ptr& cr,
|
||||
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel = 0);
|
||||
|
||||
static bool ValidateMacroString(const String& macro);
|
||||
|
||||
|
@ -62,10 +66,17 @@ private:
|
|||
static Value InternalResolveMacrosShim(const std::vector<Value>& args, const ResolverList& resolvers,
|
||||
const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn,
|
||||
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel);
|
||||
static Value InternalResolveArgumentsShim(const std::vector<Value>& args, const ResolverList& resolvers,
|
||||
const CheckResult::Ptr& cr, const Dictionary::Ptr& resolvedMacros,
|
||||
bool useResolvedMacros, int recursionLevel);
|
||||
static Value EvaluateFunction(const Function::Ptr& func, const ResolverList& resolvers,
|
||||
const CheckResult::Ptr& cr, const MacroProcessor::EscapeCallback& escapeFn,
|
||||
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, int recursionLevel);
|
||||
|
||||
static void AddArgumentHelper(const Array::Ptr& args, const String& key, const String& value,
|
||||
bool add_key, bool add_value);
|
||||
static Value EscapeMacroShellArg(const Value& value);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "base/convert.hpp"
|
||||
#include "base/process.hpp"
|
||||
#include "base/objectlock.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
@ -32,54 +33,6 @@
|
|||
|
||||
using namespace icinga;
|
||||
|
||||
struct CommandArgument
|
||||
{
|
||||
int Order;
|
||||
bool SkipKey;
|
||||
bool RepeatKey;
|
||||
bool SkipValue;
|
||||
String Key;
|
||||
Value AValue;
|
||||
|
||||
CommandArgument(void)
|
||||
: Order(0), SkipKey(false), RepeatKey(true), SkipValue(false)
|
||||
{ }
|
||||
|
||||
bool operator<(const CommandArgument& rhs) const
|
||||
{
|
||||
return Order < rhs.Order;
|
||||
}
|
||||
};
|
||||
|
||||
void PluginUtility::AddArgumentHelper(const Array::Ptr& args, const String& key, const String& value, bool add_key, bool add_value)
|
||||
{
|
||||
if (add_key)
|
||||
args->Add(key);
|
||||
|
||||
if (add_value)
|
||||
args->Add(value);
|
||||
}
|
||||
|
||||
Value PluginUtility::EscapeMacroShellArg(const Value& value)
|
||||
{
|
||||
String result;
|
||||
|
||||
if (value.IsObjectType<Array>()) {
|
||||
Array::Ptr arr = value;
|
||||
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const Value& arg, arr) {
|
||||
if (result.GetLength() > 0)
|
||||
result += " ";
|
||||
|
||||
result += Utility::EscapeShellArg(arg);
|
||||
}
|
||||
} else
|
||||
result = Utility::EscapeShellArg(value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkable::Ptr& checkable,
|
||||
const CheckResult::Ptr& cr, const MacroProcessor::ResolverList& macroResolvers,
|
||||
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros,
|
||||
|
@ -89,136 +42,26 @@ void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkab
|
|||
Dictionary::Ptr raw_arguments = commandObj->GetArguments();
|
||||
|
||||
Value command;
|
||||
if (!raw_arguments || raw_command.IsObjectType<Array>() || raw_command.IsObjectType<Function>())
|
||||
command = MacroProcessor::ResolveMacros(raw_command, macroResolvers, cr, NULL,
|
||||
PluginUtility::EscapeMacroShellArg, resolvedMacros, useResolvedMacros);
|
||||
else {
|
||||
Array::Ptr arr = new Array();
|
||||
arr->Add(raw_command);
|
||||
command = arr;
|
||||
}
|
||||
|
||||
if (raw_arguments) {
|
||||
std::vector<CommandArgument> args;
|
||||
try {
|
||||
command = MacroProcessor::ResolveArguments(raw_command, raw_arguments,
|
||||
macroResolvers, cr, resolvedMacros, useResolvedMacros);
|
||||
} catch (const std::exception& ex) {
|
||||
String message = DiagnosticInformation(ex);
|
||||
|
||||
ObjectLock olock(raw_arguments);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, raw_arguments) {
|
||||
const Value& arginfo = kv.second;
|
||||
Log(LogWarning, "PluginUtility", message);
|
||||
|
||||
CommandArgument arg;
|
||||
arg.Key = kv.first;
|
||||
|
||||
bool required = false;
|
||||
Value argval;
|
||||
|
||||
if (arginfo.IsObjectType<Dictionary>()) {
|
||||
Dictionary::Ptr argdict = arginfo;
|
||||
if (argdict->Contains("key"))
|
||||
arg.Key = argdict->Get("key");
|
||||
argval = argdict->Get("value");
|
||||
if (argdict->Contains("required"))
|
||||
required = argdict->Get("required");
|
||||
arg.SkipKey = argdict->Get("skip_key");
|
||||
if (argdict->Contains("repeat_key"))
|
||||
arg.RepeatKey = argdict->Get("repeat_key");
|
||||
arg.Order = argdict->Get("order");
|
||||
|
||||
Value set_if = argdict->Get("set_if");
|
||||
|
||||
if (!set_if.IsEmpty()) {
|
||||
String missingMacro;
|
||||
Value set_if_resolved = MacroProcessor::ResolveMacros(set_if, macroResolvers,
|
||||
cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros,
|
||||
useResolvedMacros);
|
||||
|
||||
if (!missingMacro.IsEmpty())
|
||||
continue;
|
||||
|
||||
int value;
|
||||
|
||||
if (set_if_resolved == "true")
|
||||
value = 1;
|
||||
else if (set_if_resolved == "false")
|
||||
value = 0;
|
||||
else {
|
||||
try {
|
||||
value = Convert::ToLong(set_if_resolved);
|
||||
} catch (const std::exception& ex) {
|
||||
/* tried to convert a string */
|
||||
Log(LogWarning, "PluginUtility")
|
||||
<< "Error evaluating set_if value '" << set_if_resolved << "': " << ex.what();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!value)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
argval = arginfo;
|
||||
|
||||
if (argval.IsEmpty())
|
||||
arg.SkipValue = true;
|
||||
|
||||
String missingMacro;
|
||||
arg.AValue = MacroProcessor::ResolveMacros(argval, macroResolvers,
|
||||
cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros,
|
||||
useResolvedMacros);
|
||||
|
||||
if (!missingMacro.IsEmpty()) {
|
||||
if (required) {
|
||||
String message = "Non-optional macro '" + missingMacro + "' used in argument '" +
|
||||
arg.Key + "' is missing while executing command '" + commandObj->GetName() +
|
||||
"' for object '" + checkable->GetName() + "'";
|
||||
Log(LogWarning, "PluginUtility", message);
|
||||
|
||||
if (callback) {
|
||||
ProcessResult pr;
|
||||
pr.PID = -1;
|
||||
pr.ExecutionStart = Utility::GetTime();
|
||||
pr.ExecutionEnd = pr.ExecutionStart;
|
||||
pr.ExitStatus = 3; /* Unknown */
|
||||
pr.Output = message;
|
||||
callback(Empty, pr);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
args.push_back(arg);
|
||||
if (callback) {
|
||||
ProcessResult pr;
|
||||
pr.PID = -1;
|
||||
pr.ExecutionStart = Utility::GetTime();
|
||||
pr.ExecutionEnd = pr.ExecutionStart;
|
||||
pr.ExitStatus = 3; /* Unknown */
|
||||
pr.Output = message;
|
||||
callback(Empty, pr);
|
||||
}
|
||||
|
||||
std::sort(args.begin(), args.end());
|
||||
|
||||
Array::Ptr command_arr = command;
|
||||
BOOST_FOREACH(const CommandArgument& arg, args) {
|
||||
|
||||
if (arg.AValue.IsObjectType<Dictionary>()) {
|
||||
Log(LogWarning, "PluginUtility", "Tried to use dictionary in argument");
|
||||
continue;
|
||||
} else if (arg.AValue.IsObjectType<Array>()) {
|
||||
bool first = true;
|
||||
Array::Ptr arr = static_cast<Array::Ptr>(arg.AValue);
|
||||
|
||||
ObjectLock olock(arr);
|
||||
BOOST_FOREACH(const Value& value, arr) {
|
||||
bool add_key;
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
add_key = !arg.SkipKey;
|
||||
} else
|
||||
add_key = !arg.SkipKey && arg.RepeatKey;
|
||||
|
||||
AddArgumentHelper(command_arr, arg.Key, value, add_key, !arg.SkipValue);
|
||||
}
|
||||
} else
|
||||
AddArgumentHelper(command_arr, arg.Key, arg.AValue, !arg.SkipKey, !arg.SkipValue);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary::Ptr envMacros = new Dictionary();
|
||||
|
|
|
@ -52,9 +52,6 @@ public:
|
|||
|
||||
private:
|
||||
PluginUtility(void);
|
||||
|
||||
static void AddArgumentHelper(const Array::Ptr& args, const String& key, const String& value, bool add_key, bool add_value);
|
||||
static Value EscapeMacroShellArg(const Value& value);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue