At least two files are needed to provide new functionality:
A file in /etc/webconf
that provides
meta-information for the web interface. This file is named
<package>.webconf
.
The .cgi(s) that actually perform the configuration.
The /etc/webconf/<package>.webconf
file
describes how the various cgi scripts in the package plug into the
webconf menu system. Here is an example of a .webconf file:
displayname:General all:Log Files:/logfiles.cgi all:General Health:/general-info.cgi all:Active Connections:/connection-info.cgi # displayname:Save To disk all:Backup Packages:/lrcfg.back.cgi expert:Destinations:/lrcfg.pkgdisks.cgi expert:Edit leaf.cfg:/leafcfg.cgi
The first item in the file should be a tag for the "displayname", or the title of the menu category. It is possible to have more than one main category - In the example above, there are two: "General" and "Save to Disk".
After each main category are the menu options within that category. Each line consists of three fields:
1. A tag identifying which "menu-set" this menu option belongs to. In the reference design, the choices are "basic", "expert", or "all", but any number of menu-sets can be defined. The menu options are only displayed if the user has chosen that menu-set. For example, "expert" options are only visible when the user chooses the "expert" menu set. The "all" menu-set tag means that the menu option is displayed in all menu sets.
2. The text shown for the menu option
3. The script to run. The script must end in
.cgi, and the path is relative to the document root
(/var/webconf/www
.)
The example above displays a menu that looks like this:
General Active Connections General Heath Log Files Save To Disk Backup Packages Destinations Edit leaf.cfg
The menu options are sorted, so Active Connections comes first, even though it is defined last in the "General" section. The sort order can be controlled as described later on.
The /var/webconf/lib/menubuilder.sh
script
takes all
/etc/webconf/*.webconf
files and sorts them; so if
there are two .webconf files that have definitions for a displayname of
"General", options from both .webconf files will be
combined under one "General" heading.
All options (displayname and menu options) are sorted. In order to control the sorting order, numbers can be prepended to the name. The number will control the sort order, but will not be displayed.
Here is an example of three webconfs using the numeric sorting order, and how they are displayed:
/etc/webconf/network.webconf displayname:20Networking all:10Interfaces:interfaces.cgi all:20Traffic Shaping:tc.cgi /etc/webconf/shorwall.webconf displayname:30Firewall all:20Advanced:shorewall.adv.cgi all:10Basic Setup:shorewall.cgi /etc/webconf/ezipupd.webconf displayname:20Networking all:50Dynamic DNS:ezipupd.cgi
Networking Interfaces Traffic Shaping Dynamic DNS Firewall Basic Setup Advanced
Warning: It is possible for one developer to
have 20Networking
and another developer to specify
30Networking
. The net result is two menu headings
with the name Networking.
The .webconf files serve as pointers to the .cgi scripts located
in /var/webconf/www
. The .cgi files must have
execute permissions and be able to be run by the web server.
Typically the .cgi scripts are written in haserl (http://haserl.sourceforge.net) script. This cgi interpreter automatically populates shell variables based on the POST or GET data received from the client.
Haserl was written for LEAF routers because PHP is a fast way to write server-side interpreted code, but is too big for a diskette based Linux distro. After several attempts to write a web configuration framework with sh, awk and c programs, haserl was written to provide the bare minimum to fuse HTML with a shell interpreter. This section is not a tutorial on haserl, but provides some basic information to help explain the code in the existing cgi's.
Haserl automatically parses POST and GET requests and exposes any
form elements or client-provided data as shell environment variables.
For instance,
http://some.host.com/index.cgi?myvar=3&yourvar=3
will automatically cause any shell script that you write to have two
variables defined: FORM_myvar (set to 3), and
FORM_yourvar (set to 2).
Anything inside <? ... ?>
tags is shell
script. To verify the above really does define FORM_myvar, you could
write HTML code like this:
<p>Your variable "FORM_myvar" is <? echo -n $FORM_myvar ?></p>
A limitation of early versions of haserl was each code block was a separate sub-shell. This is no longer the case; there is one sub-shell that is started at the beginning of the script.
Haserl needs to use file descriptor 5 for communication with the
sub-shell. You should not close or write to fd 5. (i.e. you should never
do something like this in your shell code: echo "hi mom"
>&5
It will cause your cgi to fail)
Haserl is installed suid root. When installed this way it sets its uid/gid to the owner of the .cgi script. So if you need a script to do things "root" does, make the file owned by root:root. Other cgi scripts that don't need root access can be owned by by nobody:nogroup or sh-httpd:nogroup.
If you want the client to be able to upload a file, you must
include -u
on the command line, like this:
#!/usr/bin/haserl -u
A number of shell script libraries are available to ease writing
.cgi scripts. These libraries also ensure a consistent look-and-feel.
The scripts mentioned here are in the
/var/webconf/lib
directory.
Two helper scripts are provided to write the leading and
trailing HTML necessary for each page.
preamble.sh
displays the HTTP and HTML header
information. preamble.sh
also calls the
menubuilder.sh
script to display the menu.
footer.sh
writes the information necessary to
close the HTML page.
Here is an example of the minimum necessary to generate a .cgi that looks like all other .cgi's in the webconf.lrp:
#!/usr/bin/haserl <? title="Sample Script" /var/webconf/lib/preamble.sh ?> <h1>Sample</h1> <p>This is a sample .cgi script. It doesn't do anything.</p> <? /var/webconf/lib/footer.sh ?>
The footer.sh can print your own contact information at the bottom of the footer. To do so, simply add your message as a parameter to footer.sh. Enclose your comment in quotes; footer.sh will list only up to the first unprotected space.
Here's how you can include your own contact information:
<? /var/webconf/lib/footer.sh "This plugin maintained by \ <a href=\"mailto:me@somewhere.com\">J. R. Hacker</a>" ?>
The custom message can contain html (such as color highligting) but please note that this text is inside a table; div tags (such as <h1> should not be used.
The menubuilder.sh
script is responsible
for building the menu on the left of the page. It is automatically
called by preamble.sh
. The "menu-set" (expert,
basic, etc.) is passed as the first parameter.
The svcstat.sh
script provides a common way
to present the status of a daemon, and buttons to change the daemon's
state. This script requires 3 or 4 parameters:
1.The command - either "", "start", "stop",
or "restart". This is the command button the client selected. (This
corresponds to running /etc/init.d/<service>
command
). Even if no button was pushed,
a null parameter "" is required.
2.The service - the name of the script in
/etc/init.d
that is run.
3.The process name - This is the
name of the process that is checked to see if the
service (daemon) is currently running. For instance, the
/etc/init.d/
script is named "webserver", but the
process name is "mhttpd
". In other cases, there
is no process id to check. For instance,
/etc/init.d/networking
does not have a process
id. In this case, the process name must be "-" (dash), and parameter 4
is the command to run to check for a running process.
4.Optional command If the previous parameter
is a "-", then this is the command to run to check if the process is
running. The command should print output if the service is running,
and print nothing if it is not. For instance, to check if networking
is running, you could use: '/sbin/ip addr sho eth0 | grep
inet'
.
Here are typical examples of svcstat.sh use:
<? /var/webconf/lib/svcstat.sh "$cmd" squid squid ?> <? /var/webconf/lib/svcstat.sh "$cmd" networking - '/sbin/ip addr sho eth0 | \ grep inet' ?>
The validator.sh
file contains common
functions that can be used to validate web forms. It also contains two
functions (report_validation_fail
and
report_validation_ok
) that provide a consistent
wat of reporting whether a form contains validated data or not.
The file is usually sourced inside a haserl code block when it is used:
<? . /var/webconf/lib/validator.sh echo "$myinputtextbox" | dostounix >/tmp/$SESSIONID.textbox ?>