mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-03-11 13:23:06 +01:00
On MacOS allow UserShell to override /bin/bash (#137)
* switch emain to using the bash from PATH, not defaulting to /bin/bash. not convinced this fixes #132 yet because the PATH set for MacOS applications is not set from .bash_profile or .zprofile. those seem to be set with launchctl setenv. * move MacUserShell() func to shexec. use dscl UserShell output as bash path on MacOS when present. fixes #132
This commit is contained in:
parent
3b65e9941a
commit
8200a312b9
@ -547,7 +547,7 @@ function runWaveSrv() {
|
||||
envCopy[WaveDevVarName] = "1";
|
||||
}
|
||||
console.log("trying to run local server", getWaveSrvPath());
|
||||
let proc = child_process.spawn("/bin/bash", ["-c", getWaveSrvCmd()], {
|
||||
let proc = child_process.spawn("bash", ["-c", getWaveSrvCmd()], {
|
||||
cwd: getWaveSrvCwd(),
|
||||
env: envCopy,
|
||||
});
|
||||
|
@ -150,7 +150,7 @@ func runSingleCompGen(cwd string, compType string, prefix string) ([]string, boo
|
||||
return nil, false, fmt.Errorf("invalid compgen type '%s'", compType)
|
||||
}
|
||||
compGenCmdStr := fmt.Sprintf("cd %s; compgen -A %s -- %s | sort | uniq | head -n %d", shellescape.Quote(cwd), shellescape.Quote(compType), shellescape.Quote(prefix), packet.MaxCompGenValues+1)
|
||||
ecmd := exec.Command("bash", "-c", compGenCmdStr)
|
||||
ecmd := exec.Command(shexec.GetLocalBashPath(), "-c", compGenCmdStr)
|
||||
outputBytes, err := ecmd.Output()
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("compgen error: %w", err)
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"os/signal"
|
||||
"os/user"
|
||||
"path"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -52,6 +53,8 @@ const RtnStateFdNum = 20
|
||||
const ReturnStateReadWaitTime = 2 * time.Second
|
||||
|
||||
const GetStateTimeout = 5 * time.Second
|
||||
const RemoteBashPath = "bash"
|
||||
const DefaultMacOSShell = "/bin/bash"
|
||||
|
||||
const BaseBashOpts = `set +m; set +H; shopt -s extglob`
|
||||
|
||||
@ -62,7 +65,7 @@ var LocalBashMajorVersionOnce = &sync.Once{}
|
||||
var LocalBashMajorVersion = ""
|
||||
|
||||
var GetShellStateCmds = []string{
|
||||
`echo bash v${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}.${BASH_VERSINFO[2]};`,
|
||||
ShellVersionCmdStr + ";",
|
||||
`pwd;`,
|
||||
`declare -p $(compgen -A variable);`,
|
||||
`alias -p;`,
|
||||
@ -101,6 +104,7 @@ func MakeInstallCommandStr() string {
|
||||
return strings.ReplaceAll(InstallCommandFmt, "[%VERSION%]", semver.MajorMinor(base.MShellVersion))
|
||||
}
|
||||
|
||||
// TODO fix bash path in these constants
|
||||
const RunCommandFmt = `%s`
|
||||
const RunSudoCommandFmt = `sudo -n -C %d bash /dev/fd/%d`
|
||||
const RunSudoPasswordCommandFmt = `cat /dev/fd/%d | sudo -k -S -C %d bash -c "echo '[from-mshell]'; exec %d>&-; bash /dev/fd/%d < /dev/fd/%d"`
|
||||
@ -179,6 +183,16 @@ type ShExecUPR struct {
|
||||
UPR packet.UnknownPacketReporter
|
||||
}
|
||||
|
||||
func GetLocalBashPath() string {
|
||||
if runtime.GOOS == "darwin" {
|
||||
macShell := GetMacUserShell()
|
||||
if strings.Index(macShell, "bash") != -1 {
|
||||
return shellescape.Quote(macShell)
|
||||
}
|
||||
}
|
||||
return "bash"
|
||||
}
|
||||
|
||||
func GetShellStateCmd() string {
|
||||
return strings.Join(GetShellStateCmds, ` printf "\x00\x00";`)
|
||||
}
|
||||
@ -320,7 +334,7 @@ func MakeDetachedExecCmd(pk *packet.RunPacketType, cmdTty *os.File) (*exec.Cmd,
|
||||
if state == nil {
|
||||
state = &packet.ShellState{}
|
||||
}
|
||||
ecmd := exec.Command("bash", "-c", pk.Command)
|
||||
ecmd := exec.Command(GetLocalBashPath(), "-c", pk.Command)
|
||||
if !pk.StateComplete {
|
||||
ecmd.Env = os.Environ()
|
||||
}
|
||||
@ -525,7 +539,7 @@ func (opts SSHOpts) MakeSSHExecCmd(remoteCommand string) *exec.Cmd {
|
||||
if homeDir == "" {
|
||||
homeDir = "/"
|
||||
}
|
||||
ecmd := exec.Command("bash", "-c", remoteCommand)
|
||||
ecmd := exec.Command(GetLocalBashPath(), "-c", remoteCommand)
|
||||
ecmd.Dir = homeDir
|
||||
return ecmd
|
||||
} else {
|
||||
@ -552,7 +566,7 @@ func (opts SSHOpts) MakeSSHExecCmd(remoteCommand string) *exec.Cmd {
|
||||
}
|
||||
// note that SSHOptsStr is *not* escaped
|
||||
sshCmd := fmt.Sprintf("ssh %s %s %s %s", strings.Join(moreSSHOpts, " "), opts.SSHOptsStr, shellescape.Quote(opts.SSHHost), shellescape.Quote(remoteCommand))
|
||||
ecmd := exec.Command("bash", "-c", sshCmd)
|
||||
ecmd := exec.Command(RemoteBashPath, "-c", sshCmd)
|
||||
return ecmd
|
||||
}
|
||||
}
|
||||
@ -1141,9 +1155,9 @@ func RunCommandSimple(pk *packet.RunPacketType, sender *packet.PacketSender, fro
|
||||
rcFileName = fmt.Sprintf("/dev/fd/%d", rcFileFdNum)
|
||||
}
|
||||
if pk.UsePty {
|
||||
cmd.Cmd = exec.Command("bash", "--rcfile", rcFileName, "-i", "-c", pk.Command)
|
||||
cmd.Cmd = exec.Command(GetLocalBashPath(), "--rcfile", rcFileName, "-i", "-c", pk.Command)
|
||||
} else {
|
||||
cmd.Cmd = exec.Command("bash", "--rcfile", rcFileName, "-c", pk.Command)
|
||||
cmd.Cmd = exec.Command(GetLocalBashPath(), "--rcfile", rcFileName, "-c", pk.Command)
|
||||
}
|
||||
if !pk.StateComplete {
|
||||
cmd.Cmd.Env = os.Environ()
|
||||
@ -1582,7 +1596,7 @@ func GetShellState() (*packet.ShellState, error) {
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), GetStateTimeout)
|
||||
defer cancelFn()
|
||||
cmdStr := BaseBashOpts + "; " + GetShellStateCmd()
|
||||
ecmd := exec.CommandContext(ctx, "bash", "-l", "-i", "-c", cmdStr)
|
||||
ecmd := exec.CommandContext(ctx, GetLocalBashPath(), "-l", "-i", "-c", cmdStr)
|
||||
outputBytes, err := runSimpleCmdInPty(ecmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -1625,3 +1639,40 @@ func GetLocalBashMajorVersion() string {
|
||||
})
|
||||
return LocalBashMajorVersion
|
||||
}
|
||||
|
||||
var userShellRegexp = regexp.MustCompile(`^UserShell: (.*)$`)
|
||||
|
||||
var cachedMacUserShell string
|
||||
var macUserShellOnce = &sync.Once{}
|
||||
|
||||
func GetMacUserShell() string {
|
||||
if runtime.GOOS != "darwin" {
|
||||
return ""
|
||||
}
|
||||
macUserShellOnce.Do(func() {
|
||||
cachedMacUserShell = internalMacUserShell()
|
||||
})
|
||||
return cachedMacUserShell
|
||||
}
|
||||
|
||||
// dscl . -read /User/[username] UserShell
|
||||
// defaults to /bin/bash
|
||||
func internalMacUserShell() string {
|
||||
osUser, err := user.Current()
|
||||
if err != nil {
|
||||
return DefaultMacOSShell
|
||||
}
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancelFn()
|
||||
userStr := "/Users/" + osUser.Username
|
||||
out, err := exec.CommandContext(ctx, "dscl", ".", "-read", userStr, "UserShell").CombinedOutput()
|
||||
if err != nil {
|
||||
return DefaultMacOSShell
|
||||
}
|
||||
outStr := strings.TrimSpace(string(out))
|
||||
m := userShellRegexp.FindStringSubmatch(outStr)
|
||||
if m == nil {
|
||||
return DefaultMacOSShell
|
||||
}
|
||||
return m[1]
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"regexp"
|
||||
"runtime"
|
||||
@ -39,7 +38,6 @@ const WaveAppPathVarName = "WAVETERM_APP_PATH"
|
||||
const WaveVersion = "v0.5.1"
|
||||
const WaveAuthKeyFileName = "waveterm.authkey"
|
||||
const MShellVersion = "v0.3.0"
|
||||
const DefaultMacOSShell = "/bin/bash"
|
||||
|
||||
var SessionDirCache = make(map[string]string)
|
||||
var ScreenDirCache = make(map[string]string)
|
||||
@ -379,30 +377,3 @@ func MacOSRelease() string {
|
||||
})
|
||||
return osRelease
|
||||
}
|
||||
|
||||
var userShellRegexp = regexp.MustCompile(`^UserShell: (.*)$`)
|
||||
|
||||
// dscl . -read /User/[username] UserShell
|
||||
// defaults to /bin/bash
|
||||
func MacUserShell() string {
|
||||
osUser, err := user.Current()
|
||||
if err != nil {
|
||||
log.Printf("error getting current user: %v\n", err)
|
||||
return DefaultMacOSShell
|
||||
}
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancelFn()
|
||||
userStr := "/Users/" + osUser.Name
|
||||
out, err := exec.CommandContext(ctx, "dscl", ".", "-read", userStr, "UserShell").CombinedOutput()
|
||||
if err != nil {
|
||||
log.Printf("error executing macos user shell lookup: %v %q\n", err, string(out))
|
||||
return DefaultMacOSShell
|
||||
}
|
||||
outStr := strings.TrimSpace(string(out))
|
||||
m := userShellRegexp.FindStringSubmatch(outStr)
|
||||
if m == nil {
|
||||
log.Printf("error in format of dscl output: %q\n", outStr)
|
||||
return DefaultMacOSShell
|
||||
}
|
||||
return m[1]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user