Do you use your laptop in different network environments ?

At home ? In the office ? At a customers site ?

If yes, the small package netenv might be useful for you. When booting your laptop it provides you with a simple interface from which you can choose the current network environment. If you are the first time in an environment, you can enter the basic data for later reuse.

Netenv sets up a file containing variable assignments which describe the current environment. This can be used by the pcmcia setup scheme (e.g. like the one that comes with Debian, RedHat and SuSe). If you have a Network Interface Card (often simpy called NIC) onboard, you can use the same mechanism.

Have a look at netenv's chooser box:

Besides the basic functionality of configuring the NIC, the netenv data can be used for thinks like:

Netenv is available prepackaged for Debian and Redhat Linux as well as tarball. Mandrake- and SuSe-Users may use the RedHat-RPM. netenv depends on dialog(1) resp. gdialog (which comes with the mentionend distributions).

A word to all gurus: In this docu I try to explain things with Linux novices in mind, so be patient.


Table of Contents

What does netenv do ?

Where to get netenv ?

How to install

Basics

First time configuration

Configuration

Examples

Remarks at DNS

Remarks for SuSe 7.3 Users

netenv alternatives

Conclusion


Where to get netenv ?

Netenv has a homepage at Sourceforge: http://netenv.sourceforge.net

But you may know this already ...

You will find there the tar-file as well as the RedHat-RPM. The latter should be useable in Mandrake and Suse too.

Debian-User

Netenv has been available for Debian quite a while. Look at http://www.debian.org/distrib/packages.

Back to Table of Contents

How to Install

It depends ... For all distributions, which use RPM, do as root e.g.:
rpm -i netenv-0.94-1.i386.rpm
In Debian e.g.:
dpkg -i netenv-0.92-2.i386.deb
In all other cases:
tar xvf netenv-0.94-2.tar
This installs a shellscript called netenv, a little helper utility trpnc, configuration examples and these docs. Depending on the distribution a little handwork may be necessary.

RedHat

I don't know anything about current RedHat versions. Therefore the following hints are probably out of date. You may find useful hints in the section
How to use the tar-file

The netenv-RPM has been packaged under RedHat 6.1. So it should be possible to install in all distributions using RPM.

The postinstall-script puts

/etc/rc.d/rc.sysinit now looks like this:
lulu:/home/bav> tail -2 /etc/rc.d/rc.sysinit
# Added by package netenv on 06.03.2000 19:53:10
/usr/sbin/netenv
Additionally /etc/sysconfig/network-scripts/ifcfg-eth0 will be changed. Just after first installing Redhat this file looks like:
lulu:/etc/sysconfig/network-scripts>>> cat ifcfg-eth0 
DEVICE=eth0
BROADCAST=192.168.200.255
IPADDR=192.168.200.201
NETMASK=255.255.255.0
NETWORK=192.168.200.0
ONBOOT=yes
Installing netenv adds two lines:
lulu:/etc/sysconfig/network-scripts>>> tail -3 ifcfg-eth0
ONBOOT=yes
# Added by package netenv on 06.03.2000 19:53:10
if [ -r /tmp/netenv ]; then . /tmp/netenv; fi

SuSe

With Suse 8.x a couple of changes in system boot and network configuration were introduced. The current procedure assumes Suse 8.1, but it should work with 8.0 as well. For older versions see the next paragraph.

SuSe 8.1

The postinstall-script adds two lines to /etc/init.d/boot.local:
lulu:/etc/init.d> tail -3 boot.local
#
# Added by package netenv on 06.12.2002 10:45:10
/usr/sbin/netenv
This way netenv is called during boot. netenv assumes the NIC to be configured is eth0, so the line
if [ -r /tmp/netenv ]; then . /tmp/netenv; fi
is appended to the file
/etc/sysconfig/network/ifcfg-eth0
It then looks like:
lulu:/etc/sysconfig/network> cat ifcfg-eth0
FIREWALL="YES"
BOOTPROTO='static'
BROADCAST='nn.nn.nn.nn'
IPADDR='nn.nn.nn.nn'
NETMASK='nn.nn.nn.nn'
NETWORK='nn.nn.nn.nn'
REMOTE_IPADDR=''
STARTMODE='onboot'
UNIQUE='oxTw.yHaVEFCrUXE'
WIRELESS='no'
if [ -r /tmp/netenv ]; then . /tmp/netenv; fi
The entries IPADDR, NETMASK etc. spring from the basic installation. There is no need to delete them as they are superseded by the assignments in /tmp/netenv. In this example I assume that the NIC is not a PCMCIA-NIC. Otherwise the line
STARTMODE='onboot'
must read
STARTMODE='hotplug'

