


 
[a4]report
headings

0.09.05

AutoMount Daemon Version 
Wolfram Saringer 

 







Introduction
This Manual describes the AutoMount Daemon, a simple automounter
for use under Linux. It is not intended to be a perfect all
purpose program, but to fit my particular need that arose from the
installation of a server running under Linux in an environment, where
most of the time no administrator is present. What the program offers
is quite simple to explain: Upon insertion of a CDROM (or
whatever) the volume is mounted. It can be unmounted by a
normal user using another program called ``eject''. This was inspired
by the Solaris automounter. If someone now says, that there is a
package that allows a normal user do issue ``mount'' and ``umount''
commands, one should consider, that in this network there are only
DOS-clients (argh) and people who would be quite concerned if
they were told to write commands like ``mount -r -tiso9660 /dev/scd0
/cdrom''.

Setup should be easy even for non-experienced users. In case you just
plan to use it for CDROM drives and floppies without polling, you
should be able to start with the supplied sample configuration file
right away. Refer to chapter  for detailed instructions.

Please note that I still consider this to be in (late) beta
status. This does not mean that the versions released are unstable,
but that it is some kind of public review.





Usage

'automountd' Daemon
Usage is quite straightforward. Normally the daemon is started at boot
time together with other daemons (for example in /etc/rc.local). The
syntax is:
automount [-i interval] 
The following arguments are supported:

intervall: The -i option can be used to change the intervall
length Default is 5 seconds between the checks for inserted
media.

 To facilitate usage, the daemon reacts to different signals:

SIGHUP: This signal can be used to force a reread of the
initialization file.
SIGTERM: This signal lets the daemon exit gracefully,
unmounting any device it has mounted. In this case, CD's are by
default not ejected (This can be changed, see section ).
SIGQUIT: See SIGTERM.
SIGINT:  See SIGTERM.


The daemon creates a file The default is
/var/adm/automountd.log, where startup, shutdown and any failures
are logged. This is a plain text file and should be self-explanatory.
If this file does not exist after the daemon was started, the daemon
was possibly compiled with an option instructing it to use the normal
syslog facility.

'eject' Program

This user program can be used to ``unmount'' a volume previously
mounted by automountd. The syntax is:
eject volumename [volumename ]
where volumename has to be the same as the name given in the
configuration file.
Supplying no argument is identical to 'all'.

Due to the design of the daemon, errors are not reported. Implementing
this is not impossible, but would impose a pause of up to Intervall
seconds, because unmount requests are also handled
synchroniously This not true anymore from version 0.08.00
on when compiling without the DONTUSESELECT option (This is
the default and should only be changed if select() does not work
properly).. Maybe this will be an additional option (at compile time)
in the future. 

'volcheck' Program

This program can be used to force an immediate check of ALL devices
listed in the configuration file, including those with the ``NOPOLL''
flag set.

'automountd.conf' Configuration file

This file names all volumes for automountd to check for present
media. It consists of lines in the format explained below. Normally it
should be located in /etc. See the source comments to change this
default. Lines starting with a '' sign are comments. The format used
is quite similar to fstab with some options missing. Spaces and tabs
can be used to separate the fields on one line, a newline ends one
record. The maximum number of lines is equal to the maximum positive
number that can be represented using an integer (this is normally
about ). The line length is not restricted, but be shure to
end each line (including the last one) with a newline
character. Please note that the Options field must be present. If no
options are used, put a '-' there, as shown in the example below.
Do not use device names longer than about 255 characters.
Format of automountd.conf This file is included as a
starting point. 'make install' will copy it to /etc if it 
is not already there.: 
lllll
device		&mountpoint	&filesystem	&name	&options
/dev/cdrom	&/cdrom		&iso9660	&cd	&RO
/dev/floppy	&/floppy	&msdos		&floppy	&NOPOLL,NOEJECT
/dev/zip	&/zip		&msdos		&zip	&-

Adding any floppy drives to the daemon configuration file without the
``NOPOLL'' flag is not a good idea, as these drives may wear out.
Devices with this flag are not mounted automatically, but can be
forced to be checked with the volcheck (See
section ) command.

