10

I was playing with a perl script that takes user input with the following:

system( qw( stty -echo ) );
$? == 0 or die "Error unable to disable character printing.\n";
print "$prompt: ";
my $input = <STDIN>;

I thought I would be able to pipe in a response using echo however it seems to conflict with the stty -echo command and produces the following error:

stty: standard input: Inappropriate ioctl for device

Without changing the perl script what could be done in bash to pass in the input? What causes the problem?

2

2 Answers 2

5

stty -echo changes the settings on the input file descriptor. If you're piping something to the stty command, then the input file descriptor is the pipe, and stty on a pipe is, eh, inappropriate (like the error message says).

It's unclear what you're trying to achieve. If you want to send the text test to your perl script to be read in the my $input = <STDIN>; line, then simply get rid of the stty stuff.

If you also want to read the text as user input (i.e. typed in) and while doing that prevent the text being echoed (e.g. a password) then test whether standard input is a tty (terminal) before doing the stty:

system( qw( stty -echo ) ) if -t 0;

That said, don't shell out for all sorts of things, that's not what perl is for (otherwise you might as well write the whole thing in shell). You can change stty settings from within perl, google is your friend.

2
  • It wasn't my script so I was looking for ways to pass input and automate it without changing it. Expect is probably the solution, I thought there might have been a another way to pipe things in. Sep 27, 2014 at 9:45
  • system( qw( stty -echo < /dev/tty) ); is a possible workaround, but the script needs to restore the echo afterwards. Using expect may be a better fit. Sep 27, 2014 at 10:15
3

stty connects to the terminal on its standard input. You need to run the Perl script with its standard input connected to the terminal that you want to act on. If the Perl script is itself invoked from a scope where standard input is redirected to something other than the terminal, you can use /dev/tty to refer to the process's controlling terminal:

that_perl_script </dev/tty

If you want to be able to pass input to the script, and you don't care about what the script does with the terminal settings, you can use expect. Using expect to feed a password to a command that requires a terminal is common.

If the Perl script only accesses the terminal by calling the stty command, an alternative approach would be to provide a dummy stty command.

mkdir dummy-stty
echo '#!/bin/sh' >dummy-stty/stty
chmod a+rx dummy-stty/stty
echo swordfish | PATH=$PWD/dummy-stty:$PATH that_perl_script

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .