mirror of
https://github.com/Icinga/icinga2.git
synced 2025-04-08 17:05:25 +02:00
Implemented environment-based macros.
This commit is contained in:
parent
f8851aa79d
commit
ee37e0cace
@ -32,6 +32,8 @@ AC_LANG_CPLUSPLUS
|
||||
AC_PROG_CC
|
||||
AC_LANG_C
|
||||
|
||||
AC_FUNC_VFORK
|
||||
|
||||
LT_INIT([dlopen disable-static win32-dll])
|
||||
LT_CONFIG_LTDL_DIR([third-party/ltdl])
|
||||
LTDL_INIT
|
||||
|
@ -43,3 +43,7 @@ String Convert::ToString(long val)
|
||||
return cs.str();
|
||||
}
|
||||
|
||||
String Convert::ToString(const Value& val)
|
||||
{
|
||||
return static_cast<String>(val);
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ public:
|
||||
static double ToDouble(const String& val);
|
||||
static bool ToBool(const String& val);
|
||||
static String ToString(long val);
|
||||
static String ToString(const Value& val);
|
||||
|
||||
private:
|
||||
Convert(void);
|
||||
|
@ -255,4 +255,3 @@ cJSON *Dictionary::ToJson(void) const
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,6 @@
|
||||
|
||||
#include "i2-base.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# include "popen_noshell.h"
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
bool Process::m_ThreadCreated = false;
|
||||
@ -30,8 +26,9 @@ boost::mutex Process::m_Mutex;
|
||||
deque<Process::Ptr> Process::m_Tasks;
|
||||
condition_variable Process::m_TasksCV;
|
||||
|
||||
Process::Process(const String& command)
|
||||
: AsyncTask<Process, ProcessResult>(), m_Command(command), m_UsePopen(false)
|
||||
Process::Process(const String& command, const Dictionary::Ptr& environment)
|
||||
: AsyncTask<Process, ProcessResult>(), m_Command(command),
|
||||
m_Environment(environment), m_FP(NULL)
|
||||
{
|
||||
assert(Application::IsMainThread());
|
||||
|
||||
@ -130,29 +127,127 @@ void Process::WorkerThreadProc(void)
|
||||
}
|
||||
}
|
||||
|
||||
void Process::Spawn(const String& command, const Dictionary::Ptr& env)
|
||||
{
|
||||
vector<String> args;
|
||||
args.push_back("sh");
|
||||
args.push_back("-c");
|
||||
args.push_back(command);
|
||||
|
||||
return Spawn(args, env);
|
||||
}
|
||||
|
||||
void Process::Spawn(const vector<String>& args, const Dictionary::Ptr& extraEnv)
|
||||
{
|
||||
assert(m_FP == NULL);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#error "TODO: implement"
|
||||
#else /* _MSC_VER */
|
||||
int fds[2];
|
||||
|
||||
if (pipe(fds) < 0)
|
||||
BOOST_THROW_EXCEPTION(PosixException("pipe() failed.", errno));
|
||||
|
||||
char **argv = new char *[args.size() + 1];
|
||||
|
||||
for (int i = 0; i < args.size(); i++)
|
||||
argv[i] = strdup(args[i].CStr());
|
||||
|
||||
argv[args.size()] = NULL;
|
||||
|
||||
int envc = 0;
|
||||
|
||||
/* count existing environment variables */
|
||||
while (environ[envc] != NULL)
|
||||
envc++;
|
||||
|
||||
char **envp = new char *[envc + (extraEnv ? extraEnv->GetLength() : 0) + 1];
|
||||
|
||||
for (int i = 0; i < envc; i++)
|
||||
envp[i] = environ[i];
|
||||
|
||||
if (extraEnv) {
|
||||
String key;
|
||||
Value value;
|
||||
int index = envc;
|
||||
BOOST_FOREACH(tie(key, value), extraEnv) {
|
||||
String kv = key + "=" + Convert::ToString(value);
|
||||
envp[index] = strdup(kv.CStr());
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
envp[envc + (extraEnv ? extraEnv->GetLength() : 0)] = NULL;
|
||||
|
||||
#ifdef HAVE_VFORK
|
||||
m_Pid = vfork();
|
||||
#else /* HAVE_VFORK */
|
||||
m_Pid = fork();
|
||||
#endif /* HAVE_VFORK */
|
||||
|
||||
if (m_Pid < 0)
|
||||
BOOST_THROW_EXCEPTION(PosixException("fork() failed.", errno));
|
||||
|
||||
if (m_Pid == 0) {
|
||||
/* child */
|
||||
if (dup2(fds[1], STDOUT_FILENO) < 0 || dup2(fds[1], STDERR_FILENO) < 0) {
|
||||
perror("dup2() failed.");
|
||||
_exit(128);
|
||||
}
|
||||
|
||||
(void) close(fds[1]);
|
||||
|
||||
if (execvpe(argv[0], argv, envp) < 0) {
|
||||
perror("execvpe() failed.");
|
||||
_exit(128);
|
||||
}
|
||||
|
||||
_exit(128);
|
||||
} else {
|
||||
for (int i = 0; i < args.size(); i++)
|
||||
free(argv[i]);
|
||||
|
||||
delete [] argv;
|
||||
|
||||
if (extraEnv) {
|
||||
for (int i = envc; i < envc + extraEnv->GetLength(); i++)
|
||||
free(envp[i]);
|
||||
}
|
||||
|
||||
delete [] envp;
|
||||
|
||||
/* parent */
|
||||
(void) close(fds[1]);
|
||||
|
||||
m_FP = fdopen(fds[0], "r");
|
||||
|
||||
if (m_FP == NULL)
|
||||
BOOST_THROW_EXCEPTION(PosixException("fdopen() failed.", errno));
|
||||
}
|
||||
#endif /* _MSC_VER */
|
||||
}
|
||||
|
||||
int Process::WaitPid(void)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _pclose(m_FP);
|
||||
#else /* _MSC_VER */
|
||||
fclose(m_FP);
|
||||
|
||||
int status;
|
||||
if (waitpid(m_Pid, &status, 0) != m_Pid)
|
||||
BOOST_THROW_EXCEPTION(PosixException("waitpid() failed.", errno));
|
||||
|
||||
return status;
|
||||
#endif /* _MSC_VER */
|
||||
}
|
||||
|
||||
void Process::InitTask(void)
|
||||
{
|
||||
m_Result.ExecutionStart = Utility::GetTime();
|
||||
|
||||
#ifdef _MSC_VER
|
||||
m_FP = _popen(m_Command.CStr(), "r");
|
||||
#else /* _MSC_VER */
|
||||
if (!m_UsePopen) {
|
||||
m_PCloseArg = new popen_noshell_pass_to_pclose;
|
||||
|
||||
m_FP = popen_noshell_compat(m_Command.CStr(), "r",
|
||||
(popen_noshell_pass_to_pclose *)m_PCloseArg);
|
||||
|
||||
if (m_FP == NULL)
|
||||
m_UsePopen = true;
|
||||
}
|
||||
|
||||
if (m_UsePopen)
|
||||
m_FP = popen(m_Command.CStr(), "r");
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
if (m_FP == NULL)
|
||||
BOOST_THROW_EXCEPTION(runtime_error("Could not create process."));
|
||||
Spawn(m_Command, m_Environment);
|
||||
}
|
||||
|
||||
bool Process::RunTask(void)
|
||||
@ -169,18 +264,8 @@ bool Process::RunTask(void)
|
||||
String output = m_OutputStream.str();
|
||||
|
||||
int status, exitcode;
|
||||
#ifdef _MSC_VER
|
||||
status = _pclose(m_FP);
|
||||
#else /* _MSC_VER */
|
||||
if (m_UsePopen) {
|
||||
status = pclose(m_FP);
|
||||
} else {
|
||||
status = pclose_noshell((popen_noshell_pass_to_pclose *)m_PCloseArg);
|
||||
delete (popen_noshell_pass_to_pclose *)m_PCloseArg;
|
||||
}
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
m_Result.ExecutionEnd = Utility::GetTime();
|
||||
status = WaitPid();
|
||||
|
||||
#ifndef _MSC_VER
|
||||
if (WIFEXITED(status)) {
|
||||
@ -206,6 +291,7 @@ bool Process::RunTask(void)
|
||||
}
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
m_Result.ExecutionEnd = Utility::GetTime();
|
||||
m_Result.ExitStatus = exitcode;
|
||||
m_Result.Output = output;
|
||||
|
||||
|
@ -50,19 +50,20 @@ public:
|
||||
|
||||
static const deque<Process::Ptr>::size_type MaxTasksPerThread = 512;
|
||||
|
||||
Process(const String& command);
|
||||
Process(const String& command, const Dictionary::Ptr& environment = Dictionary::Ptr());
|
||||
|
||||
private:
|
||||
static bool m_ThreadCreated;
|
||||
|
||||
String m_Command;
|
||||
Dictionary::Ptr m_Environment;
|
||||
|
||||
#ifndef _WIN32
|
||||
pid_t m_Pid;
|
||||
#endif /* _WIN32 */
|
||||
FILE *m_FP;
|
||||
|
||||
stringstream m_OutputStream;
|
||||
bool m_UsePopen;
|
||||
#ifndef _MSC_VER
|
||||
void *m_PCloseArg;
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
ProcessResult m_Result;
|
||||
|
||||
@ -78,6 +79,10 @@ private:
|
||||
bool RunTask(void);
|
||||
|
||||
int GetFD(void) const;
|
||||
|
||||
void Spawn(const String& command, const Dictionary::Ptr& extraEnv);
|
||||
void Spawn(const vector<String>& args, const Dictionary::Ptr& extraEnv);
|
||||
int WaitPid(void);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -56,3 +56,21 @@ String MacroProcessor::ResolveMacros(const String& str, const vector<Dictionary:
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Dictionary::Ptr MacroProcessor::MakeEnvironment(const vector<Dictionary::Ptr>& dicts)
|
||||
{
|
||||
Dictionary::Ptr result = boost::make_shared<Dictionary>();
|
||||
|
||||
BOOST_REVERSE_FOREACH(const Dictionary::Ptr& dict, dicts) {
|
||||
String key;
|
||||
Value value;
|
||||
BOOST_FOREACH(tie(key, value), dict) {
|
||||
if (!value.IsScalar())
|
||||
continue;
|
||||
|
||||
result->Set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ class I2_ICINGA_API MacroProcessor
|
||||
{
|
||||
public:
|
||||
static String ResolveMacros(const String& str, const vector<Dictionary::Ptr>& macroDicts);
|
||||
static Dictionary::Ptr MakeEnvironment(const vector<Dictionary::Ptr>& macroDicts);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value
|
||||
macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros());
|
||||
String command = MacroProcessor::ResolveMacros(checkCommand, macroDicts);
|
||||
|
||||
Process::Ptr process = boost::make_shared<Process>(command);
|
||||
Process::Ptr process = boost::make_shared<Process>(command, MacroProcessor::MakeEnvironment(macroDicts));
|
||||
|
||||
PluginCheckTask ct(task, process);
|
||||
|
||||
|
@ -53,7 +53,7 @@ void PluginNotificationTask::ScriptFunc(const ScriptTask::Ptr& task, const vecto
|
||||
macroDicts.push_back(IcingaApplication::GetInstance()->GetMacros());
|
||||
String command = MacroProcessor::ResolveMacros(notificationCommand, macroDicts);
|
||||
|
||||
Process::Ptr process = boost::make_shared<Process>(command);
|
||||
Process::Ptr process = boost::make_shared<Process>(command, MacroProcessor::MakeEnvironment(macroDicts));
|
||||
|
||||
PluginNotificationTask ct(task, process, notification->GetService()->GetName(), command);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user