How can Perl prompt for a password without showing it in the terminal?
To use Term::ReadKey, this works:
sub prompt_for_password {
require Term::ReadKey;
# Tell the terminal not to show the typed chars
Term::ReadKey::ReadMode('noecho');
print "Type in your secret password: ";
my $password = Term::ReadKey::ReadLine(0);
# Rest the terminal to what it was previously doing
Term::ReadKey::ReadMode('restore');
# The one you typed didn't echo!
print "\n";
# get rid of that pesky line ending (and works on Windows)
$password =~ s/\R\z//;
# say "Password was <$password>"; # check what you are doing :)
return $password;
}
You can also use IO::Prompter:
$ perl -MIO::Prompter -wE '$pass = prompt("Password: ", -echo => "*"); $pass =~ s/\R\z//; say $pass'
It is probably overkill for just asking for the password, but it is useful if you need to elicit other types of user input as well. Note that you do need Term::ReadKey for the password masking function to work. Unfortunately, the module does not warn you about this at build time. You will know you are in this situation if the one-liner above generates the warning:
Warning: next input will be in plaintext
The
prompt()
subroutine was called with the -echo flag, but theTerm::ReadKey
module was not available to implement this feature. The input will proceed as normal, but this warning is issued to ensure that the user doesn't type in something secret, expecting it to remain hidden, which it won't.
How that warning message corresponds to the meaning given in the explanation is beyond me, but, oh well.
Note that on Windows the module leaves a CR
at the end of the input string which chomp
does not remove (because it is looking for a CRLF
sequence). That's why I use \R
in the example above. See RT #118255.