aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorPedro F. Giffuni <pfg@FreeBSD.org>2015-01-28 22:55:06 +0000
committerPedro F. Giffuni <pfg@FreeBSD.org>2015-01-28 22:55:06 +0000
commite925d4a747df4a349c2baac436a71f606945baa5 (patch)
treee3a2ccc21623f0453c6f43f9016535205ba10d21 /doc
parent509fcedcfec077a6070002f4059db0ae675be869 (diff)
downloadsrc-e925d4a747df4a349c2baac436a71f606945baa5.tar.gz
src-e925d4a747df4a349c2baac436a71f606945baa5.zip
amd: flatten the tree
Notes
Notes: svn path=/vendor/amd/dist/; revision=277863
Diffstat (limited to 'doc')
-rw-r--r--doc/am-utils.texi8686
-rw-r--r--doc/stamp-vti4
-rw-r--r--doc/texinfo.tex7014
-rw-r--r--doc/version.texi4
4 files changed, 15708 insertions, 0 deletions
diff --git a/doc/am-utils.texi b/doc/am-utils.texi
new file mode 100644
index 000000000000..1cc46b608bae
--- /dev/null
+++ b/doc/am-utils.texi
@@ -0,0 +1,8686 @@
+\input texinfo @c -*-texinfo-*-
+@c
+@c Copyright (c) 1997-2006 Erez Zadok
+@c Copyright (c) 1989 Jan-Simon Pendry
+@c Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+@c Copyright (c) 1989 The Regents of the University of California.
+@c All rights reserved.
+@c
+@c This code is derived from software contributed to Berkeley by
+@c Jan-Simon Pendry at Imperial College, London.
+@c
+@c Redistribution and use in source and binary forms, with or without
+@c modification, are permitted provided that the following conditions
+@c are met:
+@c 1. Redistributions of source code must retain the above copyright
+@c notice, this list of conditions and the following disclaimer.
+@c 2. Redistributions in binary form must reproduce the above copyright
+@c notice, this list of conditions and the following disclaimer in the
+@c documentation and/or other materials provided with the distribution.
+@c 3. All advertising materials mentioning features or use of this software
+@c must display the following acknowledgment:
+@c This product includes software developed by the University of
+@c California, Berkeley and its contributors.
+@c 4. Neither the name of the University nor the names of its contributors
+@c may be used to endorse or promote products derived from this software
+@c without specific prior written permission.
+@c
+@c THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+@c ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+@c IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+@c ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+@c FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+@c DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+@c OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+@c HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+@c LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+@c OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+@c
+@c
+@c File: am-utils/doc/am-utils.texi
+@c
+@setfilename am-utils.info
+
+@include version.texi
+
+@c info directory entry
+@dircategory Administration
+@direntry
+* Am-utils: (am-utils). The Amd automounter suite of utilities
+@end direntry
+
+@settitle Am-utils (4.4BSD Automounter Utilities)
+@setchapternewpage odd
+
+@titlepage
+@title Am-utils (4.4BSD Automounter Utilities)
+@subtitle For version @value{VERSION}, @value{UPDATED}
+
+@author Erez Zadok
+(Originally by Jan-Simon Pendry and Nick Williams)
+
+@page
+Copyright @copyright{} 1997-2006 Erez Zadok
+@*
+Copyright @copyright{} 1989 Jan-Simon Pendry
+@*
+Copyright @copyright{} 1989 Imperial College of Science, Technology & Medicine
+@*
+Copyright @copyright{} 1989 The Regents of the University of California.
+@sp
+All Rights Reserved.
+@vskip 1ex
+Permission to copy this document, or any portion of it, as
+necessary for use of this software is granted provided this
+copyright notice and statement of permission are included.
+@end titlepage
+@page
+
+@c Define a new index for options.
+@syncodeindex pg cp
+@syncodeindex vr cp
+
+@ifinfo
+
+@c ################################################################
+@node Top, License, , (DIR)
+
+@b{Am-utils (4.4BSD Automounter Utilities) User Manual}
+@*
+For version @value{VERSION}, @value{UPDATED}
+
+@b{Erez Zadok}
+@*
+(Originally by Jan-Simon Pendry and Nick Williams)
+
+Copyright @copyright{} 1997-2006 Erez Zadok
+@*
+Copyright @copyright{} 1989 Jan-Simon Pendry
+@*
+Copyright @copyright{} 1989 Imperial College of Science, Technology & Medicine
+@*
+Copyright @copyright{} 1989 The Regents of the University of California.
+@*
+All Rights Reserved.
+
+Permission to copy this document, or any portion of it, as
+necessary for use of this software is granted provided this
+copyright notice and statement of permission are included.
+
+Am-utils is the 4.4BSD Automounter Tool Suite, which includes the Amd
+automounter, the Amq query and control program, the Hlfsd daemon, and
+other tools. This Info file describes how to use and understand the
+tools within Am-utils.
+@end ifinfo
+
+@menu
+* License:: Explains the terms and conditions for using
+ and distributing Am-utils.
+* Distrib:: How to get the latest Am-utils distribution.
+* AddInfo:: How to get additional information.
+* Intro:: An introduction to Automounting concepts.
+* History:: History of am-utils' development.
+* Overview:: An overview of Amd.
+* Supported Platforms:: Machines and Systems supported by Amd.
+* Mount Maps:: Details of mount maps.
+* Amd Command Line Options:: All the Amd command line options explained.
+* Filesystem Types:: The different mount types supported by Amd.
+* Amd Configuration File:: The amd.conf file syntax and meaning.
+* Run-time Administration:: How to start, stop and control Amd.
+* FSinfo:: The FSinfo filesystem management tool.
+* Hlfsd:: The Home-Link Filesystem server.
+* Assorted Tools:: Other tools which come with am-utils.
+* Examples:: Some examples showing how Amd might be used.
+* Internals:: Implementation details.
+* Acknowledgments & Trademarks:: Legal Notes.
+
+Indexes
+* Index:: An item for each concept.
+@end menu
+
+@iftex
+@unnumbered Preface
+
+This manual documents the use of the 4.4BSD automounter tool suite,
+which includes @i{Amd}, @i{Amq}, @i{Hlfsd}, and other programs. This is
+primarily a reference manual. While no tutorial exists, there are
+examples available. @xref{Examples}.
+
+This manual comes in two forms: the published form and the Info form.
+The Info form is for on-line perusal with the INFO program which is
+distributed along with GNU texinfo package (a version of which is
+available for GNU Emacs).@footnote{GNU packages can be found in
+@url{ftp://ftp.gnu.org/pub/gnu/}.} Both forms contain substantially
+the same text and are generated from a common source file, which is
+distributed with the @i{Am-utils} source.
+@end iftex
+
+@c ################################################################
+@node License, Distrib, Top, Top
+@unnumbered License
+@cindex License Information
+
+@i{Am-utils} is not in the public domain; it is copyrighted and there are
+restrictions on its distribution.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+@enumerate
+
+@item
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+@item
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+@item
+All advertising materials mentioning features or use of this software
+must display the following acknowledgment:
+
+@cartouche
+``This product includes software developed by the University of
+California, Berkeley and its contributors, as well as the Trustees of
+Columbia University.''
+@end cartouche
+
+@item
+Neither the name of the University nor the names of its contributors may
+be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+@end enumerate
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+@c ################################################################
+@node Distrib, AddInfo, License, Top
+@unnumbered Source Distribution
+@cindex Source code distribution
+@cindex Obtaining the source code
+
+The @i{Am-utils} home page is located in
+@example
+@url{http://www.am-utils.org/}
+@end example
+
+You can get the latest distribution version of @i{Am-utils} from
+@example
+@url{ftp://ftp.am-utils.org/pub/am-utils/am-utils.tar.gz}
+@end example
+
+Additional alpha, beta, and release distributions are available in
+@example
+@url{ftp://ftp.am-utils.org/pub/am-utils/}.
+@end example
+
+Revision 5.2 was part of the 4.3BSD Reno distribution.
+
+Revision 5.3bsdnet, a late alpha version of 5.3, was part
+of the BSD network version 2 distribution
+
+Revision 6.0 was made independently by
+@email{ezk@@cs.columbia.edu,Erez Zadok} at the Computer Science
+Department of @uref{http://www.cs.columbia.edu/,Columbia University},
+as part of his
+@uref{http://www.fsl.cs.sunysb.edu/docs/zadok-thesis-proposal/,PhD
+thesis work}. Am-utils (especially version 6.1) continues to be
+developed and maintained at the
+@uref{http://www.cs.sunysb.edu/,Computer Science Department} of
+@uref{http://www.stonybrook.edu/,Stony Brook University}, as a service
+to the user community.
+
+
+@xref{History}, for more details.
+
+@c ################################################################
+@node AddInfo, Intro, Distrib, Top
+@unnumbered Getting Additional Information
+@cindex Getting Additional Information
+
+@unnumberedsec Bug Reports
+@cindex Bug reports
+
+Before reporting a bug, see if it is a known one in the
+@uref{http://www.am-utils.org/docs/am-utils/BUGS.txt,bugs} file.
+
+If you find a problem and hopefully you can reproduce it, please
+describe it in detail and
+@uref{https://bugzilla.filesystems.org/,submit a bug report} via
+@uref{http://www.bugzilla.org/,Bugzilla}. Alternatively, you can send
+your bug report to @email{am-utils@@am-utils.org} quoting the details
+of the release and your configuration. These details can be obtained
+by running the command @samp{amd -v}. It would greatly help if you
+could provide a reproducible procedure for detecting the bug you are
+reporting.
+
+Providing working patches is highly encouraged. Every patch
+incorporated, however small, will get its author an honorable mention in
+the @uref{http://www.am-utils.org/docs/am-utils/AUTHORS.txt,authors
+file}.
+
+@unnumberedsec Mailing Lists
+@cindex Mailing lists
+
+There are several mailing lists for people interested in keeping up-to-date
+with developments.
+
+@c ###############
+
+@enumerate
+
+@item
+The users mailing list, @samp{am-utils} is for
+
+@itemize @minus
+@item
+announcements of alpha and beta releases of am-utils
+@item
+reporting of bugs and patches
+@item
+discussions of new features for am-utils
+@item
+implementation and porting issues
+@end itemize
+
+To subscribe, visit
+@url{http://lists.am-utils.org/mailman/listinfo/am-utils}. After
+subscribing, you can post a message to this list at
+@email{am-utils@@am-utils.org}. To avoid as much spam as
+possible, only subscribers to this list may post to it.
+
+Subscribers of @samp{am-utils} are most helpful if they have the time
+and resources to test new and development versions of amd, on as many
+different platforms as possible. They should also be prepared to
+learn and use the GNU Autoconf, Automake, and Libtool packages, as
+needed; and of course, become familiar with the complex code in the
+am-utils package. In other words, subscribers on this list should
+hopefully be able to contribute meaningfully to the development of
+amd.
+
+Note that this @samp{am-utils} list used to be called @samp{amd-dev}
+before January 1st, 2004. Please use the new name, @samp{am-utils}.
+
+@item
+The announcements mailing list, @samp{am-utils-announce} is for
+announcements only (mostly new releases). To subscribe, visit
+@url{http://lists.am-utils.org/mailman/listinfo/am-utils-announce}.
+This list is read-only: only am-utils developers may post to it.
+
+@item
+We distribute nightly CVS snapshots in
+@url{ftp://ftp.am-utils.org/pub/am-utils/snapshots/daily/}. If you
+like to get email notices of commits to the am-utils CVS repository,
+subscribe to the CVS logs mailing list, @samp{am-utils-cvs} at
+@url{http://lists.am-utils.org/mailman/listinfo/am-utils-cvs}.
+
+@item
+The older list which was used to user discussions, @samp{amd-workers},
+is defunct as of January 2004. (Its last address was
+@email{amd-workers@@majordomo.glue.umd.edu}.) Don't use
+@samp{amd-workers}: use the newer, more active @samp{am-utils} list.
+
+@item
+For completeness, there's a developers-only closed list called
+@samp{am-utils-developers@@am-utils.org}.
+
+@end enumerate
+
+@unnumberedsec Am-utils Book
+@cindex Am-utils book
+@cindex Amd book
+@cindex Automounter book
+@cindex book
+
+@email{ezk@@cs.sunysb.edu,Erez Zadok} wrote a
+@uref{http://www.fsl.cs.sunysb.edu/docs/amd-book/,book}, titled @i{Linux NFS and
+Automounter Administration}, ISBN 0-7821-2739-8, (Sybex, 2001). The
+book is full of details and examples that go beyond what this manual
+has. The book also covers NFS in great detail. Although the book is
+geared toward Linux users, it is general enough for any Unix
+administrator and contains specific sections for non-Linux systems.
+
+@c ################################################################
+@node Intro, History, AddInfo, Top
+@unnumbered Introduction
+@cindex Introduction
+
+An @dfn{automounter} maintains a cache of mounted filesystems.
+Filesystems are mounted on demand when they are first referenced,
+and unmounted after a period of inactivity.
+
+@i{Amd} may be used as a replacement for Sun's automounter. The choice
+of which filesystem to mount can be controlled dynamically with
+@dfn{selectors}. Selectors allow decisions of the form ``hostname is
+@var{this},'' or ``architecture is not @var{that}.'' Selectors may be
+combined arbitrarily. @i{Amd} also supports a variety of filesystem
+types, including NFS, UFS and the novel @dfn{program} filesystem. The
+combination of selectors and multiple filesystem types allows identical
+configuration files to be used on all machines thus reducing the
+administrative overhead.
+
+@i{Amd} ensures that it will not hang if a remote server goes down.
+Moreover, @i{Amd} can determine when a remote server has become
+inaccessible and then mount replacement filesystems as and when they
+become available.
+
+@i{Amd} contains no proprietary source code and has been ported to
+numerous flavors of Unix.
+
+@c ################################################################
+@node History, Overview, Intro, Top
+@unnumbered History
+@cindex History
+
+The @i{Amd} package has been without an official maintainer since 1992.
+Several people have stepped in to maintain it unofficially. Most
+notable were the `upl' (Unofficial Patch Level) releases of @i{Amd},
+created by me (@email{ezk@@cs.sunysb.edu,Erez Zadok}), and available from
+@url{ftp://ftp.am-utils.org/pub/amd/}. The last such unofficial
+release was `upl102'.
+
+Through the process of patching and aging, it was becoming more and more
+apparent that @i{Amd} was in much need of revitalizing. Maintaining
+@i{Amd} had become a difficult task. I took it upon myself to cleanup
+the code, so that it would be easier to port to new platforms, add new
+features, keep up with the many new feature requests, and deal with the
+never ending stream of bug reports.
+
+I have been working on such a release of @i{Amd} on and off since
+January of 1996. The new suite of tools is currently named "am-utils"
+(AutoMounter Utilities), in line with GNU naming conventions, befitting
+the contents of the package. In October of 1996 I had received enough
+offers to help me with this task that I decided to make a mailing list
+for this group of people. Around the same time, @i{Amd} had become a
+necessary part of my PhD thesis work, resulting in more work performed
+on am-utils.
+
+Am-utils version 6.0 was numbered with a major new release number to
+distinguish it from the last official release of @i{Amd} (5.x). Many
+new features have been added such as a GNU @code{configure} system, NFS
+Version 3, a run-time configuration file (`amd.conf'), many new ports,
+more scripts and programs, as well as numerous bug fixes. Another
+reason for the new major release number was to alert users of am-utils
+that user-visible interfaces may have changed. In order to make @i{Amd}
+work well for the next 10 years, and be easier to maintain, it was
+necessary to remove old or unused features, change various syntax files,
+etc. However, great care was taken to ensure the maximum possible
+backwards compatibility.
+
+Am-utils version 6.1 has autofs support for Linux and Solaris 2.5+ as
+@i{the} major new feature, in addition to several other minor new
+features. The autofs support is completely transparent to the
+end-user, aside from the fact that @code{/bin/pwd} now always returns
+the correct amd-ified path. The administrator can easily switch
+between NFS and autofs mounts by changing one parameter in
+@code{amd.conf}. Autofs support and maintenance was developed in
+conjunction with @email{ionut@@badula.org,Ion Badulescu}.
+
+@c ################################################################
+@node Overview, Supported Platforms, History, Top
+@chapter Overview
+
+@i{Amd} maintains a cache of mounted filesystems. Filesystems are
+@dfn{demand-mounted} when they are first referenced, and unmounted after
+a period of inactivity. @i{Amd} may be used as a replacement for Sun's
+@b{automount}(8) program. It contains no proprietary source code and
+has been ported to numerous flavors of Unix. @xref{Supported
+Platforms}.@refill
+
+@i{Amd} was designed as the basis for experimenting with filesystem
+layout and management. Although @i{Amd} has many direct applications it
+is loaded with additional features which have little practical use. At
+some point the infrequently used components may be removed to streamline
+the production system.
+
+@i{Amd} supports the notion of @dfn{replicated} filesystems by evaluating
+each member of a list of possible filesystem locations one by one.
+@i{Amd} checks that each cached mapping remains valid. Should a mapping be
+lost -- such as happens when a fileserver goes down -- @i{Amd} automatically
+selects a replacement should one be available.
+
+@menu
+* Fundamentals::
+* Filesystems and Volumes::
+* Volume Naming::
+* Volume Binding::
+* Operational Principles::
+* Mounting a Volume::
+* Automatic Unmounting::
+* Keep-alives::
+* Non-blocking Operation::
+@end menu
+
+@node Fundamentals, Filesystems and Volumes, Overview, Overview
+@comment node-name, next, previous, up
+@section Fundamentals
+@cindex Automounter fundamentals
+
+The fundamental concept behind @i{Amd} is the ability to separate the
+name used to refer to a file from the name used to refer to its physical
+storage location. This allows the same files to be accessed with the
+same name regardless of where in the network the name is used. This is
+very different from placing @file{/n/hostname} in front of the pathname
+since that includes location dependent information which may change if
+files are moved to another machine.
+
+By placing the required mappings in a centrally administered database,
+filesystems can be re-organized without requiring changes to
+configuration files, shell scripts and so on.
+
+@node Filesystems and Volumes, Volume Naming, Fundamentals, Overview
+@comment node-name, next, previous, up
+@section Filesystems and Volumes
+@cindex Filesystem
+@cindex Volume
+@cindex Fileserver
+@cindex sublink
+
+@i{Amd} views the world as a set of fileservers, each containing one or
+more filesystems where each filesystem contains one or more
+@dfn{volumes}. Here the term @dfn{volume} is used to refer to a
+coherent set of files such as a user's home directory or a @TeX{}
+distribution.@refill
+
+In order to access the contents of a volume, @i{Amd} must be told in
+which filesystem the volume resides and which host owns the filesystem.
+By default the host is assumed to be local and the volume is assumed to
+be the entire filesystem. If a filesystem contains more than one
+volume, then a @dfn{sublink} is used to refer to the sub-directory
+within the filesystem where the volume can be found.
+
+@node Volume Naming, Volume Binding, Filesystems and Volumes, Overview
+@comment node-name, next, previous, up
+@section Volume Naming
+@cindex Volume names
+@cindex Network-wide naming
+@cindex Replicated volumes
+@cindex Duplicated volumes
+@cindex Replacement volumes
+
+Volume names are defined to be unique across the entire network. A
+volume name is the pathname to the volume's root as known by the users
+of that volume. Since this name uniquely identifies the volume
+contents, all volumes can be named and accessed from each host, subject
+to administrative controls.
+
+Volumes may be replicated or duplicated. Replicated volumes contain
+identical copies of the same data and reside at two or more locations in
+the network. Each of the replicated volumes can be used
+interchangeably. Duplicated volumes each have the same name but contain
+different, though functionally identical, data. For example,
+@samp{/vol/tex} might be the name of a @TeX{} distribution which varied
+for each machine architecture.@refill
+
+@i{Amd} provides facilities to take advantage of both replicated and
+duplicated volumes. Configuration options allow a single set of
+configuration data to be shared across an entire network by taking
+advantage of replicated and duplicated volumes.
+
+@i{Amd} can take advantage of replacement volumes by mounting them as
+required should an active fileserver become unavailable.
+
+@node Volume Binding, Operational Principles, Volume Naming, Overview
+@comment node-name, next, previous, up
+@section Volume Binding
+@cindex Volume binding
+@cindex Unix namespace
+@cindex Namespace
+@cindex Binding names to filesystems
+
+Unix implements a namespace of hierarchically mounted filesystems. Two
+forms of binding between names and files are provided. A @dfn{hard
+link} completes the binding when the name is added to the filesystem. A
+@dfn{soft link} delays the binding until the name is accessed. An
+@dfn{automounter} adds a further form in which the binding of name to
+filesystem is delayed until the name is accessed.@refill
+
+The target volume, in its general form, is a tuple (host, filesystem,
+sublink) which can be used to name the physical location of any volume
+in the network.
+
+When a target is referenced, @i{Amd} ignores the sublink element and
+determines whether the required filesystem is already mounted. This is
+done by computing the local mount point for the filesystem and checking
+for an existing filesystem mounted at the same place. If such a
+filesystem already exists then it is assumed to be functionally
+identical to the target filesystem. By default there is a one-to-one
+mapping between the pair (host, filesystem) and the local mount point so
+this assumption is valid.
+
+@node Operational Principles, Mounting a Volume, Volume Binding, Overview
+@comment node-name, next, previous, up
+@section Operational Principles
+@cindex Operational principles
+
+@i{Amd} operates by introducing new mount points into the namespace.
+These are called @dfn{automount} points. The kernel sees these
+automount points as NFS filesystems being served by @i{Amd}. Having
+attached itself to the namespace, @i{Amd} is now able to control the
+view the rest of the system has of those mount points. RPC calls are
+received from the kernel one at a time.
+
+When a @dfn{lookup} call is received @i{Amd} checks whether the name is
+already known. If it is not, the required volume is mounted. A
+symbolic link pointing to the volume root is then returned. Once the
+symbolic link is returned, the kernel will send all other requests
+direct to the mounted filesystem.
+
+If a volume is not yet mounted, @i{Amd} consults a configuration
+@dfn{mount-map} corresponding to the automount point. @i{Amd} then
+makes a runtime decision on what and where to mount a filesystem based
+on the information obtained from the map.
+
+@i{Amd} does not implement all the NFS requests; only those relevant
+to name binding such as @dfn{lookup}, @dfn{readlink} and @dfn{readdir}.
+Some other calls are also implemented but most simply return an error
+code; for example @dfn{mkdir} always returns ``read-only filesystem''.
+
+@node Mounting a Volume, Automatic Unmounting, Operational Principles, Overview
+@comment node-name, next, previous, up
+@section Mounting a Volume
+@cindex Mounting a volume
+@cindex Location lists
+@cindex Alternate locations
+@cindex Mount retries
+@cindex Background mounts
+
+Each automount point has a corresponding mount map. The mount map
+contains a list of key--value pairs. The key is the name of the volume
+to be mounted. The value is a list of locations describing where the
+filesystem is stored in the network. In the source for the map the
+value would look like
+
+@display
+location1 location2 @dots{} locationN
+@end display
+
+@i{Amd} examines each location in turn. Each location may contain
+@dfn{selectors} which control whether @i{Amd} can use that location.
+For example, the location may be restricted to use by certain hosts.
+Those locations which cannot be used are ignored.
+
+@i{Amd} attempts to mount the filesystem described by each remaining
+location until a mount succeeds or @i{Amd} can no longer proceed. The
+latter can occur in three ways:
+
+@itemize @bullet
+@item
+If none of the locations could be used, or if all of the locations
+caused an error, then the last error is returned.
+
+@item
+If a location could be used but was being mounted in the background then
+@i{Amd} marks that mount as being ``in progress'' and continues with
+the next request; no reply is sent to the kernel.
+
+@item
+Lastly, one or more of the mounts may have been @dfn{deferred}. A mount
+is deferred if extra information is required before the mount can
+proceed. When the information becomes available the mount will take
+place, but in the mean time no reply is sent to the kernel. If the
+mount is deferred, @i{Amd} continues to try any remaining locations.
+@end itemize
+
+Once a volume has been mounted, @i{Amd} establishes a @dfn{volume
+mapping} which is used to satisfy subsequent requests.@refill
+
+@node Automatic Unmounting, Keep-alives, Mounting a Volume, Overview
+@comment node-name, next, previous, up
+@section Automatic Unmounting
+
+To avoid an ever increasing number of filesystem mounts, @i{Amd} removes
+volume mappings which have not been used recently. A time-to-live
+interval is associated with each mapping and when that expires the
+mapping is removed. When the last reference to a filesystem is removed,
+that filesystem is unmounted. If the unmount fails, for example the
+filesystem is still busy, the mapping is re-instated and its
+time-to-live interval is extended. The global default for this grace
+period is controlled by the @code{-w} command-line option (@pxref{-w
+Option, -w}) or the @i{amd.conf} parameter @samp{dismount_interval}
+(@pxref{dismount_interval Parameter}). It is also possible to set this
+value on a per-mount basis (@pxref{opts Option, opts, opts}).
+
+Filesystems can be forcefully timed out using the @i{Amq} command.
+@xref{Run-time Administration}. Note that on new enough systems that
+support forced unmounts, such as Linux, @i{Amd} can try to use the
+@b{umount2}(2) system call to force the unmount, if the regular
+@b{umount}(2) system call failed in a way that indicates that the
+mount point is hung or stale. @xref{forced_unmounts Parameter}.
+
+@node Keep-alives, Non-blocking Operation, Automatic Unmounting, Overview
+@comment node-name, next, previous, up
+@section Keep-alives
+@cindex Keep-alives
+@cindex Server crashes
+@cindex NFS ping
+
+Use of some filesystem types requires the presence of a server on
+another machine. If a machine crashes then it is of no concern to
+processes on that machine that the filesystem is unavailable. However,
+to processes on a remote host using that machine as a fileserver this
+event is important. This situation is most widely recognized when an
+NFS server crashes and the behavior observed on client machines is that
+more and more processes hang. In order to provide the possibility of
+recovery, @i{Amd} implements a @dfn{keep-alive} interval timer for some
+filesystem types. Currently only NFS makes use of this service.
+
+The basis of the NFS keep-alive implementation is the observation that
+most sites maintain replicated copies of common system data such as
+manual pages, most or all programs, system source code and so on. If
+one of those servers goes down it would be reasonable to mount one of
+the others as a replacement.
+
+The first part of the process is to keep track of which fileservers are
+up and which are down. @i{Amd} does this by sending RPC requests to the
+servers' NFS @code{NullProc} and checking whether a reply is returned.
+While the server state is uncertain the requests are re-transmitted at
+three second intervals and if no reply is received after four attempts
+the server is marked down. If a reply is received the fileserver is
+marked up and stays in that state for 30 seconds at which time another
+NFS ping is sent. This interval is configurable and can even be
+turned off using the @i{ping} option. @xref{opts Option}.
+
+Once a fileserver is marked down, requests continue to be sent every 30
+seconds in order to determine when the fileserver comes back up. During
+this time any reference through @i{Amd} to the filesystems on that
+server fail with the error ``Operation would block''. If a replacement
+volume is available then it will be mounted, otherwise the error is
+returned to the user.
+
+@c @i{Amd} keeps track of which servers are up and which are down.
+@c It does this by sending RPC requests to the servers' NFS {\sc NullProc} and
+@c checking whether a reply is returned. If no replies are received after a
+@c short period, @i{Amd} marks the fileserver @dfn{down}.
+@c RPC requests continue to be sent so that it will notice when a fileserver
+@c comes back up.
+@c ICMP echo packets \cite{rfc:icmp} are not used because it is the availability
+@c of the NFS service that is important, not the existence of a base kernel.
+@c Whenever a reference to a fileserver which is down is made via @i{Amd}, an alternate
+@c filesystem is mounted if one is available.
+@c
+Although this action does not protect user files, which are unique on
+the network, or processes which do not access files via @i{Amd} or
+already have open files on the hung filesystem, it can prevent most new
+processes from hanging.
+@c
+@c With a suitable combination of filesystem management and mount-maps,
+@c machines can be protected against most server downtime. This can be
+@c enhanced by allocating boot-servers dynamically which allows a diskless
+@c workstation to be quickly restarted if necessary. Once the root filesystem
+@c is mounted, @i{Amd} can be started and allowed to mount the remainder of
+@c the filesystem from whichever fileservers are available.
+
+@node Non-blocking Operation, , Keep-alives, Overview
+@comment node-name, next, previous, up
+@section Non-blocking Operation
+@cindex Non-blocking operation
+@cindex Multiple-threaded server
+@cindex RPC retries
+
+Since there is only one instance of @i{Amd} for each automount point,
+and usually only one instance on each machine, it is important that it
+is always available to service kernel calls. @i{Amd} goes to great
+lengths to ensure that it does not block in a system call. As a last
+resort @i{Amd} will fork before it attempts a system call that may block
+indefinitely, such as mounting an NFS filesystem. Other tasks such as
+obtaining filehandle information for an NFS filesystem, are done using a
+purpose built non-blocking RPC library which is integrated with
+@i{Amd}'s task scheduler. This library is also used to implement NFS
+keep-alives (@pxref{Keep-alives}).
+
+Whenever a mount is deferred or backgrounded, @i{Amd} must wait for it
+to complete before replying to the kernel. However, this would cause
+@i{Amd} to block waiting for a reply to be constructed. Rather than do
+this, @i{Amd} simply @dfn{drops} the call under the assumption that the
+kernel RPC mechanism will automatically retry the request.
+
+@c ################################################################
+@node Supported Platforms, Mount Maps, Overview, Top
+@comment node-name, next, previous, up
+@chapter Supported Platforms
+@cindex Supported Platforms
+@cindex shared libraries
+@cindex NFS V.3 support
+
+@i{Am-utils} has been ported to a wide variety of machines and operating
+systems. @i{Am-utils}'s code works for little-endian and big-endian
+machines, as well as 32 bit and 64 bit architectures. Furthermore, when
+@i{Am-utils} ports to an Operating System on one architecture, it is generally
+readily portable to the same Operating System on all platforms on which
+it is available.
+
+See the @file{INSTALL} in the distribution for more specific details on
+building and/or configuring for some systems.
+
+@c ################################################################
+@node Mount Maps, Amd Command Line Options, Supported Platforms, Top
+@comment node-name, next, previous, up
+@chapter Mount Maps
+@cindex Mount maps
+@cindex Automounter configuration maps
+@cindex Mount information
+
+@i{Amd} has no built-in knowledge of machines or filesystems.
+External @dfn{mount-maps} are used to provide the required information.
+Specifically, @i{Amd} needs to know when and under what conditions it
+should mount filesystems.
+
+The map entry corresponding to the requested name contains a list of
+possible locations from which to resolve the request. Each location
+specifies filesystem type, information required by that filesystem (for
+example the block special device in the case of UFS), and some
+information describing where to mount the filesystem (@pxref{fs Option}). A
+location may also contain @dfn{selectors} (@pxref{Selectors}).@refill
+
+@menu
+* Map Types::
+* Key Lookup::
+* Location Format::
+@end menu
+
+@node Map Types, Key Lookup, Mount Maps, Mount Maps
+@comment node-name, next, previous, up
+@section Map Types
+@cindex Mount map types
+@cindex Map types
+@cindex Configuration map types
+@cindex Types of mount map
+@cindex Types of configuration map
+@cindex Determining the map type
+
+A mount-map provides the run-time configuration information to @i{Amd}.
+Maps can be implemented in many ways. Some of the forms supported by
+@i{Amd} are regular files, ndbm databases, NIS maps, the @dfn{Hesiod}
+name server, and even the password file.
+
+A mount-map @dfn{name} is a sequence of characters. When an automount
+point is created a handle on the mount-map is obtained. For each map
+type configured, @i{Amd} attempts to reference the map of the
+appropriate type. If a map is found, @i{Amd} notes the type for future
+use and deletes the reference, for example closing any open file
+descriptors. The available maps are configured when @i{Amd} is built
+and can be displayed by running the command @samp{amd -v}.
+
+When using an @i{Amd} configuration file (@pxref{Amd Configuration File})
+and the keyword @samp{map_type} (@pxref{map_type Parameter}), you may
+force the map used to any type.
+
+By default, @i{Amd} caches data in a mode dependent on the type of map.
+This is the same as specifying @samp{cache:=mapdefault} and selects a
+suitable default cache mode depending on the map type. The individual
+defaults are described below. The @var{cache} option can be specified
+on automount points to alter the caching behavior (@pxref{Automount
+Filesystem}).@refill
+
+The following map types have been implemented, though some are not
+available on all machines. Run the command @samp{amd -v} to obtain a
+list of map types configured on your machine.
+
+@menu
+* File maps::
+* ndbm maps::
+* NIS maps::
+* NIS+ maps::
+* Hesiod maps::
+* Password maps::
+* Union maps::
+* LDAP maps::
+* Executable maps::
+@end menu
+
+@c ----------------------------------------------------------------
+@node File maps, ndbm maps, Map Types, Map Types
+@comment node-name, next, previous, up
+@subsection File maps
+@cindex File maps
+@cindex Flat file maps
+@cindex File map syntactic conventions
+
+When @i{Amd} searches a file for a map entry it does a simple scan of
+the file and supports both comments and continuation lines.
+
+Continuation lines are indicated by a backslash character (@samp{\}) as
+the last character of a line in the file. The backslash, newline character
+@emph{and any leading white space on the following line} are discarded. A maximum
+line length of 2047 characters is enforced after continuation lines are read
+but before comments are stripped. Each line must end with
+a newline character; that is newlines are terminators, not separators.
+The following examples illustrate this:
+
+@example
+key valA valB; \
+ valC
+@end example
+
+specifies @emph{three} locations, and is identical to
+
+@example
+key valA valB; valC
+@end example
+
+However,
+
+@example
+key valA valB;\
+ valC
+@end example
+
+specifies only @emph{two} locations, and is identical to
+
+@example
+key valA valB;valC
+@end example
+
+After a complete line has been read from the file, including
+continuations, @i{Amd} determines whether there is a comment on the
+line. A comment begins with a hash (``@samp{#}'') character and
+continues to the end of the line. There is no way to escape or change
+the comment lead-in character.
+
+Note that continuation lines and comment support @dfn{only} apply to
+file maps, or ndbm maps built with the @code{mk-amd-map} program.
+
+When caching is enabled, file maps have a default cache mode of
+@code{all} (@pxref{Automount Filesystem}).
+
+@c ----------------------------------------------------------------
+@node ndbm maps, NIS maps, File maps, Map Types
+@comment node-name, next, previous, up
+@subsection ndbm maps
+@cindex ndbm maps
+
+An ndbm map may be used as a fast access form of a file map. The program,
+@code{mk-amd-map}, converts a normal map file into an ndbm database.
+This program supports the same continuation and comment conventions that
+are provided for file maps. Note that ndbm format files may @emph{not}
+be sharable across machine architectures. The notion of speed generally
+only applies to large maps; a small map, less than a single disk block,
+is almost certainly better implemented as a file map.
+
+ndbm maps have a default cache mode of @samp{all}
+(@pxref{Automount Filesystem}).
+
+@c ----------------------------------------------------------------
+@node NIS maps, NIS+ maps, ndbm maps, Map Types
+@comment node-name, next, previous, up
+@subsection NIS maps
+@cindex NIS (YP) maps
+
+When using NIS (formerly YP), an @i{Amd} map is implemented directly
+by the underlying NIS map. Comments and continuation lines are
+@emph{not} supported in the automounter and must be stripped when
+constructing the NIS server's database.
+
+NIS maps have a default cache mode of @code{all} (@pxref{Automount
+Filesystem}).
+
+The following rule illustrates what could be added to your NIS @file{Makefile},
+in this case causing the @file{amd.home} map to be rebuilt:
+@example
+$(YPTSDIR)/amd.home.time: $(ETCDIR)/amd.home
+ -@@sed -e "s/#.*$$//" -e "/^$$/d" $(ETCDIR)/amd.home | \
+ awk '@{ \
+ for (i = 1; i <= NF; i++) \
+ if (i == NF) @{ \
+ if (substr($$i, length($$i), 1) == "\\") \
+ printf("%s", substr($$i, 1, length($$i) - 1)); \
+ else \
+ printf("%s\n", $$i); \
+ @} \
+ else \
+ printf("%s ", $$i); \
+ @}' | \
+ $(MAKEDBM) - $(YPDBDIR)/amd.home; \
+ touch $(YPTSDIR)/amd.home.time; \
+ echo "updated amd.home"; \
+ if [ ! $(NOPUSH) ]; then \
+ $(YPPUSH) amd.home; \
+ echo "pushed amd.home"; \
+ else \
+ : ; \
+ fi
+@end example
+
+Here @code{$(YPTSDIR)} contains the time stamp files, and
+@code{$(YPDBDIR)} contains the dbm format NIS files.
+
+@c ----------------------------------------------------------------
+@node NIS+ maps, Hesiod maps, NIS maps, Map Types
+@comment node-name, next, previous, up
+@subsection NIS+ maps
+@cindex NIS+ maps
+
+NIS+ maps do not support cache mode @samp{all} and, when caching is
+enabled, have a default cache mode of @samp{inc}.
+
+XXX: FILL IN WITH AN EXAMPLE.
+
+@c ----------------------------------------------------------------
+@node Hesiod maps, Password maps, NIS+ maps, Map Types
+@comment node-name, next, previous, up
+@subsection Hesiod maps
+@cindex Hesiod maps
+
+When the map name begins with the string @samp{hesiod.} lookups are made
+using the @dfn{Hesiod} name server. The string following the dot is
+used as a name qualifier and is prepended with the key being located.
+The entire string is then resolved in the @code{automount} context, or
+the @i{amd.conf} parameter @samp{hesiod_base} (@pxref{hesiod_base
+Parameter}). For example, if the key is @samp{jsp} and map name is
+@samp{hesiod.homes} then @dfn{Hesiod} is asked to resolve
+@samp{jsp.homes.automount}.
+
+Hesiod maps do not support cache mode @samp{all} and, when caching is
+enabled, have a default cache mode of @samp{inc} (@pxref{Automount
+Filesystem}).
+
+The following is an example of a @dfn{Hesiod} map entry:
+
+@example
+jsp.homes.automount HS TXT "rfs:=/home/charm;rhost:=charm;sublink:=jsp"
+njw.homes.automount HS TXT "rfs:=/home/dylan/dk2;rhost:=dylan;sublink:=njw"
+@end example
+
+@c ----------------------------------------------------------------
+@node Password maps, Union maps, Hesiod maps, Map Types
+@comment node-name, next, previous, up
+@subsection Password maps
+@cindex Password file maps
+@cindex /etc/passwd maps
+@cindex User maps, automatic generation
+@cindex Automatic generation of user maps
+@cindex Using the password file as a map
+
+The password map support is unlike the four previous map types. When
+the map name is the string @file{/etc/passwd} @i{Amd} can lookup a user
+name in the password file and re-arrange the home directory field to
+produce a usable map entry.
+
+@i{Amd} assumes the home directory has the format
+`@t{/}@i{anydir}@t{/}@i{dom1}@t{/../}@i{domN}@t{/}@i{login}'.
+@c @footnote{This interpretation is not necessarily exactly what you want.}
+It breaks this string into a map entry where @code{$@{rfs@}} has the
+value `@t{/}@i{anydir}@t{/}@i{domN}', @code{$@{rhost@}} has the value
+`@i{domN}@t{.}@i{...}@t{.}@i{dom1}', and @code{$@{sublink@}} has the
+value @i{login}.@refill
+
+Thus if the password file entry was
+
+@example
+/home/achilles/jsp
+@end example
+
+the map entry used by @i{Amd} would be
+
+@example
+rfs:=/home/achilles;rhost:=achilles;sublink:=jsp
+@end example
+
+Similarly, if the password file entry was
+
+@example
+/home/cc/sugar/mjh
+@end example
+
+the map entry used by @i{Amd} would be
+
+@example
+rfs:=/home/sugar;rhost:=sugar.cc;sublink:=jsp
+@end example
+
+@c ----------------------------------------------------------------
+@node Union maps, LDAP maps, Password maps, Map Types
+@comment node-name, next, previous, up
+@subsection Union maps
+@cindex Union file maps
+
+The union map support is provided specifically for use with the union
+filesystem, @pxref{Union Filesystem}.
+
+It is identified by the string @samp{union:} which is followed by a
+colon separated list of directories. The directories are read in order,
+and the names of all entries are recorded in the map cache. Later
+directories take precedence over earlier ones. The union filesystem
+type then uses the map cache to determine the union of the names in all
+the directories.
+
+@c ----------------------------------------------------------------
+@node LDAP maps, Executable maps, Union maps, Map Types
+@comment node-name, next, previous, up
+@subsection LDAP maps
+@cindex LDAP maps
+@cindex Lightweight Directory Access Protocol
+
+LDAP (Lightweight Directory Access Protocol) maps do not support cache
+mode @samp{all} and, when caching is enabled, have a default cache mode
+of @samp{inc}.
+
+For example, an @i{Amd} map @samp{amd.home} that looks as follows:
+
+@example
+/defaults opts:=rw,intr;type:=link
+
+zing -rhost:=shekel \
+ host==shekel \
+ host!=shekel;type:=nfs
+@end example
+@noindent
+when converted to LDAP (@pxref{amd2ldif}), will result in the following
+LDAP database:
+@example
+$ amd2ldif amd.home CUCS < amd.home
+dn: cn=amdmap timestamp, CUCS
+cn : amdmap timestamp
+objectClass : amdmapTimestamp
+amdmapTimestamp: 873071363
+
+dn: cn=amdmap amd.home[/defaults], CUCS
+cn : amdmap amd.home[/defaults]
+objectClass : amdmap
+amdmapName : amd.home
+amdmapKey : /defaults
+amdmapValue : opts:=rw,intr;type:=link
+
+dn: cn=amdmap amd.home[], CUCS
+cn : amdmap amd.home[]
+objectClass : amdmap
+amdmapName : amd.home
+amdmapKey :
+amdmapValue :
+
+dn: cn=amdmap amd.home[zing], CUCS
+cn : amdmap amd.home[zing]
+objectClass : amdmap
+amdmapName : amd.home
+amdmapKey : zing
+amdmapValue : -rhost:=shekel host==shekel host!=shekel;type:=nfs
+@end example
+
+@c ----------------------------------------------------------------
+@node Executable maps, , LDAP maps, Map Types
+@comment node-name, next, previous, up
+@subsection Executable maps
+@cindex Executable maps
+
+An executable map is a dynamic map in which the keys and values for
+the maps are generated on the fly by a program or script. The program
+is expected to take a single parameter argument which is the key to
+lookup. If the key is found, the program should print on stdout the
+key-value pair that were found; if the key was not found, nothing
+should be printed out. Below is an sample of such a map script:
+
+@example
+#!/bin/sh
+# executable map example
+case "$1" in
+ "/defaults" )
+ echo "/defaults type:=nfs;rfs:=filer"
+ ;;
+ "a" )
+ echo "a type:=nfs;fs:=/tmp"
+ ;;
+ "b" )
+ echo "b type:=link;fs:=/usr/local"
+ ;;
+ * ) # no match, echo nothing
+ ;;
+esac
+@end example
+
+@xref{exec_map_timeout Parameter}.
+
+@c ----------------------------------------------------------------
+@c subsection Gdbm
+@c ----------------------------------------------------------------
+@node Key Lookup, Location Format, Map Types, Mount Maps
+@comment node-name, next, previous, up
+@section How keys are looked up
+@cindex Key lookup
+@cindex Map lookup
+@cindex Looking up keys
+@cindex How keys are looked up
+@cindex Wildcards in maps
+
+The key is located in the map whose type was determined when the
+automount point was first created. In general the key is a pathname
+component. In some circumstances this may be modified by variable
+expansion (@pxref{Variable Expansion}) and prefixing. If the automount
+point has a prefix, specified by the @var{pref} option, then that is
+prepended to the search key before the map is searched.
+
+If the map cache is a @samp{regexp} cache then the key is treated as an
+egrep-style regular expression, otherwise a normal string comparison is
+made.
+
+If the key cannot be found then a @dfn{wildcard} match is attempted.
+@i{Amd} repeatedly strips the basename from the key, appends @samp{/*} and
+attempts a lookup. Finally, @i{Amd} attempts to locate the special key @samp{*}.
+
+For example, the following sequence would be checked if @file{home/dylan/dk2} was
+being located:
+
+@example
+ home/dylan/dk2
+ home/dylan/*
+ home/*
+ *
+@end example
+
+At any point when a wildcard is found, @i{Amd} proceeds as if an exact
+match had been found and the value field is then used to resolve the
+mount request, otherwise an error code is propagated back to the kernel.
+(@pxref{Filesystem Types}).@refill
+
+@node Location Format, , Key Lookup, Mount Maps
+@comment node-name, next, previous, up
+@section Location Format
+@cindex Location format
+@cindex Map entry format
+@cindex How locations are parsed
+
+The value field from the lookup provides the information required to
+mount a filesystem. The information is parsed according to the syntax
+shown below.
+
+@display
+@i{location-list}:
+ @i{location-selection}
+ @i{location-list} @i{white-space} @t{||} @i{white-space} @i{location-selection}
+@i{location-selection}:
+ @i{location}
+ @i{location-selection} @i{white-space} @i{location}
+@i{location}:
+ @i{location-info}
+ @t{-}@i{location-info}
+ @t{-}
+@i{location-info}:
+ @i{sel-or-opt}
+ @i{location-info}@t{;}@i{sel-or-opt}
+ @t{;}
+@i{sel-or-opt}:
+ @i{selection}
+ @i{opt-ass}
+@i{selection}:
+ selector@t{==}@i{value}
+ selector@t{!=}@i{value}
+@i{opt-ass}:
+ option@t{:=}@i{value}
+@i{white-space}:
+ space
+ tab
+@end display
+
+Note that unquoted whitespace is not allowed in a location description.
+White space is only allowed, and is mandatory, where shown with non-terminal
+@i{white-space}.
+
+A @dfn{location-selection} is a list of possible volumes with which to
+satisfy the request. Each @dfn{location-selection} is tried
+sequentially, until either one succeeds or all fail. This, by the
+way, is different from the historically documented behavior, which
+claimed (falsely, at least for last 3 years) that @i{Amd} would
+attempt to mount all @dfn{location-selection}s in parallel and the
+first one to succeed would be used.
+
+@dfn{location-selection}s are optionally separated by the @samp{||}
+operator. The effect of this operator is to prevent use of
+location-selections to its right if any of the location-selections on
+its left were selected, whether or not any of them were successfully
+mounted (@pxref{Selectors}).@refill
+
+The location-selection, and singleton @dfn{location-list},
+@samp{type:=ufs;dev:=/dev/xd1g} would inform @i{Amd} to mount a UFS
+filesystem from the block special device @file{/dev/xd1g}.
+
+The @dfn{sel-or-opt} component is either the name of an option required
+by a specific filesystem, or it is the name of a built-in, predefined
+selector such as the architecture type. The value may be quoted with
+double quotes @samp{"}, for example
+@samp{type:="ufs";dev:="/dev/xd1g"}. These quotes are stripped when the
+value is parsed and there is no way to get a double quote into a value
+field. Double quotes are used to get white space into a value field,
+which is needed for the program filesystem (@pxref{Program Filesystem}).@refill
+
+@menu
+* Map Defaults::
+* Variable Expansion::
+* Selectors::
+* Map Options::
+@end menu
+
+@node Map Defaults, Variable Expansion, Location Format, Location Format
+@comment node-name, next, previous, up
+@subsection Map Defaults
+@cindex Map defaults
+@cindex How to set default map parameters
+@cindex Setting default map parameters
+
+A location beginning with a dash @samp{-} is used to specify default
+values for subsequent locations. Any previously specified defaults in
+the location-list are discarded. The default string can be empty in
+which case no defaults apply.
+
+The location @samp{-fs:=/mnt;opts:=ro} would set the local mount point
+to @file{/mnt} and cause mounts to be read-only by default. Defaults
+specified this way are appended to, and so override, any global map
+defaults given with @samp{/defaults}).
+
+@c
+@c A @samp{/defaults} value @dfn{gdef} and a location list
+@c \begin{quote}
+@c $@samp{-}@dfn{def}_a $\verb*+ +$ @dfn{loc}_{a_1} $\verb*+ +$ @dfn{loc}_{a_2} $\verb*+ +$ @samp{-}@dfn{def}_b $\verb*+ +$ @dfn{loc}_{b_1} \ldots$
+@c \end{quote}
+@c is equivalent to
+@c \begin{quote}
+@c $@samp{-}@dfn{gdef}@samp{;}@dfn{def}_a $\verb*+ +$ @dfn{loc}_{a_1} $\verb*+ +$ @dfn{loc}_{a_2} $\verb*+ +$ @samp{-}@dfn{gdef}@samp{;}@dfn{def}_b $\verb*+ +$ @dfn{loc}_{b_1} \ldots$
+@c \end{quote}
+@c which is equivalent to
+@c \begin{quote}
+@c $@dfn{gdef}@samp{;}@dfn{def}_a@samp{;}@dfn{loc}_{a_1} $\verb*+ +$@dfn{gdef}@samp{;}@dfn{def}_a@samp{;}@dfn{loc}_{a_2} $\verb*+ +$@dfn{gdef}@samp{;}@dfn{def}_b@samp{;}@dfn{loc}_{b_1} \ldots$
+@c \end{quote}
+
+@node Variable Expansion, Selectors, Map Defaults, Location Format
+@comment node-name, next, previous, up
+@subsection Variable Expansion
+@cindex Variable expansion
+@cindex How variables are expanded
+@cindex Pathname operators
+@cindex Domain stripping
+@cindex Domainname operators
+@cindex Stripping the local domain name
+@cindex Environment variables
+@cindex How to access environment variables in maps
+
+To allow generic location specifications @i{Amd} does variable expansion
+on each location and also on some of the option strings. Any option or
+selector appearing in the form @code{$@dfn{var}} is replaced by the
+current value of that option or selector. For example, if the value of
+@code{$@{key@}} was @samp{bin}, @code{$@{autodir@}} was @samp{/a} and
+@code{$@{fs@}} was `@t{$@{autodir@}}@t{/local/}@t{$@{key@}}' then
+after expansion @code{$@{fs@}} would have the value @samp{/a/local/bin}.
+Any environment variable can be accessed in a similar way.@refill
+
+Two pathname operators are available when expanding a variable. If the
+variable name begins with @samp{/} then only the last component of the
+pathname is substituted. For example, if @code{$@{path@}} was
+@samp{/foo/bar} then @code{$@{/path@}} would be expanded to @samp{bar}.
+Similarly, if the variable name ends with @samp{/} then all but the last
+component of the pathname is substituted. In the previous example,
+@code{$@{path/@}} would be expanded to @samp{/foo}.@refill
+
+Two domain name operators are also provided. If the variable name
+begins with @samp{.} then only the domain part of the name is
+substituted. For example, if @code{$@{rhost@}} was
+@samp{swan.doc.ic.ac.uk} then @code{$@{.rhost@}} would be expanded to
+@samp{doc.ic.ac.uk}. Similarly, if the variable name ends with @samp{.}
+then only the host component is substituted. In the previous example,
+@code{$@{rhost.@}} would be expanded to @samp{swan}.@refill
+
+Variable expansion is a two phase process. Before a location is parsed,
+all references to selectors, @i{eg} @code{$@{path@}}, are expanded. The
+location is then parsed, selections are evaluated and option assignments
+recorded. If there were no selections or they all succeeded the
+location is used and the values of the following options are expanded in
+the order given: @var{sublink}, @var{rfs}, @var{fs}, @var{opts},
+@var{remopts}, @var{mount} and @var{unmount}.
+
+Note that expansion of option values is done after @dfn{all} assignments
+have been completed and not in a purely left to right order as is done
+by the shell. This generally has the desired effect but care must be
+taken if one of the options references another, in which case the
+ordering can become significant.
+
+There are two special cases concerning variable expansion:
+
+@enumerate
+@item
+before a map is consulted, any selectors in the name received
+from the kernel are expanded. For example, if the request from the
+kernel was for `@t{$@{arch@}}@t{.bin}' and the machine architecture
+was @samp{vax}, the value given to @code{$@{key@}} would be
+@samp{vax.bin}.@refill
+
+@item
+the value of @code{$@{rhost@}} is expanded and normalized before the
+other options are expanded. The normalization process strips any local
+sub-domain components. For example, if @code{$@{domain@}} was
+@samp{Berkeley.EDU} and @code{$@{rhost@}} was initially
+@samp{snow.Berkeley.EDU}, after the normalization it would simply be
+@samp{snow}. Hostname normalization is currently done in a
+@emph{case-dependent} manner.@refill
+@end enumerate
+
+@c======================================================================
+@node Selectors, Map Options, Variable Expansion, Location Format
+@comment node-name, next, previous, up
+@subsection Selectors
+@cindex Selectors
+
+Selectors are used to control the use of a location. It is possible to
+share a mount map between many machines in such a way that filesystem
+location, architecture and operating system differences are hidden from
+the users. A selector of the form @samp{arch==sun3;os==sunos4} would only
+apply on Sun-3s running SunOS 4.x.
+
+Selectors can be negated by using @samp{!=} instead of @samp{==}. For
+example to select a location on all non-Vax machines the selector
+@samp{arch!=vax} would be used.
+
+Selectors are evaluated left to right. If a selector fails then that
+location is ignored. Thus the selectors form a conjunction and the
+locations form a disjunction. If all the locations are ignored or
+otherwise fail then @i{Amd} uses the @dfn{error} filesystem
+(@pxref{Error Filesystem}). This is equivalent to having a location
+@samp{type:=error} at the end of each mount-map entry.@refill
+
+The default value of many of the selectors listed here can be overridden
+by an @i{Amd} command line switch or in an @i{Amd} configuration file.
+@xref{Amd Configuration File}.
+
+The following selectors are currently implemented.
+
+@menu
+* arch Selector Variable::
+* autodir Selector Variable::
+* byte Selector Variable::
+* cluster Selector Variable::
+* domain Selector Variable::
+* dollar Selector Variable::
+* host Selector Variable::
+* hostd Selector Variable::
+* karch Selector Variable::
+* os Selector Variable::
+* osver Selector Variable::
+* full_os Selector Variable::
+* vendor Selector Variable::
+
+* key Selector Variable::
+* map Selector Variable::
+* netnumber Selector Variable::
+* network Selector Variable::
+* path Selector Variable::
+* wire Selector Variable::
+* uid Selector Variable::
+* gid Selector Variable::
+
+* exists Selector Function::
+* false Selector Function::
+* netgrp Selector Function::
+* netgrpd Selector Function::
+* in_network Selector Function::
+* true Selector Function::
+* xhost Selector Function::
+@end menu
+
+@c ----------------------------------------------------------------
+@node arch Selector Variable, autodir Selector Variable, Selectors, Selectors
+@comment node-name, next, previous, up
+@subsubsection arch Selector Variable
+@cindex arch Selector Variable
+@cindex arch, mount selector
+@cindex Mount selector; arch
+@cindex Selector; arch
+
+The machine architecture which was automatically determined at compile
+time. The architecture type can be displayed by running the command
+@samp{amd -v}. You can override this value also using the @code{-A}
+command line option. @xref{Supported Platforms}.@refill
+
+@c ----------------------------------------------------------------
+@node autodir Selector Variable, byte Selector Variable, arch Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection autodir Selector Variable
+@cindex autodir Selector Variable
+@cindex autodir, mount selector
+@cindex Mount selector; autodir
+@cindex Selector; autodir
+
+The default directory under which to mount filesystems. This may be
+changed by the @code{-a} command line option. @xref{fs Option}.
+
+@c ----------------------------------------------------------------
+@node byte Selector Variable, cluster Selector Variable, autodir Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection byte Selector Variable
+@cindex byte Selector Variable
+@cindex byte, mount selector
+@cindex Mount selector; byte
+@cindex Selector; byte
+
+The machine's byte ordering. This is either @samp{little}, indicating
+little-endian, or @samp{big}, indicating big-endian. One possible use
+is to share @samp{rwho} databases (@pxref{rwho servers}). Another is to
+share ndbm databases, however this use can be considered a courageous
+juggling act.
+
+@c ----------------------------------------------------------------
+@node cluster Selector Variable, domain Selector Variable, byte Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection cluster Selector Variable
+@cindex cluster Selector Variable
+@cindex cluster, mount selector
+@cindex Mount selector; cluster
+@cindex Selector; cluster
+
+This is provided as a hook for the name of the local cluster. This can
+be used to decide which servers to use for copies of replicated
+filesystems. @code{$@{cluster@}} defaults to the value of
+@code{$@{domain@}} unless a different value is set with the @code{-C}
+command line option.
+
+@c ----------------------------------------------------------------
+@node domain Selector Variable, dollar Selector Variable, cluster Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection domain Selector Variable
+@cindex domain Selector Variable
+@cindex domain, mount selector
+@cindex Mount selector; domain
+@cindex Selector; domain
+
+The local domain name as specified by the @code{-d} command line option.
+@xref{host Selector Variable}.
+
+@c ----------------------------------------------------------------
+@node dollar Selector Variable, host Selector Variable, domain Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection dollar Selector Variable
+@cindex dollar Selector Variable
+
+This is a special variable, whose sole purpose is to produce a literal
+dollar sign in the value of another variable. For example, if you have
+a remote file system whose name is @samp{/disk$s}, you can mount it by
+setting the remote file system variable as follows:
+
+@example
+rfs:=/disk$@{dollar@}s
+@end example
+
+@c ----------------------------------------------------------------
+@node host Selector Variable, hostd Selector Variable, dollar Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection host Selector Variable
+@cindex host Selector Variable
+@cindex host, mount selector
+@cindex Mount selector; host
+@cindex Selector; host
+
+The local hostname as determined by @b{gethostname}(2). If no domain
+name was specified on the command line and the hostname contains a
+period @samp{.} then the string before the period is used as the host
+name, and the string after the period is assigned to @code{$@{domain@}}.
+For example, if the hostname is @samp{styx.doc.ic.ac.uk} then
+@code{host} would be @samp{styx} and @code{domain} would be
+@samp{doc.ic.ac.uk}. @code{hostd} would be
+@samp{styx.doc.ic.ac.uk}.@refill
+
+@c ----------------------------------------------------------------
+@node hostd Selector Variable, karch Selector Variable, host Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection hostd Selector Variable
+@cindex hostd Selector Variable
+@cindex hostd, mount selector
+@cindex Mount selector; hostd
+@cindex Selector; hostd
+
+This resolves to the @code{$@{host@}} and @code{$@{domain@}}
+concatenated with a @samp{.} inserted between them if required. If
+@code{$@{domain@}} is an empty string then @code{$@{host@}} and
+@code{$@{hostd@}} will be identical.
+
+@c ----------------------------------------------------------------
+@node karch Selector Variable, os Selector Variable, hostd Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection karch Selector Variable
+@cindex karch Selector Variable
+@cindex karch, mount selector
+@cindex Mount selector; karch
+@cindex Selector; karch
+
+This is provided as a hook for the kernel architecture. This is used on
+SunOS 4 and SunOS 5, for example, to distinguish between different
+@samp{/usr/kvm} volumes. @code{$@{karch@}} defaults to the ``machine''
+value gotten from @b{uname}(2). If the @b{uname}(2) system call is not
+available, the value of @code{$@{karch@}} defaults to that of
+@code{$@{arch@}}. Finally, a different value can be set with the @code{-k}
+command line option.
+
+@c ----------------------------------------------------------------
+@node os Selector Variable, osver Selector Variable, karch Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection os Selector Variable
+@cindex os Selector Variable
+@cindex os, mount selector
+@cindex Mount selector; os
+@cindex Selector; os
+
+The operating system. Like the machine architecture, this is
+automatically determined at compile time. The operating system name can
+be displayed by running the command @samp{amd -v}. @xref{Supported
+Platforms}.@refill
+
+@c ----------------------------------------------------------------
+@node osver Selector Variable, full_os Selector Variable, os Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection osver Selector Variable
+@cindex osver Selector Variable
+@cindex osver, mount selector
+@cindex Mount selector; osver
+@cindex Selector; osver
+
+The operating system version. Like the machine architecture, this is
+automatically determined at compile time. The operating system name can
+be displayed by running the command @samp{amd -v}. @xref{Supported
+Platforms}.@refill
+
+@c ----------------------------------------------------------------
+@node full_os Selector Variable, vendor Selector Variable, osver Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection full_os Selector Variable
+@cindex full_os Selector Variable
+@cindex full_os, mount selector
+@cindex Mount selector; full_os
+@cindex Selector; full_os
+
+The full name of the operating system, including its version. This
+value is automatically determined at compile time. The full operating
+system name and version can be displayed by running the command
+@samp{amd -v}. @xref{Supported Platforms}.@refill
+
+@c ----------------------------------------------------------------
+@node vendor Selector Variable, key Selector Variable, full_os Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection vendor Selector Variable
+@cindex vendor Selector Variable
+@cindex vendor, mount selector
+@cindex Mount selector; vendor
+@cindex Selector; vendor
+
+The name of the vendor of the operating system. This value is
+automatically determined at compile time. The name of the vendor can be
+displayed by running the command @samp{amd -v}. @xref{Supported
+Platforms}.@refill
+
+
+@c ----------------------------------------------------------------
+@ifhtml
+<HR>
+@end ifhtml
+@sp 3
+The following selectors are also provided. Unlike the other selectors,
+they vary for each lookup. Note that when the name from the kernel is
+expanded prior to a map lookup, these selectors are all defined as empty
+strings.
+
+@c ----------------------------------------------------------------
+@node key Selector Variable, map Selector Variable, vendor Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection key Selector Variable
+@cindex key Selector Variable
+@cindex key, mount selector
+@cindex Mount selector; key
+@cindex Selector; key
+
+The name being resolved. For example, if @file{/home} is an automount
+point, then accessing @file{/home/foo} would set @code{$@{key@}} to the
+string @samp{foo}. The key is prefixed by the @var{pref} option set in
+the parent mount point. The default prefix is an empty string. If the
+prefix was @file{blah/} then @code{$@{key@}} would be set to
+@file{blah/foo}.@refill
+
+@c ----------------------------------------------------------------
+@node map Selector Variable, netnumber Selector Variable, key Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection map Selector Variable
+@cindex map Selector Variable
+@cindex map, mount selector
+@cindex Mount selector; map
+@cindex Selector; map
+
+The name of the mount map being used.
+
+@c ----------------------------------------------------------------
+@node netnumber Selector Variable, network Selector Variable, map Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection netnumber Selector Variable
+@cindex netnumber Selector Variable
+@cindex netnumber, mount selector
+@cindex Mount selector; netnumber
+@cindex Selector; netnumber
+
+This selector is identical to the @samp{in_network} selector function,
+see @ref{in_network Selector Function}. It will match either the name
+or number of @i{any} network interface on which this host is connected
+to. The names and numbers of all attached interfaces are available from
+the output of @samp{amd -v}.
+
+@c ----------------------------------------------------------------
+@node network Selector Variable, path Selector Variable, netnumber Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection network Selector Variable
+@cindex network Selector Variable
+@cindex network, mount selector
+@cindex Mount selector; network
+@cindex Selector; network
+
+This selector is identical to the @samp{in_network} selector function,
+see @ref{in_network Selector Function}. It will match either the name
+or number of @i{any} network interface on which this host is connected
+to. The names and numbers of all attached interfaces are available from
+the output of @samp{amd -v}.
+
+@c ----------------------------------------------------------------
+@node path Selector Variable, wire Selector Variable, network Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection path Selector Variable
+@cindex path Selector Variable
+@cindex path, mount selector
+@cindex Mount selector; path
+@cindex Selector; path
+
+The full pathname of the name being resolved. For example
+@file{/home/foo} in the example above.
+
+@c ----------------------------------------------------------------
+@node wire Selector Variable, uid Selector Variable, path Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection wire Selector Variable
+@cindex wire Selector Variable
+@cindex wire, mount selector
+@cindex Mount selector; wire
+@cindex Selector; wire
+
+This selector is identical to the @samp{in_network} selector function,
+see @ref{in_network Selector Function}. It will match either the name
+or number of @i{any} network interface on which this host is connected
+to. The names and numbers of all attached interfaces are available from
+the output of @samp{amd -v}.
+
+@c ----------------------------------------------------------------
+@node uid Selector Variable, gid Selector Variable, wire Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection uid Selector Variable
+@cindex uid Selector Variable
+@cindex uid, mount selector
+@cindex Mount selector; uid
+@cindex Selector; uid
+
+This selector provides the numeric effective user ID (UID) of the user
+which last accessed an automounted path name. This simple example shows
+how floppy mounting can be assigned only to machine owners:
+
+@example
+floppy -type:=pcfs \
+ uid==2301;host==shekel;dev:=/dev/floppy \
+ uid==6712;host==titan;dev=/dev/fd0 \
+ uid==0;dev:=/dev/fd0c \
+ type:=error
+@end example
+
+The example allows two machine owners to mount floppies on their
+designated workstations, allows the root user to mount on any host, and
+otherwise forces an error.
+
+@c ----------------------------------------------------------------
+@node gid Selector Variable, exists Selector Function, uid Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection gid Selector Variable
+@cindex gid Selector Variable
+@cindex gid, mount selector
+@cindex Mount selector; gid
+@cindex Selector; gid
+
+This selector provides the numeric effective group ID (GID) of the user
+which last accessed an automounted path name.
+
+@c ----------------------------------------------------------------
+@ifhtml
+<HR>
+@end ifhtml
+@sp 2
+The following boolean functions are selectors which take an argument
+@i{ARG}. They return a value of true or false, and thus do not need to
+be compared with a value. Each of these may be negated by prepending
+@samp{!} to their name.
+
+@c ----------------------------------------------------------------
+@node exists Selector Function, false Selector Function, gid Selector Variable, Selectors
+@comment node-name, next, previous, up
+@subsubsection exists Selector Function
+@cindex exists Selector Function
+@cindex exists, boolean mount selector
+@cindex !exists, boolean mount selector
+@cindex Mount selector; exists
+@cindex Selector; exists
+
+If the file listed by @i{ARG} exists (via @b{lstat}(2)), this function
+evaluates to true. Otherwise it evaluates to false.
+
+@c ----------------------------------------------------------------
+@node false Selector Function, netgrp Selector Function, exists Selector Function, Selectors
+@comment node-name, next, previous, up
+@subsubsection false Selector Function
+@cindex false Selector Function
+@cindex false, boolean mount selector
+@cindex !false, boolean mount selector
+@cindex Mount selector; false
+@cindex Selector; false
+
+Always evaluates to false. @i{ARG} is ignored.
+
+@c ----------------------------------------------------------------
+@node netgrp Selector Function, netgrpd Selector Function, false Selector Function, Selectors
+@comment node-name, next, previous, up
+@subsubsection netgrp Selector Function
+@cindex netgrp Selector Function
+@cindex netgrp, boolean mount selector
+@cindex !netgrp, boolean mount selector
+@cindex Mount selector; netgrp
+@cindex Selector; netgrp
+
+The argument @i{ARG} of this selector is a netgroup name followed
+optionally by a comma and a host name. If the host name is not
+specified, it defaults to @code{$@{host@}}. If the host name (short
+name) is a member of the netgroup, this selector evaluates to
+true. Otherwise it evaluates to false.
+
+For example, suppose you have a netgroup @samp{ppp-hosts}, and for
+reasons of performance, these have a local @file{/home} partition,
+while all other clients on the faster network can access a shared home
+directory. A common map to use for both might look like the
+following:
+
+@example
+home/* netgrp(ppp-hosts);type:=link;fs:=/local/$@{key@} \
+ !netgrp(ppp-hosts);type:=nfs;rhost:=serv1;rfs:=/remote/$@{key@}
+@end example
+
+A more complex example that takes advantage of the two argument netgrp
+mount selector is given in the following scenario. Suppose one wants
+to mount the local scratch space from a each host under
+@file{scratch/<hostname>} and some hosts have their scratch space in a
+different path than others. Hosts in the netgroup @samp{apple-hosts}
+have their scratch space in the @file{/apple} path, where hosts in the
+netgroup @samp{cherry-hosts} have their scratch space in the
+@file{/cherry} path. For hosts that are neither in the
+@samp{apple-hosts} or @samp{cherry-hosts} netgroups we want to make a
+symlink pointing to nowhere but provide a descriptive error message in
+the link destination:
+
+@example
+scratch/* netgrp(apple-hosts,$@{/key@});type:=nfs;rhost:=$@{/key@};\
+ rfs:="/apple" \
+ netgrp(cherry-hosts,$@{/key@});type:=nfs;rhost:=$@{/key@};\
+ rfs:="/cherry" \
+ type:=link;rfs:="no local partition for $@{/key@}"
+@end example
+
+@c ----------------------------------------------------------------
+@node netgrpd Selector Function, in_network Selector Function, netgrp Selector Function, Selectors
+@comment node-name, next, previous, up
+@subsubsection netgrpd Selector Function
+@cindex netgrpd Selector Function
+@cindex netgrpd, boolean mount selector
+@cindex !netgrpd, boolean mount selector
+@cindex Mount selector; netgrpd
+@cindex Selector; netgrpd
+
+The argument @i{ARG} of this selector is a netgroup name followed
+optionally by a comma and a host name. If the host name is not
+specified, it defaults to @code{$@{hostd@}}. If the host name
+(fully-qualified name) is a member of the netgroup, this selector
+evaluates to true. Otherwise it evaluates to false.
+
+The @samp{netgrpd} function uses fully-qualified host names to match
+netgroup names, while the @samp{netgrp} function (@pxref{netgrp
+Selector Function}) uses short host names.
+
+@c ----------------------------------------------------------------
+@node in_network Selector Function, true Selector Function, netgrpd Selector Function, Selectors
+@comment node-name, next, previous, up
+@subsubsection in_network Selector Function
+@cindex in_network Selector Function
+@cindex in_network, boolean mount selector
+@cindex !in_network, boolean mount selector
+@cindex Mount selector; in_network
+@cindex Selector; in_network
+
+This selector matches against any network name or number with an
+optional netmask. First, if the current host has any network interface that is
+locally attached to the network specified in @i{ARG} (either via name or
+number), this selector evaluates to true.
+
+Second, @samp{in_network} supports a network/netmask syntax such as
+@samp{128.59.16.0/255.255.255.0}, @samp{128.59.16.0/24},
+@samp{128.59.16.0/0xffffff00}, or @samp{128.59.16.0/}. Using the last
+form, @i{Amd} will match the specified network number against the
+default netmasks of each of the locally attached interfaces.
+
+If the selector does not match, it evaluates to false.
+
+For example, suppose you have two servers that have an exportable
+@file{/opt} that smaller clients can NFS mount. The two servers are
+say, @samp{serv1} on network @samp{foo-net.site.com} and @samp{serv2} on
+network @samp{123.4.5.0}. You can write a map to be used by all clients
+that will attempt to mount the closest one as follows:
+
+@example
+opt in_network(foo-net.site.com);rhost:=serv1;rfs:=/opt \
+ in_network(123.4.5.0);rhost:=serv2;rfs:=/opt \
+ rhost:=fallback-server
+@end example
+
+@c ----------------------------------------------------------------
+@node true Selector Function, xhost Selector Function, in_network Selector Function, Selectors
+@comment node-name, next, previous, up
+@subsubsection true Selector Function
+@cindex true Selector Function
+@cindex true, boolean mount selector
+@cindex !true, boolean mount selector
+@cindex Mount selector; true
+@cindex Selector; true
+
+Always evaluates to true. @i{ARG} is ignored.
+
+@c ----------------------------------------------------------------
+@node xhost Selector Function, , true Selector Function, Selectors
+@comment node-name, next, previous, up
+@subsubsection xhost Selector Function
+@cindex xhost Selector Function
+@cindex xhost, boolean mount selector
+@cindex !xhost, boolean mount selector
+@cindex Mount selector; xhost
+@cindex Selector; xhost
+@cindex CNAMEs
+
+This function compares @i{ARG} against the current hostname, similarly
+to the @ref{host Selector Variable}. However, this function will
+also match if @i{ARG} is a CNAME (DNS Canonical Name, or alias) for
+the current host's name.
+
+@c ================================================================
+@node Map Options, , Selectors, Location Format
+@comment node-name, next, previous, up
+@subsection Map Options
+@cindex Map options
+@cindex Setting map options
+
+Options are parsed concurrently with selectors. The difference is that
+when an option is seen the string following the @samp{:=} is
+recorded for later use. As a minimum the @var{type} option must be
+specified. Each filesystem type has other options which must also be
+specified. @xref{Filesystem Types}, for details on the filesystem
+specific options.@refill
+
+Superfluous option specifications are ignored and are not reported
+as errors.
+
+The following options apply to more than one filesystem type.
+
+@menu
+* addopts Option::
+* delay Option::
+* fs Option::
+* opts Option::
+* remopts Option::
+* sublink Option::
+* type Option::
+@end menu
+
+@node addopts Option, delay Option, Map Options, Map Options
+@comment node-name, next, previous, up
+@subsubsection addopts Option
+@cindex Setting additional options on a mount location
+@cindex Overriding or adding options to a mount
+@cindex addopts, mount option
+@cindex Mount option; addopts
+
+This option adds additional options to default options normally
+specified in the @samp{/defaults} entry or the defaults of the key entry
+being processed (@pxref{opts Option}). Normally when you specify
+@samp{opts} in both the @samp{/defaults} and the map entry, the latter
+overrides the former completely. But with @samp{addopts} it will append
+the options and override any conflicting ones.
+
+@samp{addopts} also overrides the value of the @samp{remopts} option
+(@pxref{remopts Option}), which unless specified defaults to the value
+of @samp{opts}.
+
+Options which start with @samp{no} will override those with the same
+name that do not start with @samp{no} and vice verse. Special handling
+is given to inverted options such as @samp{soft} and @samp{hard},
+@samp{bg} and @samp{fg}, @samp{ro} and @samp{rw}, etc.
+
+For example, if the default options specified were
+@example
+opts:=rw,nosuid,intr,rsize=1024,wsize=1024,quota,posix
+@end example
+
+and the ones specified in a map entry were
+
+@example
+addopts:=grpid,suid,ro,rsize=2048,quota,nointr
+@end example
+
+then the actual options used would be
+
+@example
+wsize=1024,posix,grpid,suid,ro,rsize=2048,quota,nointr
+@end example
+
+@node delay Option, fs Option, addopts Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection delay Option
+@cindex Setting a delay on a mount location
+@cindex Delaying mounts from specific locations
+@cindex Primary server
+@cindex Secondary server
+@cindex delay, mount option
+@cindex Mount option; delay
+
+The delay, in seconds, before an attempt will be made to mount from the
+current location. Auxiliary data, such as network address, file handles
+and so on are computed regardless of this value.
+
+A delay can be used to implement the notion of primary and secondary
+file servers. The secondary servers would have a delay of a few
+seconds, thus giving the primary servers a chance to respond first.
+
+@node fs Option, opts Option, delay Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection fs Option
+@cindex Setting the local mount point
+@cindex Overriding the default mount point
+@cindex fs, mount option
+@cindex Mount option; fs
+
+The local mount point. The semantics of this option vary between
+filesystems.
+
+For NFS and UFS filesystems the value of @code{$@{fs@}} is used as the
+local mount point. For other filesystem types it has other meanings
+which are described in the section describing the respective filesystem
+type. It is important that this string uniquely identifies the
+filesystem being mounted. To satisfy this requirement, it should
+contain the name of the host on which the filesystem is resident and the
+pathname of the filesystem on the local or remote host.
+
+The reason for requiring the hostname is clear if replicated filesystems
+are considered. If a fileserver goes down and a replacement filesystem
+is mounted then the @dfn{local} mount point @dfn{must} be different from
+that of the filesystem which is hung. Some encoding of the filesystem
+name is required if more than one filesystem is to be mounted from any
+given host.
+
+If the hostname is first in the path then all mounts from a particular
+host will be gathered below a single directory. If that server goes
+down then the hung mount points are less likely to be accidentally
+referenced, for example when @b{getcwd}(3) traverses the namespace to
+find the pathname of the current directory.
+
+The @samp{fs} option defaults to
+@code{$@{autodir@}/$@{rhost@}$@{rfs@}}. In addition,
+@samp{rhost} defaults to the local host name (@code{$@{host@}}) and
+@samp{rfs} defaults to the value of @code{$@{path@}}, which is the full
+path of the requested file; @samp{/home/foo} in the example above
+(@pxref{Selectors}). @code{$@{autodir@}} defaults to @samp{/a} but may
+be changed with the @code{-a} command line option. Sun's automounter
+defaults to @samp{/tmp_mnt}. Note that there is no @samp{/} between
+the @code{$@{rhost@}} and @code{$@{rfs@}} since @code{$@{rfs@}} begins
+with a @samp{/}.@refill
+
+@node opts Option, remopts Option, fs Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection opts Option
+@cindex Setting system mount options
+@cindex Passing parameters to the mount system call
+@cindex mount system call
+@cindex mount system call flags
+@cindex The mount system call
+@cindex opts, mount option
+@cindex Mount option; opts
+
+The options to pass to the mount system call. A leading @samp{-} is
+silently ignored. The mount options supported generally correspond to
+those used by @b{mount}(8) and are listed below. Some additional
+pseudo-options are interpreted by @i{Amd} and are also listed.
+
+Unless specifically overridden, each of the system default mount options
+applies. Any options not recognized are ignored. If no options list is
+supplied the string @samp{rw,defaults} is used and all the system
+default mount options apply. Options which are not applicable for a
+particular operating system are silently ignored. For example, only 4.4BSD
+is known to implement the @code{compress} and @code{spongy} options.
+
+@table @code
+
+@item acdirmax=@var{n}
+@cindex Mount flags; acdirmax
+Set the maximum directory attribute cache timeout to @var{n}.
+
+@item acdirmin=@var{n}
+@cindex Mount flags; acdirmin
+Set the minimum directory attribute cache timeout to @var{n}.
+
+@item acregmax=@var{n}
+@cindex Mount flags; acregmax
+Set the maximum file attribute cache timeout to @var{n}.
+
+@item acregmin=@var{n}
+@cindex Mount flags; acregmin
+Set the minimum file attribute cache timeout to @var{n}.
+
+@item actimeo=@var{n}
+@cindex Mount flags; actimeo
+Set the overall attribute cache timeout to @var{n}.
+
+@item auto
+@cindex Mount flags; auto
+@itemx ignore
+@cindex Mount flags; ignore
+Ignore this mount by @b{df}(1).
+
+@item cache
+@cindex Mount flags; cache
+Allow data to be cached from a remote server for this mount.
+
+@item compress
+@cindex Mount flags; compress
+Use NFS compression protocol.
+
+@item defperm
+@cindex Mount flags; defperm
+Ignore the permission mode bits, and default file permissions to 0555,
+UID 0, and GID 0. Useful for CD-ROMs formatted as ISO-9660.
+
+@item dev
+@cindex Mount flags; dev
+Allow local special devices on this filesystem.
+
+@item dirmask=@var{n}
+@cindex Mount flags; dirmask
+For PCFS mounts, specify the maximum file permissions for directories
+in the file system. See the @samp{mask} option's description for more
+details. The mask value of @var{n} can be specified in decimal,
+octal, or hexadecimal.
+
+@item dumbtimr
+@cindex Mount flags; dumbtimr
+Turn off the dynamic retransmit timeout estimator. This may be useful
+for UDP mounts that exhibit high retry rates, since it is possible that
+the dynamically estimated timeout interval is too short.
+
+@item extatt
+@cindex Mount flags; extatt
+Enable extended attributes in ISO-9660 file systems.
+
+@item fsid
+@cindex Mount flags; fsid
+Set ID of filesystem.
+
+@item gens
+@cindex Mount flags; gens
+Enable generations in ISO-9660 file systems. Generations allow you to
+see all versions of a given file.
+
+@item group=@var{n}
+@cindex Mount flags; group
+For PCFS mounts, set the group of the files in the file system to
+@var{n} (which can either be a group name or a GID number). The
+default group is the group of the directory on which the file system
+is being mounted.
+
+@item grpid
+@cindex Mount flags; grpid
+Use BSD directory group-id semantics.
+
+@item int
+@cindex Mount flags; int
+@itemx intr
+@cindex Mount flags; intr
+Allow keyboard interrupts on hard mounts.
+
+@item lock
+@cindex Mount flags; lock
+Use the NFS locking protocol (default)
+
+@item longname
+@cindex Mount Flags; longname
+For PCFS mounts, force Win95 long names.
+
+@item mask=@var{n}
+@cindex Mount flags; mask
+For PCFS mounts, specify the maximum file permissions for files in the
+file system. For example, a mask of 755 specifies that, by default,
+the owner should have read, write, and execute permissions for files,
+but others should only have read and execute permissions. Only the
+nine low-order bits of mask are used. The default mask is taken from
+the directory on which the file system is being mounted. The mask
+value of @var{n} can be specified in decimal, octal, or hexadecimal.
+
+@item multi
+@cindex Mount flags; multi
+Perform multi-component lookup on files.
+
+@item maxgroups
+@cindex Mount flags; maxgroups
+Set the maximum number of groups to allow for this mount.
+
+@item nfsv3
+@cindex Mount flags; nfsv3
+Use NFS Version 3 for this mount.
+
+@item noac
+@cindex Mount flags; noac
+Turn off the attribute cache.
+
+@item noauto
+@cindex Mount flags; noauto
+This option is used by the mount command in @samp{/etc/fstab} or
+@samp{/etc/vfstab} and means not to mount this file system when mount -a
+is used.
+
+@item nocache
+@cindex Mount flags; nocache
+Do not allow data to be cached from a remote server for this
+mount.
+
+@item noconn
+@cindex Mount flags; noconn
+Don't make a connection on datagram transports.
+
+@item nocto
+@cindex Mount flags; nocto
+No close-to-open consistency.
+
+@item nodefperm
+@cindex Mount flags; nodefperm
+Do not ignore the permission mode bits. Useful for CD-ROMS formatted as
+ISO-9660.
+
+@item nodev
+@cindex Mount flags; nodev
+@itemx nodevs
+@cindex Mount flags; nodevs
+Don't allow local special devices on this filesystem.
+
+@item noexec
+@cindex Mount flags; noexec
+Don't allow program execution.
+
+@item noint
+@cindex Mount flags; noint
+Do not allow keyboard interrupts for this mount
+
+@item nolock
+@cindex Mount flags; nolock
+Do not use the NFS locking protocol
+
+@item nomnttab
+@cindex Mount flags; nomnttab
+This option is used internally to tell Amd that a Solaris 8 system using
+mntfs is in use.
+
+@item norrip
+@cindex Mount flags; norrip
+Turn off using of the Rock Ridge Interchange Protocol (RRIP) extensions
+to ISO-9660.
+
+@item nosub
+@cindex Mount flags; nosub
+Disallow mounts beneath this mount.
+
+@item nosuid
+@cindex Mount flags; nosuid
+Don't allow set-uid or set-gid executables on this filesystem.
+
+@item noversion
+@cindex Mount flags; noversion
+Strip the extension @samp{;#} from the version string of files recorded
+on an ISO-9660 CD-ROM.
+
+@item nowin95
+@cindex Mount Flags; nowin95
+For PCFS mounts, completely ignore Win95 entries.
+
+@item optionstr
+@cindex Mount flags; optionstr
+Under Solaris 8, provide the kernel a string of options to parse and
+show as part of the special in-kernel mount file system.
+
+@item overlay
+@cindex Mount flags; overlay
+Overlay this mount on top of an existing mount, if any.
+
+@item pgthresh=@var{n}
+@cindex Mount flags; pgthresh
+Set the paging threshold to @var{n} kilobytes.
+
+@item port=@var{n}
+@cindex Mount flags; port
+Set the NFS port to @var{n}.
+
+@item posix
+@cindex Mount flags; posix
+Turn on POSIX static pathconf for mounts.
+
+@item private
+@cindex Mount flags; private
+Use local locking instead of the NLM protocol, useful for IRIX 6 only.
+
+@item proplist
+@cindex Mount flags; proplist
+Support property lists (ACLs) for this mount, useful primarily for Tru64
+UNIX.
+
+@item proto=@var{s}
+@cindex Mount flags; proto
+Use transport protocol @var{s} for NFS (can be @code{"tcp"} or @code{"udp"}).
+
+@item quota
+@cindex Mount flags; quota
+Enable quota checking on this mount.
+
+@item rdonly
+@cindex Mount flags; rdonly
+@itemx ro
+@cindex Mount flags; ro
+Mount this filesystem readonly.
+
+@item resvport
+@cindex Mount flags; resvport
+Use a reserved port (smaller than 1024) for remote NFS mounts. Most
+systems assume that, but some allow for mounts to occur on non-reserved
+ports. This causes problems when such a system tries to NFS mount one
+that requires reserved ports. It is recommended that this option always
+be on.
+
+@item retrans=@i{n}
+@cindex Mount flags; retrans
+The number of NFS retransmits made before a user error is generated by a
+@samp{soft} mounted filesystem, and before a @samp{hard} mounted
+filesystem reports @samp{NFS server @dfn{yoyo} not responding still
+trying}.
+
+@item retry
+@cindex Mount flags; retry
+Set the NFS retry counter.
+
+@item rrip
+@cindex Mount flags; rrip
+Uses the Rock Ridge Interchange Protocol (RRIP) extensions to ISO-9660.
+
+@item rsize=@var{n}
+@cindex Mount flags; rsize
+The NFS read packet size. You may need to set this if you are using
+NFS/UDP through a gateway or a slow link.
+
+@item rw
+@cindex Mount flags; rw
+Allow reads and writes on this filesystem.
+
+@item shortname
+@cindex Mount Flags; longname
+For PCFS mounts, force old DOS short names only.
+
+@item soft
+@cindex Mount flags; soft
+Give up after @dfn{retrans} retransmissions.
+
+@item spongy
+@cindex Mount flags; spongy
+Like @samp{soft} for status requests, and @samp{hard} for data transfers.
+
+@item suid
+@cindex Mount flags; suid
+Allow set-uid programs on this mount.
+
+@item symttl
+@cindex Mount flags; symttl
+Turn off the symbolic link cache time-to-live.
+
+@item sync
+@cindex Mount flags; sync
+Perform synchronous filesystem operations on this mount.
+
+@item tcp
+@cindex Mount flags; tcp
+Use TCP/IP instead of UDP/IP, ignored if the NFS implementation does not
+support TCP/IP mounts.
+
+@item timeo=@var{n}
+@cindex Mount flags; timeo
+The NFS timeout, in tenth-seconds, before a request is retransmitted.
+
+@item user=@var{n}
+@cindex Mount flags; user
+For PCFS mounts, set the owner of the files in the file system to
+@var{n} (which can either be a user name or a UID number). The
+default owner is the owner of the directory on which the file system
+is being mounted.
+
+@item vers=@var{n}
+@cindex Mount flags; vers
+Use NFS protocol version number @var{n} (can be 2 or 3).
+
+@item wsize=@var{n}
+@cindex Mount flags; wsize
+The NFS write packet size. You may need to set this if you are using
+NFS/UDP through a gateway or a slow link.
+
+@end table
+
+The following options are implemented by @i{Amd}, rather than being
+passed to the kernel.
+
+@table @code
+
+@item nounmount
+@cindex Mount flags; nounmount
+Configures the mount so that its time-to-live will never expire. This
+is the default for non-network based filesystem types (such as
+mounting local disks, floppies, and CD-ROMs). See also the related
+@i{unmount} option.
+@c
+@c Implementation broken:
+
+@item ping=@var{n}
+@cindex Mount flags; ping
+The interval, in seconds, between keep-alive pings. When four
+consecutive pings have failed the mount point is marked as hung. This
+interval defaults to 30 seconds; if the ping interval is set to zero,
+@i{Amd} will use the default 30-second interval. If the interval is
+set to -1 (or any other negative value), no pings are sent and the
+host is assumed to be always up, which can cause unmounts to hang See
+the @i{softlookup} option for a better alternative. Turning pings off
+can be useful in NFS-HA (High-Availability) sites where the NFS
+service rarely goes down. Setting the ping value to a large value can
+reduce the amount of NFS_NULL chatter on your network considerably,
+especially in large sites.
+
+Note that if you have multiple @i{Amd} entries using the same file
+server, and each entry sets a different value of N, then each time Amd
+mounts a new entry, the ping value will be re-evaluated (and updated,
+turned off, or turned back on as needed). Finally, note that NFS_NULL
+pings are sent for both UDP and TCP mounts, because even a hung TCP
+mount can cause user processes to hang.
+
+@item public
+@cindex Mount flags; public
+Use WebNFS multi-component lookup on the public file handle instead of
+the mount protocol to obtain NFS file handles, as documented in the
+WebNFS Client Specification, RFC 2054. This means that @i{Amd} will not
+attempt to contact the remote portmapper or remote mountd daemon, and
+will only connect to the well-known NFS port 2049 or the port specified
+with the @i{port} mount option, thus making it easier to use NFS through
+a firewall.
+
+@item retry=@var{n}
+@cindex Mount flags; retry=@var{n}
+The number of times to retry the mount system call.
+
+@item softlookup
+@cindex Mount flags; softlookup
+Configures @i{Amd}'s behavior with respect to already-mounted shares from
+NFS fileservers that are unreachable. If softlookup is specified,
+trying to access such a share will result in an error (EIO, which is
+changed from the ENOENT 6.0 used to return). If it is not specified, a
+regular symlink is provided and the access will probably hang
+in the NFS filesystem.
+
+The default behavior depends on whether the mount is 'soft' or 'hard';
+softlookup can be used to change this default. This is changed from 6.0
+which always behaved as if softlookup was specified.
+
+@item unmount
+@cindex Mount flags; unmount
+Configures the mount so that its time-to-live will indeed expire (and
+thus may be automatically unmounted). This is also the default for
+network-based filesystem types (e.g., NFS). This option is useful for
+removable local media such as CD-ROMs, USB drives, etc. so they can
+expire when not in use, and get unmounted (such drives can get work
+out when they keep spinning). See also the related @i{nounmount}
+option.
+
+@item utimeout=@var{n}
+@cindex Mount flags; utimeout=@var{n}
+The interval, in seconds, that looked up and mounted map entries are
+cached. After that period of time, @i{Amd} will attempt to unmount
+the entries. If, however, the unmount fails (with EBUSY), then
+@i{Amd} will extend the mount's time-to-live by the @i{utimeout} value
+before the next unmount attempt is made. In fact the interval is
+extended before the unmount is attempted, to avoid thrashing. The
+default value is 120 seconds (two minutes) or as set by the @code{-w}
+command line option.
+
+@item xlatecookie
+@cindex Mount flags; xlatecookie
+Translate directory cookies between 32-long and 64-long lengths.
+
+@end table
+
+@node remopts Option, sublink Option, opts Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection remopts Option
+@cindex Setting system mount options for non-local networks
+@cindex remopts, mount option
+@cindex Mount option; remopts
+
+This option has the same use as @code{$@{opts@}} but applies only when
+the remote host is on a non-local network. For example, when using NFS
+across a gateway it is often necessary to use smaller values for the
+data read and write sizes. This can simply be done by specifying the
+small values in @var{remopts}. When a non-local host is accessed, the
+smaller sizes will automatically be used.
+
+@i{Amd} determines whether a host is local by examining the network
+interface configuration at startup. Any interface changes made after
+@i{Amd} has been started will not be noticed. The likely effect will
+be that a host may incorrectly be declared non-local.
+
+Unless otherwise set, the value of @code{$@{remopts@}} is the same as
+the value of @code{$@{opts@}}.
+
+@node sublink Option, type Option, remopts Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection sublink Option
+@cindex Setting the sublink option
+@cindex sublink, mount option
+@cindex Mount option; sublink
+
+The subdirectory within the mounted filesystem to which the reference
+should point. This can be used to prevent duplicate mounts in cases
+where multiple directories in the same mounted filesystem are used.
+
+@node type Option, , sublink Option, Map Options
+@comment node-name, next, previous, up
+@subsubsection type Option
+@cindex Setting the filesystem type option
+@cindex type, mount option
+@cindex Mount option; type
+
+The filesystem type to be used. @xref{Filesystem Types}, for a full
+description of each type.@refill
+
+@c ################################################################
+@node Amd Command Line Options, Filesystem Types, Mount Maps, Top
+@comment node-name, next, previous, up
+@chapter @i{Amd} Command Line Options
+@cindex Command line options, Amd
+@cindex Amd command line options
+@cindex Overriding defaults on the command line
+
+Many of @i{Amd}'s parameters can be set from the command line. The
+command line is also used to specify automount points and maps.
+
+The general format of a command line is
+
+@example
+amd [@i{options}] [@{ @i{directory} @i{map-name} [-@i{map-options}] @} ...]
+@end example
+
+For each directory and map-name given or specified in the
+@file{amd.conf} file, @i{Amd} establishes an automount point. The
+@dfn{map-options} may be any sequence of options or
+selectors---@pxref{Location Format}. The @dfn{map-options} apply only
+to @i{Amd}'s mount point.
+
+@samp{type:=toplvl;cache:=mapdefault;fs:=$@{map@}} is the default value for the
+map options. Default options for a map are read from a special entry in
+the map whose key is the string @samp{/defaults}. When default options
+are given they are prepended to any options specified in the mount-map
+locations as explained in @ref{Map Defaults}.
+
+The @dfn{options} are any combination of those listed below.
+
+Once the command line has been parsed, the automount points are mounted.
+The mount points are created if they do not already exist, in which case they
+will be removed when @i{Amd} exits.
+Finally, @i{Amd} disassociates itself from its controlling terminal and
+forks into the background.
+
+Note: Even if @i{Amd} has been built with @samp{-DDEBUG} (via
+@code{configure --enable-debug}), it will still background itself and
+disassociate itself from the controlling terminal. To use a debugger it
+is necessary to specify @samp{-D daemon} on the command line.
+However, even with all of this, mounts and unmounts are performed in the
+background, and @i{Amd} will always fork before doing them. Therefore,
+debugging what happens closely during un/mounts is more challenging.
+
+@emph{All} of @i{Amd}'s command options (save @code{-F} and @code{-T})
+can be specified in the @file{amd.conf} file. @xref{Amd Configuration
+File}. If @i{Amd} is invoked without any command line options, it will
+default to using the configuration file @file{/etc/amd.conf}, if one
+exists.
+
+@menu
+* -a Option:: Automount directory.
+* -c Option:: Cache timeout interval.
+* -d Option:: Domain name.
+* -k Option:: Kernel architecture.
+* -l Option:: Log file.
+* -n Option:: Hostname normalization.
+* -o Option:: Operating system version.
+* -p Option:: Output process id.
+* -r Option:: Restart existing mounts.
+* -t Option:: Kernel RPC timeout.
+* -v Option:: Version information.
+* -w Option:: Wait interval after failed unmount.
+* -x Option:: Log options.
+* -y Option:: NIS domain.
+* -A Option:: Operating system Architecture.
+* -C Option:: Cluster name.
+* -D Option:: Debug flags.
+* -F Option:: Amd configuration file.
+* -H Option:: Show brief help.
+* -O Option:: Operating system name.
+* -S Option:: Lock executable pages in memory.
+* -T Option:: Set tag for configuration file.
+@end menu
+
+@c ----------------------------------------------------------------
+@node -a Option, -c Option, Amd Command Line Options, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-a} @var{directory}
+@cindex Automount directory
+@cindex Setting the default mount directory
+
+Specifies the default mount directory. This option changes the variable
+@code{$@{autodir@}} which otherwise defaults to @file{/a}. For example,
+some sites prefer @file{/amd} or @file{/n}.
+
+@example
+amd -a /amd ...
+@end example
+
+@c ----------------------------------------------------------------
+@node -c Option, -d Option, -a Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-c} @var{cache-interval}
+@cindex Cache interval
+@cindex Interval before a filesystem times out
+@cindex Setting the interval before a filesystem times out
+@cindex Changing the interval before a filesystem times out
+
+Selects the period, in seconds, for which a name is cached by @i{Amd}.
+If no reference is made to the volume in this period, @i{Amd} discards
+the volume name to filesystem mapping.
+
+Once the last reference to a filesystem has been removed, @i{Amd}
+attempts to unmount the filesystem. If the unmount fails the interval
+is extended by a further period as specified by the @samp{-w} command
+line option or by the @samp{utimeout} mount option.
+
+The default @dfn{cache-interval} is 300 seconds (five minutes).
+
+@c ----------------------------------------------------------------
+@node -d Option, -k Option, -c Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-d} @var{domain}
+@cindex Domain name
+@cindex Setting the local domain name
+@cindex Overriding the local domain name
+
+Specifies the host's domain. This sets the internal variable
+@code{$@{domain@}} and affects the @code{$@{hostd@}} variable.
+
+If this option is not specified and the hostname already contains the
+local domain then that is used, otherwise the default value of
+@code{$@{domain@}} is @samp{unknown.domain}.
+
+For example, if the local domain was @samp{doc.ic.ac.uk}, @i{Amd} could
+be started as follows:
+
+@example
+amd -d doc.ic.ac.uk ...
+@end example
+
+@c ----------------------------------------------------------------
+@node -k Option, -l Option, -d Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-k} @var{kernel-architecture}
+@cindex Setting the Kernel architecture
+
+Specifies the kernel architecture of the system. This is usually the
+output of @samp{uname -m} (the ``machine'' value gotten from
+@b{uname}(2)). If the @b{uname}(2) system call is not available, the
+value of @code{$@{karch@}} defaults to that of @code{$@{arch@}}.
+
+The only effect of this option is to set the variable @code{$@{karch@}}.
+
+This option would be used as follows:
+
+@example
+amd -k `arch -k` ...
+@end example
+
+@c ----------------------------------------------------------------
+@node -l Option, -n Option, -k Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-l} @var{log-option}
+@cindex Log filename
+@cindex Setting the log file
+@cindex Using syslog to log errors
+@cindex syslog
+
+Selects the form of logging to be made. Several special @dfn{log-options}
+are recognized.
+
+@enumerate
+@item
+If @dfn{log-option} is the string @samp{syslog}, @i{Amd} will use the
+@b{syslog}(3) mechanism. If your system supports syslog facilities, then
+the default facility used is @samp{LOG_DAEMON}.
+
+@item
+@cindex syslog facility; specifying an alternate
+When using syslog, if you wish to change the facility, append its name
+to the log option name, delimited by a single colon. For example, if
+@dfn{log-options} is the string @samp{syslog:local7} then @b{Amd} will
+log messages via @b{syslog}(3) using the @samp{LOG_LOCAL7} facility. If
+the facility name specified is not recognized, @i{Amd} will default to
+@samp{LOG_DAEMON}. Note: while you can use any syslog facility
+available on your system, it is generally a bad idea to use those
+reserved for other services such as @samp{kern}, @samp{lpr},
+@samp{cron}, etc.
+
+@item
+If @dfn{log-option} is the string @samp{/dev/stderr}, @i{Amd} will use
+standard error, which is also the default target for log messages. To
+implement this, @i{Amd} simulates the effect of the @samp{/dev/fd}
+driver.
+@end enumerate
+
+Any other string is taken as a filename to use for logging. Log
+messages are appended to the file if it already exists, otherwise a new
+file is created. The file is opened once and then held open, rather
+than being re-opened for each message.
+
+Normally, when long-running daemons hold an open file descriptor on a
+log file, it is impossible to ``rotate'' the log file and compress older
+logs on a daily basis. The daemon needs to be told to discard (via
+@b{close}(2)) its file handle, and re-open the log file. This is done
+using @code{amq -l} @i{log-option}. @xref{Amq -l option}.
+
+If the @samp{syslog} option is specified but the system does not support
+syslog or if the named file cannot be opened or created, @i{Amd} will
+use standard error. Error messages generated before @i{Amd} has
+finished parsing the command line are printed on standard error.
+
+Since @i{Amd} tends to generate a lot of logging information (especially
+if debugging was turned on), and due to it being an important program
+running on the system, it is usually best to log to a separate disk
+file. In that case @i{Amd} would be started as follows:
+
+@example
+amd -l /var/log/amd ...
+@end example
+
+@c ----------------------------------------------------------------
+@node -n Option, -o Option, -l Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-n}
+@cindex Hostname normalization
+@cindex Aliased hostnames
+@cindex Resolving aliased hostnames
+@cindex Normalizing hostnames
+
+Normalizes the remote hostname before using it. Normalization is done
+by replacing the value of @code{$@{rhost@}} with the (generally fully
+qualified) primary name returned by a hostname lookup.
+
+This option should be used if several names are used to refer to a
+single host in a mount map.
+
+@c ----------------------------------------------------------------
+@node -o Option, -p Option, -n Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-o} @var{op-sys-ver}
+@cindex Operating System version
+@cindex Setting the Operating System version
+
+Overrides the compiled-in version number of the operating system, with
+@var{op-sys-ver}. Useful when the built-in version is not desired for
+backward compatibility reasons. For example, if the built-in version is
+@samp{2.5.1}, you can override it to @samp{5.5.1}, and use older maps
+that were written with the latter in mind.
+
+@c ----------------------------------------------------------------
+@node -p Option, -r Option, -o Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-p}
+@cindex Process id
+@cindex Displaying the process id
+@cindex process id of Amd daemon
+@cindex pid file, creating with -p option
+@cindex Creating a pid file
+
+Causes @i{Amd}'s process id to be printed on standard output.
+This can be redirected to a suitable file for use with kill:
+
+@example
+amd -p > /var/run/amd.pid ...
+@end example
+
+This option only has an affect if @i{Amd} is running in daemon mode.
+If @i{Amd} is started with the @code{-D daemon} debug flag, this
+option is ignored.
+
+@c ----------------------------------------------------------------
+@node -r Option, -t Option, -p Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-r}
+@cindex Restarting existing mounts
+@cindex Picking up existing mounts
+
+Tells @i{Amd} to restart existing mounts (@pxref{Inheritance Filesystem}).
+@c @dfn{This option will be made the default in the next release.}
+
+@c ----------------------------------------------------------------
+@node -t Option, -v Option, -r Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-t} @var{timeout.retransmit}
+@cindex Setting Amd's RPC parameters
+
+Specifies the RPC @dfn{timeout} interval and the @dfn{retransmit}
+counter used by the kernel to communicate to @i{Amd}. These are used to
+set the @samp{timeo} and @samp{retrans} mount options, respectively.
+The default timeout is 0.8 seconds, and the default number of
+retransmissions is 11.
+
+@i{Amd} relies on the kernel RPC retransmit mechanism to trigger mount
+retries. The values of these parameters change the overall retry
+interval. Too long an interval gives poor interactive response; too
+short an interval causes excessive retries.
+
+@c ----------------------------------------------------------------
+@node -v Option, -w Option, -t Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-v}
+@cindex Version information
+@cindex Discovering version information
+@cindex How to discover your version of Amd
+
+Print version information on standard error and then exit. The output
+is of the form:
+
+@example
+Copyright (c) 1997-1999 Erez Zadok
+Copyright (c) 1990 Jan-Simon Pendry
+Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+Copyright (c) 1990 The Regents of the University of California.
+am-utils version 6.0a15 (build 61).
+Built by ezk@@cs.columbia.edu on date Wed Oct 22 15:21:03 EDT 1997.
+cpu=sparc (big-endian), arch=sun4, karch=sun4u.
+full_os=solaris2.5.1, os=sos5, osver=5.5.1, vendor=sun.
+Map support for: root, passwd, union, nisplus, nis, ndbm, file, error.
+AMFS: nfs, link, nfsx, nfsl, host, linkx, program, union, inherit,
+ ufs, lofs, hsfs, pcfs, auto, direct, toplvl, error.
+FS: autofs, cachefs, cdfs, lofs, nfs, nfs3, pcfs, tfs, tmpfs, ufs.
+Network 1: wire="mcl-lab-net.cs.columbia.edu" (netnumber=128.59.13).
+Network 2: wire="14-net.cs.columbia.edu" (netnumber=128.59.14).
+Network 3: wire="old-net.cs.columbia.edu" (netnumber=128.59.16).
+@end example
+
+The information includes the version number, number of times @i{Amd} was
+compiled on the local system, release date and name of the release.
+Following come the cpu type, byte ordering, and the architecture and
+kernel architecture as @code{$@{arch@}} and @code{$@{karch@}},
+respectively. The next line lists the operating system full name, short
+name, version, and vendor. These four values correspond to the
+variables @code{$@{full_os@}}, @code{$@{os@}}, @code{$@{osver@}}, and
+@code{$@{vendor@}}, respectively. @xref{Supported Platforms}.
+
+Then come a list of map types supported, filesystems internally
+supported by @i{Amd} (AMFS), and generic filesystems available (FS).
+Finally all known networks (if any) of this host are listed by name
+and number. They are available via the variables
+@code{$@{wire@}} or @code{$@{network@}}, and
+@code{$@{netnumber@}} (@pxref{Selectors}) or the @samp{in_network}
+selector function (@pxref{in_network Selector Function}).
+
+@c ----------------------------------------------------------------
+@node -w Option, -x Option, -v Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-w} @var{wait-timeout}
+@cindex Setting the interval between unmount attempts
+@cindex unmount attempt backoff interval
+
+Selects the interval in seconds between unmount attempts after the
+initial time-to-live has expired.
+
+This defaults to 120 seconds (two minutes).
+
+@c ----------------------------------------------------------------
+@node -x Option, -y Option, -w Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-x} @var{opts}
+@cindex Log message selection
+@cindex Selecting specific log messages
+@cindex How to select log messages
+@cindex syslog priorities
+
+Specifies the type and verbosity of log messages. @dfn{opts} is
+a comma separated list selected from the following options:
+
+@table @code
+@item fatal
+Fatal errors
+@item error
+Non-fatal errors
+@item user
+Non-fatal user errors
+@item warn
+Recoverable errors
+@item warning
+Alias for @code{warn}
+@item info
+Information messages
+@item map
+Mount map usage
+@item stats
+Additional statistics
+@item all
+All of the above
+@end table
+
+Initially a set of default logging flags is enabled. This is as if
+@samp{-x all,nomap,nostats} had been selected. The command line is
+parsed and logging is controlled by the @code{-x} option. The very first
+set of logging flags is saved and can not be subsequently disabled using
+@i{Amq}. This default set of options is useful for general production
+use.@refill
+
+The @samp{info} messages include details of what is mounted and
+unmounted and when filesystems have timed out. If you want to have the
+default set of messages without the @samp{info} messages then you simply
+need @samp{-x noinfo}. The messages given by @samp{user} relate to
+errors in the mount maps, so these are useful when new maps are
+installed. The following table lists the syslog priorities used for each
+of the message types.@refill
+
+@table @code
+@item fatal
+@samp{LOG_CRIT}
+@item error
+@samp{LOG_ERR}
+@item user
+@samp{LOG_WARNING}
+@item warning
+@samp{LOG_WARNING}
+@item info
+@samp{LOG_INFO}
+@item debug
+@samp{LOG_DEBUG}
+@item map
+@samp{LOG_DEBUG}
+@item stats
+@samp{LOG_INFO}
+@end table
+
+
+The options can be prefixed by the string @samp{no} to indicate
+that this option should be turned off. For example, to obtain all
+but @samp{info} messages the option @samp{-x all,noinfo} would be used.
+
+If @i{Amd} was built with debugging enabled the @code{debug} option is
+automatically enabled regardless of the command line options.
+
+@c ----------------------------------------------------------------
+@node -y Option, -A Option, -x Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-y} @var{NIS-domain}
+@cindex NIS (YP) domain name
+@cindex Overriding the NIS (YP) domain name
+@cindex Setting the NIS (YP) domain name
+@cindex YP domain name
+
+Selects an alternate NIS domain. This is useful for debugging and
+cross-domain shared mounting. If this flag is specified, @i{Amd}
+immediately attempts to bind to a server for this domain.
+@c @i{Amd} refers to NIS maps when it starts, unless the @code{-m} option
+@c is specified, and whenever required in a mount map.
+
+@c ----------------------------------------------------------------
+@node -A Option, -C Option, -y Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-A} @var{architecture}
+@cindex Setting the operating system architecture
+
+Specifies the OS architecture of the system.
+The only effect of this option is to set the variable @code{$@{arch@}}.
+
+This option would be used as follows:
+
+@example
+amd -A i386 ...
+@end example
+
+@c ----------------------------------------------------------------
+@node -C Option, -D Option, -A Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-C} @var{cluster-name}
+@cindex Cluster names
+@cindex Setting the cluster name
+
+Specifies the name of the cluster of which the local machine is a member.
+The only effect is to set the variable @code{$@{cluster@}}.
+The @dfn{cluster-name} is will usually obtained by running another command which uses
+a database to map the local hostname into a cluster name.
+@code{$@{cluster@}} can then be used as a selector to restrict mounting of
+replicated data.
+If this option is not given, @code{$@{cluster@}} has the same value as @code{$@{domain@}}.
+This would be used as follows:
+
+@example
+amd -C `clustername` ...
+@end example
+
+@c ----------------------------------------------------------------
+@node -D Option, -F Option, -C Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-D} @var{opts}
+@cindex Debug options
+@cindex Setting debug flags
+
+Controls the verbosity and coverage of the debugging trace; @dfn{opts}
+is a comma separated list of debugging options. The @code{-D} option is
+only available if @i{Amd} was compiled with @samp{-DDEBUG}, or
+configured with @code{configure --enable-debug}. The memory debugging
+facilities (@samp{mem}) are only available if @i{Amd} was compiled with
+@samp{-DDEBUG_MEM} (in addition to @samp{-DDEBUG}), or configured with
+@code{configure --enable-debug=mem}.
+
+The most common options to use are @samp{-D trace} and @samp{-D test}
+(which turns on all the useful debug options). As usual, every option
+can be prefixed with @samp{no} to turn it off.
+
+@table @code
+@item all
+all ``reasonable'' options (currently trace|str|full|mem|info|readdir)
+@item amq
+do not register for amq
+@item daemon
+do not enter daemon mode
+@item fork
+do not fork child worker (hlfsd only)
+@item full
+program trace
+@item hrtime
+print high resolution time stamps (only if @b{syslog}(3) is not used)
+@item info
+@cindex debugging hesiod resolver service
+@cindex Hesiod; turning on RES_DEBUG
+info service specific debugging (hesiod, nis, etc.) In the case of
+hesiod maps, turns on the hesiod RES_DEBUG internal debugging option.
+@item mem
+trace memory allocations. Needs to be explicitly enabled at compile
+time with --enable-debug=mem.
+@item mtab
+use local @file{./mtab} file
+@item readdir
+show readdir progress
+@item str
+debug string munging
+@item test
+full debug but no daemon
+@item trace
+trace RPC protocol and NFS mount arguments
+@item xdrtrace
+trace XDR routines
+@end table
+
+You may also refer to the program source for a more detailed explanation
+of the available options.
+
+@c ----------------------------------------------------------------
+@node -F Option, -H Option, -D Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-F} @var{conf-file}
+@cindex Amd configuration file; specifying name
+@cindex Amd configuration file
+@cindex amd.conf file
+
+Specify an @i{Amd} configuration file @var{conf-file} to use. For a
+description of the format and syntax, @pxref{Amd Configuration File}.
+This configuration file is used to specify any options in lieu of typing
+many of them on the command line. The @file{amd.conf} file includes
+directives for every command line option @i{Amd} has, and many more that
+are only available via the configuration file facility. The
+configuration file specified by this option is processed after all other
+options had been processed, regardless of the actual location of this
+option on the command line.
+
+@c ----------------------------------------------------------------
+@node -H Option, -O Option, -F Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-H}
+@cindex Displaying brief help
+@cindex Help; showing from Amd
+
+Print a brief help and usage string.
+
+@c ----------------------------------------------------------------
+@node -O Option, -S Option, -H Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-O} @var{op-sys-name}
+@cindex Operating System name
+@cindex Setting the Operating System name
+
+Overrides the compiled-in name of the operating system, with
+@var{op-sys-name}. Useful when the built-in name is not desired for
+backward compatibility reasons. For example, if the build in name is
+@samp{sunos5}, you can override it to the old name @samp{sos5}, and use
+older maps which were written with the latter in mind.
+
+@c ----------------------------------------------------------------
+@node -S Option, -T Option, -O Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-S}
+@cindex plock; using
+@cindex mlockall; using
+@cindex locking executable pages in memory
+
+Do @emph{not} lock the running executable pages of @i{Amd} into memory.
+To improve @i{Amd}'s performance, systems that support the @b{plock}(3)
+or @b{mlockall}(2)
+call lock the @i{Amd} process into memory. This way there is less
+chance the operating system will schedule, page out, and swap the
+@i{Amd} process as needed. This tends to improve @i{Amd}'s performance,
+at the cost of reserving the memory used by the @i{Amd} process (making
+it unavailable for other processes). If this behavior is not desired,
+use the @code{-S} option.
+
+@c ----------------------------------------------------------------
+@node -T Option, , -S Option, Amd Command Line Options
+@comment node-name, next, previous, up
+@section @code{-T} @var{tag}
+@cindex Tags for Amd configuration file
+@cindex Configuration file; tags
+
+Specify a tag to use with @file{amd.conf}. All map entries tagged with
+@var{tag} will be processed. Map entries that are not tagged are always
+processed. Map entries that are tagged with a tag other than @var{tag}
+will not be processed.
+
+@c ################################################################
+@node Filesystem Types, Amd Configuration File, Amd Command Line Options, Top
+@comment node-name, next, previous, up
+@chapter Filesystem Types
+@cindex Filesystem types
+@cindex Mount types
+@cindex Types of filesystem
+
+To mount a volume, @i{Amd} must be told the type of filesystem to be
+used. Each filesystem type typically requires additional information
+such as the fileserver name for NFS.
+
+From the point of view of @i{Amd}, a @dfn{filesystem} is anything that
+can resolve an incoming name lookup. An important feature is support
+for multiple filesystem types. Some of these filesystems are
+implemented in the local kernel and some on remote fileservers, whilst
+the others are implemented internally by @i{Amd}.@refill
+
+The two common filesystem types are UFS and NFS. Four other user
+accessible filesystems (@samp{link}, @samp{program}, @samp{auto} and
+@samp{direct}) are also implemented internally by @i{Amd} and these are
+described below. There are two additional filesystem types internal to
+@i{Amd} which are not directly accessible to the user (@samp{inherit}
+and @samp{error}). Their use is described since they may still have an
+effect visible to the user.@refill
+
+@menu
+* Network Filesystem:: A single NFS filesystem.
+* Network Host Filesystem:: NFS mount a host's entire export tree.
+* Network Filesystem Group:: An atomic group of NFS filesystems.
+* Unix Filesystem:: Native disk filesystem.
+* Caching Filesystem:: Caching from remote server filesystem.
+* CD-ROM Filesystem:: ISO9660 CD ROM.
+* Loopback Filesystem:: Local loopback-mount filesystem.
+* Memory/RAM Filesystem:: A memory or RAM-based filesystem.
+* Null Filesystem:: 4.4BSD's loopback-mount filesystem.
+* Floppy Filesystem:: MS-DOS Floppy filesystem.
+* Translucent Filesystem:: The directory merging filesystem.
+* Shared Memory+Swap Filesystem:: Sun's tmpfs filesystem.
+* User ID Mapping Filesystem:: 4.4BSD's umapfs filesystem.
+* Program Filesystem:: Generic Program mounts.
+* Symbolic Link Filesystem:: Local link.
+* Symbolic Link Filesystem II:: Local link referencing existing filesystem.
+* NFS-Link Filesystem:: Link if path exists, NFS otherwise.
+* Automount Filesystem::
+* Direct Automount Filesystem::
+* Union Filesystem::
+* Error Filesystem::
+* Top-level Filesystem::
+* Root Filesystem::
+* Inheritance Filesystem::
+@end menu
+
+@c ----------------------------------------------------------------
+@node Network Filesystem, Network Host Filesystem, Filesystem Types, Filesystem Types
+@comment node-name, next, previous, up
+@section Network Filesystem (@samp{nfs})
+@cindex NFS
+@cindex Mounting an NFS filesystem
+@cindex How to mount and NFS filesystem
+@cindex nfs, filesystem type
+@cindex Filesystem type; nfs
+
+The @dfn{nfs} (@samp{type:=nfs}) filesystem type provides access to Sun's NFS.
+
+@noindent
+The following options must be specified:
+
+@table @code
+@cindex rhost, mount option
+@cindex Mount option; rhost
+@item rhost
+the remote fileserver. This must be an entry in the hosts database. IP
+addresses are not accepted. The default value is taken
+from the local host name (@code{$@{host@}}) if no other value is
+specified.
+
+@cindex rfs, mount option
+@cindex Mount option; rfs
+@item rfs
+the remote filesystem.
+If no value is specified for this option, an internal default of
+@code{$@{path@}} is used.
+@end table
+
+NFS mounts require a two stage process. First, the @dfn{file handle} of
+the remote file system must be obtained from the server. Then a mount
+system call must be done on the local system. @i{Amd} keeps a cache
+of file handles for remote file systems. The cache entries have a
+lifetime of a few minutes.
+
+If a required file handle is not in the cache, @i{Amd} sends a request
+to the remote server to obtain it.
+@c @i{Amd} @dfn{does not} wait for
+@c a response; it notes that one of the locations needs retrying, but
+@c continues with any remaining locations. When the file handle becomes
+@c available, and assuming none of the other locations was successfully
+@c mounted, @i{Amd} will retry the mount. This mechanism allows several
+@c NFS filesystems to be mounted in parallel.
+@c @footnote{The mechanism
+@c is general, however NFS is the only filesystem
+@c for which the required hooks have been written.}
+@c The first one which responds with a valid file handle will be used.
+
+Historically, this documentation has maintained that @i{Amd} will try
+all the locations in parallel and use the first one which responds
+with a valid file handle. This has not been the case for quite some
+time, however. Instead, @i{Amd} will go through each location, one by
+one, and will only skip to the next one if the previous one either
+fails or times out.
+
+@noindent
+An NFS entry might be:
+
+@example
+jsp host!=charm;type:=nfs;rhost:=charm;rfs:=/home/charm;sublink:=jsp
+@end example
+
+The mount system call and any unmount attempts are always done
+in a new task to avoid the possibility of blocking @i{Amd}.
+
+@c ----------------------------------------------------------------
+@node Network Host Filesystem, Network Filesystem Group, Network Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Network Host Filesystem (@samp{host})
+@cindex Network host filesystem
+@cindex Mounting entire export trees
+@cindex How to mount all NFS exported filesystems
+@cindex host, filesystem type
+@cindex Filesystem type; host
+
+@c NOTE: the current implementation of the @dfn{host} filesystem type
+@c sometimes fails to maintain a consistent view of the remote mount tree.
+@c This happens when the mount times out and only some of the remote mounts
+@c are successfully unmounted. To prevent this from occurring, use the
+@c @samp{nounmount} mount option.
+
+The @dfn{host} (@samp{type:=host}) filesystem allows access to the entire export tree of an
+NFS server. The implementation is layered above the @samp{nfs}
+implementation so keep-alives work in the same way. The only option
+which needs to be specified is @samp{rhost} which is the name of the
+fileserver to mount.
+
+The @samp{host} filesystem type works by querying the mount daemon on
+the given fileserver to obtain its export list. @i{Amd} then obtains
+filehandles for each of the exported filesystems. Any errors at this
+stage cause that particular filesystem to be ignored. Finally each
+filesystem is mounted. Again, errors are logged but ignored. One
+common reason for mounts to fail is that the mount point does not exist.
+Although @i{Amd} attempts to automatically create the mount point, it
+may be on a remote filesystem to which @i{Amd} does not have write
+permission.
+
+When an attempt to unmount a @samp{host} filesystem mount fails, @i{Amd}
+remounts any filesystems which had successfully been unmounted. To do
+this @i{Amd} queries the mount daemon again and obtains a fresh copy of
+the export list. @i{Amd} then tries to mount any exported filesystems
+which are not currently mounted.
+
+Sun's automounter provides a special @samp{-hosts} map. To achieve the
+same effect with @i{Amd} requires two steps. First a mount map must
+be created as follows:
+
+@example
+* type:=host;rhost:=$@{key@};fs:=$@{autodir@}/$@{rhost@}/root
+@end example
+
+@noindent
+and then start @i{Amd} with the following command
+
+@example
+amd /net net.map
+@end example
+
+@noindent
+where @samp{net.map} is the name of map described above. Note that the
+value of @code{$@{fs@}} is overridden in the map. This is done to avoid
+a clash between the mount tree and any other filesystem already mounted
+from the same fileserver.
+
+If different mount options are needed for different hosts then
+additional entries can be added to the map, for example
+
+@example
+host2 opts:=ro,nosuid,soft
+@end example
+
+@noindent
+would soft mount @samp{host2} read-only.
+
+@c ----------------------------------------------------------------
+@node Network Filesystem Group, Unix Filesystem, Network Host Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Network Filesystem Group (@samp{nfsx})
+@cindex Network filesystem group
+@cindex Atomic NFS mounts
+@cindex Mounting an atomic group of NFS filesystems
+@cindex How to mount an atomic group of NFS filesystems
+@cindex nfsx, filesystem type
+@cindex Filesystem type; nfsx
+
+The @dfn{nfsx} (@samp{type:=nfsx}) filesystem allows a group of filesystems to be mounted
+from a single NFS server. The implementation is layered above the
+@samp{nfs} implementation so keep-alives work in the same way.
+
+@emph{WARNING}: @samp{nfsx} is meant to be a ``last resort'' kind of
+solution. It is racy and poorly supported. The authors @emph{highly}
+recommend that other solutions be considered before relying on it.
+
+The options are the same as for the @samp{nfs} filesystem with one
+difference for @samp{rfs}, as explained below.
+
+@noindent
+The following options should be specified:
+
+@table @code
+@item rhost
+the remote fileserver. The default value is taken from the local
+host name (@code{$@{host@}}) if no other value is specified.
+
+@item rfs
+is a list of filesystems to mount, and must be specified.
+The list is in the form of a comma separated strings.
+@end table
+
+@noindent
+For example:
+
+@example
+pub type:=nfsx;rhost:=gould;\
+ rfs:=/public,/,graphics,usenet;fs:=$@{autodir@}/$@{rhost@}/root
+@end example
+
+The first string defines the root of the tree, and is applied as a
+prefix to the remaining members of the list which define the individual
+filesystems. The first string is @emph{not} used as a filesystem name.
+A serial operation is used to determine the local mount points to
+ensure a consistent layout of a tree of mounts.
+
+Here, the @emph{three} filesystems, @samp{/public},
+@samp{/public/graphics} and @samp{/public/usenet}, would be mounted.@refill
+
+A local mount point, @code{$@{fs@}}, @emph{must} be specified. The
+default local mount point will not work correctly in the general case.
+A suggestion is to use @samp{fs:=$@{autodir@}/$@{rhost@}/root}.@refill
+
+@c ----------------------------------------------------------------
+@node Unix Filesystem, Caching Filesystem, Network Filesystem Group, Filesystem Types
+@comment node-name, next, previous, up
+@section Unix Filesystem (@samp{ufs}, @samp{xfs}, or @samp{efs})
+@cindex Unix filesystem
+@cindex UFS
+@cindex XFS
+@cindex EFS
+@cindex Mounting a UFS filesystem
+@cindex Mounting a local disk
+@cindex How to mount a UFS filesystems
+@cindex How to mount a local disk
+@cindex Disk filesystems
+@cindex ufs, filesystem type
+@cindex Filesystem type; ufs
+@cindex xfs, filesystem type
+@cindex Filesystem type; xfs
+@cindex efs, filesystem type
+@cindex Filesystem type; efs
+
+The @dfn{ufs} (@samp{type:=ufs}) filesystem type provides access to the system's standard
+disk filesystem---usually a derivative of the Berkeley Fast Filesystem.
+
+@noindent
+The following option must be specified:
+
+@table @code
+@cindex dev, mount option
+@cindex Mount option; dev
+@item dev
+the block special device to be mounted.
+@end table
+
+A UFS entry might be:
+
+@example
+jsp host==charm;type:=ufs;dev:=/dev/sd0d;sublink:=jsp
+@end example
+
+UFS is the default Unix disk-based file system, which Am-utils picks up
+during the autoconfiguration phase. Some systems have more than one
+type, such as IRIX, that comes with EFS (Extent File System) and XFS
+(Extended File System). In those cases, you may explicitly set the file
+system type, by using entries such:
+
+@example
+ez1 type:=efs;dev:=/dev/xd0a
+ez2 type:=xfs;dev:=/dev/sd3c
+@end example
+
+The UFS/XFS/EFS filesystems are never timed out by default, i.e. they
+will never be unmounted by @i{Amd}. If automatic unmounting is
+desired, the ``unmount'' option should be added to the mount options
+for the entry.
+
+@c ----------------------------------------------------------------
+@node Caching Filesystem, CD-ROM Filesystem, Unix Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Caching Filesystem (@samp{cachefs})
+@cindex Caching Filesystem
+@cindex cachefs, filesystem type
+@cindex Filesystem type; cachefs
+
+The @dfn{cachefs} (@samp{type:=cachefs}) filesystem caches files from
+one location onto another, presumably providing faster access. It is
+particularly useful to cache from a larger and remote (slower) NFS
+partition to a smaller and local (faster) UFS directory.
+
+@noindent
+The following options must be specified:
+
+@table @code
+@cindex cachedir, mount option
+@cindex Mount option; cachedir
+@item cachedir
+the directory where the cache is stored.
+@item rfs
+the path name to the ``back file system'' to be cached from.
+@item fs
+the ``front file system'' mount point to the cached files, where @i{Amd}
+will set a symbolic link pointing to.
+@end table
+
+A CacheFS entry for, say, the @file{/import} @i{Amd} mount point, might
+be:
+
+@example
+copt type:=cachefs;cachedir:=/cache;rfs:=/import/opt;fs:=/n/import/copt
+@end example
+
+Access to the pathname @file{/import/copt} will follow a symbolic link
+to @file{/n/import/copt}. The latter is the mount point for a caching
+file system, that caches from @file{/import/opt} to @file{/cache}.
+
+The cachefs filesystem is never timed out by default, i.e. it will
+never be unmounted by @i{Amd}. If automatic unmounting is desired, the
+``unmount'' option should be added to the mount options for the entry.
+
+@b{Caveats}:
+@enumerate
+@item This file system is currently only implemented for Solaris 2.x!
+@item Before being used for the first time, the cache directory @i{must} be
+initialized with @samp{cfsadmin -c @var{cachedir}}. See the manual page for
+@b{cfsadmin}(1M) for more information.
+@item The ``back file system'' mounted must be a complete file system, not
+a subdirectory thereof; otherwise you will get an error ``Invalid Argument''.
+@item If @i{Amd} aborts abnormally, the state of the cache may be
+inconsistent, requiring running the command @file{fsck -F cachefs
+@var{cachedir}}. Otherwise you will get the error ``No Space Left on Device''.
+@end enumerate
+
+@c ----------------------------------------------------------------
+@node CD-ROM Filesystem, Loopback Filesystem, Caching Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section CD-ROM Filesystem (@samp{cdfs})
+@cindex CD-ROM Filesystem
+@cindex cdfs, filesystem type
+@cindex Filesystem type; cdfs
+
+The @dfn{cdfs} (@samp{type:=cdfs}) filesystem mounts a CD-ROM with an
+ISO9660 format filesystem on it.
+
+@noindent
+The following option must be specified:
+
+@table @code
+@cindex dev, mount option
+@cindex Mount option; dev
+@item dev
+the block special device to be mounted.
+@end table
+
+Some operating systems will fail to mount read-only CDs unless the
+@samp{ro} option is specified. A cdfs entry might be:
+
+@example
+cdfs os==sunos4;type:=cdfs;dev:=/dev/sr0 \
+ os==sunos5;addopts:=ro;type:=cdfs;dev:=/dev/dsk/c0t6d0s2
+@end example
+
+@c ----------------------------------------------------------------
+@node Loopback Filesystem, Memory/RAM Filesystem, CD-ROM Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Loopback Filesystem (@samp{lofs})
+@cindex Loopback Filesystem
+@cindex lofs, filesystem type
+@cindex Filesystem type; lofs
+
+The @dfn{lofs} (@samp{type:=lofs}) filesystem is also called the
+loopback filesystem. It mounts a local directory on another, thus
+providing mount-time binding to another location (unlike symbolic
+links).
+
+The loopback filesystem is particularly useful within the context of a
+chroot-ed directory (via @b{chroot}(2)), to provide access to
+directories otherwise inaccessible.
+
+@noindent
+The following option must be specified:
+
+@table @code
+@cindex rfs, mount option
+@cindex Mount option; rfs
+@item rfs
+the pathname to be mounted on top of @code{$@{fs@}}.
+@end table
+
+Usually, the FTP server runs in a chroot-ed environment, for security
+reasons. In this example, lofs is used to provide a subdirectory within
+a user's home directory, also available for public ftp.
+
+@example
+lofs type:=lofs;rfs:=/home/ezk/myftpdir;fs:=/usr/ftp/pub/ezk
+@end example
+
+@c ----------------------------------------------------------------
+@node Memory/RAM Filesystem, Null Filesystem, Loopback Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Memory/RAM Filesystem (@samp{mfs})
+@cindex Memory/RAM Filesystem
+@cindex mfs, filesystem type
+@cindex Filesystem type; mfs
+
+The @dfn{mfs} (@samp{type:=mfs}) filesystem is available in 4.4BSD,
+Linux, and other systems. It creates a filesystem in a portion of the
+system's memory, thus providing very fast file (volatile) access.
+
+XXX: THIS FILESYSTEM IS NOT IMPLEMENTED YET!
+
+@c ----------------------------------------------------------------
+@node Null Filesystem, Floppy Filesystem, Memory/RAM Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Null Filesystem (@samp{nullfs})
+@cindex Null Filesystem
+@cindex nullfs, filesystem type
+@cindex Filesystem type; nullfs
+
+The @dfn{nullfs} (@samp{type:=nullfs}) filesystem is available from 4.4BSD,
+and is very similar to the loopback filesystem, @dfn{lofs}.
+
+XXX: THIS FILESYSTEM IS NOT IMPLEMENTED YET!
+
+@c ----------------------------------------------------------------
+@node Floppy Filesystem, Translucent Filesystem, Null Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Floppy Filesystem (@samp{pcfs})
+@cindex Floppy Filesystem
+@cindex pcfs, filesystem type
+@cindex Filesystem type; pcfs
+
+The @dfn{pcfs} (@samp{type:=pcfs}) filesystem mounts a floppy previously
+formatted for the MS-DOS format.
+
+@noindent
+The following option must be specified:
+
+@table @code
+@cindex dev, mount option
+@cindex Mount option; dev
+@item dev
+the block special device to be mounted.
+@end table
+
+A pcfs entry might be:
+
+@example
+pcfs os==sunos4;type:=pcfs;dev:=/dev/fd0 \
+ os==sunos5;type:=pcfs;dev:=/dev/diskette
+@end example
+
+@c ----------------------------------------------------------------
+@node Translucent Filesystem, Shared Memory+Swap Filesystem, Floppy Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Translucent Filesystem (@samp{tfs})
+@cindex Translucent Filesystem
+@cindex tfs, filesystem type
+@cindex Filesystem type; tfs
+
+The @dfn{tfs} (@samp{type:=tfs}) filesystem is an older version of the
+4.4BSD @dfn{unionfs}.
+
+XXX: THIS FILESYSTEM IS NOT IMPLEMENTED YET!
+
+@c ----------------------------------------------------------------
+@node Shared Memory+Swap Filesystem, User ID Mapping Filesystem, Translucent Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Shared Memory+Swap Filesystem (@samp{tmpfs})
+@cindex Shared Memory and Swap Filesystem
+@cindex tmpfs, filesystem type
+@cindex Filesystem type; tmpfs
+
+The @dfn{tmpfs} (@samp{type:=tmpfs}) filesystem shares memory between a
+the swap device and the rest of the system. It is generally used to
+provide a fast access @file{/tmp} directory, one that uses memory that
+is otherwise unused. This filesystem is available in SunOS 4.x and 5.x.
+
+XXX: THIS FILESYSTEM IS NOT IMPLEMENTED YET!
+
+@c ----------------------------------------------------------------
+@node User ID Mapping Filesystem, Program Filesystem, Shared Memory+Swap Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section User ID Mapping Filesystem (@samp{umapfs})
+@cindex User ID Mapping Filesystem
+@cindex umapfs, filesystem type
+@cindex Filesystem type; umapfs
+
+The @dfn{umapfs} (@samp{type:=umapfs}) filesystem maps User IDs of file
+ownership, and is available from 4.4BSD.
+
+XXX: THIS FILESYSTEM IS NOT IMPLEMENTED YET!
+
+@c ----------------------------------------------------------------
+@node Program Filesystem, Symbolic Link Filesystem, User ID Mapping Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Program Filesystem (@samp{program})
+@cindex Program filesystem
+@cindex Mount a filesystem under program control
+@cindex program, filesystem type
+@cindex Filesystem type; program
+
+The @dfn{program} (@samp{type:=program}) filesystem type allows a
+program to be run whenever a mount or unmount is required. This allows
+easy addition of support for other filesystem types, such as MIT's
+Remote Virtual Disk (RVD) which has a programmatic interface via the
+commands @samp{rvdmount} and @samp{rvdunmount}.
+
+@noindent
+Both of the following options must be specified:
+
+@table @code
+@cindex mount, mount option
+@cindex Mount option; mount
+@item mount
+the program which will perform the mount.
+
+@cindex unmount, mount option
+@cindex umount, mount option
+@cindex Mount option; unmount
+@cindex Mount option; umount
+@item unmount
+@item umount
+the program which will perform the unmount. For convenience, you may
+use either @samp{unmount} or @samp{umount} but not both. If neither
+is defined, @i{Amd} will default to @samp{umount $@{fs@}} (the actual
+unmount program pathname will be automatically determined at the time
+GNU @code{configure} runs.)
+@end table
+
+The exit code from these two programs is interpreted as a Unix error
+code. As usual, exit code zero indicates success. To execute the
+program, @i{Amd} splits the string on whitespace to create an array of
+substrings. Single quotes @samp{'} can be used to quote whitespace
+if that is required in an argument. There is no way to escape or change
+the single quote character.
+
+To run e.g. the program @samp{rvdmount} with a host name and filesystem as
+arguments, it would be specified by
+@samp{fs:=$@{autodir@}$@{path@};type:=program;mount:="/etc/rvdmount
+rvdmount fserver $@{fs@}";unmount:="/etc/rdvumount rvdumount $@{fs@}"}.
+
+The first element in the array is taken as the pathname of the program
+to execute. The other members of the array form the argument vector
+to be passed to the program, @dfn{including argument zero}. The array
+is exactly the same as the array passed to the execv() system call
+(man execv for details). The split string must have at least two
+elements. The programs are directly executed by @i{Amd}, not via a
+shell. Therefore, if a script is to be used as a mount/umount
+program, it @dfn{must} begin with a @code{#!} interpreter specification.
+
+Often, this program mount type is used for Samba mounts, where you
+need a double slash in pathnames. However, @i{Amd} normalizes
+sequences of slashes into one slash. Therefore, you must use an
+escaped slash, preceded by an escaped backslash. So to get a double
+slash in the mount command, you need the eight character sequence
+@samp{\\\/\\\/} in your map. For example:
+
+@samp{mount="/sbin/mount mount -r -t smbfs -o-N,-Ihostname \\\/\\\/guest@@venus/mp3"}
+
+If a filesystem type is to be heavily used, it may be worthwhile adding
+a new filesystem type into @i{Amd}, but for most uses the program
+filesystem should suffice.
+
+When the program is run, standard input and standard error are inherited
+from the current values used by @i{Amd}. Standard output is a
+duplicate of standard error. The value specified with the @code{-l}
+command line option has no effect on standard error.
+
+@i{Amd} guarantees that the mountpoint will be created before calling
+the mount program, and that it will be removed after the umount
+program returns success.
+
+@c ----------------------------------------------------------------
+@node Symbolic Link Filesystem, Symbolic Link Filesystem II, Program Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Symbolic Link Filesystem (@samp{link})
+@cindex Symbolic link filesystem
+@cindex Referencing part of the local name space
+@cindex Mounting part of the local name space
+@cindex How to reference part of the local name space
+@cindex link, filesystem type
+@cindex symlink, link filesystem type
+@cindex Filesystem type; link
+
+Each filesystem type creates a symbolic link to point from the volume
+name to the physical mount point. The @samp{link} filesystem does the
+same without any other side effects. This allows any part of the
+machines name space to be accessed via @i{Amd}.
+
+One common use for the symlink filesystem is @file{/homes} which can be
+made to contain an entry for each user which points to their
+(auto-mounted) home directory. Although this may seem rather expensive,
+it provides a great deal of administrative flexibility.
+
+@noindent
+The following option must be defined:
+
+@table @code
+@item fs
+The value of @var{fs} option specifies the destination of the link, as
+modified by the @var{sublink} option. If @var{sublink} is non-null, it
+is appended to @code{$@{fs@}}@code{/} and the resulting string is used
+as the target.
+@end table
+
+The @samp{link} filesystem can be thought of as identical to the
+@samp{ufs} filesystem but without actually mounting anything.
+
+An example entry might be:
+
+@example
+jsp host==charm;type:=link;fs:=/home/charm;sublink:=jsp
+@end example
+which would return a symbolic link pointing to @file{/home/charm/jsp}.
+
+@c ----------------------------------------------------------------
+@node Symbolic Link Filesystem II, NFS-Link Filesystem, Symbolic Link Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Symbolic Link Filesystem II (@samp{linkx})
+@cindex Symbolic link filesystem II
+@cindex Referencing an existing part of the local name space
+@cindex Mounting an existing part of the local name space
+@cindex How to reference an existing part of the local name space
+@cindex linkx, filesystem type
+@cindex symlink, linkx filesystem type
+@cindex Filesystem type; linkx
+
+The @dfn{linkx} (@samp{type:=linkx}) filesystem type is identical to @samp{link} with the
+exception that the target of the link must exist. Existence is checked
+with the @b{lstat}(2) system call.
+
+The @samp{linkx} filesystem type is particularly useful for wildcard map
+entries. In this case, a list of possible targets can be given and
+@i{Amd} will choose the first one which exists on the local machine.
+
+@c ----------------------------------------------------------------
+@node NFS-Link Filesystem, Automount Filesystem, Symbolic Link Filesystem II, Filesystem Types
+@comment node-name, next, previous, up
+@section NFS-Link Filesystem (@samp{nfsl})
+@cindex NFS-Link filesystem II
+@cindex Referencing an existing part of the name space if target exists
+@cindex Mounting a remote part of the name space if target is missing
+@cindex Symlink if target exists, NFS otherwise
+@cindex nfsl, filesystem type
+@cindex symlink, nfsl filesystem type
+@cindex Filesystem type; nfsl
+
+The @dfn{nfsl} (@samp{type:=nfsl}) filesystem type is a combination of two others:
+@samp{link} and @samp{nfs}. If the local host name is equal to the
+value of @code{$@{rhost@}} @emph{and} the target pathname listed in
+@code{$@{fs@}} exists, @samp{nfsl} will behave exactly as
+@samp{type:=link}, and refer to the target as a symbolic link. If the
+local host name is not equal to the value of @code{$@{rhost@}}, or if
+the target of the link does not exist, @i{Amd} will treat it as
+@samp{type:=nfs}, and will mount a remote pathname for it.
+
+The @samp{nfsl} filesystem type is particularly useful as a shorthand
+for the more cumbersome and yet one of the most popular @i{Amd}
+entries. For example, you can simplify all map entries that look like:
+
+@example
+zing -fs:=/n/shekel/u/zing \
+ host!=shekel;type:=nfs;rhost:=shekel;rfs:=$@{fs@} \
+ host==shekel;type:=link
+@end example
+
+or
+
+@example
+zing -fs:=/n/shekel/u/zing \
+ exists($@{fs@});type:=link \
+ !exists($@{fs@});type:=nfs;rhost:=shekel;rfs:=$@{fs@}
+@end example
+
+into a shorter form
+
+@example
+zing type:=nfsl;fs:=/n/shekel/u/zing;rhost:=shekel;rfs:=$@{fs@}
+@end example
+
+Not just does it make the maps smaller and simpler, but it avoids
+possible mistakes that often happen when forgetting to set up the two
+entries (one for @samp{type:=nfs} and the other for @samp{type:=link})
+necessary to perform transparent mounts of existing or remote mounts.
+
+@c ----------------------------------------------------------------
+@node Automount Filesystem, Direct Automount Filesystem, NFS-Link Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Automount Filesystem (@samp{auto})
+@cindex Automount filesystem
+@cindex Map cache types
+@cindex Setting map cache parameters
+@cindex How to set map cache parameters
+@cindex How to start an indirect automount point
+@cindex auto, filesystem type
+@cindex Filesystem type; auto
+@cindex SIGHUP signal
+@cindex Map cache synchronizing
+@cindex Synchronizing the map cache
+@cindex Map cache options
+@cindex Regular expressions in maps
+
+The @dfn{auto} (@samp{type:=auto}) filesystem type creates a new automount point below an
+existing automount point. Top-level automount points appear as system
+mount points. An automount mount point can also appear as a
+sub-directory of an existing automount point. This allows some
+additional structure to be added, for example to mimic the mount tree of
+another machine.
+
+The following options may be specified:
+
+@table @code
+@cindex cache, mount map option
+@cindex Mount map option; cache
+@item cache
+specifies whether the data in this mount-map should be
+cached. The default value is @samp{none}, in which case
+no caching is done in order to conserve memory.
+
+However, better performance and reliability can be obtained by caching
+some or all of a mount-map.
+
+If the cache option specifies @samp{all},
+the entire map is enumerated when the mount point is created.
+
+If the cache option specifies @samp{inc}, caching is done incrementally
+as and when data is required.
+Some map types do not support cache mode @samp{all}, in which case @samp{inc}
+is used whenever @samp{all} is requested.
+
+Caching can be entirely disabled by using cache mode @samp{none}.
+
+If the cache option specifies @samp{regexp} then the entire map will be
+enumerated and each key will be treated as an egrep-style regular
+expression. The order in which a cached map is searched does not
+correspond to the ordering in the source map so the regular expressions
+should be mutually exclusive to avoid confusion.
+
+Each mount map type has a default cache type, usually @samp{inc}, which
+can be selected by specifying @samp{mapdefault}.
+
+The cache mode for a mount map can only be selected on the command line.
+Starting @i{Amd} with the command:
+
+@example
+amd /homes hesiod.homes -cache:=inc
+@end example
+
+will cause @samp{/homes} to be automounted using the @dfn{Hesiod} name
+server with local incremental caching of all successfully resolved names.
+
+All cached data is forgotten whenever @i{Amd} receives a @samp{SIGHUP}
+signal and, if cache @samp{all} mode was selected, the cache will be
+reloaded. This can be used to inform @i{Amd} that a map has been
+updated. In addition, whenever a cache lookup fails and @i{Amd} needs
+to examine a map, the map's modify time is examined. If the cache is
+out of date with respect to the map then it is flushed as if a
+@samp{SIGHUP} had been received.
+
+An additional option (@samp{sync}) may be specified to force @i{Amd} to
+check the map's modify time whenever a cached entry is being used. For
+example, an incremental, synchronized cache would be created by the
+following command:
+
+@example
+amd /homes hesiod.homes -cache:=inc,sync
+@end example
+
+@item fs
+specifies the name of the mount map to use for the new mount point.
+
+Arguably this should have been specified with the @code{$@{rfs@}} option but
+we are now stuck with it due to historical accident.
+
+@c %If the string @samp{.} is used then the same map is used;
+@c %in addition the lookup prefix is set to the name of the mount point followed
+@c %by a slash @samp{/}.
+@c %This is the same as specifying @samp{fs:=\$@{map@};pref:=\$@{key@}/}.
+@c
+
+@item pref
+alters the name that is looked up in the mount map. If
+@code{$@{pref@}}, the @dfn{prefix}, is non-null then it is prepended
+to the name requested by the kernel @dfn{before} the map is
+searched. The default prefix is the prefix of the parent map (if any)
+with name of the auto node appended to it. That means if you want no
+prefix you must say so in the map: @samp{pref:=null}.
+
+@item opts
+Normally, @samp{auto} style maps are not browsable even if you turn on
+directory browsability (@pxref{browsable_dirs Parameter}). To enable
+browsing entries in @samp{auto} maps, specify @samp{opts:=browsable}
+or @samp{opts:=fullybrowsable} in
+the description of this map.
+
+@end table
+
+The server @samp{dylan.doc.ic.ac.uk} has two user disks:
+@samp{/dev/dsk/2s0} and @samp{/dev/dsk/5s0}. These are accessed as
+@samp{/home/dylan/dk2} and @samp{/home/dylan/dk5} respectively. Since
+@samp{/home} is already an automount point, this naming is achieved with
+the following map entries:@refill
+
+@example
+dylan type:=auto;fs:=$@{map@};pref:=$@{key@}/
+dylan/dk2 type:=ufs;dev:=/dev/dsk/2s0
+dylan/dk5 type:=ufs;dev:=/dev/dsk/5s0
+@end example
+
+@c ----------------------------------------------------------------
+@node Direct Automount Filesystem, Union Filesystem, Automount Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Direct Automount Filesystem (@samp{direct})
+@cindex Direct automount filesystem
+@cindex How to start a direct automount point
+@cindex direct, filesystem type
+@cindex Filesystem type; direct
+
+The @dfn{direct} (@samp{type:=direct}) filesystem is almost identical to
+the automount filesystem. Instead of appearing to be a directory of
+mount points, it appears as a symbolic link to a mounted filesystem.
+The mount is done at the time the link is accessed. @xref{Automount
+Filesystem}, for a list of required options.
+
+Direct automount points are created by specifying the @samp{direct}
+filesystem type on the command line:
+
+@example
+amd ... /usr/man auto.direct -type:=direct
+@end example
+
+where @samp{auto.direct} would contain an entry such as:
+
+@example
+usr/man -type:=nfs;rfs:=/usr/man \
+ rhost:=man-server1 rhost:=man-server2
+@end example
+
+In this example, @samp{man-server1} and @samp{man-server2} are file
+servers which export copies of the manual pages. Note that the key
+which is looked up is the name of the automount point without the
+leading @samp{/}.
+
+Note that the implementation of the traditional @dfn{direct} filesystem is
+essentially a hack (pretending that the root of an NFS filesystem is a
+symlink) and many modern operating systems get very unhappy about
+it. For example, Linux kernel 2.4+ completely disallows it, and Solaris
+2.8 fails to unmount it when @i{Amd} shuts down. Therefore, the use of
+the traditional @dfn{direct} filesystem is strongly discouraged; it is
+only semi-supported, at best.
+
+The autofs implementations that permit direct mounts are fully
+supported, however. That currently includes all versions of
+Solaris. Linux autofs does NOT support direct mounts at all.
+
+@c ----------------------------------------------------------------
+@node Union Filesystem, Error Filesystem, Direct Automount Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Union Filesystem (@samp{union})
+@cindex Union filesystem
+@cindex union, filesystem type
+@cindex Filesystem type; union
+
+The @dfn{union} (@samp{type:=union}) filesystem type allows the contents of several
+directories to be merged and made visible in a single directory. This
+can be used to overcome one of the major limitations of the Unix mount
+mechanism which only allows complete directories to be mounted.
+
+For example, supposing @file{/tmp} and @file{/var/tmp} were to be merged
+into a new directory called @file{/mtmp}, with files in @file{/var/tmp}
+taking precedence. The following command could be used to achieve this
+effect:
+
+@example
+amd ... /mtmp union:/tmp:/var/tmp -type:=union
+@end example
+
+Currently, the unioned directories must @emph{not} be automounted. That
+would cause a deadlock. This seriously limits the current usefulness of
+this filesystem type and the problem will be addressed in a future
+release of @i{Amd}.
+
+Files created in the union directory are actually created in the last
+named directory. This is done by creating a wildcard entry which points
+to the correct directory. The wildcard entry is visible if the union
+directory is listed, so allowing you to see which directory has
+priority.
+
+The files visible in the union directory are computed at the time
+@i{Amd} is started, and are not kept up-to-date with respect to the
+underlying directories. Similarly, if a link is removed, for example
+with the @samp{rm} command, it will be lost forever.
+
+@c ----------------------------------------------------------------
+@node Error Filesystem, Top-level Filesystem, Union Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Error Filesystem (@samp{error})
+@cindex Error filesystem
+@cindex error, filesystem type
+@cindex Filesystem type; error
+
+The @dfn{error} (@samp{type:=error}) filesystem type is used internally as a catch-all in the
+case where none of the other filesystems was selected, or some other
+error occurred. Lookups and mounts always fail with ``No such file or
+directory''. All other operations trivially succeed.
+
+The error filesystem is not directly accessible.
+
+@c ----------------------------------------------------------------
+@node Top-level Filesystem, Root Filesystem, Error Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Top-level Filesystem (@samp{toplvl})
+@cindex Top level filesystem
+@cindex toplvl, filesystem type
+@cindex Filesystem type; toplvl
+
+The @dfn{toplvl} (@samp{type:=toplvl}) filesystems is derived from the @samp{auto} filesystem
+and is used to mount the top-level automount nodes. Requests of this
+type are automatically generated from the command line arguments.
+
+@c ----------------------------------------------------------------
+@node Root Filesystem, Inheritance Filesystem, Top-level Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Root Filesystem (@samp{root})
+@cindex Root filesystem
+@cindex root, filesystem type
+@cindex Filesystem type; root
+
+The @dfn{root} (@samp{type:=root}) filesystem type acts as an internal
+placeholder onto which @i{Amd} can pin @samp{toplvl} mounts. Only one
+node of this type need ever exist and one is created automatically
+during startup. The effect of having more than one root node is
+undefined.
+
+The root filesystem is not directly accessible.
+
+@c ----------------------------------------------------------------
+@node Inheritance Filesystem, , Root Filesystem, Filesystem Types
+@comment node-name, next, previous, up
+@section Inheritance Filesystem (@samp{inherit})
+@cindex Inheritance filesystem
+@cindex Nodes generated on a restart
+@cindex inherit, filesystem type
+@cindex Filesystem type; inherit
+
+The @dfn{inheritance} (@samp{type:=inherit}) filesystem is not directly
+accessible. Instead, internal mount nodes of this type are
+automatically generated when @i{Amd} is started with the @code{-r} option.
+At this time the system mount table is scanned to locate any filesystems
+which are already mounted. If any reference to these filesystems is
+made through @i{Amd} then instead of attempting to mount it, @i{Amd}
+simulates the mount and @dfn{inherits} the filesystem. This allows a
+new version of @i{Amd} to be installed on a live system simply by
+killing the old daemon with @samp{SIGTERM} and starting the new one.@refill
+
+This filesystem type is not generally visible externally, but it is
+possible that the output from @samp{amq -m} may list @samp{inherit} as
+the filesystem type. This happens when an inherit operation cannot
+be completed for some reason, usually because a fileserver is down.
+
+@c ################################################################
+@node Amd Configuration File, Run-time Administration, Filesystem Types, Top
+@comment node-name, next, previous, up
+@chapter Amd Configuration File
+@cindex Amd Configuration File
+@cindex amd.conf
+
+The @samp{amd.conf} file is the configuration file for @i{Amd}, as part
+of the am-utils suite. This file contains runtime configuration
+information for the @i{Amd} automounter program.
+
+@menu
+* File Format::
+* The Global Section::
+* Regular Map Sections::
+* Common Parameters::
+* Global Parameters::
+* Regular Map Parameters::
+* amd.conf Examples::
+@end menu
+
+@c ================================================================
+@node File Format, The Global Section, Amd Configuration File, Amd Configuration File
+@comment node-name, next, previous, up
+@section File Format
+@cindex amd.conf file format
+
+The @samp{amd.conf} file consists of sections and parameters. A section
+begins with the name of the section in square brackets @samp{[]} and
+continues until the next section begins or the end of the file is reached.
+Sections contain parameters of the form @samp{name = value}.
+
+The file is line-based --- that is, each newline-terminated line
+represents either a comment, a section name or a parameter. No
+line-continuation syntax is available.
+
+Section names, parameter names and their values are case sensitive.
+
+Only the first equals sign in a parameter is significant. Whitespace
+before or after the first equals sign is discarded. Leading, trailing
+and internal whitespace in section and parameter names is irrelevant.
+Leading and trailing whitespace in a parameter value is discarded.
+Internal whitespace within a parameter value is not allowed, unless the
+whole parameter value is quoted with double quotes as in @samp{name =
+"some value"}.
+
+Any line beginning with a pound sign @samp{#} is ignored, as are lines
+containing only whitespace.
+
+The values following the equals sign in parameters are all either a
+string (no quotes needed if string does not include spaces) or a
+boolean, which may be given as @samp{yes}/@samp{no}. Case is significant in all
+values. Some items such as cache timeouts are numeric.
+
+@c ================================================================
+@node The Global Section, Regular Map Sections, File Format, Amd Configuration File
+@comment node-name, next, previous, up
+@section The Global Section
+@cindex amd.conf global section
+
+The global section must be specified as @samp{[global]}. Parameters in
+this section either apply to @i{Amd} as a whole, or to all other regular map
+sections which follow. There should be only one global section defined
+in one configuration file.
+
+It is highly recommended that this section be specified first in the
+configuration file. If it is not, then regular map sections which
+precede it will not use global values defined later.
+
+@c ================================================================
+@node Regular Map Sections, Common Parameters, The Global Section, Amd Configuration File
+@comment node-name, next, previous, up
+@section Regular Map Sections
+@cindex amd.conf regular map sections
+
+Parameters in regular (non-global) sections apply to a single map entry.
+For example, if the map section @samp{[/homes]} is defined, then all
+parameters following it will be applied to the @file{/homes}
+@i{Amd}-managed mount point.
+
+@c ================================================================
+@node Common Parameters, Global Parameters, Regular Map Sections, Amd Configuration File
+@comment node-name, next, previous, up
+@section Common Parameters
+@cindex amd.conf common parameters
+
+These parameters can be specified either in the global or a map-specific
+section. Entries specified in a map-specific section override the default
+value or one defined in the global section. If such a common parameter is
+specified only in the global section, it is applicable to all regular map
+sections that follow.
+
+@menu
+* autofs_use_lofs Parameter::
+* browsable_dirs Parameter::
+* map_defaults Parameter::
+* map_options Parameter::
+* map_type Parameter::
+* mount_type Parameter::
+* search_path Parameter::
+* selectors_in_defaults Parameter::
+@end menu
+
+@c ----------------------------------------------------------------
+@node autofs_use_lofs Parameter, browsable_dirs Parameter, Common Parameters, Common Parameters
+@comment node-name, next, previous, up
+@subsection @t{autofs_use_lofs} Parameter
+@cindex autofs_use_lofs Parameter
+
+(type=string, default=@samp{yes}).
+When set to @samp{yes}, @i{Amd}'s autofs code will use lofs-type
+(loopback) mounts for @code{type:=link} mounts, as well as several
+other cases that require local references. This has the advantage
+that @i{Amd} does not use a secondary mount point and users do not see
+external pathnames (the infamous @code{/bin/pwd} problem, where it
+reports a different path than the user chdir'ed into). One of the
+disadvantages of using this option is that the autofs code is
+relatively new and the in-place mounts have not been throughly tested.
+
+If this option is set to @samp{no}, then @i{Amd}'s autofs code will
+use symlinks instead of lofs-type mounts for local references. This
+has the advantage of using simpler (more stable) code, but at the
+expense of negating one of autofs's big advantages: the hiding of
+@i{Amd}'s internal paths. Note that symlinks are not supported in all
+autofs implementations, especially those derived from Solaris Autofs
+v1. Also, on Solaris 2.6 and newer, autofs symlinks are not cached,
+resulting in repeated up-call requests to @i{Amd}.
+
+@c ----------------------------------------------------------------
+@node browsable_dirs Parameter, map_defaults Parameter, autofs_use_lofs Parameter, Common Parameters
+@comment node-name, next, previous, up
+@subsection @t{browsable_dirs} Parameter
+@cindex browsable_dirs Parameter
+
+(type=string, default=@samp{no}). If @samp{yes}, then @i{Amd}'s top-level
+mount points will be browsable to @b{readdir}(3) calls. This means you
+could run for example @b{ls}(1) and see what keys are available to mount
+in that directory. Not all entries are made visible to @b{readdir}(3):
+the @samp{/defaults} entry, wildcard entries, and those with a @file{/}
+in them are not included. If you specify @samp{full} to this option,
+all but the @samp{/defaults} entry will be visible. Note that if you run
+a command which will attempt to @b{stat}(2) the entries, such as often
+done by @samp{ls -l} or @samp{ls -F}, @i{Amd} will attempt to mount
+@i{every} entry in that map. This is often called a ``mount storm''.
+
+Note that mount storms are mostly avoided by using autofs mounts
+(@samp{mount_type = autofs}).
+
+@c ----------------------------------------------------------------
+@node map_defaults Parameter, map_options Parameter, browsable_dirs Parameter, Common Parameters
+@comment node-name, next, previous, up
+@subsection @t{map_defaults} Parameter
+@cindex map_defaults Parameter
+
+(type=string, default to empty). This option sets a string to be used
+as the map's @code{/defaults} entry, overriding any @code{/defaults}
+specified in the map. This allows local users to override a given
+map's defaults without modifying maps globally (which is impossible in
+sites where the maps are managed by a different administrative group).
+
+@c ----------------------------------------------------------------
+@node map_options Parameter, map_type Parameter, map_defaults Parameter, Common Parameters
+@comment node-name, next, previous, up
+@subsection @t{map_options} Parameter
+@cindex map_options Parameter
+
+(type=string, default no options). This option is the same as
+specifying map options on the command line to @i{Amd}, such as
+@samp{cache:=all}.
+
+@c ----------------------------------------------------------------
+@node map_type Parameter, mount_type Parameter, map_options Parameter, Common Parameters
+@comment node-name, next, previous, up
+@subsection @t{map_type} Parameter
+@cindex map_type Parameter
+
+(type=string, default search all map types). If specified, @i{Amd} will
+initialize the map only for the type given. This is useful to avoid the
+default map search type used by @i{Amd} which takes longer and can have
+undesired side-effects such as initializing NIS even if not used.
+Possible values are
+
+@table @samp
+@item file
+plain files
+@item hesiod
+Hesiod name service from MIT
+@item ldap
+Lightweight Directory Access Protocol
+@item ndbm
+(New) dbm style hash files
+@item nis
+Network Information Services (version 2)
+@item nisplus
+Network Information Services Plus (version 3)
+@item passwd
+local password files
+@item union
+union maps
+@end table
+
+@c ----------------------------------------------------------------
+@node mount_type Parameter, search_path Parameter, map_type Parameter, Common Parameters
+@comment node-name, next, previous, up
+@subsection @t{mount_type} Parameter
+@cindex mount_type Parameter
+
+(type=string, default=@samp{nfs}). All @i{Amd} mount types default to NFS.
+That is, @i{Amd} is an NFS server on the map mount points, for the local
+host it is running on. If @samp{autofs} is specified, @i{Amd} will be
+an autofs server for those mount points.
+
+@c ----------------------------------------------------------------
+@node search_path Parameter, selectors_in_defaults Parameter, mount_type Parameter, Common Parameters
+@comment node-name, next, previous, up
+@subsection @t{search_path} Parameter
+@cindex search_path Parameter
+
+(type=string, default no search path). This provides a
+(colon-delimited) search path for file maps. Using a search path,
+sites can allow for local map customizations and overrides, and can
+distributed maps in several locations as needed.
+
+@c ----------------------------------------------------------------
+@node selectors_in_defaults Parameter, , search_path Parameter, Common Parameters
+@comment node-name, next, previous, up
+@subsection @t{selectors_in_defaults} Parameter
+@cindex selectors_in_defaults Parameter
+
+(type=boolean, default=@samp{no}). If @samp{yes}, then the
+@samp{/defaults} entry of maps will search for and process any
+selectors before setting defaults for all other keys in that map.
+Useful when you want to set different options for a complete map based
+on some parameters. For example, you may want to better the NFS
+performance over slow slip-based networks as follows:
+
+@example
+/defaults \
+ wire==slip-net;opts:=intr,rsize=1024,wsize=1024 \
+ wire!=slip-net;opts:=intr,rsize=8192,wsize=8192
+@end example
+
+Deprecated form: selectors_on_default.
+
+
+@c ================================================================
+@node Global Parameters, Regular Map Parameters, Common Parameters, Amd Configuration File
+@comment node-name, next, previous, up
+@section Global Parameters
+@cindex amd.conf global parameters
+
+The following parameters are applicable to the @samp{[global]} section only.
+
+@menu
+* arch Parameter::
+* auto_attrcache Parameter::
+* auto_dir Parameter::
+* cache_duration Parameter::
+* cluster Parameter::
+* debug_mtab_file Parameter::
+* debug_options Parameter::
+* dismount_interval Parameter::
+* domain_strip Parameter::
+* exec_map_timeout Parameter::
+* forced_unmounts Parameter::
+* full_os Parameter::
+* fully_qualified_hosts Parameter::
+* hesiod_base Parameter::
+* karch Parameter::
+* ldap_base Parameter::
+* ldap_cache_maxmem Parameter::
+* ldap_cache_seconds Parameter::
+* ldap_hostports Parameter::
+* ldap_proto_version Parameter::
+* local_domain Parameter::
+* localhost_address Parameter::
+* log_file Parameter::
+* log_options Parameter::
+* map_reload_interval Parameter::
+* nfs_allow_any_interface Parameter::
+* nfs_allow_insecure_port Parameter::
+* nfs_proto Parameter::
+* nfs_retransmit_counter Parameter::
+* nfs_retransmit_counter_udp Parameter::
+* nfs_retransmit_counter_tcp Parameter::
+* nfs_retransmit_counter_toplvl Parameter::
+* nfs_retry_interval Parameter::
+* nfs_retry_interval_udp Parameter::
+* nfs_retry_interval_tcp Parameter::
+* nfs_retry_interval_toplvl Parameter::
+* nfs_vers Parameter::
+* nis_domain Parameter::
+* normalize_hostnames Parameter::
+* normalize_slashes Parameter::
+* os Parameter::
+* osver Parameter::
+* pid_file Parameter::
+* plock Parameter::
+* portmap_program Parameter::
+* preferred_amq_port Parameter::
+* print_pid Parameter::
+* print_version Parameter::
+* restart_mounts Parameter::
+* show_statfs_entries Parameter::
+* truncate_log Parameter::
+* unmount_on_exit Parameter::
+* use_tcpwrappers Parameter::
+* vendor Parameter::
+@end menu
+
+@c ----------------------------------------------------------------
+@node arch Parameter, auto_attrcache Parameter, Global Parameters, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{arch} Parameter
+@cindex arch Parameter
+
+(type=string, default to compiled in value). Same as the @code{-A}
+option to @i{Amd}. Allows you to override the value of the @i{arch}
+@i{Amd} variable.
+
+@c ----------------------------------------------------------------
+@node auto_attrcache Parameter, auto_dir Parameter, arch Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{auto_attrcache} Parameter
+@cindex auto_attrcache Parameter
+
+(type=numeric, default=0). Specify in seconds (or units of 0.1
+seconds, depending on the OS), what is the (kernel-side) NFS attribute
+cache timeout for @i{Amd}'s own automount points. A value of 0 is
+supposed to turn off attribute caching, meaning that @i{Amd} will be
+consulted via a kernel-RPC each time someone stat()'s the mount point
+(which could be abused as a denial-of-service attack).
+
+@emph{WARNING}: @i{Amd} depends on being able to turn off the NFS
+attribute cache of the client OS. If it cannot be turned off, then
+users may get ESTALE errors or symlinks that point to the wrong
+places. This is more likely under heavy use of @i{Amd}, for example
+if your system is experiencing frequent map changes or frequent
+mounts/unmounts. Therefore, under normal circumstances, this
+parameter should remain set to 0, to ensure that the attribute cache
+is indeed off.
+
+Unfortunately, some kernels (e.g., certain BSDs) don't have a way to
+turn off the NFS attribute cache. Setting this parameter to 0 is
+supposed to turn off attribute caching entirely, but unfortunately it
+does not; instead, the attribute cache is set to some internal
+hard-coded default (usually anywhere from 5-30 seconds). If you
+suspect that your OS doesn't have a reliable way of turning off the
+attribute cache, then it is better to set this parameter to the
+smallest possible non-zero value (set @samp{auto_attrcache=1} in your
+@code{amd.conf}). This will not eliminate the problem, but reduce the
+risk window somewhat. The best solutions are (1) to use @i{Amd} in
+Autofs mode, if it's supported in your OS, and (2) talk to your OS
+vendor to support a true @samp{noac} flag. See the
+@uref{http://www.am-utils.org/docs/am-utils/attrcache.txt,README.attrcache}
+document for more details.
+
+If you are able to turn off the attribute cache on your OS, alas,
+@i{Amd}'s performance may degrade (when not using Autofs) because
+every traversal of an automounter-controlled pathname will result in a
+lookup request from the kernel to @i{Amd}. Under heavy loads, for
+example when using recursive tools like @samp{find}, @samp{rdist}, or
+@samp{rsync}, this performance degradation can be noticeable. There
+are two possible solutions that some administrators have chosen to
+improve performance:
+
+@enumerate
+
+@item
+First, you can turn off unmounting using the @samp{nounmount} mount
+option. This will ensure that no @i{Amd} symlink could ever change,
+thereby the kernel's attribute cache and @i{Amd} will always be in
+sync. However, this method will cause the number of mounts to keep
+growing, even if some are no longer in use; this has the disadvantage
+that your system could be more susceptible to hangs if even one of
+those accumulating mounts hangs due to a downed server.
+
+@item
+Second, you can turn on attribute caching carefully by setting a small
+automounter attribute cache value (say, one second), and a relatively
+large dismount interval (say, one hour). (@xref{dismount_interval
+Parameter}.) For example, you can set this in your @code{amd.conf}:
+
+@example
+[global]
+auto_attrcache = 1
+dismount_interval = 3600
+@end example
+
+This has the benefit of using the kernel's attribute cache and thus
+improving performance. The disadvantage with this option is that the
+window of vulnerability is not eliminated entirely: it is only made
+smaller.
+
+@end enumerate
+
+@c ----------------------------------------------------------------
+@node auto_dir Parameter, cache_duration Parameter, auto_attrcache Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{auto_dir} Parameter
+@cindex auto_dir Parameter
+
+(type=string, default=@samp{/a}). Same as the @code{-a} option to @i{Amd}.
+This sets the private directory where @i{Amd} will create
+sub-directories for its real mount points.
+
+@c ----------------------------------------------------------------
+@node cache_duration Parameter, cluster Parameter, auto_dir Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{cache_duration} Parameter
+@cindex cache_duration Parameter
+
+(type=numeric, default=300). Same as the @code{-c} option to @i{Amd}.
+Sets the duration in seconds that looked-up or mounted map entries
+remain in the cache.
+
+@c ----------------------------------------------------------------
+@node cluster Parameter, debug_mtab_file Parameter, cache_duration Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{cluster} Parameter
+@cindex cluster Parameter
+
+(type=string, default no cluster). Same as the @code{-C} option to
+@i{Amd}. Specifies the alternate HP-UX cluster to use.
+
+@c ----------------------------------------------------------------
+@node debug_mtab_file Parameter, debug_options Parameter, cluster Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{debug_mtab_file} Parameter
+@cindex debug_mtab_file Parameter
+
+(type=string, default="/tmp/mnttab"). Path to mtab file that is used
+by @i{Amd} to store a list of mounted file systems during debug-mtab mode.
+This option only applies to systems that store mtab information on disk.
+
+@c ----------------------------------------------------------------
+@node debug_options Parameter, dismount_interval Parameter, debug_mtab_file Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{debug_options} Parameter
+@cindex debug_options Parameter
+
+(type=string, default no debug options). Same as the @code{-D} option
+to @i{Amd}. Specify any debugging options for @i{Amd}. Works only if
+am-utils was configured for debugging using the @code{--enable-debug}
+option. The additional @samp{mem} option can be turned on via
+@code{--enable-debug=mem}. Otherwise debugging options are ignored.
+Options are comma delimited, and can be preceded by the string
+@samp{no} to negate their meaning. You can get the list of supported
+debugging and logging options by running @code{amd -H}. Possible
+values those listed for the -D option. @xref{-D Option}.
+
+@c ----------------------------------------------------------------
+@node dismount_interval Parameter, domain_strip Parameter, debug_options Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{dismount_interval} Parameter
+@cindex dismount_interval Parameter
+
+(type=numeric, default=120). Same as the @code{-w} option to
+@i{Amd}. Specify in seconds, the time between attempts to dismount file
+systems that have exceeded their cached times.
+
+@c ----------------------------------------------------------------
+@node domain_strip Parameter, exec_map_timeout Parameter, dismount_interval Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{domain_strip} Parameter
+@cindex domain_strip Parameter
+
+(type=boolean, default=@samp{yes}). If @samp{yes}, then the domain
+name part referred to by @code{$@{rhost@}} is stripped off. This is
+useful to keep logs and smaller. If @samp{no}, then the domain name
+part is left changed. This is useful when using multiple domains with
+the same maps (as you may have hosts whose domain-stripped name is
+identical).
+
+@c ----------------------------------------------------------------
+@node exec_map_timeout Parameter, forced_unmounts Parameter, domain_strip Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{exec_map_timeout} Parameter
+@cindex exec_map_timeout Parameter
+
+(type=numeric, default=10). The timeout in seconds that @i{Amd} will
+wait for an executable map program before an answer is returned from
+that program (or script). This value should be set to as small as
+possible while still allowing normal replies to be returned before the
+timer expires, because during the time that the executable map program
+is queried, @i{Amd} is essentially waiting and is thus not responding
+to any other queries. @xref{Executable maps}.
+
+@c ----------------------------------------------------------------
+@node forced_unmounts Parameter, full_os Parameter, exec_map_timeout Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{forced_unmounts} Parameter
+@cindex forced_unmounts Parameter
+
+(type=boolean, default=@samp{no}).
+Sometimes, mount points are hung due to unrecoverable conditions, such
+as when NFS servers migrate, change their IP address, are down
+permanently, or due to hardware failures, and more. In this case,
+attempting to unmount an existing mount point, or even just to
+@b{stat}(2) it, results in one of three fatal errors: EIO, ESTALE, or
+EBUSY. At that point, @i{Amd} can do little to recover that hung
+point (in fact, the OS cannot automatically recover either). For that
+reason, some OSs support special kinds of forced unmounts, which must
+be used very carefully: they will force an unmount immediately (or
+lazily on Linux), which could result in application data loss.
+However, that may be the only way to recover the entire host (without
+rebooting). Once a hung mount point is forced out, @i{Amd} can then
+re-mount a replacement one (if available), bringing a mostly-hung
+system back to operation and avoiding a potentially costly reboot.
+
+If the @samp{forced_unmounts} option is set to @samp{yes}, and the
+client OS supports forced or lazy unmounts, then @i{Amd} will attempt
+to use them if it gets any of the three serious error conditions
+listed above. Note that @i{Amd} will force the unmount of mount
+points that returned EBUSY only for @samp{type:=toplvl} mounts
+(@pxref{Top-level Filesystem}): that is, @i{Amd}'s own mount points.
+This is useful to recover from a previously hung @i{Amd}, and to
+ensure that an existing @i{Amd} can shutdown cleanly even if some
+processes are keeping its mount points busy (i.e., when a user's shell
+process uses @code{cd} to set its CWD to @i{Amd}'s own mount point).
+
+If this option is set to @samp{no} (the default), then @i{Amd} will
+not attempt this special recovery procedure.
+
+@c ----------------------------------------------------------------
+@node full_os Parameter, fully_qualified_hosts Parameter, forced_unmounts Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{full_os} Parameter
+@cindex full_os Parameter
+
+(type=string, default to compiled in value). The full name of the
+operating system, along with its version. Allows you to override the
+compiled-in full name and version of the operating system. Useful when
+the compiled-in name is not desired. For example, the full operating
+system name on linux comes up as @samp{linux}, but you can override it
+to @samp{linux-2.2.5}.
+
+@c ----------------------------------------------------------------
+@node fully_qualified_hosts Parameter, hesiod_base Parameter, full_os Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{fully_qualified_hosts} Parameter
+@cindex fully_qualified_hosts Parameter
+
+(type=string, default=@samp{no}). If @samp{yes}, @i{Amd} will perform RPC
+authentication using fully-qualified host names. This is necessary for
+some systems, and especially when performing cross-domain mounting. For
+this function to work, the @i{Amd} variable @samp{$@{hostd@}} is used,
+requiring that @samp{$@{domain@}} not be null.
+
+@c ----------------------------------------------------------------
+@node hesiod_base Parameter, karch Parameter, fully_qualified_hosts Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{hesiod_base} Parameter
+@cindex hesiod_base Parameter
+
+(type=string, default=@samp{automount}). Specify the base name for
+hesiod maps.
+
+@c ----------------------------------------------------------------
+@node karch Parameter, ldap_base Parameter, hesiod_base Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{karch} Parameter
+@cindex karch Parameter
+
+(type=string, default to karch of the system). Same as the @code{-k}
+option to @i{Amd}. Allows you to override the kernel-architecture of
+your system. Useful for example on Sun (Sparc) machines, where you can
+build one @i{Amd} binary, and run it on multiple machines, yet you want
+each one to get the correct @i{karch} variable set (for example, sun4c,
+sun4m, sun4u, etc.) Note that if not specified, @i{Amd} will use
+@b{uname}(2) to figure out the kernel architecture of the machine.
+
+@c ----------------------------------------------------------------
+@node ldap_base Parameter, ldap_cache_maxmem Parameter, karch Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{ldap_base} Parameter
+@cindex ldap_base Parameter
+
+(type=string, default not set).
+Specify the base name for LDAP. This often includes LDAP-specific
+values such as country and organization.
+
+@c ----------------------------------------------------------------
+@node ldap_cache_maxmem Parameter, ldap_cache_seconds Parameter, ldap_base Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{ldap_cache_maxmem} Parameter
+@cindex ldap_cache_maxmem Parameter
+
+(type=numeric, default=131072). Specify the maximum memory @i{Amd}
+should use to cache LDAP entries.
+
+@c ----------------------------------------------------------------
+@node ldap_cache_seconds Parameter, ldap_hostports Parameter, ldap_cache_maxmem Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{ldap_cache_seconds} Parameter
+@cindex ldap_cache_seconds Parameter
+
+(type=numeric, default=0). Specify the number of seconds to keep
+entries in the cache.
+
+@c ----------------------------------------------------------------
+@node ldap_hostports Parameter, ldap_proto_version Parameter, ldap_cache_seconds Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{ldap_hostports} Parameter
+@cindex ldap_hostports Parameter
+
+(type=string, default not set).
+Specify the LDAP host and port values.
+
+@c ----------------------------------------------------------------
+@node ldap_proto_version Parameter, local_domain Parameter, ldap_hostports Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{ldap_proto_version} Parameter
+@cindex ldap_proto_version Parameter
+
+(type=numeric, default=2). Specify the LDAP protocol version to use.
+With a value of 3 will use LDAPv3 protocol.
+
+@c ----------------------------------------------------------------
+@node local_domain Parameter, localhost_address Parameter, ldap_proto_version Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{local_domain} Parameter
+@cindex local_domain Parameter
+
+(type=string, default no sub-domain). Same as the @code{-d} option
+to @i{Amd}. Specify the local domain name. If this option is not given
+the domain name is determined from the hostname, by removing the first
+component of the fully-qualified host name.
+
+@c ----------------------------------------------------------------
+@node localhost_address Parameter, log_file Parameter, local_domain Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{localhost_address} Parameter
+@cindex localhost_address Parameter
+
+(type=string, default to localhost or 127.0.0.1). Specify the name or
+IP address for @i{Amd} to use when connecting the sockets for the
+local NFS server and the RPC server. This defaults to 127.0.0.1 or
+whatever the host reports as its local address. This parameter is
+useful on hosts with multiple addresses where you want to force
+@i{Amd} to connect to a specific address.
+
+@c ----------------------------------------------------------------
+@node log_file Parameter, log_options Parameter, localhost_address Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{log_file} Parameter
+@cindex log_file Parameter
+
+(type=string, default=@samp{stderr}). Same as the @code{-l} option to
+@i{Amd}. Specify a file name to log @i{Amd} events to.
+If the string @samp{/dev/stderr} is specified,
+@i{Amd} will send its events to the standard error file descriptor.
+
+If the string @samp{syslog} is given, @i{Amd} will record its events
+with the system logger @b{syslogd}(8). If your system supports syslog
+facilities, then the default facility used is @samp{LOG_DAEMON}.
+
+When using syslog, if you wish to change the facility, append its name
+to the option name, delimited by a single colon. For example, if it is
+the string @samp{syslog:local7} then @i{Amd} will log messages via
+@b{syslog}(3) using the @samp{LOG_LOCAL7} facility. If the facility
+name specified is not recognized, @i{Amd} will default to @samp{LOG_DAEMON}.
+Note: while you can use any syslog facility available on your system, it
+is generally a bad idea to use those reserved for other services such as
+@samp{kern}, @samp{lpr}, @samp{cron}, etc.
+
+@c ----------------------------------------------------------------
+@node log_options Parameter, map_reload_interval Parameter, log_file Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{log_options} Parameter
+@cindex log_options Parameter
+
+(type=string, default no logging options). Same as the @code{-x}
+option to @i{Amd}. Specify any logging options for @i{Amd}. Options
+are comma delimited, and can be preceded by the string @samp{no} to
+negate their meaning. The @samp{debug} logging option is only available
+if am-utils was configured with @code{--enable-debug}. You can get the
+list of supported debugging options by running @code{amd -H}. Possible
+values are:
+
+@table @samp
+@item all
+all messages
+@item debug
+debug messages
+@item error
+non-fatal system errors
+@item fatal
+fatal errors
+@item info
+information
+@item map
+map errors
+@item stats
+additional statistical information
+@item user
+non-fatal user errors
+@item warn
+warnings
+@item warning
+warnings
+@end table
+
+@c ----------------------------------------------------------------
+@node map_reload_interval Parameter, nfs_allow_any_interface Parameter, log_options Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{map_reload_interval} Parameter
+@cindex map_reload_interval Parameter
+
+(type=numeric, default=3600). The number of seconds that @i{Amd} will
+wait before it checks to see if any maps have changed at their source
+(NIS servers, LDAP servers, files, etc.). @i{Amd} will reload only
+those maps that have changed.
+
+@c ----------------------------------------------------------------
+@node nfs_allow_any_interface Parameter, nfs_allow_insecure_port Parameter, map_reload_interval Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_allow_any_interface} Parameter
+@cindex nfs_allow_any_interface Parameter
+
+(type=string, default=@samp{no}). Normally @i{Amd} accepts local NFS
+packets only from 127.0.0.1. If this parameter is set to @samp{yes},
+then @i{amd} will accept local NFS packets from any local interface;
+this is useful on hosts that may have multiple interfaces where the
+system is forced to send all outgoing packets (even those bound to the
+same host) via an address other than 127.0.0.1.
+
+@c ----------------------------------------------------------------
+@node nfs_allow_insecure_port Parameter, nfs_proto Parameter, nfs_allow_any_interface Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_allow_insecure_port} Parameter
+@cindex nfs_allow_insecure_port Parameter
+
+(type=string, default=@samp{no}). Normally @i{Amd} will refuse requests
+coming from unprivileged ports (i.e., ports >= 1024 on Unix systems),
+so that only privileged users and the kernel can send NFS requests to
+it. However, some kernels (certain versions of Darwin, MacOS X, and
+Linux) have bugs that cause them to use unprivileged ports in certain
+situations, which causes @i{Amd} to stop dead in its tracks. This
+parameter allows @i{Amd} to operate normally even on such systems, at the
+expense of a slight decrease in the security of its operations. If
+you see messages like ``ignoring request from foo:1234, port not
+reserved'' in your @i{Amd} log, try enabling this parameter and give it
+another go.
+
+@c ----------------------------------------------------------------
+@node nfs_proto Parameter, nfs_retransmit_counter Parameter, nfs_allow_insecure_port Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_proto} Parameter
+@cindex nfs_proto Parameter
+
+(type=string, default to trying version tcp then udp). By default,
+@i{Amd} tries @code{tcp} and then @code{udp}. This option forces the
+overall NFS protocol used to TCP or UDP. It overrides what is in the
+@i{Amd} maps, and is useful when @i{Amd} is compiled with TCP support
+in NFSv2/NFSv3 that may not be stable. With this option you can turn
+off the complete usage of TCP for NFS dynamically (without having to
+recompile @i{Amd}), and use UDP only, until such time as TCP support
+is desired again.
+
+@c ----------------------------------------------------------------
+@node nfs_retransmit_counter Parameter, nfs_retransmit_counter_udp Parameter, nfs_proto Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_retransmit_counter} Parameter
+@cindex nfs_retransmit_counter Parameter
+
+(type=numeric, default=11). Same as the @i{retransmit} part of the
+@code{-t} @i{timeout.retransmit} option to @i{Amd}. Specifies the
+number of NFS retransmissions that the kernel will use to communicate
+with @i{Amd} using either UDP or TCP mounts. @xref{-t Option}.
+
+@c ----------------------------------------------------------------
+@node nfs_retransmit_counter_udp Parameter, nfs_retransmit_counter_tcp Parameter, nfs_retransmit_counter Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_retransmit_counter_udp} Parameter
+@cindex nfs_retransmit_counter_udp Parameter
+@cindex nfs_retransmit_counter Parameter
+@cindex UDP
+
+(type=numeric, default=11). Same as the @i{nfs_retransmit_counter}
+parameter, but applied globally only to UDP mounts.
+@xref{nfs_retransmit_counter Parameter}.
+
+@c ----------------------------------------------------------------
+@node nfs_retransmit_counter_tcp Parameter, nfs_retransmit_counter_toplvl Parameter, nfs_retransmit_counter_udp Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_retransmit_counter_tcp} Parameter
+@cindex nfs_retransmit_counter_tcp Parameter
+@cindex nfs_retransmit_counter Parameter
+@cindex TCP
+
+(type=numeric, default=11). Same as the @i{nfs_retransmit_counter}
+parameter, but applied globally only to TCP mounts.
+@xref{nfs_retransmit_counter Parameter}.
+
+@c ----------------------------------------------------------------
+@node nfs_retransmit_counter_toplvl Parameter, nfs_retry_interval Parameter, nfs_retransmit_counter_tcp Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_retransmit_counter_toplvl} Parameter
+@cindex nfs_retransmit_counter_toplvl Parameter
+@cindex nfs_retransmit_counter Parameter
+@cindex UDP
+
+(type=numeric, default=11). Same as the @i{nfs_retransmit_counter}
+parameter, applied only for @i{Amd}'s top-level UDP mounts. On some
+systems it is useful to set this differently than the OS default, so
+as to better tune @i{Amd}'s responsiveness under heavy scheduler
+loads. @xref{nfs_retransmit_counter Parameter}.
+
+@c ----------------------------------------------------------------
+@node nfs_retry_interval Parameter, nfs_retry_interval_udp Parameter, nfs_retransmit_counter_toplvl Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_retry_interval} Parameter
+@cindex nfs_retry_interval Parameter
+
+(type=numeric, default=8). Same as the @i{timeout} part of the
+@code{-t} @i{timeout.retransmit} option to @i{Amd}. Specifies the NFS
+timeout interval, in @emph{tenths} of seconds, between NFS/RPC retries
+(for UDP or TCP). This is the value that the kernel will use to
+communicate with @i{Amd}. @xref{-t Option}.
+
+@i{Amd} relies on the kernel RPC retransmit mechanism to trigger mount
+retries. The values of the @i{nfs_retransmit_counter} and the
+@i{nfs_retry_interval} parameters change the overall retry interval.
+Too long an interval gives poor interactive response; too short an
+interval causes excessive retries.
+
+@c ----------------------------------------------------------------
+@node nfs_retry_interval_udp Parameter, nfs_retry_interval_tcp Parameter, nfs_retry_interval Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_retry_interval_udp} Parameter
+@cindex nfs_retry_interval_udp Parameter
+@cindex nfs_retry_interval Parameter
+@cindex UDP
+
+(type=numeric, default=8). Same as the @i{nfs_retry_interval}
+parameter, but applied globally only to UDP mounts.
+@xref{nfs_retry_interval Parameter}.
+
+@c ----------------------------------------------------------------
+@node nfs_retry_interval_tcp Parameter, nfs_retry_interval_toplvl Parameter, nfs_retry_interval_udp Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_retry_interval_tcp} Parameter
+@cindex nfs_retry_interval_tcp Parameter
+@cindex nfs_retry_interval Parameter
+@cindex TCP
+
+(type=numeric, default=8). Same as the @i{nfs_retry_interval}
+parameter, but applied globally only to TCP mounts.
+@xref{nfs_retry_interval Parameter}.
+
+@c ----------------------------------------------------------------
+@node nfs_retry_interval_toplvl Parameter, nfs_vers Parameter, nfs_retry_interval_tcp Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_retry_interval_toplvl} Parameter
+@cindex nfs_retry_interval_toplvl Parameter
+@cindex nfs_retry_interval Parameter
+@cindex UDP
+
+(type=numeric, default=8). Same as the @i{nfs_retry_interval}
+parameter, applied only for @i{Amd}'s top-level UDP mounts. On some
+systems it is useful to set this differently than the OS default, so
+as to better tune @i{Amd}'s responsiveness under heavy scheduler
+loads. @xref{nfs_retry_interval Parameter}.
+
+@c ----------------------------------------------------------------
+@node nfs_vers Parameter, nis_domain Parameter, nfs_retry_interval_toplvl Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nfs_vers} Parameter
+@cindex nfs_vers Parameter
+
+(type=numeric, default to trying version 3 then 2). By default,
+@i{Amd} tries version 3 and then version 2. This option forces the
+overall NFS protocol used to version 3 or 2. It overrides what is in
+the @i{Amd} maps, and is useful when @i{Amd} is compiled with NFSv3
+support that may not be stable. With this option you can turn off the
+complete usage of NFSv3 dynamically (without having to recompile
+@i{Amd}), and use NFSv2 only, until such time as NFSv3 support is
+desired again.
+
+@c ----------------------------------------------------------------
+@node nis_domain Parameter, normalize_hostnames Parameter, nfs_vers Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{nis_domain} Parameter
+@cindex nis_domain Parameter
+
+(type=string, default to local NIS domain name). Same as the
+@code{-y} option to @i{Amd}. Specify an alternative NIS domain from
+which to fetch the NIS maps. The default is the system domain name.
+This option is ignored if NIS support is not available.
+
+@c ----------------------------------------------------------------
+@node normalize_hostnames Parameter, normalize_slashes Parameter, nis_domain Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{normalize_hostnames} Parameter
+@cindex normalize_hostnames Parameter
+
+(type=boolean, default=@samp{no}). Same as the @code{-n} option to @i{Amd}.
+If @samp{yes}, then the name referred to by @code{$@{rhost@}} is normalized
+relative to the host database before being used. The effect is to
+translate aliases into ``official'' names.
+
+@c ----------------------------------------------------------------
+@node normalize_slashes Parameter, os Parameter, normalize_hostnames Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{normalize_slashes} Parameter
+@cindex normalize_slashes Parameter
+
+(type=boolean, default=@samp{yes}). If @samp{yes} then amd will
+condense all multiple @code{/} (slash) characters into one and remove
+all trailing slashes. If @samp{no}, then amd will not touch strings
+that may contain repeated or trailing slashes. The latter is
+sometimes useful with SMB mounts, which often require multiple slash
+characters in pathnames.
+
+@c ----------------------------------------------------------------
+@node os Parameter, osver Parameter, normalize_slashes Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{os} Parameter
+@cindex os Parameter
+
+(type=string, default to compiled in value). Same as the @code{-O}
+option to @i{Amd}. Allows you to override the compiled-in name of the
+operating system. Useful when the built-in name is not desired for
+backward compatibility reasons. For example, if the built-in name is
+@samp{sunos5}, you can override it to @samp{sos5}, and use older maps
+which were written with the latter in mind.
+
+
+@c ----------------------------------------------------------------
+@node osver Parameter, pid_file Parameter, os Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{osver} Parameter
+@cindex osver Parameter
+
+(type=string, default to compiled in value). Same as the @code{-o}
+option to @i{Amd}. Allows you to override the compiled-in version
+number of the operating system. Useful when the built-in version is not
+desired for backward compatibility reasons. For example, if the build
+in version is @samp{2.5.1}, you can override it to @samp{5.5.1}, and use
+older maps that were written with the latter in mind.
+
+@c ----------------------------------------------------------------
+@node pid_file Parameter, plock Parameter, osver Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{pid_file} Parameter
+@cindex pid_file Parameter
+
+(type=string, default=@samp{/dev/stdout}). Specify a file to store the process
+ID of the running daemon into. If not specified, @i{Amd} will print its
+process id onto the standard output. Useful for killing @i{Amd} after
+it had run. Note that the PID of a running @i{Amd} can also be
+retrieved via @i{Amq} (@pxref{Amq -p option}).
+
+This file is used only if the @samp{print_pid} option is on
+(@pxref{print_pid Parameter}).
+
+@c ----------------------------------------------------------------
+@node plock Parameter, portmap_program Parameter, pid_file Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{plock} Parameter
+@cindex plock Parameter
+
+(type=boolean, default=@samp{yes}). Same as the @code{-S} option to @i{Amd}.
+If @samp{yes}, lock the running executable pages of @i{Amd} into memory.
+To improve @i{Amd}'s performance, systems that support the @b{plock}(3)
+or @b{mlockall}(2)
+call can lock the @i{Amd} process into memory. This way there is less
+chance the operating system will schedule, page out, and swap the
+@i{Amd} process as needed. This improves @i{Amd}'s performance, at the
+cost of reserving the memory used by the @i{Amd} process (making it
+unavailable for other processes).
+
+@c ----------------------------------------------------------------
+@node portmap_program Parameter, preferred_amq_port Parameter, plock Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{portmap_program} Parameter
+@cindex portmap_program Parameter
+
+(type=numeric, default=300019). Specify an alternate Port-mapper RPC
+program number, other than the official number. This is useful when
+running multiple @i{Amd} processes. For example, you can run another
+@i{Amd} in ``test'' mode, without affecting the primary @i{Amd} process
+in any way. For safety reasons, the alternate program numbers that can
+be specified must be in the range 300019-300029, inclusive. @i{Amq} has
+an option @code{-P} which can be used to specify an alternate program
+number of an @i{Amd} to contact. In this way, amq can fully control any
+number of @i{Amd} processes running on the same host.
+
+@c ----------------------------------------------------------------
+@node preferred_amq_port Parameter, print_pid Parameter, portmap_program Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{preferred_amq_port} Parameter
+@cindex preferred_amq_port Parameter
+
+(type=numeric, default=0). Specify an alternate Port-mapper RPC port
+number for @i{Amd}'s @i{Amq} service. This is used for both UDP and
+TCP. Setting this value to 0 (or not defining it) will cause @i{Amd}
+to select an arbitrary port number. Setting the @i{Amq} RPC service
+port to a specific number is useful in firewalled or NAT'ed
+environments, where you need to know which port @i{Amd} will listen
+on.
+
+@c ----------------------------------------------------------------
+@node print_pid Parameter, print_version Parameter, preferred_amq_port Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{print_pid} Parameter
+@cindex print_pid Parameter
+
+(type=boolean, default=@samp{no}). Same as the @code{-p} option to @i{Amd}.
+If @samp{yes}, @i{Amd} will print its process ID upon starting.
+
+@c ----------------------------------------------------------------
+@node print_version Parameter, restart_mounts Parameter, print_pid Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{print_version} Parameter
+@cindex print_version Parameter
+
+(type=boolean, default=@samp{no}). Same as the @code{-v} option to @i{Amd},
+but the version prints and @i{Amd} continues to run. If @samp{yes}, @i{Amd}
+will print its version information string, which includes some
+configuration and compilation values.
+
+@c ----------------------------------------------------------------
+@node restart_mounts Parameter, show_statfs_entries Parameter, print_version Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{restart_mounts} Parameter
+@cindex restart_mounts Parameter
+
+(type=boolean, default=@samp{no}). Same as the @code{-r} option to @i{Amd}.
+If @samp{yes} @i{Amd} will scan the mount table to determine which file
+systems are currently mounted. Whenever one of these would have been
+auto-mounted, @i{Amd} inherits it.
+
+@c ----------------------------------------------------------------
+@node show_statfs_entries Parameter, truncate_log Parameter, restart_mounts Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{show_statfs_entries} Parameter
+@cindex show_statfs_entries Parameter
+
+(type=boolean), default=@samp{no}). If @samp{yes}, then all maps which are
+browsable will also show the number of entries (keys) they have when
+@b{df}(1) runs. (This is accomplished by returning non-zero values to
+the @b{statfs}(2) system call).
+
+@c ----------------------------------------------------------------
+@node truncate_log Parameter, unmount_on_exit Parameter, show_statfs_entries Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{truncate_log} Parameter
+@cindex truncate_log Parameter
+
+(type=boolean), default=@samp{no}). If @samp{yes}, then @i{Amd} will
+truncate the log file (if it's a regular file) on startup. This could
+be useful when conducting extensive testing on @i{Amd} maps (or
+@i{Amd} itself) and you don't want to see log data from a previous run
+in the same file.
+
+@c ----------------------------------------------------------------
+@node unmount_on_exit Parameter, use_tcpwrappers Parameter, truncate_log Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{unmount_on_exit} Parameter
+@cindex unmount_on_exit Parameter
+
+(type=boolean, default=@samp{no}). If @samp{yes}, then @i{Amd} will attempt
+to unmount all file systems which it knows about. Normally it leaves
+all (esp. NFS) mounted file systems intact. Note that @i{Amd} does not
+know about file systems mounted before it starts up, unless the
+@samp{restart_mounts} option is used (@pxref{restart_mounts Parameter}).
+
+@c ----------------------------------------------------------------
+@node use_tcpwrappers Parameter, vendor Parameter, unmount_on_exit Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{use_tcpwrappers} Parameter
+@cindex use_tcpwrappers Parameter
+
+(type=boolean), default=@samp{yes}). If @samp{yes}, then amd will use
+the tcpwrappers (tcpd/librwap) library (if available) to control
+access to @i{Amd} via the @code{/etc/hosts.allow} and
+@code{/etc/hosts.deny} files. @i{Amd} will verify that the host
+running @i{Amq} is authorized to connect. The @code{amd} service name
+must used in the @code{/etc/hosts.allow} and @code{/etc/hosts.deny}
+files. For example, to allow only localhost to connect to @i{Amd},
+add this line to @code{/etc/hosts.allow}:
+
+@example
+amd: localhost
+@end example
+
+and this line to @code{/etc/hosts.deny}:
+
+@example
+amd: ALL
+@end example
+
+Consult the man pages for @b{hosts_access}(5) for more information on using
+the tcpwrappers access-control library.
+
+Note that in particular, you should not configure your @code{hosts.allow}
+file to spawn a command for @i{Amd}: that will cause @i{Amd} to not be able
+to @code{waitpid} on the child process ID of any background un/mount that
+@i{Amd} issued, resulting in a confused @i{Amd} that does not know what
+happened to those background un/mount requests.
+
+@c ----------------------------------------------------------------
+@node vendor Parameter, , use_tcpwrappers Parameter, Global Parameters
+@comment node-name, next, previous, up
+@subsection @t{vendor} Parameter
+@cindex vendor Parameter
+
+(type=string, default to compiled in value). The name of the vendor of
+the operating system. Overrides the compiled-in vendor name. Useful
+when the compiled-in name is not desired. For example, most Intel based
+systems set the vendor name to @samp{unknown}, but you can set it to
+@samp{redhat}.
+
+@c ================================================================
+@node Regular Map Parameters, amd.conf Examples, Global Parameters, Amd Configuration File
+@comment node-name, next, previous, up
+@section Regular Map Parameters
+@cindex amd.conf regular map parameters
+
+The following parameters are applicable only to regular map sections.
+
+@menu
+* map_name Parameter::
+* tag Parameter::
+@end menu
+
+@c ----------------------------------------------------------------
+@node map_name Parameter, tag Parameter, Regular Map Parameters, Regular Map Parameters
+@comment node-name, next, previous, up
+@subsection map_name Parameter
+@cindex map_name Parameter
+
+(type=string, must be specified). Name of the map where the keys are
+located.
+
+@c ----------------------------------------------------------------
+@node tag Parameter, , map_name Parameter, Regular Map Parameters
+@comment node-name, next, previous, up
+@subsection tag Parameter
+@cindex tag Parameter
+
+(type=string, default no tag). Each map entry in the configuration file
+can be tagged. If no tag is specified, that map section will always be
+processed by @i{Amd}. If it is specified, then @i{Amd} will process the map
+if the @code{-T} option was given to @i{Amd}, and the value given to that
+command-line option matches that in the map section.
+
+@c ================================================================
+@node amd.conf Examples, , Regular Map Parameters, Amd Configuration File
+@comment node-name, next, previous, up
+@section amd.conf Examples
+@cindex amd.conf examples
+
+The following is the actual @code{amd.conf} file I used at the
+Computer Science Department of Columbia University.
+
+@example
+# GLOBAL OPTIONS SECTION
+[ global ]
+normalize_hostnames = no
+print_pid = no
+#pid_file = /var/run/amd.pid
+restart_mounts = yes
+#unmount_on_exit = yes
+auto_dir = /n
+log_file = /var/log/amd
+log_options = all
+#debug_options = all
+plock = no
+selectors_in_defaults = yes
+# config.guess picks up "sunos5" and I don't want to edit my maps yet
+os = sos5
+# if you print_version after setting up "os", it will show it.
+print_version = no
+map_type = file
+search_path = /etc/amdmaps:/usr/lib/amd:/usr/local/AMD/lib
+browsable_dirs = yes
+fully_qualified_hosts = no
+
+# DEFINE AN AMD MOUNT POINT
+[ /u ]
+map_name = amd.u
+
+[ /proj ]
+map_name = amd.proj
+
+[ /src ]
+map_name = amd.src
+
+[ /misc ]
+map_name = amd.misc
+
+[ /import ]
+map_name = amd.import
+
+[ /tftpboot/.amd ]
+tag = tftpboot
+map_name = amd.tftpboot
+@end example
+
+@c ################################################################
+@node Run-time Administration, FSinfo, Amd Configuration File, Top
+@comment node-name, next, previous, up
+@chapter Run-time Administration
+@cindex Run-time administration
+@cindex Amq command
+
+@menu
+* Starting Amd::
+* Stopping Amd::
+* Restarting Amd::
+* Controlling Amd::
+@end menu
+
+@node Starting Amd, Stopping Amd, Run-time Administration, Run-time Administration
+@comment node-name, next, previous, up
+@section Starting @i{Amd}
+@cindex Starting Amd
+@cindex Additions to /etc/rc.local
+@cindex /etc/rc.local additions
+@cindex ctl-amd
+
+@i{Amd} is best started from @samp{/etc/rc.local} on BSD systems, or
+from the appropriate start-level script in @samp{/etc/init.d} on System V
+systems.
+
+@example
+if [ -f /usr/local/sbin/ctl-amd ]; then
+ /usr/local/sbin/ctl-amd start; (echo -n ' amd') > /dev/console
+fi
+@end example
+
+@noindent
+The shell script, @samp{ctl-amd} is used to start, stop, or restart
+@i{Amd}. It is a relatively generic script. All options you want to
+set should not be made in this script, but rather updated in the
+@file{amd.conf} file. @xref{Amd Configuration File}.
+
+If you do not wish to use an @i{Amd} configuration file, you may start
+@i{Amd} manually. For example, getting the map entries via NIS:
+
+@example
+amd -r -l /var/log/amd `ypcat -k auto.master`
+@end example
+
+@node Stopping Amd, Restarting Amd, Starting Amd, Run-time Administration
+@comment node-name, next, previous, up
+@section Stopping @i{Amd}
+@cindex Stopping Amd
+@cindex SIGTERM signal
+@cindex SIGINT signal
+
+@i{Amd} stops in response to two signals.
+
+@table @samp
+@item SIGTERM
+causes the top-level automount points to be unmounted and then @i{Amd}
+to exit. Any automounted filesystems are left mounted. They can be
+recovered by restarting @i{Amd} with the @code{-r} command line option.@refill
+
+@item SIGINT
+causes @i{Amd} to attempt to unmount any filesystems which it has
+automounted, in addition to the actions of @samp{SIGTERM}. This signal
+is primarily used for debugging.@refill
+@end table
+
+Actions taken for other signals are undefined.
+
+The easiest and safest way to stop @i{Amd}, without having to find its
+process ID by hand, is to use the @file{ctl-amd} script, as with:
+
+@example
+ctl-amd stop
+@end example
+
+@node Restarting Amd, Controlling Amd, Stopping Amd, Run-time Administration
+@comment node-name, next, previous, up
+@section Restarting @i{Amd}
+@cindex Restarting Amd
+@cindex Killing and starting Amd
+
+Before @i{Amd} can be started, it is vital to ensure that no other
+@i{Amd} processes are managing any of the mount points, and that the
+previous process(es) have terminated cleanly. When a terminating signal
+is set to @i{Amd}, the automounter does @emph{not} terminate right then.
+Rather, it starts by unmounting all of its managed mount mounts in the
+background, and then terminates. It usually takes a few seconds for
+this process to happen, but it can take an arbitrarily longer time. If
+two or more @i{Amd} processes attempt to manage the same mount point, it
+usually will result in a system lockup.
+
+The easiest and safest way to restart @i{Amd}, without having to find
+its process ID by hand, sending it the @samp{SIGTERM} signal, waiting for @i{Amd}
+to die cleanly, and verifying so, is to use the @file{ctl-amd} script,
+as with:
+
+@example
+ctl-amd restart
+@end example
+
+The script will locate the process ID of @i{Amd}, kill it, and wait for
+it to die cleanly before starting a new instance of the automounter.
+@file{ctl-amd} will wait for a total of 30 seconds for @i{Amd} to die,
+and will check once every 5 seconds if it had.
+
+@node Controlling Amd, , Restarting Amd, Run-time Administration
+@comment node-name, next, previous, up
+@section Controlling @i{Amd}
+@cindex Controlling Amd
+@cindex Discovering what is going on at run-time
+@cindex Listing currently mounted filesystems
+
+It is sometimes desirable or necessary to exercise external control
+over some of @i{Amd}'s internal state. To support this requirement,
+@i{Amd} implements an RPC interface which is used by the @dfn{Amq} program.
+A variety of information is available.
+
+@i{Amq} generally applies an operation, specified by a single letter option,
+to a list of mount points. The default operation is to obtain statistics
+about each mount point. This is similar to the output shown above
+but includes information about the number and type of accesses to each
+mount point.
+
+@menu
+* Amq default:: Default command behavior.
+* Amq -f option:: Flushing the map cache.
+* Amq -h option:: Controlling a non-local host.
+* Amq -H option:: Print help message.
+* Amq -l option:: Controlling the log file.
+* Amq -m option:: Obtaining mount statistics.
+* Amq -p option:: Getting Amd's process ID.
+* Amq -P option:: Contacting alternate Amd processes.
+* Amq -s option:: Obtaining global statistics.
+* Amq -T option:: Use TCP transport.
+* Amq -U option:: Use UDP transport.
+* Amq -u option:: Forcing volumes to time out.
+* Amq -v option:: Version information.
+* Amq -w option:: Print Amd current working directory.
+* Other Amq options:: Three other special options.
+@end menu
+
+@c ----------------------------------------------------------------
+@node Amq default, Amq -f option, Controlling Amd, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} default information
+
+With no arguments, @dfn{Amq} obtains a brief list of all existing
+mounts created by @i{Amd}. This is different from the list displayed by
+@b{df}(1) since the latter only includes system mount points.
+
+@noindent
+The output from this option includes the following information:
+
+@itemize @bullet
+@item
+the automount point,
+@item
+the filesystem type,
+@item
+the mount map or mount information,
+@item
+the internal, or system mount point.
+@end itemize
+
+@noindent
+For example:
+
+@example
+/ root "root" sky:(pid75)
+/homes toplvl /usr/local/etc/amd.homes /homes
+/home toplvl /usr/local/etc/amd.home /home
+/homes/jsp nfs charm:/home/charm /a/charm/home/charm/jsp
+/homes/phjk nfs toytown:/home/toytown /a/toytown/home/toytown/ai/phjk
+@end example
+
+@noindent
+If an argument is given then statistics for that volume name will
+be output. For example:
+
+@example
+What Uid Getattr Lookup RdDir RdLnk Statfs Mounted@@
+/homes 0 1196 512 22 0 30 90/09/14 12:32:55
+/homes/jsp 0 0 0 0 1180 0 90/10/13 12:56:58
+@end example
+
+@table @code
+@item What
+the volume name.
+
+@item Uid
+ignored.
+
+@item Getattr
+the count of NFS @dfn{getattr} requests on this node. This should only be
+non-zero for directory nodes.
+
+@item Lookup
+the count of NFS @dfn{lookup} requests on this node. This should only be
+non-zero for directory nodes.
+
+@item RdDir
+the count of NFS @dfn{readdir} requests on this node. This should only
+be non-zero for directory nodes.
+
+@item RdLnk
+the count of NFS @dfn{readlink} requests on this node. This should be
+zero for directory nodes.
+
+@item Statfs
+the count of NFS @dfn{statfs} requests on this node. This should only
+be non-zero for top-level automount points.
+
+@item Mounted@@
+the date and time the volume name was first referenced.
+@end table
+
+@c ----------------------------------------------------------------
+@node Amq -f option, Amq -h option, Amq default, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-f} option
+@cindex Flushing the map cache
+@cindex Map cache, flushing
+
+The @code{-f} option causes @i{Amd} to flush the internal mount map cache.
+This is useful for example in Hesiod maps since @i{Amd} will not
+automatically notice when they have been updated. The map cache can
+also be synchronized with the map source by using the @samp{sync} option
+(@pxref{Automount Filesystem}).@refill
+
+@c ----------------------------------------------------------------
+@node Amq -h option, Amq -H option, Amq -f option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-h} option
+@cindex Querying an alternate host
+
+By default the local host is used. In an HP-UX cluster the root server
+is used since that is the only place in the cluster where @i{Amd} will
+be running. To query @i{Amd} on another host the @code{-h} option should
+be used.
+
+@c ----------------------------------------------------------------
+@node Amq -H option, Amq -l option, Amq -h option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-H} option
+@cindex Displaying brief help
+@cindex Help; showing from Amq
+
+Print a brief help and usage string.
+
+@c ----------------------------------------------------------------
+@node Amq -l option, Amq -m option, Amq -H option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-l} option
+@cindex Resetting the Amd log file
+@cindex Setting the Amd log file via Amq
+@cindex Log file, resetting
+
+Tell @i{Amd} to use @i{log_file} as the log file name. For security
+reasons, this @emph{must} be the same log file which @i{Amd} used when
+started. This option is therefore only useful to refresh @i{Amd}'s open
+file handle on the log file, so that it can be rotated and compressed
+via daily cron jobs.
+
+@c ----------------------------------------------------------------
+@node Amq -m option, Amq -p option, Amq -l option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-m} option
+
+The @code{-m} option displays similar information about mounted
+filesystems, rather than automount points. The output includes the
+following information:
+
+@itemize @bullet
+@item
+the mount information,
+@item
+the mount point,
+@item
+the filesystem type,
+@item
+the number of references to this filesystem,
+@item
+the server hostname,
+@item
+the state of the file server,
+@item
+any error which has occurred.
+@end itemize
+
+For example:
+
+@example
+"root" truth:(pid602) root 1 localhost is up
+hesiod.home /home toplvl 1 localhost is up
+hesiod.vol /vol toplvl 1 localhost is up
+hesiod.homes /homes toplvl 1 localhost is up
+amy:/home/amy /a/amy/home/amy nfs 5 amy is up
+swan:/home/swan /a/swan/home/swan nfs 0 swan is up (Permission denied)
+ex:/home/ex /a/ex/home/ex nfs 0 ex is down
+@end example
+
+When the reference count is zero the filesystem is not mounted but
+the mount point and server information is still being maintained
+by @i{Amd}.
+
+@c ----------------------------------------------------------------
+@ignore
+@comment Retained for future consideration: from the description of the
+@comment amq -M option removed in amd 6.0.5.
+
+A future release of @i{Amd} will include code to allow the @b{mount}(8)
+command to mount automount points:
+
+@example
+mount -t amd /vol hesiod.vol
+@end example
+
+This will then allow @i{Amd} to be controlled from the standard system
+filesystem mount list.
+
+@end ignore
+
+@c ----------------------------------------------------------------
+@node Amq -p option, Amq -P option, Amq -m option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-p} option
+@cindex Process ID; Amd
+@cindex Amd's process ID
+@cindex Amd's PID
+@cindex PID; Amd
+
+Return the process ID of the remote or locally running @i{Amd}. Useful
+when you need to send a signal to the local @i{Amd} process, and would
+rather not have to search through the process table. This option is
+used in the @file{ctl-amd} script.
+
+@c ----------------------------------------------------------------
+@node Amq -P option, Amq -s option, Amq -p option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-P} option
+@cindex Multiple Amd processes
+@cindex Running multiple Amd
+@cindex Debugging a new Amd configuration
+@cindex RPC Program numbers; Amd
+
+Contact an alternate running @i{Amd} that had registered itself on a
+different RPC @var{program_number} and apply all other operations to
+that instance of the automounter. This is useful when you run multiple
+copies of @i{Amd}, and need to manage each one separately. If not
+specified, @i{Amq} will use the default program number for @i{Amd}, 300019.
+For security reasons, the only alternate program numbers @i{Amd} can use
+range from 300019 to 300029, inclusive.
+
+For example, to kill an alternate running @i{Amd}:
+
+@example
+kill `amq -p -P 300020`
+@end example
+
+@c ----------------------------------------------------------------
+@node Amq -s option, Amq -T option, Amq -P option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-s} option
+@cindex Global statistics
+@cindex Statistics
+
+The @code{-s} option displays global statistics. If any other options are specified
+or any filesystems named then this option is ignored. For example:
+
+@example
+requests stale mount mount unmount
+deferred fhandles ok failed failed
+1054 1 487 290 7017
+@end example
+
+@table @samp
+@item Deferred requests
+are those for which an immediate reply could not be constructed. For
+example, this would happen if a background mount was required.
+
+@item Stale filehandles
+counts the number of times the kernel passes a stale filehandle to @i{Amd}.
+Large numbers indicate problems.
+
+@item Mount ok
+counts the number of automounts which were successful.
+
+@item Mount failed
+counts the number of automounts which failed.
+
+@item Unmount failed
+counts the number of times a filesystem could not be unmounted. Very
+large numbers here indicate that the time between unmount attempts
+should be increased.
+@end table
+
+@c ----------------------------------------------------------------
+@node Amq -T option, Amq -U option, Amq -s option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-T} option
+@cindex Forcing Amq to use a TCP transport
+@cindex TCP; using with Amq
+
+The @code{-T} option causes the @i{Amq} to contact @i{Amd} using the TCP
+transport only (connection oriented). Normally, @i{Amq} will use TCP
+first, and if that failed, will try UDP.
+
+@c ----------------------------------------------------------------
+@node Amq -U option, Amq -u option, Amq -T option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-U} option
+@cindex Forcing Amq to use a UDP transport
+@cindex UDP; using with Amq
+
+The @code{-U} option causes the @i{Amq} to contact @i{Amd} using the UDP
+transport only (connectionless). Normally, @i{Amq} will use TCP first,
+and if that failed, will try UDP.
+
+@c ----------------------------------------------------------------
+@node Amq -u option, Amq -v option, Amq -U option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-u} option
+@cindex Forcing filesystem to time out
+@cindex Unmounting a filesystem
+
+The @code{-u} option causes the time-to-live interval of the named mount
+points to be expired, thus causing an unmount attempt. This is the only
+safe way to unmount an automounted filesystem. It is not possible to
+unmount a filesystem which has been mounted with the @samp{nounmount}
+flag.
+
+@c The @code{-H} option informs @i{Amd} that the specified mount point
+@c has hung - as if its keepalive timer had expired.
+
+@c ----------------------------------------------------------------
+@node Amq -v option, Amq -w option, Amq -u option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-v} option
+@cindex Version information at run-time
+
+The @code{-v} option displays the version of @i{Amd} in a similar way to
+@i{Amd}'s @code{-v} option.
+
+@c ----------------------------------------------------------------
+@node Amq -w option, Other Amq options, Amq -v option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection @i{Amq} @code{-w} option
+@cindex Getting real working directory
+
+The @code{-w} option translates a full pathname as returned by
+@b{getpwd}(3) into a short @i{Amd} pathname that goes through its mount
+points. This option requires that @i{Amd} is running.
+
+@c ----------------------------------------------------------------
+@node Other Amq options, , Amq -w option, Controlling Amd
+@comment node-name, next, previous, up
+@subsection Other @i{Amq} options
+@cindex Logging options via Amq
+@cindex Debugging options via Amq
+
+Two other operations are implemented. These modify the state of @i{Amd}
+as a whole, rather than any particular filesystem. The @code{-x} and
+@code{-D} options have exactly the same effect as @i{Amd}'s corresponding
+command line options.
+
+When @i{Amd} receives a @code{-x} flag it limits the log options being
+modified to those which were not enabled at startup. This prevents a
+user turning @emph{off} any logging option which was specified at
+startup, though any which have been turned on since then can still be
+turned off. The @code{-D} option has a similar behavior.
+
+@c ################################################################
+@node FSinfo, Hlfsd, Run-time Administration, Top
+@comment node-name, next, previous, up
+@chapter FSinfo
+@cindex FSinfo
+@cindex Filesystem info package
+
+XXX: this chapter should be reviewed by someone knowledgeable with
+fsinfo.
+
+@menu
+* FSinfo Overview:: Introduction to FSinfo.
+* Using FSinfo:: Basic concepts.
+* FSinfo Grammar:: Language syntax, semantics and examples.
+* FSinfo host definitions:: Defining a new host.
+* FSinfo host attributes:: Definable host attributes.
+* FSinfo filesystems:: Defining locally attached filesystems.
+* FSinfo static mounts:: Defining additional static mounts.
+* FSinfo automount definitions::
+* FSinfo Command Line Options::
+* FSinfo errors::
+@end menu
+
+@node FSinfo Overview, Using FSinfo, FSinfo, FSinfo
+@comment node-name, next, previous, up
+@section @i{FSinfo} overview
+@cindex FSinfo overview
+
+@i{FSinfo} is a filesystem management tool. It has been designed to
+work with @i{Amd} to help system administrators keep track of the ever
+increasing filesystem namespace under their control.
+
+The purpose of @i{FSinfo} is to generate all the important standard
+filesystem data files from a single set of input data. Starting with a
+single data source guarantees that all the generated files are
+self-consistent. One of the possible output data formats is a set of
+@i{Amd} maps which can be used among the set of hosts described in the
+input data.
+
+@i{FSinfo} implements a declarative language. This language is
+specifically designed for describing filesystem namespace and physical
+layouts. The basic declaration defines a mounted filesystem including
+its device name, mount point, and all the volumes and access
+permissions. @i{FSinfo} reads this information and builds an internal
+map of the entire network of hosts. Using this map, many different data
+formats can be produced including @file{/etc/fstab},
+@file{/etc/exports}, @i{Amd} mount maps and
+@file{/etc/bootparams}.@refill
+
+@node Using FSinfo, FSinfo Grammar, FSinfo Overview, FSinfo
+@comment node-name, next, previous, up
+@section Using @i{FSinfo}
+@cindex Using FSinfo
+
+The basic strategy when using @i{FSinfo} is to gather all the
+information about all disks on all machines into one set of
+declarations. For each machine being managed, the following data is
+required:
+
+@itemize @bullet
+@item
+Hostname
+@item
+List of all filesystems and, optionally, their mount points.
+@item
+Names of volumes stored on each filesystem.
+@item
+NFS export information for each volume.
+@item
+The list of static filesystem mounts.
+@end itemize
+
+The following information can also be entered into the same
+configuration files so that all data can be kept in one place.
+
+@itemize @bullet
+@item
+List of network interfaces
+@item
+IP address of each interface
+@item
+Hardware address of each interface
+@item
+Dumpset to which each filesystem belongs
+@item
+and more @dots{}
+@end itemize
+
+To generate @i{Amd} mount maps, the automount tree must also be defined
+(@pxref{FSinfo automount definitions}). This will have been designed at
+the time the volume names were allocated. Some volume names will not be
+automounted, so @i{FSinfo} needs an explicit list of which volumes
+should be automounted.@refill
+
+Hostnames are required at several places in the @i{FSinfo} language. It
+is important to stick to either fully qualified names or unqualified
+names. Using a mixture of the two will inevitably result in confusion.
+
+Sometimes volumes need to be referenced which are not defined in the set
+of hosts being managed with @i{FSinfo}. The required action is to add a
+dummy set of definitions for the host and volume names required. Since
+the files generated for those particular hosts will not be used on them,
+the exact values used is not critical.
+
+@node FSinfo Grammar, FSinfo host definitions, Using FSinfo, FSinfo
+@comment node-name, next, previous, up
+@section @i{FSinfo} grammar
+@cindex FSinfo grammar
+@cindex Grammar, FSinfo
+
+@i{FSinfo} has a relatively simple grammar. Distinct syntactic
+constructs exist for each of the different types of data, though they
+share a common flavor. Several conventions are used in the grammar
+fragments below.
+
+The notation, @i{list(}@t{xxx}@i{)}, indicates a list of zero or more
+@t{xxx}'s. The notation, @i{opt(}@t{xxx}@i{)}, indicates zero or one
+@t{xxx}. Items in double quotes, @i{eg} @t{"host"}, represent input
+tokens. Items in angle brackets, @i{eg} @var{<hostname>}, represent
+strings in the input. Strings need not be in double quotes, except to
+differentiate them from reserved words. Quoted strings may include the
+usual set of C ``@t{\}'' escape sequences with one exception: a
+backslash-newline-whitespace sequence is squashed into a single space
+character. To defeat this feature, put a further backslash at the start
+of the second line.
+
+At the outermost level of the grammar, the input consists of a
+sequence of host and automount declarations. These declarations are
+all parsed before they are analyzed. This means they can appear in
+any order and cyclic host references are possible.
+
+@example
+fsinfo : @i{list(}fsinfo_attr@i{)} ;
+
+fsinfo_attr : host | automount ;
+@end example
+
+@menu
+* FSinfo host definitions::
+* FSinfo automount definitions::
+@end menu
+
+@node FSinfo host definitions, FSinfo host attributes, FSinfo Grammar, FSinfo
+@comment node-name, next, previous, up
+@section @i{FSinfo} host definitions
+@cindex FSinfo host definitions
+@cindex Defining a host, FSinfo
+
+A host declaration consists of three parts: a set of machine attribute
+data, a list of filesystems physically attached to the machine, and a
+list of additional statically mounted filesystems.
+
+@example
+host : "host" host_data @i{list(}filesystem@i{@i{)}} @i{list(}mount@i{@i{)}} ;
+@end example
+
+Each host must be declared in this way exactly once. Such things as the
+hardware address, the architecture and operating system types and the
+cluster name are all specified within the @dfn{host data}.
+
+All the disks the machine has should then be described in the @dfn{list
+of filesystems}. When describing disks, you can specify what
+@dfn{volname} the disk/partition should have and all such entries are
+built up into a dictionary which can then be used for building the
+automounter maps.
+
+The @dfn{list of mounts} specifies all the filesystems that should be
+statically mounted on the machine.
+
+@menu
+* FSinfo host attributes::
+* FSinfo filesystems::
+* FSinfo static mounts::
+@end menu
+
+@node FSinfo host attributes, FSinfo filesystems, FSinfo host definitions , FSinfo host definitions
+@comment node-name, next, previous, up
+@section @i{FSinfo} host attributes
+@cindex FSinfo host attributes
+@cindex Defining host attributes, FSinfo
+
+The host data, @dfn{host_data}, always includes the @dfn{hostname}. In
+addition, several other host attributes can be given.
+
+@example
+host_data : @var{<hostname>}
+ | "@{" @i{list(}host_attrs@i{)} "@}" @var{<hostname>}
+ ;
+
+host_attrs : host_attr "=" @var{<string>}
+ | netif
+ ;
+
+host_attr : "config"
+ | "arch"
+ | "os"
+ | "cluster"
+ ;
+@end example
+
+The @dfn{hostname} is, typically, the fully qualified hostname of the
+machine.
+
+Examples:
+
+@example
+host dylan.doc.ic.ac.uk
+
+host @{
+ os = hpux
+ arch = hp300
+@} dougal.doc.ic.ac.uk
+@end example
+
+The options that can be given as host attributes are shown below.
+
+@menu
+* FSinfo netif Option:: FSinfo host netif.
+* FSinfo config Option:: FSinfo host config.
+* FSinfo arch Option:: FSinfo host arch.
+* FSinfo os Option:: FSinfo host os.
+* FSinfo cluster Option:: FSinfo host cluster.
+@end menu
+
+@node FSinfo netif Option, FSinfo config Option, , FSinfo host attributes
+@comment node-name, next, previous, up
+@subsection netif Option
+
+This defines the set of network interfaces configured on the machine.
+The interface attributes collected by @i{FSinfo} are the IP address,
+subnet mask and hardware address. Multiple interfaces may be defined
+for hosts with several interfaces by an entry for each interface. The
+values given are sanity checked, but are currently unused for anything
+else.
+
+@example
+netif : "netif" @var{<string>} "@{" @i{list(}netif_attrs@i{)} "@}" ;
+
+netif_attrs : netif_attr "=" @var{<string>} ;
+
+netif_attr : "inaddr" | "netmask" | "hwaddr" ;
+@end example
+
+Examples:
+
+@example
+netif ie0 @{
+ inaddr = 129.31.81.37
+ netmask = 0xfffffe00
+ hwaddr = "08:00:20:01:a6:a5"
+@}
+
+netif ec0 @{ @}
+@end example
+
+@node FSinfo config Option, FSinfo arch Option, FSinfo netif Option, FSinfo host attributes
+@comment node-name, next, previous, up
+@subsection config Option
+@cindex FSinfo config host attribute
+@cindex config, FSinfo host attribute
+
+This option allows you to specify configuration variables for the
+startup scripts (@file{rc} scripts). A simple string should immediately
+follow the keyword.
+
+Example:
+
+@example
+config "NFS_SERVER=true"
+config "ZEPHYR=true"
+@end example
+
+This option is currently unsupported.
+
+@node FSinfo arch Option, FSinfo os Option, FSinfo config Option, FSinfo host attributes
+@comment node-name, next, previous, up
+@subsection arch Option
+@cindex FSinfo arch host attribute
+@cindex arch, FSinfo host attribute
+
+This defines the architecture of the machine. For example:
+
+@example
+arch = hp300
+@end example
+
+This is intended to be of use when building architecture specific
+mountmaps, however, the option is currently unsupported.
+
+@node FSinfo os Option, FSinfo cluster Option, FSinfo arch Option, FSinfo host attributes
+@comment node-name, next, previous, up
+@subsection os Option
+@cindex FSinfo os host attribute
+@cindex os, FSinfo host attribute
+
+This defines the operating system type of the host. For example:
+
+@example
+os = hpux
+@end example
+
+This information is used when creating the @file{fstab} files, for
+example in choosing which format to use for the @file{fstab} entries
+within the file.
+
+@node FSinfo cluster Option, , FSinfo os Option, FSinfo host attributes
+@comment node-name, next, previous, up
+@subsection cluster Option
+@cindex FSinfo cluster host attribute
+@cindex cluster, FSinfo host attribute
+
+This is used for specifying in which cluster the machine belongs. For
+example:
+
+@example
+cluster = "theory"
+@end example
+
+The cluster is intended to be used when generating the automount maps,
+although it is currently unsupported.
+
+@node FSinfo filesystems, FSinfo static mounts, FSinfo host attributes, FSinfo host definitions
+@comment node-name, next, previous, up
+@section @i{FSinfo} filesystems
+@cindex FSinfo filesystems
+
+The list of physically attached filesystems follows the machine
+attributes. These should define all the filesystems available from this
+machine, whether exported or not. In addition to the device name,
+filesystems have several attributes, such as filesystem type, mount
+options, and @samp{fsck} pass number which are needed to generate
+@file{fstab} entries.
+
+@example
+filesystem : "fs" @var{<device>} "@{" @i{list(}fs_data@i{)} "@}" ;
+
+fs_data : fs_data_attr "=" @var{<string>}
+ | mount
+ ;
+
+fs_data_attr
+ : "fstype" | "opts" | "passno"
+ | "freq" | "dumpset" | "log"
+ ;
+@end example
+
+Here, @var{<device>} is the device name of the disk (for example,
+@file{/dev/dsk/2s0}). The device name is used for building the mount
+maps and for the @file{fstab} file. The attributes that can be
+specified are shown in the following section.
+
+The @i{FSinfo} configuration file for @code{dylan.doc.ic.ac.uk} is listed below.
+
+@example
+host dylan.doc.ic.ac.uk
+
+fs /dev/dsk/0s0 @{
+ fstype = swap
+@}
+
+fs /dev/dsk/0s0 @{
+ fstype = hfs
+ opts = rw,noquota,grpid
+ passno = 0;
+ freq = 1;
+ mount / @{ @}
+@}
+
+fs /dev/dsk/1s0 @{
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount /usr @{
+ local @{
+ exportfs "dougal eden dylan zebedee brian"
+ volname /nfs/hp300/local
+ @}
+ @}
+@}
+
+fs /dev/dsk/2s0 @{
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount default @{
+ exportfs "toytown_clients hangers_on"
+ volname /home/dylan/dk2
+ @}
+@}
+
+fs /dev/dsk/3s0 @{
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount default @{
+ exportfs "toytown_clients hangers_on"
+ volname /home/dylan/dk3
+ @}
+@}
+
+fs /dev/dsk/5s0 @{
+ fstype = hfs
+ opts = defaults
+ passno = 1;
+ freq = 1;
+ mount default @{
+ exportfs "toytown_clients hangers_on"
+ volname /home/dylan/dk5
+ @}
+@}
+@end example
+
+@menu
+* FSinfo fstype Option:: FSinfo filesystems fstype.
+* FSinfo opts Option:: FSinfo filesystems opts.
+* FSinfo passno Option:: FSinfo filesystems passno.
+* FSinfo freq Option:: FSinfo filesystems freq.
+* FSinfo mount Option:: FSinfo filesystems mount.
+* FSinfo dumpset Option:: FSinfo filesystems dumpset.
+* FSinfo log Option:: FSinfo filesystems log.
+@end menu
+
+@node FSinfo fstype Option, FSinfo opts Option, , FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection fstype Option
+@cindex FSinfo fstype filesystems option
+@cindex fstype, FSinfo filesystems option
+@cindex export, FSinfo special fstype
+
+This specifies the type of filesystem being declared and will be placed
+into the @file{fstab} file as is. The value of this option will be
+handed to @code{mount} as the filesystem type---it should have such
+values as @code{4.2}, @code{nfs} or @code{swap}. The value is not
+examined for correctness.
+
+There is one special case. If the filesystem type is specified as
+@samp{export} then the filesystem information will not be added to the
+host's @file{fstab} information, but it will still be visible on the
+network. This is useful for defining hosts which contain referenced
+volumes but which are not under full control of @i{FSinfo}.
+
+Example:
+
+@example
+fstype = swap
+@end example
+
+@node FSinfo opts Option, FSinfo passno Option, FSinfo fstype Option, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection opts Option
+@cindex FSinfo opts filesystems option
+@cindex opts, FSinfo filesystems option
+
+This defines any options that should be given to @b{mount}(8) in the
+@file{fstab} file. For example:
+
+@example
+opts = rw,nosuid,grpid
+@end example
+
+@node FSinfo passno Option, FSinfo freq Option, FSinfo opts Option, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection passno Option
+@cindex FSinfo passno filesystems option
+@cindex passno, FSinfo filesystems option
+
+This defines the @b{fsck}(8) pass number in which to check the
+filesystem. This value will be placed into the @file{fstab} file.
+
+Example:
+
+@example
+passno = 1
+@end example
+
+@node FSinfo freq Option, FSinfo mount Option, FSinfo passno Option, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection freq Option
+@cindex FSinfo freq filesystems option
+@cindex freq, FSinfo filesystems option
+
+This defines the interval (in days) between dumps. The value is placed
+as is into the @file{fstab} file.
+
+Example:
+
+@example
+freq = 3
+@end example
+
+@node FSinfo mount Option, FSinfo dumpset Option, FSinfo freq Option, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection mount Option
+@cindex FSinfo mount filesystems option
+@cindex mount, FSinfo filesystems option
+@cindex exportfs, FSinfo mount option
+@cindex volname, FSinfo mount option
+@cindex sel, FSinfo mount option
+
+This defines the mountpoint at which to place the filesystem. If the
+mountpoint of the filesystem is specified as @code{default}, then the
+filesystem will be mounted in the automounter's tree under its volume
+name and the mount will automatically be inherited by the automounter.
+
+Following the mountpoint, namespace information for the filesystem may
+be described. The options that can be given here are @code{exportfs},
+@code{volname} and @code{sel}.
+
+The format is:
+
+@example
+mount : "mount" vol_tree ;
+
+vol_tree : @i{list(}vol_tree_attr@i{)} ;
+
+vol_tree_attr
+ : @var{<string>} "@{" @i{list(}vol_tree_info@i{)} vol_tree "@}" ;
+
+vol_tree_info
+ : "exportfs" @var{<export-data>}
+ | "volname" @var{<volname>}
+ | "sel" @var{<selector-list>}
+ ;
+@end example
+
+Example:
+
+@example
+mount default @{
+ exportfs "dylan dougal florence zebedee"
+ volname /vol/andrew
+@}
+@end example
+
+In the above example, the filesystem currently being declared will have
+an entry placed into the @file{exports} file allowing the filesystem to
+be exported to the machines @code{dylan}, @code{dougal}, @code{florence}
+and @code{zebedee}. The volume name by which the filesystem will be
+referred to remotely, is @file{/vol/andrew}. By declaring the
+mountpoint to be @code{default}, the filesystem will be mounted on the
+local machine in the automounter tree, where @i{Amd} will automatically
+inherit the mount as @file{/vol/andrew}.@refill
+
+@table @samp
+@item exportfs
+a string defining which machines the filesystem may be exported to.
+This is copied, as is, into the @file{exports} file---no sanity checking
+is performed on this string.@refill
+
+@item volname
+a string which declares the remote name by which to reference the
+filesystem. The string is entered into a dictionary and allows you to
+refer to this filesystem in other places by this volume name.@refill
+
+@item sel
+a string which is placed into the automounter maps as a selector for the
+filesystem.@refill
+
+@end table
+
+@node FSinfo dumpset Option, FSinfo log Option, FSinfo mount Option, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection dumpset Option
+@cindex FSinfo dumpset filesystems option
+@cindex dumpset, FSinfo filesystems option
+
+This provides support for Imperial College's local file backup tools and
+is not documented further here.
+
+@node FSinfo log Option, , FSinfo dumpset Option, FSinfo filesystems
+@comment node-name, next, previous, up
+@subsection log Option
+@cindex FSinfo log filesystems option
+@cindex log, FSinfo filesystems option
+
+Specifies the log device for the current filesystem. This is ignored if
+not required by the particular filesystem type.
+
+@node FSinfo static mounts, FSinfo automount definitions , FSinfo filesystems, FSinfo host definitions
+@comment node-name, next, previous, up
+@section @i{FSinfo} static mounts
+@cindex FSinfo static mounts
+@cindex Statically mounts filesystems, FSinfo
+
+Each host may also have a number of statically mounted filesystems. For
+example, the host may be a diskless workstation in which case it will
+have no @code{fs} declarations. In this case the @code{mount}
+declaration is used to determine from where its filesystems will be
+mounted. In addition to being added to the @file{fstab} file, this
+information can also be used to generate a suitable @file{bootparams}
+file.@refill
+
+@example
+mount : "mount" @var{<volname>} @i{list(}localinfo@i{)} ;
+
+localinfo : localinfo_attr @var{<string>} ;
+
+localinfo_attr
+ : "as"
+ | "from"
+ | "fstype"
+ | "opts"
+ ;
+@end example
+
+The filesystem specified to be mounted will be searched for in the
+dictionary of volume names built when scanning the list of hosts'
+definitions.
+
+The attributes have the following semantics:
+@table @samp
+@item from @var{machine}
+mount the filesystem from the machine with the hostname of
+@dfn{machine}.@refill
+
+@item as @var{mountpoint}
+mount the filesystem locally as the name given, in case this is
+different from the advertised volume name of the filesystem.
+
+@item opts @var{options}
+native @b{mount}(8) options.
+
+@item fstype @var{type}
+type of filesystem to be mounted.
+@end table
+
+An example:
+
+@example
+mount /export/exec/hp300/local as /usr/local
+@end example
+
+If the mountpoint specified is either @file{/} or @file{swap}, the
+machine will be considered to be booting off the net and this will be
+noted for use in generating a @file{bootparams} file for the host which
+owns the filesystems.
+
+@node FSinfo automount definitions, FSinfo Command Line Options, FSinfo static mounts, FSinfo
+@comment node-name, next, previous, up
+@section Defining an @i{Amd} Mount Map in @i{FSinfo}
+@cindex FSinfo automount definitions
+@cindex Defining an Amd mount map, FSinfo
+
+The maps used by @i{Amd} can be constructed from @i{FSinfo} by defining
+all the automount trees. @i{FSinfo} takes all the definitions found and
+builds one map for each top level tree.
+
+The automount tree is usually defined last. A single automount
+configuration will usually apply to an entire management domain. One
+@code{automount} declaration is needed for each @i{Amd} automount point.
+@i{FSinfo} determines whether the automount point is @dfn{direct}
+(@pxref{Direct Automount Filesystem}) or @dfn{indirect}
+(@pxref{Top-level Filesystem}). Direct automount points are
+distinguished by the fact that there is no underlying
+@dfn{automount_tree}.@refill
+
+@example
+automount : "automount" @i{opt(}auto_opts@i{)} automount_tree ;
+
+auto_opts : "opts" @var{<mount-options>} ;
+
+automount_tree
+ : @i{list(}automount_attr@i{)}
+ ;
+
+automount_attr
+ : @var{<string>} "=" @var{<volname>}
+ | @var{<string>} "->" @var{<symlink>}
+ | @var{<string>} "@{" automount_tree "@}"
+ ;
+@end example
+
+If @var{<mount-options>} is given, then it is the string to be placed in
+the maps for @i{Amd} for the @code{opts} option.
+
+A @dfn{map} is typically a tree of filesystems, for example @file{home}
+normally contains a tree of filesystems representing other machines in
+the network.
+
+A map can either be given as a name representing an already defined
+volume name, or it can be a tree. A tree is represented by placing
+braces after the name. For example, to define a tree @file{/vol}, the
+following map would be defined:
+
+@example
+automount /vol @{ @}
+@end example
+
+Within a tree, the only items that can appear are more maps.
+For example:
+
+@example
+automount /vol @{
+ andrew @{ @}
+ X11 @{ @}
+@}
+@end example
+
+In this case, @i{FSinfo} will look for volumes named @file{/vol/andrew}
+and @file{/vol/X11} and a map entry will be generated for each. If the
+volumes are defined more than once, then @i{FSinfo} will generate
+a series of alternate entries for them in the maps.@refill
+
+Instead of a tree, either a link (@var{name} @code{->}
+@var{destination}) or a reference can be specified (@var{name} @code{=}
+@var{destination}). A link creates a symbolic link to the string
+specified, without further processing the entry. A reference will
+examine the destination filesystem and optimize the reference. For
+example, to create an entry for @code{njw} in the @file{/homes} map,
+either of the two forms can be used:@refill
+
+@example
+automount /homes @{
+ njw -> /home/dylan/njw
+@}
+@end example
+
+or
+
+@example
+automount /homes @{
+ njw = /home/dylan/njw
+@}
+@end example
+
+In the first example, when @file{/homes/njw} is referenced from @i{Amd},
+a link will be created leading to @file{/home/dylan/njw} and the
+automounter will be referenced a second time to resolve this filename.
+The map entry would be:
+
+@example
+njw type:=link;fs:=/home/dylan/njw
+@end example
+
+In the second example, the destination directory is analyzed and found
+to be in the filesystem @file{/home/dylan} which has previously been
+defined in the maps. Hence the map entry will look like:
+
+@example
+njw rhost:=dylan;rfs:=/home/dylan;sublink:=njw
+@end example
+
+Creating only one symbolic link, and one access to @i{Amd}.
+
+@node FSinfo Command Line Options, FSinfo errors, FSinfo automount definitions, FSinfo
+@comment node-name, next, previous, up
+@section @i{FSinfo} Command Line Options
+@cindex FSinfo command line options
+@cindex Command line options, FSinfo
+
+@i{FSinfo} is started from the command line by using the command:
+
+@example
+fsinfo [@i{options}] @i{files} ...
+@end example
+
+The input to @i{FSinfo} is a single set of definitions of machines and
+automount maps. If multiple files are given on the command-line, then
+the files are concatenated together to form the input source. The files
+are passed individually through the C pre-processor before being parsed.
+
+Several options define a prefix for the name of an output file. If the
+prefix is not specified no output of that type is produced. The suffix
+used will correspond either to the hostname to which a file belongs, or
+to the type of output if only one file is produced. Dumpsets and the
+@file{bootparams} file are in the latter class. To put the output into
+a subdirectory simply put a @file{/} at the end of the prefix, making
+sure that the directory has already been made before running
+@i{Fsinfo}.
+
+@menu
+* -a FSinfo Option:: Amd automount directory:
+* -b FSinfo Option:: Prefix for bootparams files.
+* -d FSinfo Option:: Prefix for dumpset data files.
+* -e FSinfo Option:: Prefix for exports files.
+* -f FSinfo Option:: Prefix for fstab files.
+* -h FSinfo Option:: Local hostname.
+* -m FSinfo Option:: Prefix for automount maps.
+* -q FSinfo Option:: Ultra quiet mode.
+* -v FSinfo Option:: Verbose mode.
+* -I FSinfo Option:: Define new #include directory.
+* -D-FSinfo Option:: Define macro.
+* -U FSinfo Option:: Undefine macro.
+@end menu
+
+@node -a FSinfo Option, -b FSinfo Option, FSinfo Command Line Options, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-a} @var{autodir}
+
+Specifies the directory name in which to place the automounter's
+mountpoints. This defaults to @file{/a}. Some sites have the autodir set
+to be @file{/amd}, and this would be achieved by:
+
+@example
+fsinfo -a /amd ...
+@end example
+
+@node -b FSinfo Option, -d FSinfo Option, -a FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-b} @var{bootparams}
+@cindex bootparams, FSinfo prefix
+
+This specifies the prefix for the @file{bootparams} filename. If it is
+not given, then the file will not be generated. The @file{bootparams}
+file will be constructed for the destination machine and will be placed
+into a file named @file{bootparams} and prefixed by this string. The
+file generated contains a list of entries describing each diskless
+client that can boot from the destination machine.
+
+As an example, to create a @file{bootparams} file in the directory
+@file{generic}, the following would be used:
+
+@example
+fsinfo -b generic/ ...
+@end example
+
+@node -d FSinfo Option, -e FSinfo Option, -b FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-d} @var{dumpsets}
+@cindex dumpset, FSinfo prefix
+
+This specifies the prefix for the @file{dumpsets} file. If it is not
+specified, then the file will not be generated. The file will be for
+the destination machine and will be placed into a filename
+@file{dumpsets}, prefixed by this string. The @file{dumpsets} file is
+for use by Imperial College's local backup system.
+
+For example, to create a @file{dumpsets} file in the directory @file{generic},
+then you would use the following:
+
+@example
+fsinfo -d generic/ ...
+@end example
+
+@node -e FSinfo Option, -f FSinfo Option, -d FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-e} @var{exportfs}
+@cindex exports, FSinfo prefix
+
+Defines the prefix for the @file{exports} files. If it is not given,
+then the file will not be generated. For each machine defined in the
+configuration files as having disks, an @file{exports} file is
+constructed and given a filename determined by the name of the machine,
+prefixed with this string. If a machine is defined as diskless, then no
+@file{exports} file will be created for it. The files contain entries
+for directories on the machine that may be exported to clients.
+
+Example: To create the @file{exports} files for each diskfull machine
+and place them into the directory @file{exports}:
+
+@example
+fsinfo -e exports/ ...
+@end example
+
+@node -f FSinfo Option, -h FSinfo Option, -e FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-f} @var{fstab}
+@cindex fstab, FSinfo prefix
+
+This defines the prefix for the @file{fstab} files. The files will only
+be created if this prefix is defined. For each machine defined in the
+configuration files, a @file{fstab} file is created with the filename
+determined by prefixing this string with the name of the machine. These
+files contain entries for filesystems and partitions to mount at boot
+time.
+
+Example, to create the files in the directory @file{fstabs}:
+
+@example
+fsinfo -f fstabs/ ...
+@end example
+
+@node -h FSinfo Option, -m FSinfo Option, -f FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-h} @var{hostname}
+@cindex hostname, FSinfo command line option
+
+Defines the hostname of the destination machine to process for. If this
+is not specified, it defaults to the local machine name, as returned by
+@b{gethostname}(2).
+
+Example:
+
+@example
+fsinfo -h dylan.doc.ic.ac.uk ...
+@end example
+
+@node -m FSinfo Option, -q FSinfo Option, -h FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-m} @var{mount-maps}
+@cindex maps, FSinfo command line option
+
+Defines the prefix for the automounter files. The maps will only be
+produced if this prefix is defined. The mount maps suitable for the
+network defined by the configuration files will be placed into files
+with names calculated by prefixing this string to the name of each map.
+
+For example, to create the automounter maps and place them in the
+directory @file{automaps}:
+
+@example
+fsinfo -m automaps/ ...
+@end example
+
+@node -q FSinfo Option, -v FSinfo Option, -m FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-q}
+@cindex quiet, FSinfo command line option
+
+Selects quiet mode. @i{FSinfo} suppress the ``running commentary'' and
+only outputs any error messages which are generated.
+
+@node -v FSinfo Option, -D-FSinfo Option, -q FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-v}
+@cindex verbose, FSinfo command line option
+
+Selects verbose mode. When this is activated, the program will display
+more messages, and display all the information discovered when
+performing the semantic analysis phase. Each verbose message is output
+to @file{stdout} on a line starting with a @samp{#} character.
+
+@node -D-FSinfo Option, -I FSinfo Option, -v FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-D} @var{name}@i{[=defn]}
+
+Defines a symbol @dfn{name} for the preprocessor when reading the
+configuration files. Equivalent to @code{#define} directive.
+
+@node -I FSinfo Option, -U FSinfo Option, -D-FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-I} @var{directory}
+
+This option is passed into the preprocessor for the configuration files.
+It specifies directories in which to find include files
+
+@node -U FSinfo Option, , -I FSinfo Option, FSinfo Command Line Options
+@comment node-name, next, previous, up
+@subsection @code{-U} @var{name}
+
+Removes any initial definition of the symbol @dfn{name}. Inverse of the
+@code{-D} option.
+
+@node FSinfo errors, , FSinfo Command Line Options, FSinfo
+@comment node-name, next, previous, up
+@section Errors produced by @i{FSinfo}
+@cindex FSinfo error messages
+
+The following table documents the errors and warnings which @i{FSinfo} may produce.
+
+@table @t
+
+@item " expected
+Occurs if an unescaped newline is found in a quoted string.
+
+@item ambiguous mount: @var{volume} is a replicated filesystem
+If several filesystems are declared as having the same volume name, they
+will be considered replicated filesystems. To mount a replicated
+filesystem statically, a specific host will need to be named, to say
+which particular copy to try and mount, else this error will
+result.
+
+@item can't open @var{filename} for writing
+Occurs if any errors are encountered when opening an output file.
+
+@item cannot determine localname since volname @var{volume} is not uniquely defined
+If a volume is replicated and an attempt is made to mount the filesystem
+statically without specifying a local mountpoint, @i{FSinfo} cannot
+calculate a mountpoint, as the desired pathname would be
+ambiguous.
+
+@item @var{device} has duplicate exportfs data
+Produced if the @samp{exportfs} option is used multiple times within the
+same branch of a filesystem definition. For example, if you attempt to
+set the @samp{exportfs} data at different levels of the mountpoint
+directory tree.
+
+@item dump frequency for @var{host}:@var{device} is non-zero
+Occurs if @var{device} has its @samp{fstype} declared to be @samp{swap}
+or @samp{export} and the @samp{dump} option is set to a value greater
+than zero. Swap devices should not be dumped.
+
+@item duplicate host @var{hostname}!
+If a host has more than one definition.
+
+@item end of file within comment
+A comment was unterminated before the end of one of the configuration
+files.
+
+@item @var{filename}: cannot open for reading
+If a file specified on the command line as containing configuration data
+could not be opened.
+
+@item @var{filesystem} has a volname but no exportfs data
+Occurs when a volume name is declared for a file system, but the string
+specifying what machines the filesystem can be exported to is
+missing.
+
+@item fs field "@var{field-name}" already set
+Occurs when multiple definitions are given for one of the attributes of a
+host's filesystem.
+
+@item host field "@var{field-name}" already set
+If duplicate definitions are given for any of the fields with a host
+definition.
+
+@item @var{host}:@var{device} has more than one mount point
+Occurs if the mount option for a host's filesystem specifies multiple
+trees at which to place the mountpoint.
+
+@item @var{host}:@var{device} has no mount point
+Occurs if the @samp{mount} option is not specified for a host's
+filesystem.
+
+@item @var{host}:@var{device} needs field "@var{field-name}"
+Occurs when a filesystem is missing a required field. @var{field-name} could
+be one of @samp{fstype}, @samp{opts}, @samp{passno} or
+@samp{mount}.
+
+@item @var{host}:mount field specified for swap partition
+Occurs if a mountpoint is given for a filesystem whose type is declared
+to be @samp{swap}.
+
+@item malformed IP dotted quad: @var{address}
+If the Internet address of an interface is incorrectly specified. An
+Internet address definition is handled to @b{inet_addr}(3N) to see if it
+can cope. If not, then this message will be displayed.
+
+@item malformed netmask: @var{netmask}
+If the netmask cannot be decoded as though it were a hexadecimal number,
+then this message will be displayed. It will typically be caused by
+incorrect characters in the @var{netmask} value.
+
+@item mount field "@var{field-name}" already set
+Occurs when a static mount has multiple definitions of the same field.
+
+@item mount tree field "@var{field-name}" already set
+Occurs when the @var{field-name} is defined more than once during the
+definition of a filesystems mountpoint.
+
+@item netif field @var{field-name} already set
+Occurs if you attempt to define an attribute of an interface more than
+once.
+
+@item network booting requires both root and swap areas
+Occurs if a machine has mount declarations for either the root partition
+or the swap area, but not both. You cannot define a machine to only
+partially boot via the network.
+
+@item no disk mounts on @var{hostname}
+If there are no static mounts, nor local disk mounts specified for a
+machine, this message will be displayed.
+
+@item no volname given for @var{host}:@var{device}
+Occurs when a filesystem is defined to be mounted on @file{default}, but
+no volume name is given for the file system, then the mountpoint cannot
+be determined.
+
+@item not allowed '/' in a directory name
+Occurs when a pathname with multiple directory elements is specified as
+the name for an automounter tree. A tree should only have one name at
+each level.
+
+@item pass number for @var{host}:@var{device} is non-zero
+Occurs if @var{device} has its @samp{fstype} declared to be @samp{swap}
+or @samp{export} and the @b{fsck}(8) pass number is set. Swap devices
+should not be fsck'd. @xref{FSinfo fstype Option}.
+
+@item sub-directory @var{directory} of @var{directory-tree} starts with '/'
+Within the filesystem specification for a host, if an element
+@var{directory} of the mountpoint begins with a @samp{/} and it is not
+the start of the tree.
+
+@item sub-directory of @var{directory-tree} is named "default"
+@samp{default} is a keyword used to specify if a mountpoint should be
+automatically calculated by @i{FSinfo}. If you attempt to specify a
+directory name as this, it will use the filename of @file{default} but
+will produce this warning.
+
+@item unknown \ sequence
+Occurs if an unknown escape sequence is found inside a string. Within a
+string, you can give the standard C escape sequences for strings, such
+as newlines and tab characters.
+
+@item unknown directory attribute
+If an unknown keyword is found while reading the definition of a host's
+filesystem mount option.
+
+@item unknown filesystem attribute
+Occurs if an unrecognized keyword is used when defining a host's
+filesystems.
+
+@item unknown host attribute
+Occurs if an unrecognized keyword is used when defining a host.
+
+@item unknown mount attribute
+Occurs if an unrecognized keyword is found while parsing the list of
+static mounts.
+
+@item unknown volname @var{volume} automounted @i{[} on @i{name} @i{]}
+Occurs if @var{volume} is used in a definition of an automount map but the volume
+name has not been declared during the host filesystem definitions.
+
+@item volname @var{volume} is unknown
+Occurs if an attempt is made to mount or reference a volume name which
+has not been declared during the host filesystem definitions.
+
+@item volname @var{volume} not exported from @var{machine}
+Occurs if you attempt to mount the volume @var{volume} from a machine
+which has not declared itself to have such a filesystem
+available.
+
+@end table
+
+@c ################################################################
+@node Hlfsd, Assorted Tools, FSinfo, Top
+@comment node-name, next, previous, up
+@chapter Hlfsd
+@pindex Hlfsd
+@cindex Home-Link Filesystem
+
+@i{Hlfsd} is a daemon which implements a filesystem containing a
+symbolic link to subdirectory within a user's home directory, depending
+on the user which accessed that link. It was primarily designed to
+redirect incoming mail to users' home directories, so that it can be read
+from anywhere. It was designed and implemented by
+@email{ezk@@cs.columbia.edu,Erez Zadok} and
+@email{dupuy@@cs.columbia.edu,Alexander Dupuy}, at the
+@uref{http://www.cs.columbia.edu/,Computer Science Department} of
+@uref{http://www.columbia.edu/,Columbia University}. A
+@uref{http://www.fsl.cs.sunysb.edu/docs/hlfsd/hlfsd.html,paper}
+on @i{Hlfsd} was presented at the Usenix LISA VII conference in 1993.
+
+@i{Hlfsd} operates by mounting itself as an NFS server for the directory
+containing @i{linkname}, which defaults to @file{/hlfs/home}. Lookups
+within that directory are handled by @i{Hlfsd}, which uses the
+password map to determine how to resolve the lookup. The directory will
+be created if it doesn't already exist. The symbolic link will be to
+the accessing user's home directory, with @i{subdir} appended to it. If
+not specified, @i{subdir} defaults to @file{.hlfsdir}. This directory
+will also be created if it does not already exist.
+
+A @samp{SIGTERM} sent to @i{Hlfsd} will cause it to shutdown. A
+@samp{SIGHUP} will flush the internal caches, and reload the password
+map. It will also close and reopen the log file, to enable the original
+log file to be removed or rotated. A @samp{SIGUSR1} will cause it to
+dump its internal table of user IDs and home directories to the file
+@file{/tmp/hlfsddump}.
+
+@menu
+* Introduction to Hlfsd::
+* Background to Mail Delivery::
+* Using Hlfsd::
+@end menu
+
+@c ================================================================
+@node Introduction to Hlfsd, Background to Mail Delivery, Hlfsd, Hlfsd
+@comment node-name, next, previous, up
+@section Introduction to Hlfsd
+@cindex Introduction to Hlfsd
+@cindex Hlfsd; introduction
+
+Electronic mail has become one of the major applications for many
+computer networks, and use of this service is expected to increase over
+time, as networks proliferate and become faster. Providing a convenient
+environment for users to read, compose, and send electronic mail has
+become a requirement for systems administrators (SAs).
+
+Widely used methods for handling mail usually require users to be logged
+into a designated ``home'' machine, where their mailbox files reside.
+Only on that one machine can they read newly arrived mail. Since users
+have to be logged into that system to read their mail, they often find
+it convenient to run all of their other processes on that system as
+well, including memory and CPU-intensive jobs. For example, in our
+department, we have allocated and configured several multi-processor
+servers to handle such demanding CPU/memory applications, but these were
+underutilized, in large part due to the inconvenience of not being able
+to read mail on those machines. (No home directories were located on
+these designated CPU-servers, since we did not want NFS service for
+users' home directories to have to compete with CPU-intensive jobs. At the
+same time, we discouraged users from running demanding applications on
+their home machines.)
+
+Many different solutions have been proposed to allow users to read their
+mail on any host. However, all of these solutions fail in one or more
+of several ways:
+
+@itemize @bullet
+
+@item
+they introduce new single points of failure
+
+@item
+they require using different mail transfer agents (MTAs) or user agents
+(UAs)
+
+@item
+they do not solve the problem for all cases, i.e. the solution is only
+partially successful for a particular environment.
+
+@end itemize
+
+We have designed a simple filesystem, called the @dfn{Home-Link File
+System}, to provide the ability to deliver mail to users' home
+directories, without modification to mail-related applications. We have
+endeavored to make it as stable as possible. Of great importance to us
+was to make sure the HLFS daemon, @file{hlfsd} , would not hang under
+any circumstances, and would take the next-best action when faced with
+problems. Compared to alternative methods, @i{Hlfsd} is a stable, more
+general solution, and easier to install/use. In fact, in some ways, we
+have even managed to improve the reliability and security of mail
+service.
+
+Our server implements a small filesystem containing a symbolic link
+to a subdirectory of the invoking user's home directory, and named symbolic
+links to users' mailbox files.
+
+The @i{Hlfsd} server finds out the @var{uid} of the process that is
+accessing its mount point, and resolves the pathname component @samp{home} as a
+symbolic link to a subdirectory within the home directory given by the
+@var{uid}'s entry in the password file. If the @var{gid} of the process
+that attempts to access a mailbox file is a special one (called
+HLFS_GID), then the server maps the name of the @emph{next} pathname
+component directly to the user's mailbox. This is necessary so that
+access to a mailbox file by users other than the owner can succeed. The
+server has safety features in case of failures such as hung filesystems
+or home directory filesystems that are inaccessible or full.
+
+On most of our machines, mail gets delivered to the directory
+@file{/var/spool/mail}. Many programs, including UAs, depend on that
+path. @i{Hlfsd} creates a directory @file{/mail}, and mounts itself on
+top of that directory. @i{Hlfsd} implements the path name component
+called @samp{home}, pointing to a subdirectory of the user's home directory.
+We have made @file{/var/spool/mail} a symbolic link to
+@file{/mail/home}, so that accessing @file{/var/spool/mail} actually
+causes access to a subdirectory within a user's home directory.
+
+The following table shows an example of how resolving the pathname
+@file{/var/mail/@i{NAME}} to @file{/users/ezk/.mailspool/@i{NAME}} proceeds.
+
+@multitable {Resolving Component} {Pathname left to resolve} {Value if symbolic link}
+
+@item @b{Resolving Component}
+@tab @b{Pathname left to resolve}
+@tab @b{Value if symbolic link}
+
+@item @t{/}
+@tab @t{var/mail/}@i{NAME}
+
+@item @t{var/}
+@tab @t{mail/}@i{NAME}
+
+@item @t{mail}@@
+@tab @t{/mail/home/}@i{NAME}
+@tab @t{mail}@@ -> @t{/mail/home}
+
+@item @t{/}
+@tab @t{mail/home/}@i{NAME}
+
+@item @t{mail/}
+@tab @t{home/}@i{NAME}
+
+@item @t{home}@@
+@tab @i{NAME}
+@tab @t{home}@@ -> @t{/users/ezk/.mailspool}
+
+@item @t{/}
+@tab @t{users/ezk/.mailspool/}@i{NAME}
+
+@item @t{users/}
+@tab @t{ezk/.mailspool/}@i{NAME}
+
+@item @t{ezk/}
+@tab @t{.mailspool/}@i{NAME}
+
+@item @t{.mailspool/}
+@tab @i{NAME}
+
+@item @i{NAME}
+
+@end multitable
+
+@c ================================================================
+@node Background to Mail Delivery, Using Hlfsd, Introduction to Hlfsd, Hlfsd
+@comment node-name, next, previous, up
+@section Background to Mail Delivery
+@cindex Background to Mail Delivery
+@cindex Hlfsd; background
+
+This section provides an in-depth discussion of why available methods
+for delivering mail to home directories are not as good as the one used
+by @i{Hlfsd}.
+
+@menu
+* Single-Host Mail Spool Directory::
+* Centralized Mail Spool Directory::
+* Distributed Mail Spool Service::
+* Why Deliver Into the Home Directory?::
+@end menu
+
+@c ----------------------------------------------------------------
+@node Single-Host Mail Spool Directory, Centralized Mail Spool Directory, Background to Mail Delivery, Background to Mail Delivery
+@comment node-name, next, previous, up
+@subsection Single-Host Mail Spool Directory
+@cindex Single-Host Mail Spool Directory
+
+The most common method for mail delivery is for mail to be appended to a
+mailbox file in a standard spool directory on the designated ``mail
+home'' machine of the user. The greatest advantage of this method is
+that it is the default method most vendors provide with their systems,
+thus very little (if any) configuration is required on the SA's part.
+All they need to set up are mail aliases directing mail to the host on
+which the user's mailbox file is assigned. (Otherwise, mail is
+delivered locally, and users find mailboxes on many machines.)
+
+As users become more sophisticated, and aided by windowing systems, they
+find themselves logging in on multiple hosts at once, performing several
+tasks concurrently. They ask to be able to read their mail on any host
+on the network, not just the one designated as their ``mail home''.
+
+@c ----------------------------------------------------------------
+@node Centralized Mail Spool Directory, Distributed Mail Spool Service, Single-Host Mail Spool Directory, Background to Mail Delivery
+@comment node-name, next, previous, up
+@subsection Centralized Mail Spool Directory
+@cindex Centralized Mail Spool Directory
+
+A popular method for providing mail readability from any host is to have
+all mail delivered to a mail spool directory on a designated
+``mail-server'' which is exported via NFS to all of the hosts on the
+network. Configuring such a system is relatively easy. On most
+systems, the bulk of the work is a one-time addition to one or two
+configuration files in @file{/etc}. The file-server's spool directory
+is then hard-mounted across every machine on the local network. In
+small environments with only a handful of hosts this can be an
+acceptable solution. In our department, with a couple of hundred active
+hosts and thousands of mail messages processed daily, this was deemed
+completely unacceptable, as it introduced several types of problems:
+
+@table @b
+
+@item Scalability and Performance
+
+As more and more machines get added to the network, more mail traffic
+has to go over NFS to and from the mail-server. Users like to run
+mail-watchers, and read their mail often. The stress on the shared
+infrastructure increases with every user and host added; loads on the
+mail server would most certainly be high since all mail delivery goes
+through that one machine.@footnote{ Delivery via NFS-mounted filesystems
+may require usage of @samp{rpc.lockd} and @samp{rpc.statd} to provide
+distributed file-locking, both of which are widely regarded as unstable
+and unreliable. Furthermore, this will degrade performance, as local
+processes as well as remote @samp{nfsd} processes are kept busy.} This
+leads to lower reliability and performance. To reduce the number of
+concurrent connections between clients and the server host, some SAs
+have resorted to automounting the mail-spool directory. But this
+solution only makes things worse: since users often run mail watchers,
+and many popular applications such as @samp{trn}, @samp{emacs},
+@samp{csh} or @samp{ksh} check periodically for new mail, the
+automounted directory would be effectively permanently mounted. If it
+gets unmounted automatically by the automounter program, it is most
+likely to get mounted shortly afterwards, consuming more I/O resources
+by the constant cycle of mount and umount calls.
+
+@item Reliability
+
+The mail-server host and its network connectivity must be very reliable.
+Worse, since the spool directory has to be hard-mounted,@footnote{No SA
+in their right minds would soft-mount read/write partitions --- the
+chances for data loss are too great.} many processes which access the
+spool directory (various shells, @samp{login}, @samp{emacs}, etc.)
+would be hung as long as connectivity to the mail-server is severed. To
+improve reliability, SAs may choose to backup the mail-server's spool
+partition several times a day. This may make things worse since reading
+or delivering mail while backups are in progress may cause backups to be
+inconsistent; more backups consume more backup-media resources, and
+increase the load on the mail-server host.
+
+@end table
+
+@c ----------------------------------------------------------------
+@node Distributed Mail Spool Service, Why Deliver Into the Home Directory?, Centralized Mail Spool Directory, Background to Mail Delivery
+@comment node-name, next, previous, up
+@subsection Distributed Mail Spool Service
+@cindex Distributed Mail Spool Service
+
+Despite the existence of a few systems that support delivery to users'
+home directories, mail delivery to home directories hasn't caught on.
+We believe the main reason is that there are too many programs that
+``know'' where mailbox files reside. Besides the obvious (the delivery
+program @file{/bin/mail} and mail readers like @file{/usr/ucb/Mail},
+@samp{mush}, @samp{mm}, etc.), other programs that know mailbox location
+are login, from, almost every shell, @samp{xbiff}, @samp{xmailbox}, and
+even some programs not directly related to mail, such as @samp{emacs}
+and @samp{trn}. Although some of these programs can be configured to
+look in different directories with the use of environment variables and
+other resources, many of them cannot. The overall porting work is
+significant.
+
+Other methods that have yet to catch on require the use of a special
+mail-reading server, such as IMAP or POP. The main disadvantage of
+these systems is that UAs need to be modified to use these services ---
+a long and involved task. That is why they are not popular at this
+time.
+
+Several other ideas have been proposed and even used in various
+environments. None of them is robust. They are mostly very
+specialized, inflexible, and do not extend to the general case. Some of
+the ideas are plain bad, potentially leading to lost or corrupt mail:
+
+@table @b
+
+@item automounters
+
+Using an automounter such as @i{Amd} to provide a set of symbolic links
+from the normal spool directory to user home directories is not
+sufficient. UAs rename, unlink, and recreate the mailbox as a regular
+file, therefore it must be a real file, not a symbolic link.
+Furthermore, it must reside in a real directory which is writable by the
+UAs and MTAs. This method may also require populating
+@file{/var/spool/mail} with symbolic links and making sure they are
+updated. Making @i{Amd} manage that directory directly fails, since
+many various lock files need to be managed as well. Also, @i{Amd} does
+not provide all of the NFS operations which are required to write mail
+such as write, create, remove, and unlink.
+
+@item @code{$MAIL}
+
+Setting this variable to an automounted directory pointing to the user's
+mail spool host only solves the problem for those programs which know
+and use @code{$MAIL}. Many programs don't, therefore this solution is partial
+and of limited flexibility. Also, it requires the SAs or the users to
+set it themselves --- an added level of inconvenience and possible
+failures.
+
+@item @t{/bin/mail}
+
+Using a different mail delivery agent could be the solution. One such
+example is @samp{hdmail}. However, @samp{hdmail} still requires
+modifying all UAs, the MTA's configuration, installing new daemons, and
+changing login scripts. This makes the system less upgradable or
+compatible with others, and adds one more complicated system for SAs to
+deal with. It is not a complete solution because it still requires each
+user have their @code{$MAIL} variable setup correctly, and that every program
+use this variable.
+
+@end table
+
+@c ----------------------------------------------------------------
+@node Why Deliver Into the Home Directory?, , Distributed Mail Spool Service, Background to Mail Delivery
+@comment node-name, next, previous, up
+@subsection Why Deliver Into the Home Directory?
+@cindex Why Deliver Into the Home Directory?
+@cindex Hlfsd; Why Deliver Into the Home Directory?
+
+There are several major reasons why SAs might want to deliver mail
+directly into the users' home directories:
+
+@table @b
+
+@item Location
+
+Many mail readers need to move mail from the spool directory to the
+user's home directory. It speeds up this operation if the two are on
+the same filesystem. If for some reason the user's home directory is
+inaccessible, it isn't that useful to be able to read mail, since there
+is no place to move it to. In some cases, trying to move mail to a
+non-existent or hung filesystem may result in mail loss.
+
+@item Distribution
+
+Having all mail spool directories spread among the many more filesystems
+minimizes the chances that complete environments will grind to a halt
+when a single server is down. It does increase the chance that there
+will be someone who is not able to read their mail when a machine is
+down, but that is usually preferred to having no one be able to read
+their mail because a centralized mail server is down. The problem of
+losing some mail due to the (presumably) higher chances that a user's
+machine is down is minimized in HLFS.
+
+@item Security
+
+Delivering mail to users' home directories has another advantage ---
+enhanced security and privacy. Since a shared system mail spool
+directory has to be world-readable and searchable, any user can see
+whether other users have mail, when they last received new mail, or when
+they last read their mail. Programs such as @samp{finger} display this
+information, which some consider an infringement of privacy. While it
+is possible to disable this feature of @samp{finger} so that remote
+users cannot see a mailbox file's status, this doesn't prevent local
+users from getting the information. Furthermore, there are more
+programs which make use of this information. In shared environments,
+disabling such programs has to be done on a system-wide basis, but with
+mail delivered to users' home directories, users less concerned with
+privacy who do want to let others know when they last received or read
+mail can easily do so using file protection bits.
+
+@c Lastly, on systems that do not export their NFS filesystem with
+@c @t{anon=0}, superusers are less likely to snoop around others' mail, as
+@c they become ``nobodies'' across NFS.
+
+@end table
+
+In summary, delivering mail to home directories provides users the
+functionality sought, and also avoids most of the problems just
+discussed.
+
+@c ================================================================
+@node Using Hlfsd, , Background to Mail Delivery, Hlfsd
+@comment node-name, next, previous, up
+@section Using Hlfsd
+@cindex Using Hlfsd
+@cindex Hlfsd; using
+
+@menu
+* Controlling Hlfsd::
+* Hlfsd Options::
+* Hlfsd Files::
+@end menu
+
+@c ----------------------------------------------------------------
+@node Controlling Hlfsd, Hlfsd Options, Using Hlfsd, Using Hlfsd
+@comment node-name, next, previous, up
+@subsection Controlling Hlfsd
+@cindex Controlling Hlfsd
+@cindex Hlfsd; controlling
+@pindex ctl-hlfsd
+
+Much the same way @i{Amd} is controlled by @file{ctl-amd}, so does
+@i{Hlfsd} get controlled by the @file{ctl-hlfsd} script:
+
+@table @t
+
+@item ctl-hlfsd start
+Start a new @i{Hlfsd}.
+
+@item ctl-hlfsd stop
+Stop a running @i{Hlfsd}.
+
+@item ctl-hlfsd restart
+Stop a running @i{Hlfsd}, wait for 10 seconds, and then start a new
+one. It is hoped that within 10 seconds, the previously running
+@i{Hlfsd} terminate properly; otherwise, starting a second one could
+cause system lockup.
+
+@end table
+
+For example, on our systems, we start @i{Hlfsd} within @file{ctl-hlfsd}
+as follows on Solaris 2 systems:
+
+@example
+hlfsd -a /var/alt_mail -x all -l /var/log/hlfsd /mail/home .mailspool
+@end example
+
+The directory @file{/var/alt_mail} is a directory in the root partition
+where alternate mail will be delivered into, when it cannot be delivered
+into the user's home directory.
+
+Normal mail gets delivered into @file{/var/mail}, but on our systems,
+that is a symbolic link to @file{/mail/home}. @file{/mail} is managed
+by @i{Hlfsd}, which creates a dynamic symlink named @samp{home},
+pointing to the subdirectory @file{.mailspool} @emph{within} the
+accessing user's home directory. This results in mail which normally
+should go to @file{/var/mail/@code{$USER}}, to go to
+@file{@code{$HOME}/.mailspool/@code{$USER}}.
+
+@i{Hlfsd} does not create the @file{/var/mail} symlink. This needs to
+be created (manually) once on each host, by the system administrators,
+as follows:
+
+@example
+mv /var/mail /var/alt_mail
+ln -s /mail/home /var/mail
+@end example
+
+@i{Hlfsd} also responds to the following signals:
+
+A @samp{SIGHUP} signal sent to @i{Hlfsd} will force it to reload the
+password map immediately.
+
+A @samp{SIGUSR1} signal sent to @i{Hlfsd} will cause it to dump its
+internal password map to the file @file{/usr/tmp/hlfsd.dump.XXXXXX},
+where @samp{XXXXXX} will be replaced by a random string generated by
+@b{mktemp}(3) or (the more secure) @b{mkstemp}(3).
+
+@c ----------------------------------------------------------------
+@node Hlfsd Options, Hlfsd Files, Controlling Hlfsd, Using Hlfsd
+@comment node-name, next, previous, up
+@subsection Hlfsd Options
+@cindex Hlfsd Options
+@cindex Hlfsd; Options
+
+@table @t
+
+@item -a @var{alt_dir}
+Alternate directory. The name of the directory to which the symbolic
+link returned by @i{Hlfsd} will point, if it cannot access the home
+directory of the user. This defaults to @file{/var/hlfs}. This
+directory will be created if it doesn't exist. It is expected that
+either users will read these files, or the system administrators will
+run a script to resend this ``lost mail'' to its owner.
+
+@item -c @var{cache-interval}
+Caching interval. @i{Hlfsd} will cache the validity of home directories
+for this interval, in seconds. Entries which have been verified within
+the last @var{cache-interval} seconds will not be verified again, since
+the operation could be expensive, and the entries are most likely still
+valid. After the interval has expired, @i{Hlfsd} will re-verify the
+validity of the user's home directory, and reset the cache time-counter.
+The default value for @var{cache-interval} is 300 seconds (5 minutes).
+
+@item -f
+Force fast startup. This option tells @i{Hlfsd} to skip startup-time
+consistency checks such as existence of mount directory, alternate spool
+directory, symlink to be hidden under the mount directory, their
+permissions and validity.
+
+@item -g @var{group}
+Set the special group HLFS_GID to @var{group}. Programs such as
+@file{/usr/ucb/from} or @file{/usr/sbin/in.comsat}, which access the
+mailboxes of other users, must be setgid @samp{HLFS_GID} to work properly. The
+default group is @samp{hlfs}. If no group is provided, and there is no
+group @samp{hlfs}, this feature is disabled.
+
+@item -h
+Help. Print a brief help message, and exit.
+
+@item -i @var{reload-interval}
+Map-reloading interval. Each @var{reload-interval} seconds, @i{Hlfsd}
+will reload the password map. @i{Hlfsd} needs the password map for the
+UIDs and home directory pathnames. @i{Hlfsd} schedules a @samp{SIGALRM} to
+reload the password maps. A @samp{SIGHUP} sent to @i{Hlfsd} will force it to
+reload the maps immediately. The default value for
+@var{reload-interval} is 900 seconds (15 minutes.)
+
+@item -l @var{logfile}
+Specify a log file to which @i{Hlfsd} will record events. If
+@var{logfile} is the string @samp{syslog} then the log messages will be
+sent to the system log daemon by @b{syslog}(3), using the @samp{LOG_DAEMON}
+facility. This is also the default.
+
+@item -n
+No verify. @i{Hlfsd} will not verify the validity of the symbolic link
+it will be returning, or that the user's home directory contains
+sufficient disk-space for spooling. This can speed up @i{Hlfsd} at the
+cost of possibly returning symbolic links to home directories which are
+not currently accessible or are full. By default, @i{Hlfsd} validates
+the symbolic-link in the background. The @code{-n} option overrides the
+meaning of the @code{-c} option, since no caching is necessary.
+
+@item -o @var{mount-options}
+Mount options which @i{Hlfsd} will use to mount itself on top of
+@var{dirname}. By default, @var{mount-options} is set to @samp{ro}. If
+the system supports symbolic-link caching, default options are set
+to @samp{ro,nocache}.
+
+@item -p
+Print PID. Outputs the process-id of @i{Hlfsd} to standard output where
+it can be saved into a file.
+
+@item -v
+Version. Displays version information to standard error.
+
+@item -x @var{log-options}
+Specify run-time logging options. The options are a comma separated
+list chosen from: @samp{fatal}, @samp{error}, @samp{user}, @samp{warn}, @samp{info}, @samp{map}, @samp{stats}, @samp{all}.
+
+@item -C
+Force @i{Hlfsd} to run on systems that cannot turn off the NFS
+attribute-cache. Use of this option on those systems is discouraged, as
+it may result in loss or misdelivery of mail. The option is ignored on
+systems that can turn off the attribute-cache.
+
+@item -D @var{log-options}
+Select from a variety of debugging options. Prefixing an option with
+the string @samp{no} reverses the effect of that option. Options are
+cumulative. The most useful option is @samp{all}. Since this option is
+only used for debugging other options are not documented here. A fuller
+description is available in the program source.
+
+@item -P @var{password-file}
+Read the user-name, user-id, and home directory information from the
+file @var{password-file}. Normally, @i{Hlfsd} will use @b{getpwent}(3)
+to read the password database. This option allows you to override the
+default database, and is useful if you want to map users' mail files to
+a directory other than their home directory. Only the username, uid,
+and home-directory fields of the file @var{password-file} are read and
+checked. All other fields are ignored. The file @var{password-file}
+must otherwise be compliant with Unix Version 7 colon-delimited format
+@b{passwd}(4).
+
+@end table
+
+@c ----------------------------------------------------------------
+@node Hlfsd Files, , Hlfsd Options, Using Hlfsd
+@comment node-name, next, previous, up
+@subsection Hlfsd Files
+@cindex Hlfsd Files
+@cindex Hlfsd; Files
+
+The following files are used by @i{Hlfsd}:
+
+@table @file
+
+@item /hlfs
+directory under which @i{Hlfsd} mounts itself and manages the symbolic
+link @file{home}.
+
+@item .hlfsdir
+default sub-directory in the user's home directory, to which the
+@file{home} symbolic link returned by @i{Hlfsd} points.
+
+@item /var/hlfs
+directory to which @file{home} symbolic link returned by @i{Hlfsd}
+points if it is unable to verify the that user's home directory is
+accessible.
+
+@item /usr/tmp/hlfsd.dump.XXXXXX
+file to which @i{Hlfsd} will dump its internal password map when it
+receives the @samp{SIGUSR1} signal. @samp{XXXXXX} will be replaced by
+a random string generated by @b{mktemp}(3) or (the more secure)
+@b{mkstemp}(3).
+
+@end table
+
+For discussion on other files used by @i{Hlfsd}, see @xref{lostaltmail}, and
+@ref{lostaltmail.conf-sample}.
+
+@c ################################################################
+@node Assorted Tools, Examples, Hlfsd, Top
+@comment node-name, next, previous, up
+@chapter Assorted Tools
+@cindex Assorted Tools
+
+The following are additional utilities and scripts included with
+am-utils, and get installed.
+
+@menu
+* am-eject::
+* amd.conf-sample::
+* amd2ldif::
+* amd2sun::
+* automount2amd::
+* ctl-amd::
+* ctl-hlfsd::
+* expn::
+* fix-amd-map::
+* fixmount::
+* fixrmtab::
+* lostaltmail::
+* lostaltmail.conf-sample::
+* mk-amd-map::
+* pawd::
+* redhat-ctl-amd::
+* wait4amd::
+* wait4amd2die::
+* wire-test::
+@end menu
+
+@c ----------------------------------------------------------------
+@node am-eject, amd.conf-sample, Assorted Tools, Assorted Tools
+@comment node-name, next, previous, up
+@section am-eject
+@pindex am-eject
+
+A shell script unmounts a floppy or CD-ROM that is automounted, and
+then attempts to eject the removable device.
+
+@c ----------------------------------------------------------------
+@node amd.conf-sample, amd2ldif, am-eject, Assorted Tools
+@comment node-name, next, previous, up
+@section amd.conf-sample
+@pindex amd.conf-sample
+
+A sample @i{Amd} configuration file. @xref{Amd Configuration File}.
+
+@c ----------------------------------------------------------------
+@node amd2ldif, amd2sun, amd.conf-sample, Assorted Tools
+@comment node-name, next, previous, up
+@section amd2ldif
+@pindex amd2ldif
+
+A script to convert @i{Amd} maps to LDAP input files. Use it as follows:
+
+@example
+amd2ldif @i{mapname} @i{base} < @i{amd.mapfile} > @i{mapfile.ldif}
+@end example
+
+@c ----------------------------------------------------------------
+@node amd2sun, automount2amd, amd2ldif, Assorted Tools
+@comment node-name, next, previous, up
+@section amd2sun
+@pindex amd2sun
+
+A script to convert @i{Amd} maps to Sun Automounter maps. Use it as
+follows
+
+@example
+amd2sun < @i{amd.mapfile} > @i{auto_mapfile}
+@end example
+
+@c ----------------------------------------------------------------
+@node automount2amd, ctl-amd, amd2sun, Assorted Tools
+@comment node-name, next, previous, up
+@section automount2amd
+@pindex automount2amd
+
+A script to convert old Sun Automounter maps to @i{Amd} maps.
+
+Say you have the Sun automount file @i{auto.foo}, with these two lines:
+@example
+home earth:/home
+moon -ro,intr server:/proj/images
+@end example
+Running
+@example
+automount2amd auto.foo > amd.foo
+@end example
+
+will produce the @i{Amd} map @i{amd.foo} with this content:
+
+@example
+# generated by automount2amd on Sat Aug 14 17:59:32 US/Eastern 1999
+
+/defaults \\
+ type:=nfs;opts:=rw,grpid,nosuid,utimeout=600
+
+home \
+ host==earth;type:=link;fs:=/home \\
+ rhost:=earth;rfs:=/home
+
+moon \
+ -addopts:=ro,intr \\
+ host==server;type:=link;fs:=/proj/images \\
+ rhost:=server;rfs:=/proj/images
+@end example
+
+This perl script will use the following @i{/default} entry
+@example
+type:=nfs;opts:=rw,grpid,nosuid,utimeout=600
+@end example
+If you wish to override that, define the @b{$DEFAULTS} environment
+variable, or modify the script.
+
+If you wish to generate Amd maps using the @i{hostd} (@pxref{hostd
+Selector Variable}) @i{Amd} map syntax, then define the environment
+variable @b{$DOMAIN} or modify the script.
+
+Note that automount2amd does not understand the syntax in newer Sun
+Automount maps, those used with autofs.
+
+@c ----------------------------------------------------------------
+@node ctl-amd, ctl-hlfsd, automount2amd, Assorted Tools
+@comment node-name, next, previous, up
+@section ctl-amd
+@pindex ctl-amd
+
+A script to start, stop, or restart @i{Amd}. Use it as follows:
+
+@table @t
+@item ctl-amd start
+Start a new @i{Amd} process.
+@item ctl-amd stop
+Stop the running @i{Amd}.
+@item ctl-amd restart
+Stop the running @i{Amd} (if any), safely wait for it to terminate, and
+then start a new process --- only if the previous one died cleanly.
+@end table
+
+@xref{Run-time Administration}, for more details.
+
+@c ----------------------------------------------------------------
+@node ctl-hlfsd, expn, ctl-amd, Assorted Tools
+@comment node-name, next, previous, up
+@section ctl-hlfsd
+@pindex ctl-hlfsd
+
+A script for controlling @i{Hlfsd}, much the same way @file{ctl-amd}
+controls @i{Amd}. Use it as follows:
+
+@table @t
+@item ctl-hlfsd start
+Start a new @i{Hlfsd} process.
+@item ctl-hlfsd stop
+Stop the running @i{Hlfsd}.
+@item ctl-hlfsd restart
+Stop the running @i{Hlfsd} (if any), wait for 10 seconds for it to
+terminate, and then start a new process --- only if the previous one
+died cleanly.
+@end table
+
+@xref{Hlfsd}, for more details.
+
+@c ----------------------------------------------------------------
+@node expn, fix-amd-map, ctl-hlfsd, Assorted Tools
+@comment node-name, next, previous, up
+@section expn
+@pindex expn
+
+A script to expand email addresses into their full name. It is
+generally useful when using with the @file{lostaltmail} script, but is a
+useful tools otherwise.
+
+@example
+$ expn -v ezk@@cs.columbia.edu
+ezk@@cs.columbia.edu ->
+ ezk@@shekel.mcl.cs.columbia.edu
+ezk@@shekel.mcl.cs.columbia.edu ->
+ Erez Zadok <"| /usr/local/mh/lib/slocal -user ezk || exit 75>
+ Erez Zadok <\ezk>
+ Erez Zadok </u/zing/ezk/.mailspool/backup>
+@end example
+
+@c ----------------------------------------------------------------
+@node fix-amd-map, fixmount, expn, Assorted Tools
+@comment node-name, next, previous, up
+@section fix-amd-map
+@pindex fix-amd-map
+
+Am-utils changed some of the syntax and default values of some
+variables. For example, the default value for @samp{$@{os@}} for
+Solaris 2.x (aka SunOS 5.x) systems used to be @samp{sos5}, it is now
+more automatically generated from @file{config.guess} and its value is
+@samp{sunos5}.
+
+This script converts older @i{Amd} maps to new ones. Use it as follows:
+
+@example
+fix-amd-map < @i{old.map} > @i{new.map}
+@end example
+
+@c ----------------------------------------------------------------
+@node fixmount, fixrmtab, fix-amd-map, Assorted Tools
+@comment node-name, next, previous, up
+@section fixmount
+@pindex fixmount
+
+@samp{fixmount} is a variant of @b{showmount}(8) that can delete bogus
+mount entries in remote @b{mountd}(8) daemons. This is useful to
+cleanup otherwise ever-accumulating ``junk''. Use it for example:
+
+@example
+fixmount -r @i{host}
+@end example
+
+See the online manual page for @samp{fixmount} for more details of its
+usage.
+
+@c ----------------------------------------------------------------
+@node fixrmtab, lostaltmail, fixmount, Assorted Tools
+@comment node-name, next, previous, up
+@section fixrmtab
+@pindex fixrmtab
+
+A script to invalidate @file{/etc/rmtab} entries for hosts named. Also
+restart mountd for changes to take effect. Use it for example:
+
+@example
+fixrmtab @i{host1} @i{host2} @i{...}
+@end example
+
+@c ----------------------------------------------------------------
+@node lostaltmail, lostaltmail.conf-sample, fixrmtab, Assorted Tools
+@comment node-name, next, previous, up
+@section lostaltmail
+@pindex lostaltmail
+
+A script used with @i{Hlfsd} to resend any ``lost'' mail. @i{Hlfsd}
+redirects mail which cannot be written into the user's home directory to
+an alternate directory. This is useful to continue delivering mail,
+even if the user's file system was unavailable, full, or over quota.
+But, the mail which gets delivered to the alternate directory needs to
+be resent to its respective users. This is what the @samp{lostaltmail}
+script does.
+
+Use it as follows:
+
+@example
+lostaltmail
+@end example
+
+This script needs a configuration file @samp{lostaltmail.conf} set up
+with the right parameters to properly work. @xref{Hlfsd}, for more
+details.
+
+@c ----------------------------------------------------------------
+@node lostaltmail.conf-sample, mk-amd-map, lostaltmail, Assorted Tools
+@comment node-name, next, previous, up
+@section lostaltmail.conf-sample
+@pindex lostaltmail.conf-sample
+@cindex lostaltmail; configuration file
+
+This is a text file with configuration parameters needed for the
+@samp{lostaltmail} script. The script includes comments explaining each
+of the configuration variables. See it for more information. Also
+@pxref{Hlfsd} for general information.
+
+@c ----------------------------------------------------------------
+@node mk-amd-map, pawd, lostaltmail.conf-sample, Assorted Tools
+@comment node-name, next, previous, up
+@section mk-amd-map
+@pindex mk-amd-map
+
+This program converts a normal @i{Amd} map file into an ndbm database
+with the same prefix as the named file. Use it as follows:
+
+@example
+mk-amd-map @i{mapname}
+@end example
+
+@c ----------------------------------------------------------------
+@node pawd, redhat-ctl-amd, mk-amd-map, Assorted Tools
+@comment node-name, next, previous, up
+@section pawd
+@pindex pawd
+
+@i{Pawd} is used to print the current working directory, adjusted to
+reflect proper paths that can be reused to go through the automounter
+for the shortest possible path. In particular, the path printed back
+does not include any of @i{Amd}'s local mount points. Using them is
+unsafe, because @i{Amd} may unmount managed file systems from the mount
+points, and thus including them in paths may not always find the files
+within.
+
+Without any arguments, @i{Pawd} will print the automounter adjusted
+current working directory. With any number of arguments, it will print
+the adjusted path of each one of the arguments.
+
+@c ----------------------------------------------------------------
+@node redhat-ctl-amd, wait4amd, pawd, Assorted Tools
+@comment node-name, next, previous, up
+@section redhat-ctl-amd
+@pindex redhat-ctl-amd
+
+This script is similar to @i{ctl-amd} (@pxref{ctl-amd}) but is intended
+for Red Hat Linux systems. You can safely copy @i{redhat-ctl-amd} onto
+@file{/etc/rc.d/init.d/amd}. The script supplied by @i{Am-utils} is
+usually better than the one provided by Red Hat, because the Red Hat
+script does not correctly kill @i{Amd} processes: it is too quick to
+kill the wrong processes, leaving stale or hung mount points behind.
+
+@c ----------------------------------------------------------------
+@node wait4amd, wait4amd2die, redhat-ctl-amd, Assorted Tools
+@comment node-name, next, previous, up
+@section wait4amd
+@pindex wait4amd
+
+A script to wait for @i{Amd} to start on a particular host before
+performing an arbitrary command. The command is executed repeatedly,
+with 1 second intervals in between. You may interrupt the script using
+@samp{^C} (or whatever keyboard sequence your terminal's @samp{intr} function
+is bound to).
+
+Examples:
+
+@table @t
+@item wait4amd saturn amq -p -h saturn
+When @i{Amd} is up on host @samp{saturn}, get the process ID of that
+running @i{Amd}.
+@item wait4amd pluto rlogin pluto
+Remote login to host @samp{pluto} when @i{Amd} is up on that host. It
+is generally necessary to wait for @i{Amd} to properly start and
+initialize on a remote host before logging in to it, because otherwise
+user home directories may not be accessible across the network.
+@item wait4amd pluto
+A short-hand version of the previous command, since the most useful
+reason for this script is to login to a remote host. I use it very
+often when testing out new versions of @i{Amd}, and need to reboot hung
+hosts.
+@end table
+
+@c ----------------------------------------------------------------
+@node wait4amd2die, wire-test, wait4amd, Assorted Tools
+@comment node-name, next, previous, up
+@section wait4amd2die
+@pindex wait4amd2die
+
+This script is used internally by @samp{ctl-amd} when used to restart
+@i{Amd}. It waits for @i{Amd} to terminate. If it detected that
+@i{Amd} terminated cleanly, this script will return an exist status of
+zero. Otherwise, it will return a non-zero exit status.
+
+The script tests for @i{Amd}'s existence once every 5 seconds, six
+times, for a total of 30 seconds. It will return a zero exist status as
+soon as it detects that @i{Amd} dies.
+
+@c ----------------------------------------------------------------
+@node wire-test, , wait4amd2die, Assorted Tools
+@comment node-name, next, previous, up
+@section wire-test
+@pindex wire-test
+
+A simple program to test if some of the most basic networking functions
+in am-util's library @file{libamu} work. It also tests the combination
+of NFS protocol and version number that are supported from the current
+host, to a remote one.
+
+For example, in this test a machine which only supports NFS Version 2 is
+contacting a remote host that can support the same version, but using
+both UDP and TCP. If no host name is specified, @samp{wire-test} will
+try @file{localhost}.
+
+@example
+$ wire-test moisil
+Network name is "mcl-lab-net.cs.columbia.edu"
+Network number is "128.59.13"
+Network name is "old-net.cs.columbia.edu"
+Network number is "128.59.16"
+My IP address is 0x7f000001.
+NFS Version and protocol tests to host "moisil"...
+ testing vers=2, proto="udp" -> found version 2.
+ testing vers=3, proto="udp" -> failed!
+ testing vers=2, proto="tcp" -> found version 2.
+ testing vers=3, proto="tcp" -> failed!
+@end example
+
+@c ################################################################
+@node Examples, Internals, Assorted Tools, Top
+@comment node-name, next, previous, up
+@chapter Examples
+
+@menu
+* User Filesystems::
+* Home Directories::
+* Architecture Sharing::
+* Wildcard Names::
+* rwho servers::
+* /vol::
+* /defaults with selectors::
+* /tftpboot in a chroot-ed environment::
+
+@end menu
+
+@node User Filesystems, Home Directories, Examples, Examples
+@comment node-name, next, previous, up
+@section User Filesystems
+@cindex User filesystems
+@cindex Mounting user filesystems
+
+With more than one fileserver, the directories most frequently
+cross-mounted are those containing user home directories. A common
+convention used at Imperial College is to mount the user disks under
+@t{/home/}@i{machine}.
+
+Typically, the @samp{/etc/fstab} file contained a long list of entries
+such as:
+
+@example
+@i{machine}:/home/@i{machine} /home/@i{machine} nfs ...
+@end example
+
+for each fileserver on the network.
+
+There are numerous problems with this system. The mount list can become
+quite large and some of the machines may be down when a system is
+booted. When a new fileserver is installed, @samp{/etc/fstab} must be
+updated on every machine, the mount directory created and the filesystem
+mounted.
+
+In many environments most people use the same few workstations, but
+it is convenient to go to a colleague's machine and access your own
+files. When a server goes down, it can cause a process on a client
+machine to hang. By minimizing the mounted filesystems to only include
+those actively being used, there is less chance that a filesystem will
+be mounted when a server goes down.
+
+The following is a short extract from a map taken from a research fileserver
+at Imperial College.
+
+Note the entry for @samp{localhost} which is used for users such as
+the operator (@samp{opr}) who have a home directory on most machine as
+@samp{/home/localhost/opr}.
+
+@example
+/defaults opts:=rw,intr,grpid,nosuid
+charm host!=$@{key@};type:=nfs;rhost:=$@{key@};rfs:=/home/$@{key@} \
+ host==$@{key@};type:=ufs;dev:=/dev/xd0g
+#
+...
+
+#
+localhost type:=link;fs:=$@{host@}
+...
+#
+# dylan has two user disks so have a
+# top directory in which to mount them.
+#
+dylan type:=auto;fs:=$@{map@};pref:=$@{key@}/
+#
+dylan/dk2 host!=dylan;type:=nfs;rhost:=dylan;rfs:=/home/$@{key@} \
+ host==dylan;type:=ufs;dev:=/dev/dsk/2s0
+#
+dylan/dk5 host!=dylan;type:=nfs;rhost:=dylan;rfs:=/home/$@{key@} \
+ host==dylan;type:=ufs;dev:=/dev/dsk/5s0
+...
+#
+toytown host!=$@{key@};type:=nfs;rhost:=$@{key@};rfs:=/home/$@{key@} \
+ host==$@{key@};type:=ufs;dev:=/dev/xy1g
+...
+#
+zebedee host!=$@{key@};type:=nfs;rhost:=$@{key@};rfs:=/home/$@{key@} \
+ host==$@{key@};type:=ufs;dev:=/dev/dsk/1s0
+#
+# Just for access...
+#
+gould type:=auto;fs:=$@{map@};pref:=$@{key@}/
+gould/staff host!=gould;type:=nfs;rhost:=gould;rfs:=/home/$@{key@}
+#
+gummo host!=$@{key@};type:=nfs;rhost:=$@{key@};rfs:=/home/$@{key@}
+...
+@end example
+
+This map is shared by most of the machines listed so on those
+systems any of the user disks is accessible via a consistent name.
+@i{Amd} is started with the following command
+
+@example
+amd /home amd.home
+@end example
+
+Note that when mounting a remote filesystem, the @dfn{automounted}
+mount point is referenced, so that the filesystem will be mounted if
+it is not yet (at the time the remote @samp{mountd} obtains the file handle).
+
+@node Home Directories, Architecture Sharing, User Filesystems, Examples
+@comment node-name, next, previous, up
+@section Home Directories
+@cindex Home directories
+@cindex Example of mounting home directories
+@cindex Mount home directories
+
+One convention for home directories is to locate them in @samp{/homes}
+so user @samp{jsp}'s home directory is @samp{/homes/jsp}. With more
+than a single fileserver it is convenient to spread user files across
+several machines. All that is required is a mount-map which converts
+login names to an automounted directory.
+
+Such a map might be started by the command:
+
+@example
+amd /homes amd.homes
+@end example
+
+where the map @samp{amd.homes} contained the entries:
+
+@example
+/defaults type:=link # All the entries are of type:=link
+jsp fs:=/home/charm/jsp
+njw fs:=/home/dylan/dk5/njw
+...
+phjk fs:=/home/toytown/ai/phjk
+sjv fs:=/home/ganymede/sjv
+@end example
+
+Whenever a login name is accessed in @samp{/homes} a symbolic link
+appears pointing to the real location of that user's home directory. In
+this example, @samp{/homes/jsp} would appear to be a symbolic link
+pointing to @samp{/home/charm/jsp}. Of course, @samp{/home} would also
+be an automount point.
+
+This system causes an extra level of symbolic links to be used.
+Although that turns out to be relatively inexpensive, an alternative is
+to directly mount the required filesystems in the @samp{/homes}
+map. The required map is simple, but long, and its creation is best automated.
+The entry for @samp{jsp} could be:
+
+@example
+jsp -sublink:=$@{key@};rfs:=/home/charm \
+ host==charm;type:=ufs;dev:=/dev/xd0g \
+ host!=charm;type:=nfs;rhost:=charm
+@end example
+
+This map can become quite big if it contains a large number of entries.
+By combining two other features of @i{Amd} it can be greatly simplified.
+
+First the UFS partitions should be mounted under the control of
+@samp{/etc/fstab}, taking care that they are mounted in the same place
+that @i{Amd} would have automounted them. In most cases this would be
+something like @samp{/a/@dfn{host}/home/@dfn{host}} and
+@samp{/etc/fstab} on host @samp{charm} would have a line:@refill
+
+@example
+/dev/xy0g /a/charm/home/charm 4.2 rw,nosuid,grpid 1 5
+@end example
+
+The map can then be changed to:
+
+@example
+/defaults type:=nfs;sublink:=$@{key@};opts:=rw,intr,nosuid,grpid
+jsp rhost:=charm;rfs:=/home/charm
+njw rhost:=dylan;rfs:=/home/dylan/dk5
+...
+phjk rhost:=toytown;rfs:=/home/toytown;sublink:=ai/$@{key@}
+sjv rhost:=ganymede;rfs:=/home/ganymede
+@end example
+
+This map operates as usual on a remote machine (@i{ie} @code{$@{host@}}
+not equal to @code{$@{rhost@}}). On the machine where the filesystem is
+stored (@i{ie} @code{$@{host@}} equal to @code{$@{rhost@}}), @i{Amd}
+will construct a local filesystem mount point which corresponds to the
+name of the locally mounted UFS partition. If @i{Amd} is started with
+the @code{-r} option then instead of attempting an NFS mount, @i{Amd} will
+simply inherit the UFS mount (@pxref{Inheritance Filesystem}). If
+@code{-r} is not used then a loopback NFS mount will be made. This type of
+mount is known to cause a deadlock on many systems.
+
+@node Architecture Sharing, Wildcard Names, Home Directories, Examples
+@comment node-name, next, previous, up
+@section Architecture Sharing
+@cindex Architecture sharing
+@cindex Sharing a fileserver between architectures
+@cindex Architecture dependent volumes
+
+@c %At the moment some of the research machines have sets of software
+@c %mounted in @samp{/vol}. This contains subdirectories for \TeX,
+@c %system sources, local sources, prolog libraries and so on.
+Often a filesystem will be shared by machines of different architectures.
+Separate trees can be maintained for the executable images for each
+architecture, but it may be more convenient to have a shared tree,
+with distinct subdirectories.
+
+A shared tree might have the following structure on the fileserver (called
+@samp{fserver} in the example):
+
+@example
+local/tex
+local/tex/fonts
+local/tex/lib
+local/tex/bin
+local/tex/bin/sun3
+local/tex/bin/sun4
+local/tex/bin/hp9000
+...
+@end example
+
+In this example, the subdirectories of @samp{local/tex/bin} should be
+hidden when accessed via the automount point (conventionally @samp{/vol}).
+A mount-map for @samp{/vol} to achieve this would look like:
+
+@example
+/defaults sublink:=$@{/key@};rhost:=fserver;type:=link
+tex type:=auto;fs:=$@{map@};pref:=$@{key@}/
+tex/fonts host!=fserver;type:=nfs;rfs:=/vol/tex \
+ host==fserver;fs:=/usr/local/tex
+tex/lib host!=fserver;type:=nfs;rfs:=/vol/tex \
+ host==fserver;fs:=/usr/local/tex
+tex/bin -sublink:=$@{/key@}/$@{arch@} \
+ host!=fserver;type:=nfs;rfs:=/vol/tex \
+ host:=fserver;fs:=/usr/local/tex
+@end example
+
+When @samp{/vol/tex/bin} is referenced, the current machine architecture
+is automatically appended to the path by the @code{$@{sublink@}}
+variable. This means that users can have @samp{/vol/tex/bin} in their
+@samp{PATH} without concern for architecture dependencies.
+
+@node Wildcard Names, rwho servers, Architecture Sharing, Examples
+@comment node-name, next, previous, up
+@section Wildcard Names & Replicated Servers
+
+By using the wildcard facility, @i{Amd} can @dfn{overlay} an existing
+directory with additional entries.
+The system files are usually mounted under @samp{/usr}. If instead,
+@i{Amd} is mounted on @samp{/usr}, additional
+names can be overlayed to augment or replace names in the ``master'' @samp{/usr}.
+A map to do this would have the form:
+
+@example
+local type:=auto;fs:=local-map
+share type:=auto;fs:=share-map
+* -type:=nfs;rfs:=/export/exec/$@{arch@};sublink:="$@{key@}" \
+ rhost:=fserv1 rhost:=fserv2 rhost:=fserv3
+@end example
+
+Note that the assignment to @code{$@{sublink@}} is surrounded by double
+quotes to prevent the incoming key from causing the map to be
+misinterpreted. This map has the effect of directing any access to
+@samp{/usr/local} or @samp{/usr/share} to another automount point.
+
+In this example, it is assumed that the @samp{/usr} files are replicated
+on three fileservers: @samp{fserv1}, @samp{fserv2} and @samp{fserv3}.
+For any references other than to @samp{local} and @samp{share} one of
+the servers is used and a symbolic link to
+@t{$@{autodir@}/$@{rhost@}/export/exec/$@{arch@}/@i{whatever}} is
+returned once an appropriate filesystem has been mounted.@refill
+
+@node rwho servers, /vol, Wildcard Names, Examples
+@comment node-name, next, previous, up
+@section @samp{rwho} servers
+@cindex rwho servers
+@cindex Architecture specific mounts
+@cindex Example of architecture specific mounts
+
+The @samp{/usr/spool/rwho} directory is a good candidate for automounting.
+For efficiency reasons it is best to capture the rwho data on a small
+number of machines and then mount that information onto a large number
+of clients. The data written into the rwho files is byte order dependent
+so only servers with the correct byte ordering can be used by a client:
+
+@example
+/defaults type:=nfs
+usr/spool/rwho -byte==little;rfs:=/usr/spool/rwho \
+ rhost:=vaxA rhost:=vaxB \
+ || -rfs:=/usr/spool/rwho \
+ rhost:=sun4 rhost:=hp300
+@end example
+
+@node /vol, /defaults with selectors, rwho servers, Examples
+@comment node-name, next, previous, up
+@section @samp{/vol}
+@cindex /vol
+@cindex Catch-all mount point
+@cindex Generic volume name
+
+@samp{/vol} is used as a catch-all for volumes which do not have other
+conventional names.
+
+Below is part of the @samp{/vol} map for the domain @samp{doc.ic.ac.uk}.
+The @samp{r+d} tree is used for new or experimental software that needs
+to be available everywhere without installing it on all the fileservers.
+Users wishing to try out the new software then simply include
+@samp{/vol/r+d/@{bin,ucb@}} in their path.@refill
+
+The main tree resides on one host @samp{gould.doc.ic.ac.uk}, which has
+different @samp{bin}, @samp{etc}, @samp{lib} and @samp{ucb}
+sub-directories for each machine architecture. For example,
+@samp{/vol/r+d/bin} for a Sun-4 would be stored in the sub-directory
+@samp{bin/sun4} of the filesystem @samp{/usr/r+d}. When it was accessed
+a symbolic link pointing to @samp{/a/gould/usr/r+d/bin/sun4} would be
+returned.@refill
+
+@example
+/defaults type:=nfs;opts:=rw,grpid,nosuid,intr,soft
+wp -opts:=rw,grpid,nosuid;rhost:=charm \
+ host==charm;type:=link;fs:=/usr/local/wp \
+ host!=charm;type:=nfs;rfs:=/vol/wp
+...
+#
+src -opts:=rw,grpid,nosuid;rhost:=charm \
+ host==charm;type:=link;fs:=/usr/src \
+ host!=charm;type:=nfs;rfs:=/vol/src
+#
+r+d type:=auto;fs:=$@{map@};pref:=r+d/
+# per architecture bin,etc,lib&ucb...
+r+d/bin rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}/$@{arch@}
+r+d/etc rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}/$@{arch@}
+r+d/include rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}
+r+d/lib rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}/$@{arch@}
+r+d/man rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}
+r+d/src rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}
+r+d/ucb rhost:=gould.doc.ic.ac.uk;rfs:=/usr/r+d;sublink:=$@{/key@}/$@{arch@}
+# hades pictures
+pictures -opts:=rw,grpid,nosuid;rhost:=thpfs \
+ host==thpfs;type:=link;fs:=/nbsd/pictures \
+ host!=thpfs;type:=nfs;rfs:=/nbsd;sublink:=pictures
+# hades tools
+hades -opts:=rw,grpid,nosuid;rhost:=thpfs \
+ host==thpfs;type:=link;fs:=/nbsd/hades \
+ host!=thpfs;type:=nfs;rfs:=/nbsd;sublink:=hades
+# bsd tools for hp.
+bsd -opts:=rw,grpid,nosuid;arch==hp9000;rhost:=thpfs \
+ host==thpfs;type:=link;fs:=/nbsd/bsd \
+ host!=thpfs;type:=nfs;rfs:=/nbsd;sublink:=bsd
+@end example
+
+@node /defaults with selectors, /tftpboot in a chroot-ed environment, /vol, Examples
+@comment node-name, next, previous, up
+@section @samp{/defaults} with selectors
+@cindex /defaults with selectors
+@cindex selectors on default
+
+It is sometimes useful to have different defaults for a given map. To
+achieve this, the @samp{/defaults} entry must be able to process normal
+selectors. This feature is turned on by setting
+@samp{selectors_in_defaults = yes} in the @file{amd.conf} file.
+@xref{selectors_in_defaults Parameter}.
+
+In this example, I set different default NFS mount options for hosts
+which are running over a slower network link. By setting a smaller size
+for the NFS read and write buffer sizes, you can greatly improve remote
+file service performance.
+
+@example
+/defaults \
+ wire==slip-net;opts:=rw,intr,rsize=1024,wsize=1024,timeo=20,retrans=10 \
+ wire!=slip-net;opts:=rw,intr
+@end example
+
+@node /tftpboot in a chroot-ed environment, , /defaults with selectors, Examples
+@comment node-name, next, previous, up
+@section @samp{/tftpboot} in a chroot-ed environment
+@cindex /tftpboot in a chroot-ed environment
+@cindex chroot; /tftpboot example
+
+In this complex example, we attempt to run an @i{Amd} process
+@emph{inside} a chroot-ed environment. @samp{tftpd} (Trivial FTP) is
+used to trivially retrieve files used to boot X-Terminals, Network
+Printers, Network routers, diskless workstations, and other such
+devices. For security reasons, @samp{tftpd} (and also @samp{ftpd})
+processes are run using the @b{chroot}(2) system call. This provides an
+environment for these processes, where access to any files outside the
+directory where the chroot-ed process runs is denied.
+
+For example, if you start @samp{tftpd} on your system with
+
+@example
+chroot /tftpboot /usr/sbin/tftpd
+@end example
+
+@noindent
+then the @samp{tftpd} process will not be able to access any files
+outside @file{/tftpboot}. This ensures that no one can retrieve files
+such as @file{/etc/passwd} and run password crackers on it.
+
+Since the TFTP service works by broadcast, it is necessary to have at
+least one TFTP server running on each subnet. If you have lots of files
+that you need to make available for @samp{tftp}, and many subnets, it
+could take significant amounts of disk space on each host serving them.
+
+A solution we implemented at Columbia University was to have every host
+run @samp{tftpd}, but have those servers retrieve the boot files from
+two replicated servers. Those replicated servers have special
+partitions dedicated to the many network boot files.
+
+We start @i{Amd} as follows:
+
+@example
+amd /tftpboot/.amd amd.tftpboot
+@end example
+
+That is, @i{Amd} is serving the directory @file{/tftpboot/.amd}. The
+@samp{tftp} server runs inside @file{/tftpboot} and is chroot-ed in that
+directory too. The @file{amd.tftpboot} map looks like:
+
+@example
+#
+# Amd /tftpboot directory -> host map
+#
+
+/defaults opts:=nosuid,ro,intr,soft;fs:=/tftpboot/import;type:=nfs
+
+tp host==lol;rfs:=/n/lol/import/tftpboot;type:=lofs \
+ host==ober;rfs:=/n/ober/misc/win/tftpboot;type:=lofs \
+ rhost:=ober;rfs:=/n/ober/misc/win/tftpboot \
+ rhost:=lol;rfs:=/n/lol/import/tftpboot
+@end example
+
+To help understand this example, I list a few of the file entries that
+are created inside @file{/tftpboot}:
+
+@example
+$ ls -la /tftpboot
+dr-xr-xr-x 2 root 512 Aug 30 23:11 .amd
+drwxrwsr-x 12 root 512 Aug 30 08:00 import
+lrwxrwxrwx 1 root 33 Feb 27 1997 adminpr.cfg -> ./.amd/tp/hplj/adminpr.cfg
+lrwxrwxrwx 1 root 22 Dec 5 1996 tekxp -> ./.amd/tp/xterms/tekxp
+lrwxrwxrwx 1 root 1 Dec 5 1996 tftpboot -> .
+@end example
+
+Here is an explanation of each of the entries listed above:
+
+@table @code
+
+@item .amd
+This is the @i{Amd} mount point. Note that you do not need to run a
+separate @i{Amd} process for the TFTP service. The @b{chroot}(2) system
+call only protects against file access, but the same process can still
+serve files and directories inside and outside the chroot-ed
+environment, because @i{Amd} itself was not run in chroot-ed mode.
+
+@item import
+This is the mount point where @i{Amd} will mount the directories
+containing the boot files. The map is designed so that remote
+directories will be NFS mounted (even if they are already mounted
+elsewhere), and local directories are loopback mounted (since they are
+not accessible outside the chroot-ed @file{/tftpboot} directory).
+
+@item adminpr.cfg
+@itemx tekxp
+Two manually created symbolic links to directories @emph{inside} the
+@i{Amd}-managed directory. The crossing of the component @file{tp} will
+cause @i{Amd} to automount one of the remote replicas. Once crossed,
+access to files inside proceeds as usual. The @samp{adminpr.cfg} is a
+configuration file for an HP Laser-Jet 4si printer, and the @samp{tekxp}
+is a directory for Tektronix X-Terminal boot files.
+
+@item tftpboot
+This innocent looking symlink is important. Usually, when devices boot
+via the TFTP service, they perform the @samp{get file} command to
+retrieve @var{file}. However, some devices assume that @samp{tftpd}
+does not run in a chroot-ed environment, but rather ``unprotected'', and
+thus use a full pathname for files to retrieve, as in @samp{get
+/tftpboot/file}. This symlink effectively strips out the leading
+@file{/tftpboot/}.
+
+@end table
+
+@c ################################################################
+@node Internals, Acknowledgments & Trademarks, Examples, Top
+@comment node-name, next, previous, up
+@chapter Internals
+
+Note that there are more error and logging messages possible than are
+listed here. Most of them are self-explanatory. Refer to the program
+sources for more details on the rest.
+
+@menu
+* Log Messages::
+@end menu
+
+@node Log Messages, , Internals, Internals
+@comment node-name, next, previous, up
+@section Log Messages
+
+In the following sections a brief explanation is given of some of the
+log messages made by @i{Amd}. Where the message is in @samp{typewriter}
+font, it corresponds exactly to the message produced by @i{Amd}. Words
+in @dfn{italic} are replaced by an appropriate string. Variables,
+@code{$@{@i{var}@}}, indicate that the value of the appropriate variable is
+output.
+
+Log messages are either sent directly to a file,
+or logged via the @b{syslog}(3) mechanism. @xref{log_file Parameter}.
+In either case, entries in the file are of the form:
+@example
+@i{date-string} @i{hostname} @t{amd[}@i{pid}@t{]} @i{message}
+@end example
+
+@menu
+* Fatal errors::
+* Info messages::
+@end menu
+
+@node Fatal errors, Info messages, Log Messages, Log Messages
+@comment node-name, next, previous, up
+@subsection Fatal errors
+
+@i{Amd} attempts to deal with unusual events. Whenever it is not
+possible to deal with such an error, @i{Amd} will log an appropriate
+message and, if it cannot possibly continue, will either exit or abort.
+These messages are selected by @samp{-x fatal} on the command line.
+When @b{syslog}(3) is being used, they are logged with level
+@samp{LOG_FATAL}. Even if @i{Amd} continues to operate it is likely to
+remain in a precarious state and should be restarted at the earliest
+opportunity.
+
+@table @t
+
+@item Attempting to inherit not-a-filesystem
+The prototype mount point created during a filesystem restart did not
+contain a reference to the restarted filesystem. This error ``should
+never happen''.
+
+@item Can't bind to domain "@i{NIS-domain}"
+A specific NIS domain was requested on the command line, but no server
+for that domain is available on the local net.
+
+@item Can't determine IP address of this host (@i{hostname})
+When @i{Amd} starts it determines its own IP address. If this lookup
+fails then @i{Amd} cannot continue. The hostname it looks up is that
+obtained returned by @b{gethostname}(2) system call.
+
+@item Can't find root file handle for @i{automount point}
+@i{Amd} creates its own file handles for the automount points. When it
+mounts itself as a server, it must pass these file handles to the local
+kernel. If the filehandle is not obtainable the mount point is ignored.
+This error ``should never happen''.
+
+@item Must be root to mount filesystems (euid = @i{euid})
+To prevent embarrassment, @i{Amd} makes sure it has appropriate system
+privileges. This amounts to having an euid of 0. The check is made
+after argument processing complete to give non-root users a chance to
+access the @code{-v} option.
+
+@item No work to do - quitting
+No automount points were given on the command line and so there is no
+work to do.
+
+@item Out of memory
+While attempting to malloc some memory, the memory space available to
+@i{Amd} was exhausted. This is an unrecoverable error.
+
+@item Out of memory in realloc
+While attempting to realloc some memory, the memory space available to
+@i{Amd} was exhausted. This is an unrecoverable error.
+
+@item cannot create rpc/udp service
+Either the NFS or AMQ endpoint could not be created.
+
+@item gethostname: @i{description}
+The @b{gethostname}(2) system call failed during startup.
+
+@item host name is not set
+The @b{gethostname}(2) system call returned a zero length host name.
+This can happen if @i{Amd} is started in single user mode just after
+booting the system.
+
+@item ifs_match called!
+An internal error occurred while restarting a pre-mounted filesystem.
+This error ``should never happen''.
+
+@item mount_afs: @i{description}
+An error occurred while @i{Amd} was mounting itself.
+
+@item run_rpc failed
+Somehow the main NFS server loop failed. This error ``should never
+happen''.
+
+@item unable to free rpc arguments in amqprog_1
+The incoming arguments to the AMQ server could not be free'ed.
+
+@item unable to free rpc arguments in nfs_program_1
+The incoming arguments to the NFS server could not be free'ed.
+
+@item unable to register (AMQ_PROGRAM, AMQ_VERSION, udp)
+The AMQ server could not be registered with the local portmapper or the
+internal RPC dispatcher.
+
+@item unable to register (NFS_PROGRAM, NFS_VERSION, 0)
+The NFS server could not be registered with the internal RPC dispatcher.
+
+@end table
+
+XXX: This section needs to be updated
+
+@node Info messages, , Fatal errors, Log Messages
+@comment node-name, next, previous, up
+@subsection Info messages
+
+@i{Amd} generates information messages to record state changes. These
+messages are selected by @samp{-x info} on the command line. When
+@b{syslog}(3) is being used, they are logged with level @samp{LOG_INFO}.
+
+The messages listed below can be generated and are in a format suitable
+for simple statistical analysis. @dfn{mount-info} is the string
+that is displayed by @dfn{Amq} in its mount information column and
+placed in the system mount table.
+
+@table @t
+
+@item "@t{$@{@i{path}@}}" forcibly timed out
+An automount point has been timed out by the @i{Amq} command.
+
+@item "@t{$@{@i{path}@}}" has timed out
+No access to the automount point has been made within the timeout
+period.
+
+@item Filehandle denied for "$@{@i{rhost}@}:$@{@i{rfs}@}"
+The mount daemon refused to return a file handle for the requested filesystem.
+
+@item Filehandle error for "$@{@i{rhost}@}:$@{@i{rfs}@}": @i{description}
+The mount daemon gave some other error for the requested filesystem.
+
+@item Finishing with status @i{exit-status}
+@i{Amd} is about to exit with the given exit status.
+
+@item Re-synchronizing cache for map @t{$@{@i{map}@}}
+The named map has been modified and the internal cache is being re-synchronized.
+
+@item file server @t{$@{@i{rhost}@}} is down - timeout of "@t{$@{@i{path}@}}" ignored
+An automount point has timed out, but the corresponding file server is
+known to be down. This message is only produced once for each mount
+point for which the server is down.
+
+@item file server @t{$@{@i{rhost}@}} type nfs is down
+An NFS file server that was previously up is now down.
+
+@item file server @t{$@{@i{rhost}@}} type nfs is up
+An NFS file server that was previously down is now up.
+
+@item file server @t{$@{@i{rhost}@}} type nfs starts down
+A new NFS file server has been referenced and is known to be down.
+
+@item file server @t{$@{@i{rhost}@}} type nfs starts up
+A new NFS file server has been referenced and is known to be up.
+
+@item mount of "@t{$@{@i{path}@}}" on @t{$@{@i{fs}@}} timed out
+Attempts to mount a filesystem for the given automount point have failed
+to complete within 30 seconds.
+
+@item @i{mount-info} mounted fstype @t{$@{@i{type}@}} on @t{$@{@i{fs}@}}
+A new file system has been mounted.
+
+@item @i{mount-info} restarted fstype @t{$@{@i{type}@}} on @t{$@{@i{fs}@}}
+@i{Amd} is using a pre-mounted filesystem to satisfy a mount request.
+
+@item @i{mount-info} unmounted fstype @t{$@{@i{type}@}} from @t{$@{@i{fs}@}}
+A file system has been unmounted.
+
+@item @i{mount-info} unmounted fstype @t{$@{@i{type}@}} from @t{$@{@i{fs}@}} link @t{$@{@i{fs}@}}/@t{$@{@i{sublink}@}}
+A file system of which only a sub-directory was in use has been unmounted.
+
+@item restarting @i{mount-info} on @t{$@{@i{fs}@}}
+A pre-mounted file system has been noted.
+
+@end table
+
+XXX: This section needs to be updated
+
+@c ################################################################
+@node Acknowledgments & Trademarks, Index, Internals, Top
+@comment node-name, next, previous, up
+@unnumbered Acknowledgments & Trademarks
+
+Many thanks to the @email{am-utils@@am-utils.org,Am-Utils Users}
+mailing list through the months developing am-utils. These members
+have contributed to the discussions, ideas, code and documentation,
+and subjected their systems to alpha quality code. Special thanks go
+to those @uref{http://www.am-utils.org/docs/am-utils/AUTHORS.txt,authors} who have
+submitted patches, and especially to the maintainers:
+
+@itemize @bullet
+@item @email{ezk@@cs.sunysb.edu,Erez Zadok}
+@item @email{ib42@@cs.columbia.edu,Ion Badulescu}
+@item @email{ro@@techfak.uni-bielefeld.de,Rainer Orth}
+@item @email{nick.williams@@morganstanley.com,Nick Williams}
+@end itemize
+
+Thanks to the Formal Methods Group at Imperial College for suffering
+patiently while @i{Amd} was being developed on their machines.
+
+Thanks to the many people who have helped with the development of
+@i{Amd}, especially Piete Brooks at the Cambridge University Computing
+Lab for many hours of testing, experimentation and discussion.
+
+Thanks to the older @email{amd-workers@@majordomo.glue.umd.edu,Amd
+Workers} mailing list (now defunct) members for many suggestions and
+bug reports to @i{Amd}.
+
+@itemize @bullet
+@item
+@b{DEC}, @b{VAX} and @b{Ultrix} are registered trademarks of Digital
+Equipment Corporation.
+@item
+@b{AIX} and @b{IBM} are registered trademarks of International Business
+Machines Corporation.
+@item
+@b{Sun}, @b{NFS} and @b{SunOS} are registered trademarks of Sun
+Microsystems, Inc.
+@item
+@b{UNIX} is a registered trademark in the USA and other countries,
+exclusively licensed through X/Open Company, Ltd.
+@item
+All other registered trademarks are owned by their respective owners.
+@end itemize
+
+@c ################################################################
+@node Index, , Acknowledgments & Trademarks, Top
+@comment node-name, next, previous, up
+@unnumbered Index
+
+@printindex cp
+
+@contents
+@bye
+
+@c ====================================================================
+@c ISPELL LOCAL WORDS:
+@c LocalWords: setfilename amdref overfullrule settitle titlepage titlefont nz
+@c LocalWords: authorfont vskip ifinfo iftex cindex unnumberedsec dfn xref vol
+@c LocalWords: locationN pxref jpo nott concentrix Sjoerd sjoerd cwi Eitan vuw
+@c LocalWords: Mizrotsky eitan shumuji dgux fpx scp hcx metcalf masala hlh OTS
+@c LocalWords: Presnell srp cgl Trost trost ogi pyrOSx OSx tubsibr riscix iX
+@c LocalWords: Piete pb Lindblad cjl ai umax utek xinu Mitchum D'Souza dsouza
+@c LocalWords: mrc apu alliant aviion AViiON fps macII multimax tahoe vax emph
+@c LocalWords: mapdefault valA valB valC YPTSDIR ETCDIR substr MAKEDBM YPDBDIR
+@c LocalWords: NOPUSH njw dylan dk dylan njw anydir domN achilles mjh pref sel
+@c LocalWords: gdef loc loc loc ldots autodir remopts rwho rwho styx styx yoyo
+@c LocalWords: noindent gould rvdmount rvdunmount fserver mtmp unioned logfile
+@c LocalWords: dmn esac phjk toytown toytown toytown toytown phjk RdDir RdLnk
+@c LocalWords: volname attrs netif dougal inaddr hwaddr ec mountmaps passno xy
+@c LocalWords: freq dumpset hfs brian florence localinfo fstabs automaps defn
+@c LocalWords: localname fsck'd opr gummo sjv ganymede sjv fserv fserv fserv
+@c LocalWords: vaxA vaxB wp thpfs nbsd asis ifs amqprog free'ed printindex gov
+@c LocalWords: LocalWords syncodeindex Distrib bsdnet lanl AutoMounter acis ic
+@c LocalWords: ac uk aix bsd Mullender nl il DG lcs hpux irix ucsf NeXT cse cl
+@c LocalWords: mt FX hp ibm mips utils def def Domainname eg hostd getwd tmp
+@c LocalWords: subsubsection rw grpid intr noconn nocto nodevs nosuid retrans
+@c LocalWords: rsize tcp timeo nounmount utimeout DDEBUG nodaemon fd hostnames
+@c LocalWords: pid Amd's pendry vangogh nfsx backoff stats nomap nostats CRIT
+@c LocalWords: noinfo clustername RVD dsk dsk amq hostports osver statfs str
+@c LocalWords: ou counter's amdmaps proj src tftpboot sh mv cd sbin ypcat inet
+@c LocalWords: Getattr getattr localhost fhandles netmask fstype noquota addr
+@c LocalWords: exportfs Dumpsets dumpsets pindex ldif fixmount fixrmtab euid
+@c LocalWords: lostaltmail realloc netnumber itemx primnetnum primnetname ARG
+@c LocalWords: subsnetname subsnetnum netgrp netgroup multitable Shlib dec osf
+@c LocalWords: hppa pc bsdi freebsd netbsd openbsd ncr sysv rs acdirmax fsid
+@c LocalWords: acdirmin acregmax acregmin actimeo dumbtimr nfsv noac noauto sd
+@c LocalWords: nocache nodev noint nosub pgthresh posix rdonly suid symttl mfs
+@c LocalWords: AMFS umapfs myftpdir unionfs es mapname mapfile mapfile slocal
+@c LocalWords: mailspool saturn saturn notknown lol ober dr xr xr drwxrwsr cfg
+@c LocalWords: lrwxrwxrwx adminpr hplj adminpr cfg tekxp xterms tekxp Dupuy tp
+@c LocalWords: linkname hlfsddump dirname rmtab pluto rlogin direntry pg vr dn
+@c LocalWords: maxmem hlfsdir xmailbox showmount cn amdmap amdmapName resvport
+@c LocalWords: objectClass amdmapKey amdmapValue ln powerpc amdmapTimestamp ez
+@c LocalWords: moisil FSinfo Libtool Unmounting sublink fileservers NullProc
+@c LocalWords: gethostname mount's unmounts linkx remounts unmounting UAs SA's
+@c LocalWords: mountpoint mountpoints unescaped UIDs util's overlayed uref EFS
+@c LocalWords: serv maxgroups nfsl cachedir copt cfsadmin efs addopts fg ROMs
+@c LocalWords: nointr extatt setchapternewpage columnfractions alphaev gnulibc
+@c LocalWords: freebsdelf gnuoldld ifhtml defperm nodefperm norrip RRIP rrip
+@c LocalWords: noversion attr XXXXXX netgrpd rh mkstemp uid gid noexec mntfs
+@c LocalWords: nomnttab optionstr hrtime xdrtrace getpwd proplist redhat ctl
+@c LocalWords: texinfo texi ib sp cartouche ified xlatecookie dircategory sc
+@c LocalWords: AddInfo suse Novell softlookup ENOENT USB fullybrowsable LDAPv
+@c LocalWords: amy ie xfffffe zebedee andrew diskfull hdmail searchable si
+@c LocalWords: Orth ESTALE
diff --git a/doc/stamp-vti b/doc/stamp-vti
new file mode 100644
index 000000000000..41b19a30d5c6
--- /dev/null
+++ b/doc/stamp-vti
@@ -0,0 +1,4 @@
+@set UPDATED 20 April 2006
+@set UPDATED-MONTH April 2006
+@set EDITION 6.1.5
+@set VERSION 6.1.5
diff --git a/doc/texinfo.tex b/doc/texinfo.tex
new file mode 100644
index 000000000000..e758cedae7e6
--- /dev/null
+++ b/doc/texinfo.tex
@@ -0,0 +1,7014 @@
+% texinfo.tex -- TeX macros to handle Texinfo files.
+%
+% Load plain if necessary, i.e., if running under initex.
+\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
+%
+\def\texinfoversion{2004-09-06.16}
+%
+% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
+% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+% Foundation, Inc.
+%
+% This texinfo.tex file is free software; you can redistribute it and/or
+% modify it under the terms of the GNU General Public License as
+% published by the Free Software Foundation; either version 2, or (at
+% your option) any later version.
+%
+% This texinfo.tex file is distributed in the hope that it will be
+% useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+% General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this texinfo.tex file; see the file COPYING. If not, write
+% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+% Boston, MA 02111-1307, USA.
+%
+% As a special exception, when this file is read by TeX when processing
+% a Texinfo source document, you may use the result without
+% restriction. (This has been our intent since Texinfo was invented.)
+%
+% Please try the latest version of texinfo.tex before submitting bug
+% reports; you can get the latest version from:
+% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or
+% ftp://tug.org/tex/texinfo.tex
+% (and all CTAN mirrors, see http://www.ctan.org).
+% The texinfo.tex in any given distribution could well be out
+% of date, so if that's what you're using, please check.
+%
+% Send bug reports to bug-texinfo@gnu.org. Please include including a
+% complete document in each bug report with which we can reproduce the
+% problem. Patches are, of course, greatly appreciated.
+%
+% To process a Texinfo manual with TeX, it's most reliable to use the
+% texi2dvi shell script that comes with the distribution. For a simple
+% manual foo.texi, however, you can get away with this:
+% tex foo.texi
+% texindex foo.??
+% tex foo.texi
+% tex foo.texi
+% dvips foo.dvi -o # or whatever; this makes foo.ps.
+% The extra TeX runs get the cross-reference information correct.
+% Sometimes one run after texindex suffices, and sometimes you need more
+% than two; texi2dvi does it as many times as necessary.
+%
+% It is possible to adapt texinfo.tex for other languages, to some
+% extent. You can get the existing language-specific files from the
+% full Texinfo distribution.
+%
+% The GNU Texinfo home page is http://www.gnu.org/software/texinfo.
+
+
+\message{Loading texinfo [version \texinfoversion]:}
+
+% If in a .fmt file, print the version number
+% and turn on active characters that we couldn't do earlier because
+% they might have appeared in the input file name.
+\everyjob{\message{[Texinfo version \texinfoversion]}%
+ \catcode`+=\active \catcode`\_=\active}
+
+\message{Basics,}
+\chardef\other=12
+
+% We never want plain's \outer definition of \+ in Texinfo.
+% For @tex, we can use \tabalign.
+\let\+ = \relax
+
+% Save some plain tex macros whose names we will redefine.
+\let\ptexb=\b
+\let\ptexbullet=\bullet
+\let\ptexc=\c
+\let\ptexcomma=\,
+\let\ptexdot=\.
+\let\ptexdots=\dots
+\let\ptexend=\end
+\let\ptexequiv=\equiv
+\let\ptexexclam=\!
+\let\ptexfootnote=\footnote
+\let\ptexgtr=>
+\let\ptexhat=^
+\let\ptexi=\i
+\let\ptexindent=\indent
+\let\ptexnoindent=\noindent
+\let\ptexinsert=\insert
+\let\ptexlbrace=\{
+\let\ptexless=<
+\let\ptexplus=+
+\let\ptexrbrace=\}
+\let\ptexslash=\/
+\let\ptexstar=\*
+\let\ptext=\t
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Pre-3.0.
+\else
+ \def\linenumber{l.\the\inputlineno:\space}
+\fi
+
+% Set up fixed words for English if not already set.
+\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi
+\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi
+\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi
+\ifx\putwordin\undefined \gdef\putwordin{in}\fi
+\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
+\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
+\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi
+\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi
+\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi
+\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi
+\ifx\putwordof\undefined \gdef\putwordof{of}\fi
+\ifx\putwordon\undefined \gdef\putwordon{on}\fi
+\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi
+\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi
+\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi
+\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi
+\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi
+\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi
+\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi
+%
+\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi
+\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi
+\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi
+\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi
+\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi
+\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi
+\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi
+\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi
+\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi
+\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi
+\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi
+\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi
+%
+\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi
+\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi
+\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi
+\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi
+\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi
+
+% In some macros, we cannot use the `\? notation---the left quote is
+% in some cases the escape char.
+\chardef\colonChar = `\:
+\chardef\commaChar = `\,
+\chardef\dotChar = `\.
+\chardef\exclamChar= `\!
+\chardef\questChar = `\?
+\chardef\semiChar = `\;
+\chardef\underChar = `\_
+
+\chardef\spaceChar = `\ %
+\chardef\spacecat = 10
+\def\spaceisspace{\catcode\spaceChar=\spacecat}
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+% The following is used inside several \edef's.
+\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname}
+
+% Hyphenation fixes.
+\hyphenation{
+ Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script
+ ap-pen-dix bit-map bit-maps
+ data-base data-bases eshell fall-ing half-way long-est man-u-script
+ man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm
+ par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces
+ spell-ing spell-ings
+ stand-alone strong-est time-stamp time-stamps which-ever white-space
+ wide-spread wrap-around
+}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen\bindingoffset
+\newdimen\normaloffset
+\newdimen\pagewidth \newdimen\pageheight
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+% @| inserts a changebar to the left of the current line. It should
+% surround any changed text. This approach does *not* work if the
+% change spans more than two lines of output. To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+}
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal. We don't just call \tracingall here,
+% since that produces some useless output on the terminal. We also make
+% some effort to order the tracing commands to reduce output in the log
+% file; cf. trace.sty in LaTeX.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{%
+ \tracingstats2
+ \tracingpages1
+ \tracinglostchars2 % 2 gives us more in etex
+ \tracingparagraphs1
+ \tracingoutput1
+ \tracingmacros2
+ \tracingrestores1
+ \showboxbreadth\maxdimen \showboxdepth\maxdimen
+ \ifx\eTeXversion\undefined\else % etex gives us more logging
+ \tracingscantokens1
+ \tracingifs1
+ \tracinggroups1
+ \tracingnesting2
+ \tracingassigns1
+ \fi
+ \tracingcommands3 % 3 gives us more in etex
+ \errorcontextlines16
+}%
+
+% add check for \lastpenalty to plain's definitions. If the last thing
+% we did was a \nobreak, we don't want to insert more space.
+%
+\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount
+ \removelastskip\penalty-50\smallskip\fi\fi}
+\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount
+ \removelastskip\penalty-100\medskip\fi\fi}
+\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount
+ \removelastskip\penalty-200\bigskip\fi\fi}
+
+% For @cropmarks command.
+% Do @cropmarks to get crop marks.
+%
+\newif\ifcropmarks
+\let\cropmarks = \cropmarkstrue
+%
+% Dimensions to add cropmarks at corners.
+% Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines
+\newdimen\cornerlong \cornerlong=1pc
+\newdimen\cornerthick \cornerthick=.3pt
+\newdimen\topandbottommargin \topandbottommargin=.75in
+
+% Main output routine.
+\chardef\PAGE = 255
+\output = {\onepageout{\pagecontents\PAGE}}
+
+\newbox\headlinebox
+\newbox\footlinebox
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions, but you have to call it yourself.
+\def\onepageout#1{%
+ \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi
+ %
+ \ifodd\pageno \advance\hoffset by \bindingoffset
+ \else \advance\hoffset by -\bindingoffset\fi
+ %
+ % Do this outside of the \shipout so @code etc. will be expanded in
+ % the headline as they should be, not taken literally (outputting ''code).
+ \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+ \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
+ %
+ {%
+ % Have to do this stuff outside the \shipout because we want it to
+ % take effect in \write's, yet the group defined by the \vbox ends
+ % before the \shipout runs.
+ %
+ \escapechar = `\\ % use backslash in output files.
+ \indexdummies % don't expand commands in the output.
+ \normalturnoffactive % \ in index entries must not stay \, e.g., if
+ % the page break happens to be in the middle of an example.
+ \shipout\vbox{%
+ % Do this early so pdf references go to the beginning of the page.
+ \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi
+ %
+ \ifcropmarks \vbox to \outervsize\bgroup
+ \hsize = \outerhsize
+ \vskip-\topandbottommargin
+ \vtop to0pt{%
+ \line{\ewtop\hfil\ewtop}%
+ \nointerlineskip
+ \line{%
+ \vbox{\moveleft\cornerthick\nstop}%
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}%
+ }%
+ \vss}%
+ \vskip\topandbottommargin
+ \line\bgroup
+ \hfil % center the page within the outer (page) hsize.
+ \ifodd\pageno\hskip\bindingoffset\fi
+ \vbox\bgroup
+ \fi
+ %
+ \unvbox\headlinebox
+ \pagebody{#1}%
+ \ifdim\ht\footlinebox > 0pt
+ % Only leave this space if the footline is nonempty.
+ % (We lessened \vsize for it in \oddfootingxxx.)
+ % The \baselineskip=24pt in plain's \makefootline has no effect.
+ \vskip 2\baselineskip
+ \unvbox\footlinebox
+ \fi
+ %
+ \ifcropmarks
+ \egroup % end of \vbox\bgroup
+ \hfil\egroup % end of (centering) \line\bgroup
+ \vskip\topandbottommargin plus1fill minus1fill
+ \boxmaxdepth = \cornerthick
+ \vbox to0pt{\vss
+ \line{%
+ \vbox{\moveleft\cornerthick\nsbot}%
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}%
+ }%
+ \nointerlineskip
+ \line{\ewbot\hfil\ewbot}%
+ }%
+ \egroup % \vbox from first cropmarks clause
+ \fi
+ }% end of \shipout\vbox
+ }% end of group with \normalturnoffactive
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+}
+
+\newinsert\margin \dimen\margin=\maxdimen
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+% marginal hacks, juha@viisa.uucp (Juha Takala)
+\ifvoid\margin\else % marginal info is present
+ \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1. The argument is the rest of
+% the input line (except we remove a trailing comment). #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg{\parseargusing{}}
+\def\parseargusing#1#2{%
+ \def\next{#2}%
+ \begingroup
+ \obeylines
+ \spaceisspace
+ #1%
+ \parseargline\empty% Insert the \empty token, see \finishparsearg below.
+}
+
+{\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ \argremovecomment #1\comment\ArgTerm%
+ }%
+}
+
+% First remove any @comment, then any @c comment.
+\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm}
+\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm}
+
+% Each occurence of `\^^M' or `<space>\^^M' is replaced by a single space.
+%
+% \argremovec might leave us with trailing space, e.g.,
+% @end itemize @c foo
+% This space token undergoes the same procedure and is eventually removed
+% by \finishparsearg.
+%
+\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M}
+\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M}
+\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{%
+ \def\temp{#3}%
+ \ifx\temp\empty
+ % We cannot use \next here, as it holds the macro to run;
+ % thus we reuse \temp.
+ \let\temp\finishparsearg
+ \else
+ \let\temp\argcheckspaces
+ \fi
+ % Put the space token in:
+ \temp#1 #3\ArgTerm
+}
+
+% If a _delimited_ argument is enclosed in braces, they get stripped; so
+% to get _exactly_ the rest of the line, we had to prevent such situation.
+% We prepended an \empty token at the very beginning and we expand it now,
+% just before passing the control to \next.
+% (Similarily, we have to think about #3 of \argcheckspacesY above: it is
+% either the null string, or it ends with \^^M---thus there is no danger
+% that a pair of braces would be stripped.
+%
+% But first, we have to remove the trailing space token.
+%
+\def\finishparsearg#1 \ArgTerm{\expandafter\next\expandafter{#1}}
+
+% \parseargdef\foo{...}
+% is roughly equivalent to
+% \def\foo{\parsearg\Xfoo}
+% \def\Xfoo#1{...}
+%
+% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my
+% favourite TeX trick. --kasal, 16nov03
+
+\def\parseargdef#1{%
+ \expandafter \doparseargdef \csname\string#1\endcsname #1%
+}
+\def\doparseargdef#1#2{%
+ \def#2{\parsearg#1}%
+ \def#1##1%
+}
+
+% Several utility definitions with active space:
+{
+ \obeyspaces
+ \gdef\obeyedspace{ }
+
+ % Make each space character in the input produce a normal interword
+ % space in the output. Don't allow a line break at this space, as this
+ % is used only in environments like @example, where each line of input
+ % should produce a line of output anyway.
+ %
+ \gdef\sepspaces{\obeyspaces\let =\tie}
+
+ % If an index command is used in an @example environment, any spaces
+ % therein should become regular spaces in the raw index file, not the
+ % expansion of \tie (\leavevmode \penalty \@M \ ).
+ \gdef\unsepspaces{\let =\space}
+}
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+% Define the framework for environments in texinfo.tex. It's used like this:
+%
+% \envdef\foo{...}
+% \def\Efoo{...}
+%
+% It's the responsibility of \envdef to insert \begingroup before the
+% actual body; @end closes the group after calling \Efoo. \envdef also
+% defines \thisenv, so the current environment is known; @end checks
+% whether the environment name matches. The \checkenv macro can also be
+% used to check whether the current environment is the one expected.
+%
+% Non-false conditionals (@iftex, @ifset) don't fit into this, so they
+% are not treated as enviroments; they don't open a group. (The
+% implementation of @end takes care not to call \endgroup in this
+% special case.)
+
+
+% At runtime, environments start with this:
+\def\startenvironment#1{\begingroup\def\thisenv{#1}}
+% initialize
+\let\thisenv\empty
+
+% ... but they get defined via ``\envdef\foo{...}'':
+\long\def\envdef#1#2{\def#1{\startenvironment#1#2}}
+\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}}
+
+% Check whether we're in the right environment:
+\def\checkenv#1{%
+ \def\temp{#1}%
+ \ifx\thisenv\temp
+ \else
+ \badenverr
+ \fi
+}
+
+% Evironment mismatch, #1 expected:
+\def\badenverr{%
+ \errhelp = \EMsimple
+ \errmessage{This command can appear only \inenvironment\temp,
+ not \inenvironment\thisenv}%
+}
+\def\inenvironment#1{%
+ \ifx#1\empty
+ out of any environment%
+ \else
+ in environment \expandafter\string#1%
+ \fi
+}
+
+% @end foo executes the definition of \Efoo.
+% But first, it executes a specialized version of \checkenv
+%
+\parseargdef\end{%
+ \if 1\csname iscond.#1\endcsname
+ \else
+ % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03
+ \expandafter\checkenv\csname#1\endcsname
+ \csname E#1\endcsname
+ \endgroup
+ \fi
+}
+
+\newhelp\EMsimple{Press RETURN to continue.}
+
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt\char64}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+\def\mylbrace {{\tt\char123}}
+\def\myrbrace {{\tt\char125}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+\begingroup
+ % Definitions to produce \{ and \} commands for indices,
+ % and @{ and @} for the aux file.
+ \catcode`\{ = \other \catcode`\} = \other
+ \catcode`\[ = 1 \catcode`\] = 2
+ \catcode`\! = 0 \catcode`\\ = \other
+ !gdef!lbracecmd[\{]%
+ !gdef!rbracecmd[\}]%
+ !gdef!lbraceatcmd[@{]%
+ !gdef!rbraceatcmd[@}]%
+!endgroup
+
+% @comma{} to avoid , parsing problems.
+\let\comma = ,
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
+\let\, = \c
+\let\dotaccent = \.
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \t
+\let\ubaraccent = \b
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown @ordf @ordm
+% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}}
+\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+ \def\temp{#1}%
+ \ifx\temp\imacro \ptexi
+ \else\ifx\temp\jmacro \j
+ \else \errmessage{@dotless can be used only with i or j}%
+ \fi\fi
+}
+
+% The \TeX{} logo, as in plain, but resetting the spacing so that a
+% period following counts as ending a sentence. (Idea found in latex.)
+%
+\edef\TeX{\TeX \spacefactor=1000 }
+
+% @LaTeX{} logo. Not quite the same results as the definition in
+% latex.ltx, since we use a different font for the raised A; it's most
+% convenient for us to use an explicitly smaller font, rather than using
+% the \scriptstyle font (since we don't reset \scriptstyle and
+% \scriptscriptstyle).
+%
+\def\LaTeX{%
+ L\kern-.36em
+ {\setbox0=\hbox{T}%
+ \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}%
+ \kern-.15em
+ \TeX
+}
+
+% Be sure we're in horizontal mode when doing a tie, since we make space
+% equivalent to this in @example-like environments. Otherwise, a space
+% at the beginning of a line will start with \penalty -- and
+% since \penalty is valid in vertical mode, we'd end up putting the
+% penalty on the vertical list instead of in the new paragraph.
+{\catcode`@ = 11
+ % Avoid using \@M directly, because that causes trouble
+ % if the definition is written into an index file.
+ \global\let\tiepenalty = \@M
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
+}
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @/ allows a line break.
+\let\/=\allowbreak
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @! is an end-of-sentence bang.
+\def\!{!\spacefactor=3000 }
+
+% @? is an end-of-sentence query.
+\def\?{?\spacefactor=3000 }
+
+% @w prevents a word break. Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line. According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0). If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+% Another complication is that the group might be very large. This can
+% cause the glue on the previous page to be unduly stretched, because it
+% does not have much material. In this case, it's better to add an
+% explicit \vfill so that the extra space is at the bottom. The
+% threshold for doing this is if the group is more than \vfilllimit
+% percent of a page (\vfilllimit can be changed inside of @tex).
+%
+\newbox\groupbox
+\def\vfilllimit{0.7}
+%
+\envdef\group{%
+ \ifnum\catcode`\^^M=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ \startsavinginserts
+ %
+ \setbox\groupbox = \vtop\bgroup
+ % Do @comment since we are called inside an environment such as
+ % @example, where each end-of-line in the input causes an
+ % end-of-line in the output. We don't want the end-of-line after
+ % the `@group' to put extra space in the output. Since @group
+ % should appear on a line by itself (according to the Texinfo
+ % manual), we don't worry about eating any user text.
+ \comment
+}
+%
+% The \vtop produces a box with normal height and large depth; thus, TeX puts
+% \baselineskip glue before it, and (when the next line of text is done)
+% \lineskip glue after it. Thus, space below is not quite equal to space
+% above. But it's pretty close.
+\def\Egroup{%
+ % To get correct interline space between the last line of the group
+ % and the first line afterwards, we have to propagate \prevdepth.
+ \endgraf % Not \par, as it may have been set to \lisppar.
+ \global\dimen1 = \prevdepth
+ \egroup % End the \vtop.
+ % \dimen0 is the vertical size of the group's box.
+ \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox
+ % \dimen2 is how much space is left on the page (more or less).
+ \dimen2 = \pageheight \advance\dimen2 by -\pagetotal
+ % if the group doesn't fit on the current page, and it's a big big
+ % group, force a page break.
+ \ifdim \dimen0 > \dimen2
+ \ifdim \pagetotal < \vfilllimit\pageheight
+ \page
+ \fi
+ \fi
+ \box\groupbox
+ \prevdepth = \dimen1
+ \checkinserts
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+% Old definition--didn't work.
+%\parseargdef\need{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
+%\prevdepth=-1000pt
+%}}
+
+\parseargdef\need{%
+ % Ensure vertical mode, so we don't make a big box in the middle of a
+ % paragraph.
+ \par
+ %
+ % If the @need value is less than one line space, it's useless.
+ \dimen0 = #1\mil
+ \dimen2 = \ht\strutbox
+ \advance\dimen2 by \dp\strutbox
+ \ifdim\dimen0 > \dimen2
+ %
+ % Do a \strut just to make the height of this box be normal, so the
+ % normal leading is inserted relative to the preceding line.
+ % And a page break here is fine.
+ \vtop to #1\mil{\strut\vfil}%
+ %
+ % TeX does not even consider page breaks if a penalty added to the
+ % main vertical list is 10000 or more. But in order to see if the
+ % empty box we just added fits on the page, we must make it consider
+ % page breaks. On the other hand, we don't want to actually break the
+ % page after the empty box. So we use a penalty of 9999.
+ %
+ % There is an extremely small chance that TeX will actually break the
+ % page at this \penalty, if there are no other feasible breakpoints in
+ % sight. (If the user is using lots of big @group commands, which
+ % almost-but-not-quite fill up a page, TeX will have a hard time doing
+ % good page breaking, for example.) However, I could not construct an
+ % example where a page broke at this \penalty; if it happens in a real
+ % document, then we can reconsider our strategy.
+ \penalty9999
+ %
+ % Back up by the size of the box, whether we did a page break or not.
+ \kern -#1\mil
+ %
+ % Do not allow a page break right after this kern.
+ \nobreak
+ \fi
+}
+
+% @br forces paragraph break (and is undocumented).
+
+\let\br = \par
+
+% @page forces the start of a new page.
+%
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}
+
+% This defn is used inside nofill environments such as @example.
+\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount
+ \leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current
+% paragraph. For more general purposes, use the \margin insertion
+% class. WHICH is `l' or `r'.
+%
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+%
+\def\doinmargin#1#2{\strut\vadjust{%
+ \nobreak
+ \kern-\strutdepth
+ \vtop to \strutdepth{%
+ \baselineskip=\strutdepth
+ \vss
+ % if you have multiple lines of stuff to put here, you'll need to
+ % make the vbox yourself of the appropriate size.
+ \ifx#1l%
+ \llap{\ignorespaces #2\hskip\inmarginspacing}%
+ \else
+ \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}%
+ \fi
+ \null
+ }%
+}}
+\def\inleftmargin{\doinmargin l}
+\def\inrightmargin{\doinmargin r}
+%
+% @inmargin{TEXT [, RIGHT-TEXT]}
+% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right;
+% else use TEXT for both).
+%
+\def\inmargin#1{\parseinmargin #1,,\finish}
+\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing.
+ \setbox0 = \hbox{\ignorespaces #2}%
+ \ifdim\wd0 > 0pt
+ \def\lefttext{#1}% have both texts
+ \def\righttext{#2}%
+ \else
+ \def\lefttext{#1}% have only one text
+ \def\righttext{#1}%
+ \fi
+ %
+ \ifodd\pageno
+ \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin
+ \else
+ \def\temp{\inleftmargin\lefttext}%
+ \fi
+ \temp
+}
+
+% @include file insert text of that file as input.
+%
+\def\include{\parseargusing\filenamecatcodes\includezzz}
+\def\includezzz#1{%
+ \pushthisfilestack
+ \def\thisfile{#1}%
+ {%
+ \makevalueexpandable
+ \def\temp{\input #1 }%
+ \expandafter
+ }\temp
+ \popthisfilestack
+}
+\def\filenamecatcodes{%
+ \catcode`\\=\other
+ \catcode`~=\other
+ \catcode`^=\other
+ \catcode`_=\other
+ \catcode`|=\other
+ \catcode`<=\other
+ \catcode`>=\other
+ \catcode`+=\other
+ \catcode`-=\other
+}
+
+\def\pushthisfilestack{%
+ \expandafter\pushthisfilestackX\popthisfilestack\StackTerm
+}
+\def\pushthisfilestackX{%
+ \expandafter\pushthisfilestackY\thisfile\StackTerm
+}
+\def\pushthisfilestackY #1\StackTerm #2\StackTerm {%
+ \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}%
+}
+
+\def\popthisfilestack{\errthisfilestackempty}
+\def\errthisfilestackempty{\errmessage{Internal error:
+ the stack of filenames is empty.}}
+
+\def\thisfile{}
+
+% @center line
+% outputs that line, centered.
+%
+\parseargdef\center{%
+ \ifhmode
+ \let\next\centerH
+ \else
+ \let\next\centerV
+ \fi
+ \next{\hfil \ignorespaces#1\unskip \hfil}%
+}
+\def\centerH#1{%
+ {%
+ \hfil\break
+ \advance\hsize by -\leftskip
+ \advance\hsize by -\rightskip
+ \line{#1}%
+ \break
+ }%
+}
+\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}}
+
+% @sp n outputs n lines of vertical space
+
+\parseargdef\sp{\vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\begingroup \catcode`\^^M=\other%
+\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
+\commentxxx}
+{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}
+
+\let\c=\comment
+
+% @paragraphindent NCHARS
+% We'll use ems for NCHARS, close enough.
+% NCHARS can also be the word `asis' or `none'.
+% We cannot feasibly implement @paragraphindent asis, though.
+%
+\def\asisword{asis} % no translation, these are keywords
+\def\noneword{none}
+%
+\parseargdef\paragraphindent{%
+ \def\temp{#1}%
+ \ifx\temp\asisword
+ \else
+ \ifx\temp\noneword
+ \defaultparindent = 0pt
+ \else
+ \defaultparindent = #1em
+ \fi
+ \fi
+ \parindent = \defaultparindent
+}
+
+% @exampleindent NCHARS
+% We'll use ems for NCHARS like @paragraphindent.
+% It seems @exampleindent asis isn't necessary, but
+% I preserve it to make it similar to @paragraphindent.
+\parseargdef\exampleindent{%
+ \def\temp{#1}%
+ \ifx\temp\asisword
+ \else
+ \ifx\temp\noneword
+ \lispnarrowing = 0pt
+ \else
+ \lispnarrowing = #1em
+ \fi
+ \fi
+}
+
+% @firstparagraphindent WORD
+% If WORD is `none', then suppress indentation of the first paragraph
+% after a section heading. If WORD is `insert', then do indent at such
+% paragraphs.
+%
+% The paragraph indentation is suppressed or not by calling
+% \suppressfirstparagraphindent, which the sectioning commands do.
+% We switch the definition of this back and forth according to WORD.
+% By default, we suppress indentation.
+%
+\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent}
+\def\insertword{insert}
+%
+\parseargdef\firstparagraphindent{%
+ \def\temp{#1}%
+ \ifx\temp\noneword
+ \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent
+ \else\ifx\temp\insertword
+ \let\suppressfirstparagraphindent = \relax
+ \else
+ \errhelp = \EMsimple
+ \errmessage{Unknown @firstparagraphindent option `\temp'}%
+ \fi\fi
+}
+
+% Here is how we actually suppress indentation. Redefine \everypar to
+% \kern backwards by \parindent, and then reset itself to empty.
+%
+% We also make \indent itself not actually do anything until the next
+% paragraph.
+%
+\gdef\dosuppressfirstparagraphindent{%
+ \gdef\indent{%
+ \restorefirstparagraphindent
+ \indent
+ }%
+ \gdef\noindent{%
+ \restorefirstparagraphindent
+ \noindent
+ }%
+ \global\everypar = {%
+ \kern -\parindent
+ \restorefirstparagraphindent
+ }%
+}
+
+\gdef\restorefirstparagraphindent{%
+ \global \let \indent = \ptexindent
+ \global \let \noindent = \ptexnoindent
+ \global \everypar = {}%
+}
+
+
+% @asis just yields its argument. Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math outputs its argument in math mode.
+%
+% One complication: _ usually means subscripts, but it could also mean
+% an actual _ character, as in @math{@var{some_variable} + 1}. So make
+% _ active, and distinguish by seeing if the current family is \slfam,
+% which is what @var uses.
+{
+ \catcode\underChar = \active
+ \gdef\mathunderscore{%
+ \catcode\underChar=\active
+ \def_{\ifnum\fam=\slfam \_\else\sb\fi}%
+ }
+}
+% Another complication: we want \\ (and @\) to output a \ character.
+% FYI, plain.tex uses \\ as a temporary control sequence (why?), but
+% this is not advertised and we don't care. Texinfo does not
+% otherwise define @\.
+%
+% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\.
+\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi}
+%
+\def\math{%
+ \tex
+ \mathunderscore
+ \let\\ = \mathbackslash
+ \mathactive
+ $\finishmath
+}
+\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex.
+
+% Some active characters (such as <) are spaced differently in math.
+% We have to reset their definitions in case the @math was an argument
+% to a command which sets the catcodes (such as @item or @section).
+%
+{
+ \catcode`^ = \active
+ \catcode`< = \active
+ \catcode`> = \active
+ \catcode`+ = \active
+ \gdef\mathactive{%
+ \let^ = \ptexhat
+ \let< = \ptexless
+ \let> = \ptexgtr
+ \let+ = \ptexplus
+ }
+}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{$\ptexbullet$}
+\def\minus{$-$}
+
+% @dots{} outputs an ellipsis using the current font.
+% We do .5em per period so that it has the same spacing in a typewriter
+% font as three actual period characters.
+%
+\def\dots{%
+ \leavevmode
+ \hbox to 1.5em{%
+ \hskip 0pt plus 0.25fil
+ .\hfil.\hfil.%
+ \hskip 0pt plus 0.5fil
+ }%
+}
+
+% @enddots{} is an end-of-sentence ellipsis.
+%
+\def\enddots{%
+ \dots
+ \spacefactor=3000
+}
+
+% @comma{} is so commas can be inserted into text without messing up
+% Texinfo's parsing.
+%
+\let\comma = ,
+
+% @refill is a no-op.
+\let\refill=\relax
+
+% If working on a large document in chapters, it is convenient to
+% be able to disable indexing, cross-referencing, and contents, for test runs.
+% This is done with @novalidate (before @setfilename).
+%
+\newif\iflinks \linkstrue % by default we want the aux files.
+\let\novalidate = \linksfalse
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \iflinks
+ \tryauxfile
+ % Open the new aux file. TeX will close it automatically at exit.
+ \immediate\openout\auxfile=\jobname.aux
+ \fi % \openindices needs to do some work in any case.
+ \openindices
+ \let\setfilename=\comment % Ignore extra @setfilename cmds.
+ %
+ % If texinfo.cnf is present on the system, read it.
+ % Useful for site-wide @afourpaper, etc.
+ \openin 1 texinfo.cnf
+ \ifeof 1 \else \input texinfo.cnf \fi
+ \closein 1
+ %
+ \comment % Ignore the actual filename.
+}
+
+% Called from \setfilename.
+%
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% @bye.
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+
+\message{pdf,}
+% adobe `portable' document format
+\newcount\tempnum
+\newcount\lnkcount
+\newtoks\filename
+\newcount\filenamelength
+\newcount\pgn
+\newtoks\toksA
+\newtoks\toksB
+\newtoks\toksC
+\newtoks\toksD
+\newbox\boxA
+\newcount\countA
+\newif\ifpdf
+\newif\ifpdfmakepagedest
+
+% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1
+% can be set). So we test for \relax and 0 as well as \undefined,
+% borrowed from ifpdf.sty.
+\ifx\pdfoutput\undefined
+\else
+ \ifx\pdfoutput\relax
+ \else
+ \ifcase\pdfoutput
+ \else
+ \pdftrue
+ \fi
+ \fi
+\fi
+%
+\ifpdf
+ \input pdfcolor
+ \pdfcatalog{/PageMode /UseOutlines}%
+ \def\dopdfimage#1#2#3{%
+ \def\imagewidth{#2}%
+ \def\imageheight{#3}%
+ % without \immediate, pdftex seg faults when the same image is
+ % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.)
+ \ifnum\pdftexversion < 14
+ \immediate\pdfimage
+ \else
+ \immediate\pdfximage
+ \fi
+ \ifx\empty\imagewidth\else width \imagewidth \fi
+ \ifx\empty\imageheight\else height \imageheight \fi
+ \ifnum\pdftexversion<13
+ #1.pdf%
+ \else
+ {#1.pdf}%
+ \fi
+ \ifnum\pdftexversion < 14 \else
+ \pdfrefximage \pdflastximage
+ \fi}
+ \def\pdfmkdest#1{{%
+ % We have to set dummies so commands such as @code in a section title
+ % aren't expanded.
+ \atdummies
+ \normalturnoffactive
+ \pdfdest name{#1} xyz%
+ }}
+ \def\pdfmkpgn#1{#1}
+ \let\linkcolor = \Blue % was Cyan, but that seems light?
+ \def\endlink{\Black\pdfendlink}
+ % Adding outlines to PDF; macros for calculating structure of outlines
+ % come from Petr Olsak
+ \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0%
+ \else \csname#1\endcsname \fi}
+ \def\advancenumber#1{\tempnum=\expnumber{#1}\relax
+ \advance\tempnum by 1
+ \expandafter\xdef\csname#1\endcsname{\the\tempnum}}
+ %
+ % #1 is the section text. #2 is the pdf expression for the number
+ % of subentries (or empty, for subsubsections). #3 is the node
+ % text, which might be empty if this toc entry had no
+ % corresponding node. #4 is the page number.
+ %
+ \def\dopdfoutline#1#2#3#4{%
+ % Generate a link to the node text if that exists; else, use the
+ % page number. We could generate a destination for the section
+ % text in the case where a section has no node, but it doesn't
+ % seem worthwhile, since most documents are normally structured.
+ \def\pdfoutlinedest{#3}%
+ \ifx\pdfoutlinedest\empty \def\pdfoutlinedest{#4}\fi
+ %
+ \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{#1}%
+ }
+ %
+ \def\pdfmakeoutlines{%
+ \begingroup
+ % Thanh's hack / proper braces in bookmarks
+ \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace
+ \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace
+ %
+ % Read toc silently, to get counts of subentries for \pdfoutline.
+ \def\numchapentry##1##2##3##4{%
+ \def\thischapnum{##2}%
+ \let\thissecnum\empty
+ \let\thissubsecnum\empty
+ }%
+ \def\numsecentry##1##2##3##4{%
+ \advancenumber{chap\thischapnum}%
+ \def\thissecnum{##2}%
+ \let\thissubsecnum\empty
+ }%
+ \def\numsubsecentry##1##2##3##4{%
+ \advancenumber{sec\thissecnum}%
+ \def\thissubsecnum{##2}%
+ }%
+ \def\numsubsubsecentry##1##2##3##4{%
+ \advancenumber{subsec\thissubsecnum}%
+ }%
+ \let\thischapnum\empty
+ \let\thissecnum\empty
+ \let\thissubsecnum\empty
+ %
+ % use \def rather than \let here because we redefine \chapentry et
+ % al. a second time, below.
+ \def\appentry{\numchapentry}%
+ \def\appsecentry{\numsecentry}%
+ \def\appsubsecentry{\numsubsecentry}%
+ \def\appsubsubsecentry{\numsubsubsecentry}%
+ \def\unnchapentry{\numchapentry}%
+ \def\unnsecentry{\numsecentry}%
+ \def\unnsubsecentry{\numsubsecentry}%
+ \def\unnsubsubsecentry{\numsubsubsecentry}%
+ \input \jobname.toc
+ %
+ % Read toc second time, this time actually producing the outlines.
+ % The `-' means take the \expnumber as the absolute number of
+ % subentries, which we calculated on our first read of the .toc above.
+ %
+ % We use the node names as the destinations.
+ \def\numchapentry##1##2##3##4{%
+ \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}%
+ \def\numsecentry##1##2##3##4{%
+ \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}%
+ \def\numsubsecentry##1##2##3##4{%
+ \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}%
+ \def\numsubsubsecentry##1##2##3##4{% count is always zero
+ \dopdfoutline{##1}{}{##3}{##4}}%
+ %
+ % PDF outlines are displayed using system fonts, instead of
+ % document fonts. Therefore we cannot use special characters,
+ % since the encoding is unknown. For example, the eogonek from
+ % Latin 2 (0xea) gets translated to a | character. Info from
+ % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100.
+ %
+ % xx to do this right, we have to translate 8-bit characters to
+ % their "best" equivalent, based on the @documentencoding. Right
+ % now, I guess we'll just let the pdf reader have its way.
+ \indexnofonts
+ \turnoffactive
+ \input \jobname.toc
+ \endgroup
+ }
+ %
+ \def\makelinks #1,{%
+ \def\params{#1}\def\E{END}%
+ \ifx\params\E
+ \let\nextmakelinks=\relax
+ \else
+ \let\nextmakelinks=\makelinks
+ \ifnum\lnkcount>0,\fi
+ \picknum{#1}%
+ \startlink attr{/Border [0 0 0]}
+ goto name{\pdfmkpgn{\the\pgn}}%
+ \linkcolor #1%
+ \advance\lnkcount by 1%
+ \endlink
+ \fi
+ \nextmakelinks
+ }
+ \def\picknum#1{\expandafter\pn#1}
+ \def\pn#1{%
+ \def\p{#1}%
+ \ifx\p\lbrace
+ \let\nextpn=\ppn
+ \else
+ \let\nextpn=\ppnn
+ \def\first{#1}
+ \fi
+ \nextpn
+ }
+ \def\ppn#1{\pgn=#1\gobble}
+ \def\ppnn{\pgn=\first}
+ \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,}
+ \def\skipspaces#1{\def\PP{#1}\def\D{|}%
+ \ifx\PP\D\let\nextsp\relax
+ \else\let\nextsp\skipspaces
+ \ifx\p\space\else\addtokens{\filename}{\PP}%
+ \advance\filenamelength by 1
+ \fi
+ \fi
+ \nextsp}
+ \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax}
+ \ifnum\pdftexversion < 14
+ \let \startlink \pdfannotlink
+ \else
+ \let \startlink \pdfstartlink
+ \fi
+ \def\pdfurl#1{%
+ \begingroup
+ \normalturnoffactive\def\@{@}%
+ \makevalueexpandable
+ \leavevmode\Red
+ \startlink attr{/Border [0 0 0]}%
+ user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
+ \endgroup}
+ \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}}
+ \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
+ \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks}
+ \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}}
+ \def\maketoks{%
+ \expandafter\poptoks\the\toksA|ENDTOKS|\relax
+ \ifx\first0\adn0
+ \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3
+ \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6
+ \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9
+ \else
+ \ifnum0=\countA\else\makelink\fi
+ \ifx\first.\let\next=\done\else
+ \let\next=\maketoks
+ \addtokens{\toksB}{\the\toksD}
+ \ifx\first,\addtokens{\toksB}{\space}\fi
+ \fi
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+ \next}
+ \def\makelink{\addtokens{\toksB}%
+ {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
+ \def\pdflink#1{%
+ \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}}
+ \linkcolor #1\endlink}
+ \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
+\else
+ \let\pdfmkdest = \gobble
+ \let\pdfurl = \gobble
+ \let\endlink = \relax
+ \let\linkcolor = \relax
+ \let\pdfmakeoutlines = \relax
+\fi % \ifx\pdfoutput
+
+
+\message{fonts,}
+
+% Change the current font style to #1, remembering it in \curfontstyle.
+% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in
+% italics, not bold italics.
+%
+\def\setfontstyle#1{%
+ \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd.
+ \csname ten#1\endcsname % change the current font
+}
+
+% Select #1 fonts with the current style.
+%
+\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname}
+
+\def\rm{\fam=0 \setfontstyle{rm}}
+\def\it{\fam=\itfam \setfontstyle{it}}
+\def\sl{\fam=\slfam \setfontstyle{sl}}
+\def\bf{\fam=\bffam \setfontstyle{bf}}
+\def\tt{\fam=\ttfam \setfontstyle{tt}}
+
+% Texinfo sort of supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf.
+\newfam\sffam
+\def\sf{\fam=\sffam \setfontstyle{sf}}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this font style.
+\def\ttsl{\setfontstyle{ttsl}}
+
+% Default leading.
+\newdimen\textleading \textleading = 13.2pt
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly. There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+ \normalbaselineskip = #1\relax
+ \normallineskip = \lineskipfactor\normalbaselineskip
+ \normalbaselines
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+}
+
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
+% #3 is the font's design size, #4 is a scale factor
+\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+
+% Use cm as the default font prefix.
+% To specify the font prefix, you must define \fontprefix
+% before you read in texinfo.tex.
+\ifx\fontprefix\undefined
+\def\fontprefix{cm}
+\fi
+% Support font families that don't use the same naming scheme as CM.
+\def\rmshape{r}
+\def\rmbshape{bx} %where the normal face is bold
+\def\bfshape{b}
+\def\bxshape{bx}
+\def\ttshape{tt}
+\def\ttbshape{tt}
+\def\ttslshape{sltt}
+\def\itshape{ti}
+\def\itbshape{bxti}
+\def\slshape{sl}
+\def\slbshape{bxsl}
+\def\sfshape{ss}
+\def\sfbshape{ss}
+\def\scshape{csc}
+\def\scbshape{csc}
+
+% Text fonts (11.2pt, magstep1).
+\newcount\mainmagstep
+\ifx\bigger\relax
+ % not really supported.
+ \mainmagstep=\magstep1
+ \setfont\textrm\rmshape{12}{1000}
+ \setfont\texttt\ttshape{12}{1000}
+\else
+ \mainmagstep=\magstephalf
+ \setfont\textrm\rmshape{10}{\mainmagstep}
+ \setfont\texttt\ttshape{10}{\mainmagstep}
+\fi
+\setfont\textbf\bfshape{10}{\mainmagstep}
+\setfont\textit\itshape{10}{\mainmagstep}
+\setfont\textsl\slshape{10}{\mainmagstep}
+\setfont\textsf\sfshape{10}{\mainmagstep}
+\setfont\textsc\scshape{10}{\mainmagstep}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun names and args.
+\setfont\defbf\bfshape{10}{\magstep1}
+\setfont\deftt\ttshape{10}{\magstep1}
+\setfont\defttsl\ttslshape{10}{\magstep1}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf}
+
+% Fonts for indices, footnotes, small examples (9pt).
+\setfont\smallrm\rmshape{9}{1000}
+\setfont\smalltt\ttshape{9}{1000}
+\setfont\smallbf\bfshape{10}{900}
+\setfont\smallit\itshape{9}{1000}
+\setfont\smallsl\slshape{9}{1000}
+\setfont\smallsf\sfshape{9}{1000}
+\setfont\smallsc\scshape{10}{900}
+\setfont\smallttsl\ttslshape{10}{900}
+\font\smalli=cmmi9
+\font\smallsy=cmsy9
+
+% Fonts for small examples (8pt).
+\setfont\smallerrm\rmshape{8}{1000}
+\setfont\smallertt\ttshape{8}{1000}
+\setfont\smallerbf\bfshape{10}{800}
+\setfont\smallerit\itshape{8}{1000}
+\setfont\smallersl\slshape{8}{1000}
+\setfont\smallersf\sfshape{8}{1000}
+\setfont\smallersc\scshape{10}{800}
+\setfont\smallerttsl\ttslshape{10}{800}
+\font\smalleri=cmmi8
+\font\smallersy=cmsy8
+
+% Fonts for title page (20.4pt):
+\setfont\titlerm\rmbshape{12}{\magstep3}
+\setfont\titleit\itbshape{10}{\magstep4}
+\setfont\titlesl\slbshape{10}{\magstep4}
+\setfont\titlett\ttbshape{12}{\magstep3}
+\setfont\titlettsl\ttslshape{10}{\magstep4}
+\setfont\titlesf\sfbshape{17}{\magstep1}
+\let\titlebf=\titlerm
+\setfont\titlesc\scbshape{10}{\magstep4}
+\font\titlei=cmmi12 scaled \magstep3
+\font\titlesy=cmsy10 scaled \magstep4
+\def\authorrm{\secrm}
+\def\authortt{\sectt}
+
+% Chapter (and unnumbered) fonts (17.28pt).
+\setfont\chaprm\rmbshape{12}{\magstep2}
+\setfont\chapit\itbshape{10}{\magstep3}
+\setfont\chapsl\slbshape{10}{\magstep3}
+\setfont\chaptt\ttbshape{12}{\magstep2}
+\setfont\chapttsl\ttslshape{10}{\magstep3}
+\setfont\chapsf\sfbshape{17}{1000}
+\let\chapbf=\chaprm
+\setfont\chapsc\scbshape{10}{\magstep3}
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+% Section fonts (14.4pt).
+\setfont\secrm\rmbshape{12}{\magstep1}
+\setfont\secit\itbshape{10}{\magstep2}
+\setfont\secsl\slbshape{10}{\magstep2}
+\setfont\sectt\ttbshape{12}{\magstep1}
+\setfont\secttsl\ttslshape{10}{\magstep2}
+\setfont\secsf\sfbshape{12}{\magstep1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% Subsection fonts (13.15pt).
+\setfont\ssecrm\rmbshape{12}{\magstephalf}
+\setfont\ssecit\itbshape{10}{1315}
+\setfont\ssecsl\slbshape{10}{1315}
+\setfont\ssectt\ttbshape{12}{\magstephalf}
+\setfont\ssecttsl\ttslshape{10}{1315}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{1315}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled 1315
+
+% Reduced fonts for @acro in text (10pt).
+\setfont\reducedrm\rmshape{10}{1000}
+\setfont\reducedtt\ttshape{10}{1000}
+\setfont\reducedbf\bfshape{10}{1000}
+\setfont\reducedit\itshape{10}{1000}
+\setfont\reducedsl\slshape{10}{1000}
+\setfont\reducedsf\sfshape{10}{1000}
+\setfont\reducedsc\scshape{10}{1000}
+\setfont\reducedttsl\ttslshape{10}{1000}
+\font\reducedi=cmmi10
+\font\reducedsy=cmsy10
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families. Since
+% texinfo doesn't allow for producing subscripts and superscripts except
+% in the main text, we don't bother to reset \scriptfont and
+% \scriptscriptfont (which would also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+ \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy
+ \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf
+ \textfont\ttfam=\tentt \textfont\sffam=\tensf
+}
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE. We do this because \STYLE needs to also set the
+% current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire
+% \tenSTYLE to set the current font.
+%
+% Each font-changing command also sets the names \lsize (one size lower)
+% and \lllsize (three sizes lower). These relative commands are used in
+% the LaTeX logo and acronyms.
+%
+% This all needs generalizing, badly.
+%
+\def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+ \let\tenttsl=\textttsl
+ \def\lsize{reduced}\def\lllsize{smaller}%
+ \resetmathfonts \setleading{\textleading}}
+\def\titlefonts{%
+ \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl
+ \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc
+ \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy
+ \let\tenttsl=\titlettsl
+ \def\lsize{chap}\def\lllsize{subsec}%
+ \resetmathfonts \setleading{25pt}}
+\def\titlefont#1{{\titlefonts\rm #1}}
+\def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl
+ \def\lsize{sec}\def\lllsize{text}%
+ \resetmathfonts \setleading{19pt}}
+\def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+ \let\tenttsl=\secttsl
+ \def\lsize{subsec}\def\lllsize{reduced}%
+ \resetmathfonts \setleading{16pt}}
+\def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+ \let\tenttsl=\ssecttsl
+ \def\lsize{text}\def\lllsize{small}%
+ \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts
+\def\reducedfonts{%
+ \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl
+ \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc
+ \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy
+ \let\tenttsl=\reducedttsl
+ \def\lsize{small}\def\lllsize{smaller}%
+ \resetmathfonts \setleading{10.5pt}}
+\def\smallfonts{%
+ \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl
+ \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc
+ \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy
+ \let\tenttsl=\smallttsl
+ \def\lsize{smaller}\def\lllsize{smaller}%
+ \resetmathfonts \setleading{10.5pt}}
+\def\smallerfonts{%
+ \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl
+ \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc
+ \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy
+ \let\tenttsl=\smallerttsl
+ \def\lsize{smaller}\def\lllsize{smaller}%
+ \resetmathfonts \setleading{9.5pt}}
+
+% Set the fonts to use with the @small... environments.
+\let\smallexamplefonts = \smallfonts
+
+% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample
+% can fit this many characters:
+% 8.5x11=86 smallbook=72 a4=90 a5=69
+% If we use \scriptfonts (8pt), then we can fit this many characters:
+% 8.5x11=90+ smallbook=80 a4=90+ a5=77
+% For me, subjectively, the few extra characters that fit aren't worth
+% the additional smallness of 8pt. So I'm making the default 9pt.
+%
+% By the way, for comparison, here's what fits with @example (10pt):
+% 8.5x11=71 smallbook=60 a4=75 a5=58
+%
+% I wish the USA used A4 paper.
+% --karl, 24jan03.
+
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts \rm
+
+% Define these so they can be easily changed for other fonts.
+\def\angleleft{$\langle$}
+\def\angleright{$\rangle$}
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}
+\setfont\shortcontbf\bfshape{10}{\magstep1} % no cmb12
+\setfont\shortcontsl\slshape{12}{1000}
+\setfont\shortconttt\ttshape{12}{1000}
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else
+ \ptexslash\fi\fi\fi}
+\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx}
+\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx}
+
+% like \smartslanted except unconditionally uses \ttsl.
+% @var is set to this for defun arguments.
+\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx}
+
+% like \smartslanted except unconditionally use \sl. We never want
+% ttsl for book titles, do we?
+\def\cite#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\slanted=\smartslanted
+\let\var=\smartslanted
+\let\dfn=\smartslanted
+\let\emph=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph. Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+% Set sfcode to normal for the chars that usually have another value.
+% Can't use plain's \frenchspacing because it uses the `\x notation, and
+% sometimes \x has an active definition that messes things up.
+%
+\catcode`@=11
+ \def\frenchspacing{%
+ \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m
+ \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m
+ }
+\catcode`@=\other
+
+\def\t#1{%
+ {\tt \rawbackslash \frenchspacing #1}%
+ \null
+}
+\def\samp#1{`\tclose{#1}'\null}
+\setfont\keyrm\rmshape{8}{1000}
+\font\keysy=cmsy9
+\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
+ \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
+ \vbox{\hrule\kern-0.4pt
+ \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
+ \kern-0.4pt\hrule}%
+ \kern-.06em\raise0.4pt\hbox{\angleright}}}}
+% The old definition, with no lozenge:
+%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+% @file, @option are the same as @samp.
+\let\file=\samp
+\let\option=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+ {%
+ % Change normal interword space to be same as for the current font.
+ \spaceskip = \fontdimen2\font
+ %
+ % Switch to typewriter.
+ \tt
+ %
+ % But `\ ' produces the large typewriter interword space.
+ \def\ {{\spaceskip = 0pt{} }}%
+ %
+ % Turn off hyphenation.
+ \nohyphenation
+ %
+ \rawbackslash
+ \frenchspacing
+ #1%
+ }%
+ \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in @code.
+% Otherwise, it is too hard to avoid overfull hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate at a dash.
+% -- rms.
+{
+ \catcode`\-=\active
+ \catcode`\_=\active
+ %
+ \global\def\code{\begingroup
+ \catcode`\-=\active \let-\codedash
+ \catcode`\_=\active \let_\codeunder
+ \codex
+ }
+}
+
+\def\realdash{-}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{%
+ % this is all so @math{@code{var_name}+1} can work. In math mode, _
+ % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.)
+ % will therefore expand the active definition of _, which is us
+ % (inside @code that is), therefore an endless loop.
+ \ifusingtt{\ifmmode
+ \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_.
+ \else\normalunderscore \fi
+ \discretionary{}{}{}}%
+ {\_}%
+}
+\def\codex #1{\tclose{#1}\endgroup}
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
+% `example' (@kbd uses ttsl only inside of @example and friends),
+% or `code' (@kbd uses normal tty font always).
+\parseargdef\kbdinputstyle{%
+ \def\arg{#1}%
+ \ifx\arg\worddistinct
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
+ \else\ifx\arg\wordexample
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
+ \else\ifx\arg\wordcode
+ \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+ \else
+ \errhelp = \EMsimple
+ \errmessage{Unknown @kbdinputstyle option `\arg'}%
+ \fi\fi\fi
+}
+\def\worddistinct{distinct}
+\def\wordexample{example}
+\def\wordcode{code}
+
+% Default is `distinct.'
+\kbdinputstyle distinct
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\kbdfont\look}}\fi
+\else{\tclose{\kbdfont\look}}\fi}
+
+% For @indicateurl, @env, @command quotes seem unnecessary, so use \code.
+\let\indicateurl=\code
+\let\env=\code
+\let\command=\code
+
+% @uref (abbreviation for `urlref') takes an optional (comma-separated)
+% second argument specifying the text to display and an optional third
+% arg as text to display instead of (rather than in addition to) the url
+% itself. First (mandatory) arg is the url. Perhaps eventually put in
+% a hypertex \special here.
+%
+\def\uref#1{\douref #1,,,\finish}
+\def\douref#1,#2,#3,#4\finish{\begingroup
+ \unsepspaces
+ \pdfurl{#1}%
+ \setbox0 = \hbox{\ignorespaces #3}%
+ \ifdim\wd0 > 0pt
+ \unhbox0 % third arg given, show only that
+ \else
+ \setbox0 = \hbox{\ignorespaces #2}%
+ \ifdim\wd0 > 0pt
+ \ifpdf
+ \unhbox0 % PDF: 2nd arg given, show only it
+ \else
+ \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url
+ \fi
+ \else
+ \code{#1}% only url given, so show it
+ \fi
+ \fi
+ \endlink
+\endgroup}
+
+% @url synonym for @uref, since that's how everyone uses it.
+%
+\let\url=\uref
+
+% rms does not like angle brackets --karl, 17may97.
+% So now @email is just like @uref, unless we are pdf.
+%
+%\def\email#1{\angleleft{\tt #1}\angleright}
+\ifpdf
+ \def\email#1{\doemail#1,,\finish}
+ \def\doemail#1,#2,#3\finish{\begingroup
+ \unsepspaces
+ \pdfurl{mailto:#1}%
+ \setbox0 = \hbox{\ignorespaces #2}%
+ \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi
+ \endlink
+ \endgroup}
+\else
+ \let\email=\uref
+\fi
+
+% Check if we are currently using a typewriter font. Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+% @l was never documented to mean ``switch to the Lisp font'',
+% and it is not used as such in any manual I can find. We need it for
+% Polish suppressed-l. --karl, 22sep96.
+%\def\l#1{{\li #1}\null}
+
+% Explicit font changes: @r, @sc, undocumented @ii.
+\def\r#1{{\rm #1}} % roman font
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+% @acronym for "FBI", "NATO", and the like.
+% We print this one point size smaller, since it's intended for
+% all-uppercase.
+%
+\def\acronym#1{\doacronym #1,,\finish}
+\def\doacronym#1,#2,#3\finish{%
+ {\selectfonts\lsize #1}%
+ \def\temp{#2}%
+ \ifx\temp\empty \else
+ \space ({\unsepspaces \ignorespaces \temp \unskip})%
+ \fi
+}
+
+% @abbr for "Comput. J." and the like.
+% No font change, but don't do end-of-sentence spacing.
+%
+\def\abbr#1{\doabbr #1,,\finish}
+\def\doabbr#1,#2,#3\finish{%
+ {\frenchspacing #1}%
+ \def\temp{#2}%
+ \ifx\temp\empty \else
+ \space ({\unsepspaces \ignorespaces \temp \unskip})%
+ \fi
+}
+
+% @pounds{} is a sterling sign, which Knuth put in the CM italic font.
+%
+\def\pounds{{\it\$}}
+
+% @registeredsymbol - R in a circle. The font for the R should really
+% be smaller yet, but lllsize is the best we can do for now.
+% Adapted from the plain.tex definition of \copyright.
+%
+\def\registeredsymbol{%
+ $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}%
+ \hfil\crcr\Orb}}%
+ }$%
+}
+
+% Laurent Siebenmann reports \Orb undefined with:
+% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38
+% so we'll define it if necessary.
+%
+\ifx\Orb\undefined
+\def\Orb{\mathhexbox20D}
+\fi
+
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+% Do an implicit @contents or @shortcontents after @end titlepage if the
+% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage.
+%
+\newif\ifsetcontentsaftertitlepage
+ \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue
+\newif\ifsetshortcontentsaftertitlepage
+ \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue
+
+\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+\envdef\titlepage{%
+ % Open one extra group, as we want to close it in the middle of \Etitlepage.
+ \begingroup
+ \parindent=0pt \textfonts
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \let\page = \oldpage
+ \page
+ \null
+ }%
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ %
+ % Need this before the \...aftertitlepage checks so that if they are
+ % in effect the toc pages will come out with page numbers.
+ \HEADINGSon
+ %
+ % If they want short, they certainly want long too.
+ \ifsetshortcontentsaftertitlepage
+ \shortcontents
+ \contents
+ \global\let\shortcontents = \relax
+ \global\let\contents = \relax
+ \fi
+ %
+ \ifsetcontentsaftertitlepage
+ \contents
+ \global\let\contents = \relax
+ \global\let\shortcontents = \relax
+ \fi
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt width \hsize
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Macros to be used within @titlepage:
+
+\let\subtitlerm=\tenrm
+\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}
+
+\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines
+ \let\tt=\authortt}
+
+\parseargdef\title{%
+ \checkenv\titlepage
+ \leftline{\titlefonts\rm #1}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt width \hsize \vskip4pt
+}
+
+\parseargdef\subtitle{%
+ \checkenv\titlepage
+ {\subtitlefont \rightline{#1}}%
+}
+
+% @author should come last, but may come many times.
+% It can also be used inside @quotation.
+%
+\parseargdef\author{%
+ \def\temp{\quotation}%
+ \ifx\thisenv\temp
+ \def\quotationauthor{#1}% printed in \Equotation.
+ \else
+ \checkenv\titlepage
+ \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi
+ {\authorfont \leftline{#1}}%
+ \fi
+}
+
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks\evenheadline % headline on even pages
+\newtoks\oddheadline % headline on odd pages
+\newtoks\evenfootline % footline on even pages
+\newtoks\oddfootline % footline on odd pages
+
+% Now make TeX use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish}
+\def\evenheadingyyy #1\|#2\|#3\|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish}
+\def\oddheadingyyy #1\|#2\|#3\|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish}
+\def\evenfootingyyy #1\|#2\|#3\|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish}
+\def\oddfootingyyy #1\|#2\|#3\|#4\finish{%
+ \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}%
+ %
+ % Leave some space for the footline. Hopefully ok to assume
+ % @evenfooting will not be used by itself.
+ \global\advance\pageheight by -\baselineskip
+ \global\advance\vsize by -\baselineskip
+}
+
+\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}}
+
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off at the start of a document,
+% and turned `on' after @end titlepage.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{%
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{%
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+\let\contentsalignmacro = \chappager
+
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{%
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+
+% Subroutines used in generating headings
+% This produces Day Month Year style of output.
+% Only define if not already defined, in case a txi-??.tex file has set
+% up a different format (e.g., txi-cs.tex does this).
+\ifx\today\undefined
+\def\today{%
+ \number\day\space
+ \ifcase\month
+ \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr
+ \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug
+ \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec
+ \fi
+ \space\number\year}
+\fi
+
+% @settitle line... specifies the title of the document, for headings.
+% It generates no output of its own.
+\def\thistitle{\putwordNoTitle}
+\def\settitle{\parsearg{\gdef\thistitle}}
+
+
+\message{tables,}
+% Tables -- @table, @ftable, @vtable, @item(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @ftable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\newif\ifitemxneedsnegativevskip
+
+\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemindicate{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ %
+ % Make this a paragraph so we get the \parskip glue and wrapping,
+ % but leave it ragged-right.
+ \begingroup
+ \advance\leftskip by-\tableindent
+ \advance\hsize by\tableindent
+ \advance\rightskip by0pt plus1fil
+ \leavevmode\unhbox0\par
+ \endgroup
+ %
+ % We're going to be starting a paragraph, but we don't want the
+ % \parskip glue -- logically it's part of the @item we just started.
+ \nobreak \vskip-\parskip
+ %
+ % Stop a page break at the \parskip glue coming up. However, if
+ % what follows is an environment such as @example, there will be no
+ % \parskip glue; then the negative vskip we just inserted would
+ % cause the example and the item to crash together. So we use this
+ % bizarre value of 10001 as a signal to \aboveenvbreak to insert
+ % \parskip glue after all. Section titles are handled this way also.
+ %
+ \penalty 10001
+ \endgroup
+ \itemxneedsnegativevskipfalse
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line.
+ \noindent
+ % Do this with kerns and \unhbox so that if there is a footnote in
+ % the item text, it can migrate to the main vertical list and
+ % eventually be printed.
+ \nobreak\kern-\tableindent
+ \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0
+ \unhbox0
+ \nobreak\kern\dimen0
+ \endgroup
+ \itemxneedsnegativevskiptrue
+ \fi
+}
+
+\def\item{\errmessage{@item while not in a list environment}}
+\def\itemx{\errmessage{@itemx while not in a list environment}}
+
+% @table, @ftable, @vtable.
+\envdef\table{%
+ \let\itemindex\gobble
+ \tablex
+}
+\envdef\ftable{%
+ \def\itemindex ##1{\doind {fn}{\code{##1}}}%
+ \tablex
+}
+\envdef\vtable{%
+ \def\itemindex ##1{\doind {vr}{\code{##1}}}%
+ \tablex
+}
+\def\tablex#1{%
+ \def\itemindicate{#1}%
+ \parsearg\tabley
+}
+\def\tabley#1{%
+ {%
+ \makevalueexpandable
+ \edef\temp{\noexpand\tablez #1\space\space\space}%
+ \expandafter
+ }\temp \endtablez
+}
+\def\tablez #1 #2 #3 #4\endtablez{%
+ \aboveenvbreak
+ \ifnum 0#1>0 \advance \leftskip by #1\mil \fi
+ \ifnum 0#2>0 \tableindent=#2\mil \fi
+ \ifnum 0#3>0 \advance \rightskip by #3\mil \fi
+ \itemmax=\tableindent
+ \advance \itemmax by -\itemmargin
+ \advance \leftskip by \tableindent
+ \exdentamount=\tableindent
+ \parindent = 0pt
+ \parskip = \smallskipamount
+ \ifdim \parskip=0pt \parskip=2pt \fi
+ \let\item = \internalBitem
+ \let\itemx = \internalBitemx
+}
+\def\Etable{\endgraf\afterenvbreak}
+\let\Eftable\Etable
+\let\Evtable\Etable
+\let\Eitemize\Etable
+\let\Eenumerate\Etable
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\envdef\itemize{\parsearg\doitemize}
+
+\def\doitemize#1{%
+ \aboveenvbreak
+ \itemmax=\itemindent
+ \advance\itemmax by -\itemmargin
+ \advance\leftskip by \itemindent
+ \exdentamount=\itemindent
+ \parindent=0pt
+ \parskip=\smallskipamount
+ \ifdim\parskip=0pt \parskip=2pt \fi
+ \def\itemcontents{#1}%
+ % @itemize with no arg is equivalent to @itemize @bullet.
+ \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi
+ \let\item=\itemizeitem
+}
+
+% Definition of @item while inside @itemize and @enumerate.
+%
+\def\itemizeitem{%
+ \advance\itemno by 1 % for enumerations
+ {\let\par=\endgraf \smallbreak}% reasonable place to break
+ {%
+ % If the document has an @itemize directly after a section title, a
+ % \nobreak will be last on the list, and \sectionheading will have
+ % done a \vskip-\parskip. In that case, we don't want to zero
+ % parskip, or the item text will crash with the heading. On the
+ % other hand, when there is normal text preceding the item (as there
+ % usually is), we do want to zero parskip, or there would be too much
+ % space. In that case, we won't have a \nobreak before. At least
+ % that's the theory.
+ \ifnum\lastpenalty<10000 \parskip=0in \fi
+ \noindent
+ \hbox to 0pt{\hss \itemcontents \kern\itemmargin}%
+ \vadjust{\penalty 1200}}% not good to break after first line of item.
+ \flushcr
+}
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list. No
+% argument is the same as `1'.
+%
+\envparseargdef\enumerate{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+}
+
+% An @enumerate whose labels are integers. The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+}
+
+% Call \doitemize, adding a period to the first argument and supplying the
+% common last two arguments. Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+ \advance\itemno by -1
+ \doitemize{#1.}\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+
+% @multitable macros
+% Amy Hendrickson, 8/18/94, 3/6/96
+%
+% @multitable ... @end multitable will make as many columns as desired.
+% Contents of each column will wrap at width given in preamble. Width
+% can be specified either with sample text given in a template line,
+% or in percent of \hsize, the current width of text on page.
+
+% Table can continue over pages but will only break between lines.
+
+% To make preamble:
+%
+% Either define widths of columns in terms of percent of \hsize:
+% @multitable @columnfractions .25 .3 .45
+% @item ...
+%
+% Numbers following @columnfractions are the percent of the total
+% current hsize to be used for each column. You may use as many
+% columns as desired.
+
+
+% Or use a template:
+% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+% @item ...
+% using the widest term desired in each column.
+
+% Each new table line starts with @item, each subsequent new column
+% starts with @tab. Empty columns may be produced by supplying @tab's
+% with nothing between them for as many times as empty columns are needed,
+% ie, @tab@tab@tab will produce two empty columns.
+
+% @item, @tab do not need to be on their own lines, but it will not hurt
+% if they are.
+
+% Sample multitable:
+
+% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+% @item first col stuff @tab second col stuff @tab third col
+% @item
+% first col stuff
+% @tab
+% second col stuff
+% @tab
+% third col
+% @item first col stuff @tab second col stuff
+% @tab Many paragraphs of text may be used in any column.
+%
+% They will wrap at the width determined by the template.
+% @item@tab@tab This will be in third column.
+% @end multitable
+
+% Default dimensions may be reset by user.
+% @multitableparskip is vertical space between paragraphs in table.
+% @multitableparindent is paragraph indent in table.
+% @multitablecolmargin is horizontal space to be left between columns.
+% @multitablelinespace is space to leave between table items, baseline
+% to baseline.
+% 0pt means it depends on current normal line spacing.
+%
+\newskip\multitableparskip
+\newskip\multitableparindent
+\newdimen\multitablecolspace
+\newskip\multitablelinespace
+\multitableparskip=0pt
+\multitableparindent=6pt
+\multitablecolspace=12pt
+\multitablelinespace=0pt
+
+% Macros used to set up halign preamble:
+%
+\let\endsetuptable\relax
+\def\xendsetuptable{\endsetuptable}
+\let\columnfractions\relax
+\def\xcolumnfractions{\columnfractions}
+\newif\ifsetpercent
+
+% #1 is the @columnfraction, usually a decimal number like .5, but might
+% be just 1. We just use it, whatever it is.
+%
+\def\pickupwholefraction#1 {%
+ \global\advance\colcount by 1
+ \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}%
+ \setuptable
+}
+
+\newcount\colcount
+\def\setuptable#1{%
+ \def\firstarg{#1}%
+ \ifx\firstarg\xendsetuptable
+ \let\go = \relax
+ \else
+ \ifx\firstarg\xcolumnfractions
+ \global\setpercenttrue
+ \else
+ \ifsetpercent
+ \let\go\pickupwholefraction
+ \else
+ \global\advance\colcount by 1
+ \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a
+ % separator; typically that is always in the input, anyway.
+ \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
+ \fi
+ \fi
+ \ifx\go\pickupwholefraction
+ % Put the argument back for the \pickupwholefraction call, so
+ % we'll always have a period there to be parsed.
+ \def\go{\pickupwholefraction#1}%
+ \else
+ \let\go = \setuptable
+ \fi%
+ \fi
+ \go
+}
+
+% multitable-only commands.
+%
+% @headitem starts a heading row, which we typeset in bold.
+% Assignments have to be global since we are inside the implicit group
+% of an alignment entry. Note that \everycr resets \everytab.
+\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}%
+%
+% A \tab used to include \hskip1sp. But then the space in a template
+% line is not enough. That is bad. So let's go back to just `&' until
+% we encounter the problem it was intended to solve again.
+% --karl, nathan@acm.org, 20apr99.
+\def\tab{\checkenv\multitable &\the\everytab}%
+
+% @multitable ... @end multitable definitions:
+%
+\newtoks\everytab % insert after every tab.
+%
+\envdef\multitable{%
+ \vskip\parskip
+ \startsavinginserts
+ %
+ % @item within a multitable starts a normal row.
+ % We use \def instead of \let so that if one of the multitable entries
+ % contains an @itemize, we don't choke on the \item (seen as \crcr aka
+ % \endtemplate) expanding \doitemize.
+ \def\item{\crcr}%
+ %
+ \tolerance=9500
+ \hbadness=9500
+ \setmultitablespacing
+ \parskip=\multitableparskip
+ \parindent=\multitableparindent
+ \overfullrule=0pt
+ \global\colcount=0
+ %
+ \everycr = {%
+ \noalign{%
+ \global\everytab={}%
+ \global\colcount=0 % Reset the column counter.
+ % Check for saved footnotes, etc.
+ \checkinserts
+ % Keeps underfull box messages off when table breaks over pages.
+ %\filbreak
+ % Maybe so, but it also creates really weird page breaks when the
+ % table breaks over pages. Wouldn't \vfil be better? Wait until the
+ % problem manifests itself, so it can be fixed for real --karl.
+ }%
+ }%
+ %
+ \parsearg\domultitable
+}
+\def\domultitable#1{%
+ % To parse everything between @multitable and @item:
+ \setuptable#1 \endsetuptable
+ %
+ % This preamble sets up a generic column definition, which will
+ % be used as many times as user calls for columns.
+ % \vtop will set a single line and will also let text wrap and
+ % continue for many paragraphs if desired.
+ \halign\bgroup &%
+ \global\advance\colcount by 1
+ \multistrut
+ \vtop{%
+ % Use the current \colcount to find the correct column width:
+ \hsize=\expandafter\csname col\the\colcount\endcsname
+ %
+ % In order to keep entries from bumping into each other
+ % we will add a \leftskip of \multitablecolspace to all columns after
+ % the first one.
+ %
+ % If a template has been used, we will add \multitablecolspace
+ % to the width of each template entry.
+ %
+ % If the user has set preamble in terms of percent of \hsize we will
+ % use that dimension as the width of the column, and the \leftskip
+ % will keep entries from bumping into each other. Table will start at
+ % left margin and final column will justify at right margin.
+ %
+ % Make sure we don't inherit \rightskip from the outer environment.
+ \rightskip=0pt
+ \ifnum\colcount=1
+ % The first column will be indented with the surrounding text.
+ \advance\hsize by\leftskip
+ \else
+ \ifsetpercent \else
+ % If user has not set preamble in terms of percent of \hsize
+ % we will advance \hsize by \multitablecolspace.
+ \advance\hsize by \multitablecolspace
+ \fi
+ % In either case we will make \leftskip=\multitablecolspace:
+ \leftskip=\multitablecolspace
+ \fi
+ % Ignoring space at the beginning and end avoids an occasional spurious
+ % blank line, when TeX decides to break the line at the space before the
+ % box from the multistrut, so the strut ends up on a line by itself.
+ % For example:
+ % @multitable @columnfractions .11 .89
+ % @item @code{#}
+ % @tab Legal holiday which is valid in major parts of the whole country.
+ % Is automatically provided with highlighting sequences respectively
+ % marking characters.
+ \noindent\ignorespaces##\unskip\multistrut
+ }\cr
+}
+\def\Emultitable{%
+ \crcr
+ \egroup % end the \halign
+ \global\setpercentfalse
+}
+
+\def\setmultitablespacing{% test to see if user has set \multitablelinespace.
+% If so, do nothing. If not, give it an appropriate dimension based on
+% current baselineskip.
+\ifdim\multitablelinespace=0pt
+\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip
+\global\advance\multitablelinespace by-\ht0
+%% strut to put in table in case some entry doesn't have descenders,
+%% to keep lines equally spaced
+\let\multistrut = \strut
+\else
+%% FIXME: what is \box0 supposed to be?
+\gdef\multistrut{\vrule height\multitablelinespace depth\dp0
+width0pt\relax} \fi
+%% Test to see if parskip is larger than space between lines of
+%% table. If not, do nothing.
+%% If so, set to same dimension as multitablelinespace.
+\ifdim\multitableparskip>\multitablelinespace
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi%
+\ifdim\multitableparskip=0pt
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi}
+
+
+\message{conditionals,}
+
+% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext,
+% @ifnotxml always succeed. They currently do nothing; we don't
+% attempt to check whether the conditionals are properly nested. But we
+% have to remember that they are conditionals, so that @end doesn't
+% attempt to close an environment group.
+%
+\def\makecond#1{%
+ \expandafter\let\csname #1\endcsname = \relax
+ \expandafter\let\csname iscond.#1\endcsname = 1
+}
+\makecond{iftex}
+\makecond{ifnotdocbook}
+\makecond{ifnothtml}
+\makecond{ifnotinfo}
+\makecond{ifnotplaintext}
+\makecond{ifnotxml}
+
+% Ignore @ignore, @ifhtml, @ifinfo, and the like.
+%
+\def\direntry{\doignore{direntry}}
+\def\documentdescription{\doignore{documentdescription}}
+\def\docbook{\doignore{docbook}}
+\def\html{\doignore{html}}
+\def\ifdocbook{\doignore{ifdocbook}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifnottex{\doignore{ifnottex}}
+\def\ifplaintext{\doignore{ifplaintext}}
+\def\ifxml{\doignore{ifxml}}
+\def\ignore{\doignore{ignore}}
+\def\menu{\doignore{menu}}
+\def\xml{\doignore{xml}}
+
+% Ignore text until a line `@end #1', keeping track of nested conditionals.
+%
+% A count to remember the depth of nesting.
+\newcount\doignorecount
+
+\def\doignore#1{\begingroup
+ % Scan in ``verbatim'' mode:
+ \catcode`\@ = \other
+ \catcode`\{ = \other
+ \catcode`\} = \other
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \spaceisspace
+ %
+ % Count number of #1's that we've seen.
+ \doignorecount = 0
+ %
+ % Swallow text until we reach the matching `@end #1'.
+ \dodoignore{#1}%
+}
+
+{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source.
+ \obeylines %
+ %
+ \gdef\dodoignore#1{%
+ % #1 contains the command name as a string, e.g., `ifinfo'.
+ %
+ % Define a command to find the next `@end #1', which must be on a line
+ % by itself.
+ \long\def\doignoretext##1^^M@end #1{\doignoretextyyy##1^^M@#1\_STOP_}%
+ % And this command to find another #1 command, at the beginning of a
+ % line. (Otherwise, we would consider a line `@c @ifset', for
+ % example, to count as an @ifset for nesting.)
+ \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}%
+ %
+ % And now expand that command.
+ \obeylines %
+ \doignoretext ^^M%
+ }%
+}
+
+\def\doignoreyyy#1{%
+ \def\temp{#1}%
+ \ifx\temp\empty % Nothing found.
+ \let\next\doignoretextzzz
+ \else % Found a nested condition, ...
+ \advance\doignorecount by 1
+ \let\next\doignoretextyyy % ..., look for another.
+ % If we're here, #1 ends with ^^M\ifinfo (for example).
+ \fi
+ \next #1% the token \_STOP_ is present just after this macro.
+}
+
+% We have to swallow the remaining "\_STOP_".
+%
+\def\doignoretextzzz#1{%
+ \ifnum\doignorecount = 0 % We have just found the outermost @end.
+ \let\next\enddoignore
+ \else % Still inside a nested condition.
+ \advance\doignorecount by -1
+ \let\next\doignoretext % Look for the next @end.
+ \fi
+ \next
+}
+
+% Finish off ignored text.
+\def\enddoignore{\endgroup\ignorespaces}
+
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.
+% We rely on the fact that \parsearg sets \catcode`\ =10.
+%
+\parseargdef\set{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+ {%
+ \makevalueexpandable
+ \def\temp{#2}%
+ \edef\next{\gdef\makecsname{SET#1}}%
+ \ifx\temp\empty
+ \next{}%
+ \else
+ \setzzz#2\endsetzzz
+ \fi
+ }%
+}
+% Remove the trailing space \setxxx inserted.
+\def\setzzz#1 \endsetzzz{\next{#1}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\parseargdef\clear{%
+ {%
+ \makevalueexpandable
+ \global\expandafter\let\csname SET#1\endcsname=\relax
+ }%
+}
+
+% @value{foo} gets the text saved in variable foo.
+\def\value{\begingroup\makevalueexpandable\valuexxx}
+\def\valuexxx#1{\expandablevalue{#1}\endgroup}
+{
+ \catcode`\- = \active \catcode`\_ = \active
+ %
+ \gdef\makevalueexpandable{%
+ \let\value = \expandablevalue
+ % We don't want these characters active, ...
+ \catcode`\-=\other \catcode`\_=\other
+ % ..., but we might end up with active ones in the argument if
+ % we're called from @code, as @code{@value{foo-bar_}}, though.
+ % So \let them to their normal equivalents.
+ \let-\realdash \let_\normalunderscore
+ }
+}
+
+% We have this subroutine so that we can handle at least some @value's
+% properly in indexes (we call \makevalueexpandable in \indexdummies).
+% The command has to be fully expandable (if the variable is set), since
+% the result winds up in the index file. This means that if the
+% variable's value contains other Texinfo commands, it's almost certain
+% it will fail (although perhaps we could fix that with sufficient work
+% to do a one-level expansion on the result, instead of complete).
+%
+\def\expandablevalue#1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ {[No value for ``#1'']}%
+ \message{Variable `#1', used in @value, is not set.}%
+ \else
+ \csname SET#1\endcsname
+ \fi
+}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+% To get special treatment of `@end ifset,' call \makeond and the redefine.
+%
+\makecond{ifset}
+\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}}
+\def\doifset#1#2{%
+ {%
+ \makevalueexpandable
+ \let\next=\empty
+ \expandafter\ifx\csname SET#2\endcsname\relax
+ #1% If not set, redefine \next.
+ \fi
+ \expandafter
+ }\next
+}
+\def\ifsetfail{\doignore{ifset}}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+% The `\else' inside the `\doifset' parameter is a trick to reuse the
+% above code: if the variable is not set, do nothing, if it is set,
+% then redefine \next to \ifclearfail.
+%
+\makecond{ifclear}
+\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}}
+\def\ifclearfail{\doignore{ifclear}}
+
+% @dircategory CATEGORY -- specify a category of the dir file
+% which this file should belong to. Ignore this in TeX.
+\let\dircategory=\comment
+
+% @defininfoenclose.
+\let\definfoenclose=\comment
+
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+%
+\def\newindex#1{%
+ \iflinks
+ \expandafter\newwrite \csname#1indfile\endcsname
+ \openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+ \fi
+ \expandafter\xdef\csname#1index\endcsname{% % Define @#1index
+ \noexpand\doindex{#1}}
+}
+
+% @defindex foo == \newindex{foo}
+%
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+%
+\def\defcodeindex{\parsearg\newcodeindex}
+%
+\def\newcodeindex#1{%
+ \iflinks
+ \expandafter\newwrite \csname#1indfile\endcsname
+ \openout \csname#1indfile\endcsname \jobname.#1
+ \fi
+ \expandafter\xdef\csname#1index\endcsname{%
+ \noexpand\docodeindex{#1}}%
+}
+
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+%
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+%
+\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}}
+\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}}
+
+% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo),
+% #3 the target index (bar).
+\def\dosynindex#1#2#3{%
+ % Only do \closeout if we haven't already done it, else we'll end up
+ % closing the target index.
+ \expandafter \ifx\csname donesynindex#2\endcsname \undefined
+ % The \closeout helps reduce unnecessary open files; the limit on the
+ % Acorn RISC OS is a mere 16 files.
+ \expandafter\closeout\csname#2indfile\endcsname
+ \expandafter\let\csname\donesynindex#2\endcsname = 1
+ \fi
+ % redefine \fooindfile:
+ \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname
+ \expandafter\let\csname#2indfile\endcsname=\temp
+ % redefine \fooindex:
+ \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+% Take care of Texinfo commands that can appear in an index entry.
+% Since there are some commands we want to expand, and others we don't,
+% we have to laboriously prevent expansion for those that we don't.
+%
+\def\indexdummies{%
+ \def\@{@}% change to @@ when we switch to @ as escape char in index files.
+ \def\ {\realbackslash\space }%
+ % Need these in case \tex is in effect and \{ is a \delimiter again.
+ % But can't use \lbracecmd and \rbracecmd because texindex assumes
+ % braces and backslashes are used only as delimiters.
+ \let\{ = \mylbrace
+ \let\} = \myrbrace
+ %
+ % \definedummyword defines \#1 as \realbackslash #1\space, thus
+ % effectively preventing its expansion. This is used only for control
+ % words, not control letters, because the \space would be incorrect
+ % for control characters, but is needed to separate the control word
+ % from whatever follows.
+ %
+ % For control letters, we have \definedummyletter, which omits the
+ % space.
+ %
+ % These can be used both for control words that take an argument and
+ % those that do not. If it is followed by {arg} in the input, then
+ % that will dutifully get written to the index (or wherever).
+ %
+ \def\definedummyword##1{%
+ \expandafter\def\csname ##1\endcsname{\realbackslash ##1\space}%
+ }%
+ \def\definedummyletter##1{%
+ \expandafter\def\csname ##1\endcsname{\realbackslash ##1}%
+ }%
+ \let\definedummyaccent\definedummyletter
+ %
+ % Do the redefinitions.
+ \commondummies
+}
+
+% For the aux file, @ is the escape character. So we want to redefine
+% everything using @ instead of \realbackslash. When everything uses
+% @, this will be simpler.
+%
+\def\atdummies{%
+ \def\@{@@}%
+ \def\ {@ }%
+ \let\{ = \lbraceatcmd
+ \let\} = \rbraceatcmd
+ %
+ % (See comments in \indexdummies.)
+ \def\definedummyword##1{%
+ \expandafter\def\csname ##1\endcsname{@##1\space}%
+ }%
+ \def\definedummyletter##1{%
+ \expandafter\def\csname ##1\endcsname{@##1}%
+ }%
+ \let\definedummyaccent\definedummyletter
+ %
+ % Do the redefinitions.
+ \commondummies
+}
+
+% Called from \indexdummies and \atdummies. \definedummyword and
+% \definedummyletter must be defined first.
+%
+\def\commondummies{%
+ %
+ \normalturnoffactive
+ %
+ \commondummiesnofonts
+ %
+ \definedummyletter{_}%
+ %
+ % Non-English letters.
+ \definedummyword{AA}%
+ \definedummyword{AE}%
+ \definedummyword{L}%
+ \definedummyword{OE}%
+ \definedummyword{O}%
+ \definedummyword{aa}%
+ \definedummyword{ae}%
+ \definedummyword{l}%
+ \definedummyword{oe}%
+ \definedummyword{o}%
+ \definedummyword{ss}%
+ \definedummyword{exclamdown}%
+ \definedummyword{questiondown}%
+ \definedummyword{ordf}%
+ \definedummyword{ordm}%
+ %
+ % Although these internal commands shouldn't show up, sometimes they do.
+ \definedummyword{bf}%
+ \definedummyword{gtr}%
+ \definedummyword{hat}%
+ \definedummyword{less}%
+ \definedummyword{sf}%
+ \definedummyword{sl}%
+ \definedummyword{tclose}%
+ \definedummyword{tt}%
+ %
+ \definedummyword{LaTeX}%
+ \definedummyword{TeX}%
+ %
+ % Assorted special characters.
+ \definedummyword{bullet}%
+ \definedummyword{comma}%
+ \definedummyword{copyright}%
+ \definedummyword{registeredsymbol}%
+ \definedummyword{dots}%
+ \definedummyword{enddots}%
+ \definedummyword{equiv}%
+ \definedummyword{error}%
+ \definedummyword{expansion}%
+ \definedummyword{minus}%
+ \definedummyword{pounds}%
+ \definedummyword{point}%
+ \definedummyword{print}%
+ \definedummyword{result}%
+ %
+ % Handle some cases of @value -- where it does not contain any
+ % (non-fully-expandable) commands.
+ \makevalueexpandable
+ %
+ % Normal spaces, not active ones.
+ \unsepspaces
+ %
+ % No macro expansion.
+ \turnoffmacros
+}
+
+% \commondummiesnofonts: common to \commondummies and \indexnofonts.
+%
+% Better have this without active chars.
+{
+ \catcode`\~=\other
+ \gdef\commondummiesnofonts{%
+ % Control letters and accents.
+ \definedummyletter{!}%
+ \definedummyaccent{"}%
+ \definedummyaccent{'}%
+ \definedummyletter{*}%
+ \definedummyaccent{,}%
+ \definedummyletter{.}%
+ \definedummyletter{/}%
+ \definedummyletter{:}%
+ \definedummyaccent{=}%
+ \definedummyletter{?}%
+ \definedummyaccent{^}%
+ \definedummyaccent{`}%
+ \definedummyaccent{~}%
+ \definedummyword{u}%
+ \definedummyword{v}%
+ \definedummyword{H}%
+ \definedummyword{dotaccent}%
+ \definedummyword{ringaccent}%
+ \definedummyword{tieaccent}%
+ \definedummyword{ubaraccent}%
+ \definedummyword{udotaccent}%
+ \definedummyword{dotless}%
+ %
+ % Texinfo font commands.
+ \definedummyword{b}%
+ \definedummyword{i}%
+ \definedummyword{r}%
+ \definedummyword{sc}%
+ \definedummyword{t}%
+ %
+ % Commands that take arguments.
+ \definedummyword{acronym}%
+ \definedummyword{cite}%
+ \definedummyword{code}%
+ \definedummyword{command}%
+ \definedummyword{dfn}%
+ \definedummyword{emph}%
+ \definedummyword{env}%
+ \definedummyword{file}%
+ \definedummyword{kbd}%
+ \definedummyword{key}%
+ \definedummyword{math}%
+ \definedummyword{option}%
+ \definedummyword{samp}%
+ \definedummyword{strong}%
+ \definedummyword{tie}%
+ \definedummyword{uref}%
+ \definedummyword{url}%
+ \definedummyword{var}%
+ \definedummyword{verb}%
+ \definedummyword{w}%
+ }
+}
+
+% \indexnofonts is used when outputting the strings to sort the index
+% by, and when constructing control sequence names. It eliminates all
+% control sequences and just writes whatever the best ASCII sort string
+% would be for a given command (usually its argument).
+%
+\def\indexnofonts{%
+ % Accent commands should become @asis.
+ \def\definedummyaccent##1{%
+ \expandafter\let\csname ##1\endcsname\asis
+ }%
+ % We can just ignore other control letters.
+ \def\definedummyletter##1{%
+ \expandafter\def\csname ##1\endcsname{}%
+ }%
+ % Hopefully, all control words can become @asis.
+ \let\definedummyword\definedummyaccent
+ %
+ \commondummiesnofonts
+ %
+ % Don't no-op \tt, since it isn't a user-level command
+ % and is used in the definitions of the active chars like <, >, |, etc.
+ % Likewise with the other plain tex font commands.
+ %\let\tt=\asis
+ %
+ \def\ { }%
+ \def\@{@}%
+ % how to handle braces?
+ \def\_{\normalunderscore}%
+ %
+ % Non-English letters.
+ \def\AA{AA}%
+ \def\AE{AE}%
+ \def\L{L}%
+ \def\OE{OE}%
+ \def\O{O}%
+ \def\aa{aa}%
+ \def\ae{ae}%
+ \def\l{l}%
+ \def\oe{oe}%
+ \def\o{o}%
+ \def\ss{ss}%
+ \def\exclamdown{!}%
+ \def\questiondown{?}%
+ \def\ordf{a}%
+ \def\ordm{o}%
+ %
+ \def\LaTeX{LaTeX}%
+ \def\TeX{TeX}%
+ %
+ % Assorted special characters.
+ % (The following {} will end up in the sort string, but that's ok.)
+ \def\bullet{bullet}%
+ \def\comma{,}%
+ \def\copyright{copyright}%
+ \def\registeredsymbol{R}%
+ \def\dots{...}%
+ \def\enddots{...}%
+ \def\equiv{==}%
+ \def\error{error}%
+ \def\expansion{==>}%
+ \def\minus{-}%
+ \def\pounds{pounds}%
+ \def\point{.}%
+ \def\print{-|}%
+ \def\result{=>}%
+ %
+ % Don't write macro names.
+ \emptyusermacros
+}
+
+\let\indexbackslash=0 %overridden during \printindex.
+\let\SETmarginindex=\relax % put index entries in margin (undocumented)?
+
+% Most index entries go through here, but \dosubind is the general case.
+% #1 is the index name, #2 is the entry text.
+\def\doind#1#2{\dosubind{#1}{#2}{}}
+
+% Workhorse for all \fooindexes.
+% #1 is name of index, #2 is stuff to put there, #3 is subentry --
+% empty if called from \doind, as we usually are (the main exception
+% is with most defuns, which call us directly).
+%
+\def\dosubind#1#2#3{%
+ \iflinks
+ {%
+ % Store the main index entry text (including the third arg).
+ \toks0 = {#2}%
+ % If third arg is present, precede it with a space.
+ \def\thirdarg{#3}%
+ \ifx\thirdarg\empty \else
+ \toks0 = \expandafter{\the\toks0 \space #3}%
+ \fi
+ %
+ \edef\writeto{\csname#1indfile\endcsname}%
+ %
+ \ifvmode
+ \dosubindsanitize
+ \else
+ \dosubindwrite
+ \fi
+ }%
+ \fi
+}
+
+% Write the entry in \toks0 to the index file:
+%
+\def\dosubindwrite{%
+ % Put the index entry in the margin if desired.
+ \ifx\SETmarginindex\relax\else
+ \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}%
+ \fi
+ %
+ % Remember, we are within a group.
+ \indexdummies % Must do this here, since \bf, etc expand at this stage
+ \escapechar=`\\
+ \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now
+ % so it will be output as is; and it will print as backslash.
+ %
+ % Process the index entry with all font commands turned off, to
+ % get the string to sort by.
+ {\indexnofonts
+ \edef\temp{\the\toks0}% need full expansion
+ \xdef\indexsorttmp{\temp}%
+ }%
+ %
+ % Set up the complete index entry, with both the sort key and
+ % the original text, including any font commands. We write
+ % three arguments to \entry to the .?? file (four in the
+ % subentry case), texindex reduces to two when writing the .??s
+ % sorted result.
+ \edef\temp{%
+ \write\writeto{%
+ \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}%
+ }%
+ \temp
+}
+
+% Take care of unwanted page breaks:
+%
+% If a skip is the last thing on the list now, preserve it
+% by backing up by \lastskip, doing the \write, then inserting
+% the skip again. Otherwise, the whatsit generated by the
+% \write will make \lastskip zero. The result is that sequences
+% like this:
+% @end defun
+% @tindex whatever
+% @defun ...
+% will have extra space inserted, because the \medbreak in the
+% start of the @defun won't see the skip inserted by the @end of
+% the previous defun.
+%
+% But don't do any of this if we're not in vertical mode. We
+% don't want to do a \vskip and prematurely end a paragraph.
+%
+% Avoid page breaks due to these extra skips, too.
+%
+% But wait, there is a catch there:
+% We'll have to check whether \lastskip is zero skip. \ifdim is not
+% sufficient for this purpose, as it ignores stretch and shrink parts
+% of the skip. The only way seems to be to check the textual
+% representation of the skip.
+%
+% The following is almost like \def\zeroskipmacro{0.0pt} except that
+% the ``p'' and ``t'' characters have catcode \other, not 11 (letter).
+%
+\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname}
+%
+% ..., ready, GO:
+%
+\def\dosubindsanitize{%
+ % \lastskip and \lastpenalty cannot both be nonzero simultaneously.
+ \skip0 = \lastskip
+ \edef\lastskipmacro{\the\lastskip}%
+ \count255 = \lastpenalty
+ %
+ % If \lastskip is nonzero, that means the last item was a
+ % skip. And since a skip is discardable, that means this
+ % -\skip0 glue we're inserting is preceded by a
+ % non-discardable item, therefore it is not a potential
+ % breakpoint, therefore no \nobreak needed.
+ \ifx\lastskipmacro\zeroskipmacro
+ \else
+ \vskip-\skip0
+ \fi
+ %
+ \dosubindwrite
+ %
+ \ifx\lastskipmacro\zeroskipmacro
+ % If \lastskip was zero, perhaps the last item was a penalty, and
+ % perhaps it was >=10000, e.g., a \nobreak. In that case, we want
+ % to re-insert the same penalty (values >10000 are used for various
+ % signals); since we just inserted a non-discardable item, any
+ % following glue (such as a \parskip) would be a breakpoint. For example:
+ %
+ % @deffn deffn-whatever
+ % @vindex index-whatever
+ % Description.
+ % would allow a break between the index-whatever whatsit
+ % and the "Description." paragraph.
+ \ifnum\count255>9999 \penalty\count255 \fi
+ \else
+ % On the other hand, if we had a nonzero \lastskip,
+ % this make-up glue would be preceded by a non-discardable item
+ % (the whatsit from the \write), so we must insert a \nobreak.
+ \nobreak\vskip\skip0
+ \fi
+}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% @printindex causes a particular index (the ??s file) to get printed.
+% It does not print any chapter heading (usually an @unnumbered).
+%
+\parseargdef\printindex{\begingroup
+ \dobreak \chapheadingskip{10000}%
+ %
+ \smallfonts \rm
+ \tolerance = 9500
+ \everypar = {}% don't want the \kern\-parindent from indentation suppression.
+ %
+ % See if the index file exists and is nonempty.
+ % Change catcode of @ here so that if the index file contains
+ % \initial {@}
+ % as its first line, TeX doesn't complain about mismatched braces
+ % (because it thinks @} is a control sequence).
+ \catcode`\@ = 11
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ \putwordIndexNonexistent
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ \putwordIndexIsEmpty
+ \else
+ % Index files are almost Texinfo source, but we use \ as the escape
+ % character. It would be better to use @, but that's too big a change
+ % to make right now.
+ \def\indexbackslash{\backslashcurfont}%
+ \catcode`\\ = 0
+ \escapechar = `\\
+ \begindoublecolumns
+ \input \jobname.#1s
+ \enddoublecolumns
+ \fi
+ \fi
+ \closein 1
+\endgroup}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+\def\initial#1{{%
+ % Some minor font changes for the special characters.
+ \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+ %
+ % Remove any glue we may have, we'll be inserting our own.
+ \removelastskip
+ %
+ % We like breaks before the index initials, so insert a bonus.
+ \nobreak
+ \vskip 0pt plus 3\baselineskip
+ \penalty 0
+ \vskip 0pt plus -3\baselineskip
+ %
+ % Typeset the initial. Making this add up to a whole number of
+ % baselineskips increases the chance of the dots lining up from column
+ % to column. It still won't often be perfect, because of the stretch
+ % we need before each entry, but it's better.
+ %
+ % No shrink because it confuses \balancecolumns.
+ \vskip 1.67\baselineskip plus .5\baselineskip
+ \leftline{\secbf #1}%
+ % Do our best not to break after the initial.
+ \nobreak
+ \vskip .33\baselineskip plus .1\baselineskip
+}}
+
+% \entry typesets a paragraph consisting of the text (#1), dot leaders, and
+% then page number (#2) flushed to the right margin. It is used for index
+% and table of contents entries. The paragraph is indented by \leftskip.
+%
+% A straightforward implementation would start like this:
+% \def\entry#1#2{...
+% But this frozes the catcodes in the argument, and can cause problems to
+% @code, which sets - active. This problem was fixed by a kludge---
+% ``-'' was active throughout whole index, but this isn't really right.
+%
+% The right solution is to prevent \entry from swallowing the whole text.
+% --kasal, 21nov03
+\def\entry{%
+ \begingroup
+ %
+ % Start a new paragraph if necessary, so our assignments below can't
+ % affect previous text.
+ \par
+ %
+ % Do not fill out the last line with white space.
+ \parfillskip = 0in
+ %
+ % No extra space above this paragraph.
+ \parskip = 0in
+ %
+ % Do not prefer a separate line ending with a hyphen to fewer lines.
+ \finalhyphendemerits = 0
+ %
+ % \hangindent is only relevant when the entry text and page number
+ % don't both fit on one line. In that case, bob suggests starting the
+ % dots pretty far over on the line. Unfortunately, a large
+ % indentation looks wrong when the entry text itself is broken across
+ % lines. So we use a small indentation and put up with long leaders.
+ %
+ % \hangafter is reset to 1 (which is the value we want) at the start
+ % of each paragraph, so we need not do anything with that.
+ \hangindent = 2em
+ %
+ % When the entry text needs to be broken, just fill out the first line
+ % with blank space.
+ \rightskip = 0pt plus1fil
+ %
+ % A bit of stretch before each entry for the benefit of balancing
+ % columns.
+ \vskip 0pt plus1pt
+ %
+ % Swallow the left brace of the text (first parameter):
+ \afterassignment\doentry
+ \let\temp =
+}
+\def\doentry{%
+ \bgroup % Instead of the swallowed brace.
+ \noindent
+ \aftergroup\finishentry
+ % And now comes the text of the entry.
+}
+\def\finishentry#1{%
+ % #1 is the page number.
+ %
+ % The following is kludged to not output a line of dots in the index if
+ % there are no page numbers. The next person who breaks this will be
+ % cursed by a Unix daemon.
+ \def\tempa{{\rm }}%
+ \def\tempb{#1}%
+ \edef\tempc{\tempa}%
+ \edef\tempd{\tempb}%
+ \ifx\tempc\tempd
+ \ %
+ \else
+ %
+ % If we must, put the page number on a line of its own, and fill out
+ % this line with blank space. (The \hfil is overwhelmed with the
+ % fill leaders glue in \indexdotfill if the page number does fit.)
+ \hfil\penalty50
+ \null\nobreak\indexdotfill % Have leaders before the page number.
+ %
+ % The `\ ' here is removed by the implicit \unskip that TeX does as
+ % part of (the primitive) \par. Without it, a spurious underfull
+ % \hbox ensues.
+ \ifpdf
+ \pdfgettoks#1.%
+ \ \the\toksA
+ \else
+ \ #1%
+ \fi
+ \fi
+ \par
+ \endgroup
+}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+\def\secondary#1#2{{%
+ \parfillskip=0in
+ \parskip=0in
+ \hangindent=1in
+ \hangafter=1
+ \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill
+ \ifpdf
+ \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph.
+ \else
+ #2
+ \fi
+ \par
+}}
+
+% Define two-column mode, which we use to typeset indexes.
+% Adapted from the TeXbook, page 416, which is to say,
+% the manmac.tex format used to print the TeXbook itself.
+\catcode`\@=11
+
+\newbox\partialpage
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
+ % Grab any single-column material above us.
+ \output = {%
+ %
+ % Here is a possibility not foreseen in manmac: if we accumulate a
+ % whole lot of material, we might end up calling this \output
+ % routine twice in a row (see the doublecol-lose test, which is
+ % essentially a couple of indexes with @setchapternewpage off). In
+ % that case we just ship out what is in \partialpage with the normal
+ % output routine. Generally, \partialpage will be empty when this
+ % runs and this will be a no-op. See the indexspread.tex test case.
+ \ifvoid\partialpage \else
+ \onepageout{\pagecontents\partialpage}%
+ \fi
+ %
+ \global\setbox\partialpage = \vbox{%
+ % Unvbox the main output page.
+ \unvbox\PAGE
+ \kern-\topskip \kern\baselineskip
+ }%
+ }%
+ \eject % run that output routine to set \partialpage
+ %
+ % Use the double-column output routine for subsequent pages.
+ \output = {\doublecolumnout}%
+ %
+ % Change the page size parameters. We could do this once outside this
+ % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+ % format, but then we repeat the same computation. Repeating a couple
+ % of assignments once per index is clearly meaningless for the
+ % execution time, so we may as well do it in one place.
+ %
+ % First we halve the line length, less a little for the gutter between
+ % the columns. We compute the gutter based on the line length, so it
+ % changes automatically with the paper format. The magic constant
+ % below is chosen so that the gutter has the same value (well, +-<1pt)
+ % as it did when we hard-coded it.
+ %
+ % We put the result in a separate register, \doublecolumhsize, so we
+ % can restore it in \pagesofar, after \hsize itself has (potentially)
+ % been clobbered.
+ %
+ \doublecolumnhsize = \hsize
+ \advance\doublecolumnhsize by -.04154\hsize
+ \divide\doublecolumnhsize by 2
+ \hsize = \doublecolumnhsize
+ %
+ % Double the \vsize as well. (We don't need a separate register here,
+ % since nobody clobbers \vsize.)
+ \vsize = 2\vsize
+}
+
+% The double-column output routine for all double-column pages except
+% the last.
+%
+\def\doublecolumnout{%
+ \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ % Get the available space for the double columns -- the normal
+ % (undoubled) page height minus any material left over from the
+ % previous page.
+ \dimen@ = \vsize
+ \divide\dimen@ by 2
+ \advance\dimen@ by -\ht\partialpage
+ %
+ % box0 will be the left-hand column, box2 the right.
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar
+ \unvbox255
+ \penalty\outputpenalty
+}
+%
+% Re-output the contents of the output page -- any previous material,
+% followed by the two boxes we just split, in box0 and box2.
+\def\pagesofar{%
+ \unvbox\partialpage
+ %
+ \hsize = \doublecolumnhsize
+ \wd0=\hsize \wd2=\hsize
+ \hbox to\pagewidth{\box0\hfil\box2}%
+}
+%
+% All done with double columns.
+\def\enddoublecolumns{%
+ \output = {%
+ % Split the last of the double-column material. Leave it on the
+ % current page, no automatic page break.
+ \balancecolumns
+ %
+ % If we end up splitting too much material for the current page,
+ % though, there will be another page break right after this \output
+ % invocation ends. Having called \balancecolumns once, we do not
+ % want to call it again. Therefore, reset \output to its normal
+ % definition right away. (We hope \balancecolumns will never be
+ % called on to balance too much material, but if it is, this makes
+ % the output somewhat more palatable.)
+ \global\output = {\onepageout{\pagecontents\PAGE}}%
+ }%
+ \eject
+ \endgroup % started in \begindoublecolumns
+ %
+ % \pagegoal was set to the doubled \vsize above, since we restarted
+ % the current page. We're now back to normal single-column
+ % typesetting, so reset \pagegoal to the normal \vsize (after the
+ % \endgroup where \vsize got restored).
+ \pagegoal = \vsize
+}
+%
+% Called at the end of the double column material.
+\def\balancecolumns{%
+ \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120.
+ \dimen@ = \ht0
+ \advance\dimen@ by \topskip
+ \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by 2 % target to split to
+ %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}%
+ \splittopskip = \topskip
+ % Loop until we get a decent breakpoint.
+ {%
+ \vbadness = 10000
+ \loop
+ \global\setbox3 = \copy0
+ \global\setbox1 = \vsplit3 to \dimen@
+ \ifdim\ht3>\dimen@
+ \global\advance\dimen@ by 1pt
+ \repeat
+ }%
+ %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}%
+ \setbox0=\vbox to\dimen@{\unvbox1}%
+ \setbox2=\vbox to\dimen@{\unvbox3}%
+ %
+ \pagesofar
+}
+\catcode`\@ = \other
+
+
+\message{sectioning,}
+% Chapters, sections, etc.
+
+% \unnumberedno is an oxymoron, of course. But we count the unnumbered
+% sections so that we can refer to them unambiguously in the pdf
+% outlines by their "section number". We avoid collisions with chapter
+% numbers by starting them at 10000. (If a document ever has 10000
+% chapters, we're in trouble anyway, I'm sure.)
+\newcount\unnumberedno \unnumberedno = 10000
+\newcount\chapno
+\newcount\secno \secno=0
+\newcount\subsecno \subsecno=0
+\newcount\subsubsecno \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount\appendixno \appendixno = `\@
+%
+% \def\appendixletter{\char\the\appendixno}
+% We do the following ugly conditional instead of the above simple
+% construct for the sake of pdftex, which needs the actual
+% letter in the expansion, not just typeset.
+%
+\def\appendixletter{%
+ \ifnum\appendixno=`A A%
+ \else\ifnum\appendixno=`B B%
+ \else\ifnum\appendixno=`C C%
+ \else\ifnum\appendixno=`D D%
+ \else\ifnum\appendixno=`E E%
+ \else\ifnum\appendixno=`F F%
+ \else\ifnum\appendixno=`G G%
+ \else\ifnum\appendixno=`H H%
+ \else\ifnum\appendixno=`I I%
+ \else\ifnum\appendixno=`J J%
+ \else\ifnum\appendixno=`K K%
+ \else\ifnum\appendixno=`L L%
+ \else\ifnum\appendixno=`M M%
+ \else\ifnum\appendixno=`N N%
+ \else\ifnum\appendixno=`O O%
+ \else\ifnum\appendixno=`P P%
+ \else\ifnum\appendixno=`Q Q%
+ \else\ifnum\appendixno=`R R%
+ \else\ifnum\appendixno=`S S%
+ \else\ifnum\appendixno=`T T%
+ \else\ifnum\appendixno=`U U%
+ \else\ifnum\appendixno=`V V%
+ \else\ifnum\appendixno=`W W%
+ \else\ifnum\appendixno=`X X%
+ \else\ifnum\appendixno=`Y Y%
+ \else\ifnum\appendixno=`Z Z%
+ % The \the is necessary, despite appearances, because \appendixletter is
+ % expanded while writing the .toc file. \char\appendixno is not
+ % expandable, thus it is written literally, thus all appendixes come out
+ % with the same letter (or @) in the toc without it.
+ \else\char\the\appendixno
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise.
+% However, they are not reliable, because we don't use marks.
+\def\thischapter{}
+\def\thissection{}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% we only have subsub.
+\chardef\maxseclevel = 3
+%
+% A numbered section within an unnumbered changes to unnumbered too.
+% To achive this, remember the "biggest" unnum. sec. we are currently in:
+\chardef\unmlevel = \maxseclevel
+%
+% Trace whether the current chapter is an appendix or not:
+% \chapheadtype is "N" or "A", unnumbered chapters are ignored.
+\def\chapheadtype{N}
+
+% Choose a heading macro
+% #1 is heading type
+% #2 is heading level
+% #3 is text for heading
+\def\genhead#1#2#3{%
+ % Compute the abs. sec. level:
+ \absseclevel=#2
+ \advance\absseclevel by \secbase
+ % Make sure \absseclevel doesn't fall outside the range:
+ \ifnum \absseclevel < 0
+ \absseclevel = 0
+ \else
+ \ifnum \absseclevel > 3
+ \absseclevel = 3
+ \fi
+ \fi
+ % The heading type:
+ \def\headtype{#1}%
+ \if \headtype U%
+ \ifnum \absseclevel < \unmlevel
+ \chardef\unmlevel = \absseclevel
+ \fi
+ \else
+ % Check for appendix sections:
+ \ifnum \absseclevel = 0
+ \edef\chapheadtype{\headtype}%
+ \else
+ \if \headtype A\if \chapheadtype N%
+ \errmessage{@appendix... within a non-appendix chapter}%
+ \fi\fi
+ \fi
+ % Check for numbered within unnumbered:
+ \ifnum \absseclevel > \unmlevel
+ \def\headtype{U}%
+ \else
+ \chardef\unmlevel = 3
+ \fi
+ \fi
+ % Now print the heading:
+ \if \headtype U%
+ \ifcase\absseclevel
+ \unnumberedzzz{#3}%
+ \or \unnumberedseczzz{#3}%
+ \or \unnumberedsubseczzz{#3}%
+ \or \unnumberedsubsubseczzz{#3}%
+ \fi
+ \else
+ \if \headtype A%
+ \ifcase\absseclevel
+ \appendixzzz{#3}%
+ \or \appendixsectionzzz{#3}%
+ \or \appendixsubseczzz{#3}%
+ \or \appendixsubsubseczzz{#3}%
+ \fi
+ \else
+ \ifcase\absseclevel
+ \chapterzzz{#3}%
+ \or \seczzz{#3}%
+ \or \numberedsubseczzz{#3}%
+ \or \numberedsubsubseczzz{#3}%
+ \fi
+ \fi
+ \fi
+ \suppressfirstparagraphindent
+}
+
+% an interface:
+\def\numhead{\genhead N}
+\def\apphead{\genhead A}
+\def\unnmhead{\genhead U}
+
+% @chapter, @appendix, @unnumbered. Increment top-level counter, reset
+% all lower-level sectioning counters to zero.
+%
+% Also set \chaplevelprefix, which we prepend to @float sequence numbers
+% (e.g., figures), q.v. By default (before any chapter), that is empty.
+\let\chaplevelprefix = \empty
+%
+\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz#1{%
+ % section resetting is \global in case the chapter is in a group, such
+ % as an @include file.
+ \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+ \global\advance\chapno by 1
+ %
+ % Used for \float.
+ \gdef\chaplevelprefix{\the\chapno.}%
+ \resetallfloatnos
+ %
+ \message{\putwordChapter\space \the\chapno}%
+ %
+ % Write the actual heading.
+ \chapmacro{#1}{Ynumbered}{\the\chapno}%
+ %
+ % So @section and the like are numbered underneath this chapter.
+ \global\let\section = \numberedsec
+ \global\let\subsection = \numberedsubsec
+ \global\let\subsubsection = \numberedsubsubsec
+}
+
+\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz#1{%
+ \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+ \global\advance\appendixno by 1
+ \gdef\chaplevelprefix{\appendixletter.}%
+ \resetallfloatnos
+ %
+ \def\appendixnum{\putwordAppendix\space \appendixletter}%
+ \message{\appendixnum}%
+ %
+ \chapmacro{#1}{Yappendix}{\appendixletter}%
+ %
+ \global\let\section = \appendixsec
+ \global\let\subsection = \appendixsubsec
+ \global\let\subsubsection = \appendixsubsubsec
+}
+
+\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz#1{%
+ \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+ \global\advance\unnumberedno by 1
+ %
+ % Since an unnumbered has no number, no prefix for figures.
+ \global\let\chaplevelprefix = \empty
+ \resetallfloatnos
+ %
+ % This used to be simply \message{#1}, but TeX fully expands the
+ % argument to \message. Therefore, if #1 contained @-commands, TeX
+ % expanded them. For example, in `@unnumbered The @cite{Book}', TeX
+ % expanded @cite (which turns out to cause errors because \cite is meant
+ % to be executed, not expanded).
+ %
+ % Anyway, we don't want the fully-expanded definition of @cite to appear
+ % as a result of the \message, we just want `@cite' itself. We use
+ % \the<toks register> to achieve this: TeX expands \the<toks> only once,
+ % simply yielding the contents of <toks register>. (We also do this for
+ % the toc entries.)
+ \toks0 = {#1}%
+ \message{(\the\toks0)}%
+ %
+ \chapmacro{#1}{Ynothing}{\the\unnumberedno}%
+ %
+ \global\let\section = \unnumberedsec
+ \global\let\subsection = \unnumberedsubsec
+ \global\let\subsubsection = \unnumberedsubsubsec
+}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\parseargdef\centerchap{%
+ % Well, we could do the following in a group, but that would break
+ % an assumption that \chapmacro is called at the outermost level.
+ % Thus we are safer this way: --kasal, 24feb04
+ \let\centerparametersmaybe = \centerparameters
+ \unnmhead0{#1}%
+ \let\centerparametersmaybe = \relax
+}
+
+% @top is like @unnumbered.
+\let\top\unnumbered
+
+% Sections.
+\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz
+\def\seczzz#1{%
+ \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1
+ \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}%
+}
+
+\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz#1{%
+ \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1
+ \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}%
+}
+\let\appendixsec\appendixsection
+
+\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz#1{%
+ \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1
+ \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}%
+}
+
+% Subsections.
+\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz#1{%
+ \global\subsubsecno=0 \global\advance\subsecno by 1
+ \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}%
+}
+
+\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz#1{%
+ \global\subsubsecno=0 \global\advance\subsecno by 1
+ \sectionheading{#1}{subsec}{Yappendix}%
+ {\appendixletter.\the\secno.\the\subsecno}%
+}
+
+\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz#1{%
+ \global\subsubsecno=0 \global\advance\subsecno by 1
+ \sectionheading{#1}{subsec}{Ynothing}%
+ {\the\unnumberedno.\the\secno.\the\subsecno}%
+}
+
+% Subsubsections.
+\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz#1{%
+ \global\advance\subsubsecno by 1
+ \sectionheading{#1}{subsubsec}{Ynumbered}%
+ {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz#1{%
+ \global\advance\subsubsecno by 1
+ \sectionheading{#1}{subsubsec}{Yappendix}%
+ {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz#1{%
+ \global\advance\subsubsecno by 1
+ \sectionheading{#1}{subsubsec}{Ynothing}%
+ {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\let\section = \numberedsec
+\let\subsection = \numberedsubsec
+\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{%
+ {\advance\chapheadingskip by 10pt \chapbreak }%
+ \parsearg\chapheadingzzz
+}
+
+\def\chapheading{\chapbreak \parsearg\chapheadingzzz}
+\def\chapheadingzzz#1{%
+ {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}%
+ \bigskip \par\penalty 200\relax
+ \suppressfirstparagraphindent
+}
+
+% @heading, @subheading, @subsubheading.
+\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{}
+ \suppressfirstparagraphindent}
+\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{}
+ \suppressfirstparagraphindent}
+\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{}
+ \suppressfirstparagraphindent}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip\chapheadingskip
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{%
+\global\let\contentsalignmacro = \chapoddpage
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+% Chapter opening.
+%
+% #1 is the text, #2 is the section type (Ynumbered, Ynothing,
+% Yappendix, Yomitfromtoc), #3 the chapter number.
+%
+% To test against our argument.
+\def\Ynothingkeyword{Ynothing}
+\def\Yomitfromtockeyword{Yomitfromtoc}
+\def\Yappendixkeyword{Yappendix}
+%
+\def\chapmacro#1#2#3{%
+ \pchapsepmacro
+ {%
+ \chapfonts \rm
+ %
+ % Have to define \thissection before calling \donoderef, because the
+ % xref code eventually uses it. On the other hand, it has to be called
+ % after \pchapsepmacro, or the headline will change too soon.
+ \gdef\thissection{#1}%
+ \gdef\thischaptername{#1}%
+ %
+ % Only insert the separating space if we have a chapter/appendix
+ % number, and don't print the unnumbered ``number''.
+ \def\temptype{#2}%
+ \ifx\temptype\Ynothingkeyword
+ \setbox0 = \hbox{}%
+ \def\toctype{unnchap}%
+ \def\thischapter{#1}%
+ \else\ifx\temptype\Yomitfromtockeyword
+ \setbox0 = \hbox{}% contents like unnumbered, but no toc entry
+ \def\toctype{omit}%
+ \xdef\thischapter{}%
+ \else\ifx\temptype\Yappendixkeyword
+ \setbox0 = \hbox{\putwordAppendix{} #3\enspace}%
+ \def\toctype{app}%
+ % We don't substitute the actual chapter name into \thischapter
+ % because we don't want its macros evaluated now. And we don't
+ % use \thissection because that changes with each section.
+ %
+ \xdef\thischapter{\putwordAppendix{} \appendixletter:
+ \noexpand\thischaptername}%
+ \else
+ \setbox0 = \hbox{#3\enspace}%
+ \def\toctype{numchap}%
+ \xdef\thischapter{\putwordChapter{} \the\chapno:
+ \noexpand\thischaptername}%
+ \fi\fi\fi
+ %
+ % Write the toc entry for this chapter. Must come before the
+ % \donoderef, because we include the current node name in the toc
+ % entry, and \donoderef resets it to empty.
+ \writetocentry{\toctype}{#1}{#3}%
+ %
+ % For pdftex, we have to write out the node definition (aka, make
+ % the pdfdest) after any page break, but before the actual text has
+ % been typeset. If the destination for the pdf outline is after the
+ % text, then jumping from the outline may wind up with the text not
+ % being visible, for instance under high magnification.
+ \donoderef{#2}%
+ %
+ % Typeset the actual heading.
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent=\wd0 \centerparametersmaybe
+ \unhbox0 #1\par}%
+ }%
+ \nobreak\bigskip % no page break after a chapter title
+ \nobreak
+}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerparameters{%
+ \advance\rightskip by 3\rightskip
+ \leftskip = \rightskip
+ \parfillskip = 0pt
+}
+
+
+% I don't think this chapter style is supported any more, so I'm not
+% updating it with the new noderef stuff. We'll see. --karl, 11aug03.
+%
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+%
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\nobreak
+}
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+\def\centerchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt
+ \hfill {\rm #1}\hfill}}\bigskip \par\nobreak
+}
+\def\CHAPFopen{%
+ \global\let\chapmacro=\chfopen
+ \global\let\centerchapmacro=\centerchfopen}
+
+
+% Section titles. These macros combine the section number parts and
+% call the generic \sectionheading to do the printing.
+%
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip{-1000}}
+
+% Subsection titles.
+\newskip\subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}}
+
+% Subsubsection titles.
+\def\subsubsecheadingskip{\subsecheadingskip}
+\def\subsubsecheadingbreak{\subsecheadingbreak}
+
+
+% Print any size, any type, section title.
+%
+% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is
+% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the
+% section number.
+%
+\def\sectionheading#1#2#3#4{%
+ {%
+ % Switch to the right set of fonts.
+ \csname #2fonts\endcsname \rm
+ %
+ % Insert space above the heading.
+ \csname #2headingbreak\endcsname
+ %
+ % Only insert the space after the number if we have a section number.
+ \def\sectionlevel{#2}%
+ \def\temptype{#3}%
+ %
+ \ifx\temptype\Ynothingkeyword
+ \setbox0 = \hbox{}%
+ \def\toctype{unn}%
+ \gdef\thissection{#1}%
+ \else\ifx\temptype\Yomitfromtockeyword
+ % for @headings -- no section number, don't include in toc,
+ % and don't redefine \thissection.
+ \setbox0 = \hbox{}%
+ \def\toctype{omit}%
+ \let\sectionlevel=\empty
+ \else\ifx\temptype\Yappendixkeyword
+ \setbox0 = \hbox{#4\enspace}%
+ \def\toctype{app}%
+ \gdef\thissection{#1}%
+ \else
+ \setbox0 = \hbox{#4\enspace}%
+ \def\toctype{num}%
+ \gdef\thissection{#1}%
+ \fi\fi\fi
+ %
+ % Write the toc entry (before \donoderef). See comments in \chfplain.
+ \writetocentry{\toctype\sectionlevel}{#1}{#4}%
+ %
+ % Write the node reference (= pdf destination for pdftex).
+ % Again, see comments in \chfplain.
+ \donoderef{#3}%
+ %
+ % Output the actual section heading.
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent=\wd0 % zero if no section number
+ \unhbox0 #1}%
+ }%
+ % Add extra space after the heading -- half of whatever came above it.
+ % Don't allow stretch, though.
+ \kern .5 \csname #2headingskip\endcsname
+ %
+ % Do not let the kern be a potential breakpoint, as it would be if it
+ % was followed by glue.
+ \nobreak
+ %
+ % We'll almost certainly start a paragraph next, so don't let that
+ % glue accumulate. (Not a breakpoint because it's preceded by a
+ % discardable item.)
+ \vskip-\parskip
+ %
+ % This is purely so the last item on the list is a known \penalty >
+ % 10000. This is so \startdefun can avoid allowing breakpoints after
+ % section headings. Otherwise, it would insert a valid breakpoint between:
+ %
+ % @section sec-whatever
+ % @deffn def-whatever
+ \penalty 10001
+}
+
+
+\message{toc,}
+% Table of contents.
+\newwrite\tocfile
+
+% Write an entry to the toc file, opening it if necessary.
+% Called from @chapter, etc.
+%
+% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno}
+% We append the current node name (if any) and page number as additional
+% arguments for the \{chap,sec,...}entry macros which will eventually
+% read this. The node name is used in the pdf outlines as the
+% destination to jump to.
+%
+% We open the .toc file for writing here instead of at @setfilename (or
+% any other fixed time) so that @contents can be anywhere in the document.
+% But if #1 is `omit', then we don't do anything. This is used for the
+% table of contents chapter openings themselves.
+%
+\newif\iftocfileopened
+\def\omitkeyword{omit}%
+%
+\def\writetocentry#1#2#3{%
+ \edef\writetoctype{#1}%
+ \ifx\writetoctype\omitkeyword \else
+ \iftocfileopened\else
+ \immediate\openout\tocfile = \jobname.toc
+ \global\tocfileopenedtrue
+ \fi
+ %
+ \iflinks
+ \toks0 = {#2}%
+ \toks2 = \expandafter{\lastnode}%
+ \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}{#3}%
+ {\the\toks2}{\noexpand\folio}}}%
+ \temp
+ \fi
+ \fi
+ %
+ % Tell \shipout to create a pdf destination on each page, if we're
+ % writing pdf. These are used in the table of contents. We can't
+ % just write one on every page because the title pages are numbered
+ % 1 and 2 (the page numbers aren't printed), and so are the first
+ % two pages of the document. Thus, we'd have two destinations named
+ % `1', and two named `2'.
+ \ifpdf \global\pdfmakepagedesttrue \fi
+}
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\newcount\savepageno
+\newcount\lastnegativepageno \lastnegativepageno = -1
+
+% Prepare to read what we've written to \tocfile.
+%
+\def\startcontents#1{%
+ % If @setchapternewpage on, and @headings double, the contents should
+ % start on an odd page, unlike chapters. Thus, we maintain
+ % \contentsalignmacro in parallel with \pagealignmacro.
+ % From: Torbjorn Granlund <tege@matematik.su.se>
+ \contentsalignmacro
+ \immediate\closeout\tocfile
+ %
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \def\thischapter{}%
+ \chapmacro{#1}{Yomitfromtoc}{}%
+ %
+ \savepageno = \pageno
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ % We can't do this, because then an actual ^ in a section
+ % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97.
+ %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+ %
+ % Roman numerals for page numbers.
+ \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi
+}
+
+
+% Normal (long) toc.
+\def\contents{%
+ \startcontents{\putwordTOC}%
+ \openin 1 \jobname.toc
+ \ifeof 1 \else
+ \input \jobname.toc
+ \fi
+ \vfill \eject
+ \contentsalignmacro % in case @setchapternewpage odd is in effect
+ \ifeof 1 \else
+ \pdfmakeoutlines
+ \fi
+ \closein 1
+ \endgroup
+ \lastnegativepageno = \pageno
+ \global\pageno = \savepageno
+}
+
+% And just the chapters.
+\def\summarycontents{%
+ \startcontents{\putwordShortTOC}%
+ %
+ \let\numchapentry = \shortchapentry
+ \let\appentry = \shortchapentry
+ \let\unnchapentry = \shortunnchapentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf
+ \let\sl=\shortcontsl \let\tt=\shortconttt
+ \rm
+ \hyphenpenalty = 10000
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\numsecentry##1##2##3##4{}
+ \let\appsecentry = \numsecentry
+ \let\unnsecentry = \numsecentry
+ \let\numsubsecentry = \numsecentry
+ \let\appsubsecentry = \numsecentry
+ \let\unnsubsecentry = \numsecentry
+ \let\numsubsubsecentry = \numsecentry
+ \let\appsubsubsecentry = \numsecentry
+ \let\unnsubsubsecentry = \numsecentry
+ \openin 1 \jobname.toc
+ \ifeof 1 \else
+ \input \jobname.toc
+ \fi
+ \closein 1
+ \vfill \eject
+ \contentsalignmacro % in case @setchapternewpage odd is in effect
+ \endgroup
+ \lastnegativepageno = \pageno
+ \global\pageno = \savepageno
+}
+\let\shortcontents = \summarycontents
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g., `A' for an appendix, or `3' for a chapter.
+%
+\def\shortchaplabel#1{%
+ % This space should be enough, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % But use \hss just in case.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in by \shortchapentry above.)
+ %
+ % We'd like to right-justify chapter numbers, but that looks strange
+ % with appendix letters. And right-justifying numbers and
+ % left-justifying letters looks strange when there is less than 10
+ % chapters. Have to read the whole toc once to know how many chapters
+ % there are before deciding ...
+ \hbox to 1em{#1\hss}%
+}
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapters, in the main contents.
+\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}}
+%
+% Chapters, in the short toc.
+% See comments in \dochapentry re vbox and related settings.
+\def\shortchapentry#1#2#3#4{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}%
+}
+
+% Appendices, in the main contents.
+% Need the word Appendix, and a fixed-size box.
+%
+\def\appendixbox#1{%
+ % We use M since it's probably the widest letter.
+ \setbox0 = \hbox{\putwordAppendix{} M}%
+ \hbox to \wd0{\putwordAppendix{} #1\hss}}
+%
+\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}}
+
+% Unnumbered chapters.
+\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}}
+\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}}
+
+% Sections.
+\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}}
+\let\appsecentry=\numsecentry
+\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}}
+
+% Subsections.
+\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}}
+\let\appsubsecentry=\numsubsecentry
+\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}}
+
+% And subsubsections.
+\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}}
+\let\appsubsubsecentry=\numsubsubsecentry
+\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}}
+
+% This parameter controls the indentation of the various levels.
+% Same as \defaultparindent.
+\newdimen\tocindent \tocindent = 15pt
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we want it to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
+ \begingroup
+ \chapentryfonts
+ \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+ \endgroup
+ \nobreak\vskip .25\baselineskip plus.1\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+ \secentryfonts \leftskip=\tocindent
+ \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+ \subsecentryfonts \leftskip=2\tocindent
+ \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+ \subsubsecentryfonts \leftskip=3\tocindent
+ \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+% We use the same \entry macro as for the index entries.
+\let\tocentry = \entry
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\def\subsecentryfonts{\textfonts}
+\def\subsubsecentryfonts{\textfonts}
+
+
+\message{environments,}
+% @foo ... @end foo.
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+%
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+%
+\def\point{$\star$}
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% The @error{} command.
+% Adapted from the TeXbook's \boxit.
+%
+\newbox\errorbox
+%
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+%
+\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{%
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+%
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\envdef\tex{%
+ \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+ \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+ \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie
+ \catcode `\%=14
+ \catcode `\+=\other
+ \catcode `\"=\other
+ \catcode `\|=\other
+ \catcode `\<=\other
+ \catcode `\>=\other
+ \escapechar=`\\
+ %
+ \let\b=\ptexb
+ \let\bullet=\ptexbullet
+ \let\c=\ptexc
+ \let\,=\ptexcomma
+ \let\.=\ptexdot
+ \let\dots=\ptexdots
+ \let\equiv=\ptexequiv
+ \let\!=\ptexexclam
+ \let\i=\ptexi
+ \let\indent=\ptexindent
+ \let\noindent=\ptexnoindent
+ \let\{=\ptexlbrace
+ \let\+=\tabalign
+ \let\}=\ptexrbrace
+ \let\/=\ptexslash
+ \let\*=\ptexstar
+ \let\t=\ptext
+ %
+ \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
+ \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
+ \def\@{@}%
+}
+% There is no need to define \Etex.
+
+% Define @lisp ... @end lisp.
+% @lisp environment forms a group so it can rebind things,
+% including the definition of @end lisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments. \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical. We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip.
+%
+\def\aboveenvbreak{{%
+ % =10000 instead of <10000 because of a special case in \itemzzz and
+ % \sectionheading, q.v.
+ \ifnum \lastpenalty=10000 \else
+ \advance\envskipamount by \parskip
+ \endgraf
+ \ifdim\lastskip<\envskipamount
+ \removelastskip
+ % it's not a good place to break if the last penalty was \nobreak
+ % or better ...
+ \ifnum\lastpenalty<10000 \penalty-50 \fi
+ \vskip\envskipamount
+ \fi
+ \fi
+}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+% @cartouche ... @end cartouche: draw rectangle w/rounded corners around
+% environment contents.
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\envdef\cartouche{%
+ \ifhmode\par\fi % can't be in the midst of a paragraph.
+ \startsavinginserts
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt % we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18.4pt % allow for 3pt kerns on either
+ % side, and for 6pt waste from
+ % each corner char, and rule thickness
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \kern3pt
+ \hsize=\cartinner
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+ \comment % For explanation, see the end of \def\group.
+}
+\def\Ecartouche{%
+ \ifhmode\par\fi
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+ \checkinserts
+}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+ \aboveenvbreak
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \fi
+ \let\exdent=\nofillexdent
+}
+
+% If you want all examples etc. small: @set dispenvsize small.
+% If you want even small examples the full size: @set dispenvsize nosmall.
+% This affects the following displayed environments:
+% @example, @display, @format, @lisp
+%
+\def\smallword{small}
+\def\nosmallword{nosmall}
+\let\SETdispenvsize\relax
+\def\setnormaldispenv{%
+ \ifx\SETdispenvsize\smallword
+ \smallexamplefonts \rm
+ \fi
+}
+\def\setsmalldispenv{%
+ \ifx\SETdispenvsize\nosmallword
+ \else
+ \smallexamplefonts \rm
+ \fi
+}
+
+% We often define two environments, @foo and @smallfoo.
+% Let's do it by one command:
+\def\makedispenv #1#2{
+ \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}
+ \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}
+ \expandafter\let\csname E#1\endcsname \afterenvbreak
+ \expandafter\let\csname Esmall#1\endcsname \afterenvbreak
+}
+
+% Define two synonyms:
+\def\maketwodispenvs #1#2#3{
+ \makedispenv{#1}{#3}
+ \makedispenv{#2}{#3}
+}
+
+% @lisp: indented, narrowed, typewriter font; @example: same as @lisp.
+%
+% @smallexample and @smalllisp: use smaller fonts.
+% Originally contributed by Pavel@xerox.
+%
+\maketwodispenvs {lisp}{example}{%
+ \nonfillstart
+ \tt
+ \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
+ \gobble % eat return
+}
+
+% @display/@smalldisplay: same as @lisp except keep current font.
+%
+\makedispenv {display}{%
+ \nonfillstart
+ \gobble
+}
+
+% @format/@smallformat: same as @display except don't narrow margins.
+%
+\makedispenv{format}{%
+ \let\nonarrowing = t%
+ \nonfillstart
+ \gobble
+}
+
+% @flushleft: same as @format, but doesn't obey \SETdispenvsize.
+\envdef\flushleft{%
+ \let\nonarrowing = t%
+ \nonfillstart
+ \gobble
+}
+\let\Eflushleft = \afterenvbreak
+
+% @flushright.
+%
+\envdef\flushright{%
+ \let\nonarrowing = t%
+ \nonfillstart
+ \advance\leftskip by 0pt plus 1fill
+ \gobble
+}
+\let\Eflushright = \afterenvbreak
+
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins. We keep \parskip nonzero in general, since
+% we're doing normal filling. So, when using \aboveenvbreak and
+% \afterenvbreak, temporarily make \parskip 0.
+%
+\envdef\quotation{%
+ {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+ \parindent=0pt
+ %
+ % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+ \ifx\nonarrowing\relax
+ \advance\leftskip by \lispnarrowing
+ \advance\rightskip by \lispnarrowing
+ \exdentamount = \lispnarrowing
+ \let\nonarrowing = \relax
+ \fi
+ \parsearg\quotationlabel
+}
+
+% We have retained a nonzero parskip for the environment, since we're
+% doing normal filling.
+%
+\def\Equotation{%
+ \par
+ \ifx\quotationauthor\undefined\else
+ % indent a bit.
+ \leftline{\kern 2\leftskip \sl ---\quotationauthor}%
+ \fi
+ {\parskip=0pt \afterenvbreak}%
+}
+
+% If we're given an argument, typeset it in bold with a colon after.
+\def\quotationlabel#1{%
+ \def\temp{#1}%
+ \ifx\temp\empty \else
+ {\bf #1: }%
+ \fi
+}
+
+
+% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>}
+% If we want to allow any <char> as delimiter,
+% we need the curly braces so that makeinfo sees the @verb command, eg:
+% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org
+%
+% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook.
+%
+% [Knuth] p.344; only we need to do the other characters Texinfo sets
+% active too. Otherwise, they get lost as the first character on a
+% verbatim line.
+\def\dospecials{%
+ \do\ \do\\\do\{\do\}\do\$\do\&%
+ \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~%
+ \do\<\do\>\do\|\do\@\do+\do\"%
+}
+%
+% [Knuth] p. 380
+\def\uncatcodespecials{%
+ \def\do##1{\catcode`##1=\other}\dospecials}
+%
+% [Knuth] pp. 380,381,391
+% Disable Spanish ligatures ?` and !` of \tt font
+\begingroup
+ \catcode`\`=\active\gdef`{\relax\lq}
+\endgroup
+%
+% Setup for the @verb command.
+%
+% Eight spaces for a tab
+\begingroup
+ \catcode`\^^I=\active
+ \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }}
+\endgroup
+%
+\def\setupverb{%
+ \tt % easiest (and conventionally used) font for verbatim
+ \def\par{\leavevmode\endgraf}%
+ \catcode`\`=\active
+ \tabeightspaces
+ % Respect line breaks,
+ % print special symbols as themselves, and
+ % make each space count
+ % must do in this order:
+ \obeylines \uncatcodespecials \sepspaces
+}
+
+% Setup for the @verbatim environment
+%
+% Real tab expansion
+\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount
+%
+\def\starttabbox{\setbox0=\hbox\bgroup}
+\begingroup
+ \catcode`\^^I=\active
+ \gdef\tabexpand{%
+ \catcode`\^^I=\active
+ \def^^I{\leavevmode\egroup
+ \dimen0=\wd0 % the width so far, or since the previous tab
+ \divide\dimen0 by\tabw
+ \multiply\dimen0 by\tabw % compute previous multiple of \tabw
+ \advance\dimen0 by\tabw % advance to next multiple of \tabw
+ \wd0=\dimen0 \box0 \starttabbox
+ }%
+ }
+\endgroup
+\def\setupverbatim{%
+ \nonfillstart
+ \advance\leftskip by -\defbodyindent
+ % Easiest (and conventionally used) font for verbatim
+ \tt
+ \def\par{\leavevmode\egroup\box0\endgraf}%
+ \catcode`\`=\active
+ \tabexpand
+ % Respect line breaks,
+ % print special symbols as themselves, and
+ % make each space count
+ % must do in this order:
+ \obeylines \uncatcodespecials \sepspaces
+ \everypar{\starttabbox}%
+}
+
+% Do the @verb magic: verbatim text is quoted by unique
+% delimiter characters. Before first delimiter expect a
+% right brace, after last delimiter expect closing brace:
+%
+% \def\doverb'{'<char>#1<char>'}'{#1}
+%
+% [Knuth] p. 382; only eat outer {}
+\begingroup
+ \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other
+ \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next]
+\endgroup
+%
+\def\verb{\begingroup\setupverb\doverb}
+%
+%
+% Do the @verbatim magic: define the macro \doverbatim so that
+% the (first) argument ends when '@end verbatim' is reached, ie:
+%
+% \def\doverbatim#1@end verbatim{#1}
+%
+% For Texinfo it's a lot easier than for LaTeX,
+% because texinfo's \verbatim doesn't stop at '\end{verbatim}':
+% we need not redefine '\', '{' and '}'.
+%
+% Inspired by LaTeX's verbatim command set [latex.ltx]
+%
+\begingroup
+ \catcode`\ =\active
+ \obeylines %
+ % ignore everything up to the first ^^M, that's the newline at the end
+ % of the @verbatim input line itself. Otherwise we get an extra blank
+ % line in the output.
+ \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}%
+ % We really want {...\end verbatim} in the body of the macro, but
+ % without the active space; thus we have to use \xdef and \gobble.
+\endgroup
+%
+\envdef\verbatim{%
+ \setupverbatim\doverbatim
+}
+\let\Everbatim = \afterenvbreak
+
+
+% @verbatiminclude FILE - insert text of file in verbatim environment.
+%
+\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude}
+%
+\def\doverbatiminclude#1{%
+ {%
+ \makevalueexpandable
+ \setupverbatim
+ \input #1
+ \afterenvbreak
+ }%
+}
+
+% @copying ... @end copying.
+% Save the text away for @insertcopying later.
+%
+% We save the uninterpreted tokens, rather than creating a box.
+% Saving the text in a box would be much easier, but then all the
+% typesetting commands (@smallbook, font changes, etc.) have to be done
+% beforehand -- and a) we want @copying to be done first in the source
+% file; b) letting users define the frontmatter in as flexible order as
+% possible is very desirable.
+%
+\def\copying{\checkenv{}\begingroup\scanargctxt\docopying}
+\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}}
+%
+\def\insertcopying{%
+ \begingroup
+ \parindent = 0pt % paragraph indentation looks wrong on title page
+ \scanexp\copyingtext
+ \endgroup
+}
+
+\message{defuns,}
+% @defun etc.
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+% Start the processing of @deffn:
+\def\startdefun{%
+ \ifnum\lastpenalty<10000
+ \medbreak
+ \else
+ % If there are two @def commands in a row, we'll have a \nobreak,
+ % which is there to keep the function description together with its
+ % header. But if there's nothing but headers, we need to allow a
+ % break somewhere. Check specifically for penalty 10002, inserted
+ % by \defargscommonending, instead of 10000, since the sectioning
+ % commands also insert a nobreak penalty, and we don't want to allow
+ % a break between a section heading and a defun.
+ %
+ \ifnum\lastpenalty=10002 \penalty2000 \fi
+ %
+ % Similarly, after a section heading, do not allow a break.
+ % But do insert the glue.
+ \medskip % preceded by discardable penalty, so not a breakpoint
+ \fi
+ %
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+}
+
+\def\dodefunx#1{%
+ % First, check whether we are in the right environment:
+ \checkenv#1%
+ %
+ % As above, allow line break if we have multiple x headers in a row.
+ % It's not a great place, though.
+ \ifnum\lastpenalty=10002 \penalty3000 \fi
+ %
+ % And now, it's time to reuse the body of the original defun:
+ \expandafter\gobbledefun#1%
+}
+\def\gobbledefun#1\startdefun{}
+
+% \printdefunline \deffnheader{text}
+%
+\def\printdefunline#1#2{%
+ \begingroup
+ % call \deffnheader:
+ #1#2 \endheader
+ % common ending:
+ \interlinepenalty = 10000
+ \advance\rightskip by 0pt plus 1fil
+ \endgraf
+ \nobreak\vskip -\parskip
+ \penalty 10002 % signal to \startdefun and \dodefunx
+ % Some of the @defun-type tags do not enable magic parentheses,
+ % rendering the following check redundant. But we don't optimize.
+ \checkparencounts
+ \endgroup
+}
+
+\def\Edefun{\endgraf\medbreak}
+
+% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn;
+% the only thing remainnig is to define \deffnheader.
+%
+\def\makedefun#1{%
+ \expandafter\let\csname E#1\endcsname = \Edefun
+ \edef\temp{\noexpand\domakedefun
+ \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}%
+ \temp
+}
+
+% \domakedefun \deffn \deffnx \deffnheader
+%
+% Define \deffn and \deffnx, without parameters.
+% \deffnheader has to be defined explicitly.
+%
+\def\domakedefun#1#2#3{%
+ \envdef#1{%
+ \startdefun
+ \parseargusing\activeparens{\printdefunline#3}%
+ }%
+ \def#2{\dodefunx#1}%
+ \def#3%
+}
+
+%%% Untyped functions:
+
+% @deffn category name args
+\makedefun{deffn}{\deffngeneral{}}
+
+% @deffn category class name args
+\makedefun{defop}#1 {\defopon{#1\ \putwordon}}
+
+% \defopon {category on}class name args
+\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
+
+% \deffngeneral {subind}category name args
+%
+\def\deffngeneral#1#2 #3 #4\endheader{%
+ % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}.
+ \dosubind{fn}{\code{#3}}{#1}%
+ \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}%
+}
+
+%%% Typed functions:
+
+% @deftypefn category type name args
+\makedefun{deftypefn}{\deftypefngeneral{}}
+
+% @deftypeop category class type name args
+\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}}
+
+% \deftypeopon {category on}class type name args
+\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
+
+% \deftypefngeneral {subind}category type name args
+%
+\def\deftypefngeneral#1#2 #3 #4 #5\endheader{%
+ \dosubind{fn}{\code{#4}}{#1}%
+ \defname{#2}{#3}{#4}\defunargs{#5\unskip}%
+}
+
+%%% Typed variables:
+
+% @deftypevr category type var args
+\makedefun{deftypevr}{\deftypecvgeneral{}}
+
+% @deftypecv category class type var args
+\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}}
+
+% \deftypecvof {category of}class type var args
+\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} }
+
+% \deftypecvgeneral {subind}category type var args
+%
+\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{%
+ \dosubind{vr}{\code{#4}}{#1}%
+ \defname{#2}{#3}{#4}\defunargs{#5\unskip}%
+}
+
+%%% Untyped variables:
+
+% @defvr category var args
+\makedefun{defvr}#1 {\deftypevrheader{#1} {} }
+
+% @defcv category class var args
+\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}}
+
+% \defcvof {category of}class var args
+\def\defcvof#1#2 {\deftypecvof{#1}#2 {} }
+
+%%% Type:
+% @deftp category name args
+\makedefun{deftp}#1 #2 #3\endheader{%
+ \doind{tp}{\code{#2}}%
+ \defname{#1}{}{#2}\defunargs{#3\unskip}%
+}
+
+% Remaining @defun-like shortcuts:
+\makedefun{defun}{\deffnheader{\putwordDeffunc} }
+\makedefun{defmac}{\deffnheader{\putwordDefmac} }
+\makedefun{defspec}{\deffnheader{\putwordDefspec} }
+\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} }
+\makedefun{defvar}{\defvrheader{\putwordDefvar} }
+\makedefun{defopt}{\defvrheader{\putwordDefopt} }
+\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} }
+\makedefun{defmethod}{\defopon\putwordMethodon}
+\makedefun{deftypemethod}{\deftypeopon\putwordMethodon}
+\makedefun{defivar}{\defcvof\putwordInstanceVariableof}
+\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof}
+
+% \defname, which formats the name of the @def (not the args).
+% #1 is the category, such as "Function".
+% #2 is the return type, if any.
+% #3 is the function name.
+%
+% We are followed by (but not passed) the arguments, if any.
+%
+\def\defname#1#2#3{%
+ % Get the values of \leftskip and \rightskip as they were outside the @def...
+ \advance\leftskip by -\defbodyindent
+ %
+ % How we'll format the type name. Putting it in brackets helps
+ % distinguish it from the body text that may end up on the next line
+ % just below it.
+ \def\temp{#1}%
+ \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi}
+ %
+ % Figure out line sizes for the paragraph shape.
+ % The first line needs space for \box0; but if \rightskip is nonzero,
+ % we need only space for the part of \box0 which exceeds it:
+ \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip
+ % The continuations:
+ \dimen2=\hsize \advance\dimen2 by -\defargsindent
+ % (plain.tex says that \dimen1 should be used only as global.)
+ \parshape 2 0in \dimen0 \defargsindent \dimen2
+ %
+ % Put the type name to the right margin.
+ \noindent
+ \hbox to 0pt{%
+ \hfil\box0 \kern-\hsize
+ % \hsize has to be shortened this way:
+ \kern\leftskip
+ % Intentionally do not respect \rightskip, since we need the space.
+ }%
+ %
+ % Allow all lines to be underfull without complaint:
+ \tolerance=10000 \hbadness=10000
+ \exdentamount=\defbodyindent
+ {%
+ % defun fonts. We use typewriter by default (used to be bold) because:
+ % . we're printing identifiers, they should be in tt in principle.
+ % . in languages with many accents, such as Czech or French, it's
+ % common to leave accents off identifiers. The result looks ok in
+ % tt, but exceedingly strange in rm.
+ % . we don't want -- and --- to be treated as ligatures.
+ % . this still does not fix the ?` and !` ligatures, but so far no
+ % one has made identifiers using them :).
+ \df \tt
+ \def\temp{#2}% return value type
+ \ifx\temp\empty\else \tclose{\temp} \fi
+ #3% output function name
+ }%
+ {\rm\enskip}% hskip 0.5 em of \tenrm
+ %
+ \boldbrax
+ % arguments will be output next, if any.
+}
+
+% Print arguments in slanted roman (not ttsl), inconsistently with using
+% tt for the name. This is because literal text is sometimes needed in
+% the argument list (groff manual), and ttsl and tt are not very
+% distinguishable. Prevent hyphenation at `-' chars.
+%
+\def\defunargs#1{%
+ % use sl by default (not ttsl),
+ % tt for the names.
+ \df \sl \hyphenchar\font=0
+ %
+ % On the other hand, if an argument has two dashes (for instance), we
+ % want a way to get ttsl. Let's try @var for that.
+ \let\var=\ttslanted
+ #1%
+ \sl\hyphenchar\font=45
+}
+
+% We want ()&[] to print specially on the defun line.
+%
+\def\activeparens{%
+ \catcode`\(=\active \catcode`\)=\active
+ \catcode`\[=\active \catcode`\]=\active
+ \catcode`\&=\active
+}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+% Be sure that we always have a definition for `(', etc. For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+{
+ \activeparens
+ \global\let(=\lparen \global\let)=\rparen
+ \global\let[=\lbrack \global\let]=\rbrack
+ \global\let& = \&
+
+ \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+ \gdef\magicamp{\let&=\amprm}
+}
+
+\newcount\parencount
+
+% If we encounter &foo, then turn on ()-hacking afterwards
+\newif\ifampseen
+\def\amprm#1 {\ampseentrue{\bf\&#1 }}
+
+\def\parenfont{%
+ \ifampseen
+ % At the first level, print parens in roman,
+ % otherwise use the default font.
+ \ifnum \parencount=1 \rm \fi
+ \else
+ % The \sf parens (in \boldbrax) actually are a little bolder than
+ % the contained text. This is especially needed for [ and ] .
+ \sf
+ \fi
+}
+\def\infirstlevel#1{%
+ \ifampseen
+ \ifnum\parencount=1
+ #1%
+ \fi
+ \fi
+}
+\def\bfafterword#1 {#1 \bf}
+
+\def\opnr{%
+ \global\advance\parencount by 1
+ {\parenfont(}%
+ \infirstlevel \bfafterword
+}
+\def\clnr{%
+ {\parenfont)}%
+ \infirstlevel \sl
+ \global\advance\parencount by -1
+}
+
+\newcount\brackcount
+\def\lbrb{%
+ \global\advance\brackcount by 1
+ {\bf[}%
+}
+\def\rbrb{%
+ {\bf]}%
+ \global\advance\brackcount by -1
+}
+
+\def\checkparencounts{%
+ \ifnum\parencount=0 \else \badparencount \fi
+ \ifnum\brackcount=0 \else \badbrackcount \fi
+}
+\def\badparencount{%
+ \errmessage{Unbalanced parentheses in @def}%
+ \global\parencount=0
+}
+\def\badbrackcount{%
+ \errmessage{Unbalanced square braces in @def}%
+ \global\brackcount=0
+}
+
+
+\message{macros,}
+% @macro.
+
+% To do this right we need a feature of e-TeX, \scantokens,
+% which we arrange to emulate with a temporary file in ordinary TeX.
+\ifx\eTeXversion\undefined
+ \newwrite\macscribble
+ \def\scantokens#1{%
+ \toks0={#1}%
+ \immediate\openout\macscribble=\jobname.tmp
+ \immediate\write\macscribble{\the\toks0}%
+ \immediate\closeout\macscribble
+ \input \jobname.tmp
+ }
+\fi
+
+\def\scanmacro#1{%
+ \begingroup
+ \newlinechar`\^^M
+ \let\xeatspaces\eatspaces
+ % Undo catcode changes of \startcontents and \doprintindex
+ % When called from @insertcopying or (short)caption, we need active
+ % backslash to get it printed correctly. Previously, we had
+ % \catcode`\\=\other instead. We'll see whether a problem appears
+ % with macro expansion. --kasal, 19aug04
+ \catcode`\@=0 \catcode`\\=\active \escapechar=`\@
+ % ... and \example
+ \spaceisspace
+ %
+ % Append \endinput to make sure that TeX does not see the ending newline.
+ %
+ % I've verified that it is necessary both for e-TeX and for ordinary TeX
+ % --kasal, 29nov03
+ \scantokens{#1\endinput}%
+ \endgroup
+}
+
+\def\scanexp#1{%
+ \edef\temp{\noexpand\scanmacro{#1}}%
+ \temp
+}
+
+\newcount\paramno % Count of parameters
+\newtoks\macname % Macro name
+\newif\ifrecursive % Is it recursive?
+\def\macrolist{} % List of all defined macros in the form
+ % \do\macro1\do\macro2...
+
+% Utility routines.
+% This does \let #1 = #2, with \csnames; that is,
+% \let \csname#1\endcsname = \csname#2\endcsname
+% (except of course we have to play expansion games).
+%
+\def\cslet#1#2{%
+ \expandafter\let
+ \csname#1\expandafter\endcsname
+ \csname#2\endcsname
+}
+
+% Trim leading and trailing spaces off a string.
+% Concepts from aro-bend problem 15 (see CTAN).
+{\catcode`\@=11
+\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }}
+\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@}
+\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}
+\def\unbrace#1{#1}
+\unbrace{\gdef\trim@@@ #1 } #2@{#1}
+}
+
+% Trim a single trailing ^^M off a string.
+{\catcode`\^^M=\other \catcode`\Q=3%
+\gdef\eatcr #1{\eatcra #1Q^^MQ}%
+\gdef\eatcra#1^^MQ{\eatcrb#1Q}%
+\gdef\eatcrb#1Q#2Q{#1}%
+}
+
+% Macro bodies are absorbed as an argument in a context where
+% all characters are catcode 10, 11 or 12, except \ which is active
+% (as in normal texinfo). It is necessary to change the definition of \.
+
+% It's necessary to have hard CRs when the macro is executed. This is
+% done by making ^^M (\endlinechar) catcode 12 when reading the macro
+% body, and then making it the \newlinechar in \scanmacro.
+
+\def\scanctxt{%
+ \catcode`\"=\other
+ \catcode`\+=\other
+ \catcode`\<=\other
+ \catcode`\>=\other
+ \catcode`\@=\other
+ \catcode`\^=\other
+ \catcode`\_=\other
+ \catcode`\|=\other
+ \catcode`\~=\other
+}
+
+\def\scanargctxt{%
+ \scanctxt
+ \catcode`\\=\other
+ \catcode`\^^M=\other
+}
+
+\def\macrobodyctxt{%
+ \scanctxt
+ \catcode`\{=\other
+ \catcode`\}=\other
+ \catcode`\^^M=\other
+ \usembodybackslash
+}
+
+\def\macroargctxt{%
+ \scanctxt
+ \catcode`\\=\other
+}
+
+% \mbodybackslash is the definition of \ in @macro bodies.
+% It maps \foo\ => \csname macarg.foo\endcsname => #N
+% where N is the macro parameter number.
+% We define \csname macarg.\endcsname to be \realbackslash, so
+% \\ in macro replacement text gets you a backslash.
+
+{\catcode`@=0 @catcode`@\=@active
+ @gdef@usembodybackslash{@let\=@mbodybackslash}
+ @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname}
+}
+\expandafter\def\csname macarg.\endcsname{\realbackslash}
+
+\def\macro{\recursivefalse\parsearg\macroxxx}
+\def\rmacro{\recursivetrue\parsearg\macroxxx}
+
+\def\macroxxx#1{%
+ \getargs{#1}% now \macname is the macname and \argl the arglist
+ \ifx\argl\empty % no arguments
+ \paramno=0%
+ \else
+ \expandafter\parsemargdef \argl;%
+ \fi
+ \if1\csname ismacro.\the\macname\endcsname
+ \message{Warning: redefining \the\macname}%
+ \else
+ \expandafter\ifx\csname \the\macname\endcsname \relax
+ \else \errmessage{Macro name \the\macname\space already defined}\fi
+ \global\cslet{macsave.\the\macname}{\the\macname}%
+ \global\expandafter\let\csname ismacro.\the\macname\endcsname=1%
+ % Add the macroname to \macrolist
+ \toks0 = \expandafter{\macrolist\do}%
+ \xdef\macrolist{\the\toks0
+ \expandafter\noexpand\csname\the\macname\endcsname}%
+ \fi
+ \begingroup \macrobodyctxt
+ \ifrecursive \expandafter\parsermacbody
+ \else \expandafter\parsemacbody
+ \fi}
+
+\parseargdef\unmacro{%
+ \if1\csname ismacro.#1\endcsname
+ \global\cslet{#1}{macsave.#1}%
+ \global\expandafter\let \csname ismacro.#1\endcsname=0%
+ % Remove the macro name from \macrolist:
+ \begingroup
+ \expandafter\let\csname#1\endcsname \relax
+ \let\do\unmacrodo
+ \xdef\macrolist{\macrolist}%
+ \endgroup
+ \else
+ \errmessage{Macro #1 not defined}%
+ \fi
+}
+
+% Called by \do from \dounmacro on each macro. The idea is to omit any
+% macro definitions that have been changed to \relax.
+%
+\def\unmacrodo#1{%
+ \ifx#1\relax
+ % remove this
+ \else
+ \noexpand\do \noexpand #1%
+ \fi
+}
+
+% This makes use of the obscure feature that if the last token of a
+% <parameter list> is #, then the preceding argument is delimited by
+% an opening brace, and that opening brace is not consumed.
+\def\getargs#1{\getargsxxx#1{}}
+\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs}
+\def\getmacname #1 #2\relax{\macname={#1}}
+\def\getmacargs#1{\def\argl{#1}}
+
+% Parse the optional {params} list. Set up \paramno and \paramlist
+% so \defmacro knows what to do. Define \macarg.blah for each blah
+% in the params list, to be ##N where N is the position in that list.
+% That gets used by \mbodybackslash (above).
+
+% We need to get `macro parameter char #' into several definitions.
+% The technique used is stolen from LaTeX: let \hash be something
+% unexpandable, insert that wherever you need a #, and then redefine
+% it to # just before using the token list produced.
+%
+% The same technique is used to protect \eatspaces till just before
+% the macro is used.
+
+\def\parsemargdef#1;{\paramno=0\def\paramlist{}%
+ \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,}
+\def\parsemargdefxxx#1,{%
+ \if#1;\let\next=\relax
+ \else \let\next=\parsemargdefxxx
+ \advance\paramno by 1%
+ \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
+ {\xeatspaces{\hash\the\paramno}}%
+ \edef\paramlist{\paramlist\hash\the\paramno,}%
+ \fi\next}
+
+% These two commands read recursive and nonrecursive macro bodies.
+% (They're different since rec and nonrec macros end differently.)
+
+\long\def\parsemacbody#1@end macro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+\long\def\parsermacbody#1@end rmacro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+
+% This defines the macro itself. There are six cases: recursive and
+% nonrecursive macros of zero, one, and many arguments.
+% Much magic with \expandafter here.
+% \xdef is used so that macro definitions will survive the file
+% they're defined in; @include reads the file inside a group.
+\def\defmacro{%
+ \let\hash=##% convert placeholders to macro parameter chars
+ \ifrecursive
+ \ifcase\paramno
+ % 0
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \noexpand\scanmacro{\temp}}%
+ \or % 1
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \noexpand\braceorline
+ \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+ \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+ \egroup\noexpand\scanmacro{\temp}}%
+ \else % many
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \noexpand\csname\the\macname xx\endcsname}%
+ \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+ \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+ \expandafter\expandafter
+ \expandafter\xdef
+ \expandafter\expandafter
+ \csname\the\macname xxx\endcsname
+ \paramlist{\egroup\noexpand\scanmacro{\temp}}%
+ \fi
+ \else
+ \ifcase\paramno
+ % 0
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \noexpand\norecurse{\the\macname}%
+ \noexpand\scanmacro{\temp}\egroup}%
+ \or % 1
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \noexpand\braceorline
+ \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+ \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+ \egroup
+ \noexpand\norecurse{\the\macname}%
+ \noexpand\scanmacro{\temp}\egroup}%
+ \else % many
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \expandafter\noexpand\csname\the\macname xx\endcsname}%
+ \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+ \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+ \expandafter\expandafter
+ \expandafter\xdef
+ \expandafter\expandafter
+ \csname\the\macname xxx\endcsname
+ \paramlist{%
+ \egroup
+ \noexpand\norecurse{\the\macname}%
+ \noexpand\scanmacro{\temp}\egroup}%
+ \fi
+ \fi}
+
+\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
+
+% \braceorline decides whether the next nonwhitespace character is a
+% {. If so it reads up to the closing }, if not, it reads the whole
+% line. Whatever was read is then fed to the next control sequence
+% as an argument (by \parsebrace or \parsearg)
+\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx}
+\def\braceorlinexxx{%
+ \ifx\nchar\bgroup\else
+ \expandafter\parsearg
+ \fi \next}
+
+% We want to disable all macros during \shipout so that they are not
+% expanded by \write.
+\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}%
+ \edef\next{\macrolist}\expandafter\endgroup\next}
+
+% For \indexnofonts, we need to get rid of all macros, leaving only the
+% arguments (if present). Of course this is not nearly correct, but it
+% is the best we can do for now. makeinfo does not expand macros in the
+% argument to @deffn, which ends up writing an index entry, and texindex
+% isn't prepared for an index sort entry that starts with \.
+%
+% Since macro invocations are followed by braces, we can just redefine them
+% to take a single TeX argument. The case of a macro invocation that
+% goes to end-of-line is not handled.
+%
+\def\emptyusermacros{\begingroup
+ \def\do##1{\let\noexpand##1=\noexpand\asis}%
+ \edef\next{\macrolist}\expandafter\endgroup\next}
+
+
+% @alias.
+% We need some trickery to remove the optional spaces around the equal
+% sign. Just make them active and then expand them all to nothing.
+\def\alias{\parseargusing\obeyspaces\aliasxxx}
+\def\aliasxxx #1{\aliasyyy#1\relax}
+\def\aliasyyy #1=#2\relax{%
+ {%
+ \expandafter\let\obeyedspace=\empty
+ \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}%
+ }%
+ \next
+}
+
+
+\message{cross references,}
+
+\newwrite\auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% @inforef is relatively simple.
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
+% @node's only job in TeX is to define \lastnode, which is used in
+% cross-references. The @node line might or might not have commas, and
+% might or might not have spaces before the first comma, like:
+% @node foo , bar , ...
+% We don't want such trailing spaces in the node name.
+%
+\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse}
+%
+% also remove a trailing comma, in case of something like this:
+% @node Help-Cross, , , Cross-refs
+\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse}
+\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}}
+
+\let\nwnode=\node
+\let\lastnode=\empty
+
+% Write a cross-reference definition for the current node. #1 is the
+% type (Ynumbered, Yappendix, Ynothing).
+%
+\def\donoderef#1{%
+ \ifx\lastnode\empty\else
+ \setref{\lastnode}{#1}%
+ \global\let\lastnode=\empty
+ \fi
+}
+
+% @anchor{NAME} -- define xref target at arbitrary point.
+%
+\newcount\savesfregister
+%
+\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi}
+\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi}
+\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces}
+
+% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an
+% anchor), which consists of three parts:
+% 1) NAME-title - the current sectioning name taken from \thissection,
+% or the anchor name.
+% 2) NAME-snt - section number and type, passed as the SNT arg, or
+% empty for anchors.
+% 3) NAME-pg - the page number.
+%
+% This is called from \donoderef, \anchor, and \dofloat. In the case of
+% floats, there is an additional part, which is not written here:
+% 4) NAME-lof - the text as it should appear in a @listoffloats.
+%
+\def\setref#1#2{%
+ \pdfmkdest{#1}%
+ \iflinks
+ {%
+ \atdummies % preserve commands, but don't expand them
+ \turnoffactive
+ \otherbackslash
+ \edef\writexrdef##1##2{%
+ \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef
+ ##1}{##2}}% these are parameters of \writexrdef
+ }%
+ \toks0 = \expandafter{\thissection}%
+ \immediate \writexrdef{title}{\the\toks0 }%
+ \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc.
+ \writexrdef{pg}{\folio}% will be written later, during \shipout
+ }%
+ \fi
+}
+
+% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is
+% the node name, #2 the name of the Info cross-reference, #3 the printed
+% node name, #4 the name of the Info file, #5 the name of the printed
+% manual. All but the node name can be omitted.
+%
+\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
+\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+ \unsepspaces
+ \def\printedmanual{\ignorespaces #5}%
+ \def\printedrefname{\ignorespaces #3}%
+ \setbox1=\hbox{\printedmanual\unskip}%
+ \setbox0=\hbox{\printedrefname\unskip}%
+ \ifdim \wd0 = 0pt
+ % No printed node name was explicitly given.
+ \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+ % Use the node name inside the square brackets.
+ \def\printedrefname{\ignorespaces #1}%
+ \else
+ % Use the actual chapter/section title appear inside
+ % the square brackets. Use the real section title if we have it.
+ \ifdim \wd1 > 0pt
+ % It is in another manual, so we don't have it.
+ \def\printedrefname{\ignorespaces #1}%
+ \else
+ \ifhavexrefs
+ % We know the real title if we have the xref values.
+ \def\printedrefname{\refx{#1-title}{}}%
+ \else
+ % Otherwise just copy the Info node name.
+ \def\printedrefname{\ignorespaces #1}%
+ \fi%
+ \fi
+ \fi
+ \fi
+ %
+ % Make link in pdf output.
+ \ifpdf
+ \leavevmode
+ \getfilename{#4}%
+ {\turnoffactive \otherbackslash
+ \ifnum\filenamelength>0
+ \startlink attr{/Border [0 0 0]}%
+ goto file{\the\filename.pdf} name{#1}%
+ \else
+ \startlink attr{/Border [0 0 0]}%
+ goto name{\pdfmkpgn{#1}}%
+ \fi
+ }%
+ \linkcolor
+ \fi
+ %
+ % Float references are printed completely differently: "Figure 1.2"
+ % instead of "[somenode], p.3". We distinguish them by the
+ % LABEL-title being set to a magic string.
+ {%
+ % Have to otherify everything special to allow the \csname to
+ % include an _ in the xref name, etc.
+ \indexnofonts
+ \turnoffactive
+ \otherbackslash
+ \expandafter\global\expandafter\let\expandafter\Xthisreftitle
+ \csname XR#1-title\endcsname
+ }%
+ \iffloat\Xthisreftitle
+ % If the user specified the print name (third arg) to the ref,
+ % print it instead of our usual "Figure 1.2".
+ \ifdim\wd0 = 0pt
+ \refx{#1-snt}%
+ \else
+ \printedrefname
+ \fi
+ %
+ % if the user also gave the printed manual name (fifth arg), append
+ % "in MANUALNAME".
+ \ifdim \wd1 > 0pt
+ \space \putwordin{} \cite{\printedmanual}%
+ \fi
+ \else
+ % node/anchor (non-float) references.
+ %
+ % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
+ % insert empty discretionaries after hyphens, which means that it will
+ % not find a line break at a hyphen in a node names. Since some manuals
+ % are best written with fairly long node names, containing hyphens, this
+ % is a loss. Therefore, we give the text of the node name again, so it
+ % is as if TeX is seeing it for the first time.
+ \ifdim \wd1 > 0pt
+ \putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}%
+ \else
+ % _ (for example) has to be the character _ for the purposes of the
+ % control sequence corresponding to the node, but it has to expand
+ % into the usual \leavevmode...\vrule stuff for purposes of
+ % printing. So we \turnoffactive for the \refx-snt, back on for the
+ % printing, back off for the \refx-pg.
+ {\turnoffactive \otherbackslash
+ % Only output a following space if the -snt ref is nonempty; for
+ % @unnumbered and @anchor, it won't be.
+ \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}%
+ \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
+ }%
+ % output the `[mynode]' via a macro so it can be overridden.
+ \xrefprintnodename\printedrefname
+ %
+ % But we always want a comma and a space:
+ ,\space
+ %
+ % output the `page 3'.
+ \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}%
+ \fi
+ \fi
+ \endlink
+\endgroup}
+
+% This macro is called from \xrefX for the `[nodename]' part of xref
+% output. It's a separate macro only so it can be changed more easily,
+% since square brackets don't work well in some documents. Particularly
+% one that Bob is working on :).
+%
+\def\xrefprintnodename#1{[#1]}
+
+% Things referred to by \setref.
+%
+\def\Ynothing{}
+\def\Yomitfromtoc{}
+\def\Ynumbered{%
+ \ifnum\secno=0
+ \putwordChapter@tie \the\chapno
+ \else \ifnum\subsecno=0
+ \putwordSection@tie \the\chapno.\the\secno
+ \else \ifnum\subsubsecno=0
+ \putwordSection@tie \the\chapno.\the\secno.\the\subsecno
+ \else
+ \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno
+ \fi\fi\fi
+}
+\def\Yappendix{%
+ \ifnum\secno=0
+ \putwordAppendix@tie @char\the\appendixno{}%
+ \else \ifnum\subsecno=0
+ \putwordSection@tie @char\the\appendixno.\the\secno
+ \else \ifnum\subsubsecno=0
+ \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno
+ \else
+ \putwordSection@tie
+ @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno
+ \fi\fi\fi
+}
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+%
+\def\refx#1#2{%
+ {%
+ \indexnofonts
+ \otherbackslash
+ \expandafter\global\expandafter\let\expandafter\thisrefX
+ \csname XR#1\endcsname
+ }%
+ \ifx\thisrefX\relax
+ % If not defined, say something at least.
+ \angleleft un\-de\-fined\angleright
+ \iflinks
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \thisrefX
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% This is the macro invoked by entries in the aux file. Usually it's
+% just a \def (we prepend XR to the control sequence name to avoid
+% collisions). But if this is a float type, we have more work to do.
+%
+\def\xrdef#1#2{%
+ \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value.
+ %
+ % Was that xref control sequence that we just defined for a float?
+ \expandafter\iffloat\csname XR#1\endcsname
+ % it was a float, and we have the (safe) float type in \iffloattype.
+ \expandafter\let\expandafter\floatlist
+ \csname floatlist\iffloattype\endcsname
+ %
+ % Is this the first time we've seen this float type?
+ \expandafter\ifx\floatlist\relax
+ \toks0 = {\do}% yes, so just \do
+ \else
+ % had it before, so preserve previous elements in list.
+ \toks0 = \expandafter{\floatlist\do}%
+ \fi
+ %
+ % Remember this xref in the control sequence \floatlistFLOATTYPE,
+ % for later use in \listoffloats.
+ \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}%
+ \fi
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+%
+\def\tryauxfile{%
+ \openin 1 \jobname.aux
+ \ifeof 1 \else
+ \readauxfile
+ \global\havexrefstrue
+ \fi
+ \closein 1
+}
+
+\def\readauxfile{\begingroup
+ \catcode`\^^@=\other
+ \catcode`\^^A=\other
+ \catcode`\^^B=\other
+ \catcode`\^^C=\other
+ \catcode`\^^D=\other
+ \catcode`\^^E=\other
+ \catcode`\^^F=\other
+ \catcode`\^^G=\other
+ \catcode`\^^H=\other
+ \catcode`\^^K=\other
+ \catcode`\^^L=\other
+ \catcode`\^^N=\other
+ \catcode`\^^P=\other
+ \catcode`\^^Q=\other
+ \catcode`\^^R=\other
+ \catcode`\^^S=\other
+ \catcode`\^^T=\other
+ \catcode`\^^U=\other
+ \catcode`\^^V=\other
+ \catcode`\^^W=\other
+ \catcode`\^^X=\other
+ \catcode`\^^Z=\other
+ \catcode`\^^[=\other
+ \catcode`\^^\=\other
+ \catcode`\^^]=\other
+ \catcode`\^^^=\other
+ \catcode`\^^_=\other
+ % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc.
+ % in xref tags, i.e., node names. But since ^^e4 notation isn't
+ % supported in the main text, it doesn't seem desirable. Furthermore,
+ % that is not enough: for node names that actually contain a ^
+ % character, we would end up writing a line like this: 'xrdef {'hat
+ % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first
+ % argument, and \hat is not an expandable control sequence. It could
+ % all be worked out, but why? Either we support ^^ or we don't.
+ %
+ % The other change necessary for this was to define \auxhat:
+ % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter
+ % and then to call \auxhat in \setq.
+ %
+ \catcode`\^=\other
+ %
+ % Special characters. Should be turned off anyway, but...
+ \catcode`\~=\other
+ \catcode`\[=\other
+ \catcode`\]=\other
+ \catcode`\"=\other
+ \catcode`\_=\other
+ \catcode`\|=\other
+ \catcode`\<=\other
+ \catcode`\>=\other
+ \catcode`\$=\other
+ \catcode`\#=\other
+ \catcode`\&=\other
+ \catcode`\%=\other
+ \catcode`+=\other % avoid \+ for paranoia even though we've turned it off
+ %
+ % This is to support \ in node names and titles, since the \
+ % characters end up in a \csname. It's easier than
+ % leaving it active and making its active definition an actual \
+ % character. What I don't understand is why it works in the *value*
+ % of the xrdef. Seems like it should be a catcode12 \, and that
+ % should not typeset properly. But it works, so I'm moving on for
+ % now. --karl, 15jan04.
+ \catcode`\\=\other
+ %
+ % Make the characters 128-255 be printing characters.
+ {%
+ \count 1=128
+ \def\loop{%
+ \catcode\count 1=\other
+ \advance\count 1 by 1
+ \ifnum \count 1<256 \loop \fi
+ }%
+ }%
+ %
+ % @ is our escape character in .aux files, and we need braces.
+ \catcode`\{=1
+ \catcode`\}=2
+ \catcode`\@=0
+ %
+ \input \jobname.aux
+\endgroup}
+
+
+\message{insertions,}
+% including footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed. (Generally, numeric constants should always be followed by a
+% space to prevent strange expansion errors.)
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only.
+\let\footnotestyle=\comment
+
+{\catcode `\@=11
+%
+% Auto-number footnotes. Otherwise like plain.
+\gdef\footnote{%
+ \let\indent=\ptexindent
+ \let\noindent=\ptexnoindent
+ \global\advance\footnoteno by \@ne
+ \edef\thisfootno{$^{\the\footnoteno}$}%
+ %
+ % In case the footnote comes at the end of a sentence, preserve the
+ % extra spacing after we do the footnote number.
+ \let\@sf\empty
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \dofootnote
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter. Our footnotes don't need to be so general.
+%
+% Oh yes, they do; otherwise, @ifset (and anything else that uses
+% \parseargline) fails inside footnotes because the tokens are fixed when
+% the footnote is read. --karl, 16nov96.
+%
+\gdef\dofootnote{%
+ \insert\footins\bgroup
+ % We want to typeset this text as a normal paragraph, even if the
+ % footnote reference occurs in (for example) a display environment.
+ % So reset some parameters.
+ \hsize=\pagewidth
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox
+ \floatingpenalty\@MM
+ \leftskip\z@skip
+ \rightskip\z@skip
+ \spaceskip\z@skip
+ \xspaceskip\z@skip
+ \parindent\defaultparindent
+ %
+ \smallfonts \rm
+ %
+ % Because we use hanging indentation in footnotes, a @noindent appears
+ % to exdent this text, so make it be a no-op. makeinfo does not use
+ % hanging indentation so @noindent can still be needed within footnote
+ % text after an @example or the like (not that this is good style).
+ \let\noindent = \relax
+ %
+ % Hang the footnote text off the number. Use \everypar in case the
+ % footnote extends for more than one paragraph.
+ \everypar = {\hang}%
+ \textindent{\thisfootno}%
+ %
+ % Don't crash into the line above the footnote text. Since this
+ % expands into a box, it must come within the paragraph, lest it
+ % provide a place where TeX can split the footnote.
+ \footstrut
+ \futurelet\next\fo@t
+}
+}%end \catcode `\@=11
+
+% In case a @footnote appears in a vbox, save the footnote text and create
+% the real \insert just after the vbox finished. Otherwise, the insertion
+% would be lost.
+% Similarily, if a @footnote appears inside an alignment, save the footnote
+% text to a box and make the \insert when a row of the table is finished.
+% And the same can be done for other insert classes. --kasal, 16nov03.
+
+% Replace the \insert primitive by a cheating macro.
+% Deeper inside, just make sure that the saved insertions are not spilled
+% out prematurely.
+%
+\def\startsavinginserts{%
+ \ifx \insert\ptexinsert
+ \let\insert\saveinsert
+ \else
+ \let\checkinserts\relax
+ \fi
+}
+
+% This \insert replacement works for both \insert\footins{foo} and
+% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}.
+%
+\def\saveinsert#1{%
+ \edef\next{\noexpand\savetobox \makeSAVEname#1}%
+ \afterassignment\next
+ % swallow the left brace
+ \let\temp =
+}
+\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}}
+\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1}
+
+\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi}
+
+\def\placesaveins#1{%
+ \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname
+ {\box#1}%
+}
+
+% eat @SAVE -- beware, all of them have catcode \other:
+{
+ \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-)
+ \gdef\gobblesave @SAVE{}
+}
+
+% initialization:
+\def\newsaveins #1{%
+ \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}%
+ \next
+}
+\def\newsaveinsX #1{%
+ \csname newbox\endcsname #1%
+ \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts
+ \checksaveins #1}%
+}
+
+% initialize:
+\let\checkinserts\empty
+\newsaveins\footins
+\newsaveins\margin
+
+
+% @image. We use the macros from epsf.tex to support this.
+% If epsf.tex is not installed and @image is used, we complain.
+%
+% Check for and read epsf.tex up front. If we read it only at @image
+% time, we might be inside a group, and then its definitions would get
+% undone and the next image would fail.
+\openin 1 = epsf.tex
+\ifeof 1 \else
+ % Do not bother showing banner with epsf.tex v2.7k (available in
+ % doc/epsf.tex and on ctan).
+ \def\epsfannounce{\toks0 = }%
+ \input epsf.tex
+\fi
+\closein 1
+%
+% We will only complain once about lack of epsf.tex.
+\newif\ifwarnednoepsf
+\newhelp\noepsfhelp{epsf.tex must be installed for images to
+ work. It is also included in the Texinfo distribution, or you can get
+ it from ftp://tug.org/tex/epsf.tex.}
+%
+\def\image#1{%
+ \ifx\epsfbox\undefined
+ \ifwarnednoepsf \else
+ \errhelp = \noepsfhelp
+ \errmessage{epsf.tex not found, images will be ignored}%
+ \global\warnednoepsftrue
+ \fi
+ \else
+ \imagexxx #1,,,,,\finish
+ \fi
+}
+%
+% Arguments to @image:
+% #1 is (mandatory) image filename; we tack on .eps extension.
+% #2 is (optional) width, #3 is (optional) height.
+% #4 is (ignored optional) html alt text.
+% #5 is (ignored optional) extension.
+% #6 is just the usual extra ignored arg for parsing this stuff.
+\newif\ifimagevmode
+\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup
+ \catcode`\^^M = 5 % in case we're inside an example
+ \normalturnoffactive % allow _ et al. in names
+ % If the image is by itself, center it.
+ \ifvmode
+ \imagevmodetrue
+ \nobreak\bigskip
+ % Usually we'll have text after the image which will insert
+ % \parskip glue, so insert it here too to equalize the space
+ % above and below.
+ \nobreak\vskip\parskip
+ \nobreak
+ \line\bgroup\hss
+ \fi
+ %
+ % Output the image.
+ \ifpdf
+ \dopdfimage{#1}{#2}{#3}%
+ \else
+ % \epsfbox itself resets \epsf?size at each figure.
+ \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi
+ \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi
+ \epsfbox{#1.eps}%
+ \fi
+ %
+ \ifimagevmode \hss \egroup \bigbreak \fi % space after the image
+\endgroup}
+
+
+% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables,
+% etc. We don't actually implement floating yet, we always include the
+% float "here". But it seemed the best name for the future.
+%
+\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish}
+
+% There may be a space before second and/or third parameter; delete it.
+\def\eatcommaspace#1, {#1,}
+
+% #1 is the optional FLOATTYPE, the text label for this float, typically
+% "Figure", "Table", "Example", etc. Can't contain commas. If omitted,
+% this float will not be numbered and cannot be referred to.
+%
+% #2 is the optional xref label. Also must be present for the float to
+% be referable.
+%
+% #3 is the optional positioning argument; for now, it is ignored. It
+% will somehow specify the positions allowed to float to (here, top, bottom).
+%
+% We keep a separate counter for each FLOATTYPE, which we reset at each
+% chapter-level command.
+\let\resetallfloatnos=\empty
+%
+\def\dofloat#1,#2,#3,#4\finish{%
+ \let\thiscaption=\empty
+ \let\thisshortcaption=\empty
+ %
+ % don't lose footnotes inside @float.
+ %
+ % BEWARE: when the floats start float, we have to issue warning whenever an
+ % insert appears inside a float which could possibly float. --kasal, 26may04
+ %
+ \startsavinginserts
+ %
+ % We can't be used inside a paragraph.
+ \par
+ %
+ \vtop\bgroup
+ \def\floattype{#1}%
+ \def\floatlabel{#2}%
+ \def\floatloc{#3}% we do nothing with this yet.
+ %
+ \ifx\floattype\empty
+ \let\safefloattype=\empty
+ \else
+ {%
+ % the floattype might have accents or other special characters,
+ % but we need to use it in a control sequence name.
+ \indexnofonts
+ \turnoffactive
+ \xdef\safefloattype{\floattype}%
+ }%
+ \fi
+ %
+ % If label is given but no type, we handle that as the empty type.
+ \ifx\floatlabel\empty \else
+ % We want each FLOATTYPE to be numbered separately (Figure 1,
+ % Table 1, Figure 2, ...). (And if no label, no number.)
+ %
+ \expandafter\getfloatno\csname\safefloattype floatno\endcsname
+ \global\advance\floatno by 1
+ %
+ {%
+ % This magic value for \thissection is output by \setref as the
+ % XREFLABEL-title value. \xrefX uses it to distinguish float
+ % labels (which have a completely different output format) from
+ % node and anchor labels. And \xrdef uses it to construct the
+ % lists of floats.
+ %
+ \edef\thissection{\floatmagic=\safefloattype}%
+ \setref{\floatlabel}{Yfloat}%
+ }%
+ \fi
+ %
+ % start with \parskip glue, I guess.
+ \vskip\parskip
+ %
+ % Don't suppress indentation if a float happens to start a section.
+ \restorefirstparagraphindent
+}
+
+% we have these possibilities:
+% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap
+% @float Foo,lbl & no caption: Foo 1.1
+% @float Foo & @caption{Cap}: Foo: Cap
+% @float Foo & no caption: Foo
+% @float ,lbl & Caption{Cap}: 1.1: Cap
+% @float ,lbl & no caption: 1.1
+% @float & @caption{Cap}: Cap
+% @float & no caption:
+%
+\def\Efloat{%
+ \let\floatident = \empty
+ %
+ % In all cases, if we have a float type, it comes first.
+ \ifx\floattype\empty \else \def\floatident{\floattype}\fi
+ %
+ % If we have an xref label, the number comes next.
+ \ifx\floatlabel\empty \else
+ \ifx\floattype\empty \else % if also had float type, need tie first.
+ \appendtomacro\floatident{\tie}%
+ \fi
+ % the number.
+ \appendtomacro\floatident{\chaplevelprefix\the\floatno}%
+ \fi
+ %
+ % Start the printed caption with what we've constructed in
+ % \floatident, but keep it separate; we need \floatident again.
+ \let\captionline = \floatident
+ %
+ \ifx\thiscaption\empty \else
+ \ifx\floatident\empty \else
+ \appendtomacro\captionline{: }% had ident, so need a colon between
+ \fi
+ %
+ % caption text.
+ \appendtomacro\captionline{\scanexp\thiscaption}%
+ \fi
+ %
+ % If we have anything to print, print it, with space before.
+ % Eventually this needs to become an \insert.
+ \ifx\captionline\empty \else
+ \vskip.5\parskip
+ \captionline
+ %
+ % Space below caption.
+ \vskip\parskip
+ \fi
+ %
+ % If have an xref label, write the list of floats info. Do this
+ % after the caption, to avoid chance of it being a breakpoint.
+ \ifx\floatlabel\empty \else
+ % Write the text that goes in the lof to the aux file as
+ % \floatlabel-lof. Besides \floatident, we include the short
+ % caption if specified, else the full caption if specified, else nothing.
+ {%
+ \atdummies \turnoffactive \otherbackslash
+ % since we read the caption text in the macro world, where ^^M
+ % is turned into a normal character, we have to scan it back, so
+ % we don't write the literal three characters "^^M" into the aux file.
+ \scanexp{%
+ \xdef\noexpand\gtemp{%
+ \ifx\thisshortcaption\empty
+ \thiscaption
+ \else
+ \thisshortcaption
+ \fi
+ }%
+ }%
+ \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident
+ \ifx\gtemp\empty \else : \gtemp \fi}}%
+ }%
+ \fi
+ \egroup % end of \vtop
+ %
+ % place the captured inserts
+ %
+ % BEWARE: when the floats start float, we have to issue warning whenever an
+ % insert appears inside a float which could possibly float. --kasal, 26may04
+ %
+ \checkinserts
+}
+
+% Append the tokens #2 to the definition of macro #1, not expanding either.
+%
+\def\appendtomacro#1#2{%
+ \expandafter\def\expandafter#1\expandafter{#1#2}%
+}
+
+% @caption, @shortcaption
+%
+\def\caption{\docaption\thiscaption}
+\def\shortcaption{\docaption\thisshortcaption}
+\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption}
+\def\defcaption#1#2{\egroup \def#1{#2}}
+
+% The parameter is the control sequence identifying the counter we are
+% going to use. Create it if it doesn't exist and assign it to \floatno.
+\def\getfloatno#1{%
+ \ifx#1\relax
+ % Haven't seen this figure type before.
+ \csname newcount\endcsname #1%
+ %
+ % Remember to reset this floatno at the next chap.
+ \expandafter\gdef\expandafter\resetallfloatnos
+ \expandafter{\resetallfloatnos #1=0 }%
+ \fi
+ \let\floatno#1%
+}
+
+% \setref calls this to get the XREFLABEL-snt value. We want an @xref
+% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we
+% first read the @float command.
+%
+\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}%
+
+% Magic string used for the XREFLABEL-title value, so \xrefX can
+% distinguish floats from other xref types.
+\def\floatmagic{!!float!!}
+
+% #1 is the control sequence we are passed; we expand into a conditional
+% which is true if #1 represents a float ref. That is, the magic
+% \thissection value which we \setref above.
+%
+\def\iffloat#1{\expandafter\doiffloat#1==\finish}
+%
+% #1 is (maybe) the \floatmagic string. If so, #2 will be the
+% (safe) float type for this float. We set \iffloattype to #2.
+%
+\def\doiffloat#1=#2=#3\finish{%
+ \def\temp{#1}%
+ \def\iffloattype{#2}%
+ \ifx\temp\floatmagic
+}
+
+% @listoffloats FLOATTYPE - print a list of floats like a table of contents.
+%
+\parseargdef\listoffloats{%
+ \def\floattype{#1}% floattype
+ {%
+ % the floattype might have accents or other special characters,
+ % but we need to use it in a control sequence name.
+ \indexnofonts
+ \turnoffactive
+ \xdef\safefloattype{\floattype}%
+ }%
+ %
+ % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE.
+ \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax
+ \ifhavexrefs
+ % if the user said @listoffloats foo but never @float foo.
+ \message{\linenumber No `\safefloattype' floats to list.}%
+ \fi
+ \else
+ \begingroup
+ \leftskip=\tocindent % indent these entries like a toc
+ \let\do=\listoffloatsdo
+ \csname floatlist\safefloattype\endcsname
+ \endgroup
+ \fi
+}
+
+% This is called on each entry in a list of floats. We're passed the
+% xref label, in the form LABEL-title, which is how we save it in the
+% aux file. We strip off the -title and look up \XRLABEL-lof, which
+% has the text we're supposed to typeset here.
+%
+% Figures without xref labels will not be included in the list (since
+% they won't appear in the aux file).
+%
+\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish}
+\def\listoffloatsdoentry#1-title\finish{{%
+ % Can't fully expand XR#1-lof because it can contain anything. Just
+ % pass the control sequence. On the other hand, XR#1-pg is just the
+ % page number, and we want to fully expand that so we can get a link
+ % in pdf output.
+ \toksA = \expandafter{\csname XR#1-lof\endcsname}%
+ %
+ % use the same \entry macro we use to generate the TOC and index.
+ \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}%
+ \writeentry
+}}
+
+\message{localization,}
+% and i18n.
+
+% @documentlanguage is usually given very early, just after
+% @setfilename. If done too late, it may not override everything
+% properly. Single argument is the language abbreviation.
+% It would be nice if we could set up a hyphenation file here.
+%
+\parseargdef\documentlanguage{%
+ \tex % read txi-??.tex file in plain TeX.
+ % Read the file if it exists.
+ \openin 1 txi-#1.tex
+ \ifeof 1
+ \errhelp = \nolanghelp
+ \errmessage{Cannot read language file txi-#1.tex}%
+ \else
+ \input txi-#1.tex
+ \fi
+ \closein 1
+ \endgroup
+}
+\newhelp\nolanghelp{The given language definition file cannot be found or
+is empty. Maybe you need to install it? In the current directory
+should work if nowhere else does.}
+
+
+% @documentencoding should change something in TeX eventually, most
+% likely, but for now just recognize it.
+\let\documentencoding = \comment
+
+
+% Page size parameters.
+%
+\newdimen\defaultparindent \defaultparindent = 15pt
+
+\chapheadingskip = 15pt plus 4pt minus 2pt
+\secheadingskip = 12pt plus 3pt minus 2pt
+\subsecheadingskip = 9pt plus 2pt minus 2pt
+
+% Prevent underfull vbox error messages.
+\vbadness = 10000
+
+% Don't be so finicky about underfull hboxes, either.
+\hbadness = 2000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything. We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize. We call this whenever the paper size is set.
+%
+\def\setemergencystretch{%
+ \ifx\emergencystretch\thisisundefined
+ % Allow us to assign to \emergencystretch anyway.
+ \def\emergencystretch{\dimen0}%
+ \else
+ \emergencystretch = .15\hsize
+ \fi
+}
+
+% Parameters in order: 1) textheight; 2) textwidth; 3) voffset;
+% 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8)
+% physical page width.
+%
+% We also call \setleading{\textleading}, so the caller should define
+% \textleading. The caller should also set \parskip.
+%
+\def\internalpagesizes#1#2#3#4#5#6#7#8{%
+ \voffset = #3\relax
+ \topskip = #6\relax
+ \splittopskip = \topskip
+ %
+ \vsize = #1\relax
+ \advance\vsize by \topskip
+ \outervsize = \vsize
+ \advance\outervsize by 2\topandbottommargin
+ \pageheight = \vsize
+ %
+ \hsize = #2\relax
+ \outerhsize = \hsize
+ \advance\outerhsize by 0.5in
+ \pagewidth = \hsize
+ %
+ \normaloffset = #4\relax
+ \bindingoffset = #5\relax
+ %
+ \ifpdf
+ \pdfpageheight #7\relax
+ \pdfpagewidth #8\relax
+ \fi
+ %
+ \setleading{\textleading}
+ %
+ \parindent = \defaultparindent
+ \setemergencystretch
+}
+
+% @letterpaper (the default).
+\def\letterpaper{{\globaldefs = 1
+ \parskip = 3pt plus 2pt minus 1pt
+ \textleading = 13.2pt
+ %
+ % If page is nothing but text, make it come out even.
+ \internalpagesizes{46\baselineskip}{6in}%
+ {\voffset}{.25in}%
+ {\bindingoffset}{36pt}%
+ {11in}{8.5in}%
+}}
+
+% Use @smallbook to reset parameters for 7x9.5 (or so) format.
+\def\smallbook{{\globaldefs = 1
+ \parskip = 2pt plus 1pt
+ \textleading = 12pt
+ %
+ \internalpagesizes{7.5in}{5in}%
+ {\voffset}{.25in}%
+ {\bindingoffset}{16pt}%
+ {9.25in}{7in}%
+ %
+ \lispnarrowing = 0.3in
+ \tolerance = 700
+ \hfuzz = 1pt
+ \contentsrightmargin = 0pt
+ \defbodyindent = .5cm
+}}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{{\globaldefs = 1
+ \parskip = 3pt plus 2pt minus 1pt
+ \textleading = 13.2pt
+ %
+ % Double-side printing via postscript on Laserjet 4050
+ % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm.
+ % To change the settings for a different printer or situation, adjust
+ % \normaloffset until the front-side and back-side texts align. Then
+ % do the same for \bindingoffset. You can set these for testing in
+ % your texinfo source file like this:
+ % @tex
+ % \global\normaloffset = -6mm
+ % \global\bindingoffset = 10mm
+ % @end tex
+ \internalpagesizes{51\baselineskip}{160mm}
+ {\voffset}{\hoffset}%
+ {\bindingoffset}{44pt}%
+ {297mm}{210mm}%
+ %
+ \tolerance = 700
+ \hfuzz = 1pt
+ \contentsrightmargin = 0pt
+ \defbodyindent = 5mm
+}}
+
+% Use @afivepaper to print on European A5 paper.
+% From romildo@urano.iceb.ufop.br, 2 July 2000.
+% He also recommends making @example and @lisp be small.
+\def\afivepaper{{\globaldefs = 1
+ \parskip = 2pt plus 1pt minus 0.1pt
+ \textleading = 12.5pt
+ %
+ \internalpagesizes{160mm}{120mm}%
+ {\voffset}{\hoffset}%
+ {\bindingoffset}{8pt}%
+ {210mm}{148mm}%
+ %
+ \lispnarrowing = 0.2in
+ \tolerance = 800
+ \hfuzz = 1.2pt
+ \contentsrightmargin = 0pt
+ \defbodyindent = 2mm
+ \tableindent = 12mm
+}}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper.
+\def\afourlatex{{\globaldefs = 1
+ \afourpaper
+ \internalpagesizes{237mm}{150mm}%
+ {\voffset}{4.6mm}%
+ {\bindingoffset}{7mm}%
+ {297mm}{210mm}%
+ %
+ % Must explicitly reset to 0 because we call \afourpaper.
+ \globaldefs = 0
+}}
+
+% Use @afourwide to print on A4 paper in landscape format.
+\def\afourwide{{\globaldefs = 1
+ \afourpaper
+ \internalpagesizes{241mm}{165mm}%
+ {\voffset}{-2.95mm}%
+ {\bindingoffset}{7mm}%
+ {297mm}{210mm}%
+ \globaldefs = 0
+}}
+
+% @pagesizes TEXTHEIGHT[,TEXTWIDTH]
+% Perhaps we should allow setting the margins, \topskip, \parskip,
+% and/or leading, also. Or perhaps we should compute them somehow.
+%
+\parseargdef\pagesizes{\pagesizesyyy #1,,\finish}
+\def\pagesizesyyy#1,#2,#3\finish{{%
+ \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi
+ \globaldefs = 1
+ %
+ \parskip = 3pt plus 2pt minus 1pt
+ \setleading{\textleading}%
+ %
+ \dimen0 = #1
+ \advance\dimen0 by \voffset
+ %
+ \dimen2 = \hsize
+ \advance\dimen2 by \normaloffset
+ %
+ \internalpagesizes{#1}{\hsize}%
+ {\voffset}{\normaloffset}%
+ {\bindingoffset}{44pt}%
+ {\dimen0}{\dimen2}%
+}}
+
+% Set default to letter.
+%
+\letterpaper
+
+
+\message{and turning on texinfo input format.}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\catcode`\$=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+\def\normaldollar{$}%$ font-lock fix
+
+% This macro is used to make a character print one way in \tt
+% (where it can probably be output as-is), and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi}
+
+% Same as above, but check for italic font. Actually this also catches
+% non-italic slanted fonts since it is impossible to distinguish them from
+% italic fonts. But since this is only used by $ and it uses \sl anyway
+% this is not a problem.
+\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt\char34}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt\char126}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }
+
+\catcode`\|=\active
+\def|{{\tt\char124}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+\catcode`\$=\active
+\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix
+
+% If a .fmt file is being used, characters that might appear in a file
+% name cannot be active until we have parsed the command line.
+% So turn them off again, and have \everyjob (or @setfilename) turn them on.
+% \otherifyactive is called near the end of this file.
+\def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
+
+\catcode`\@=0
+
+% \backslashcurfont outputs one backslash character in current font,
+% as in \char`\\.
+\global\chardef\backslashcurfont=`\\
+\global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work
+
+% \rawbackslash defines an active \ to do \backslashcurfont.
+% \otherbackslash defines an active \ to be a literal `\' character with
+% catcode other.
+{\catcode`\\=\active
+ @gdef@rawbackslash{@let\=@backslashcurfont}
+ @gdef@otherbackslash{@let\=@realbackslash}
+}
+
+% \realbackslash is an actual character `\' with catcode other.
+{\catcode`\\=\other @gdef@realbackslash{\}}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\backslashcurfont}}
+
+\catcode`\\=\active
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+@def@turnoffactive{%
+ @let"=@normaldoublequote
+ @let\=@realbackslash
+ @let~=@normaltilde
+ @let^=@normalcaret
+ @let_=@normalunderscore
+ @let|=@normalverticalbar
+ @let<=@normalless
+ @let>=@normalgreater
+ @let+=@normalplus
+ @let$=@normaldollar %$ font-lock fix
+ @unsepspaces
+}
+
+% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of
+% the literal character `\'. (Thus, \ is not expandable when this is in
+% effect.)
+%
+@def@normalturnoffactive{@turnoffactive @let\=@normalbackslash}
+
+% Make _ and + \other characters, temporarily.
+% This is canceled by @fixbackslash.
+@otherifyactive
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+% Also back turn on active characters that might appear in the input
+% file name, in case not using a pre-dumped format.
+%
+@gdef@fixbackslash{%
+ @ifx\@eatinput @let\ = @normalbackslash @fi
+ @catcode`+=@active
+ @catcode`@_=@active
+}
+
+% Say @foo, not \foo, in error messages.
+@escapechar = `@@
+
+% These look ok in all fonts, so just make them not special.
+@catcode`@& = @other
+@catcode`@# = @other
+@catcode`@% = @other
+
+
+@c Local variables:
+@c eval: (add-hook 'write-file-hooks 'time-stamp)
+@c page-delimiter: "^\\\\message"
+@c time-stamp-start: "def\\\\texinfoversion{"
+@c time-stamp-format: "%:y-%02m-%02d.%02H"
+@c time-stamp-end: "}"
+@c End:
+
+@c vim:sw=2:
+
+@ignore
+ arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115
+@end ignore
diff --git a/doc/version.texi b/doc/version.texi
new file mode 100644
index 000000000000..41b19a30d5c6
--- /dev/null
+++ b/doc/version.texi
@@ -0,0 +1,4 @@
+@set UPDATED 20 April 2006
+@set UPDATED-MONTH April 2006
+@set EDITION 6.1.5
+@set VERSION 6.1.5