Skip to content

Commit

Permalink
Use a POSIX guaranteed way of getting the shell path
Browse files Browse the repository at this point in the history
  • Loading branch information
mawww committed Dec 15, 2016
1 parent 414808c commit 9a87926
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 7 deletions.
44 changes: 37 additions & 7 deletions src/shell_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,38 @@ namespace Kakoune

ShellManager::ShellManager()
{
const char* path = getenv("PATH");
auto new_path = format("{}:{}", path, split_path(get_kak_binary_path()).first);
setenv("PATH", new_path.c_str(), 1);
// Get a guaranteed to be POSIX shell binary
{
auto size = confstr(_CS_PATH, 0, 0);
String path; path.resize(size, 0);
confstr(_CS_PATH, path.data(), size);
for (auto dir : StringView{path} | split<StringView>(':'))
{
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)
{
m_shell = std::move(candidate);
break;
}
}
if (m_shell.empty())
throw runtime_error{format("unable to find a posix shell in {}", path)};
}

// Add Kakoune binary location to the path to guarantee that %sh{ ... }
// have access to the kak command regardless of if the user installed it
{
const char* path = getenv("PATH");
auto new_path = format("{}:{}", path, split_path(get_kak_binary_path()).first);
setenv("PATH", new_path.c_str(), 1);
}
}

namespace
Expand Down Expand Up @@ -52,8 +81,10 @@ struct Pipe
};

template<typename Func>
pid_t spawn_shell(StringView cmdline, ConstArrayView<String> params,
ConstArrayView<String> kak_env, Func setup_child)
pid_t spawn_shell(const char* shell, StringView cmdline,
ConstArrayView<String> params,
ConstArrayView<String> kak_env,
Func setup_child)
{
Vector<const char*> envptrs;
for (char** envp = environ; *envp; ++envp)
Expand All @@ -62,7 +93,6 @@ pid_t spawn_shell(StringView cmdline, ConstArrayView<String> params,
envptrs.push_back(env.c_str());
envptrs.push_back(nullptr);

const char* shell = "/bin/sh";
auto cmdlinezstr = cmdline.zstr();
Vector<const char*> execparams = { shell, "-c", cmdlinezstr };
if (not params.empty())
Expand Down Expand Up @@ -129,7 +159,7 @@ std::pair<String, int> ShellManager::eval(
auto spawn_time = profile ? Clock::now() : Clock::time_point{};

Pipe child_stdin{not input.empty()}, child_stdout, child_stderr;
pid_t pid = spawn_shell(cmdline, shell_context.params, kak_env,
pid_t pid = spawn_shell(m_shell.c_str(), cmdline, shell_context.params, kak_env,
[&child_stdin, &child_stdout, &child_stderr] {
auto move = [](int oldfd, int newfd) { dup2(oldfd, newfd); close(oldfd); };

Expand Down
2 changes: 2 additions & 0 deletions src/shell_manager.hh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public:
CandidateList complete_env_var(StringView prefix, ByteCount cursor_pos) const;

private:
String m_shell;

struct EnvVarDesc { String str; bool prefix; EnvVarRetriever func; };
Vector<EnvVarDesc, MemoryDomain::EnvVars> m_env_vars;
};
Expand Down

0 comments on commit 9a87926

Please sign in to comment.