bennetthaselton has asked for the wisdom of the Perl Monks concerning the following question:

If I have a program called foo that does something like:

Hello world. Should I continue? (y/n)
(and here the user must type 'y' and hit Enter before continuing)
Thanks!

then how would I write a perl script that launches foo, waits until it sees the line "Hello world. Should I continue? (y/n)", and automatically enters the "y" response, all while printing to stdout the output that foo is printing and the responses that the perl script is entering? Actually, how can I do it without downloading and installing any additional perl modules that don't come with the standard perl distribution? (Even if there is a specialized class that does it more elegantly, can I just do it with normal reads and writes?)

I know this must be simple, and I tried to figure it out myself, but I couldn't find any phrase to Google for that would give me the answer (e.g. "perl automate entering input", etc.)

Is it just two lines of code? I know asking people to write code for you is frowned upon, but in this case wouldn't it be faster than typing a response in English sentences? :)
  • Comment on perl code to automate launching a program and entering responses

Replies are listed 'Best First'.
Re: perl code to automate launching a program and entering responses
by Jim (Curate) on Dec 11, 2010 at 16:14 UTC

    You've ruled out CPAN modules, so Expect can't help you. But it would solve your problem for you if you'd let it.

Re: perl code to automate launching a program and entering responses
by chrestomanci (Priest) on Dec 11, 2010 at 21:16 UTC

    Why not CPAN? There are many articles around here that will tell you how to use CPAN when you think you can't so unless your boss is prohibiting you from using external libraries, then it is probably possible to use CPAN.

    Having said that, I agree that in some situations it is better to have a larger but self contained script, than a small one with a forest of dependencies.

    Back to your question. Your simplest answer is to read from the STDIN filehandle, and look for a 'Y', though that will not be as reliable or portable as using Expect.

Re: perl code to automate launching a program and entering responses
by Anonyrnous Monk (Hermit) on Dec 12, 2010 at 01:23 UTC

    Most Unix systems have a little program called "yes"1, which simply repeatedly outputs a string (by default "y\n") in order to answer questions like the one you mentioned. With that, the task essentially becomes a piped open:

    #!/usr/bin/perl -l # foo.pl print "Hello world. Should I continue? (y/n)"; my $answer = <STDIN>; print "Ok, you said $answer";
    #!/usr/bin/perl open my $foo, "yes | ./foo.pl |" or die $!; while (<$foo>) { print ": $_"; }
    $ ./876596.pl : Hello world. Should I continue? (y/n) : Ok, you said y :

    ___

    1 if you don't have it, you can trivially write it yourself...

    Update:

    Of course, if you want to actually read the questions (and only respond with 'y' to "Hello world. Should I continue?", instead of every question), you'd have to set up bidirectional communication, e.g. using IPC::Open3.

Re: perl code to automate launching a program and entering responses
by Anonymous Monk on Dec 12, 2010 at 00:00 UTC
    Is it just two lines of code?

    No, it is not just two lines of code

    I know asking people to write code for you is frowned upon, but in this case wouldn't it be faster than typing a response in English sentences? :)

    See perlipc

Re: perl code to automate launching a program and entering responses
by RedElk (Hermit) on Dec 12, 2010 at 15:14 UTC

    Here's a link that you might find helpful. Chapter 1 covers "Hello World" and program structure which, combined with the other responses to your post, should get you started on your own.

Re: perl code to automate launching a program and entering responses
by andal (Hermit) on Dec 13, 2010 at 09:41 UTC

    Assuming you are on some UNIX like system. You don't really need any CPAN modules. You can do everything "the hard way". Create 2 pipes, do fork, reopen STDOUT and STDIN of the child into appropriate pipe ends, then execute your program. Now the parent will see both STDOUT and STDIN of your program. Of course, you have to make sure, that the program does not buffer its responses, so that perl script can see them. And make sure the perl script also avoids buffering.

    Read 'perldoc perlipc' to find details and easier alternatives.