One important note regarding ZIP Drives: Be sure to have a valid
disk in the drive at the time automountd starts. This can be ejected 
afterwards without any harm. The kernel is content if it was able to read
a partition table from the disk and won't try again until an actual disk change
occurrs. Otherwise (if no disk was present on the start of automountd,
each mount request will generate several error messages from the kernel,
which will increase the system load considerably.

Another thing to say about ZIP's: For SCSI drives /dev/zip used above should be
a link to /dev/sdX4, where X is the drive identifier as in /dev/sda4. Disks
formatted for ext2 should use /dev/sdX1. I do not know how the partitions to
use are when parallel or IDE drives are used. See the ZIP-Mini-HOWTO.

As of version 0.09.03 additional per-device options are supported:

NOPOLL: Do not poll device at regular intervalls, but only upon
request via volcheck.
NOEJECT: Do not automatically try to eject devices after
unmounting them.
RO: Mount read-only.
SKIPROUND: Skip the next mount attempts after ejecting. Default
if 2. This can be changed at compile time using the option 
SKIPROUNDS. Use this to keep ATAPI CDROM drives from closing
to fast after an eject.

The option section starts at the end of the name section and continues
to the end of the line (or the next comment character). Options can be
specified upper- or lowercase, separated by commas, spaces, tabs or
even nothing at all. To enhance readability, this is not
recommended 

Notes
It may be necessary to reconfigure syslogd to protect against lots of
harmless messages generated by the kernel regarding failed mount
requests. See section .





Problems
Preamble
As with any program, this is by far not perfect. Although I've tested
every aspect that came into my mind, I'm quite sure, that I have
overlooked several cases, in which the daemon may abort, generating a
core dump. The first step should be to look at the log file
/var/adm/automountd.log by default. In many cases you
will find a brief description of the error that caused the abort(),
plus the file and line where the error was detected. If you want to
report an error to me, please send me the source you built it from
(especially the options you choose in the Makefile and the
modifications in the consts.h header).

Compilation problems
Currently I know of a problem compiling this program under RedHat
Linux. Copy processoptions-RedHat.h to 
processoptions.h. If this does not resolv the problem, please
contact me. See section . 

The Logfile
As stated above the daemon writes a logfile. This option is only
enabled when compiling without debug support (see
section ). Instead of writing its own logfile, automountd
can be compiled for using the syslog interface (See
section .
This file is used for logging the start and shutdown of
the server plus several error conditiones (both fatal and
non-fatal). The entries are separated by a line of stars and start
with a line naming the source file and line where the error was
detected, followed by the date and time of day when the error
occurred. The following lines contain the corresponding message. It looks
something like this:









In cases of fatal errors, the error message is preceeded by a line
containing the word ``Panic:'':











Error Messages
This section lists common error messages, the problem that usually
causes them and possible solutions. Note that short lines in the
configuration file will generate non-fatal error messages that contain
the offending line and say something like ``Unexpected EOL
As entries are read one by one, a missing field is noticed
at the end of the line, as there are not enough fields. Excess characters
after the defined fields are discarded. Do not use this as an implicit
comment. The comment character () is recognized when a line is parsed
and makes things clear.

Fatal Errors


Server seems to be already running 
Despite of the message, the real cause is simply the existance of the
fifo The default name is: /tmp/automountd.fifo used
for communication with the clients. It is created when the server
starts and removed if it terminates in a ``civilized'' fashion (upon a
fatal error that is recognized or via a signal handler). If a signal
that is not catched occurres or when the system goes down without the
proper shutdown procedure, this fifo may still exist although the
server is not running. In this case just remove the fifo: 
rm /tmp/automountd.fifo

Cannot create fifo, server may already be running 
This is the same as the preceding item.

Cannot open fifo 
No special points to watch, should not occurr.

malloc() failed 
The system has maybe limited resources. Normally the daemon should use
about 50k of system memory.

calloc() failed
See previous entry.

buffersize exceeded 
Although a simple message, it indicates that something is seriously
wrong: A read() returned more characters than the buffer provided
could hold. One possible way to produce this kind of error is to use
device names longer than about 255 characters. Should not occurr.

fseek() failed 
There is a failure during access to the initialization file. Should
not occurr. 

Initialization error 
Something went wrong during startup. Usually this error message will
not appear, as the error will in most cases be recognized and reported
at an earlier time.

Init file error 
There was an error reading the init file. Normally the error will be
reported at an earlier time with additional information.

Internal error (bad mount() values) 
Some arguments that have been checked for correctness are rejected by
the mount() system call. Check the configuration file. See
section .

effective UID is not root 
When the daemon is started by a normal user, the first mount attempt
will fail with this error message. The daemon is normally started at
boot time with superuser privileges. The 'eject' client is used by
normal users. For testing purposes see section .

Unknown error (bad errno) 
This indicates an unexpected errno value after the call to mount().

realloc() failed 
The dynamic size change of internal tables failed.  This can happen
due to memory limitations or by specifying an abnormal number of
devices in the config file. See section  for a possible
solution. Note: This is not a program failure. Theoretically the
server can handle several thousands of devices contained in config
file lines with unlimited length.

Config file () not found
The config file could not be found. Make sure that it exists.


Every error message text that is completely surrounded by parentheses
such as (Internal Error) is a really fatal error. This will only
occurr when the compiler failed or something like that. In this case
try to recompile and maybe change the optimization level.





Internals

This chapter will be almost useless for anyone who just wants to run
automount. People who want to compile and/or change automount will
want to read it to get a broad overview. For detailed information
refer to the comments in the sourcecode after reading this chapter.

Preamble
The design of the application may not be the best possible. So if you
have any suggestions, contact me (e-mail address see
section ).

Organization of the Sourcefiles
The following table will give an outline of the contents of the
various files. 
lll

File		&Functions	&Description

checkcmdline.c	&checkcmdline()	&checks for args

checkfifo.c		&openfifo()		&Creates fifo
			&checkfifo()		&check fifo for data

daemoninit.c		&daemoninit()		&make proc a daemon

ejectvolume.c		&ejectvolume()	&Physically eject media

getline.c		&getline()		&Read one line from
file

logmsg.c		&logmsg()		&Write msg to
logfile

main.c			&main()			&startup function

mainloop.c		&mainloop()		&main loop of
execution

panic.c			&panic()		&end process on
error

readinitfile.c	&str2mentry()		&conv. line to
structure
			&readinitfile()	&go through init
file

signal.c		&signal()		&implements signal()
using sigaction() 
			&			&providing ``reliable
signals'' 

signalhandlers.c	&sighuphandler()	&prepare for rereading init file
			&sigtermhandler()	&normal exit
			&sigsegvhandler()	&log SIGSEGV and
abort

unmount.c		&finddevice()		&looks for device in
table
			&unmountdevice()	&unmount device by
name




Overall Design
As stated above the application consists of a daemon and a user level
program. The two communicate via a  fifo (named pipe). After starting
up (reading the initfile and sending itself to background) the daemon
sleeps for DEFAULTINTERVALL or the value specified via the
commandline switch -i (in seconds). After the sleep it checks the
different flags for work to do. By now two flags are used:

Reread: Reread the init file.
checkrequest: Check all devices immediately.

Reread can be set 'by hand' using kill -HUP
pid, checkrequest is set by the volcheck client.

Then the fifo is checked for an unmount request. If one is present, it
is handled. The next step is to go through the table of mountable
devices and issue a mount command for each entry. Now the loop starts
again. Starting with version 0.08.00, the default is to combine the
two steps 'sleep' and 'check fifo' into one using 
select(). This function returns if either the fifo holds data or the
timeout occurred. The read from the fifo is only done when it actually
has data ready. This should reduce system load.
As of version 0.09.05 an additional option (SKIPROUND) was added
to allow for a delay to be added before an ejected device is tried
again. This is intended to help with the problem that ATAPI CDROM
drives close the tray upon the mount is tried. The duration is
controlled by the compile time option SKIPROUNDS, which gives
the number of subsequent mount operations to leave out.

The process is ended when a signal (SIGTERM or SIGQUIT) is
received. In this case the fifo is deleted and all devices mounted by
the daemon are unmounted. A compile time flag can be used to extend
this to call unmount for all devices in the configuration file.

Init file parser
This part (located in readinitfile.c) is quite simple. Two
functions are working together: the first (readinitfile()) goes
through the initfile line by line (using a lineread function that
allows (well, nearly) unlimited line lenghts. Lines starting with
COMMENTCHAR as well as empty lines are ignored, the others are
passed to the second function (str2mentry()) that breaks them up
into the pieces that fit into the structure that represents one device
(struct mountentry as defined in typedef.h). After removing any
comments each line is checked if enough entries exist to fill the
structure. Be aware of the fact that the entries themselfs are not
checked.

The Main Loop

This part implements the periodic services. The steps taken are
straightforward: After setting up various things, the endless loop is
entered (while(1)). This will give an outline on the normal case
(using select()), the other case is essentially the same.

if( mounttablesize <= alreadymounted) checks if all known
devices are already mounted. If so, the select call is set up for
endless sleep, as this state can only change via data arriving from a
client (tt eject or volcheck) or when SIGHUP is
received. Either will cause select to return.

When SIGHUP is received, rereadinitflag is set by the
signal handler. This condition is checked now. When set, the
initialization file is read once again.

The next thing is to check the fifo for data. This step is skipped if
select did not return because data arrived at the fifo. After
processing the client requests (in function checkfifo()), the
mount count is adjusted.

After this that mount table is scanned and every device that's poll
flag is set to YES will receive its mount try. When 
checkrequest is set, the setting of the poll flag is ignored. Note
that there is are two possibilities for the device status that will
prevent a mount call: The device is already mounted (mounted is
set to YES) or an unrecoverable error accurred during an earlier mount
call (mounted set to ERROR). The structure used for the entries
in the mount table (struct mountentry) is defined in 
typedef.h.

After this, the checkrequest flag is reset and the loop starts
over.





Advanced Topics
Tips on the programs
Client
To this time the eject client can easily be replaced
with a shell alias of the form:
alias eject='echo name /tmp/automountd.fifo'
where name is the name given to the device in the configuration
file and the optput is redirected to the default fifo name used by
the server. This can be changed in the consts.h file at compile
time.

Server

By default the daemon tries to eject any media that it unmounted,
exept when it exits upon receiving a signal. In this case all devices
that were mounted are unmounted.

Be careful not to terminate the daemon when any device mounted by the
daemon is still in use: It will neither be unmounted nor will it be in
the /etc/mtab file so that normal umount can remove it. It
is possible to change the source code so that the unmount() call in
the SIGTERM handler does not test wether the device is currently
mounted and tries to unmount any device found in the configuration
file. So the daemon can be started again after a failure and
terminated, thereby unmounting the device. See the makefile options
in .

If syslogd's system time (showed by ps -lx or ps -le on
System V) increases abnormally after starting the
daemon, add the following to the '*.info' line in the file 
/etc/syslogd.conf:
kern.none.
This will prevent syslogd from logging kernel informational
messages. Such a message is created every time the daemon tries to
mount a device, when no media is present.

The syntax given in chapter  is not completely correct: the
intervall option is ignored, the default intervall (which can be
changed at compile time) is used. This will be corrected in a later
version.

Rebuilding from Sourcecode

This section will give you a (hopefully) complete description of how
to change the default behaviour and the steps to rebuild the programs
from sourcecode. For an overview of the organization of the
sourcecode, refer to chapter .

Steps to rebuild from source
The following steps are usually to perform if you want to rebuild the
programs from the source code:

Choose target platform
Reconfigure 'Makefile' (See section  and
section )
Call make
Optionally : make docs
Optionally : make install (You have to be root to do this)

Section  describes the targets in the Makefile.

Choosing the plattform
This is quite simple, as by now there are only two versions of Unix
supported: Solaris, which was used for development and Linux as the
intended target plattform. Go through the Makefile and uncomment the
appropriate lines. I guess that noone will try to use this program on
solaris, as this system already has an automounter. The makefile
therefore comes preconfigured for Linux.

Reconfiguring the Makefile

Here you will find the options you can change in the makefile to
change the behaviour of the daemon. If you do not set any of these
variables, a default value is used. Any of these options can be added
to the line OPTIONFLAGS in the makefile in the form 
-Doptionname=value 
such as this: 
-DDEFAULTINTERVALL=3 
If not indicated otherwise, you must specify a value for each option
you use. If you want the default value to be used, do not add the
option name to this line. Other options just have to be defined to
change the behaviour (they have the line ``No value must be
specified'' in their description below). These options can be added in
the following form: 
-Doptionname 

Makefile options are checked and corrected if necessary (there are
some options that won't work together). This is done in the include
file processoptions.h. Do not change this file, as the
restrictions imposed are necessary. You might get it to compile
using incompatible options together, but it will break at runtime
(according to Murphy's law: when you expect it least).


DEFAULTINTERVALL 
Can be used to change the interval between the mount attempts.The
less this value gets, the more CPU intensive it becomes. Normally the
default of 5 seconds will be usable.

DEFAULTINITFILE 
Set the filename of the initfile to use. This must be a string
containing a valid filename. If the file does not exist, the daemon
will not start. Note that the file is not required to have meaningful
contents, it is just has to exist.

FIFONAME 
Change the name of the fifo used for communication with the client.
This must be a string containing a valid filename. If the file exists,
the daemon will not start. Make sure that each user has access
permission in the directory so that the 'eject' client can write to
the fifo. Maybe you should set the sticky bit for this directory to
prevent a user to delete files of other users in that directory.

EJECTONEXIT 
Used to force sending an eject command to each volume when
the server terminates. This option is not very sophisticated, as the
only supported devices are CDROM drives.
No value must be specified.

FORCEUNMOUNTONEXIT 
This option makes the daemon call unmount on each device in the init
file, whether is was mounted by the daemon or not. If this option is
used, the daemon can more easily recover from a crash (going down
without the normal exit routine while the system keeps running). In
that case you should start the daemon, stop it after a few seconds
using the kill command with either SIGTERM or SIGQUIT and
then restart it. This recovering procedure is necessary as the mounted
devices are not entered into /etc/mtab, so that they possibliy
cannot be unmounted with 'umount'.
No value must be specified.

USESYSLOGD 
Keep automountd from using its own logfile to be used. Use calls to
syslogd instead. See your systems manual (``man syslogd'' will give
you advice where to look for the messages sent to the syslogd
daemon).
No value must be specified.

USEEXTENDEDSIGARGS 
Cause some signalhandlers to use additional arguments that are
provided by some Unix implementations. This feature is only used for
unexpected signals (by now only SIGSEGV is considered important), not
for the normal signals as SIGTERM or SIGHUP.
No value must be specified.

DONTCATCHSIGSEGV 
If you want to do debugging, you can turn off the logging of SIGSEGV to
get a more meaningful core file.
No value must be specified.

DONTUSESELECT 
Prevent the daemon from using select(). This option restores the
default behaviour of versions prior to 0.08.00 i.e. the daemon does not
answer client requests, but serves them during the normal activity
period (every DEFAULTINTERVALL seconds). Without this option, client
requests are served asynchroniously. 
No value must be specified.

MONITORMOUNTCOUNT 
This cannot be used in conjunction with DONTUSESELECT. Will
extend sleep periods when all monitored devices are mounted. 
No value must be specified.

DONTEJECT 
When set, this option prevents the daemon from sending the eject
command to the device.

SKIPROUNDS 
Used to change the intervall increase activated by the option
SKIPROUND from the default of 2.



Performance Considerations

This is just a collectoin of tips how you can change performance and
system load with the provided options.
Reducing System Load

Don't set DEFAULTINTERVALL to anything less than 3. Normally
the default value of 5 will be usable.
Use MONITORMOUNTCOUNT option to extend the sleep
period when no unmounted devices are left.
Don't use the DONTUSESELECT option. This will add
considerable overhead (see section ).


Reducing Reaction Time

Set DEFAULTINTERVALL as low as possible. This will
increase system load. Don't try values less than 2.
Use MONITORMOUNTCOUNT option to extend the sleep
period when no unmounted devices are left.
Don't use the DONTUSESELECT option. This will add
considerable overhead (see section ).



Makefile Targets

The standard makefile has the following targets:

Standard targets

all: rebuild all executable files
clean: remove all files created by make all
realclean: remove all unnecessary files (emacs backups, latex
aux etc.) plus all files that can be recreated from the sources
(program files, object files)


Extended targets

edit: Create TAGS file for emacs and load (EDITOR) with all
source files
lint: lint sources in the right context (in the configuration
used to compile), piping output through (MORE).
docs: create documentation files (i.e. call (LATEX) on all
documentation sources).
install: copy binaries to (DAEMONDIR) / (CLIENTDIR) and
change owner and group to (OWNER) and (GROUP).
automountd: create just the daemon executable.
eject: create just the client executable.



There are lots of subtargets that are used by the ``interface''
targets. Do not change them. In the definitiones at the start of the
makefile, there are some programs that are used within the makefile
(LATEX, MORE, EDITOR). They can be changed, but of course
the features of the other programs should be identical. (for example do
not try to use  instead of ).

Testing the compiled daemon

Normally the daemon must be run with root-privileges. Just
to mention it: Do not make it setuid root, start it from rc.local or
something simmilar. See section  . Nevertheless it is 
possible for a normal user to start the daemon as long as 
the configuration file exists and is empty, as in this case no mount()
calls are issued (which is the only thing that actually requires root
status).
In this case the daemon must be compiled without the 
MONITORMOUNTCOUNT option. Otherwise it will block at the
beginning of the main loop as there are no mountable devices.





History
Here is a brief version history of this package. The numbering system
is very simple: MM.mm.ff, where MM means ``Major Version'', mm is
``minor version'' and ff stand for ``bugfix''. Major version of ``0''
means beta status. Each level mentioned in here was used at least for
a while. Therefore even minor modifications sometimes have to have
their own bugfix-number to keep them distinct.


Version 0.05.00 
The first published version. It turned out to leek memory: It grew
from 48k to 17MB within 3 or 4 days. Poor documentation. 
This version number takes into account previous versions that were
runable, but object to major design changes.

Version 0.05.03 
Big memory leak removed.

Version 0.05.04 
Removed another two minor leaks.

Version 0.06.00 
Added several compile time options. See section 
for details.

Version 0.06.01 
Removed minor bugs from the new code (see above).

Version 0.07.00 
Added safer but more resource intensive mount subroutine using fork().
Enhanced comment processing when reading the config file.

Version 0.07.01 
Made the new mount subroutine optional. Removed bug that sometimes
prevented devices from being unmounted.

Version 0.07.02 
Removed old bug from exit routine, that resulted in a far from obvious
SIGSEGV.

Version 0.07.03 
Error exit modified so that the fifo should be removed in any case
when the daemon exits.

Version 0.08.00 
Changed the delay in the main loop. Now uses select(), so it responds
immediately to client (eject) requests. Prepared to return status
message to client. Will be enabled as soon as Linux supports System V
style streams.

Version 0.08.01 
Rearranged some  include directives, added missing include file for
Linux.

Version 0.08.02 
Added mechanism to decrease activity when no more mountable devices
are available.

Version 0.08.03 
Added signal returned by Linux 1.2.13 when no CD is inserted as ignored.

Version 0.09.00 
Added volcheck client and the ``NOPOLL'' flag. Updated
documentation and expanded chapter .

Version 0.09.01 
Added the configuration file to the distribution package. Added an
ASCII version of the documentation.

Version 0.09.02 
Added the DONTEJECT compile-time option.

Version 0.09.03 
Removed an incorrect long forgotten cast to void in unmount.c, found
by Masaki Fukushima. Thanks.
Enhanced the parser for the options section of the configuration file
and added several per-device options.

Version 0.09.04 
Removed some annyoing errors from the options parser. Added code to
eject ZIP disks (thanks to Jeff Tranter (jefftranter@pobox.com)).
Removed a gcc warning regarding missing parentheses in a macro.
'make install' now copies the default configuration file  to /etc if
no config file is found there.

Version 0.09.05 
Added a workaround for ATAPI CDROM drives to give more time to get the
CD out of the tray after using eject. What I hope to get ready is that
an open tray is recognized to keep the daemon from closing it.
Motivated by Till Bubeck (bubeck@delix.de), asked for by many others.






Copyright and Contact

Written and  Copyright 1995/96/97/98 by Wolfram
Saringer.
 Copyright 1998 BSG - OEG. 

The actual copyright holder as of version 0.09.05 is BSG - OEG, which
will change essentially nothing regarding the distribution policy,
except that there now is a supporting Web site, which will mainly be
used to distribute smaller updates. I hope to be able to invest a
little more time from now on.

This program package is published under the GNU General Public
License. You may modify the source code to suit your needs, but you
have to change the name if you want to redistribute it with your
changes applied. I guess, running this program won't hurt your
computer, but if it does  well, I'm sorry. Use it at your own
risk.

Part of the code (the daemon startup code) is derived from or
inspired by example code in the (very good) book ``Advanced
Programming in the Unix Environment'' by W. Richard Stevens.
Manual generated with 2e under Solaris 2.6 x86. 

Comments and suggestions are welcome. Please write to: 
automount@bsg.at

I will try to give you feedback as time allows. Sorry for any delays
in the past. Smaller updates and fixes to this program will only be
available on the following web site:
http://www.bsg.at/automount
Major versions will still be posted on sunsite.unc.edu.



