Hello,
I'm developing a webmin module for arp-scan. If you're not familiar with
webmin, it's a web interface to linux/unix administration. The first
release was some time around 1995, right after or around when Perl 5 was
released. Webmin is programmed in Perl 5 and is basically a web server
and collection of CGI scripts in Perl. Modules can be developed in Perl
that perform various linux/unix functions, and make use of the webmin API,
basically a collection of perl functions, to easily accomplish a user
interface.
The problem I am facing right now is that webmin doesn't use packages or
classes (it is not object-oriented). Instead, API functions and variables
are customarily accessed with 'do' or 'require', and variables are global
accross files. Local variables in the modules I've looked at are
generally declared with 'local' insteady of 'my' (meaning they have
dynamic scope rather than lexical scope), and many files have 'use vars
qw()' instead of 'our'. I am guessing that it was coded before 'my' was
part of Perl, when packages were just starting to be used, and when
object-oriented programming was all but unheard of in Perl, and it has not
been overhauled and updated (perhaps because that's an overwhelming task
or because it would break against deployments or third-party modules).
My question is, how do I access these library functions and global
variables in my module? Do I have any choice but to follow the example of
the other modules? Can I somehow act like these library functions and
global variables exist in packages somewhere?
Here is an example from a typical module. It's the file 'log_parser.pl'
in the module 'shell' which basically acts like a command line. This is
the complete file:
# log_parser.pl
# Functions for parsing this module's logs
do 'shell-lib.pl';
# parse_webmin_log(user, script, action, type, object, ¶ms)
# Converts logged information from this module into human-readable form
sub parse_webmin_log
{
local ($user, $script, $action, $type, $object, $p) = @_;
if ($action eq "run") {
return &text('log_run', "<tt>$p->{'cmd'}</tt>");
}
elsif ($action eq "clear") {
return $text{'log_clear'};
}
}
That's it. Here's another example, the beginning of index.cgi in the same
module, which is run when the user tries to access the module through the
webmin web interface.
#!/usr/bin/perl
# index.cgi
# Show the shell user interface
require './shell-lib.pl';
%access = &get_module_acl();
&ReadParseMime() if ($ENV{'REQUEST_METHOD'} ne 'GET');
&ui_print_header(undef, $text{'index_title'}, "", undef,
$module_info{'usermin'} ? 0 : 1, 1,
undef, undef, undef,
"onLoad='window.scroll(0, 10000); document.forms[0].cmd.focus()'");
$prevfile = "$module_config_directory/previous.$remote_user";
if ($in{'clearcmds'}) {
&lock_file($prevfile);
unlink($prevfile);
&unlock_file($prevfile);
&webmin_log("clear");
}
else {
open(PREVFILE, $prevfile);
chop(@previous = <PREVFILE>);
close(PREVFILE);
}
$cmd = $in{'doprev'} ? $in{'pcmd'} : $in{'cmd'};
The file continues, but I'm stopping it there for brevity. Any
suggestions? Thanks for your help and advice.
Regards,
John Refior