#!/usr/bin/perl =head1 NAME shell_select - Wait for a given file descriptor, to be ready =head1 SYNOPSIS shell_select [-t timeout] [-r|-w fd[,fd]...]... Options: -t time timeout in seconds if still waiting -r fd,fd,... read input on these file descriptors -w fd,fd,... write data on these file descriptors -e fd,fd,... exceptional condition on these =head1 DESCRIPTION This program will wait for at least one of the given file descriptors to be ready for processing in some way, and report those that are ready, in a format that the shell can use to assigns to variables $rd_ready, $wr_ready and $ex_ready, and which the shell can parse in a case statement. It also will report the resulting $errno and its readable string $errstr. If a timout is provided it will exit even if no file descriptors are ready. Use 0 to poll. For example... # Read input from any of three sources eval $( shell_select -r 11,12,13 ) if [ "$errno" -ne 0 ]; then echo >&2 "select error: \"$errstr\" -- ABORTING" exit 10 fi case ",$rd_ready," in *,11,*) read -r -t 0 <&11 input1 ;; *,12,*) read -r -t 0 <&12 input2 ;; *,13,*) read -r -t 0 <&13 input3 ;; esac =head1 AUTHOR Anthony Thyssen 8 June 2011 A.Thyssen_AT_griffith.edu.au =cut use strict; use warnings; use FindBin; my $PROGNAME = $FindBin::Script; use IO::Select; # Perl Pod Usage Method sub Usage { eval { use Pod::Usage; pod2usage ( @_ ); }; } # convert file descriptors to IO select masks my $rd_select = new IO::Select; my $wr_select = new IO::Select; my $ex_select = new IO::Select; # Option handling... my $timeout=undef; # no timeout by default &Usage() unless @ARGV; while( $_ = shift ) { /t/ && do { $timeout = shift; next }; /r/ && do { $rd_select->add( split(/[^\d]+/, shift) ); next }; /w/ && do { $wr_select->add( split(/[^\d]+/, shift) ); next }; /e/ && do { $ex_select->add( split(/[^\d]+/, shift) ); next }; &Usage( "Unknown or Bad Option \"$_\"\n" ); } Usage( "$PROGNAME: Unknown argument \"$ARGV[0]\"\n" ) if @ARGV; # debugging #print "# Timeout = ", defined $timeout ? $timeout : "undef", "\n"; #print "# Read FD Count = ", $rd_select->count(), "\n"; #print "# Read FD List = ", join(", ", $rd_select->handles()), "\n"; #print "# Write FD Count = ", $wr_select->count(), "\n"; #print "# Write FD List = ", join(", ", $wr_select->handles()), "\n"; #print "# Excpt FD Count = ", $ex_select->count(), "\n"; #print "# Excpt FD List = ", join(", ", $ex_select->handles()), "\n"; my ($rd_ready, $wr_ready, $ex_ready ) = IO::Select->select( $rd_select, $wr_select, $ex_select, $timeout); print "rd_ready='", defined $rd_ready ? join(",", @$rd_ready ) : "", "'\n" if $rd_select->count; print "wr_ready='", defined $wr_ready ? join(",", @$wr_ready ) : "", "'\n" if $wr_select->count; print "ex_ready='", defined $ex_ready ? join(",", @$ex_ready ) : "", "'\n" if $ex_select->count; # error report # typically "Bad file descriptor" (9) when given file desc is closed print "errno=", $!+0, "\n"; print "errstr='$!'\n"; exit $!;