Here's how I did it - for both unix and windows at the same time. Although I relied on Term::ReadKey on unix as BrowserUk suggests, I didn't rely on it in Windows. This probably could be extended to use stty "junk" on Unix if Term::ReadKey isn't available.
# global...
our $stdin;
our $origMode;
our $isWindows = 0;
eval q{
use Win32::Console
$stdin = new Win32::Console STD_INPUT_HANDLE;
$origMode = $stdin->Mode();
$isWindows = 1;
};
# and the actual sub for getting the password:
sub getPassword
{
my $pr;
my $required;
if (@_)
{
$pr = shift || "Password";
$required = shift || undef;
}
else
{
$pr = "Password";
$required = 1;
}
my $password;
until ($password)
{
print $pr, ": ";
# if we don't have Term::ReadKey, skip it.
my $isReadmode = 0;
eval q{
use Term::ReadKey;
ReadMode(2);
$isReadmode = 1;
};
# if that didn't work, try Windows.
eval q{
$stdin->Mode(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT |
+ENABLE_MOUSE_INPUT);
} if $@ and $isWindows;
chomp($password = <STDIN>);
if ($isReadmode)
{
eval {
ReadMode(0);
print "\n"; # only needed if readmode was successful.
};
}
elsif ($isWindows)
{
$stdin->Mode($origMode);
}
last unless $required; # if not required, just skip checks.
unless (length ($password) > 5)
{
$password = undef;
print "Too short. ";
next;
}
}
$password;
}
I'm sure it could be cleaned up further, but I stopped working on this years ago.
Update: You might find more help here. Similar question posed a few months ago. Where I seemed to have posted exactly the same answer. Hmmm. :-) |