[comp.lang.perl] Reading from /dev/tty in forked process.

stuart@amc.com (Stuart Poulin) (05/24/91)

Warning: I'm new to perl.

My question is how do you get perl to stop and read from /dev/tty when
you have a forked process sub function that is taking its' input from
STDIN.

For example, say under sh I decide write a "Pager" function that prints
a screen full of lines then prompts the user to hit return to get to
the next screen of lines. (I'm not interested in a "Pager", I'm just
using it here as an example.)  I might write is as such:

#!/bin/sh

Pager () {
PageSize=24
LineCount=1
while read i
do
    if [ $LineCount -gt $PageSize ] 
    if [ $LineCount -gt $PageSize ] 
		LineCount=1
		echo -n "Hit return to continue: " 
		( exec < /dev/tty
		  read X
		)
	fi
	echo $i
	LineCount=`expr $LineCount + 1 `
done
}

cat data | Pager

#--------------------------------------------
I can then use "Pager" anywhere in the rest of the script to pump
output through so it doesn't roll off the screen.

Thinking along these lines I tried this perl program:

#!/usr/local/bin/perl 

sub pager {
	local($pagesize,$linecount) = (24,1);
	open(TTYIN,"</dev/tty") || die "can't open /dev/tty: $!";
	while (<>) {
		if ( $linecount >= $pagesize ) {
			print  "Hit return to continue: ";
			$ans = <TTYIN>;
			print "\n" ;
			$linecount = 1;
		}
		print ; 
		$linecount++ ;
	}
	close(TTYIN);
}


$pid = open (OUT,"|-");
if (!$pid) {
	&pager;
	exit;
} else {
	open(INPUT,"data") || die "Cannot open data ";
	while(<INPUT>) {
		print OUT $_;
	}
}

This prints out the "Hit return to continue" messages but it doesn't
wait for the return, it keeps on going.

Most likely my problem is I'm not thinking in perl yet, but I'm
tryin'.

Thanks,
	Stuart

Stuart Poulin                           DNS: stuart@amc.com
Applied Microsystems Corporation        UUCP: amc-gw!stuart
Redmond, Washington  98073              Dial: 800-ASK-4AMC,206-882-2000 

lwall@jpl-devvax.jpl.nasa.gov (Larry Wall) (05/25/91)

In article <1991May24.163027.12281@amc.com> stuart@anabol.amc.com () writes:
: Warning: I'm new to perl.
: 
: My question is how do you get perl to stop and read from /dev/tty when
: you have a forked process sub function that is taking its' input from
: STDIN.
: 
: For example, say under sh I decide write a "Pager" function that prints
: a screen full of lines then prompts the user to hit return to get to
: the next screen of lines.
: ...
: Thinking along these lines I tried this perl program:
: 
: #!/usr/local/bin/perl 
: 
: sub pager {
: 	local($pagesize,$linecount) = (24,1);
: 	open(TTYIN,"</dev/tty") || die "can't open /dev/tty: $!";
: 	while (<>) {
: 		if ( $linecount >= $pagesize ) {
: 			print  "Hit return to continue: ";
: 			$ans = <TTYIN>;
: 			print "\n" ;
: 			$linecount = 1;
: 		}
: 		print ; 
: 		$linecount++ ;
: 	}
: 	close(TTYIN);
: }
: 
: 
: $pid = open (OUT,"|-");
: if (!$pid) {
: 	&pager;
: 	exit;
: } else {
: 	open(INPUT,"data") || die "Cannot open data ";
: 	while(<INPUT>) {
: 		print OUT $_;
: 	}
: }
: 
: This prints out the "Hit return to continue" messages but it doesn't
: wait for the return, it keeps on going.

Oddly enough, it stops for me.  It only needs two things to work right
here.  First, $| = 1 so that the prompt comes out before it stops, and
a close OUT after the final loop so that the input process waits for
the pager process to finish.

As to why yours isn't stopping, I couldn't say.  P'raps your stdio thinks
TTYIN is always at EOF for some reason.  Try sysread(TTYIN, $ans, 1) and
see if it helps.

: Most likely my problem is I'm not thinking in perl yet, but I'm
: tryin'.

Looks to me like you're doin' a durn good job of thinking in Perl.

(At least, for someone from the north end of the lake...)    ;-)

Larry