Support KAKOUNE_POSIX_SHELL environment variable to choose the shell path

The shell will always be run with 'sh' as argv[0] to make shells such
as busybox sh supported.

Closes #2547
This commit is contained in:
Maxime Coste 2018-11-27 22:21:20 +11:00
parent 5250593129
commit d1274836cd

View File

@ -28,22 +28,32 @@ namespace Kakoune
ShellManager::ShellManager(ConstArrayView<EnvVarDesc> builtin_env_vars) ShellManager::ShellManager(ConstArrayView<EnvVarDesc> builtin_env_vars)
: m_env_vars{builtin_env_vars} : m_env_vars{builtin_env_vars}
{ {
// Get a guaranteed to be POSIX shell binary auto is_executable = [](StringView path) {
struct stat st;
if (stat(path.zstr(), &st))
return false;
bool executable = (st.st_mode & S_IXUSR)
| (st.st_mode & S_IXGRP)
| (st.st_mode & S_IXOTH);
return S_ISREG(st.st_mode) and executable;
};
if (const char* shell = getenv("KAKOUNE_POSIX_SHELL"))
{
if (not is_executable(shell))
throw runtime_error{format("KAKOUNE_POSIX_SHELL '{}' is not executable", shell)};
m_shell = shell;
}
else // Get a guaranteed to be POSIX shell binary
{ {
auto size = confstr(_CS_PATH, nullptr, 0); auto size = confstr(_CS_PATH, nullptr, 0);
String path; path.resize(size-1, 0); String path; path.resize(size-1, 0);
confstr(_CS_PATH, path.data(), size); confstr(_CS_PATH, path.data(), size);
for (auto dir : StringView{path} | split<StringView>(':')) for (auto dir : StringView{path} | split<StringView>(':'))
{ {
String candidate = format("{}/sh", dir); auto candidate = format("{}/sh", dir);
struct stat st; if (is_executable(candidate))
if (stat(candidate.c_str(), &st))
continue;
bool executable = (st.st_mode & S_IXUSR)
| (st.st_mode & S_IXGRP)
| (st.st_mode & S_IXOTH);
if (S_ISREG(st.st_mode) and executable)
{ {
m_shell = std::move(candidate); m_shell = std::move(candidate);
break; break;
@ -100,7 +110,7 @@ pid_t spawn_shell(const char* shell, StringView cmdline,
envptrs.push_back(nullptr); envptrs.push_back(nullptr);
auto cmdlinezstr = cmdline.zstr(); auto cmdlinezstr = cmdline.zstr();
Vector<const char*> execparams = { shell, "-c", cmdlinezstr }; Vector<const char*> execparams = { "sh", "-c", cmdlinezstr };
if (not params.empty()) if (not params.empty())
execparams.push_back(shell); execparams.push_back(shell);
for (auto& param : params) for (auto& param : params)