Ilia Rostovtsev Ilia Rostovtsev - 1 year ago 64
Perl Question

Trigger programmatically autocomplete event for shell in system call and get output

Before actual question few words about what I'm doing to grasp the idea.

I would want to add another cool feature to my Authentic Theme for Webmin.

I have made Command Shell module look/feel just if it was ordinary shell. However, as it's only a port, it has few limitations. One of them is missing shell autocomplete, when you hit

key (or other based on the system:

My point is to make it work natively. I'm going to use an

call to the server and pass the part of entered command to the actual shell. The call will be triggered on the event of the

For example, when you're in Authentic Theme dropdown shell (you could see it on the video screencast above), and when you type, let's say,
and hit
, the event will be triggered and make a request. Then the server receives a string
and we're ready to begin.

My questions are is:

1. What is the best way to execute such command in Perl?

2. How to properly escape such command to make sure that it won't be exploitable;

3. How to trigger programmatically
key (to run autocomplete) in the

4. How to grep output.

On the respond, using
as an example, I expect to get
on the results.

I'm aware about possibly of ambiguity of the passed command, for example, when using
, and when autocomplete wouldn't work on the single
key. I think it's better to exclude this from the scope of current question.

Answer Source

You can trigger generations of completions using the compgen bash builtin.

The -c option will complete command names, -o default will complete filenames through readline. See the options for complete for a list of options you can also use with compgen.

Note that system() will pass the command to /bin/sh -c, which may not be the same as bash on your system. So you can do something like:

system("/bin/bash", "-c", "compgen -c xa")
# xargs
# xattr
# etc…


system("/bin/bash", "-c", "compgen -o default file")
# file.txt
# file.pdf
# etc…

If you want to do literally the same thing that bash would do, you will need to run things through an expect script. See for example the way that bash-completion handles its test suite.

A simple script would be like:

#!/usr/bin/env expect

set prompt {@}
set cmd [lindex $argv 0]
spawn env [email protected] /bin/bash --norc
expect -re $prompt
send "$cmd\t\t"
expect -re $prompt

Calling ./script.exp string will print out the actual completions that bash will produce for string. You'll have to either improve the expect script or parse its output to get rid of the prompt, etc.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download