From 140642513383dfcebe381761c19b6d6c871bbe2b Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Fri, 24 Nov 2017 10:56:15 +0100 Subject: [PATCH] pty: add read_password helper Short helper which doesn't need readline and/or deal with history cleanup. Signed-off-by: Wolfgang Bumiller --- src/PVE/PTY.pm | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/PVE/PTY.pm b/src/PVE/PTY.pm index 51c7630..1178ea7 100644 --- a/src/PVE/PTY.pm +++ b/src/PVE/PTY.pm @@ -165,6 +165,66 @@ sub tcsetsize($$$) { or die "failed to set window size: $!\n"; } +sub read_password(;$$) { + my ($query, $infd, $outfd) = @_; + + my $password = ''; + + $infd //= \*STDIN; + + if (!-t $infd) { # Not a terminal? Then just get a line... + local $/ = "\n"; + $password = <$infd>; + die "EOF while reading password\n" if !defined $password; + chomp $password; # Chop off the newline + return $password; + } + + $outfd //= \*STDOUT; + + # Raw read loop: + my $old_termios; + $old_termios = tcgetattr($infd); + my $raw_termios = {%$old_termios}; + cfmakeraw($raw_termios); + tcsetattr($infd, $raw_termios); + eval { + my $echo = undef; + my ($ch, $got); + syswrite($outfd, $query, length($query)); + while (($got = sysread($infd, $ch, 1))) { + my ($ord) = unpack('C', $ch); + if ($ord == 0xD) { + # newline, we're done + syswrite($outfd, "\r\n", 2); + last; + } elsif ($ord == 0x7f) { + # backspace - if it's the first key disable + # asterisks + $echo //= 0; + if (length($password)) { + chop $password; + syswrite($outfd, "\b \b", 3); + } + } elsif ($ord == 0x09) { + # TAB disables the asterisk-echo + $echo = 0; + } else { + # other character, append to password, if it's + # the first character enable asterisks echo + $echo //= 1; + $password .= $ch; + syswrite($outfd, '*', 1) if $echo; + } + } + die "read error: $!\n" if !defined($got); + }; + my $err = $@; + tcsetattr($infd, $old_termios); + die $err if $err; + return $password; +} + # Class functions sub new { -- 2.39.2