Hiding User Input
Asked Answered
F

3

8

I'm trying to get a script that works both in a native windows shell and a cygwin shell (via ssh) that prompts for and reads a password entered by the user. So far, I have tried the following methods:

  1. using Term::ReadKey and setting ReadMode to 'noecho'
    • RESULT: returns an error GetConsoleMode failed and quits
  2. using Term::ReadPassword::Win32
    • RESULT: hangs and never offers a prompt or reads input
  3. using IO::Prompt
    • RESULT: returns an error Cannot write to terminal and quits
  4. using Term::InKey
    • RESULT: returns an error Not implemented on MSWin32: The handle is invalid and quits

All of these work in a native Windows shell (command prompt or power shell), but none of them work when I'm in an ssh session to the server.

Really, that's what I'm most interested in, getting it to work in the remote ssh session.

I'm getting ssh via cygwin installed on the Windows server (2003 R2). I'm using strawberry perl and not the cygwin perl (cygwin perl breaks other perl scripts I need to run natively in Windows, not via ssh).

My best guess is that cygwin+Windows is screwing with strawberry perl enough that it can't tell what kind of environment it is in. I'm looking into alternative sshd+Windows solutions to explore this.

These are all the methods I've been able to find in my searching. Does anybody else have any other methods for hiding user input they can suggest?

Feints answered 8/3, 2011 at 23:5 Comment(3)
What do you mean 'none of them work'? Does the user not get a prompt or is the user's input not hidden?Offence
Testing from ssh session, the first method returns an error GetConsoleMode failed and quits, the second method hangs and never offers a prompt or reads input, the third method returns an error Cannot write to terminal and quits, and the fourth method returns an error Not implemented on MSWin32: The handle is invalid and quits. In a native Windows shell they all work except for the third method which returns the same error, so it's possible I'm just not invoking it correctly.Feints
Just a note: when things are compiled under cygwin a ton of UNIXish emulations is brought along with it in the linked libraries: e.g. things like the UNIXish pty interface that cygwin's sshd is using. Unfortunately, you're using a Perl that has not been compiled with the cygwin interfaces and to interface with it, you need the cygwin emulation libraries. Have you figured out why your scripts will not run using the Perl compiled under cygwin?Repute
R
1
use Term::ReadKey;
print "Please enter your artifactory user name:";
$username = <STDIN>;
chomp($username);
ReadMode('noecho'); # don't echo
print "Please enter your artifactory password:";
$password = <STDIN>;
chomp($password);
ReadMode(0); #back to normal
print "\n\n";
Robbyrobbyn answered 19/9, 2014 at 21:7 Comment(0)
S
0

I would try outputting the environment variables (%ENV) during the sessions that work, and then again during the sessions that don't. I find that, when dealing with terminal IO, you have to carefully tweak the "TERM" variable based on things like the $^O variable and $ENV{SESSIONNAME} (in Windows).

Seacock answered 9/3, 2011 at 15:22 Comment(1)
In a cygwin ssh session, TERM is set to xterm and in a native windows shell, it is set to dumb. Any suggestions there? Thanks.Feints
C
0

how about Term::ReadKey's ReadMode(4)? i've just used this in a personal project, having found the answer here

works on cygwin / win7, can't vouch for native windows shell however.

use strict;
use warnings;
use Term::ReadKey;

sub get_input {
  my $key = 0;
  my $user_input = "";

 # disable control keys and start reading keys until enter key is pressed (ascii 10)
 ReadMode(4);
 while (ord($key = ReadKey(0)) != 10)
   {
     if (ord($key) == 127 || ord($key) == 8) {
       # backspace / del was pressed.  remove last char and move cursor back one space.
       chop ($user_input);
       print "\b \b";
     } elsif (ord($key) < 32) {
         # control characters, do nothing
     } else {
         $user_input = $user_input . $key;
         print "*";
     }
   }
  ReadMode(0);
  return $user_input;
}

# variables
my $password = "";
my $username = "";

print "\nPlease input your username: ";
$username = get_input();
print "\nHi, $username\n";

print "\nPlease input your password: ";
$password = get_input();
Copybook answered 5/2, 2013 at 11:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.