X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FPTY.pm;h=e433c4ec442a6cfdd1fae24e242ce1432215b760;hp=51c7630b831c79ab493ef239835313debe18053a;hb=e97f807c388c10250f442b1f16c5315df2ffc2af;hpb=a0f008cd1068474d35c94f5999c06fe8ae2f5a94 diff --git a/src/PVE/PTY.pm b/src/PVE/PTY.pm index 51c7630..e433c4e 100644 --- a/src/PVE/PTY.pm +++ b/src/PVE/PTY.pm @@ -165,6 +165,76 @@ 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); + last if $ord == 4; # ^D / EOF + if ($ord == 0xA || $ord == 0xD) { + # newline, we're done + syswrite($outfd, "\r\n", 2); + last; + } elsif ($ord == 3) { # ^C + die "password input aborted\n"; + } 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; +} + +sub get_confirmed_password { + my $pw1 = read_password('Enter new password: '); + my $pw2 = read_password('Retype new password: '); + die "passwords do not match\n" if $pw1 ne $pw2; + return $pw1; +} + # Class functions sub new {