You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lokinet/llarp/hook/shell.cpp

116 lines
3.0 KiB
C++

#include <hook/shell.hpp>
6 years ago
#include <util/threadpool.h>
#include <util/logger.hpp>
6 years ago
#include <sys/wait.h>
namespace llarp
{
namespace hooks
{
struct ExecShellHookJob
{
6 years ago
const std::string &m_File;
const std::unordered_map< std::string, std::string > m_env;
ExecShellHookJob(
6 years ago
const std::string &f,
const std::unordered_map< std::string, std::string > _env)
6 years ago
: m_File(f), m_env(std::move(_env))
{
}
6 years ago
static void
Exec(void *user)
{
6 years ago
ExecShellHookJob *self = static_cast< ExecShellHookJob * >(user);
char *const _args[] = {0};
std::vector< std::string > _env(self->m_env.size() + 1);
std::vector< char * > env;
6 years ago
// copy environ
6 years ago
char **ptr = environ;
do
{
env.emplace_back(*ptr);
++ptr;
} while(ptr && *ptr);
6 years ago
// put in our variables
6 years ago
for(const auto &item : self->m_env)
{
_env.emplace_back(item.first + "=" + item.second);
env.emplace_back(_env.back().c_str());
}
6 years ago
env.emplace_back(0);
int status = 0;
6 years ago
pid_t child_pid = ::fork();
if(child_pid == -1)
{
LogError("fork failed: ", strerror(errno));
errno = 0;
6 years ago
delete self;
6 years ago
return;
}
if(child_pid)
{
6 years ago
LogInfo(self->m_File, " spawned");
6 years ago
::waitpid(child_pid, &status, 0);
6 years ago
LogInfo(self->m_File, " exit code: ", status);
delete self;
6 years ago
}
else
6 years ago
::execvpe(self->m_File.c_str(), _args, env.data());
}
};
struct ExecShellHookBackend : public IBackend
{
6 years ago
llarp_threadpool *m_ThreadPool;
const std::string m_ScriptFile;
ExecShellHookBackend(std::string script)
6 years ago
: m_ThreadPool(llarp_init_threadpool(1, script.c_str()))
, m_ScriptFile(std::move(script))
{
}
6 years ago
~ExecShellHookBackend()
{
llarp_threadpool_stop(m_ThreadPool);
llarp_threadpool_join(m_ThreadPool);
6 years ago
llarp_free_threadpool(&m_ThreadPool);
}
bool
Start() override
{
6 years ago
llarp_threadpool_start(m_ThreadPool);
return true;
}
bool
Stop() override
{
6 years ago
llarp_threadpool_stop(m_ThreadPool);
llarp_threadpool_join(m_ThreadPool);
return true;
}
void
NotifyAsync(
std::unordered_map< std::string, std::string > params) override
{
6 years ago
ExecShellHookJob *job =
new ExecShellHookJob(m_ScriptFile, std::move(params));
llarp_threadpool_queue_job(m_ThreadPool,
{job, &ExecShellHookJob::Exec});
}
};
Backend_ptr
ExecShellBackend(std::string execFilePath)
{
Backend_ptr ptr = std::make_unique< ExecShellHookBackend >(execFilePath);
if(!ptr->Start())
return nullptr;
return ptr;
}
} // namespace hooks
} // namespace llarp