#! perl use warnings; use strict; use File::Temp qw( tempfile ); # this function encapsulates the technique. # it returns a function that can be used to # inject input into the targeted file handle sub inject_input { my $target_fh = shift; my ($temp_fh, $temp_fn) = tempfile(); my $temp_fd = fileno $temp_fh; local *SAVED; local *TARGET = $target_fh; local *INJECT; open SAVED, "<&TARGET" or die "can't remember target"; open TARGET, "<&=$temp_fd" or die "can't redirect target"; open INJECT, "+>>$temp_fn" or die "can't open injector"; unlink $temp_fn; # we don't need the directory entry any more select((select(INJECT), $| = 1)[0]); my $saved_fh = *SAVED; my $inject_fh = *INJECT; return sub { if (@_) { print $inject_fh @_; } else { seek $inject_fh, 0, 0 or die "can't seek"; # rewind my $injected_output = do { local $/; <$inject_fh> }; close $temp_fh or die "can't close temp file handle"; local (*SAVED, *TARGET, *INJECT) = ($saved_fh, $target_fh, $inject_fh); open TARGET, "<&SAVED" or die "can't restore target"; close SAVED or die "can't close SAVED"; close INJECT or die "can't close INJECT"; return $injected_output; } } } #### # let us inject input into STDIN my $injector = inject_input(*STDIN); # the resulting injector takes a string to inject $injector->("1234\n"); # inject 1234 print "r: ", scalar ; # read 1234 back in # now we can inject 5678, a, and b # we can read them back in via a loop $injector->("5678\n"); # inject 5678 $injector->("a\n", "b\n"); # inject a and b while (<>) { print "R: $_"; } # after the read loop reaches the EOF, we # can still inject more input and read it $injector->("we're outta here\n"); print "r: ", <>; # when we are done, we call the injector with # no arguments; this will close down the injection # apparatus, restore STDIN to its pre-injection # condition, and return a copy of what was injected # for flight-recording purposes print "\n\nwe injected:\n\n", $injector->(); # now STDIN is restored print "\n\nEnter text by hand:\n"; while (<>) { print "You entered: $_"; } # actual output follows: __END__ r: 1234 R: 5678 R: a R: b r: we're outta here we injected: 1234 5678 a b we're outta here Enter text by hand: blah You entered: blah blah You entered: blah blah You entered: blah