http://www.perlmonks.org/index.pl?node_id=263150

Description: It's easy to mask password entry from html forms, or if you use Tk. But here is a sub to do it from a text mode commandline.

UPDATE: Please see improved version in comment below

I left the original code so comparison can be made.

Update#2 :-) I had some extraneous lines in the code, so here is a nice concise version.

#!/usr/bin/perl
use strict;
use Term::ReadKey;

my $pwd = mask_pwd();
print "\n$pwd\n";

sub mask_pwd{
  ReadMode(3);
  my $password = '';
  print "Enter Password\n";

while(1){
      my $ord = getord();
          if ($ord == 10){last}    # "Enter"  
          if ($ord == 127) { # ie "Backspace"  
                chop($password);
                print chr(8),' ',chr(8);
                next;
          }
     if($ord == 27){clearstream();$ord="\0"}
     if($ord != "\0"){
             $password .= chr($ord);
              print '*';
     }
  }
ReadMode(0);
return $password;
}

sub getord{
   my $char;
   if (defined ($char = ReadKey(0))){}
return ord($char);
}

sub clearstream{
  while(1){
     my $char;
     if (defined ($char = ReadKey(-1)) ){}else{return}
    }
return ;
}
__END__
###########################################
##########################################
##########################################
#original version below, had problems with control keys
#############################################
=head1
#!/usr/bin/perl
use strict;
use Term::ReadKey;

my $pwd = mask_pwd();
print "\n$pwd\n";

############################## 
sub mask_pwd {
ReadMode(3);
    my $password = '';
    my $key;
    print "Enter password\n";

while (1) {
     my $key = ReadKey(0);
         if ( ord($key) == 10 ){last}    # "Enter" 
         if ( ord($key) == 127 ) { # ie "Backspace" 
                chop($password);
                print chr(8),' ',chr(8);
           }else{
             $password .= $key;
              print "*";
            }
}
ReadMode(0);
return $password;
}
=cut
comment on masking password entry
Download Code
Re: masking password entry
by zentara on Jun 05, 2003 at 20:39 UTC
    Well as usual with me, I've found glitches which need improving. :-) The above code had a big drawback: when you hit a control key, like pageup,arrowkeys,etc. it would grab 4 or 5 key signals, which would mess up the password. Filtering out the control keys was not easy. I had to use 2 subs, 1 to grab the first key signal, if it was (ord===27) then it was the start of a control sequence, and had to be filtered out by using a second sub, which just keeps reading and discarding input, until nothing is coming in.

    Also, be aware that this routine relies on the almost universal setting where backspace = delete.

    #!/usr/bin/perl
    use strict;
    use Term::ReadKey;
    
    my $pwd = mask_pwd();
    print "\n$pwd\n";
    
    sub mask_pwd{
      ReadMode(3);
      my $password = '';
      print "Enter Password\n";
    
    while(1){
          my $ord = getord();
              if ($ord == 10){last}    # "Enter"  
              if ($ord == 127) { # ie "Backspace"  
                    chop($password);
                    print chr(8),' ',chr(8);
                    next;
              }
         if($ord == 27){clearstream();$ord="\0"}
         if($ord != "\0"){
                 $password .= chr($ord);
                  print '*';
         }
      }
    ReadMode(0);
    return $password;
    }
    
    sub getord{
      ReadMode('cbreak');
      my $char;
      if (defined ($char = ReadKey(0))){
             # input was waiting and it was $char 
       }
    ReadMode('normal');  # restore normal tty settings 
    return ord($char);
    }
    
    sub clearstream{
       while(1){
          ReadMode('cbreak');
          my $char;
          #passing ReadKey() an argument of -1 to indicate not to block: 
          if (defined ($char = ReadKey(-1)) ) {
            #$char=''; # input was waiting and it was $char 
        } else {
            # no input was waiting 
             return;
            }
      ReadMode('normal');   # restore normal tty settings 
       }
    return ;
    }
    
    
 [reply]
d/l code

Back to Snippets Section