SuSe 7.3

The postinstall-script adds two lines to /etc/rc.d/boot.local:
mweb@guru:/etc/rc.d > tail -3 boot.local 
# before we're going to the first run level.
#
# Added by package netenv on 06.02.2001 20:28:10
/usr/sbin/netenv
For PCMCIA-Cards an entry in /etc/pcmcia/network.opts is done:
mweb@guru:/etc/pcmcia > tail -2 network.opts 
esac
# Added by package netenv on 06.02.2001 20:28:10
if [ -r /tmp/netenv ]; then . /tmp/netenv; fi
If the laptop has a builtin NIC and PCMCIA must not be used, you may override the values defined by YAST as follows:
mweb@guru:/etc/rc.d > head -16 network 
#! /bin/sh
# Copyright (c) 1996 SuSE GmbH Nuernberg, Germany.  All rights reserved.
#
# Author: Florian La Roche , 1996
#       Werner Fink , 1996
#       Burchard Steinbild , 1996
#       Rolf Haberrecker , 1998
#       Werner Fink  (based on a patch of Andries Brouwer) 1999
#
# /sbin/init.d/network
#

. /etc/rc.status
. /etc/rc.config
if [ -r /tmp/netenv ] ; then . /tmp/netenv; fi

Debian

The Debian-Package netenv is currently worked on. As far as I know, PCMCIA-NIC's can be used without further configuration.

Onboard-NIC's though need a changed /etc/network/interfaces. You can do this using netenv procedures, see the example script netenv_setup_debian_example. If you do nothing, your NIC will be configured like it was during system installation regardless what you choose with netenv.

Mandrake

Mandrake 9 users reported that the splash-screen had to be disabled (disable vga=nnn in /etc/lilo.conf) in order to be able to input something during boot. Furthermore the cdialog seems not to be stable. Problems could be solved only after using the SuSE dialog binary instead.

How to use the tar-file

These are the necessary steps:
tar zxvf netenv-0.94-2.tar.gz
cd netenv-0.94-2
make
make install # must be user root from now on !
make config
Depending on the distribution the last step make config may eventually have to be done manually.

netenv must be called before the normal network- or PCMCIA-start. Check for /etc/init.d/boot.local or the equivalent. See the SuSE 8.1 paragraph for further details.

After you have ensured that netenv is called during boot, the configuration data must be read by the network scripts. Modern distributions seem to use ifup to start a preconfigured net interface. Then the SuSE 8.1 paragraph should contain the details.

A common issue is to confuse eth0 and eth1 if there is an onboard NIC and a PCMCIA NIC. Chances are that eth0 is the onboard and eth1 is the PCMCIA NIC. Verify with dmesg | grep eth and lspci.

Netenv checks for eth1, but depending on the configuration at the time of installation this cannot be waterproof.

Back to Table of Contents

Basics

The basic idea is to enter information about the current location of the laptop in a very early phase of booting. This happens before configuring any network interface.

This is done using dialog(1), a simple menu interface, well known to most users. Booting is continued after the user has done his selection. For a default environment this may be as simple as just pressing RETURN.

If "lilo" is used as bootmanager, you may alternatively input after the lilo-prompt:

linux NETENV=office
This defines a shell variable "NETENV" with the value "office". This means for me: I am with my laptop named lulu in the office. The file containing the values for IP-address etc. is /etc/netenv/lulu-lavie. The Linuxkernel starts the init-process with the variable NETENV as part of its environment. The same does init with the so called rc-scripts.

The netenv-script tests for NETENV beeing defined. If it is, netenv carries out further actions without popping up the manu.

After having selected the current environment, netenv copies the actual file to /tmp/netenv.

This file has modes 644, so being readable by any user for further user dependent configuration tasks.

Back to Table of Contents

First time configuration

After installing the user root should call netenv. Do simply:
netenv
This will fire up a menu with only one choice:
    new  Set_up_new_environment  
