From d1274836cd8f3d3f82759b9c797a8d01f2d4c7c2 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 27 Nov 2018 22:21:20 +1100 Subject: [PATCH] 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 --- src/shell_manager.cc | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/shell_manager.cc b/src/shell_manager.cc index be8a8b2f..e774eb33 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -28,22 +28,32 @@ namespace Kakoune ShellManager::ShellManager(ConstArrayView 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); String path; path.resize(size-1, 0); confstr(_CS_PATH, path.data(), size); for (auto dir : StringView{path} | split(':')) { - String candidate = format("{}/sh", dir); - struct stat st; - 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) + auto candidate = format("{}/sh", dir); + if (is_executable(candidate)) { m_shell = std::move(candidate); break; @@ -100,7 +110,7 @@ pid_t spawn_shell(const char* shell, StringView cmdline, envptrs.push_back(nullptr); auto cmdlinezstr = cmdline.zstr(); - Vector execparams = { shell, "-c", cmdlinezstr }; + Vector execparams = { "sh", "-c", cmdlinezstr }; if (not params.empty()) execparams.push_back(shell); for (auto& param : params)