I did something like this:
our $stdin;
our $origMode;
our $isWindows = 0;
eval q{
use Win32::Console
$stdin = new Win32::Console STD_INPUT_HANDLE;
$origMode = $stdin->Mode();
$isWindows = 1;
};
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;
}
Not quite foolproof, but it was sufficient for me. As you can see, I got this working (good enough) on both unix and windows - but never tried Mac, mainframes, or PDAs. YMMV.