3

I want to write a script in perl that will define a value for a variable say "10". Then, it will ask user to enter the value through STDIN for that variable. If user, enters the value within a fixed TIME INTERVAL, then take that value, else continue the program by taking that default value of 10.

I had no idea how to do that. I thought of some thing like this.. $t=120 (for 120 seconds) decrease value of "$t" with every second, if user enters some value then come out of loop, and continue, else when $t becomes 0, take default value and continue. But, i dont have any idea of how can i decrease value of variable with time along with asking user for input.

I can do this, decrease value of variable with time, but within that, i am not able to take input.

Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • 1
    You should setup a timeout signal. Read this related article: http://stackoverflow.com/questions/2423288/ways-to-do-timeouts-in-perl Regards, – user1126070 Jun 29 '12 at 05:49

3 Answers3

4

Here's a simple example of how you might do it with an alarm signal.

use strict;
use warnings;

my $input = eval {
    my $tmp;

    # this sub will be called after the timeout set by the alarm below
    local $SIG{ALRM} = sub {
        print "timeout - using default value 10\n";
        $tmp = 10;
    };

    print "enter input: ";
    alarm 10;    # wait for 10 secs
    $tmp = <>;
    alarm 0;     # turn off alarm if we got input within 10 secs
    $tmp;
};

print "the value is: $input\n";
friedo
  • 65,762
  • 16
  • 114
  • 184
  • Why is the eval necessary? Nothing `die()`s. – pilcrow Jun 29 '12 at 18:29
  • That's true; just force-of-habit when writing alarms I guess. – friedo Jun 29 '12 at 20:00
  • This doesn't quite work. Perl will *restart* the interrupted read, meaning a line of input is required to advance execution even after the `alarm()` fires. (I suspect the reason you `eval`d this "out of habit" is because one correct technique is to `die` in the ALRM handler, avoiding the restart.) If you set `$tmp` to something other than a number in your ALRM handler (e.g., `$tmp = "timeout"`), you'll see that this techique doesn't work at all. The reason it appears to work with a numeric assignment is because of a [thorny bug](https://rt.perl.org/rt3/Public/Bug/Display.html?id=113906). – pilcrow Jul 02 '12 at 00:45
1

You can also accomplish this with IO::Select

use strict;
use IO::Select;

my $value = 10;
my $obj = IO::Select->new(\*STDIN);
foreach my $hand ($obj->can_read(2)) {
    $value = <$hand> ;
}
print "value is :$value:\n" ;
tuxuday
  • 2,977
  • 17
  • 18
1

I think you're looking for Prompt::Timeout.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339