Philipp Traeder wrote:

Good morning everybody,

I am writing a small console application, allowing the user to perform
some actions via a shell-like interface. The basics of this were rather
easy, and with the help of some very nice CPAN modules (i.e.
Base::Shell), I have got tab-completion, a help system and much more
already.

The core of the application looks (a bit simplifid and in pseudo-code)
more or less like this:

while ("true") {
$cmd = $term->ReadLine($prompt);
if ($cmd eq "help") {
# process help
}
elsif ($cmd eq "exit"}
last;
}
# ...process other actions
}


Now I would like to be able to execute a lengthy action that takes
several minutes. I think I can execute this with a fork, allowing the
user to keep on working while the action is being executed. The
appropriate action code would look more or less like this:

# ...
elsif ($cmd eq 'long_action') {
if (!fork) {
# execute the action in the child process
sleep 10;
# TODO: notify the user that the action is finished.


            exit;
       }

}

What I would like to do is perform the action in the forked child
process, and on completion the user should get a message about the
result of the action (which would be true or false, most likely).
The result should look like this for the user:

myshell> normal_action
performing normal action...done.
myshell> long_action
initiating lengthy action....done.
myshell>                             
lenghty action completed successfully.
myshell>

Please note that the user should get back the prompt after he started
'long_action', and when the action is finished, he should be informed by
a message in the shell.

With this I have got two problems:
a) I am executing the action in a child process. What would be the best
way for the child process to inform its parent that the execution has
been finished?
b) How can I set up the ReadLine() part in a way that the user is able
to type new actions, but can receive new messages (from finished long
actions) as well? I have played around with Term::ReadKey, and ended up
with something like this:

   my ($complete, $key);
   my $string = '';
   print $prompt;
   # ask for input until we have got a complete string
   while (not $complete) {
       print "so far : $string\n";
       # read a single key
       while (not defined ($key = ReadKey(-1))) {
           # No key yet
           # $string seems to be empty here!
           print "*" . $string;
           sleep 1;
           if ($string eq 'test') {
               print "youve written nothing serious so far!\n";
               print $prompt . $string;
               $string = '';
           }
       }
       if ($key eq "\n") {
           $complete = 1;
       }
       else {
           $string .= $key;
       }
   }

This construct should theoretically more or less allow me to check for
individual keystrokes of the user and parallely to print messages if
necessary, but it does not do what I would expect: If I call
ReadKey(-1), it does not seem to "know" the $string variable in the
inner while loop, and if I call ReadKey(0), it looks like all keys are
fetched first, and afterwards the "print" statements are executed.

I hope you see my problem, though I find it hard to describe.

Can anybody give me a clue in which direction I could go with that?

Thank you very much in advance for your attention and your help.

Philipp Traeder
[EMAIL PROTECTED]












Re: (A) What's the best way for the child to inform the parent that it's done?.

I can't speak from experience on this, but I have a copy of Lincoln Stein's (He wrote the Crypt::CBC module, among others) Network Programming in Perl. Lincoln recommends the pipe() function and says (verbatim quote) "It is commonly used in conjunction with the fork() function in order to create a parent-child pair that can exchange data. The parent process keeps one filehandle open and closes the other, while the child process does the opposite. The parent and child process can now communicate across the pipe as they work in parallel."

$result = pipe(READHANDLE,WRITEHANDLE) # pipe is a core perl function doc'd in the camel book.

Sounds like what you need.

Re: (B) I'm still thinking about this one.




-- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to