Home: Perl Programming Help: Frequently Asked Questions:
How can I tell if there's a character waiting on a


Jan 26, 2001, 10:38 AM

Views: 3227
How can I tell if there's a character waiting on a

(From the Perl FAQ)

How can I tell if there's a character waiting on a filehandle?

The very first thing you should do is look into getting the Term::ReadKey extension from CPAN. It now even has limited support for closed, proprietary (read: not open systems, not POSIX, not Unix, etc) systems.

You should also check out the Frequently Asked Questions list in comp.unix.* for things like this: the answer is essentially the same. It's very system dependent. Here's one solution that works on BSD systems:

    sub key_ready { 
my($rin, $nfd);
vec($rin, fileno(STDIN), 1) = 1;
return $nfd = select($rin,undef,undef,0);

If you want to find out how many characters are waiting, there's also the FIONREAD ioctl call to be looked at.

The h2ph tool that comes with Perl tries to convert C include files to Perl code, which can be required. FIONREAD ends up defined as a function in the sys/ioctl.ph file:

    require 'sys/ioctl.ph'; 

$size = pack("L", 0);
ioctl(FH, FIONREAD(), $size) or die "Couldn't call ioctl: $!\n";
$size = unpack("L", $size);

If h2ph wasn't installed or doesn't work for you, you can grep the include files by hand:

    % grep FIONREAD /usr/include/*/* 
/usr/include/asm/ioctls.h:#define FIONREAD 0x541B

Or write a small C program using the editor of champions:

    % cat > fionread.c 
#include <sys/ioctl.h>
main() {
printf("%#08x\n", FIONREAD);
% cc -o fionread fionread
% ./fionread

And then hard-code it, leaving porting as an exercise to your successor.

    $FIONREAD = 0x4004667f;         # XXX: opsys dependent 

$size = pack("L", 0);
ioctl(FH, $FIONREAD, $size) or die "Couldn't call ioctl: $!\n";
$size = unpack("L", $size);

FIONREAD requires a filehandle connected to a stream, meaning sockets, pipes, and tty devices work, but not files.