Subject: | more flexible handling of password input |
I have a script where I open two password files, use Crypt::Pwsafe to
decrypt them, perform a "diff" on the two, then pipe the result to
another program which colorizes diff-syntax output.
Attached is a patch which adds the following features that I found
necessary:
- accepts a file handle or name (v1.2 only accepts a name)
- accepts a custom user prompt as an argument to enter_combination
- prints user prompt to STDERR rather than STDOUT
- uses standard POSIX module rather than Term::ReadKey
- restores terminal to normal state on SIGINT/__DIE__ (Ctrl-C)
You might also want to remove Term::ReadKey from the prerequisites,
although I didn't need to do that over here. :)
Subject: | io.patch |
diff '--exclude=CVS' -wur Crypt/Pwsafe.pm Crypt/Pwsafe.pm
--- Crypt/Pwsafe.pm 2011-08-16 11:59:04.234375000 -0700
+++ Crypt/Pwsafe.pm 2011-03-06 20:16:41.893250000 -0800
@@ -11,8 +11,8 @@
use strict;
use FileHandle;
-use Term::ReadKey; # comment me out
-#use autouse Term::ReadKey;
+use POSIX qw(:termios_h);
+
my $SHA = "Digest::SHA";
eval "use $SHA";
if ($@) { $SHA .= "::PurePerl"; eval "use $SHA" }
@@ -97,7 +97,7 @@
sub new {
my ($class, $file, $pw) = @_;
- my $fh = new FileHandle $file;
+ my $fh = ref( $file ) eq 'GLOB' ? $file : new FileHandle $file;
die "Failed to open $file\n" unless defined $fh;
$pw = enter_combination() unless defined $pw;
my $header;
@@ -243,13 +244,24 @@
}
sub enter_combination {
- print "Enter password safe combination: ";
- local $SIG{__DIE__} = { ReadMode 0 };
- ReadMode 2;
- my $pass = <STDIN>;
- ReadMode 0;
- chomp($pass);
- print "\n";
+ my ($prompt) = @_;
+
+ my $termios = POSIX::Termios->new;
+ my $stdin = fileno STDIN;
+ $termios->getattr($stdin);
+ my $flag = $termios->getlflag;
+ my $reset = sub {
+ $termios->setlflag($flag);
+ $termios->setattr($stdin);
+ exit @_ if @_;
+ };
+ print STDERR ($prompt or "Enter password safe combination: ");
+ local $SIG{'INT'} = local $SIG{__DIE__} = $reset;
+ $termios->setlflag($flag & ~(ECHO|ECHOK|ICANON));
+ $termios->setattr($stdin);
+ chomp(my $pass = <STDIN>);
+ $reset->();
+ print STDERR "\n";
return $pass;
}