If you are on a Unix system, you can redirect STDIN to pull input from a file. You can also open the file a second time for appending to obtain an independent file descriptor. You can write into this descriptor to inject input into STDIN. The OS will keep track of the input and output file positions separately, effectively turning the file into a fifo queue with a history.

Using this approach, you can inject on the fly, interleave injections and reads, and also simulate EOF input conditions.

The following code, which should work back to Perl 5.6, shows one way to do it.

#! 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; } } }

Here is an example of how to use the function:

# 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 <STDIN>; # 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

I hope this helps.

Cheers,
Tom


In reply to Re: Pre-empting STDIN during Testing by tmoertel
in thread Pre-empting STDIN during Testing by jkeenan1

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.