These parameters will be asked for:
   Enter the current IP-Address or the keyword dhcp ...
   Enter the netmask of the current subnet ...
   Enter the IP-Address of the current network ...
   Enter the Broadcast-Address of the current network ...
   Enter the Gateway-Address of the current network ...  
   Enter the IP-address of the current nameserver ...  
If in a network with DHCP-Server, input dhcp instead of an IP-Address. Then a /tmp/netenv is generated containing only
BOOTPROTO='dhcp'
STARTMODE='hotplug'
All other values will be derived according to the DHCP-configuration. If the NIC is onboard, netenv should have written
STARTMODE='onboot'
In case of a static IP-address there will be a default entry for the other items, which will be sufficient in many situations.

Finally you will be asked if you want to save this configuration for further use:

    Do you want to save this configuration ?
Please do not use spaces in this name !

Depending on the Distribution netenv offers to restart the network and to activate the changes this way.

If this is not applicable, take out your PCMCIA-NIC (if it's PCMCIA you use ...) and stick it in again (cardmgr will ring the bell). The same result may be achieved doing

/etc/init.d/pcmcia restart
In any case cardmanager from the PCMCIA-package should configure the interface.

Ping your gateway-address and you will know !

Didn't work ? Is the link-LED green ? Check the output of

ifconfig eth0

The procedure just described may be also be used, wenn you want to switch from one network environment to another while your laptop stays up and running. There is no need to reboot - it's Linux ...

Those, who use a NIC onboard instead of a PCMCIA-NIC have to restart their network.

In RedHat or SuSE e.g.:

/etc/init.d/network restart
Netenv does this according to your input.

Back to Table of Contents

Configuration

Netenv is configured using files. You will find them in /etc/netenv. On a laptop named "lulu" files lulu, lulu-foo, lulu-bar etc. will be used. So the naming scheme is as follows:
/etc/netenv/<NODE-NAME>-<VALUE-OF-VARIABLE-NETENV>
The filename identical to the laptop's hostname is the first item in the selection menu. You simply may press RETURN and booting is continued. You should put the most frequently used environment into this file.

All files contain assignments in shell syntax, e.g.

netenv_id=At_Home_LCD_WheelMouse_pcmcia
...
IPADDR=123.456.78.9
...
NETSCAPE_PROXY_TYPE=2
Spaces will cause trouble. For a well configured NIC you will have to define at least
IPADDR
NETMASK
NETWORK
BROADCAST
Depending on the situation you may additionally have to define
GATEWAY
DNS_1
You may stick any variableassignment into the file - as long as everything is syntactically right. There is something special with an assignment like
NETENV_SCRIPT=/etc/netenv/netenv_setup
If the file pointed to is readable, netenv will execute this file (to be precise: it will source it) after the current network environment has been choosen.

Pay Attention ! This will be in a very early stage of boot. No network will be active ! NETENV_SCRIPT will be executed with root privileges !

With the help of this script you may do quite useful things. More on this in the example section.

Expert Mode

If you choose CANCEL in the netenv-dialog-box, you may enter a shell. After quitting this, the chooserbox pops up again. Security hints: The directory /etc/netenv and the files in it must be writeable only for root. netenv does some basic checks for this.

Back to Table of Contents

Examples

Of course this is the most important part of this documentation ...

The examples are described step by step. So please read them one after the other !

StandAlone_Touchpad

lulu:/etc/netenv>>> cat lulu-touch-pad 
netenv_id=StandAlone_Touchpad_no_eth
STARTMODE=manual
export XF86CONFIG_FILE=/etc/X11/XF86Config-4-lcd-touch
NETENV_SCRIPT=/etc/netenv/netenv_setup
# This may be used to edit ~/.netscape/preferences.js
NETSCAPE_PROXY_TYPE=3
I use this one when my laptop has no network connection.

The value of the variable netenv_id (as I said earlier: Please without spaces) will be used as decription in the chooser box.

There is no IP-address defined. By setting STARTMODE=manual there will no NIC be configured during boot. I assign NETENV_SCRIPT=/etc/netenv/netenv_setup. This is a file containing shell commands. It is attached to this documentation here.

This sample is written in a simple manner to get you started. Relevant code section here is:

lulu:/etc/netenv>>> cat netenv_setup
...
# Simple way to configure the X-Server 
if [ -r $XF86CONFIG_FILE ]; then
    echo $XF86CONFIG_FILE will be used for configuring the X-Server ...
    mv /etc/X11/XF86Config /etc/X11/XF86Config.old
    ln -s $XF86CONFIG_FILE /etc/X11/XF86Config
fi
fi
...
As I defined XF86CONFIG_FILE the code creates a link. Right now it is pointing to the configuration file, which I created for my laptop with touchpad.

Typically netenv_setup does everything the root user is needed for and the whole system is concerned with. Personal settings are done via .xinitrc. Here is an example:

In my private configuration I use NETSCAPE_PROXY_TYPE:

lulu:/home/bav> cat .xinitrc
#!/bin/sh
...
if [ -r /tmp/netenv ]; then
. /tmp/netenv
fi
if [ -n "$NETSCAPE_PROXY_TYPE" ]; then
   ~/tools/edit-ns-preferences $NETSCAPE_PROXY_TYPE
fi
...
You will find the script edit-ns-preferences in the netenv-documentation. It will avoid nasty network-timeouts, when starting the browser.

In_the_Office

lulu:/etc/netenv>>> cat lulu-lavie
# Networkenvironment: netask
netenv_id="lavie_pcmcia_dhcp"
export BOOTPROTO=dhcp
export STARTMODE=hotplug
export PRINTER=cc_hp
NETSCAPE_PROXY_TYPE=2
FETCHMAIL_POLL_INTERVALL=900
In the office I get my network configuration from a DHCP-Server. STARTMODE=hotplug is set, because my laptop has no onboard-NIC and therefore the PCMCIA-NIC has to be used.

PRINTER=cc_hp sets the defaultprinter to the printer in the office. NETSCAPE_PROXY_TYPE=2 activates automatic proxyconfiguration in Netscape.

When I am in the office, mail shall be fetched periodically. For this I use FETCHMAIL_POLL_INTERVALL. The following snippet from my ~/.xinitrc starts fetchmail as daemon, which will became active every 15 min and carry out things defined in ~/.fetchmailrc:

if [ -n "$FETCHMAIL_POLL_INTERVALL" ]; then 
   fetchmail -d $FETCHMAIL_POLL_INTERVALL
fi

Laptop_at_home

At home I use my default configuration file. As I work here most of the time the filename equals my laptops node name. So I just have to press return in the netenv-chooser-box:
netenv_id=At_Home_Docking_LCD_WheelMouse_onboard_VPN
IPADDR=nnn.nn.nnn.nnn
NETMASK=nnn.nnn.nnn.nnn
NETWORK=nnn.nn.nnn.nnn
BROADCAST=nnn.nn.nnn.nnn
GATEWAY=nnn.nn.nnn.nnn
SEARCH=foo.bar.com
DNS_1=nnn.nn.nn.nn
DNS_2=nnn.nn.nn.nn

FETCHMAIL_POLL_INTERVALL=900

# If the variable NETENV_SCRIPT points to an readable file,
# it will be run when netenv is executed
NETENV_SCRIPT=/etc/netenv/netenv_setup
ICEWM_INCLUDE_FILE=home
# This defines my CRT with 1024x768 and a wheelmouse
XF86CONFIG_FILE=/etc/X11/XF86Config-4-lcd-wheel
# This may be used to edit ~/.netscape/preferences.js
NETSCAPE_PROXY_TYPE=2
# This may be used to edit ~/.opera/opera6.ini
OPERA_PROXY_FILE=proxy-fsc.ini

# NIC is in the docking unit - like it were onboard
STARTMODE='onboot'
Relevant portion from my netenv_setup is this:
lulu:/etc/netenv>>> cat netenv_setup
...
PROFILE=$1
...
if [ "$PROFILE" = "default" ]; then
   print_action linking /dev/pilot
   rm -f /dev/pilot; ln -s /dev/ttyS0 /dev/pilot
   print_status
   print_action calling ptal-init start
   /usr/sbin/ptal-init start 
   print_status
else
   # When there is no docking station, start irattach appropiately and
   # link /dev/pilot to ircomm0.
   print_action running irattach
   /usr/sbin/irattach /dev/ttyS3 -s
   print_status
   print_status linking /dev/pilot
   rm -f /dev/pilot; ln -s /dev/ircomm0 /dev/pilot
   print_status
fi
...
netenv_setup is called with the parameter PROFILE, which equals "default" here (in all other cases it is the filename of the descriptionfile minus hostname portion).

At home I use a cradle for my palm. So /dev/pilot must point to the appropriate serial device. Additionally the software for my HP Officejet has to be started. In all other environments the palm can be reached only via IRDA. ptal must not be started then.

At home my laptop is in a docking-unit. This has a NIC. In order to use this NIC

STARTMODE='onboot'
has to be set.

At_Customer_Foobar

Earlier versions of libc made it possible for a non privileged user to make kind of private /etc/hosts by setting the environment variable HOSTALIASES. Due to security issues this is no longer possible in recent versions of libc.

If you don't like to edit your /etc/hosts manually, the following idea may help. For me it is useful, as I find computers with identical names but different IP-addresses in different environments.

I put marks in my /etc/hosts like this:

lulu:/home/bav> cat /etc/hosts
...
# netenv hosts begin
# netenv hosts end
...
Now I define nodes with their IP-addresses, which I want to connect to in the current environments:
NETENV_HOST_ENTRIES="192.168.10.11 abba:192.168.10.12 bebe:192.168.10.3  alfa-sw:\
192.168.10.4  beta-sw:192.168.10.13 coca:192.168.10.14 cola"
This code in my /etc/netenv/netenv_setup will care for editing /etc/hosts after choosing the environment:
if [ -n "$NETENV_HOST_ENTRIES" ]; then
   if egrep '^# netenv hosts begin$' /etc/hosts > /dev/null 2>&1; then
      (
      awk 'NR==1,/^# netenv hosts begin$/' /etc/hosts
      echo $NETENV_HOST_ENTRIES | awk -F'\:' '{ for ( j=1; j<=NF; j++ ) print $j }'
      awk '/^# netenv hosts end$/,/*/' /etc/hosts
      ) > /etc/hosts.netenv
      mv /etc/hosts.netenv /etc/hosts
      chmod 644 /etc/hosts
      echo netenv_setup: /etc/hosts was modified ...
   fi
else
   if egrep '^# netenv hosts begin$' /etc/hosts > /dev/null 2>&1; then
      (
      awk 'NR==1,/^# netenv hosts begin$/' /etc/hosts
      awk '/^# netenv hosts end$/,/*/' /etc/hosts
      ) > /etc/hosts.netenv
      mv /etc/hosts.netenv /etc/hosts
      chmod 644 /etc/hosts
      echo netenv_setup: /etc/hosts was cleaned up ...
   fi
fi
Now /etc/hosts looks like this:
...
# netenv hosts begin
192.168.10.11 abba
192.168.10.12 bebe
192.168.10.3 alfa-sw
192.168.10.4 beta-sw
192.168.10.13 coca
192.168.10.14 cola
# netenv hosts end
...
All these nodes are trusted, so I use the mechanism in my ~/.xinitrc and call xhost appropriate:
XHOST_PLUS_LISTE=`awk '/^# netenv hosts begin$/,/^# netenv hosts end$/' /etc/hosts | awk '!/^#/ {print $2}'`
xhost $XHOST_PLUS_LISTE
xhost gives me:
lulu:/home/bav> xhost 
access control enabled, only authorized clients can connect
INET:cola
INET:coca
INET:beta-sw
INET:alfa-sw
INET:bebe
INET:abba

Back to Table of Contents

Remarks concerning DNS

Netenv does no DNS configuration. Unfortunately there are a couple of differences in this area looking at the distributions.

I always felt the mechanism, which David Hinds implemented in his PCMCIA-package, being sufficient (Script network). This snippet shows what is happening there:

        # Update DNS stuff
        cp /etc/resolv.conf /etc/resolv.new
        echo "# $DEVICE begin" >> /etc/resolv.new
        test "$DOMAIN" && echo "domain $DOMAIN" >> /etc/resolv.new
        if [ "$DNSSRVS $DNS_1 $DNS_2 $DNS_3" != "   " ] ; then
            for DNS in $DNSSRVS $DNS_1 $DNS_2 $DNS_3 ; do
                echo "nameserver $DNS" >> /etc/resolv.new
            done
        fi
        echo "# $DEVICE end" >> /etc/resolv.new
        mv /etc/resolv.new /etc/resolv.conf
The file /etc/resolv.conf is copied to a temporary file. If one of the variables DOMAIN, DNSSRVS, DNS_1, DNS_2 or DNS_3 are defined, appropiate commands are issued. This new section starts e.g. with # eth0 begin and ends with e.g # eth0 end. These makes are used, to clear the section, when PCMCIA is shut down. Afterwards /etc/resolv.conf will be in the original state.

So defining e.g. DNS_1 makes this thing work.

If you want to use netenv for this task, you may put following code in /etc/netenv/netenv_setup:

if [ ! -z "$DNS_1" ]; then 
    (
    echo "# resolv.conf autogenerated by netenv "`date`
    if [ ! -z "$DOMAIN" ]; then echo domain $DOMAIN; fi
    if [ ! -z "$SEARCH" ]; then echo search $SEARCH; fi
    echo nameserver $DNS_1
    if [ ! -z "$DNS_2" ]; then echo nameserver $DNS_2; fi
    ) > /etc/resolv.conf
    chmod 644 /etc/resolv.conf
    echo netenv: /etc/resolv.conf was set up ...
fi

Back to Table of Contents

Remarks for SuSe 7.3 Users

If you have an onboard-NIC (so that there is no need to use a PCMCIA-NIC), you have to override the standard entry in /etc/rc.config. You can do this by setting IFCONFIG_0:
IFCONFIG_0="172.25.64.130 broadcast 172.25.64.255 netmask 255.255.255.0 up"
If you want to use DHCP, the entry must read
IFCONFIG_0="dhcpclient"
Using netenv you may do this as follows:

At first the appropriate profile:

elli:/etc/netenv> cat elli-ht
# Networkenvironment: DHCP
export USE_DHCP=yes
NETENV_SCRIPT=/etc/netenv/netenv_setup
Furthermore you need a netenv_setup script with at least following contents:
elli:/etc/netenv> cat netenv_setup
edit_rc_config()
{
   if [ ! -r /etc/rc.config ]; then
      echo No /etc/rc.config, probably not a SuSE-System, giving up ...
      return 1
   fi
   VARIABLE_TO_CHANGE=$1
   shift
   echo ${VARIABLE_TO_CHANGE}'="'$*'"' > /tmp/.netenv.tmp.$$
   LINE=`awk '/^'$VARIABLE_TO_CHANGE'=/ {LINE=NR} END {print LINE}' /etc/rc.config`
   awk -v LINE=$LINE 'NR /tmp/.rc.config.netenv
   cat /tmp/.netenv.tmp.$$ >> /tmp/.rc.config.netenv
   awk -v LINE=$LINE 'NR>LINE' /etc/rc.config >> /tmp/.rc.config.netenv
   cat /tmp/.rc.config.netenv > /etc/rc.config
   rm -f /tmp/.rc.config.netenv /tmp/.netenv.tmp.$$
   echo netenv_setup: rc.config edited, Variable $VARIABLE_TO_CHANGE set to $*
}
if [ "$USE_DHCP" = yes ]; then
   edit_rc_config IFCONFIG_0 dhcpclient
else
   edit_rc_config IFCONFIG_0 "$IPADDR broadcast $BROADCAST netmask $NETMASK up"
fi

SuSe uses the files /etc/route.conf for describing static routing. The default-route looks like this:

default                 172.246.2.1
Using the example where netenv edits /etc/hosts you may use e.g.:
if grep SuSE /etc/issue 1>/dev/null; then
   if [ ! -z "$GATEWAY" ]; then
    (
    echo "# route.conf autogenerated by netenv "`date`
    echo default $GATEWAY 0.0.0.0 eth0
    ) > /etc/route.conf
    echo netenv_setup: /etc/route.conf was modified ...
   fi
fi
Back to Table of Contents

netenv Alternatives

As frequently in Linux there are other choices. Read Linux on the Road - A Guide for Laptops and Mobile Devices by Werner Heuser to find alternative solutions.

Those I had a closer look at, try to find out the network environment by sending arp requests. SuSe recently came up with System Configuration Profile Management scpm, which is quite powerful but lacks an user interface during boot which I feel to be important.

Back to Table of Contents

Conclusion

I hope netenv will be useful for you. Do not hesitate to send questions and comments to gerd.bavendiek@gmx.net.

Back to Table of Contents


Gerd Bavendiek
Last modified: Mon Feb 28 21:56:49 CET 2005