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
philipp@hitchhackers.net