conradkleinespel / rpassword

Cross platform Rust library to read a password in the terminal (Linux, BSD, OSX, Windows, WASM).
Apache License 2.0
244 stars 38 forks source link

Windows and Bash #27

Closed longshorej closed 5 years ago

longshorej commented 5 years ago

Hi! Thanks for rpassword! Currently using it in a cross-platform CLI application.

When on Windows, using cmd or Powershell, all is well. Similarly, macOS and GNU/Linux with bash work fine.

When running on Windows via bash, e.g. Git Bash, calls to read_password_from_stdin fail because there's no Windows console available.

I've used the following really hacky workaround, but I'm curious if you have any ideas for a better solution. I did try enabling the Unix module when compiling rpassword on Windows, but libc for Windows naturally doesn't implement many of the required functions or constants, e.g. tcsetattr, so it fails to compile.

Here's the hack which spawns bash to read the password, for anyone else that may be stuck on this issue:

            #[cfg(windows)]
            let windows_git_bash_shell = env::var("SHELL").unwrap_or_default();

            #[cfg(not(windows))]
            let windows_git_bash_shell = "".to_string();

            if windows_git_bash_shell.ends_with("bash.exe") {
                // For some reason, this fails unless read is done twice.
                let password = Command::new(windows_git_bash_shell)
                    .stdin(Stdio::inherit())
                    .arg("-c")
                    .arg("{ read -s password || read -s password; } && echo -n \"$password\"")
                    .output()
                    .ok()
                    .and_then(|output| str::from_utf8(&output.stdout).ok().map(|s| s.to_string()))
                    .unwrap_or_default();

                self.output("\r\n");

                password
            } else {
                rpassword::read_password().unwrap_or_default()
            }
}
conradkleinespel commented 5 years ago

@longshorej Would you mind trying out the latest version on the master branch (not yet published on crates.io) with the new read_password_from_tty function ?

You can find an example for how to add a Git repo as a dependency here: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories

Basically:

[dependencies]
rand = { git = "https://github.com/rust-lang-nursery/rand" }
longshorej commented 5 years ago

Sorry for the slow response @conradkdotcom. To confirm, yes, this happens on master.

conradkleinespel commented 5 years ago

@longshorej Hmm, OK. As far as I know, not every version of Windows comes bundled with bash, right ? If this is correct, how could we fix this so that it works both with Windows without Bash and Windows with Bash ? Else, I'm totally fine with just using that you've suggested here. Basically, as long as stuff works for everyone, let's do it ! :+1:

conradkleinespel commented 5 years ago

Hello @longshorej ! Are you still interested in getting this fixed ? Otherwise, I'll have to close this issue, as unfortunately, I don't have time to invest in Windows support for this.

longshorej commented 5 years ago

I'll close it - the workaround above has us moving forward. I don't think that should belong in library code though, better to keep the hacks in the applications :smile: