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

I am executing an unrar command:
my @unrar = ("./unrar", "e", "$file"); system(@unrar);
my problem is that, as the archive is encrypted with a password, "unrar" prompts me within the execution shell for a password in the following fashion:
Enter password (will not be echoed) for tocrack.txt:
Is there any way I can have perl pass this second $password input interactively for me?

I've tried using a second system() command and backticks `` to no avail and there is unfortunately no commandline switch that I can use to extract a file using a password with the unrar command.

In short, what can I do if a program that I execute from within my script (using system() for instance) requires an interactive response?

Is there any way I can script this?

Thanks!

Replies are listed 'Best First'.
Re: Simple (hopefully) shell/system() execution question
by Tomte (Priest) on Apr 26, 2006 at 08:04 UTC

    Have a look at Expect, it is written for exactly the situation you describe: drive an interactive program out of a perl program.

    A solution could look like (straight out of the pod):

    # if you prefer the OO mindset: my $exp = new Expect; $exp->raw_pty(1); $exp->spawn("./unrar", "e", $file); or die "Cannot spawn $command: $!\n"; # send some string there: $exp->send("PASSWORD\n");

    Edit: reworded "would something look" to "could look", added pod-reference.

    regards,
    tomte


    An intellectual is someone whose mind watches itself.
    -- Albert Camus

Re: Simple (hopefully) shell/system() execution question
by ikegami (Patriarch) on Apr 26, 2006 at 07:26 UTC
    The simplest method is
    open(PIPE, "| ./unrar e $file"); print(PIPE, $passwd);

    The problem is that the contents of $file are now subject to shell interpretation.

    IPC::Open3 (core module) and IPC::Run (better interface) can avoid that problem.

      Trying to run the above solution but am running into difficulties - I am testing my script on a .rar file I created myself but for some reason the print(PIPE $pw); command does not pass the input correctly when unrar prompts for a password...

      I know the password itself is correct - at least it prints correctly when I examine it in the array:
      #use Expect; my $tocrackrar = $ARGV[0]; my $hint = '1234'; my @wild = ('a'..'z','0'..'9'); my $wild = '{'. join(',',@wild).'}'; my @password = (<$hint$wild$wild>, <$wild$hint$wild>, <$wild$wild$hint>); my $total = 0; foreach $pw (@password) { $total++; open(PIPE, "|./unrar e $tocrackrar"); print(PIPE $pw); if(-e "./tocrack.txt") { print "$total : $pw"; exit(0); } close PIPE; }
      I guess the catch might be that I am running this via the WinXP command prompt using ActivePerl 5.8.7 (have also tried using Cygwin but I get a "Broken Pipe" before the script completes). any ideas what I could be doing wrong?

      am I using the print(PIPE $pw); incorrectly somehow? In the shell it seems as if the script is doing it's job (I see it attempt to unrar the tocrack.rar file and fail with incorrect passwords) but as I set the password for this file to be a password I know the script should hit on it's 5th loop (1234ae) I know that the print(PIPE $pw) command is not passing the password value correctly...

      I'd like to try using the Expect.pm however I cannot seem to find it for Cygwin or ActiveState - and unfortunately I haven't the privilege level to install it on the Linux servers at school:)

      Thanks!
Re: Simple (hopefully) shell/system() execution question
by blazar (Canon) on Apr 26, 2006 at 09:39 UTC

    Incidentally, while you received good, general purpose answers, for the actual situation you describe Archive::Rar may be the way to go.

    Update: now that I check it, I notice that it's just a wrapper around the cli util, so maybe it won't be that much of an advantage. In general however it's sensible to search CPAN for modules suitable for whatever task you're working on.