Functions in Other Modules
The standard Webmin modules contain a vast number of useful functions for parsing and manipulating the configuration files for Apache, BIND, Unix Users and so on. If your module needs to configure these servers as well in some way, it makes sense to make use of existing functions in the standard modules.Because the standard modules have typically already been configured with the correct paths for files like httpd.conf and squid.conf, their functions will use those paths when you call them to read and write configuration files. The actual %config settings for another module can also be accessed, so that your module knows what commands to use to apply changes to or start some server like Apache or Squid.
When you first load the library for some other module with the foreign_require function, it is actually executed in a separate Perl module namespace. All of your module's CGI programs and its library will be in the main namespace, but other foreign module's functions will be put in a namespace with the same name as the Webmin module. This means that you can call those functions with code like &useradmin::list_users(), and access global variables like $useradmin::config{'passwd_file'}. This Perl namespace separation ensures that functions and globals with the same names can exist in both your and the foreign module, without any clashes. Some things are shared between all modules though, such as caches used by get_system_hostname, load_language, read_file_cached and get_all_module_infos, so that loading the library of a new module with foreign_require is not too slow.
The only way to find out which functions are available in other modules is to read the source code of their CGI programs and libraries. Unfortunately there is no documentation at the moment as to what the functions do, apart from maybe some comments in the source code. You will also find that not every feature of another module is accessible though its functions - for example, the Apache module does not have a function for applying the current configuration. Instead, this is done by the restart.cgi script, which runs the appropriate commands directly.
Probably the most useful module for others to make use of is Running Processes, as it contains several functions for starting processes in the background. Many of the standard modules make use of them, which is why Running Processes should never be un-installed unless you want to break several other Webmin modules as well.
The functions available after calling &foreign_require("proc", "proc-lib.pl"); are :
- proc::safe_process_exec(command, uid, gid, handle, input, fixtags, bsmode)
- Executes the specified command as the given Unix uid and
gid, and writes its output to a Perl file handle (usually
STDOUT). This can be useful when executing programs that fork
their own subprocesses, which would normally prevent Perl from detecting
the end of their output when run using a piped open function call.
For example, many servers have startup scripts like
/etc/init.d/httpd that exhibit this problemative behaviour.
If the input parameter is supplied, it will be fed as input to the command when run. If the fixtags parameter is set to 1, all output from the command will have HTML characters escaped that that it can be properly displayed in a browser. And if the bsmode argument is set, any backspace or return characters output by the command are interpreted to remove the last output letter or clear the current line, respectively. This can be useful if the program usually uses these characters to display an incrementing counter, as mkfs and cdrecord do.
- proc::safe_process_exec_logged(command, uid, gid, handle, input, fixtags, bsmode)
- This function behaves just like safe_process_exec, but also records
the executed command so that it will be logged when webmin_log is
called.
- proc::pty_process_exec(command, [uid, gid])
- Executes the specified command in a new PTY as either the given
Unix uid and gid or the currect user (normally root). Many
programs (such as passwd) expect to interact with a user through
the current TTY, and thus input cannot simply be piped to them after being
run with the open function. However, you can use the file handle
that this function returns to read and write to such programs as though
you were supplying user input and viewing output usually send to the
user.
pty_process_exec actually returns both a file handle and the PID of the started process, so that you can kill it if necessary. The standard wait_for function can be used to interact with the command, as this example shows :
&foreign_require("proc", "proc-lib.pl"); ($fh, $pid) = &proc::pty_process_exec("passwd $username"); while(1) { $rv = &wait_for($fh, "password:"); if ($rv == 0) { &sysprint($fh, $password); } else { last; } } close($fh); - proc::pty_process_exec_logged(command, [uid, gid])
- Just like pty_process_exec, but records the command for later
logging when webmin_log is called.
- proc::list_processes([pid])
- Returns a list of all processes currently running on the system, or just
the details of a single process if the pid parameter is supplied.
Each element of the returned array is a reference to a hash containing
at least the following keys :
pid The process's ID ppid The ID of its parent process user The name of the Unix user who owns this process cpu The percentage of CPU time that the process is currently using size The amount of memory that the process is using nice Its current nice leve time How long the process has been actually using the CPU for args The process's command and any arguments - proc::find_process(name)
- Searches for processes whose command or arguments match the given
name, and returns an array of details of those that match. Each
element is a hash reference with the same members as the list_processes function.

