[Host] Return the user's shell from GetDefaultShell

LLDB handles shell expansion by running lldb-argdumper under a shell.
Currently, this is always /bin/sh on POSIX. This potentially leads to
different behavior between lldb and the user's current shell. Here's an
example of different expansions between shells:

$ /bin/bash -c 'echo -config={Options:[{key:foo_key,value:foo_value}]}'
-config={Options:[key:foo_key]} -config={Options:[value:foo_value]}

$ /bin/zsh -c 'echo -config={Options:[{key:foo_key,value:foo_value}]}'
zsh:1: no matches found: -config={Options:[key:foo_key]}

$ /bin/sh -c 'echo -config={Options:[{key:foo_key,value:foo_value}]}'
-config={Options:[key:foo_key]} -config={Options:[value:foo_value]}

$ /bin/fish -c 'echo -config={Options:[{key:foo_key,value:foo_value}]}'
-config=Options:[key:foo_key] -config=Options:[value:foo_value]

To reduce surprises, this patch returns the user's current shell. It
first looks at the SHELL environment variable. If that isn't set, it'll
ask for the user's default shell. Only if that fails, we'll fallback to
/bin/sh, which should always be available.

Differential revision: https://reviews.llvm.org/D68316

llvm-svn: 373644
This commit is contained in:
Jonas Devlieghere 2019-10-03 18:29:01 +00:00
parent 8d2eaf9239
commit f149ea8bb5
3 changed files with 34 additions and 9 deletions

View File

@ -0,0 +1 @@
int main(int argc, char const *argv[]) { return 0; }

View File

@ -0,0 +1,8 @@
# UNSUPPORTED: system-windows
# RUN: %clang %S/Inputs/simple.c -g -o %t.out
# RUN: SHELL=bogus %lldb %t.out -b -o 'run' 2>&1 | FileCheck %s --check-prefix ERROR
# RUN: env -i %lldb %t.out -b -o 'run' 2>&1 | FileCheck %s
# ERROR: error: shell expansion failed
# CHECK-NOT: error: shell expansion failed

View File

@ -52,15 +52,19 @@ protected:
};
} // namespace
llvm::Optional<std::string> PosixUserIDResolver::DoGetUserName(id_t uid) {
struct PasswdEntry {
std::string username;
std::string shell;
};
static llvm::Optional<PasswdEntry> GetPassword(id_t uid) {
#ifdef USE_GETPWUID
// getpwuid_r is missing from android-9
// UserIDResolver provides some thread safety by making sure noone calls this
// function concurrently, but using getpwuid is ultimately not thread-safe as
// we don't know who else might be calling it.
struct passwd *user_info_ptr = ::getpwuid(uid);
if (user_info_ptr)
return std::string(user_info_ptr->pw_name);
// The caller should provide some thread safety by making sure no one calls
// this function concurrently, because using getpwuid is ultimately not
// thread-safe as we don't know who else might be calling it.
if (auto *user_info_ptr = ::getpwuid(uid))
return PasswdEntry{user_info_ptr->pw_name, user_info_ptr->pw_shell};
#else
struct passwd user_info;
struct passwd *user_info_ptr = &user_info;
@ -69,12 +73,18 @@ llvm::Optional<std::string> PosixUserIDResolver::DoGetUserName(id_t uid) {
if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size,
&user_info_ptr) == 0 &&
user_info_ptr) {
return std::string(user_info_ptr->pw_name);
return PasswdEntry{user_info_ptr->pw_name, user_info_ptr->pw_shell};
}
#endif
return llvm::None;
}
llvm::Optional<std::string> PosixUserIDResolver::DoGetUserName(id_t uid) {
if (llvm::Optional<PasswdEntry> password = GetPassword(uid))
return password->username;
return llvm::None;
}
llvm::Optional<std::string> PosixUserIDResolver::DoGetGroupName(id_t gid) {
#ifndef __ANDROID__
char group_buffer[PATH_MAX];
@ -113,7 +123,13 @@ uint32_t HostInfoPosix::GetEffectiveUserID() { return geteuid(); }
uint32_t HostInfoPosix::GetEffectiveGroupID() { return getegid(); }
FileSpec HostInfoPosix::GetDefaultShell() { return FileSpec("/bin/sh"); }
FileSpec HostInfoPosix::GetDefaultShell() {
if (const char *v = ::getenv("SHELL"))
return FileSpec(v);
if (llvm::Optional<PasswdEntry> password = GetPassword(::geteuid()))
return FileSpec(password->shell);
return FileSpec("/bin/sh");
}
bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) {
return ComputePathRelativeToLibrary(file_spec, "/bin");