views:

97

answers:

2

I've got a script that grabs standard input:

(code snippet)

&process_input

sub process_input {
    while(<STDIN>) {
       $log_data .= $_;
    }
}

When I run the script:

myscript.pl -param1=a -param2=b

I get stuck in this subroutine. Everything runs ok if I do:

echo "" | myscript.pl -param1=a -param2=b

Question is how do I determine if I even have a standard in put? I would have thought that while() would return false and not run, but I'm guessing it's actually waiting for you to type something in that why it's 'stuck'.

Thanks for the help :)

+14  A: 

What you want to do is check where your STDIN (STanDard INput) is coming from: another application or a terminal. In your case, it's the second option, causing a read operation to stall the process until the user inputs something. For a solution, see http://stackoverflow.com/questions/528781/how-can-i-tell-if-stdin-is-connected-to-a-terminal-in-perl.

if (-t STDIN) {
    # input attached to terminal and will probably ask user
} else {
    # input from other process
}

There's also IO::Interactive that might do better/more reliable checking.

MvanGeest
Thanks! Since the script can also be run by another application, I could do the -t option.
Ed Gl
A: 

The statement <STDIN> does not return until you press "enter" on the console. If you want to get around this, I believe that you can use IO::Handle to wrap STDIN, and call $stdin->blocking(0) to enable non-blocking IO.

JSBangs
The issue is not blocking IO, but that `<FILEHANDLE>` (which is equivalent to `readline(*FILEHANDLE)`) is looking for a line of input. It will not return until a `\n` (well, technically an instance of the input record separator `$/`) is found. It doesn't matter whether the handle is blocking or not. Also, if you use `IO::Handle`, you can simply use it's methods on existing global handles: `STDIN->blocking(0);`
daotoad