|
|
|
@ -21,86 +21,32 @@ namespace llarp
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
struct ExecShellHookJob
|
|
|
|
|
{
|
|
|
|
|
const std::string &m_File;
|
|
|
|
|
const std::unordered_map< std::string, std::string > m_env;
|
|
|
|
|
ExecShellHookJob(
|
|
|
|
|
const std::string &f,
|
|
|
|
|
const std::unordered_map< std::string, std::string > _env)
|
|
|
|
|
: m_File(f), m_env(std::move(_env))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
Exec(void *user)
|
|
|
|
|
{
|
|
|
|
|
ExecShellHookJob *self = static_cast< ExecShellHookJob * >(user);
|
|
|
|
|
std::vector< std::string > _args;
|
|
|
|
|
std::vector< char * > args;
|
|
|
|
|
std::istringstream s(self->m_File);
|
|
|
|
|
for(std::string arg; std::getline(s, arg, ' ');)
|
|
|
|
|
{
|
|
|
|
|
_args.emplace_back(std::move(arg));
|
|
|
|
|
char *ptr = (char *)_args.back().c_str();
|
|
|
|
|
args.push_back(ptr);
|
|
|
|
|
}
|
|
|
|
|
args.push_back(0);
|
|
|
|
|
std::vector< std::string > _env(self->m_env.size() + 1);
|
|
|
|
|
std::vector< char * > env;
|
|
|
|
|
// copy environ
|
|
|
|
|
#if defined(Darwin)
|
|
|
|
|
char **ptr = *_NSGetEnviron();
|
|
|
|
|
#else
|
|
|
|
|
char **ptr = environ;
|
|
|
|
|
#endif
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
env.emplace_back(*ptr);
|
|
|
|
|
++ptr;
|
|
|
|
|
} while(ptr && *ptr);
|
|
|
|
|
// put in our variables
|
|
|
|
|
for(const auto &item : self->m_env)
|
|
|
|
|
{
|
|
|
|
|
_env.emplace_back(item.first + "=" + item.second);
|
|
|
|
|
char *ptr = (char *)_env.back().c_str();
|
|
|
|
|
env.push_back(ptr);
|
|
|
|
|
}
|
|
|
|
|
env.push_back(0);
|
|
|
|
|
const auto exe = _args[0].c_str();
|
|
|
|
|
const auto argv = args.data();
|
|
|
|
|
const auto argp = env.data();
|
|
|
|
|
|
|
|
|
|
pid_t child_process = ::fork();
|
|
|
|
|
if(child_process == -1)
|
|
|
|
|
{
|
|
|
|
|
LogError("failed to fork");
|
|
|
|
|
delete self;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(child_process)
|
|
|
|
|
{
|
|
|
|
|
int status = 0;
|
|
|
|
|
::waitpid(child_process, &status, 0);
|
|
|
|
|
LogInfo(_args[0], " exit code: ", status);
|
|
|
|
|
delete self;
|
|
|
|
|
}
|
|
|
|
|
else if(::execve(exe, argv, argp) == -1)
|
|
|
|
|
{
|
|
|
|
|
LogError("failed to exec ", _args[0], " : ", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ExecShellHookBackend : public IBackend
|
|
|
|
|
struct ExecShellHookBackend
|
|
|
|
|
: public IBackend,
|
|
|
|
|
public std::enable_shared_from_this< ExecShellHookBackend >
|
|
|
|
|
{
|
|
|
|
|
llarp_threadpool *m_ThreadPool;
|
|
|
|
|
const std::string m_ScriptFile;
|
|
|
|
|
|
|
|
|
|
std::vector< std::string > _args;
|
|
|
|
|
std::vector< char * > args;
|
|
|
|
|
|
|
|
|
|
ExecShellHookBackend(std::string script)
|
|
|
|
|
: m_ThreadPool(llarp_init_threadpool(1, script.c_str()))
|
|
|
|
|
, m_ScriptFile(std::move(script))
|
|
|
|
|
{
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
const auto idx = script.find_first_of(' ');
|
|
|
|
|
std::string sub;
|
|
|
|
|
if(idx == std::string::npos)
|
|
|
|
|
sub = script;
|
|
|
|
|
else
|
|
|
|
|
sub = script.substr(0, idx);
|
|
|
|
|
_args.emplace_back(std::move(sub));
|
|
|
|
|
args.push_back((char *)_args.back().c_str());
|
|
|
|
|
script = script.substr(idx + 1);
|
|
|
|
|
} while(script.find_first_of(' ') != std::string::npos);
|
|
|
|
|
args.push_back(nullptr);
|
|
|
|
|
LogInfo("make hook ", args.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~ExecShellHookBackend()
|
|
|
|
@ -123,21 +69,87 @@ namespace llarp
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
Exe() const
|
|
|
|
|
{
|
|
|
|
|
return args[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *const *
|
|
|
|
|
Args() const
|
|
|
|
|
{
|
|
|
|
|
return args.data();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
NotifyAsync(
|
|
|
|
|
std::unordered_map< std::string, std::string > params) override
|
|
|
|
|
std::unordered_map< std::string, std::string > params) override;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ExecShellHookJob
|
|
|
|
|
{
|
|
|
|
|
std::vector< std::string > m_env;
|
|
|
|
|
std::vector< char * > _m_env;
|
|
|
|
|
std::shared_ptr< ExecShellHookBackend > m_Parent;
|
|
|
|
|
|
|
|
|
|
ExecShellHookJob(std::shared_ptr< ExecShellHookBackend > b,
|
|
|
|
|
const std::unordered_map< std::string, std::string > env)
|
|
|
|
|
: m_Parent(b)
|
|
|
|
|
{
|
|
|
|
|
ExecShellHookJob *job =
|
|
|
|
|
new ExecShellHookJob(m_ScriptFile, std::move(params));
|
|
|
|
|
llarp_threadpool_queue_job(m_ThreadPool,
|
|
|
|
|
{job, &ExecShellHookJob::Exec});
|
|
|
|
|
#if defined(Darwin)
|
|
|
|
|
char **ptr = *_NSGetEnviron();
|
|
|
|
|
#else
|
|
|
|
|
char **ptr = environ;
|
|
|
|
|
#endif
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
m_env.emplace_back(*ptr);
|
|
|
|
|
++ptr;
|
|
|
|
|
} while(ptr && *ptr);
|
|
|
|
|
for(const auto &item : env)
|
|
|
|
|
m_env.emplace_back(item.first + "=" + item.second);
|
|
|
|
|
for(const auto &item : m_env)
|
|
|
|
|
_m_env.push_back((char *)item.c_str());
|
|
|
|
|
_m_env.push_back(nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *const *
|
|
|
|
|
Env()
|
|
|
|
|
{
|
|
|
|
|
return _m_env.data();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
Exec(std::shared_ptr< ExecShellHookJob > self)
|
|
|
|
|
{
|
|
|
|
|
std::thread t([&]() {
|
|
|
|
|
int result = 0;
|
|
|
|
|
const pid_t child = ::fork();
|
|
|
|
|
if(child == -1)
|
|
|
|
|
return;
|
|
|
|
|
if(child)
|
|
|
|
|
::waitpid(child, &result, 0);
|
|
|
|
|
else
|
|
|
|
|
::execve(self->m_Parent->Exe(), self->m_Parent->Args(),
|
|
|
|
|
self->Env());
|
|
|
|
|
});
|
|
|
|
|
t.join();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ExecShellHookBackend::NotifyAsync(
|
|
|
|
|
std::unordered_map< std::string, std::string > params)
|
|
|
|
|
{
|
|
|
|
|
auto job = std::make_shared< ExecShellHookJob >(shared_from_this(),
|
|
|
|
|
std::move(params));
|
|
|
|
|
m_ThreadPool->QueueFunc([=]() { ExecShellHookJob::Exec(job); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Backend_ptr
|
|
|
|
|
ExecShellBackend(std::string execFilePath)
|
|
|
|
|
{
|
|
|
|
|
Backend_ptr ptr = std::make_unique< ExecShellHookBackend >(execFilePath);
|
|
|
|
|
Backend_ptr ptr = std::make_shared< ExecShellHookBackend >(execFilePath);
|
|
|
|
|
if(!ptr->Start())
|
|
|
|
|
return nullptr;
|
|
|
|
|
return ptr;
|
|
|
|
|