From e3bd25281eab155d1387cc0e76abd81bce0d2016 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Mon, 29 Apr 2013 22:23:26 +0200
Subject: [PATCH] WIP amd upgrade

---
 contrib/amd/AUTHORS                            |  168 +-
 contrib/amd/BUGS                               |  201 +-
 contrib/amd/COPYING                            |    2 +-
 contrib/amd/ChangeLog                          |11748 ++++++++++++++++++------
 contrib/amd/FAQ                                |   69 +
 contrib/amd/FREEBSD-Xlist                      |  146 +-
 contrib/amd/FREEBSD-upgrade                    |   91 +-
 contrib/amd/INSTALL                            |  239 +-
 contrib/amd/MIRRORS                            |   50 -
 contrib/amd/MIRRORS.html                       |  106 +
 contrib/amd/MIRRORS.txt                        |   60 +
 contrib/amd/NEWS                               |  737 ++-
 contrib/amd/README                             |   27 +-
 contrib/amd/README.attrcache                   |  129 +
 contrib/amd/README.ldap                        |   57 +
 contrib/amd/README.y2k                         |    8 +-
 contrib/amd/TODO                               |  177 -
 contrib/amd/amd/am_ops.c                       |  211 +-
 contrib/amd/amd/amd.8                          |  300 +-
 contrib/amd/amd/amd.c                          |  257 +-
 contrib/amd/amd/amd.h                          |  735 ++-
 contrib/amd/amd/amfs_auto.c                    | 1493 +---
 contrib/amd/amd/amfs_direct.c                  |   30 +-
 contrib/amd/amd/amfs_error.c                   |   59 +-
 contrib/amd/amd/amfs_generic.c                 | 1262 +++
 contrib/amd/amd/amfs_host.c                    |  181 +-
 contrib/amd/amd/amfs_inherit.c                 |  200 -
 contrib/amd/amd/amfs_link.c                    |   78 +-
 contrib/amd/amd/amfs_linkx.c                   |   34 +-
 contrib/amd/amd/amfs_nfsl.c                    |  143 +-
 contrib/amd/amd/amfs_nfsx.c                    |  176 +-
 contrib/amd/amd/amfs_program.c                 |   64 +-
 contrib/amd/amd/amfs_root.c                    |   30 +-
 contrib/amd/amd/amfs_toplvl.c                  |  363 +-
 contrib/amd/amd/amfs_union.c                   |   52 +-
 contrib/amd/amd/amq_subr.c                     |  213 +-
 contrib/amd/amd/amq_svc.c                      |   96 +-
 contrib/amd/amd/autil.c                        |  623 +-
 contrib/amd/amd/clock.c                        |   34 +-
 contrib/amd/amd/conf.c                         |  589 ++-
 contrib/amd/amd/conf_parse.y                   |   25 +-
 contrib/amd/amd/conf_tok.l                     |   22 +-
 contrib/amd/amd/get_args.c                     |  262 +-
 contrib/amd/amd/info_exec.c                    |  423 +
 contrib/amd/amd/info_file.c                    |   42 +-
 contrib/amd/amd/info_hesiod.c                  |   26 +-
 contrib/amd/amd/info_ldap.c                    |  268 +-
 contrib/amd/amd/info_ndbm.c                    |   15 +-
 contrib/amd/amd/info_nis.c                     |   19 +-
 contrib/amd/amd/info_nisplus.c                 |   58 +-
 contrib/amd/amd/info_passwd.c                  |   17 +-
 contrib/amd/amd/info_union.c                   |   28 +-
 contrib/amd/amd/map.c                          |  724 +-
 contrib/amd/amd/mapc.c                         |  339 +-
 contrib/amd/amd/mntfs.c                        |  121 +-
 contrib/amd/amd/nfs_prot_svc.c                 |   96 +-
 contrib/amd/amd/nfs_start.c                    |  193 +-
 contrib/amd/amd/nfs_subr.c                     |  391 +-
 contrib/amd/amd/ops_TEMPLATE.c                 |   52 +-
 contrib/amd/amd/ops_autofs.c                   | 1281 ---
 contrib/amd/amd/ops_cachefs.c                  |   67 +-
 contrib/amd/amd/ops_cdfs.c                     |   95 +-
 contrib/amd/amd/ops_efs.c                      |   58 +-
 contrib/amd/amd/ops_lofs.c                     |   55 +-
 contrib/amd/amd/ops_mfs.c                      |    5 +-
 contrib/amd/amd/ops_nfs.c                      |  634 +-
 contrib/amd/amd/ops_nfs3.c                     |    5 +-
 contrib/amd/amd/ops_nullfs.c                   |    5 +-
 contrib/amd/amd/ops_pcfs.c                     |  123 +-
 contrib/amd/amd/ops_tfs.c                      |    5 +-
 contrib/amd/amd/ops_tmpfs.c                    |    5 +-
 contrib/amd/amd/ops_ufs.c                      |   65 +-
 contrib/amd/amd/ops_umapfs.c                   |    5 +-
 contrib/amd/amd/ops_unionfs.c                  |    5 +-
 contrib/amd/amd/ops_xfs.c                      |   59 +-
 contrib/amd/amd/opts.c                         |  506 +-
 contrib/amd/amd/readdir.c                      |  498 +
 contrib/amd/amd/restart.c                      |  312 +-
 contrib/amd/amd/rpc_fwd.c                      |   76 +-
 contrib/amd/amd/sched.c                        |   72 +-
 contrib/amd/amd/srvr_amfs_auto.c               |   24 +-
 contrib/amd/amd/srvr_nfs.c                     |  630 +-
 contrib/amd/amq/amq.8                          |  265 +-
 contrib/amd/amq/amq.c                          |  437 +-
 contrib/amd/amq/amq.h                          |    6 +-
 contrib/amd/amq/amq_clnt.c                     |   37 +-
 contrib/amd/amq/amq_xdr.c                      |   24 +-
 contrib/amd/amq/pawd.1                         |   50 +-
 contrib/amd/amq/pawd.c                         |   85 +-
 contrib/amd/aux_conf.h.in                      |   58 +
 contrib/amd/bootstrap                          |  108 +
 contrib/amd/conf/checkmount/checkmount_bsd44.c |    5 +-
 contrib/amd/conf/hn_dref/hn_dref_default.h     |    2 -
 contrib/amd/conf/mtab/mtab_bsd.c               |   11 +-
 contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h  |   10 +-
 contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h  |   61 +-
 contrib/amd/conf/sa_dref/sa_dref_bsd44.h       |    1 +
 contrib/amd/conf/transp/transp_sockets.c       |  318 +-
 contrib/amd/conf/trap/trap_default.h           |    1 +
 contrib/amd/conf/umount/umount_bsd44.c         |   55 +-
 contrib/amd/doc/am-utils.texi                  | 2147 +++--
 contrib/amd/doc/stamp-vti                      |    7 +-
 contrib/amd/doc/texinfo.tex                    | 7379 +++++++++------
 contrib/amd/doc/version.texi                   |    7 +-
 contrib/amd/fixmount/fixmount.8                |  143 +-
 contrib/amd/fixmount/fixmount.c                |   30 +-
 contrib/amd/fsinfo/fsi_analyze.c               |   68 +-
 contrib/amd/fsinfo/fsi_data.h                  |    9 +-
 contrib/amd/fsinfo/fsi_dict.c                  |    5 +-
 contrib/amd/fsinfo/fsi_gram.y                  |   21 +-
 contrib/amd/fsinfo/fsi_lex.l                   |   18 +-
 contrib/amd/fsinfo/fsi_util.c                  |   40 +-
 contrib/amd/fsinfo/fsinfo.8                    |  100 +-
 contrib/amd/fsinfo/fsinfo.c                    |   21 +-
 contrib/amd/fsinfo/fsinfo.h                    |   25 +-
 contrib/amd/fsinfo/wr_atab.c                   |   16 +-
 contrib/amd/fsinfo/wr_bparam.c                 |    5 +-
 contrib/amd/fsinfo/wr_dumpset.c                |    5 +-
 contrib/amd/fsinfo/wr_exportfs.c               |    5 +-
 contrib/amd/fsinfo/wr_fstab.c                  |    7 +-
 contrib/amd/hlfsd/hlfsd.8                      |  254 +-
 contrib/amd/hlfsd/hlfsd.c                      |  209 +-
 contrib/amd/hlfsd/hlfsd.h                      |   32 +-
 contrib/amd/hlfsd/homedir.c                    |  120 +-
 contrib/amd/hlfsd/nfs_prot_svc.c               |   35 +-
 contrib/amd/hlfsd/stubs.c                      |  131 +-
 contrib/amd/include/am_compat.h                |  135 +-
 contrib/amd/include/am_defs.h                  |  338 +-
 contrib/amd/include/am_utils.h                 |  730 +--
 contrib/amd/include/am_xdr_func.h              |  184 +-
 contrib/amd/include/amq_defs.h                 |    8 +-
 contrib/amd/include/mount_headers1.h           |  216 +
 contrib/amd/include/mount_headers2.h           |   87 +
 contrib/amd/ldap-id.ms                         |  306 +
 contrib/amd/ldap-id.txt                        |  360 +
 contrib/amd/ldap.schema                        |   52 +
 contrib/amd/libamu/alloca.c                    |  504 -
 contrib/amd/libamu/amu.h                       |    7 +-
 contrib/amd/libamu/clnt_sperrno.c              |  147 -
 contrib/amd/libamu/hasmntopt.c                 |   15 +-
 contrib/amd/libamu/misc_rpc.c                  |   52 +-
 contrib/amd/libamu/mount_fs.c                  |  593 +-
 contrib/amd/libamu/mtab.c                      |  167 +-
 contrib/amd/libamu/nfs_prot_xdr.c              |    5 +-
 contrib/amd/libamu/strerror.c                  |   68 +
 contrib/amd/libamu/strutil.c                   |  270 +
 contrib/amd/libamu/util.c                      |  176 -
 contrib/amd/libamu/wire.c                      |  190 +-
 contrib/amd/libamu/xdr_func.c                  |  483 +-
 contrib/amd/libamu/xutil.c                     |  360 +-
 contrib/amd/mk-amd-map/mk-amd-map.8            |   43 +-
 contrib/amd/mk-amd-map/mk-amd-map.c            |   49 +-
 contrib/amd/scripts/am-eject.in                |   11 +-
 contrib/amd/scripts/amd.conf-sample            |  119 +-
 contrib/amd/scripts/amd.conf.5                 | 1142 ++-
 contrib/amd/scripts/amd2ldif.in                |    6 +-
 contrib/amd/scripts/amd2sun.in                 |    2 +-
 contrib/amd/scripts/automount2amd.8            |   25 +-
 contrib/amd/scripts/automount2amd.in           |    4 +-
 contrib/amd/scripts/ctl-amd.in                 |   50 +-
 contrib/amd/scripts/ctl-hlfsd.in               |   19 +-
 contrib/amd/scripts/expn.1                     |  165 +-
 contrib/amd/scripts/expn.in                    |   20 +-
 contrib/amd/scripts/fix-amd-map.in             |    2 +-
 contrib/amd/scripts/fixrmtab.in                |    2 +-
 contrib/amd/scripts/lostaltmail.conf-sample    |   84 -
 contrib/amd/scripts/lostaltmail.in             |  649 --
 contrib/amd/scripts/redhat-ctl-amd.in          |  106 +
 contrib/amd/scripts/test-attrcache.in          |  135 +
 contrib/amd/scripts/wait4amd.in                |    2 +-
 contrib/amd/scripts/wait4amd2die.in            |    6 +-
 contrib/amd/tasks                              |  117 +-
 contrib/amd/vers.m4                            |    1 +
 contrib/amd/wire-test/wire-test.8              |   47 +-
 contrib/amd/wire-test/wire-test.c              |   10 +-
 etc/amd.map                                    |    5 +-
 etc/rc.d/amd                                   |   62 +-
 usr.sbin/amd/Makefile                          |    7 +-
 usr.sbin/amd/Makefile.inc                      |   29 +-
 usr.sbin/amd/amd/Makefile                      |   49 +-
 usr.sbin/amd/amq/Makefile                      |   18 +-
 usr.sbin/amd/doc/Makefile                      |    7 +-
 usr.sbin/amd/fixmount/Makefile                 |   23 +-
 usr.sbin/amd/fsinfo/Makefile                   |   22 +-
 usr.sbin/amd/hlfsd/Makefile                    |   19 +-
 usr.sbin/amd/include/Makefile                  |   23 +-
 usr.sbin/amd/include/amu_autofs_prot.h         |    8 +
 usr.sbin/amd/include/aux_conf.h                |   30 +-
 usr.sbin/amd/include/build_version.h           |    9 +-
 usr.sbin/amd/include/config.h                  | 2861 +++---
 usr.sbin/amd/include/newvers.sh                |   39 +-
 usr.sbin/amd/libamu/Makefile                   |   40 +-
 usr.sbin/amd/mk-amd-map/Makefile               |   13 +-
 usr.sbin/amd/pawd/Makefile                     |   18 +-
 usr.sbin/amd/scripts/Makefile                  |    7 +-
 usr.sbin/amd/wire-test/Makefile                |   14 +-
 196 files changed, 32719 insertions(+), 20175 deletions(-)
 create mode 100644 contrib/amd/FAQ
 delete mode 100644 contrib/amd/MIRRORS
 create mode 100644 contrib/amd/MIRRORS.html
 create mode 100644 contrib/amd/MIRRORS.txt
 create mode 100644 contrib/amd/README.attrcache
 create mode 100644 contrib/amd/README.ldap
 delete mode 100644 contrib/amd/TODO
 create mode 100644 contrib/amd/amd/amfs_generic.c
 delete mode 100644 contrib/amd/amd/amfs_inherit.c
 create mode 100644 contrib/amd/amd/info_exec.c
 delete mode 100644 contrib/amd/amd/ops_autofs.c
 create mode 100644 contrib/amd/amd/readdir.c
 create mode 100644 contrib/amd/aux_conf.h.in
 create mode 100755 contrib/amd/bootstrap
 delete mode 100644 contrib/amd/conf/hn_dref/hn_dref_default.h
 create mode 100644 contrib/amd/include/mount_headers1.h
 create mode 100644 contrib/amd/include/mount_headers2.h
 create mode 100644 contrib/amd/ldap-id.ms
 create mode 100644 contrib/amd/ldap-id.txt
 create mode 100644 contrib/amd/ldap.schema
 delete mode 100644 contrib/amd/libamu/alloca.c
 delete mode 100644 contrib/amd/libamu/clnt_sperrno.c
 create mode 100644 contrib/amd/libamu/strerror.c
 create mode 100644 contrib/amd/libamu/strutil.c
 delete mode 100644 contrib/amd/libamu/util.c
 delete mode 100644 contrib/amd/scripts/lostaltmail.conf-sample
 delete mode 100755 contrib/amd/scripts/lostaltmail.in
 create mode 100755 contrib/amd/scripts/redhat-ctl-amd.in
 create mode 100755 contrib/amd/scripts/test-attrcache.in
 create mode 100644 contrib/amd/vers.m4
 create mode 100644 usr.sbin/amd/include/amu_autofs_prot.h

diff --git a/contrib/amd/AUTHORS b/contrib/amd/AUTHORS
index 2618766..3c241d0 100644
--- a/contrib/amd/AUTHORS
+++ b/contrib/amd/AUTHORS
@@ -1,6 +1,4 @@
-# -*- text -*-
 PRIMARY AUTHORS AND MAJOR CONTRIBUTORS TO AM_UTILS:
-
 Original authors of amd were the Berkeley team and especially Jan-Simon
 Pendry.  Since then many people have contributed patches.
 
@@ -8,15 +6,16 @@ This file lists the ones who contributed major code changes, in no
 particular order, and I thank them all.  This is of course not to diminish
 the smaller contributes of the many others.  Thank you all.
 
-* Erez Zadok <ezk@cs.columbia.edu>
+* Erez Zadok <ezk@cs.sunysb.edu>
 
 The most significant changes were made by Erez Zadok in terms of bug fixes,
 ports, and new features added.  Erez Zadok is the current maintainer of
 am-utils, as of January 1997.
 
-There is a mailing list dedicated to developers of am-utils.  To subscribe
-to it, send mail to majordomo@majordomo.cs.columbia.edu, with the body of
-the message having the single line "subscribe amd-dev".
+* Ion Badulescu <ion@cs.columbia.edu>
+
+Co-maintainer of am-utils since late 1999: Linux and Solaris autofs support,
+Linux NFSv3 support, major code reorganization, etc...
 
 * Randall S. Winchester <rsw@glue.umd.edu>
 
@@ -85,6 +84,8 @@ syslog and/or syslog facilities.
 January 29, 1998: fix for 0.0.0.0 loopback on SunOS 3.X which defines
 IFF_ROUTE instead of IFF_LOOPBACK.
 
+May 30, 2000: correct logging types for addopts/mergeopts messages.
+
 * Daniel S. Riley  <dsr@mail.lns.cornell.edu>
 
 July 11, 1997: fixes to DU-4.0 to support string POSIX.1 signals, and struct
@@ -125,6 +126,12 @@ systems.  More misc fixes.
 February 3, 1998: don't start autofs listener unless autofs maps were in
 use.
 
+December 10, 1999: assorted fixed and lots of fixes to support in-kernel
+mount tables in Solaris 8.
+
+February 9, 2000: new debug options hrtime (hi-res timer) and xdrtrace.  bug
+fixes.
+
 * Jason Thorpe <thorpej@nas.nasa.gov>
 
 August 25, 1997: make amd work when talking to NIS+ servers in NIS
@@ -152,7 +159,7 @@ that do not allow forwarding of RPC messages to other services.
 August 10, 1997: netbsd and other bsd systems have a mask flag for
 pcfs_args (msdos mount).
 
-* Christos Zoulas <christos@deshaw.com>
+* Christos Zoulas <christos@zoulas.com>
 
 September 25, 1997: fix to initialize uid/gid fields of pcfs_args_t on
 netbsd.
@@ -161,6 +168,19 @@ October 10, 1997: compile time cleanups of printf()s in hlfsd code.  If nfs
 server is down or does not support a portmapper call, then mark it down as
 version 2, and try again later.
 
+November 29, 2002: compile fixes for NetBSD, a couple of bug fixes (one
+already fixed by maintainers)
+
+April 12, 2003: support new "unmount" option, useful to timeout removable
+local media mounts.
+
+October 12, 2004: patch to support two new amd.conf options, domain_strip
+and auto_attrcache.  Patch to cleanup NFS attribute-cache flag computation.
+Patch to fix an inconsistency in timeouts in the RPC code between socket and
+TLI implementations.  Patch to print version string (amd -v) after all
+options had been initialized, so we can print domain, host, and hostd.
+Linux patch to use umount2(2) if umount(2) fails.
+
 * Bill Paul <wpaul@ctr.columbia.edu>
 
 November 5, 1997: NFS v.3 support for AIX 4.2.1, which does *not* include
@@ -186,6 +206,8 @@ and proto.
 
 January 12, 1998: minor bug in output of amd -H.
 
+June 23, 2005: assortment of small compile bugs on aix4, and solaris 5/6/7.
+
 * Thomas Richter <richter@chemie.fu-berlin.de>
 
 January 13, 1998: use case insensitive comparisons for variables that need
@@ -261,6 +283,7 @@ copies, and using cached copies if map failed to reload.
 * Peter Breitenlohner <peb@mppmu.mpg.de>
 July 24, 1999: patch for linux 2.2.x to work with older libc5 systems, and
 nis_isup mis-logic fixes.
+December 13, 2001: report typos in scripts/amd.conf.5.
 
 * Dale Talcott <aeh@quest.cc.purdue.edu>
 July 26, 1999: added NFS3 support for AIX mounting.
@@ -274,3 +297,134 @@ September 5, 1999: pawd works for type:=nfsl.
 * Nick Williams <njw@ms.com>
 September 1, 1999: bug fix for incorrect symlinks when two locations are
 requested simultaneously.
+
+November 1, 1999: fixes to sync maps even if they are set to mapcache:=sync.
+
+January 19, 2000: fix (and reduce the incidence of) stale file handles when
+doing rapid mounts and umounts in succession.
+
+June 5, 2000: better handling of potential race-conditions during rapid
+u/mounts.  Correctly update d_drops stats for amq -s.
+
+* Johann Pfefferl <johann.pfefferl.jp@germany.agfa.com>
+November 16, 1999: fix to ldap code so repeated calls to string2he don't
+corrupt the string passed.
+
+* Amitha Perera <perera@cs.rpi.edu>
+December 9, 1999: detect all wire() interfaces correctly.
+
+* Steven Danz <sdanz@awc.kc.noaa.gov>
+January 25, 2000: allow browsable auto maps.
+
+* Wolfram Klaus	<klaus@physik.fu-berlin.de>.
+November 21, 2000: recognize proplist mnttab flag.
+
+* Thomas Klausner <tk@giga.or.at>
+November 21, 2000: lots of NetBSD fixes (many of which are generic).
+
+April 18, 2003: patch to reference am-utils info pages in man page.
+
+November 28, 2004: small fixes to typos in amd.conf(5) man page.
+
+* Olaf Kirch <okir@caldera.de>
+February 1, 2001: important Linux NFS error number mapping fixed
+
+* Ahmon Dancy <dancy@franz.com>
+February 9, 2001: Apple Rhapsody/Darwin/OS X port
+
+* Sebastien Bahloul <sebastien.bahloul@mangoosta.fr>
+July 3, 2001: LDAP fixes and updates to support new APIs
+
+March 27, 2002: LDAP bug and port to HPUX-11.
+
+* Philippe Troin <phil@fifi.org>
+July 12, 2001: Proper handling of GNU getopt, support for optionally
+disabling LDAP/Hesiod, fixes for the dev/nodev option on Linux.  Texi
+documentation fix.
+
+November 28, 2001: Bug fix.  Support "nolock" as an NFS option, not a
+generic mount option.
+
+July 17, 2003: pref:=null core dump fix.  libgdbm portability.  tcpd/librap
+support.  And a few other things for the 6.0 branch.
+
+* Trond Myklebust <trond.myklebust@fys.uio.no>
+January 10, 2002: Proper initialization of the timeo parameter on Linux, TCP
+_must_ have a timeout 2 orders of magnitude larger than UDP
+
+* George Ross <gdmr@dcs.ed.ac.uk>
+April 29, 2002: Rework of old code, support for wildcards in LDAP queries,
+and an FD leak fix.  Amd -A support.
+
+October 21, 2002: ldap_unbind fix for SIGPIPE, and support for LDAPv3
+protocol version parameter (with Tim Colles <timc@inf.ed.ac.uk>).
+
+* Matthias Scheler <tron@zhadum.de>
+June 14, 2002: patch to use "xlatecookie" NFS mount option.
+
+* Jun-ichiro itojun Hagino <itojun@iijlab.net>.
+June 11, 2002: minor fixes to support NetBSD 1.6A.
+
+* Sean Fagan <sef@apple.com>
+March 14, 2003: detect and use the MNT2_GEN_OPT_AUTOMNTFS mount flag
+on OS X / Darwin.
+
+* Hendrik Scholz <hscholz@raisdorf.net>
+June 9, 2003: mk-amd-map should open temp db file using O_EXCL.
+
+* Mark Davies <mark@mcs.vuw.ac.nz>
+July 14, 2003: define "xlatecookie" mnttab option if not defined (for
+NetBSD).  Support null hesiod entries if they start with a ".".
+
+* Eric S. Raymond <esr@thyrsus.com>
+December 9, 2003: fix unbalanced [] typo in fsinfo man page.
+
+* Martin Blapp <mb@imp.ch>
+July 6, 2004: recognize fields in pcfs_args_t in FreeBSD 5.
+
+* Dan Nelson <dnelson@allantgroup.com>
+August 2, 2004: pawd to recognize "host" type mounts.
+
+* Hauke Fath <hauke@Espresso.Rhein-Neckar.DE>
+August 3, 2004: pawd to recognize "linkx" type mounts.
+
+* Michael van Elst <M.van.Elst@science-computing.de>
+September 1, 2004: bug fix to avoid race condition in calls to mntctl on
+AIX.
+
+* Jonathan Chen <jon+amd@spock.org>
+October 22, 2004: patch/fix to move mlock/mlockall/plock code after the
+fork().
+June 29, 2005: core dump going off end of exported_ap[] array.
+September 29, 2005: patch/fix for pawd not to go into an infinite loop.
+October 25, 2005: patch/fix for pawd to repeatedly resolve path.
+
+* David Rage <rage@ucl.ac.uk>
+January 17, 2005: prevent Amd from logging 'Read-only filesystem' errors
+when the mount point has an ancestor (i.e. '/') that is mounted read-only.
+
+* Kevin Layer <layer@franz.com>
+January 28, 2005: basic instructions how to setup Amd on Mac OS-X.
+
+* Dan Ottavio <dottavio@ic.sunysb.edu>
+March 2, 2005: new global amd.conf option debug_mtab_file, to set the debug
+mtab file when using debug_options=mtab.  Default has changed from "./mtab"
+to "/tmp/mtab" to avoid security problem.  Bug fixed to ensure that Amd
+terminates properly even mtab file doesn't exist.
+
+* Erik Kline <ekline at ekline dot com>
+January 3, 2005: implementation of executable maps for Amd.
+
+* Jim Zajkowski <jim.zajkowski@gmail.com>
+March 14, 2005: small patch to amd2ldif.
+
+* Adam Morley <adam at gmi dot com>
+January 27, 2005: synchronize what amd2ldif does vs. what the ldap.schema
+expects.
+
+* Graeme Wilford <G.Wilford@surrey.ac.uk>
+July 4, 2005: buffer overflow in pawd.
+
+* Steve Plite <splite-amutils@sigint.cs.purdue.edu>
+September 22, 2005: repair reversed meaning of D_AMQ, so amq will unregister
+on exit.
diff --git a/contrib/amd/BUGS b/contrib/amd/BUGS
index 3bd0f16..3a3ba6b 100644
--- a/contrib/amd/BUGS
+++ b/contrib/amd/BUGS
@@ -1,7 +1,8 @@
-# -*- text -*-
-
 	    LIST OF KNOWN BUGS IN AM-UTILS OR OPERATING SYSTEMS
 
+Note: report am-utils bugs via Bugzilla to https://bugzilla.am-utils.org/ or
+by email to the am-utils@am-utils.org mailing list.
+
 
 (1) mips-sgi-irix*
 
@@ -20,10 +21,20 @@ reliable as yp_all() which uses TCP, but it is better than hanging.
 (I have some reports that older version of hpux-9, with older libc, also
 leak file descriptors.)
 
+[1C] SGI's MIPSpro C compiler on IRIX 6 has the unfortunate habit of
+creating code specificially for the machine it runs on.  The ABI and ISA
+used depend very much on the OS version and compiler release used.  This
+means that the resulting amd binary won't run on machines different from
+the build host, particularly older ones.  Older versions of am-utils
+enforced the O32 ABI when compiling with cc to work around this, but this
+ABI is deprecated in favor of the N32 ABI now, so we use -n32 -mips3 to
+ensure that the binaries run on every host capable of running IRIX 6 at
+all.  If this is not appropriate for you, configure with something like
+CC='cc -64' instead to get the desired ABI and ISA.
 
 (2) alpha-unknown-linux-gnu (RedHat Linux 4.2)
 
-hasmntopt(mnt, opt) can goes into an infinite loop if opt is any substring
+hasmntopt(mnt, opt) can go into an infinite loop if opt is any substring
 of mnt->mnt_opts.  Redhat 5.0 does not have this libc bug.  Here is an
 example program:
 
@@ -99,7 +110,7 @@ Upgrade to gcc 2.8.x or use IBM's xlC compiler.
 in strlen inside strdup inside svc_register().
 
 
-(5) *-linux-gnu (RedHat Linux 5.1)
+(5) *-linux-rh51 (RedHat Linux 5.1)
 
 There's a UDP file descriptor leak in libnsl in RedHat Linux 5.1.  This
 library part of glibc2.  Am-utils currently declares redhat 5.1 systems as
@@ -112,17 +123,181 @@ but it is not yet in the glibc-2.0.7-19 RPM.
 
 A bug in libc results in an amq binary that doesn't work; amq -v dumps core
 in xdr_string.  There is no known fix (source code or vendor patch) at this
-time.  (Please let amd-dev know if you know of a fix.)
+time.  (Please let am-utils@am-utils.org know if you know of a fix.)
 
 
 (7) *-aix4.3.2.0
 
-The plock() function appears to fail with ENOMEM (Not Enough Space).  When
-it fails, it consumes a lot of memory.  This appears to be an AIX bug.  I
-think plock returns an error code, but it partially succeeds to lock some
-pages, thus increasing memory consumption.  When partial failures occur, it
-is possible that AIX fails to unlock those pages it did lock.  Solution:
-turn off usage of plock on AIX.  Put plock=no in your amd.conf file (which
-is the default if you do nothing).
+The plock() function will pre-reserve all of the memory up to the maximum
+listed in the ulimit.  If the ulimit is infinite, plock() will try to take
+all of the system's memory, and fail with ENOMEM (Not Enough Space).
+Normally ulimit may be set to a few gigs of max memory usage, but even that
+is too much; Amd doesn't need more than a few megs of resident memory size
+(depending on the particular usage, number of maps, etc.)  Solution: lower
+your ulimit before starting amd.  This can be done inside the ctl-amd
+script, but be careful not to limit it too low.  Alternatively, don't use
+plock on aix-4.3: set it to plock=no in amd.conf (which is the default if
+you do nothing).
+
+
+(8) *-linux (systems using glibc 2.1, such as RedHat-6.x)
+
+There's a UDP file descriptor leak in the NIS routines in glibc, especially
+those that do yp_bind.  Until this is bug fixed, do not set nis_domain in
+amd.conf, but let the system pick up the default domain name as set by your
+system.  That would avoid using the buggy yp_bind routines in libc.
+
+
+(9) *-linux (SuSE systems using unfsd)
+
+The user-level nfsd (2.2beta44) on older SuSE Linux systems (and possibly
+others) dies with a SEGV when amd tries to contact it for access to a volume
+that does not exist, or one for which there is no permission to mount.
+
+
+(10) *-*-hpux11
+
+If you're using NFSv3, you must install HP patches PHNE_20344 and
+PHNE_20371.  If you don't, and you try to use amd with NFSv3 over TCP, your
+kernel will panic.
+
+
+(11) *-linux* (any system using a 2.2.18+ kernel)
+
+The Linux kernels don't support Amd's direct mounts very well, leading to
+erratic behavior: shares that don't get remounted after the first timeout,
+inability to restart Amd because its mount points cannot be unmounted, etc.
+There are some kernel patches on the am-utils Web site, which solve these
+problems.  See http://www.am-utils.org/patches/.
+
+Later 2.4.x kernels completely disallow the hack amd was using for direct
+mounts, so another solution will have to be found.
+
+Note: the above is for the old-style amd mount_type = nfs. The autofs mounts
+don't support direct mounts at all (due to lack of kernel support).
+
+(12) *-aix5.1.0.0 and *-hpux9*
+
+/bin/sh is broken and fails to run the configure script properly. You need
+to use /bin/ksh instead. The buildall script will do it for you; if for some
+reason you need to run configure directly, run it using 'ksh configure'
+instead of just 'configure'.
+
+[12A] *-aix5.2.*
+
+Apparently there is an NFS client side bug in vmount() which causes amd to
+hang when it starts (and tries to NFS-mount itself).  According to IBM
+engineers, this has to do with partial support code for IPv6: the NFS kernel
+code doesn't appear to recognize the sin_family of the amd vmount(),
+although amd does the right thing.  The bug doesn't appear to be in 5.1 or
+4.3.3.  A fix from IBM is available, APAR number IY41417.
+
+A binary built on 4.3.3 will not work on 5.2, because the kernel ABIs have
+changed.
+
+[12C] *-aix*
+
+It is important that you install bos.net.nfs.adt before configuring and
+building am-utils.  If you don't, you will get compile-time or
+configure-time errors, especially when configure tries to find AIX's
+definition of struct nfs_args.
+
+(13) *-linux and *-darwin6.0
+
+Certain linux kernels (2.4.18+ are fine, 2.4.10- are probably bad, those in
+between have not been tested) have a bug which causes them to reconnect
+broken NFS/TCP connections using unprivileged ports (greater than 1024),
+unlike the initial connections which do originate from privileged
+ports.  This can upset quite a few NFS servers and causes accesses to the
+mounted shares to fail with "Operation not permitted" (EPERM).
+
+The darwin (MacOS X) kernel defaults to using unprivileged ports, but that
+can be changed by setting the resvport mount flag (which amd sets by
+default).  Nonetheless, if a TCP connection breaks, under certain unclear
+circumstances the kernel might "forget" about that flag and start using
+unprivileged ports, causing the same EPERM error above.
+
+(14) Solaris
+
+The line "%option" in *.l files may cause Solaris /usr/ccs/bin/lex to abort
+with the error "missing translation value."  This is a bug in Solaris lex.
+
+Moreover, both Solaris yacc and lex produce code that does not pass strict
+compilation such as "gcc -Wall -Werror".
+
+Use GNU Flex and Bison instead.  You can download ready-made binaries from
+www.sunfreeware.com.  Note, however, that sometimes the binaries on
+sunfreeware.com don't seem to work, often because they are built against an
+older revision of Solaris or build tools.  In that case, build a fresh
+version of GNU flex and/or bison from the latest stable sources.  See
+http://www.gnu.org/software/flex/ and http://www.gnu.org/software/bison/.
+
+(15) Solaris 8 + patch 10899[34]-xx (18 <= xx < 25) or patch 11260[56]-xx
+
+With this patch, Sun updated the autofs kernel module and automountd
+userspace daemon from version 3 to version 4.  They also updated the
+/usr/include/rpcsvc/autofs_prot.x file, but forgot to regenerate the
+autofs_prot.h file.  Thus, when amd is compiled, it uses the old header and
+thinks it should use autofs version 3, when in fact the kernel now supports
+(and expects) only version 4.
+
+The workaround is to run 'rpcgen -C -h /usr/include/rpcsvc/autofs_prot.x >
+/usr/include/rpcsvc/autofs_prot.h' and completely reconfigure and rebuild
+am-utils (removing config.cache before running configure).
+
+The problem is fixed in patch revisions 10899[34]-25 and up.
+
+
+(16) Linux kernel 2.4+ and lofs mounts
+
+Lofs mounts are not supported by the linux kernel, at all, but since 2.4.0
+the kernel supports a similar type of mount called a bind mount.  Its
+semantics are closer to those of a hardlink than to those of lofs, and one
+of the results is that bind mounts ignore any mount options paseed to them.
+
+Amd uses bind mounts internally to emulate lofs mounts, which means that
+lofs mounts on linux will effectively ignore their mount parameters and
+inherit whatever options the original filesystem mounted upon had.
+
+
+(17) autoconf 2.57
+
+If you see configure warnings of the following kind:
+
+configure: WARNING: sys/proc.h: present but cannot be compiled
+configure: WARNING: sys/proc.h: check for missing prerequisite headers?
+configure: WARNING: sys/proc.h: proceeding with the preprocessor's result
+configure: WARNING:     ## ------------------------------------ ##
+configure: WARNING:     ## Report this to bug-autoconf@gnu.org. ##
+configure: WARNING:     ## ------------------------------------ ##
 
-Erez.
+please ignore them.  They are not real errors, and neither
+bug-autoconf@gnu.org nor the am-utils maintainers are interested in hearing
+about them.  Autoconf simply tries to do more than we need and attempts to
+compile each header in isolation, which fails for many system headers.
+That's ok, because we only need to know if a header file exists -- we know
+how to use it properly ourselves.
+
+While autoconf does offer a way to specify other files to be included with
+the tested header, in order to avoid these warnings, using it would enlarge
+the resulting configure script by an order of magnitude, and for no real
+gain.  Configure is big enough as it is, we don't need any more useless
+baggage in it.
+
+(18) NetBSD 2.0.2, FreeBSD 5.4, OpenBSD 3.7, and quite possibly most other
+     BSDs and other OSs (as of September 2005)
+
+Some BSD kernels don't have a way to turn off the NFS attribute cache.  They
+don't have a 'noac' mount flag, and setting various cache timeout fields in
+struct nfs_args doesn't turn off the attribute cache; instead, it sets the
+attribute cache timeout to some internal hard-coded default (usually
+anywhere from 5-30 seconds).  If Amd cannot turn off the NFS attribute
+cache, under heavy Amd usage, users could get ESTALE errors from automounted
+symlinks, or find that those symlinks point to the wrong place.  One
+workaround which would minimize this effect is to set auto_attrcache=1 in
+your amd.conf, but it doesn't eliminate the problem!  The best solutions are
+(1) to use Amd in Autofs mode, if it's supported in your OS, and (2) talk to
+your OS vendor to support a true "noac" flag.  See README.attrcache for more
+details.
+
+Erez & the am-utils team.
diff --git a/contrib/amd/COPYING b/contrib/amd/COPYING
index 040bc51..035f623 100644
--- a/contrib/amd/COPYING
+++ b/contrib/amd/COPYING
@@ -1,4 +1,4 @@
-Copyright (c) 1997-1999 Erez Zadok
+Copyright (c) 1997-2006 Erez Zadok
 Copyright (c) 1989 Jan-Simon Pendry
 Copyright (c) 1989 Imperial College of Science, Technology & Medicine
 Copyright (c) 1989 The Regents of the University of California.
diff --git a/contrib/amd/ChangeLog b/contrib/amd/ChangeLog
index ca984a2..12f2c5f 100644
--- a/contrib/amd/ChangeLog
+++ b/contrib/amd/ChangeLog
@@ -1,4358 +1,10224 @@
-1999-10-13  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2006-05-11  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* released snapshot am-utils-6.0.3s1
+	*******************************************************************
+	*** Released am-utils-6.1.5					***
+	*******************************************************************
 
-1999-10-12  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2006-05-10  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/amd.c (main): On AIX you must lower the stack size using
-	ulimit() before calling plock.  Otherwise plock will reserve a lot
-	of memory space based on your maximum stack size limit.  Since it
-	is not easily possible to tell what should the limit be, I print a
-	warning before calling plock(). See the manual pages for
-	ulimit(1,3,4) on your AIX system.
+	* Minor new ports: i386-unknown-freebsd6.1 (RELEASE)
+	powerpc-apple-darwin8.6.0, and i386-unknown-openbsd3.9.
 
-	* include/am_defs.h: define default extern for vsnprintf()
+	* libamu/mount_fs.c (compute_nfs_attrcache_flags): fix signedness
+	problems on IRIX-6.5.
 
-	* aux/configure.in: check for extern definition for vsnprintf()
+	* conf/autofs/autofs_solaris_v1.c (xdr_umntrequest): fix
+	signedness problems on IRIX-6.5.
 
-1999-10-08  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2006-05-01  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/amfs_auto.c (amfs_auto_bgmount): patch from Nick Williams
-	<njw@ms.com>.  SYMPTOMS: 'occasionally' sublinks do not point to
-	the correct location, but to the top level of the mountpoint and
-	an (error-hook) is seen being mounted in the log file. This causes
-	things to Go Wrong(TM).
-	CAUSE: When evaluating two locations which are requested
-	'practically simultaneously', and the two locations resolve to the
-	same NFS mountpoint (but different sublinks), the later request
-	will be "deferred" and retried after wakeup when the first mount
-	succeeds. To do this, it rewinds the options location string to
-	re-evaluate the location when the mount is retried. However, it
-	shouldn't rewind the options for two reasons: (a) the semantics of
-	the map language say you shouldn't and (b) the NFS mount reference
-	is not reset at the same time, meaning that on the retry it will
-	have an options structure out-of-sync with the mount
-	structure. The "shortcut" code when retrying the mount sees the
-	mount structure is already filled in and does not fully evaluate
-	the options structure.... so if the first location is not the one
-	which ties in with the mountpoint (see ordering in the
-	recreate-by), you're now well messed up.
+	* configure.in: check if libc already includes dbm functionality
+	(as in FreeBSD 6), then don't bother to check specific libraries
+	such as libdbm, gdbm, etc.
 
-	* BUGS: mention aix4.3 plock() bug (memory usage blows up and
-	plock fails)
+2006-04-21  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-10-07  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: detect G/DBM support via gdbm_compat library
+	(Debian 3.1).
 
-	* aux/GNUmakefile: certain files should be copied if they are
-	newer, not also if they are bigger: install-sh, ltconfig,
-	ltmain.sh, mdate-sh, missing, mkinstalldirs, and texinfo.tex.
+	* minor new port: powerpc-apple-darwin8.5.0
 
-	* minor new port: i586-pc-linux-gnu-rh6.1 (RedHat Linux 6.1)
+2006-04-20  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-10-05  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* scripts/amd.conf-sample, scripts/amd.conf.5, doc/am-utils.texi,
+	NEWS: document new nfs_allow_any_interface parameter.
 
-	* aux/macros/check_nfs_prot_headers.m4: prepare for OSF-5.
+	* include/am_compat.h (INADDR_LOOPBACK): define INADDR_LOOPBACK if
+	not defined, since some systems don't have it.
 
-	* aux/macros/check_nfs_fh_dref.m4: prepare for Tru64, aka OSF-5.
+2006-04-20  Nick Williams <Nick.Williams@morganstanley.com>
 
-1999-09-30  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/wire.c (is_interface_local): new boolena function to
+	determine if address represents any of the local interfaces.
+	(getwire): more properly check if address equals INADDR_LOOPBACK,
+	not if IFF_LOOPBACK is not (the latter isn't as correct).
 
-	*******************************************************************
-	*** Released am-utils-6.0.2					***
-	*******************************************************************
+	* include/am_utils.h: extern for new is_interface_local() function.
 
-1999-09-27  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/transp/transp_{sockets,tli}.c: don't define INADDR_LOOPBACK
+	here but in am_compat.h
 
-	* conf/mount/mount_linux.c (mount_linux): print the updated mount
-	flags.
+	* amd/nfs_prot_svc.c (nfs_program_2): if
+	nfs_allow_any_interface=yes, then allow NFS packets from any local
+	interface (not just 127.0.0.1).
 
-	* doc/am-utils.texi: document $full_os and $vendor.
+	* amd/conf.c (gopt_nfs_allow_any_interface): implement the new
+	amd.conf parameter nfs_allow_any_interface.
 
-	* scripts/amd.conf-sample: examples of $full_os and $vendor.
+	* amd/amd.h (CFM_NFS_ANY_INTERFACE): define new global flag when
+	al interfaces are acceptable for local NFS packets.
 
-	* scripts/amd.conf.5: document $full_os and $vendor.
+2006-04-18  Christos Zoulas  <christos@zoulas.com>
 
-	* amd/conf.c: add support for $full_os and $vendor.
+	* amd/opts.c: Add support for optionally specifying the hostname
+	to match against the netgroup in the netgrp and netgrpd selectors.
 
-1999-09-26  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2006-04-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* doc/am-utils.texi (netgrp Selector Function): don't give
-	examples with old single '=' assignment variable.  Use foo:=bar.
+	* libamu/mtab.c (hasmntval): fix inverted meaning of error from
+	hasmntvalerr().
 
-	* amd/amfs_auto.c (amfs_auto_bgmount): corectly indent long
-	comment describing this complex function.
+2006-04-14  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* doc/Makefile.am (alldocs): do install-ps last (because distiller
-	is slow) and install-html next to last (because texi2html is also
-	slow).
+	* libamu/mount_fs.c (compute_nfs_attrcache_flags): use new
+	hasmntvalerr() function to set attribute cache values only if they
+	were set (regardless whether they were set to zero or a non-zero
+	value).  Before, we were unable to distinguish between an error to
+	parse an option, and a user who actually wanted to set an
+	attribute-cache value to 0.  This now fixes an important
+	performance bug that Amd was turning off the attribute caches even
+	for regular (non-automounter) NFS mounts.
 
-	* amd/amd.8: Major fixes to the description of the option -t
-	timeout.retransmit.
+	* libamu/mtab.c (hasmntvalerr): new function to set the value of
+	an option into an integer, but ONLY if that options was set and
+	parsed correctly.  This function returns 1 on error, 0 on success
+	(instead of always setting the option value to 0).
+	(hasmntval): wrapper function around hasmntvalerr, which maintains
+	backwards compatibility (always sets option value to 0, even on
+	error to parse the option).
 
-	* doc/am-utils.texi: better description of "trace" debug option.
-	amd -H (not -v) shows log_options and debug_options.  Major fixes
-	to the description of amd -t timeout.retransmit, and the amd.conf
-	parameters nfs_retransmit_counter and nfs_retry_interval.
+	* amd/nfs_subr.c (fh_to_mp3): use long int printf format for
+	fhh_pid.
 
-	* scripts/amd.conf.5: better description of "trace" debug option.
-	amd -H (not -v) shows log_options and debug_options.  Major fixes
-	to the description of the parameters nfs_retransmit_counter and
-	nfs_retry_interval.
+2006-04-05  Christos Zoulas  <christos@zoulas.com>
 
-1999-09-25  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_generic.c (amfs_lookup_mntfs): fix use-after-free bug
+	(Coverity).
 
-	* doc/am-utils.texi (Automount Filesystem): cache:= is not a mount
-	option, but a mount map option.
+2006-03-27  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* libamu/xutil.c (switch_to_logfile): log the name of the log file
-	we switched into, after the log file had been [re]opened.
+	* doc/am-utils.texi, scripts/{amd.conf.5,amd.conf-sample}:
+	document new nfs_retransmit_counter_toplvl and
+	nfs_retry_interval_toplvl global amd.conf parameters.
 
-1999-09-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/conf.c (gopt_nfs_retransmit_counter_toplvl,
+	(gopt_nfs_retry_interval_toplvl): parse amd.conf
+	nfs_retransmit_counter_toplvl and nfs_retry_interval_toplvl global
+	parameters.
 
-	* amd/mapc.c (mapc_reload_map): count and show the number of times
-	a map was reloaded.  Only reload a map if its modify-time was
-	updated.  But amq -f forced a reload no matter what.
+	* amd/amfs_toplvl.c (amfs_toplvl_mount): support setting toplvl
+	timeo/retrans parameters for Amd's toplvl mounts, separately from
+	all other UDP or NFS mounts.
 
-	* amd/amd.h: new flag to struct mnt_map to count number of times a
-	map was reloaded.
+	* amd/amd.h: define a new timeo/retrans parameter for toplvl
+	mounts.
 
-	* amd/mapc.c (mapc_reload_map): attempt to reload the map without
-	losing current data by reloading into a temp copy, and switching
-	the hashes round only if the reload was successful.  Patch from Jon
-	Peatfield <J.S.Peatfield@damtp.cam.ac.uk>.
-	(mapc_sync): mapc_reload_map() always succeeds.
+2006-03-22  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-09-22  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* minor new port: i386-pc-linux-suse10.1 (beta 8).
 
-	* amd/info_ldap.c (amu_ldap_rebind): don't busy-loop trying to
-	rebind to an LDAP server forever.  Try up to 10 times.
+2006-03-21  Christos Zoulas  <christos@zoulas.com>
 
-	* fsinfo/fsi_lex.l (yyerror): rework code that will never happen
+	* amd/am_ops.c (merge_opts): Remove useless check found by
+	Coverity; xmalloc never returns NULL.
 
-	* released snapshot am-utils-6.0.2s2
+2006-03-21  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/configure.in: bumped library version-info to 3:2:1, since
-	some libamu code got changed.
+	* minor new ports: i386-pc-linux-fc5.
 
-	* libamu/xutil.c (real_plog): use vsnprintf, not vsprintf, which
-	is better and more secure.  Fix from "David O'Brien"
-	<obrien@NUXI.com>.
+	* amd/info_ldap.c: as of Linux Fedora Core 5 (which comes with
+	openldap-2.3.9), the ldap.h headers deprecate several functions
+	used in this file, such as ldap_unbind.  You get compile errors
+	about missing extern definitions.  Those externs are still in
+	<ldap.h>, but surrounded by an ifdef LDAP_DEPRECATED.  I am
+	turning on that ifdef at the top of info_ldap.c, under the
+	assumption that the functions may be deprecated, but they still
+	work for this (older?) version of the LDAP API.  It gets am-utils
+	to compile, but it is not clear if it will work perfectly.
 
-	* aux/configure.in: check for vsnprintf.
+	* libamu/xdr_func.c (xdr_am_mountres3_ok), amq/amq_xdr.c
+	(xdr_amq_mount_tree, xdr_amq_mount_tree_p,
+	xdr_amq_mount_info_list, xdr_amq_mount_tree_list), amq/amq.c
+	(show_mti), amd/amq_subr.c (xdr_amq_setopt, xdr_amq_mount_subtree,
+	xdr_amq_mount_tree, xdr_amq_mount_tree_list, xdr_amq_mount_tree),
+	libamu/xdr_func.c (xdr_am_mountres3_ok): use casing magic to stop
+	GCC-4.1 from complaining about "dereferencing type-punned pointer
+	will break strict-aliasing rules" here (but not elsewhere).
 
-1999-09-21  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2006-03-20  Christos Zoulas  <christos@zoulas.com>
 
-	* aux/macros/linux_headers.m4: use AC_MSG_ERROR.
+	* libamu/wire.c: avoid potential dereferencing of a NULL pointer
+	(Coverity).
 
-	* aux/macros/opt_{cppflags,ldflags,libs,amu_cflags}.m4: the ARG is
-	not optional.  Make sure ARG is supplied else flag an error.
+	* hlfsd/homedir.c (delay): remove unnecessary check for NULL
+	pointer (Coverity).
 
-1999-09-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* fsinfo/fsi_analyze.c (analyze_dkmounts, analyze_mounts,
+	analyze_mounts): avoid potential dereferencing of a NULL pointer
+	(Coverity).
 
-	* minor port i386-unknown-freebsdelf3.3
+	* conf/transp/transp_sockets.c (create_amq_service): avoid
+	potential dereferencing of a NULL pointer (Coverity).
 
-	* released snapshot am-utils-6.0.2s1
+	* amd/sched.c (sigchld): properly check for the end of the waiting
+	process list (Coverity).
 
-1999-09-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/mapc.c (mapc_create): initialize 'modify' to zero (Coverity).
 
-	* aux/configure.in (AC_CHECK_FUNCS): check for getitimer().
+	* amd/autil.c (amfs_mkcacheref, am_unmounted): avoid potential
+	dereferencing of a NULL pointer (Coverity).
 
-	* include/am_defs.h: extern definition for getitimer().
+	* amd/amfs_generic.c (amfs_lookup_mntfs): free def_opts before
+	reusing it (memory leak bug detected by Coverity).
+	(amfs_bgmount): avoid potential dereferencing of a NULL pointer
+	(Coverity).
 
-	* aux/configure.in: use AC_CHECK_EXTERNS.  Look for getitimer()
-	extern.
+	* amd/am_ops.c (merge_opts): no need to check if newstr is NULL
+	(bug detected by Coverity).
 
-	* aux/macros/check_extern.m4: define a simple AC_CHECK_EXTERNS
-	that calls AC_CHECK_EXTERN in a loop.  This saves repeated code in
-	configure.
+2006-03-08  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* aux/macros/type_auth_create_gidlist.m4: AIX 4.x systems use
-	'int' as the 5th arg to authunix_create().
+	* amd/nfs_subr.c (mp_to_fh): fixed old-style filehandles--the pid
+	comparison was failing.
 
-	* aux/macros/type_recvfrom_fromlen.m4: all AIX 4.x systems use a
-	size_t for the 6th arg of recvfrom().
+2006-03-08  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/os_cflags.m4: define _XOPEN_EXTENDED_SOURCE for
-	aix4.x systems.
+	* configure.in: properly test for either <gdbm/ndbm.h> or
+	<gdbm-ndbm.h> (unfortunately, Autoconf will map both names to the
+	same $ac_cv_* variable name).  Some systems support one header or
+	another.  Patch inspired by work Debian did.
 
-	* libamu/mount_fs.c (print_nfs_args): cast some values to int, to
-	avoid gcc -Wall errors.
+2006-02-10  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* scripts/expn.in: use sockaddr_in(), not pack() to correctly fill
-	in a struct sockaddr_in.  On Solaris x86 hosts, using pack()
-	results in byte-misaligned values.   Bug fix from Jeffrey C Honig
-	<jch@BSDI.COM>.
+	*******************************************************************
+	*** Released am-utils-6.1.4					***
+	*******************************************************************
 
-	* libamu/mount_fs.c (compute_automounter_mount_flags): turn on
-	automntfs (ignore on bsdi-4.1) flag.
-	(compute_automounter_nfs_args): ditto.
+2006-01-04  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/acconfig.h: add new flag for automntfs (ignore)
+	* doc/am-utils.texi (auto_attrcache Parameter): revise discussion
+	to mention pros and cons of turning on/off this parameter,
+	including impact on Amd's performance, and ways to improve
+	performance while minimizing the window of vulnerability in which
+	kernel may return the wrong (cached) attributes.
 
-	* aux/configure.in: check for new automntfs flag (bsdi-4.1).
+2006-01-02  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-09-14  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* updated copyright year to 2006 on all files.
 
-	* MIRRORS: added new site in Germany.  Updated status of umn.edu
-	and ferginc.com, who may no longer be mirroring am-utils.
+2005-12-20  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-09-08  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* include/am_utils.h, conf/transp/transp_tli.c (amu_svc_register,
+	register_autofs_service): use a consistent prototype for the
+	dispatch function of the autofs service de/registration functions.
 
-	*******************************************************************
-	*** Released am-utils-6.0.1					***
-	*******************************************************************
+2005-12-03  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-09-08  Erez Zadok  <ezk@cs.columbia.edu>
+	* minor new ports: i386-unknown-netbsdelf2.1,
+	i386-unknown-netbsdelf3.0 (RELEASE), and i386-unknown-openbsd3.8.
 
-	* aux/macros/mount_headers.m4: bsdi-2.1 needs MAXQUOTAS and struct
-	netexport defined.
+2005-12-02  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/try_compile_anyfs.m4: bsdi-2.1 needs MAXQUOTAS and
-	struct netexport defined.
+	* m4/macros/check_field.m4: remove double inclusion of msdosfs
+	headers, which are included in mount_header1.h (netbsd 2.1 doesn't
+	protect <msdosfs/msdosfsmount.h> which causes compile errors).
 
-1999-09-07  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-11-08  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/check_field.m4 (ac_upcase_var_name): include
-	<ifaddrs.h> so we can detect fields within struct ifaddrs.
+	* minor new port: i386-unknown-freebsd6.0 (RELEASE)
 
-	* libamu/wire.c (getwire): bsdi-2.1 uses a second arg to
-	getifaddrs() and struct ifaddrs has no ifa_next field.
+2005-10-26  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/configure.in: check if 'struct ifaddrs' has a field
-	ifa_next.
+	* amd/amq_subr.c (amqproc_pawd_1_svc): repeatedly resolve path in
+	Amd, not in pawd (to avoid repeated network RPCs).
 
-	* include/amq_defs.h (AMQ_STRLEN): double size of amq string
-	length to 2048 bytes.
+	* amq/pawd.c (transform_dir): move repeated path resolution into Amd.
 
-	* conf/nfs_prot/nfs_prot_netbsd1_4.h: include several more nfs
-	header files and ufs/ufs/ufsmount.h.  Bug reported by <Christos
-	Zoulas> christos@zoulas.com.
+2005-10-25  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/try_compile_anyfs.m4: include <ufs/ufs/ufsmount.h>.
-	Bug reported by <Christos Zoulas> christos@zoulas.com.
+	* amq/pawd.c (transform_dir): resolve path repeatedly until
+	finished.  Bug fix from Jonathan Chen <jon+amd-at-spock.org>.
+	Added safety check to prevent infinite loops.
 
-	* aux/macros/mount_headers.m4: include <ufs/ufs/ufsmount.h>
+2005-10-19  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-09-06  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* doc/am-utils.texi (opts Option): document new pcfs options
+	longname, nowin95, shortname, user=N, group=N, mask=N, and
+	dirmask=N.
 
-	* libamu/xutil.c (expand_error): use strerror if available instead
-	of sys_errlist.  Bug reported by <Christos Zoulas>
-	christos@zoulas.com.
+	* amd/ops_pcfs.c (mount_pcfs): process new pcfs options longname,
+	nowin95, shortname, user=N, group=N, mask=N, and dirmask=N.
 
-	* hlfsd/hlfsd.c (fatal): use strerror if available instead of
-	sys_errlist.
+	* include/am_compat.h: provide compatibility mnttab string names,
+	if needed, for pcfs mount options longname, nowin95, shortname,
+	user=N, group=N, mask=N, and dirmask=N.
 
-	* amq/amq.c (show_mi): use strerror if available instead of
-	sys_errlist.
+	* include/am_utils.h: extern for hasmntstr().
 
-	* aux/macros/check_nfs_prot_headers.m4: make sure netbsd1.4
-	nfs_prot header is used for any future (1.5 etc.) netbsd systems.
+	* libamu/mtab.c (hasmntstr): new function to return the string
+	value following a mount option, up to the next comma-delimited
+	options.
 
-	* amq/pawd.c (find_mt): check for type nfsl as well.  Fix from
-	"Andrew J. Korty" <ajk@purdue.edu>
+	* configure.in: check for mnttab and pcfs options longname,
+	nowin95, and shortname.
 
-1999-08-29  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* Makefile.am (EXTRA_DIST_M4): distribute new macro
+	check_mnt2_pcfs_opt.m4.
 
-	* doc/am-utils.texi (Supported Platforms): updates for redhat
-	systems.
+	* m4/macros/check_mnt2_pcfs_opt.m4: new macro to check for pcfs
+	mnttab and mount options.
 
-	* INSTALL: updates for redhat systems.
+2005-10-18  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* libamu/wire.c (getwire_lookup): spell "succeeded" correctly
+	* libamu/mount_fs.c (print_nfs_args): print nfs_args->addr
+	correctly, depending if it's a pointer or not.
 
-1999-08-28  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/sa_dref/sa_dref_*.h: for each NFS_SA_DREF macro, also
+	#define NFS_ARGS_T_ADDR_IS_POINTER if nfs_args->addr is a pointer
+	or an embedded structure, so we can tell how to print it.
 
-	* scripts/ctl-amd.in: sleep 1 second between killing amd and
-	restarting it, because amq may respond that amd is down, where in
-	fact it is still trying to unmount itself after unmapping itself
-	from the portmapper.
+	* libamu/mount_fs.c (print_nfs_args): print nfs_args->addrlen
+	field, if it exists.
 
-	* aux/config.guess.long: new script to print long version of
-	config.guess output.
+	* configure.in: check for nfs_args->addrlen field.
 
-	* buildall (host_alias): use long version of config.guess.
+	* wire-test/wire-test.c (main), libamu/mount_fs.c
+	(print_nfs_args), fixmount/fixmount.c (inetresport,
+	clnt_create_timeout), amq/pawd.c (transform_dir), amq/amq.c
+	(main), amd/srvr_nfs.c (find_nfs_srvr), amd/autil.c
+	(amfs_mount): document that as per POSIX, we don't need to set the
+	sa_len/sin_len fields in struct sockaddr/sockaddr_in.  The field
+	is used only internally in the kernel.  See
+	www.awprofessional.com/articles/article.asp?p=169505&seqNum=2&rl=1
 
-1999-08-27  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* fixmount/fixmount.c (inetresport): initialize sockaddr_in
+	structure before filling in some fields.
 
-	* scripts/ctl-{amd,hlfsd}.in: update RH tags for start/stop
-	scripts.
+2005-10-11  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-08-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* doc/am-utils.texi (nfs_vers, nfs_proto parameters): clarify and
+	correct mistaken description of nfs_proto.
 
-	* released snapshot am-utils-6.0.1s11
+2005-10-10  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* libamu/xutil.c (expand_error): make sure expanding the string
-	with textual version of errno doesn't overrun the 1024 bytes
-	buffer.
-	(real_plog): null terminate msg, just in case.
+	*******************************************************************
+	*** Released am-utils-6.1.3					***
+	*******************************************************************
 
-	* amq/amq.c (main): don't getopt -M option and don't process it
-	unless ENABLE_AMQ_MOUNT is on.
+2005-10-07  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/amq_svc.c (amq_program_1): all code that relates to amq -M
-	is conditional on #ifdef ENABLE_AMQ_MOUNT.
+	* m4/macros/check_mnttab_type.m4: move the test for MOUNT_* to the
+	very end, after the test using getvfsbyname().
 
-	* amd/amq_subr.c: remove amqproc_mount_1_svc() function invoked
-	when amq -M code is disabled.  Not taking any chances.
+	* m4/macros/expand_run_string.m4: if the string value returned is
+	empty, consider it invalid.
 
-1999-08-23  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/check_varargs_macros.m4: rewrite macro so it'll
+	try and compile the varargs test, not just cpp it.  Some systems
+	pass the old cpp test, but not when you actually try to compile
+	the code (Tru64's cc).
 
-	* released snapshot am-utils-6.0.1s10
+	* conf/autofs/autofs_solaris_v1.h: redefine
+	autofs_strdup_space_hack as a macro to str3cat(NULL,(s)," ","").
+	This works everywhere and we avoid linking problems, inline
+	functions, etc.
 
-Sun Aug 22 16:18:59 1999  Erez Zadok  <ezk@subzero.cs.columbia.edu>
+	* conf/autofs/autofs_solaris_v1.c (autofs_mount_fs): remove
+	autofs_strdup_space_hack() function altogether.
 
-	* libamu/wire.c (getwire_lookup): if getnetbyaddr failed (e.g., on
-	128.59.16.0), try to shift the network out of zeros (e.g.,
-	128.59.16) and try again.  Irix 6.4 requires short network
-	numbers.
+	* m4/macros/os_cflags.m4: remove hack that hardcodes pte_t=u_int.
 
-1999-08-22  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: test for <sys/immu.h> header.
+	Test for pte_t, but only on IRIX6 systems.
 
-	* libamu/wire.c (getwire_lookup): correctly compute subnet using
-	netmask.
+	* Makefile.am (EXTRA_DIST_M4): distribute new type_pte_t.m4 file.
 
-	* libamu/mount_fs.c (compute_automounter_nfs_args): require that
-	Amd's own NFS mounts use reserved ports (if possible).  IP packet
-	security fix from Jeffrey C Honig <jch@BSDI.COM>.
+	* m4/macros/type_pte_t.m4: new test for existence of pte_t
+	typedef, needed on some IRIX-6.5/gcc systems.
 
-	* conf/transp/transp_tli.c (create_autofs_service): use correct
-	autofs_port.  IP packet security fix from Jeffrey C Honig
-	<jch@BSDI.COM>.
+	* m4/macros/header_templates.m4: add missing templates for
+	HAVE_EXTERN_GETDTABLESIZE, HAVE_EXTERN_GETWD, and
+	HAVE_EXTERN_UALARM.
 
-	* conf/transp/transp_sockets.c (bindnfs_port): remove unnecessary
-	function.  IP packet security fix from Jeffrey C Honig
-	<jch@BSDI.COM>.
-	(create_nfs_service): use bind_resv_port() directly.  ensure that
-	privileged ports are used.  IP packet security fix from Jeffrey C
-	Honig <jch@BSDI.COM>.
+	* amd/info_exec.c (exec_map_open): break assignment from inside
+	conditional, to work around an IRIX-6.5 cc bug.
 
-	* amd/nfs_prot_svc.c (nfs_program_2): verify that requests come
-	from reserved ports and from a local IP address.  IP packet
-	security fix from Jeffrey C Honig <jch@BSDI.COM>.
+	* fsinfo/fsi_util.c (set_ether_if), amd/map.c (unmount_mp),
+	libamu/xutil.c (expand_error), libamu/strutil.c (xsnprintf): avoid
+	comparison between signed and unsigned integers.
 
-	* amd/amq_subr.c (ok_security): use IPPORT_RESERVED, instead of
-	hard-coded 1024.  IP packet security fix from Jeffrey C Honig
-	<jch@BSDI.COM>.
-	(amqproc_mount_1_svc): provide information on the caller making an
-	amq -M request.  IP packet security fix from Jeffrey C Honig
-	<jch@BSDI.COM>.
+	* conf/autofs/autofs_solaris_v1.h, conf/autofs/autofs_solaris_v1.c
+	(autofs_strdup_space_hack): move "space_hack" function from static
+	inline in header, into the only source file that needs it.  This
+	is cleaner and also prevents linking problem with some compilers
+	that won't apply CPP macros inside static inline functions (for
+	the strl* functions).
 
-	* amd/map.c (free_map_if_success): If the program doing an unmount
-	of a program filesystem fails, amd tries to interpret the return
-	code as an errno.  Fix from Jeffrey C Honig <jch@BSDI.COM>.
+	* amq/pawd.c (find_mt, find_mlp): remove obsolete, inefficient
+	code.
+	(transform_dir): call the new, efficient amqproc_pawd_1() routine.
 
-	* amd/info_nis.c (determine_nis_domain): don't always print
-	warning about NIS domain name not being set, even if NIS is not in
-	use.
+	* amq/amq_clnt.c (amqproc_pawd_1): AMQPROC_PAWD wrapper routine.
 
-1999-08-21  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amq/amq.h (amqproc_pawd_1): extern for amq's AMQPROC_PAWD
+	wrapper routine.
 
-	* amd/info_ldap.c (get_ldap_timestamp): initialize variable err.
-	(amu_ldap_search): initialize variable err.
+	* amd/amq_svc.c (amq_program_1): dispatch point for
+	amqproc_pawd_1_svc.
 
-1999-08-16  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amq_subr.c (amqproc_pawd_1_svc): moved pawd's path-matching
+	functionality into Amd, where it can be done a lot more
+	efficiently.  We don't have to construct and ship a whole export
+	tree from Amd to pawd.  We just get a variable-length
+	xdr_wrapstring for the user's path, iterate over the entire export
+	list inside Amd, and return only a matched string if found
+	(otherwise we return "" to indicate that there was no match, and
+	let pawd printf the same string it sent over).
 
-	* libamu/wire.c: written using getifaddrs() for BSD systems,
-	contributed by BSDI, Jeffrey C Honig <jch@BSDI.COM>).
+	* amd/amd.h: extern for amqproc_pawd_1_svc, amd's service routine
+	the AMQPROC_PAWD RPC.
 
-1999-08-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-10-06  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* include/am_utils.h (SALLOC): a simple macro to allocate N bytes.
+	* ltmain.sh, m4/macros/libtool.m4: update to libtool-1.5.20.
+	Fixes Tru64 bugs when using ksh.
 
-	* aux/configure.in: check for irs.h and ifaddrs.h.
-	Increase libamu.so --version-info to 3:1:1 since we've changed the
-	source code for the library.
-	Check for getifaddrs() function.
+	* amd/amfs_toplvl.c (amfs_toplvl_mount): break complex ifdef macro
+	into two sections, to workaround a C99 varargs-macro bug in
+	gcc-3.2.2 (RH9).
 
-1999-08-14  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/wire.c (print_wires): convert argument-less xsnprintf to
+	xstrlcpy.
 
-	* libamu/mount_fs.c (print_nfs_args): print fields namlen and
-	bsize if they exist.
+	* include/am_utils.h: use new HAVE_C99_VARARGS_MACROS or
+	HAVE_GCC_VARARGS_MACROS to pass file name and line number to
+	xsnprintf/xvsnprintf.
 
-	* conf/mount/mount_linux.c (mount_linux): set nfs_args_t->namlen
-	and ->bsize fields correctly, if those fields exist.  This is a
-	bug in that amd neglected to set these fields, but told the
-	kernel it is mounting the nfs_args_t structure using mount version
-	3 (which requires both bsize and namlen fields).
+	* libamu/strutil.c (xsnprintf, xvsnprintf): if debugging is on,
+	then also print the source file name and line number that called
+	xsnprintf/xvsnprintf with a buffer that wasn't large enough (most
+	likely an am-utils bug).
 
-	* aux/configure.in: test for two new nfs_args_t fields (used on
-	newer linux with mount versions 2 and 3): bsize and namlen.
+	* Makefile.am (EXTRA_DIST_M4): distribute new
+	check_varargs_macros.m4 file.
 
-	* doc/am-utils.texi (netgrpd Selector Function): document new
-	selector function.
+	* configure.in: execute new AMU_VARARGS_MACROS test.
 
-	* amd/opts.c (f_netgrpd): new amd map function netgrpd(ARG) to
-	test if the current host (fully-qualified name) is in the ARG host
-	netgroup.  The netgrp() function uses the short form of a host
-	name.  Patch from Christophe Kalt <Christophe-Kalt@deshaw.com>.
+	* m4/macros/check_varargs_macros.m4: new test to check what style
+	of variable-length argument macros, if any, does the
+	compiler/pre-processor supports.
 
-	* doc/am-utils.texi (automount2amd): document new script.
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_lookup_2_req)
+	conf/autofs/autofs_solaris_v1.c (autofs_mount_1_req), amd/opts.c,
+	amd/nfs_subr.c (nfsproc_lookup_2_svc), amd/nfs_start.c
+	(mount_automounter), amd/get_args.c (get_args), amd/amfs_toplvl.c,
+	amd/amfs_auto.c (amfs_auto_mount), amd/amd.h, amd/amd.c (main):
+	use sizeof() instead of fixed SIZEOF_* macros.
 
-	* scripts/Makefile.am: create, install, and distribute
-	automount2amd perl script and its man page.
+	* libamu/strutil.c (xstrlcat, xstrlcpy), include/am_utils.h
+	(DEBUG): if debugging is on, then also print the source file name
+	and line number that called xstrl* with a buffer that wasn't large
+	enough (most likely an am-utils bug)
 
-	* scripts/automount2amd.8: new man page for automount2amd.
+	* include/am_compat.h (INADDR_NONE): define in a common location,
+	if OS doesn't have it, use 0xffffffffU which should work with any
+	ANSI compiler.
 
-	* scripts/automount2amd.in: new file, contributed a in 1993 by
-	Mike Walker <mike@tab00.larc.nasa.gov>.  Fixed to use addopts for
-	any automount map options specified.
+	* fixmount/fixmount.c, libamu/wire.c: remove local definition of
+	INADDR_NONE.
 
-1999-08-09  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_toplvl.c (amfs_toplvl_mount), amd/amfs_auto.c
+	(amfs_auto_mount): use common SIZEOF_OPTS in definition and call
+	to autofs_get_opts.
 
-	* released snapshot am-utils-6.0.1s9
+	* amd/amd.h (SIZEOF_OPTS): moved #define to common header.
 
-1999-08-09  Erez Zadok  <ezk@beetle.mcl.cs.columbia.edu>
+2005-10-06  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* amd/amfs_auto.c (DOT_DOT_COOKIE): set the NFS cookie of '..' to
-	1.
-	(amfs_auto_readdir): use DOT_DOT_COOKIE instead of (u_int)~0.
-	(amfs_auto_readdir_browsable): use DOT_DOT_COOKIE instead of
-	(u_int)~0.
+	* amd/opts.c (expand_op): Need to check BUFSPACE for env for
+	vlen+1.  Likewise for cp and strlen(cp)+1.
 
-	* amd/mapc.c (make_entry_chain): NFS cookies should be
-	monotonically increasing, because Linux 2.3 expects that, even
-	though it is not in the spec (RFC-1094) for NFS V2.
+	* amd/amfs_toplvl.c (amfs_toplvl_mount) [HAVE_FS_AUTOFS]: Pass new
+	size argument to autofs_get_opts.
 
-1999-08-06  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-10-05  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/check_lib_funcs.m4: removed unused macro.
+	* amq/pawd.c (transform_dir): was using UDP only.  Now will also
+	try TCP if UDP failed.  Destroy client after use to avoid leftover
+	TCP sockets in the kernel.
 
-	* aux/macros/linux_headers.m4: new macro to ensure that linux
-	kernel headers match running kernel version.
+	* libamu/hasmntopt.c (amu_hasmntopt): increase size of MNTMAXSTR
+	from 128 to to 256, because some users have really long option
+	strings.  Suggestion from jon+amd-at-spock.org.
 
-	* aux/acconfig.h: define HOST_HEADER_VERSION so we can check if
-	amd is configured on linux hosts that run one kernel but have
-	headers for a different version.
+	* amd/opts.c (expand_op): should check BUFSPACE for vlen+1, not
+	just vlen.  Bug discovered when started using xstrlcpy().
 
-	* amd/info_nis.c (nis_isup, nis_search, nis_init): fixes for the
-	logic which uses nis_isup and has_yp_order.  Make sure it is used
-	correctly , esp. for NIS+ in NIS-compatibility mode.  Bug fix from
-	Peter Breitenlohner <peb@mppmu.mpg.de>.
+	* ALL: convert from using strcat to the safer xstrlcat, and from
+	strcpy to safer xstrlcpy.
 
-	* include/am_defs.h: fix conflicts on linux 2.2 systems with older
-	libc5.  Bug fix from Peter Breitenlohner <peb@mppmu.mpg.de>.
+2005-10-04  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* scripts/lostaltmail.in: use sockaddr_in(), not pack() to
-	correctly fill in a struct sockaddr_in.  On Solaris x86 hosts,
-	using pack() results in byte-misaligned values.
+	* hlfsd/hlfsd.h: remove old fatalerror() and ERRM macros.
 
-1999-08-02  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* hlfsd/hlfsd.c (fatalerror): new function instead of macro.
+	Easier to use xstrlcat in this new function.
 
-	* conf/mtab/mtab_aix.c (mnt_dup): add support for nfs3
-	mounting, as per Dale Talcott <aeh@quest.cc.purdue.edu>.  Also use
-	better macros for case statement.
+	* amd/amd.h, include/am_utils.h, amd/amd.c: moved 'hostd' extern
+	from am_utils.h to amd.h, and define its size as a macro that
+	could be passed to xstrl*().
 
-	* conf/nfs_prot/nfs_prot_sunos5_7.h: don't include ldap structures
-	unless ldap is actually available.
+	* ALL: convert from using sprintf to the safer xsnprintf.
 
-	* use updated config.guess and config.sub.  Use newer automake
-	that fixes problems with distributing optional libamu files
-	(clnt_sperrno.c, hasmntopt.c, strcasecmp.c, strdup.c, strstr.c,
-	and ualarm.c)
+	* mk-amd-map/Makefile.am (LDADD): link with libamu to get
+	xsnprintf().
 
-1999-07-19  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amd.h, amd/amd.c, include/am_utils.h: moved pid_fsname
+	extern from am_utils.h to amd.h, and define its size as a macro
+	that could be passed to xsnprintf().
 
-	* minor port i386-unknown-openbsd2.5
+2005-10-02  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-07-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* include/am_utils.h: extern for xvsnprintf().
 
-	* minor ports to freebsdelf 3.[0-2] and 4.0 completed
+	* amd/autil.c: move strsplit() to libamu/strutil.c.
 
-	* aux/macros/check_nfs_prot_headers.m4: support freebsdelf
+	* libamu/Makefile.am: use strutil.c, not util.c.
 
-	* aux/macros/check_nfs_socket_connection.m4: support freebsdelf
+	* libamu/strutil.c: rename from util.c to explain better purpose
+	of file.  Move xvsnprintf and xsnprintf from xutil.c to this
+	file.  Sync up with 6.2 version of file.
 
-1999-06-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/xutil.c: explain purpose of file.  Move mkdirs/rmdirs
+	code from old util.c.
 
-	* released snapshot am-utils-6.0.1s8
+2005-10-01  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-06-23  Erez Zadok  <ezk@beetle.mcl.cs.columbia.edu>
+	* m4/macros/header_templates.m4: templates for FFS.
 
-	* include/am_defs.h: avoid various header conflicts on
-	RedHat/Linux 6.0 and kernels 2.2.10 or newer.
+	* m4/macros/check_mnttab_type.m4: on BSD44 systems, check for file
+	system mount table name via the MOUNT_* mount(2) macros (because
+	BSD44 keeps the mount table in the kernel).
 
-	* aux/configure.in: look for <db1/ndbm.h> (RedHat/Linux 6.0 and
-	kernel 2.2.10)
+	* configure.in: synchronise order of searching for mnttab entries
+	and mount names.  The new order is "ext3 ext2 ffs ufs 4.2 4.3 4.4
+	efs xfs jfs ultrix" (which would prefer ffs on BSD44 instead of
+	ufs, and ext3 instead of ext2 on Linux).
 
-	* amd/amfs_program.c (amfs_program_exec): make sure logfp is
-	initialized dynamically to stderr if needed.
+	* include/am_defs.h: include <sys/statvfs.h> if it exists.
 
-	* libamu/xutil.c (dplog): make sure logfp is initialized
-	dynamically to stderr if needed.
-	(plog): ditto.
+	* conf/nfs_prot/nfs_prot_netbsd1_4.h: NetBSD 3 has both statfs()
+	and statvfs(), but the latter is preferred, so #define to use
+	statvfs.
 
-	* amd/amfs_program.c (amfs_program_exec): set logfp to stderr if
-	not initialized.
+	* configure.in: check for statfs(), statvfs(), and
+	<sys/statvfs.h>.
 
-	* libamu/xutil.c: don't initialize logfp statically to stderr,
-	because on RedHat/Linux 6.0 (kernel 2.2.10) stderr can no longer
-	be manipulated like a variable.
+	* config.guess.long: strip trailing '.' on "netbsdelf3.0."
+	(Beta).  Workaround for bug in config.guess.
 
-	* include/am_defs.h: avoid more conflicts between <linux/fs.h> and
-	<sys/mount.h> on 2.2 linux kernels.
-	include <db1/ndbm.h> as needed (RedHat/Linux 6.0)
+	* config.{guess,sub}: update to latest versions.
 
-1999-04-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-09-30  Christos Zoulas  <christos@zoulas.com>
 
-	* all Makefile.am: use AMU_NFS_PROT_HEADER (not *_HEADERS)
+	* fsinfo/fsi_util.c (set_ether_if): use INADDR_NONE instead of
+	hard-coded value of -1.
 
-	* aux/macros/check_nfs_prot_headers.m4 (AMU_NFS_PROT_HEADER):
-	renamed AC_SUBST name from *_HEADERS to *_HEADER so that automake
-	won't attempt to add it to the header files to distribute.
+	* include/amq_defs.h (AMQ_STRLEN): increase default size from 2KB
+	to 16KB.  We can afford it these days.
 
-1999-04-19  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/strcasecmp.c (strcasecmp): use unsigned chars in
+	tolower() to avoid sign/size promotion bugs.
 
-	* aux/GNUmakefile: invoke aclocal with new --altdir flag.
+	* libamu/xutil.c (switch_to_logfile): don't output to LOG_CONS by
+	default (it's unfriendly).  If user really wants to, they can set
+	it in /etc/syslog.conf.
 
-1999-04-16  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-09-29  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* minor new port: i386-unknown-netbsd1.4 (ALPHA)
+	* amq/pawd.c (find_mt): if the auto mount type is used, pawd could
+	go into an infinite loop since the mt_directory and mt_mountpoint
+	fields are the same for auto mounts.  Solution: ignore type auto
+	mounts, similar to toplvl.  Bug fix from Jonathan Chen
+	<jon+amd@spock.org>.
 
-	* aux/macros/check_field.m4: no need to include <cdfs/cdfsmount.h>
-	and <isofs/cd9660/cd9660_mount.h> because they are also included
-	from MOUNT_HEADERS.  Causes multiple inclusion of unprotected
-	headers on netbsd-1.4_ALPHA.
+	* README.attrcache: document test-attrcache script.
 
-1999-04-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* scripts/Makefile.am (noinst_SCRIPTS): build test-attrcache
+	script.
 
-	* aux/macros/extern_sys_errlist.m4 (pattern): netbsd-1.4_ALPHA's
-	sys_errlist extern doesn't end with [].
+	* configure.in: build scripts/test-attrcache script and chmod it
+	so it can be executed in place.
 
-	* aux/macros/check_nfs_prot_headers.m4: netbsd 1.4 support.
+	* scripts/test-attrcache.in: script to test the NFS attribute
+	cache using Amd.
 
-1999-04-11  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-09-26  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* newer automake wants texinfo.tex to be in aux/ not doc/
+	* libamu/xutil.c (unregister_amq): repair broken meaning of D_AMQ,
+	which was reversed in am-utils-6.2.  Bug fix from Steve Plite
+	<splite-amutils at sigint.cs.purdue.edu>.
 
-1999-03-30  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* hlfsd/stubs.c (nfsproc_getattr_2_svc, nfsproc_lookup_2_svc,
+	nfsproc_readlink_2_svc, nfsproc_readdir_2_svc), hlfsd/hlfsd.c
+	(hlfsd_init): use new clocktime() function.
 
-	* amd/conf_parse.y: alloca support.
+2005-09-18  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* fsinfo/fsi_gram.y: alloca support.
+	*******************************************************************
+	*** Released am-utils-6.1.2.1					***
+	*******************************************************************
 
-	* libamu/Makefile.am (libamu_la_LIBADD): compile alloca.o if
-	needed.
+	* README.attrcache: Update status of freebsd and openbsd.
+	Document netbsd's patchs to support noac.
 
-	* aux/configure.in: test for alloca support.  Needed because bison
-	generates parsers that use alloca, and hpux9 does have alloca and
-	its /bin/cc doesn't support it builtin (the way gcc does).
+	* libamu/mount_fs.c (compute_nfs_attrcache_flags): cleanup the
+	code that sets the ac{reg,dir}{min,max} fields so it also sets the
+	appropriate nfs_args->flags such as MNT2_NFS_OPT_ACREGMIN.
 
-	* libamu/alloca.c: new file, needed on hpux9 with /bin/cc.  Taken
-	verbatim from bison-1.25.
+	* configure.in: check for nfs_args fields acregmax and acdirmax.
 
-	* include/am_defs.h: fixed typo #errir -> #error
+	*******************************************************************
+	*** Released am-utils-6.1.2					***
+	*******************************************************************
 
-	* released snapshot am-utils-6.0.1s7
+	* README.attrcache: new file documenting in detail OS bugs
+	relating to attribute caching, which can affect Amd's reliability
+	under heavy load.
+
+	* doc/Makefile.am: install README.attrcache file as attrache.txt
+	file on am-utils Web site.
+
+	* Makefile.am (EXTRA_DIST): include README.attrcache in distro.
+
+	* BUGS, NEWS, doc/am-utils.texi (auto_attrcache Parameter),
+	scripts/amd.conf.5, scripts/amd.conf-sample: document attribute
+	cache bugs on some OSs.
+
+2005-09-17  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* libamu/xutil.c (clocktime): newly implemented routine.  Uses
+	gettimeofday() each time to return a high-resolution clock time,
+	and does not "cache" the last time.  Returns time in seconds, just
+	like the old implementation.  If passed a non-null argument, will
+	fill it in with the current time in seconds+microseconds.
 
-	* README.y2k: more information about am-utils' compatibility, from
-	Paul Balyoz <pbalyoz@sedona.ch.intel.com>.
+	* libamu/xutil.c: remove actual declaration of clock_valid, and
+	another never-used declaration for xclock_valid.
 
-	* scripts/lostaltmail.in (Splice_in_resent_headers): ensure Y2K
-	compliant format.  Patch from Paul Balyoz
-	<pbalyoz@sedona.ch.intel.com>
+	* include/am_utils.h: remove defunct definition of clocktime()
+	macro and clock_valid variable.  Add extern for new definition.
 
-	* doc/am-utils.texi (Supported Platforms): hpux10.20 could have
-	nfs v.3 support (with some vendor patches), but it is turned off.
+	* libamu/mount_fs.c (mount_fs), hlfsd/homedir.c (homedir,
+	hlfsd_diskspace, hlfsd_getpwent, plt_reset, table_add),
+	hlfsd/hlfsd.c (main, hlfsd_init, reload, cleanup),
+	conf/mtab/mtab_mach3.c (open_locked_mtab), conf/mtab/mtab_file.c
+	(open_locked_mtab), amd/nfs_start.c (do_select, run_rpc),
+	amd/autil.c (host_normalize): remove defunct clock_valid.
 
-	* aux/macros/os_cflags.m4: use ansi compiler options on hpux.
+	* amd/nfs_subr.c (nfsproc_getattr_2_svc): Print microseconds for
+	node's mtime.
+	(fh_to_mp3): use new clocktime() to update mtime and get a better
+	time resolution.
 
-	* conf/nfs_prot/nfs_prot_hpux.h: Turn off NFS V.3 support to avoid
-	confusing am-utils.  10.20 with some patches has incomplete
-	support.  Patch from Jon Peatfield
-	<J.S.Peatfield@damtp.cam.ac.uk>.
+	* amd/mapc.c (mapc_reload_map): change prototype from returning
+	void to returning an int.  If reloading was needed and succeeded,
+	return 1; else return 0.
+	(mapc_sync): update mtime of parent node if needed.  This is a
+	CRITICAL FIX, to ensure that the kernel flushes its DNLC/dcache
+	when we run "amq -f" manually or when a map is reloaded.
 
-1999-03-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/map.c (new_ttl): update am_ttl and na_atime in one shot.
+	(init_map): use new clocktime().
+	(unmount_mp): if the OS doesn't support a "symttl" option, then
+	update the mtime of the parent node using the clocktime(); but if
+	the time hasn't gotten changed because of rapid Amd accesses on
+	systems that don't have a micro-second NFS-client resolution, then
+	increment mtime by one arbitrarily (this could, on some systems
+	and under pathological cases, result in mtime's that are in the
+	future).
 
-	* minor port i386-pc-bsdi4.0.1
+	* amd/autil.c (forcibly_timeout_mp): MAJOR BUG FIX: force mtime
+	update of parent dir, to prevent DNLC/dcache from caching the old
+	entry, which could result in ESTALE errors, bad symlinks, and
+	more.
+	(am_mounted): record mount time, and update am_stats at the same
+	time, using the double-action redone clocktime() routine.
+	(am_mounted): update parent's mtime from that of the child.
+	(am_unmounted): when unmounting an entry, update mtime of parent
+	node.
 
-1999-03-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_generic.c (amfs_bgmount): now that clocktime() doesn't
+	remember it's last non-zero value, save it in a temporary variable
+	to avoid a TOCTOU problem (between an "if" and a "dlog").
 
-	* doc/am-utils.texi (Supported Platforms): add forgotten listing
-	for powerpc-linux.
+	* libamu/xutil.c (show_time_host_and_name),
+	conf/autofs/autofs_linux.c (autofs_mounted, autofs_timeout_mp),
+	amd/srvr_nfs.c (nfs_keepalive_callback, nfs_keepalive_timeout)
+	(find_nfs_srvr), amd/rpc_fwd.c (fwd_alloc), amd/nfs_subr.c
+	(nfsproc_getattr_2_svc), amd/nfs_start.c (do_select, run_rpc),
+	amd/mapc.c (root_init), amd/map.c(map_flush_srvr, timeout_mp),
+	amd/info_ndbm.c (ndbm_init), amd/info_ldap.c (amu_ldap_rebind),
+	amd/info_file.c (file_open), amd/info_exec.c (fgets_timed,
+	exec_search), amd/clock.c (timeout, softclock), amd/autil.c
+	(forcibly_timeout_mp), amd/amfs_generic.c (amfs_retry,
+	amfs_bgmount, amfs_generic_mount_child), amd/amd.c (main): pass
+	NULL to clocktime().
 
-1999-03-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-09-07  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* scripts/amd.conf.5: fix typo.  From Jeffrey C Honig
-	<jch@BSDI.COM>.
+	* minor new port: powerpc-apple-darwin8.2.0.
 
-	* doc/am-utils.texi: document iso9660 options norrip, gens, and
-	extatt.
-	(opts Option): documented dumbtimr and noauto options.  From
-	Jeffrey C Honig <jch@BSDI.COM>.
+	* m4/macros/type_auth_create_gidlist.m4: Old macosx used "gid_t"
+	but all newer ones (10.4+) use int.
 
-	* include/am_compat.h: define default strings for options norrip,
-	gens, and extatt.
+	* m4/macros/type_recvfrom_fromlen.m4: Old macosx used "int" for
+	6th arg of recvfrom(), but all newer ones (10.4+) use socklen_t.
 
-	* amd/ops_cdfs.c (mount_cdfs): support options norrip, gens, and
-	extatt.
+	* minor new port: i386-pc-linux-deb3.1.
 
-	* aux/macros/mount_headers.m4: also include
-	<isofs/cd9660/cd9660_mount.h> as needed.
+2005-09-02  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/configure.in: check for isofs mount options for bsdi4:
-	norrip, gens, and extatt.  Reported by Jeffrey C Honig
-	<jch@BSDI.COM>.
+	* conf/mount/mount_linux.c: If autoconf didn't find any disk-based
+	file system on this system (probably because /proc isn't mounted),
+	then provide some default definition for this file to compile.
 
-	* aux/macros/check_mnt2_cdfs_opt.m4: check for ISOFSMNT_* flags
-	(bsdi4).
+2005-08-27  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-03-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* Makefile.am (DISTCLEANFILES): also remove amu_autofs_prot.h,
+	config.cache.old, and dbgcf.h on "make distclean".
+	(CLEANFILES): remove dbgcf on plain "make clean".
 
-	* conf/nfs_prot/nfs_prot_freebsd3.h: ditto.
+	* amd/Makefile.am (DISTCLEANFILES): also remove ops_autofs.c on
+	"make distclean".
 
-	* conf/nfs_prot/nfs_prot_bsdi3.h: include <ufs/ufs/ufsmount.h>,
-	for bsdi4, as per Jeffrey C Honig <jch@BSDI.COM>.
+2005-08-24  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-03-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: wrap all LDAP and HESIOD tests in test whether
+	--with-OPT was used.
 
-	* get latest copies of config.guess, config.sub, ltconfig, and
-	ltmain.sh from libtool-1.2f.
+2005-08-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* all Makefile.am: don't use continuation lines (using \) for
-	short lists of files.
+	* configure.in: sinclude([vers.m4]) version number file.
 
-	* libamu/Makefile.am (DISTCLEANFILES): make distclean should
-	remove mountutil.c, mtabutil.c, transputil.c, and umount_fs.c.
-	Reported by Jeffrey C Honig <jch@BSDI.COM>.
+	* vers.m4: new file to separate version number out of
+	configure.in, useful for nightly snapshot script to generate
+	nightly version string.
 
-	* fixmount/Makefile.am (DISTCLEANFILES): make distclean should
-	remove checkmount.c.  Reported by Jeffrey C Honig <jch@BSDI.COM>.
+	* Makefile.am (EXTRA_DIST_M4): include vers.m4 in distro.
 
-	* Makefile.am (DISTCLEANFILES): make distclean should remove
-	amu_nfs_prot.h, config.cache.old, and dbgcf.h.  Reported by
-	Jeffrey C Honig <jch@BSDI.COM>.
+2005-08-11  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-03-13  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: keep AC_INIT on same line, for nightly snapshot
+	build script.
 
-	* released snapshot am-utils-6.0.1s6
+2005-08-06  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-03-12  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* scripts/amd.conf.5: selectors_in_defaults is a common parameter,
+	not just [global].  Use consistent capitalization of Amd/Amq.
 
-	* INSTALL: document freebsdelf.
+	* scripts/amd.conf-sample: properly list all of the parameters
+	which are common to both the [global] and the per-map sections.
 
-	* doc/am-utils.texi (Supported Platforms): document freebsdelf.
+	* doc/am-utils.texi (Common Parameters): selectors_in_defaults is
+	a common parameter, not just [global].
 
-1999-03-08  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* scripts/amd.conf-sample (sun_map_syntax): example of new flag.
 
-	* minor new ports: i386-unknown-freebsdelf3.1 and
-	i386-unknown-freebsdelf4.0
+	* cvs-server.txt: update instructions after branching 6.1-stable.
 
-	* aux/macros/check_nfs_prot_headers.m4: freebsd4 support.
+2005-08-02  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/check_nfs_socket_connection.m4: freebsd4 support.
+	*******************************************************************
+	*** Released am-utils-6.1.1					***
+	*******************************************************************
 
-	* aux/macros/check_nfs_fh_dref.m4: freebsd4 support.
+	* libamu/xutil.c (xsnprintf): "unsafe" alternative to vsnprintf is
+	vsprintf, not sprintf.
+
+	* conf/umount/umount_osf.c (umount_fs): refer to proper formal
+	parameter name.
+	(umount2_fs): pass second arg to umount().
+
+	* ALL: remove CVS ID and put actual file name in source.
 
-	* amd/opts.c (eval_opts): changed log level of "executing
-	negated..." message from USER to INFO, as per Guntram Wolski
-	<gwolsk@sei.com>.
+	* conf/autofs/*.[hc]: proper copyright headers.
 
-1999-02-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* whitespace reformatting.  Remove remaining '%W%' SCCS IDs.
 
-	* */Makefile.am (LDADD): force linking against an installed
-	libamu.{a,so}.
+	* amd/mntfs.c (free_mntfs): don't discard the last reference to an
+	mntfs that had been mounted already.  It won't have the
+	MFF_RESTARTED flag on, as it gets turned off after the entry is
+	mounted, but it will have the MFF_RSTKEEP flag on.
 
-	* doc/am-utils.texi (addopts Option): document remopts interaction
-	with addopts.
+	* amd/autil.c (mf_mounted), amd/restart.c (restart_fake_mntfs):
+	show the mntfs's flags.
 
-	* amd/am_ops.c (ops_match): if addopts are specified, apply them
-	to the value of remopts as well as opts.
+2005-08-01  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/ops_nfs.c (mount_nfs_fh): tell users when remopts are used.
+	* conf/mtab/mtab_linux.c: removed unused code.  Cleanup.
+	(handler): removed this bad signal handler.
+	(lock_mtab): Redhat's original code set a signal handler called
+	"handler()" for all non-ALRM signals.  The handler called
+	unlock_mntlist(), plog'ed the signal name, and then exit(1)!
+	Never, ever, exit() from inside a utility function.  This messed
+	up Amd's careful signal-handling code, and caused Amd to abort
+	uncleanly only any other "innocent" signal
+	(even simple SIGUSR1), leaving behind a hung Amd mnt point.  That
+	code should have at least restored the signal handlers' states
+	upon a successful mtab unlocking.  Anyway, that handler was
+	unnecessary, because will call unlock_mntlist() properly anyway on
+	exit.
 
-1999-02-05  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/mtab/mtab_{file,isc3,mach3,linux}.c (unlock_mntlist): dlog
+	message that we're inside the unlock_mntlist function.
 
-	* released snapshot am-utils-6.0.1s5
+	* amd/amd.c (main): use new setup_sighandler() for Amd's four main
+	signals (INT, TERM, HUP, and CHLD).
+	(main) Add SIGINT and SIGTERM to masked_sigs, used in
+	nfs_start.c:do_select() for setjmp/longjmp code; the MASK was set
+	to all four signals if !HAVE_SIGACTION, but only to HUP+CHLD if we
+	HAVE_SIGACTION.  So this change makes Amd behave consistently.
 
-	* conf/mount/mount_linux.c (mount_linux): set default nfs_args
-	options for ac{reg,dir}{min,man} as per the mount-2.8a package,
-	but only if noac option was not used.
+	* include/am_utils.h: extern for new setup_sighandler().
 
-1999-02-05  Erez Zadok  <ezk@retro.cs.columbia.edu>
+	* libamu/xutil.c (setup_sighandler): new utility function to setup
+	a single signal-handler regardless of what method is supported by
+	this OS.
+	(going_down): call unlock_mntlist() when exiting, to ensure that
+	Amd will remove any leftover mtab lock files, if any.
 
-	* conf/mount/mount_linux.c (mount_linux): print nfs_args again
-	since it was updated.
-	(mount_linux): use 4KB for NFS rsize/wsize on 2.1.0 linux kernels
-	and newer.  Bug was found by Neil Conway
-	<nconway.list@ukaea.org.uk>
+	* amd/restart.c (restart_automounter_nodes): cleanup function.
 
-1999-02-04  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* minor new port: i386-pc-linuxoldld-deb3.1.
+
+	* configure.in: include <sys/types.h> before <linux/socket.h> to
+	get the definition of size_t on Debian-3.1r0a.
 
-	* released snapshot am-utils-6.0.1s4
+2005-07-29  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* amd/srvr_nfs.c (find_nfs_srvr): don't blindly copy the hostent
+	IP address.  First check if it differs from the existing one of
+	the fserver, and copy only if it changed.  If it did change, flush
+	the fhandle cache to avoid a stale fhandle being reused.  This
+	allows Amd to detect IP address changes even for an fserver that
+	lost one or more NFS pings, but not enough to be declared totally
+	down.  We handle the "totally down" fserver case in
+	check_fs_addr_change().
+
+	* amd/ops_nfs.c (nfs_umount), amd/sched.c (sched_task),
+	amd/nfs_subr.c (nfs_quick_reply): code clarity.
+
+	* conf/mount/mount_linux.c (linux_nfs_error): dlog mappings of
+	errnos to NFS errors.
+
+	* conf/umount/umount_linux.c (umount2_fs): cleanup code.  Trying
+	stat() seems doomed to hang at times, so don't try stat at all,
+	because umount2() appears to be clever enough to never hang.
+
+2005-07-25  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-02-03  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amd.h (FSF_FORCE_UNMOUNT): new flag used to indicate that a
+	particular fserver may need forced/lazy unmounts when it's mntfs's
+	are unmounted.
 
-	* amq/amq.c (main): don't list -M as a valid amq option unless
-	configure'd with --enable-amq-mount.
+	* amd/ops_nfs.c (nfs_umount): a simple unmount returned EBUSY, and
+	the user specified forced_unmounts=yes in amd.conf, and this
+	fserver was flagged with FSF_FORCE_UNMOUNT, and the OS supports
+	forced/lazy unmounts, then try forced/lazy unmounts.  This should
+	allow a hung mount point to be removed.
 
-Wed Feb  3 18:11:18 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+	* amd/srvr_nfs.c (find_nfs_srvr): move away IP-address change
+	detection code to its own function.
+	(check_fs_addr_change): new function to detect if the IP address
+	of a downed host has changed, and do various cleanups and fixups
+	to try and recover as best from that situation (e.g., flushing
+	various caches).  Also set the FSF_FORCE_UNMOUNT flag for the
+	fserver in question.
+	(flush_srvr_nfs_cache): pass fserver as argument, so we can
+	selectively flush the NFS cache for a single fserver (or all of
+	them, if you pass NULL).
 
-	* amd/nfs_start.c (amd_use_autofs): Define.
-	(mount_automounter): Create autofs service listener only if
-	necessary to avoid unnecessary clashes with e.g. automountd.
+	* libamu/xutil.c (switch_to_logfile): truncate a regular-file log
+	file if user passed non-zero "truncate_log" flag.
 
-	* amd/amd.h (amd_use_autofs): Declare.
+	* include/am_utils.h: switch_to_logfile() now takes a 3rd arg.
 
-	* amd/conf.c (gopt_mount_type): Set amd_use_autofs.
-	(ropt_mount_type): Likewise.
+	* amd/get_args.c (get_args): pass "truncate_log" flag as per
+	amd.conf global settings.
+
+	* amd/conf.c (gopt_truncate_log): store global value of
+	truncate_log flag.
 
-1999-02-02  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amq_subr.c (amqproc_setopt_1_svc), hlfsd/hlfsd.c (main,
+	reload): don't truncate log file when calling switch_to_logfile().
 
-	* aux/macros/check_mnt2_nfs_opt.m4:: ditto
+	* amd/amd.h (CFM_TRUNCATE_LOG): new flag.  Fix comment typo.
+
+	* NEWS, doc/am-utils.texi (truncate_log Parameter),
+	scripts/amd.conf.5, scripts/amd.conf-sample (log_file): document
+	new truncate_log amd.conf parameter.
+
+	* amd/conf.c (gopt_forced_unmounts): check Linux kernel version
+	and alert if your version may be too old for MNT_FORCE to work
+	(before 2.4.0) or for MNT_DETACH to work (before 2.6.0).
+	Otherwise it may be impossible to pin down the exact kernel
+	version in which we should enable this feature.
 
-	* aux/macros/check_mnt2_cdfs_opt.m4: ditto
+	* conf/umount/umount_linux.c (umount2_fs): if MNT_FORCE returned
+	EBUSY, then don't try to stat(2) before MNT_DETACH because it
+	could hang.
 
-	* aux/macros/check_mnt2_gen_opt.m4: ditto
+2005-07-21  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/check_mnttab_opt.m4: new macro in this file to loop
-	over AC_CHECK_MNTTAB_OPT.  Reduces size of configure script a lot.
+	* conf/umount/umount_linux.c (umount_fs): cleanup this function,
+	breaking long "if" statements using "goto out".
 
-	* conf/nfs_prot/nfs_prot_netbsd1_3.h: include nfs/rpcv2.h,
-	nfs/nfs.h and nfs/nfsmount.h if they exist.  Patch from
-	christos@zoulas.com (Christos Zoulas).
+	* conf/umount/umount_{aix,bsd44,osf,default,linux}.c (umount_fs):
+	call new utility function umount2_fs() as needed (EBUSY, EIO, or
+	ESTALE).
 
-	* amd/info_hesiod.c: some forward declarations.  Patch from
-	christos@zoulas.com (Christos Zoulas).
+	* conf/umount/umount_{aix,bsd44,osf,default,linux}.c (umount2_fs):
+	define a new utility function to invoke forcible/lazy unmounts
+	without touching any mtab files.  This separate utility function
+	is useful because it can be called from elsewhere.
 
-1999-01-28  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_toplvl.c (amfs_toplvl_init): new function, called
+	before Amd mounts toplvl mounts, which gives us a hook for cleanup
+	of a previously dead Amd.  In our case, if the user asked for
+	forced_unmounts, and the OS supports it, then we try forced/lazy
+	unmounts on any previous toplvl mounts.  This is useful if a
+	previous Amd died and left behind toplvl mount points (this Amd
+	will clean them up!).  WARNING: Don't use forced/lazy unmounts if
+	you have another valid Amd running, because this code WILL force
+	those valid toplvl mount points to be detached as well!
 
-	* libamu/mount_fs.c (compute_nfs_args): don't turn on/off noconn
-	option if it was already in that state.  Patch from David
-	Wolfskill <dhw@whistle.com>.
+	* amd/amfs_toplvl.c (amfs_toplvl_umount): don't unconditionally
+	try forced/lazy unmounts because it will prevent a normal Amd from
+	terminating and cleaning up properly (self-deadlocking: detached
+	mounts hang the parent Amd on a stat).  Since we already do
+	unmounts in the background, then try a safer policy: after trying
+	the normal unmounts a few times (5 sec), escalate and try forced
+	unmounts a few times (5 more seconds), and if even that failed,
+	then try the ultimate -- detached unmounts (which always succeed).
+	This allows Amd to first try and shutdown cleanly, and gradually
+	try more forcible ways to shutdown.  On Linux, this procedure will
+	cleanly shutdown Amd even if there are processes with their CWD on
+	Amd's mount points (which normally result in EBUSY).
 
-1999-01-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-07-20  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/configure.in: automake nowadays supports LTLIBOBJS (but not
-	LTALLOCA yet).  Substitute value of LIBTOOL_DEPS for libtool
-	rebuild make rules.
+	* Makefile.am (EXTRA_DIST_CONF): add new umount_aix.c to distro.
 
-	* Makefile.am: new rules to remake libtool (maintainers only)
+	* conf/umount/umount_aix.c: easier if AIX has its own unmount
+	helper file.
 
-	* amd/amfs_toplvl.c (mount_amfs_toplvl): print generic mount flags
-	if -D trace was used.
+	* m4/macros/check_umount_style.m4: AIX needs its own unmount style
+	file.
 
-1999-01-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* doc/am-utils.texi (forced_unmounts Parameter): @xref -> @pxref.
 
-	* buildall: all if statements should have an else clause because
-	of Ultrix's /bin/sh.
+2005-07-19  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-01-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/nfs_prot/nfs_prot_aix5_2.h: define compatible
+	forced-unmount flag.
 
-	* amq/amq.c: removed dummy variables.
+	* conf/umount/umount_default.c (umount_fs): if regular umount got
+	EBUSY, EIO, or ESTALE, then try forced unmount, if supported.  Try
+	umount2 (Solaris) or uvmount (AIX).
 
-	* amq/pawd.c: removed dummy variable.s
+	* conf/umount/umount_{bsd44,osf}.c (umount_fs): if default
+	umount() failed with EIO or ESTALE, also try forced unmount.
 
-	* fixmount/fixmount.c (usage): removed dummy variables.
+2005-07-18  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* fsinfo/fsinfo.c: removed dummy variables.
+	* amd/autil.c (amfs_mount), amd/amfs_toplvl.c
+	(amfs_toplvl_umount): enable forced/lazy unmounts only if user
+	asked for it (and dlog it).
 
-	* hlfsd/hlfsd.c: removed dummy variables.
+	* scripts/amd.conf.5: document new force_unmount global parameter.
 
-	* wire-test/wire-test.c: removed dummy variables.
+	* doc/am-utils.texi (forced_unmounts Parameter): document new
+	global parameter.
 
-	* mk-amd-map/mk-amd-map.c: removed dummy variables.
+	* amd/conf.c (gopt_forced_unmounts): process forced_unmounts
+	option (default "no").  Exit with an error if user specified the
+	option as "yes" but configure couldn't find support for either the
+	MNT_FORCE or MNT_DETACH flags.
 
-	* doc/texinfo.tex: updates from GNU mirror.
+	* scripts/amd.conf-sample (forced_unmounts): example usage of new
+	option.
 
-	* aux/GNUmakefile (../doc/texinfo.tex): new rule to update
-	doc/texinfo.tex from GNU mirror.
+	* amd/amd.h (CFM_FORCED_UNMOUNTS): new flag for forced_unmounts
+	option.
 
-	* released snapshot am-utils-6.0.1s3
+	* m4/macros/header_templates.m4: templates for _DETACH and _FORCE.
 
-	* Makefile.am (install-snapshot): better snapshot and new
-	install-snapshot and test-snapshot rules (maintainer).
+	* configure.in: check for generic u/mount options "detach" and
+	"force".
 
-	* amd/info_ldap.c (amu_ldap_init): don't run STREQ if one of the
-	args may be NULL.
-	Some dlog() entries were not enclosed in #ifdef DEBUG.  Fix from
-	Bill Paul <wpaul@ctr.columbia.edu>
+	* include/am_utils.h (UMOUNT_FS, umount_fs): new prototypes.
+	Define AMU_UMOUNT flags for force, detach, and autofs.
 
-1999-01-13  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_toplvl.c (amfs_toplvl_umount): pass _FORCE and _DETACH
+	unmount flags unconditionally.  Pass them to UMOUNT_FS().
 
-	* check for experimental generic 'ignore' mount flag on freebsd3.
+	* conf/nfs_prot/nfs_prot_linux.h: define MNT_FORCE and MNT_DETACH
+	if needed, because some Linux systems don't define them
+	(presumably because it would be too dangerous to expose these
+	flags to users).
 
-	* Update library -version-info to 3:0:1 (will result in 2.1.0 .so
-	version, which is backwards compatible with older versions.)  Only
-	one new interface was added to libamu.
+	* amd/autil.c (amfs_mount): if mount(2) failed with ESTALE or EIO,
+	then assume that we're in trouble, possibly because a previous
+	mount is hung.  So, first try to force a lazy unmount of the old
+	mount.  If the forced unmount worked, then try again to mount the
+	desired file system.  If the forced unmount failed, then don't
+	retry: just return an error.
 
-	* amd/amfs_toplvl.c (mount_amfs_toplvl): add generic mount flags
-	that are specific to automounter mounts.
+	* amd/amfs_generic.c (amfs_generic_umount), amd/amfs_host.c
+	(amfs_host_umount), amd/ops_cachefs.c (cachefs_umount),
+	amd/ops_cdfs.c (cdfs_umount), amd/ops_efs.c (efs_umount),
+	amd/ops_lofs.c (lofs_umount), amd/ops_nfs.c (nfs_umount),
+	amd/ops_pcfs.c (pcfs_umount), amd/ops_ufs.c (ufs_umount),
+	amd/ops_xfs.c (xfs_umount), conf/umount/umount_bsd44.c
+	(umount_fs), conf/umount/umount_default.c (umount_fs),
+	conf/umount/umount_linux.c (umount_fs), conf/umount/umount_osf.c
+	(umount_fs): compute and use unmount specific flags.
 
-	* aux/configure.in: update libamu.so age and revision since a new
-	interface was added to libamu/mount_fs.c
-	(compute_automounter_mount_flags).
+2005-07-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* libamu/mount_fs.c (compute_automounter_mount_flags): new
-	function to compute generic mount flags that are specific to mount
-	points only.
+	* configure.in: better help for users, if nfs_args can't be found.
 
-	* aux/{configure.in,acconfig.h}: add support for generic mount
-	entry ignore option.
+2005-07-15  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* released snapshot am-utils-6.0.1s2
+	* BUGS: more details on AIX's need to install bos.net.nfs.adt
+	before configuring am-utils (else configure cannot find struct
+	nfs_args on AIX).
 
-	* amd/info_ldap.c (get_ldap_timestamp): dlog format fixes.
+2005-07-10  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* libamu/mount_fs.c (print_nfs_args): solaris 2.7 changed format
-	of knc_semantics from u_long to u_int.
+	* amd/srvr_nfs.c (find_nfs_srvr): flush NFS handle cache if the IP
+	address of a down server had changed.
 
-	* aux/macros/check_mount_style.m4: freebsd3 no longer needs a
-	special mount helper.
+	* amd/info_union.c (union_reload): use safer xsnprintf() routine.
 
-1999-01-12  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/srvr_nfs.c (find_nfs_srvr): check to see if the IP address
+	of a named but down fserver changed (i.e., the previous IP address
+	is no longer responding).  If so, then reset the fserver to the
+	new IP address, and set the fserver's flags such that the function
+	will fall through to doing the usual NFS version/proto checks and
+	pinging.  (This should fix one case of bug #308.)
 
-	* aux/macros/check_nfs_prot_headers.m4 (AMU_NFS_PROT_HEADERS):
-	amu_nfs_conf.h should always be found in $top_builddir.
+	* conf/umount/umount_linux.c (umount_fs): warn if plain umount()
+	failed, before we try to ignore any errors or try optional
+	umount2(), possibly with forced/lazy unmount.
+	(umount_fs): dlog when unmount succeeded.
 
-Tue Jan 12 00:05:42 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+2005-07-08  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_sunos5_7.h (MNTTAB_TYPE_AUTOFS): Undefine
-	to avoid wrong reports from show_fstypes.
+	* conf/mount/mount_linux.c: add a couple more NFSv2 error codes
+	that are compatible with NFSv3.
 
-	* conf/nfs_prot/nfs_prot_irix5.h (MNTTAB_TYPE_XFS): Likewise.
+2005-07-07  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_hpux11.h (MNTTAB_TYPE_NFS3): Likewise.
+	* m4/macros/header_templates.m4: extern template for strlcat().
 
-Tue Jan 12 00:05:42 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+	* amd/get_args.c (get_version_string): use safer strlcat (or
+	replacement strlcat).  Use new wrapper xsnprintf() function, which
+	will use the safer vsnprintf() if available, else default to plain
+	sprintf.
 
-	* BUGS (mips-dec-ultrix4.3): Update Ultrix caveats.
+	* configure.in: check for existence of strlcat() and its extern,
+	replacing with libamu/strlcat.c as needed.
 
-Tue Jan 12 00:05:42 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+	* libamu/Makefile.am (EXTRA_DIST): add strlcat.c to distro.
 
-	* hlfsd/homedir.c (delay): Cast child to long, adapt format.
-	(hlfsd_getpwent): Likewise for pw_uid.
+	* include/am_defs.h: optional strlcat() extern.
 
-	* amd/info_nis.c (nis_init): Cast order to unsigned long, adapt
-	format. 
+	* include/am_utils.h: extern for new xvsnprintf().
 
-	* conf/transp/transp_tli.c (amu_clnt_create_best_vers): Cast
-	tv_sec to int to match format.
-	(get_nfs_version): Cast nfs_version, NFS_VERSION to int to match
-	formats. 
+	* configure.in: overdue new major libtool shlib version.
+	Check for snprintf function and extern.
 
-	* amd/amfs_program.c (amfs_program_exec): Cast ptr difference to
-	long, adapt format.
+2005-07-06  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* include/am_defs.h: Handle __attribute__ if available.  From
-	GNU fileutils 4.0 lib/errors.h.
+	* conf/nfs_prot/nfs_prot_aix4_3.h: cleanup struct
+	aix4_nfs_args_bis.
 
-Mon Jan 11 13:46:44 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+	* Makefile.am (EXTRA_DIST_CONF): include mount_aix3.c in
+	distribution.
 
-	* libamu/mount_fs.c (print_nfs_args): Cast sizeof() to int to
-	match format.
+	* conf/mount/mount_aix.c: mount style for aix 5.x and newer.
 
-	* hlfsd/stubs.c (nfsproc_getattr_2_svc): Cast uid, gid to long,
-	adapt format.
-	(nfsproc_lookup_2_svc): Likewise.
-	(nfsproc_readlink_2_svc): Likewise for userid, groupid.
+	* conf/mount/mount_aix3.c: mount styles for aix 3.x/4.x.
 
-	* hlfsd/nfs_prot_svc.c (nfs_program_2): Cast args to int to match
-	format.
+	* m4/macros/check_mount_style.m4: split mount styles for
+	aix3.x/4.x and the newer (and better) aix 5.x code.
 
-	* hlfsd/homedir.c (homedir): Cast uid, child to long, adapt
-	format. 
+2005-07-05  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/info_hesiod.c (hesiod_search): Cast m, pval, tp to unsigned
-	long, adapt format.
+	* amq/pawd.c (getawd): avoid buffer overflow.  Bug fix from Graeme
+	Wilford <G.Wilford@surrey.ac.uk>.
 
-	* amd/ops_nfs.c (find_nfs_fhandle_cache): Cast fh_wchan to
-	unsigned long, adapt format.
-	(got_nfs_fh): Likewise.
-	(prime_nfs_fhandle_cache): Cast fh_nfs_version to int to match
-	format. 
-	(call_mountd): Likewise, mnt_version also.
-	(mount_nfs_fh): Likewise.
+2005-06-30  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/ops_autofs.c (autofs_program_1): Cast args to int to match
-	format.
-	(autofs_unmount_1_svc): Cast ur->devid, ur_rdevid, ur->next to
-	unsigned long, adapt formats.
-	(autofs_bgmount): Cast opt_fs to unsigned to, adapt format.
-	(autofs_bgmount): Use long format to match arg.
-	(autofs_lookuppn): Removed superfluous arg.
+	* amd/map.c (get_next_exported_ap): Avoid running off the end of
+	the exported_ap[] array.  Patch from jon+amd-at-spock.org.  Fixed
+	bug #301.
 
-	* amd/srvr_nfs.c (start_ping): Cast nfs_version to int to match
-	format. 
-	(got_portmap): Likewise for port.
-	(recompute_portmap): Likewise for fs->fs_version, mnt_version.
-	(find_nfs_srvr): Likewise for nfs_version.
+2005-06-25  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/sched.c (sched_task): Cast wchan to unsigned long, adapt
-	format. 
+	* Makefile.am (EXTRA_DIST_CONF): distribute new mtab_linux.c.
 
-	* amd/nfs_start.c (checkup): Cast ptr difference to long, next_mem
-	to unsigned long, adapt format.
-	Cast tvv.tv_sec to int to match format.
+	* conf/mtab/mtab_linux.c (rewrite_mtab): variable declarations
+	must come before C code.
 
-	* amd/nfs_prot_svc.c (nfs_program_2): Cast args to int to match
-	format.
+	* conf/mtab/mtab_linux.c: Linux-specific mount table hanlding
+	that's safe (uses locks, handles symlinks to /proc/mounts, etc.).
+	Patch from Red Hat, which they adapted from mtab_file.c.  Minor
+	fixes to this file.
 
-	* amd/map.c (root_fh): Cast pid to long, adapt format.
-	(timeout_mp): Cast time_t to long, adapt format.
+	* m4/macros/check_mnttab_style.m4: Use Linux-specific mount table
+	handling.
 
-	* amd/clock.c (reschedule_timeouts): Use long format, cast time_t
-	arg.
+2005-06-24  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/amfs_host.c (fetch_fhandle): Cast nfs_version to int to
-	match format.
-	(amfs_host_fmount): Likewise.
-	(amfs_host_umounted): Likewise.  Removed superfluous arg.
+	* conf/mount/mount_aix.c (mount_aix3): minor cleanup of filehandle
+	copying code.
 
-	* amd/amfs_auto.c (amfs_auto_bgmount): Cast pointer to unsigned
-	long, adapt format.
-	(amfs_auto_bgmount): Use long format, cast time_t arg.
-	(amfs_auto_lookuppn): Removed superfluous arg.
+2005-06-23  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/amd.c (main): Cast geteuid() result to long, adapt format.
+	* conf/nfs_prot/nfs_prot_hpux.h: add extern for h_errno, which may
+	be missing from older hpux10 systems.
 
-	* conf/transp/transp_sockets.c (get_nfs_version): Cast nfs_version
-	to int to match format.
+	* configure.in: update bug-reporting address to list
+	https://bugzilla.am-utils.org/ as well as the mailing list.
 
-	* include/am_utils.h: Declare plog, dplog as printf-like.
+	* Makefile.am (EXTRA_DIST_M4): distribute new type_rpcvers_t.m4
+	macro.
 
-	* conf/mount/mount_irix6.c (mount_irix): Print type as char *.
+	* conf/transp/transp_tli.c (get_nfs_version): always use
+	rpcvers_t, now that it'll be automatically discovered.
 
-Mon Jan 11 13:46:44 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+	* configure.in: check for rpcvers_t type.
 
-	* amd/info_hesiod.c (hesiod_isup): New function.
-	* amd/mapc.c (maptypes): Add it.
+	* m4/macros/type_rpcvers_t.m4: new macro to check for type of
+	rpcvers_t (Some Solaris versions need it).
 
-1999-01-10  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/nfs_prot/nfs_prot_sunos5_8.h: don't define INADDR_NONE
+	here, but in the actual source files that may need it.
 
-	* released snapshot am-utils-6.0.1s1
+	* libamu/wire.c (INADDR_NONE): define INADDR_NONE if not defined
+	already.
 
-1999-01-09  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* include/am_defs.h: define extern for sleep(3) if needed.
 
-	* ALL: bump copyright year to 1999.
+	* m4/macros/header_templates.m4: template for sleep(3) extern.
 
-Fri Jan  8 15:24:15 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+	* configure.in: check for extern for sleep(3), which is missing
+	from some old (and buggy) versions of gcc's fixinc'ed headers.
 
-	* aux/macros/check_mtype_type.m4: Ultrix uses an int mount type,
-	too. 
+	* conf/nfs_prot/nfs_prot_aix4_3.h: update definition of struct
+	nfs_args from actual system headers.
 
-	* aux/macros/check_mtype_printf_type.m4: Adapt corresponding
-	printf type.
+	* conf/mount/mount_aix.c (mount_aix3): fix name of aix4 "bis"
+	structure.
 
-Fri Jan  8 15:24:15 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+2005-06-22  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/acconfig.h: Removed HAVE_AM_FS_AUTOFS, unused.
+	* BUGS: update Solaris information about use of f/lex and
+	yacc/bison.
 
-	* conf/nfs_prot/nfs_prot_irix6.h: Likewise.
+2005-06-20  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_sunos5_6.h: Likewise.
+	* minor new port: i386-pc-linux-suse9.3.
 
-	* conf/nfs_prot/nfs_prot_sunos5_7.h: Likewise.
+2005-06-20  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* Makefile.am (EXTRA_DIST_DIRS): Removed, not needed by current
-	automake.
+	* configure.in (linux/nfs_mount.h): Move __KERNEL__ definition up
+	so u32 is available for <linux/sunrpc/msg_prot.h>.
 
-Thu Jan  7 02:55:18 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+2005-06-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/configure.in (AM_PROG_YACC): Replaced by AC_PROG_YACC, not
-	in current automake.
+	* amd/mapc.c (maptypes): move MAP_EXEC after MAP_FILE, because
+	exec maps will always match when users use amd with command line
+	args (not amd.conf).  Using that legacy way, unfortunately, means
+	that Amd will use it's hard-coded info-service search path, which
+	doesn't work for everyone.  It's much better to use amd.conf and
+	specify what you want exactly.
 
-Thu Jan  7 02:55:18 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+2005-06-15  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* doc/am-utils.texi: Added some missing inter-punctation after
-	@xref, or use @pxref/@ref as appropriate.  Spotted by makeinfo
-	from texinfo 3.12b.
+	* minor new port: i386-pc-linux-fc4 (gcc4 catches more bugs).
 
-1999-01-07  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/type_recvfrom_fromlen.m4: linux systems use unsigned
+	int as the type of recvfrom()'s 6th argument.
 
-	* doc/texinfo.tex: updated off of latest GNU mirror.
+	* m4/macros/type_yp_order_outorder.m4: linux systems use unsigned
+	int as the type of yp_order()'s 3rd argument.
 
-1999-01-04  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-06-15  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* doc/am-utils.texi (Supported Platforms): update platforms that
-	support NFS v.3.  Nicer postscript printing on double-sided pages.
+	* scripts/amd.conf-sample (map_type): typo, said mount_type
+	instead of map_type for the 'exec' example.
 
-	* amd/info_hesiod.c: add extern definition for hesiod_init()
+2005-06-11  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1999-01-01  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	*******************************************************************
+	*** Released am-utils-6.1					***
+	*******************************************************************
+
+2005-06-04  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* amd/ops_nfs.c (mount_nfs_fh): set timeo/retrans mount options
+	only if the user specified them in amd.conf or elsewhere.  If they
+	were not specified, don't do anything, which would let the OS use
+	its own defaults.
+
+	* amd/get_args.c (get_args): negative timeo/retrans are "good" in
+	that they represent uninitialized values (meaning to let the OS
+	use it's default values).  So only check if user specified a value
+	equal to zero (invalid).
+
+	* amd/amd.h: define AMU_TYPE_NONE so we know when users didn't
+	specify timeo/retrans at all.
+
+2005-06-03  Erez Zadok  <ezk@cs.sunysb.edu>
 
 	*******************************************************************
-	*** Released am-utils-6.0					***
+	*** Released am-utils-6.1-rc7					***
 	*******************************************************************
 
-1998-12-28  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/os_cflags.m4 (CFLAGS): use custom-OS C flags for
+	configuring, not just for building.  That way the two phases
+	(configure and compile) are in sync.  This fixes getwire() on
+	OSF/1 systems.
 
-	* conf/nfs_prot/nfs_prot_sunos5_7.h: support ldap in solaris 2.7.
+	* conf/nfs_prot/nfs_prot_sunos5_8.h: define INADDR_NONE if not
+	defined in system headers.
 
-1998-12-27  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-06-01  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_bsdi3.h: don't use reserved ports on
-	bsdi4 for NFS V3/nfs mounts.
+	* libamu/Makefile.am (EXTRA_DIST): remove alloca.c as it's no
+	longer needed.
 
-1998-12-26  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-05-28  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* using latest libtool (1.2e + patches), now supporting shared
-	libraries on many more systems.  Also using latest autoconf and
-	automake (unreleased GNU CVS'd versions.)
+	* completed set of fixes for irix6.5.
 
-	* minor new ports: hppa2.0w-hp-hpux11.00,
-	i386-unknown-netbsd1.3.3, mips-sgi-irix6.5.
+	* Minor new ports alpha-unknown-linux-gentoo1.4.16
+	alphaev56-dec-osf4.0f, mips-unknown-linux-gentoo1.4.16, and
+	sparc64-unknown-linux-gentoo1.4.16, and mips-sgi-irix6.5.  Test
+	those systems with both cc and gcc, where possible.
 
-	* fsinfo/fsinfo.h (yywrap): define it for systems (osf4) that
-	have /usr/bin/flex but not libfl.
+	* include/am_xdr_func.h: remove trailing comma at end of enum
+	list.
 
-1998-12-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/os_cflags.m4: with gcc 3.4.3 on irix-6.5, we get pte_t
+	undefined.  So give it a dummy value.
 
-	* lots of code cleanup, to make sure libamu.so does not use
-	undefined symbols.  Some system's shared libraries cannot handle
-	that.
+	* libamu/alloca.c: remove file from distro.
 
-1998-12-23  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: don't call AC_FUNC_ALLOCA any more.
 
-	* include/am_defs.h: only defined seteuid extern if function also
-	exists and is not superceded by setresuid (hpux).
+	* include/am_defs.h: remove header fixups for <alloca.h>, now that
+	we don't need it.
 
-	* amd/ops_autofs.c (autofs_bgmount, autofs_lookuppn): put explicit
-	braces to avoid confusion with nested if-then-else clauses.
+	* amd/amq_svc.c (amqsvc_is_client_allowed): rewrite function to
+	avoid only use of alloca() in am-utils, and to use strdup
+	explicitly.  This way we can avoid using alloca, a feature that's
+	not portable on various systems.
 
-	* aux/config.{sub,status}, aux/{ltmain.sh,ltconfig,mkinstalldirs:
-	updated from latest versions.
+	* amq/amq.c: remove unused lint/rcsid cruft.
 
-1998-12-22  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-05-27  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* minor new port: i386-pc-bsdi4.0
+	* conf/checkmount/checkmount_osf.c (fixmount_check_mount): add
+	extra parentheses around assignments in "if" expressions (gcc
+	complains).
 
-	* conf/nfs_prot/nfs_prot_bsdi3.h: add missing hesiod header
-	definitions for bsdi4.
+	* conf/nfs_prot/nfs_prot_osf4.h: add missing extern definitions
+	for plock, hstrerror, getmntinfo, alloca, xdr_exportnode, and
+	xdr_groups.
 
-	* {amd,fsinfo}/Makefile.am: force path to .y/.l files, because
-	some make programs (bsdi4) do not support VPATH correctly.
+	* configure.in: check for <linux/socket.h>, which, if found,
+	appears to be preferable to <sys/socket.h>.  Use it to find
+	<linux/nfs_mount.h>.  On some Linux systems
+	(Gentoo), both exist but only one must be included, or else you
+	get redefined structure errors.
 
-1998-12-16  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/wire.c (is_network_member): check if masknum is
+	INADDR_NONE, not "< 0" because it's an unsigned quantity.
 
-	* conf/mount/mount_aix.c: minor code cleanup
+	* libamu/util.c (xstrlcpy): remove useless test for size_t < 0,
+	because it's an unsigned quantity.
 
-	* aux/configure.in: check for extern definition to xdr_groups.
+2005-05-26  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1998-12-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	*******************************************************************
+	*** Released am-utils-6.1-rc6					***
+	*******************************************************************
 
-	* minor new port: powerpc-ibm-aix4.3.1.0
+2005-05-25  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/*.m4: updates for aix 4.3
+	* conf/nfs_prot/nfs_prot_aix5_2.h: AIX 5.3 complains about
+	missing definition of struct thread_credentials in <sys/vfs.h>
+	but trying to bring that definition in drags a whole lot of other
+	messy stuff.  So just provide a dummy definition for this
+	structure.
 
-1998-12-14  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-05-24  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* minor new port: i386-unknown-openbsd2.4
+	* Makefile.am (EXTRA_DIST_M4): distribute m4/macros/libtool.m4.
 
-	* aux/configure.in: don't check for xfs on openbsd because
-	openbsd-2.4 introduces a new file system named xfs, but different
-	than Irix's XFS.  Sigh.
+	* m4/macros/header_templates.m4: template for HAVE_EXTERN_MNTCTL.
 
-	* minor new port: i386-unknown-freebsd2.2.8
+	* m4/macros/check_extern.m4: include <sys/vmount.h> on AIX
+	systems, so we can find extern definition for mntctl().
 
-1998-12-03  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/mtab/mtab_aix.c, conf/checkmount/checkmount_aix.c: only
+	define an extern for mntctl() if needed.
 
-	* amd/amfs_nfsl.c (amfs_nfsl_ffserver): use case insensitive host
-	name match.  Bug fix from Douglas K. Rand" <rand@aero.und.edu>.
+	* amd/ops_nfs.c (prime_nfs_fhandle_cache): never, ever, use C++
+	style comments in C code.  Some C compilers don't accept it.
 
-1998-11-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/info_ldap.c (amu_ldap_init, get_ldap_timestamp): force cast
+	of "time_t *ts" to u_long, to avoid complaints on AIX 5.2 with
+	xlC.
 
-	* scripts/ctl-amd.in: wait4amd2die runs in the stop action, to
-	avoid race conditions when shutting down systems running amd.
+	* amd/get_args.c: rename symbol conf_file to amu_conf_file to
+	avoid conflict with libldap.a from openldap-2.0.21 on AIX 5.2.
+	Oh, when will people who develop libraries learn to always prefix
+	their exported symbols with a library-specific name?
 
-	* Makefile.am: add a dist-hook to change modes of the directories
-	in the tar file so they are not world writable.
+	* configure.in: check for mntctl() extern on AIX systems.
 
-	* conf/nfs_prot/nfs_prot_freebsd3.h: turned on NFSv3 support,
-	since it is now finally defined in the header files and
-	(hopefully) stable.
+	* ltmain.sh: update from latest libtool-1.5.18, so we can properly
+	build on AIX 5.2/5.3 with cc and with gcc.
 
-	* amd/srvr_nfs.c (find_nfs_srvr): allow overriding if nfsv2 option
-	is specified in mount options.  freebsd patches from David
-	O'Brien.
+	* m4/macros/libtool.m4: update from latest libtool-1.5.18.  This
+	time, and from now on, we must include libtool.m4 from the libtool
+	distribution itself.  That way we ensure that we use an ltmain.sh
+	that matches the appropriate libtool M4 macros.  This makes
+	am-utils no longer dependent on having libtool installed on a
+	given system on which you run bootstrap.
 
-	* amq/amq.c (main), fixmount/fixmount.c (main), hlfsd/hlfsd.c
-	(main), fsinfo/fsinfo.c (fsi_get_args), hlfsd/hlfsd.c (main),
-	amd/get_args.c (get_args): posix: use -1 to check for return from
-	getopt() (not EOF), as per posix.
+2005-05-23  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/amq_subr.c (xdr_amq_mount_tree_node): patches from "David
-	O'Brien" <obrien@NUXI.com>, from the FreeBSD source tree.  Use
-	real variable whose pointer is on the stack for decoding a long
-	int.
+	* minor new port: i386-pc-linux-deb3.0.
 
-1998-11-11  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-05-22  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* scripts/ctl-{amd,hlfsd}.in: include comments useful for redhat's
-	chkconfig utility.
+	* minor new ports: i386-unknown-netbsdelf2.0.2 and
+	i386-unknown-openbsd3.7.
 
-1998-11-10  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-05-20  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* released snapshot am-utils-6.0b2s3
+	* minor new ports: i386-pc-linux-gentoo1.4.16 and
+	powerpc-unknown-linux-yellowdog2.3.
 
-	* conf/transp/transp_sockets.c (create_nfs_service): remove C++
-	style comments.
+	* include/{mount_headers2.h, am_defs.h}: safer setup before
+	inclusion of <linux/nfs_mount.h>, which is broken on several
+	systems.
 
-1998-11-04  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: test for <linux/nfs2.h>.  Separate special test
+	for <linux/nfs_mount.h> because we need to define __KERNEL__ for
+	that test, as well as optionally define struct nfs2_fh for some
+	systems (gentoo with 2.4 kernel, yellowdog 2.3, and others).
 
-	* released snapshot am-utils-6.0b2s2
+	* config.guess.long: support Gentoo and Yellow Dog Linux distros.
 
-	* created CVS package
+2005-05-18  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/nfs_subr.c (nfsproc_lookup_2_svc): try to avoid a race
-	condition between unmounting and re-mounting an entry, by
-	increasing the ttl of a looked up entry before unmounting it.
-	Patch from Mike Mitchell <mcm@unx.sas.com>.
+	* minor new ports: i386-pc-linux-suse9.2 and
+	i386-unknown-freebsd5.4.
 
-	* All files: spell comments and strings.
+	* amd/nfs_subr.c: use NFS_FHSIZE, not FHSIZE.
 
-1998-11-03  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-05-17  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/configure.in: look for yp_all in libnsl only if yp_all not
-	already found elsewhere (in libc or other default libraries).
-	This is so RedHat 5.1 systems could find yp functions in libnsl,
-	but also so AIX 4.2.1 will NOT include libnsl, because the latter
-	has broken nis functionality that also exists and works ok in libc.
+	*******************************************************************
+	*** Released am-utils-6.1-rc5					***
+	*******************************************************************
 
-1998-10-29  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/info_ldap.c (amu_ldap_init): change plog to dlog, to avoid
+	sending annoying warning for a minor issue.
 
-	* amd/amd.c (main): bug fix: swapped arguments to kill(2).  Fix
-	from Danny Rathjens <dkr@cs.fiu.edu>.
+2005-05-17  Ion Badulescu <ionut@moisil.badula.org>
 
-1998-10-28  Erez Zadok  <ezk@spruce.mcl.cs.columbia.edu>
+	* amd/nfs_subr.c: check for NULL pointer before dereferencing it.
 
-	* released snapshot am-utils-6.0b2s1
+2005-05-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1998-10-27  Erez Zadok  <ezk@spruce.mcl.cs.columbia.edu>
+	* minor new ports: powerpc-apple-darwin7.9.0.
 
-	* aux/macros/*.m4: support bsdi4 as bsdi3.
+	* m4/macros/host_macros.m4: if a NetBSD system, remove 'elf' part
+	from OS name because it's no longer relevant.  Also, don't include
+	the major OS version number in the OS name because that's also
+	unnecessary (and users can always use $osver in maps).
 
-	* aux/macros/os_ldflags.m4: enable detection of LDAP on solaris
-	2.7 (libraries located in /usr/lib/fn).  This is off until Sun
-	includes LDAP header information.
+	* amd/nfs_subr.c: use [1] for out-of-band pointer at the end of
+	struct am_fh, because it's the most portable method.  Bug fix
+	suggestion from Dan Riley <dsr at mail.lns.cornell.edu>.  Better
+	fix from Ion Badulescu: use [FHSIZE-sizeof(u_int)] which is the
+	actual size we use.
 
-1998-10-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_generic.c (amfs_lookup_mntfs): reset currently used
+	def_opts to options given in -opts, appended with the /default
+	options.  Bug fix suggestion from Dan Riley <dsr at
+	mail.lns.cornell.edu>.
+
+2005-05-13  Erez Zadok  <ezk@cs.sunysb.edu>
 
 	*******************************************************************
-	*** Released am-utils-6.0b1					***
+	*** Released am-utils-6.1-rc4					***
 	*******************************************************************
 
-1998-10-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-
-	* mk-amd-map/mk-amd-map.c (main): use perror not strerror.
-	(main): set return type to int if no ndbm maps.
+2005-05-11  Daniel P. Ottavio  <dottavio@ic.sunysb.edu>
 
-	* include/am_defs.h: avoid conflicts with <sys/mount.h> in 2.1
-	kernels.
+	* amd/amd.c (main) : fixed memory leak detected by valgrind
 
-1998-10-18  Erez Zadok  <ezk@london.mcl.cs.columbia.edu>
+	* amd/info_ldap.c (amu_ldap_init) : fixed memory leak detected by
+	valgrind
 
-	* A.i386-unknown-netbsd1.3.2/amu_nfs_prot.h: trim down and cleanup
-	for netbsd 1.3.2.
+2005-05-11  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1998-10-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/{check_checkmount_style.m4, check_mnttab_style.m4,
+	check_nfs_fh_dref.m4, check_nfs_prot_headers.m4,
+	check_nfs_sa_dref.m4, check_umount_style.m4, os_cflags.m4}: check
+	for "macosx" as valid OS string, so we compile properly on Darwin
+	systems.
 
-	* aux/configure.in: check for yp_all in libnsl, b/c redhat 5.1
-	systems put NIS functions there.
+	*******************************************************************
+	*** Released am-utils-6.1-rc3					***
+	*******************************************************************
 
-	* mk-amd-map/mk-amd-map.c: patch from "David O'Brien"
-	<obrien@NUXI.com> merged in.  Use POSIX -1 return code from
-	getopt(), not EOF.  Use .db extentions for systems that use it,
-	instead of .{pag,dir}.
+	* rerun bootstrap to get a working configure script that actually
+	checks for limits.h and dependent linux autofs/nfs headers.
 
-1998-10-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: remove redundant check for limits.h.
 
-	* wire-test/wire-test.c, hlfsd/hlfsd.c, fixmount/fixmount.c,
-	amd/amd.c (main): avoid overrunning hostname buffer.  Bug fix from
-	"David O'Brien" <obrien@NUXI.com>.
+2005-05-09  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* scripts/amd.conf.5: minor typo reported by "David O'Brien"
-	<obrien@NUXI.com> in .TH section of man page.
+	*******************************************************************
+	*** Released am-utils-6.1-rc2					***
+	*******************************************************************
 
-	* amd/info_nis.c (am_yp_all): don't leak key-val entries.  Patch
-	from Thomas Richter <richter@chemie.fu-berlin.de>.
+2005-05-08  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1998-10-12  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_generic.c (amfs_lookup_mntfs): removed redundant use of
+	old_def_opts variable.
 
-	* doc/am-utils.texi (Program Filesystem): minor typo fixed as per
-	Andreas Stolcke <stolcke@speech.sri.com>.
+2005-05-08  Daniel P. Ottavio  <dottavio@ic.sunysb.edu>
 
-	* minor new ports: sparc64-unknown-linux-gnu, i386-pc-solaris2.7,
-	and sparc-sun-solaris2.7.
+	* amd/amfs_generic.c (amfs_lookup_mntfs) : Make sure when a map
+	entry has a single dash '-', that the default options are reset.
+	This functionality was somehow lost from earlier releases and
+	reported by Dan Riley <dsr@mail.lns.cornell.edu>.
 
-	* conf/mount/mount_freebsd3.c (mount_freebsd3): freebsd 3.0 is now
-	a 4.4lite kernel, and somethings were removed, such as
-	INITMOUNTNAMES.
+2005-05-05  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/ops_autofs.c (autofs_lookuppn): don't leak memory while
-	processing /defaults.  Free temporary opts.  Patch from
-	dsr@mail.lns.cornell.edu (Daniel S. Riley)
+	* config.guess.long: detect SuSE Enterprise Server and call it
+	"sles" not "suse".
 
-	* amd/amfs_auto.c (amfs_auto_lookuppn): don't leak memory while
-	processing /defaults.  Free temporary opts.  Patch from
-	dsr@mail.lns.cornell.edu (Daniel S. Riley)
+2005-05-02  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/mtab/mtab_osf.c (read_mtab): patch from
-	 dsr@mail.lns.cornell.edu (Daniel S. Riley) not to access
-	 uninitialized memory on Digital Unix.
+	* doc/am-utils.texi (amd): document proper use of
+	/etc/hosts.allow.  Don't spawn a new Amd process because Amd will
+	get confused if someone else waitpid's on its children (which
+	often do important un/mount work).  Issue reported by Francis
+	Montagnac <Francis.Montagnac at sophia.inria.fr>.
 
-1998-10-09  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* minor new ports: powerpc64-unknown-linux-rhel4, and
+	powerpc64-unknown-linux-sles9.
 
-	* aux/macros/{check_mtype_type,check_mtype_printf_type}.m4: most
-	systems now use "char *" as their mount type.
+2005-05-01  Daniel P. Ottavio  <dottavio@ic.sunysb.edu>
 
-1998-10-08  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_host.c (amfs_host_umount): We do not want to pass
+	ENOENT as an error because if the directory does not exists our
+	work is done anyway.
 
-	* amd/conf.c (gopt_map_type, ropt_map_type): check if map type
-	exists.
+	* conf/umount/umount_linux.c (umount_fs): If we are successful or
+	there was an ENOENT, remove the mount entry from the mtab file.
 
-	* amd/mapc.c (mapc_type_exists): function to test if a map of
-	certain type exists.
+2005-05-01  Ion Badulescu  <ionut@moisil.badula.org>
 
-1998-10-08  Erez Zadok  <ezk@horatio.mcl.cs.columbia.edu>
+	* amd/nfs_subr.c: am_fh definition moved here from amd.h;
+	restructured to better reflect its duality (old/new filehandles)
+	(fh_to_mp3): fhh_gen is always used, even for new style f/h
+	(mp_to_fh): ditto
 
-	* aux/macros/{mount_headers,try_compile_anyfs,try_compile_nfs}.m4,
-	include/am_defs.h: Avoid a conflict in definitions of ntohl/htonl
-	in RH-5.1 sparc64 between <netinet/in.h> and
-	<linux/byteorder/generic.h> (2.1 kernels).
+	* amd/amd.h: moved am_fh definition to nfs_subr.c (which is the
+	only place where it's used)
 
-1998-09-28  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-04-30  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/func_bad_yp_all.m4 (ac_cv_func_yp_all_clean): RedHat
-	5.1 systems with glibc glibc-2.0.7-19 or below leak a UDP socket
-	from yp_all().
+	* m4/macros/host_macros.m4: use sw_vers on Apple machines to find
+	out more appropriate OS name (macosx) and OS version (10.3.x) than
+	uname(3) reports.
 
-1998-09-25  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-04-29  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/mount/mount_linux.c (parse_opts): check for pcfs support
-	only if autoconfigured.
+	* config.guess, config.sub, doc/texinfo.tex: updates from latest
+	official GNU distributions.
 
-1998-09-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/host_macros.m4: for macosx, change architecture value
+	from "Power Macintosh" to "powerpc".
 
-	* Makefile.am (EXTRA_DIST): distribute README.yk2 file.
+	* libamu/util.c (xstrlcpy): format 'len' parameter as u_long, not
+	int (it's a size_t).
 
-	* README.y2k: explain y2k compliance status of am-utils.
+2005-04-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1998-09-16  Erez Zadok  <ezk@iguana.mcl.cs.columbia.edu>
+	* scripts/amd.conf.5, doc/am-utils.texi (normalize_slashes
+	Parameter), scripts/amd.conf-sample: document new
+	normalize_slashes global configuration parameter.
 
-	* amd/amfs_host.c (fetch_fhandle, amfs_host_fmount,
-	amfs_host_umounted): clnt_sperrno() may return a const.
+	* amd/opts.c (deslashify, normalize_slash): don't touch trailing
+	slashes, even if multiples of them, if user said
+	normalize_slashes=no in amd.conf.
 
-Sat Aug  8 23:28:32 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/conf.c (gopt_normalize_slashes): new function to record if
+	to normalize slashes or not.
 
-	* aux/configure.in: check for <nfs/nfsmount.h>, as per Christos
-	Zoulas. Turned on checking for mount options: async, synchronous,
-	deadthresh, leasterm, nqnfs, and readahead.
+	* amd/amd.h (CFM_NORMALIZE_SLASHES): new flag to decide if to
+	normalize double-slashes or not ("yes" by default).
 
-	* amd/info_nis.c: patch from christos@zoulas.com (Christos Zoulas)
-	to include prototype definition for nis_isup().
+	* amd/autil.c (am_mounted): pass TRUE when calling mf_mounted.
+	This is the parent mntfs which does the mf->mf_fo
+	(am_opts type), and we're passing TRUE here to tell mf_mounted to
+	actually free the am_opts.
 
-Sun Jul 19 18:50:10 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/autil.c (mf_mounted): Be careful when calling free_ops and
+	XFREE here.  Some pseudo file systems like nfsx call this
+	function, even though it would be called by the lower-level amd
+	file system functions.  nfsx needs to call this function because
+	of the other actions it takes.  So we pass a boolean from the
+	caller (yes, not so clean workaround) to determine if we should
+	free or not.  If we're not freeing (often because we're called
+	from a callback function), then just to be sure, we'll zero out
+	the am_opts structure and set the pointer to NULL.  The parent
+	mntfs node owns this memory and is going to free it with a call to
+	mf_mounted(mntfs,TRUE).
 
-	* hlfsd/stubs.c (getcreds): force sscanf arg to u_long.
+	* amd/amd.h: pass flag to mf_mounted, to free or not to free the
+	am_opts.
 
-Tue Jul 14 20:34:25 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_nfsx.c (amfs_nfsx_cont): call mf_mounted with FALSE to
+	tell it not to free the am_opts, to avoid double free.
 
-	* released snapshot am-utils-6.0a17s1
+	* include/am_defs.h: include limits.h if found.
 
-Wed Jul  8 21:49:15 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: check for limits.h.  Check for certain Linux
+	headers such as auto_fs.h after checking for limits.h, and include
+	the latter if it exists, because some Linux headers depend on
+	limits.h.  This prevents warnings during configure time.
 
-	* aux/macros/host_macros.m4: all x86 hosts should have $arch be
-	i386, not i[456]86.
+2005-04-12  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Tue Jul  7 18:55:09 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_toplvl.c (amfs_toplvl_mount): do NOT set retrans/timeo
+	values from default global UDP settings, because it can cause
+	unexpected timeouts in Amd on slow systems.  The default that each
+	OS provides for these toplvl NFS mounts should be OK, or else you
+	can use the map_options entry.
 
-	* aux/macros/{mount_headers,try_compile_anyfs,try_compile_nfs}.m4,
-	include/am_defs.h: include <linux/posix_types.h> before
-	<linux/fs.h> because on redhat 5.1, there is a bug (misuse) of
-	headers in <socketbits.h> (it defines _LINUX_TYPES_H instead of
-	__KERNEL_STRICT_NAMES).
+2005-04-09  Daniel P. Ottavio  <dottavio@ic.sunysb.edu>
 
-	* aux/configure.in: check for <linux/posix_types.h> because it is
-	need for RedHat 5.1.
+	* amd/nfs_subr.c (mp_to_fh): Replace xstrlcpy with memcpy because the
+	source buffer is treated more as a filehandle than a string.
 
-Wed Jun 17 00:05:33 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/nfs_subr.c (fh_to_mp3): Replace xstrlcpy with memcpy because the
+	source buffer is treated more as a filehandle than a string.
 
-	* scripts/Makefile.am (EXTRA_DIST): have fixrmtab generated from
-	.in as well, so it doesn't get removed by make clean.
+	* amd/opts.c (free_op): No longer need to assign pointer to NULL
+	after XFREE.
 
-Tue Jun 16 22:00:15 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/opts.c (expand_op): Revert back to using strncpy() instead
+	of xstrlcpy.  The code is correct and relies on the semantics of
+	strncpy.
 
-	* aux/macros/{check_fs_mntent.m4, check_mnttab_type.m4,
-	check_mount_type.m4}: redhat 5.1 puts some modules in
-	/lib/modules/preferred/.
+	* libamu/mount_fs.c (compute_nfs_args): Leave XXX warning that use
+	of xstrlcpy in NFS_HN_DREF may corrupt a struct nfs_args, or
+	truncate our concocted "hostname:/path" string prematurely if the
+	nap->hostname field is ever less than 64 bytes long
+	(MAXHOSTNAMELEN).
 
-Wed May 13 16:33:57 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/util.c (xstrlcpy): Return immediately if len is 0 to
+	avoid unnecessary work.  Log an error and return if len is less
+	than 0.
 
-	* amd/ops_autofs.c (mount_autofs): cast pid to long.
+2005-04-07  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Tue Apr 28 15:12:36 1998  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+	* include/am_utils.h (XFREE): XFREE() should nullify the pointer
+	even when compiling without debugging.  It's safer this way.
 
-	* conf/nfs_prot/nfs_prot/nfs_prot_irix6.h,
-	conf/nfs_prot/nfs_prot_sunos5_6.h: Undef MNTTAB_TYPE_AUTOFS too to
-	avoid amd/am_ops.c (show_fstypes) from erroneously claiming
-	support.
+	* libamu/xutil.c (am_set_hostname),
+	hlfsd/stubs.c (nfsproc_lookup_2_svc),
+	fsinfo/fsinfo.c (fsi_get_args),
+	fixmount/fixmount.c (is_same_host, remove_mount, main),
+	conf/mtab/mtab_isc3.c (mnt_dup, mtab_of),
+	conf/mount/mount_svr4.c (mount_svr4),
+	conf/mount/mount_linux.c (setup_loop_device),
+	conf/hn_dref/hn_dref_linux.h (NFS_HN_DREF),
+	conf/hn_dref/hn_dref_isc3.h (NFS_HN_DREF),
+	amd/opts.c (expand_op),
+	amd/ops_nfs.c (mount_nfs_fh),
+	amd/nfs_subr.c (fh_to_mp3, mp_to_fh),
+	amd/amfs_host.c (amfs_host_mount),
+	amd/am_ops.c (merge_opts):
+	use the new xstrlcpy instead of strncpy.
 
-Fri Apr 24 23:02:11 1998  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
-	
-	* libamu/xutil.c (get_syslog_facility): Don't use LOG_DAEMON
-	unconditionally, may be missing on Ultrix V4.3.
+	* conf/checkmount/checkmount_{default,svr4}.c
+	(fixmount_check_mount): document why NOT to use xstrlcpy.
 
-Thu Apr 23 20:24:33 1998  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+	* libamu/xutil.c: am_hostname need not be MAXHOSTNAMELEN+1 any
+	more, just MAXHOSTNAMELEN.
 
-	* conf/nfs_prot/nfs_prot_sunos5_4.h (MNTTYPE_CACHEFS): Define,
-	missing from <sys/mntent.h>.
-	
-	* conf/mtab/mtab_ultrix.c: Need separate inclusion of <sys/fs_types.h>
-	without KERNEL defined here.
+	* libamu/xutil.c (real_plog): use strlcpy (not xstrlcpy to avoid
+	recursion, since xstrlcpy may use plog).
 
-	* aux/macros/mount_headers.m4: Need to include <ufs/ufs_mount.h>,
-	<cdfs/cdfs_mount.h>, <cdfs/cdfsmount.h> so autoconfiguration of
-	ufs_args_t, cdfs_args_t fields and cdfs mount options can succeed.
+	* libamu/util.c (xstrlcpy): truncating a string is serious.  Use
+	XLOG_ERROR not XLOG_WARNING.
 
-	* amd/ops_ufs.c (mount_ufs): Removed obsolete comment.
+2005-04-06  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* ChangeLog: Fixed confusing linebreaks from ChangeLog imports.
-	Removed purely local (and obsolete) entry.
+	* include/am_utils.h: external definition for new xstrlcpy
+	function.
 
-Thu Apr 23 00:22:17 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/util.c (xstrlcpy): new function.  Similar to strncpy, but
+	uses strlcpy to guarantee that the resulting string is null
+	terminated, and also warn if the resulting string was truncated.
 
-	*******************************************************************
-	*** Released am-utils-6.0a16					***
-	*******************************************************************
+	* libamu/xutil.c (get_server_pid): move this function from util.c
+	which is for general-purpose utilities.
 
-Wed Apr 22 01:20:39 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/header_templates.m4: template for HAVE_EXTERN_STRLCPY.
 
-	* aux/macros/check_mount_style.m4: define freebsd3 mount style.
+	* include/am_defs.h: provide extern definition for strlcpy, if
+	needed.
 
-	* aux/macros/check_mount_trap.m4: new mount trap for freebsd3.
+	* libamu/Makefile.am (EXTRA_DIST): include strlcpy.c in distro.
 
-	* aux/macros/check_mtype_printf_type.m4,
-	aux/macros/check_mtype_type.m4 (ac_cv_mtype_type,): freebsd3 (as
-	of snapshot 3.0-980311-SNAP) uses char * types for mount(2), not
-	integers, but I'll keep them as integers and do the mapping in
-	conf/mount/mount_freebsd3.c
+	* configure.in: search for strlcpy and its extern.
 
-	* minor new port to i386-pc-bsdi3.1.
+	* amq/pawd.c (find_mt): It only handles *some* filesystem types,
+	so it breaks on direct xfs mounts for example.  The fix (from
+	Christos Zoulas) is simple: We need to exclude toplvl to avoid
+	infinite recursion, but all other fs's are game.
 
-	* minor new port to i386-unknown-netbsd1.3.1.
+2005-03-31  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/opts.c: new option addopts:=ARG, which smartly merges ARG
-	options with whatever the /default ones for a key are.  This
-	allows adding or overriding /default options individual keys.
+	* amd/nfs_subr.c (fh_to_mp3): strncpy may not null terminate if
+	copying exactly len bytes, so add null just to be safe.
 
-	* amd/am_ops.c (ops_match): strdup/malloc string assigned to
-	opt_opts because it'll get free()'d upon next use.
-	(merge_opts): new function to merge two sets of options.
-	(ops_match): if addopts option exist, append and merge it to the
-	current default options.
+2005-03-30  Daniel P. Ottavio  <dottavio@ic.sunysb.edu>
 
-Tue Apr 21 12:54:59 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/nfs_subr.c (fh_to_mp3): Increased the n of strncpy()
+	to make sure it null terminates.
 
-	* wire-test/wire-test.c (main): use dynamically allocated returned
-	string with list of interfaces.
+2005-03-29  Daniel P. Ottavio  <dottavio@ic.sunysb.edu>
 
-	* amd/get_args.c (get_version_string): allocate enough space for
-	header version string and a list of network interfaces of any
-	length.
+	* amd/nfs_subr.c (fh_to_mp3): Fix memset bug. In this case
+	the memset can be removed because strncpy() should padd the
+	buffer with NULLs anyway.
 
-	* libamu/wire.c (print_wires): return dynamically allocated string
-	containing list of networks.  Must be dynamic because some sites
-	had potentially dozens of network interfaces.  Patch from Matthew
-	Crosby <mcrosby@ms.com> slightly modified.
+2005-03-21  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-Mon Apr 20 00:37:20 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* include/am_defs.h: Clarify comment.
 
-	* conf/nfs_prot/nfs_prot_irix5.h: underfine MNTTYPE_XFS because
-	irix 5.3 does not have full header definitions for it.
+2005-03-21  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* fsinfo/fsi_lex.l (yywrap): define yywrap if needed, and
-	undefined it when not needed (similar to amd/conf_tok.l)
+	* include/am_defs.h: undefine "GROUP" so Solaris 10 with gcc-2.96
+	won't complain about a conflict for this definition between
+	<rpcsvc/nis.h> and <sys/acl.h>.
 
-	* hlfsd/hlfsd.h (ROOTID, SLINKID, INVALID): reduced maximum size
-	of these to unsigned short (because uid_t on some linux systems is
-	small).
+2005-03-20  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* released snapshot am-utils-6.0a16s10
+	* amd/readdir.c (amfs_readdir_browsable): use %p, not %lx.
 
-	* doc/am-utils.texi (opts Option): documented resvport mount
-	option.
+	* libamu/mount_fs.c (print_nfs_args): print pointer with %p, not
+	%lx.
 
-Sun Apr 19 18:17:03 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-03-18  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* doc/am-utils.texi (-D-Option): document behavior of -D info and
-	especially what it does to hesiod (turn on RES_DEBUG).
+	*******************************************************************
+	*** Released am-utils-6.1-rc1					***
+	*******************************************************************
 
-	* scripts/amd.conf.5: document info debugging option.
+2005-03-18  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* libamu/xutil.c (dbg_opt): parse info debugging option.
+	* conf/transp/transp_tli.c (get_nfs_version): use proper type for
+	versout on Solaris (rpcvcers_t).
 
-	* include/am_utils.h (D_INFO): define new trace option.
+	* amd/mapc.c (mapc_showtypes): if last map type to print, don't
+	append newline or comma to it.
 
-	* Makefile.am (EXTRA_DIST): include list of official mirrors in
-	distribution.
+	* libamu/mount_fs.c (print_nfs_args): cast struct netbuf pointer
+	to %lx because on Solaris 10 sparc gcc-3.4.3 complains about
+	casting it to an int (size is different).
 
-	* libamu/wire.c (SIZE): in the simple case, just compute
-	sizeof(struct ifreq).
+	* configure.in, NEWS: prepare for 6.1-rc1 release.
 
-Sun Apr 19 16:30:35 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+2005-03-17  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/amd.c (daemon_mode): set a temporary secure umask(0022)
-	before writing log file and restore it afterwards.  Patch from
-	Donald Buczek <buczek@MPIMG-Berlin-Dahlem.MPG.DE>.
+	* scripts/amd2ldif.in, ldap.schema: fixes by Adam Morley
+	<adam-at-gmi-dot-com> to synchronize what amd2ldif does vs. what
+	the ldap.schema expects.
 
-	* amd/get_args.c (get_args): 
+	* amd/map.c (exported_ap_free): We're using a free-list data
+	structure and re-using malloc'ed objects.  So, to be safe, memset
+	entire structure when it's freed, not just the pointer.
+	(umount_exported): bug fix to on-exit code.  Don't run
+	am_unmounted() unless unmount_mp() didn't run, since the latter
+	already calls am_unmounted().  This way we avoid a double-free
+	bug.
 
-	* doc/am-utils.texi (-F Option), amd/amd.8: mention that amd.conf
-	file specified by -F is always processed last.
+2005-03-15  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/amd.c (daemon_mode): do not fclose(stdout) so that the fd
-	won't be reused.  Allows startup script to redirect stdout.  Patch
-	from Donald Buczek <buczek@MPIMG-Berlin-Dahlem.MPG.DE>.
+	* tasks: updates.  Executable maps is supported.  NFSv4 and
+	FreeBSD autofs isn't.
 
-	* libamu/xutil.c (switch_to_logfile): compare logfile name and
-	syslog string with correct length.  Patch from Donald Buczek
-	<buczek@MPIMG-Berlin-Dahlem.MPG.DE>.
+	* Makefile.am (EXTRA_DIST): include FAQ in distro.
 
-	* amd/restart.c (restart): correctly inherit existing NFS V.3
-	mounts upon restart.  Patch from Donald Buczek
-	<buczek@MPIMG-Berlin-Dahlem.MPG.DE>.
+	* doc/Makefile.am (alldocs): install README.lda and README.osx.
 
-Sat Apr 18 19:01:19 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* FAQ: new file, better late than never.
 
-	* using libtool 1.2 and automake 1.3 (with my patches).
+2005-03-14  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/opt_am_cflags.m4, */Makefile.in: rename AM_CFLAGS to
-	AMU_CFLAGS to avoid conflicts with automake-1.3.
+	* scripts/amd2ldif.in: patch to add the amdMapName attribute to
+	the amdMapTimestamp object when amd2ldif converts it.  This is
+	necessary if you are using type:=auto mounts and want those
+	mountmaps looked up through LDAP.  Patch from Jim Zajkowski
+	<jim.zajkowski@gmail.com>.
 
-Sun Apr  5 23:09:08 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-03-12  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* converted to using libtool-1.2.
+	* minor new ports: i386-pc-linux-rhel4.
 
-Tue Mar 10 16:52:09 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* minor new ports: powerpc-apple-darwin7.8.0.
 
-	* fsinfo/fsi_analyze.c (fixup_required_mount_info): replaced silly
-	for loop (ITER) which used to run only to initialize the variable
-	dd once and then break; with a simple assignment.
+2005-03-10  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* hlfsd/hlfsd.h: cleanup so it compiles with Solaris
-	/opt/SUNWspro/bin/cc, and use gid_t not int.
+	* amd/ops_nfs.c (prime_nfs_fhandle_cache): rearrange code so it's
+	cleaner.
 
-	* amd/mapc.c (mapc_sync): don't dereference pointer (so it
-	compiles with Solaris /opt/SUNWspro/bin/cc)
+	* ltmain.sh: upgrade from libtool-1.5.6.
 
-Sun Mar  8 15:54:22 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/check_{fs_mntent,mnttab_type,mount_type}.m4: check for
+	Linux 2.6 kernel modules, which have a .ko extension, not .o.  Now
+	we can properly detect which file systems exist on Linux 2.6 based
+	systems (SLES9, RHEL4, Fedora, etc.).
 
-	* aux/config.{guess,sub}: used from gcc-2.8.1.
+2005-03-09  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Sat Mar  7 15:33:27 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/host_macros.m4: find out what's the OS software
+	distribution name, if any.
 
-	* released snapshot am-utils-6.0a16s9
+	* m4/macros/header_templates.m4: template for DISTRO_NAME.
 
-	* INSTALL, doc/am-utils.texi (Supported Platforms): updated names
-	based on new output of new config.guess.
+	* amd/get_args.c (get_version_string): print again full_os, os,
+	osver, and vendor (bug fix).
+	(get_version_string): print distribution name, if known (e.g.,
+	rh9, suse8, etc.).
 
-	* aux/config.{sub,guess}: used newer versions from gcc-2.8.0.
+	* amd/mapc.c (mapc_showtypes): wrap around list of supported map.
 
-	* amd/amd.8,doc/am-utils.texi: document correct usage of default
-	/etc/amd.conf file.
+2005-03-08  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* fixmount/fixmount.c (inetresport,privsock): use some more
-	portable code from amq/amq.c.
+	* amd/map.c (umount_exported): when unmounting file systems on
+	exit (when amd.conf global unmount_on_exit=yes), use unmount_mp()
+	instead of unmount_node() because the latter always unmounts in
+	the foreground, whereas the former unmounts in the bg/fg as
+	needed.  Unmounting always in the foreground has two problems: (1)
+	if the unmount hangs, amd hangs, and (2) for type:=program, the
+	unmount script is execve'd(!) thus replacing the main amd process,
+	which never gets to finish up, leaving the amd mount points hung.
 
-	* amd/get_args.c (get_args): use default /etc/amd.conf file only
-	if no arguments had been passed to amd.
+	* NEWS: mention new feature of executable maps.
 
-	* fixmount/fixmount.c (clnt_create_timeout): use tli/socket code
-	ala amq/amq.c so that fixmount will work on both types of systems.
+	* AUTHORS: Acknowledge Erik Kline.
 
-	* amq/amq.c (main): do no close tcp socket before running udp try,
-	because we're not sure if it was opened at all.
+	* scripts/amd.conf.5: document executable maps and
+	exec_map_timeout parameter.
 
-	* mips-dec-ultrix* port merged in and cleaned up.
+	* scripts/amd.conf-sample: examples of an executable map and
+	exec_map_timeout.
 
-	* aux/configure.in: up minor shared library revision number, since
-	it has changed enough.
+	* m4/macros/header_templates.m4: template for HAVE_MAP_EXEC.
 
-	* hlfsd/hlfsd.c (main): don't check for overlay mount option here,
-	as it is now done in compute_nfs_args().  Remove ultrix specific
-	code also because it was moved to compute_nfs_args().
+	* doc/am-utils.texi: document Executable maps and exec_map_timeout
+	parameter.
 
-	* conf/mount/mount_svr4.c: removed DEBUG_MOUNT_SVR4 code, now that
-	we have more generic code in print_nfs_args().
+	* amd/conf.c (gopt_exec_map_timeout): function to parse
+	exec_map_timeout [global] parameter.
 
-	* libamu/mount_fs.c (print_nfs_args): print maxlen of
-	nfs_args.addr, and also syncaddr (which is mostly NULL).  Print
-	struct knetconfig from nfs_args->knconf.
+	* amd/amd.h (AMFS_EXEC_MAP_TIMEOUT): define default executable map
+	timeout to 10 seconds, and a global placeholder for the
+	configurable value.
 
-	* aux/macros/mount_headers.m4 (define): do not check for ufs/cdfs
-	headers here, but in try_compile_anyfs.m4.
+	* amd/amd.c (init_global_options): initialize default executable
+	map timeout.
 
-	* aux/macros/type_ufs_args.m4: move test for struct ufs_specific
-	(for ultrix) here from its own macro.
+	* amd/Makefile.am (EXTRA_amd_SOURCES): include info_exec.c in
+	tarball.
 
-	* aux/macros/type_cdfs_args.m4: move test for struct iso_specific
-	(for ultrix) here from its own macro.
+	* configure.in: enable executable maps.
 
-	* amd/ops_nfs.c (mount_nfs_fh): no need to run code again checking
-	for overlay mount option.  Remove code which checks for overlay
-	option, as it is now done in compute_nfs_args().
+	* amd/mapc.c: define executable map functions and behavior.
 
-	* libamu/mount_fs.c (compute_mount_flags): move here code which
-	checks for overlay mount option which was in amd/amfs_toplvl.c:
-	mount_amfs_toplvl().
+	* amd/info_exec.c: executable map implementation from Erik Kline
+	<ekline at ekline dot com>, modified, cleaned-up, and fixed.
 
-Wed Feb  7 15:35:51 1998  Rainer Orth  <ro@xayide.TechFak.Uni-Bielefeld.DE>
+2005-03-07  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* The following are Rainer's ChangeLog entries for his ultrix
-	port, added manually. -Erez.
+	* amd/info_file.c (file_init_or_mtime): consolidate identical
+	file_init and file_mtime into one function.
 
-	* merged Ultrix port with am-utils 6.0 a16s5: amd/ops_afs.c
-	(mount_toplvl) -> amd/amfs_toplvl.c (mount_amfs_toplvl)
+2005-03-05  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* include/am_defs.h: include cdfs specific mount headers
-	avoid duplication definition of gt_names[] in <sys/fs_types.h> (Ultrix)
+	* doc/am-utils.texi (Program Filesystem): if umount/unmount are
+	not specified, Amd uses "umount ${fs}" by default.
 
-	* include/am_compat.h: define several mount options corresponding
-	to mount flags: pgthresh, hard (nfs), defperm, nodefperm,
-	noversion, rrip (cdfs), nocache, quota, sync (generic) removed
-	duplicate MNTTAB_OPT_RO definition
+	* amd/amfs_program.c (amfs_program_match): if neither unmount nor
+	umount parameters are specified, use the default userland umount
+	program with "umount ${fs}".  This way type:=program doesn't have
+	to specify the umount program for basic unmounting actions.
+	(amfs_program_init): save unmount program string in mf_private
+	only if it's NULL, not based on mf_refc.
 
-	* aux/macros/try_compile_anyfs.m4: include Ultrix specific
-	ufs/cdfs mount headers
+	* configure.in: auto-detect name of userland unmount program.
 
-	* aux/macros/mount_headers.m4: include several Ultrix/Digital UNIX
-	specific mount headers
+	* aux_conf.h.in (UNMOUNT_PROGRAM): macro for default userland
+	unmount program.
 
-	* aux/macros/check_{fs_mntent, mount_type}.m4: check for GT_*
-	mount types in mount headers (Ultrix)
+	* amd/ops_cachefs.c (cachefs_init): save unmount program string in
+	mf_private only if it's NULL, not based on mf_refc.
 
-	* aux/configure.in: Ultrix/Digital UNIX specific checks: new
-	headers, mount structures and fields, filesystem and mount types,
-	mount flags
+	* configure.in: don't "discover" inheritance file system any more,
+	since we don't have the .c file for it.
 
-	* aux/acconfig.h: placeholders for new mount options: quota
-	(generic), ro (nfs), defperm, nodefperm, noversion, rrip (cdfs)
-	cdfs, nfs, ufs mount structure fields new ufs, cdfs mount
-	structures
+	* amd/get_args.c (get_version_string): hack to still show that we
+	support the inherit file system in output of amd -v.
 
-	* amd/ops_ufs.c (mount_ufs): Ultrix stores generic mount flags in
-	ufs_args.ufs_flags and has ufs specific pgthresh option
+2005-03-05  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* amd/ops_cdfs.c (mount_cdfs): handle Ultrix/Digital UNIX specific
-	CDFS mount flags and options
+	* amd/amfs_inherit.c: removed, dead code
 
-	* amd/ops_afs.c (mount_toplvl), amd/ops_nfs.c (mount_nfs_fh),
-	hlfsd/hlfsd.c (main): store generic mount flags in
-	nfs_args.gfs_flags, handle separate NFS ro flag
+	* amd/Makefile.am,
+	amd/am_ops.c,
+	amd/amd.h,
+	conf/autofs/autofs_linux.h,
+	conf/autofs/autofs_solaris_v1.h,
+	conf/autofs/autofs_solaris_v2_v3.h,
+	m4/macros/header_templates.m4: removed references to amfs_inherit.c
 
-	* aux/macros/{check_mnt2_cdfs_opt, struct_iso_specific,
-	struct_ufs_specific}.m4: new files; check for Ultrix specific
-	mount structures
+2005-03-05  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/trap/trap_ultrix.h: arg 3 to mount(2) is rwflag
+	* amd/autil.c (am_mounted): completely rewrite the unmount
+	no/timeout code to (1) make more sense for odd conditions, and (2)
+	allow utimeout=N mount options to override FS_NOTIMEOUT default
+	flags for disk-based file systems such as ufs, pcfs, cdfs, etc.
 
-	* aux/macros/type_auth_create_gidlist.m4 (ultrix*):
-	AUTH_CREATE_GIDLIST_TYPE is int (not short == gid_t) from a
-	comment in <rpc/auth.h>
+	* libamu/mount_fs.c (mount_fs): use safer XFREE() not free().
 
-	* include/am_defs.h: #define KERNEL to avoid definition of
-	gt_names[]
-	conf/mtab/mtab_ultrix.c: #include <sys/fs_types> before <config.h>
-	to force single definition here
+	* conf/umount/umount_linux.c (umount_fs): strtok is destructive,
+	so use strdup'ed string.
 
-	* libamu/mount_fs.c (compute_nfs_args): Ultrix support for
-	nfs_args.gfs_flags moved to callers
-	store mount options in nap->optstr
+	* conf/mount/mount_linux.c (parse_opts): strtok is destructive, so
+	use strdup'ed string.
 
-	* include/am_defs.h: fix _am_mntent mnt_{type, opts} field
-	descriptions
+2005-03-04  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/mount_headers.m4, aux/macros/try_compile_nfs.m4:
-	include <rpc/rpc.h> before AMU_NFS_PROTOCOL_HEADER for svc_req
-	definition in prototypes
+	* scripts/amd.conf.5, doc/am-utils.texi (cache_duration
+	Parameter): clarify actual behavior: this Parameter affects
+	initial mount timeout as well as the linear backoff what happens
+	the initial failed EBUSY unmount.
 
-	* aux/macros/mount_headers.m4: include <sys/errno.h> before
-	AMU_NFS_PROTOCOL_HEADER: <nfs/nfs.h> needs it for NFSERR_*
-	definitions
+	* doc/am-utils.texi (opts Option): better explanation of
+	utimeout=N mount pseudo-option.
 
-	* conf/nfs_prot/nfs_prot_ultrix.h: new file
+	* amd/amd.h (AM_TTL, AM_TTL_W): better comments, minor cleanup.
 
-	* aux/macros/check_nfs_prot_headers.m4: use nfs_prot_ultrix.h
+2005-03-02  Daniel P. Ottavio  <dottavio@ic.sunysb.edu>
 
-	* aux/macros/mount_headers.m4, aux/macros/try_compile_nfs.m4,
-	aux/macros/try_compile_rpc.m4, include/am_defs.h: avoid multiple
-	inclusion of <rpc/xdr.h>
+	* AUTHORS: add Dan Ottavio.
 
-Sat Mar  7 13:56:05 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* scripts/amd.conf.5: document new debug_mtab_file option.
 
-	* aux/configure.in: save state of config.cache and confdefs.h
-	(as dbgcf.h) at various points of the configure.
+	* scripts/amd.conf-sample (debug_mtab_file): show example.
 
-	* aux/macros/save_state.m4: new macro to save state of configure,
-	esp. useful in long ones.  Saves confdefs.h and write $ac_cv_*
-	cache variables that are known so far.
+	* doc/am-utils.texi (debug_mtab_file Parameter): document new
+	option.
 
-	* released snapshot am-utils-6.0a16s8
+	* conf/mtab/mtab_{file,mach3}.c (open_locked_mtab): if mtab file
+	doesn't exist by the time Amd tries to exist, return a 0 rather
+	than hang indefinitely.
+
+	* amd/conf.c (gopt_debug_mtab_file): new function to parse
+	debug_mtab_file option.
 
-1998-03-06  Erez Zadok  <ezk@mercer.psl.cs.columbia.edu>
+	* amd/amd.h: placeholder for debug_mtab_file string.
+	Define default debug_mtab_file to "/tmp/mtab".
 
-	* fsinfo/fsi_lex.l,amd/conf_tok.l: define ECHO after undefining
-	it, but only for flex.
+	* NEWS: document new debug_mtab_file option.
 
-Fri Mar  6 17:23:17 1998  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
+2005-03-02  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* hlfsd/homedir.c (plt_print): change pathname of hlfsd dump file
-	to /usr/tmp/hlfsd.dump.XXXXXX, and use a safe method (if possible)
-	to write the dump file.
+	* conf/transp/transp_{sockets,tli}.c (amu_get_myaddress): when
+	users want Amd's NFS service to bind to some arbitrary "localhost"
+	address, show which address was actually resolved and bound to.
 
-	* doc/am-utils.texi,amd/opts.c: rename all references to nomadic
-	functions to boolean functions, which is what they really are.
+2005-03-01  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/configure.in: don't look for strcasecmp in libucb at all,
-	but rather complete it from libamu/strcasecmp.c as needed.
+	* amd/srvr_nfs.c (start_nfs_pings): move code from elsewhere
+	(update_nfs_pingval) that initializes the pinger, as well as turns
+	it on/off as needed, and handles changing its value.  This is to
+	avoid races and other infinite-loop conditions that could result
+	in ping storms.
 
-Fri Mar  6 03:29:20 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/srvr_amfs_auto.c (amfs_generic_find_srvr): when creating a
+	new file server structure, default the ping value to AM_PINGER
+	(30sec) and set the FSF_PING_UNINIT flag.
 
-	* conf/nfs_prot/nfs_prot_osf4.h: avoid conflicts with Irix's EFS.
+	* amd/amd.h (FSF_PING_UNINIT): new flag to tell whether the NFS
+	pinger had been initialized for a given file server.
 
-	* libamu/wire.c (getwire): fix for 0.0.0.0 loopback on SunOS 3.X
-	which defines IFF_ROUTE instead of IFF_LOOPBACK.  Patch from Tom
-	Schmidt <tschmidt@micron.com>.
+	* scripts/ctl-amd.in (stop): no need to check if
+	/var/lock/subsys/amd file exists if you do an rm -f afterward.
+	Ensure that proper return value is returned from script.
 
-	* released snapshot am-utils-6.0a16s7
+	* NEWS, doc/am-utils.texi (opts Option): update meaning of ping=N
+	so that if N=-1, pings are off; if N=0, pings are set to the
+	default value (currently 30 seconds).
 
-	* conf/nfs_prot/nfs_prot_hpux11.h: a first working port of amd to
-	hppa1.0-hp-hpux11.00.tgz.
+2005-02-28  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Thu Mar  5 21:59:03 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/nfs_prot_svc.c (nfs_program_2): on TLI system, try to call
+	__rpc_get_local_uid to verify if the RPC call through the
+	local host interface came from UID 0.
 
-	* converted all sources to use mntent field names, and map mnttab
-	field names to mntent's.
+	* configure.in: look for internal libnsl function
+	__rpc_get_local_uid (seems to be available on all known TLI
+	systems, Solaris and HP-UX 11).
 
-	* include/am_defs.h (mnt_special): map struct mnttab field names
-	to struct mntent field names.
+	* conf/transp/transp_tli.c (amu_svc_getcaller): unnecessary
+	function for TLI systems (and it violated a array's bounds,
+	discovered with libumem.so).
+	(bind_resv_port, bind_resv_port_only_udp, get_autofs_address):
+	just to be on the safe side, set struct t_bind's qlen field to non
+	zero (64 by default).  This value cannot be zero for TCP
+	connections, and it's unclear if it's good to have it zero for UDP
+	connections, so setting it to 64 is safer.
 
-	* aux/macros/check_mount_trap.m4: hpux11's mount trap style is
-	identical to svr4/solaris2.
+2005-02-27  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/check_mount_style.m4: hpux11's mount style is
-	identical to svr4/solaris2.
+	* doc/am-utils.texi (opts Option, Keep-alives): update text on
+	ping option.
 
-	* aux/macros/check_network_transport_type.m4: hpux11 is a TLI
-	system!
+	* amd/srvr_nfs.c (update_nfs_pingval): new function to update NFS
+	server ping values, turn them off, or re-enable them.
+	(find_nfs_srvr): call update_nfs_pingval() as needed.
 
-	* aux/macros/check_nfs_sa_dref.m4: hpux11's NFS host address
-	dereferencing style is same as svr4.
+	* hlfsd/hlfsd.c (reaper, cleanup): don't use exit(3) in a signal
+	handler, but use _exit(2) instead.
 
-	* aux/macros/check_nfs_fh_dref.m4: hpux11's NFS file fh
-	dereferencing style is same as svr4.
+	* amd/amd.c (parent_exit): This signal handler is called during
+	Amd initialization.  The parent forks a child to do all the hard
+	automounting work, and waits for a SIGQUIT signal from the child.
+	When the parent gets the signal it's supposed to call this handler
+	and exit(3), thus completing the daemonizing process.  Alas, on
+	some systems, especially Linux 2.4/2.6 with Glibc, exit(3) doesn't
+	always terminate the parent process.  Worse, the parent process
+	now refuses to accept any more SIGQUIT signals -- they are
+	blocked.  What's really annoying is that this doesn't happen all
+	the time, suggesting a race condition somewhere.
+	(This happens even if I change the logic to use another signal.)
+	I traced this to something which exit(3) does in addition to
+	exiting the process, probably some atexit() stuff or other
+	side-effects related to signal handling.  Either way, since at
+	this stage the parent process just needs to terminate, I'm simply
+	calling _exit(2).  Note also that the OpenGroup doesn't list
+	exit(3) as a recommended "Base Interface" but they do list
+	_exit(2) as one.  This fix seems to work reliably all the time.
 
-	* conf/transp/transp_tli.c (create_nfs_service): if failed to
-	getnetconfigent() of ticlts, then try udp (hpux11).
+	* scripts/wait4amd2die.in: change default to recognize that amd is
+	down more quickly (check every 3 seconds instead of 5).
 
-	* conf/nfs_prot/nfs_prot_hpux11.h: added correct definitions for
-	struct nfs_args, nfs_fh, and NFSMNT_* flags, taken from solaris
-	2.5.1 (HP used them).
+2005-02-26  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/rpc_fwd.c (fwd_init): don't use O_NDELAY for t_open()
-	because hpux11 doesn't like it. if t_open failed, print error
-	based on t_errlist, not sys_errlist.
+	* libamu/xutil.c (amu_release_controlling_tty): warn if closing
+	stdin/stdout/stderr failed.  No need for tempfd.
 
-Wed Mar  4 22:01:55 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* scripts/ctl-{amd,hlfsd}.in: before running any real program in
+	these shell scripts, chdir to "/" to avoid possible hangs with
+	existing NFS mounts.  This was causing ctl-amd's forked
+	grand-child amd process to hang if restartable_mounts=no.  Go
+	figure.
 
-	* doc/am-utils.texi: lots of documentation fixes from Rainer Orth
-	<ro@TechFak.Uni-Bielefeld.DE>.
+2005-02-25  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Sat Feb 28 22:16:35 1998  Erez Zadok  <ezk@kosh.cs.columbia.edu>
+	* minor new port ia64-unknown-linux-rhel4
 
-	* fsinfo/fsi_lex.l: undefine ECHO again, so it doesn't get used
-	later.
+	* fsinfo/fsi_util.c (set_ether_if): avoid u_long casting to -1
+	(RHEL4 gcc 3.4.3 ia64 compiler complains).
 
-	* include/am_defs.h: defined the extern for ualarm() if it isn't
-	found, regardless if the function isn't found in standard
-	libraries, because otherwise libamu will include it.
+2005-02-24  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1998-02-28  Erez Zadok (per Ron Snyder)  <ezk@short.cvo.roguewave.com>
+	* minor new port i386-unknown-freebsd6.0 (6.0-CURRENT-SNAP001).
 
-	* initial port to hpux-11 completed.  Compiles cleanly, but
-	probably does not work, because of missing NFS V.2/3 headers.
+2005-02-23  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/conf_tok.l: cast yytext to char* when passed to strlen and
-	strdup, for hpux-11's ansi-cc compiler.
+	* minor new port: i386-pc-linux-rhel3.
 
-	* include/am_utils.h: renamed all xfree() to XFREE() to avoid
-	conflict with hpux-11's system headers.  Also move (voidp) cast
-	from sources to inside the macro itself.
+	* INSTALL: major update of the compatibility list.
 
-Sat Feb 28 13:44:21 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/os_cflags.m4: set AMU_CFLAGS not AM_CFLAGS.
 
-	* released snapshot am-utils-6.0a16s6
+2005-02-22  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/info_nis.c (nis_isup): new function to test if NIS is up
-	without hanging amd.  Used to ensure that amd does not clear the
-	maps when the expiration period arrived, if the service is down.
-	Otherwise it would be left with empty maps.  It is better to stay
-	with possibly old information than none at all.
+	* scripts/amd.conf.5, doc/am-utils.texi (preferred_amq_port):
+	document new preferred_amq_port [global] option.
 
-	* amd/mapc.c (mapc_sync): check to see if map service is up.
+	* scripts/amd.conf-sample (preferred_amq_port): example.
 
-Tue Feb 24 02:19:42 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* include/am_utils.h: add preferred_amq_port to prototype.
 
-	* aux/macros/check_lib2.m4 (AC_CHECK_LIB2): fix macro so it
-	includes auxiliary library only if needed.
+	* conf/transp/transp_tli.c (bind_preferred_amq_port): new function
+	to bind the Amq RPC service for UDP and TCP to a preferred port
+	(or to any port if preferred_amq_port==0).
+	(create_amq_service): decide if to bind to RPC_ANYFD, or to a
+	requested port.
 
-1998-02-22  Erez Zadok  <ezk@mercer.psl.cs.columbia.edu>
+	* conf/transp/transp_sockets.c (create_amq_service): if
+	preferred_amq_port is greater than 0, then bind to that port for
+	both UDP and TCP.  If preferred_amq_port==0, then bind to any
+	port.
 
-	* amd/conf_tok.l: undefine ECHO again, so it doesn't get used
-	later.
+	* amd/nfs_start.c (mount_automounter): pass global
+	preferred_amq_port value to create_amq_service().
 
-Sun Feb 22 01:41:08 1998  Erez Zadok  <ezk@zen.cs.columbia.edu>
+	* amd/conf.c (gopt_preferred_amq_port): new function to parse
+	amd.conf value for preferred_amq_port.
 
-	* conf/nfs_prot/nfs_prot_osf2.h: port to alpha-dec-osf2.1
-	completed.
+	* amd/amd.h: placeholder for preferred_amq_port.
 
-	* conf/mtab/mtab_osf.c (mnt_dup): not all OSF have NFS3.
+2005-02-21  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Sat Feb 21 19:45:48 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/transp/transp_tli.c (bind_resv_port_only_udp): rename old
+	bindnfs_port to a more proper name.  This function binds the NFS
+	service to a specified port, and only for UDP.
 
-	* doc/am-utils.texi (Network Host Filesystem): correct example for
-	type:=host map.
+	* conf/transp/transp_tli.c: cleanup some code, rename some
+	functions, in preparation for RPC amq port specification code.
 
-	* aux/macros/os_cflags.m4: only osf4 should compile with
-	-D_SOCKADDR_LEN.
+2005-02-19  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/check_nfs_prot_headers.m4: distinguish between OSF2
-	and OSF4.
+	* */Makefile.am: don't redefine CFLAGS or LDFLAGS; they are
+	reserved for users to pass them on the command line.  Instead, use
+	autoconf's internal AM_CFLAGS and AM_LDFLAGS.
 
-	* BUGS: include a new file listing known bugs.
+	* depcomp, install-sh, missing, mkinstalldirs: update from latest
+	versions of Automake 1.9.2.
 
-Sat Feb 21 03:50:48 1998  Erez Zadok  <ezk@mercer.psl.cs.columbia.edu>
+	* m4/macros/*.m4: properly quote AC_DEFUN'ed macro name, and fix
+	regexp/patsubst M4 commands.  Newer versions of autoconf (e.g.,
+	v2.59) complain about those.
 
-	* conf/nfs_prot/nfs_prot_linux.h: turn DES off on all linux
-	versions.
+2005-02-17  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/type_recvfrom_fromlen.m4: linux alpha should use
-	size_t for recvfrom fromlen arg.
+	* amd/opts.c (f_xhost): if we don't have hstrerror, just print the
+	value of h_errno.
 
-Sat Feb 21 03:33:59 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: include -lresolv if it defines the hstrerror()
+	function and not already available in existing libraries.
 
-	* scripts/ctl-hlfsd.in: turn -D fork so primary process never
-	hangs.
+	* minor new port: powerpc-apple-darwin7.7.0.
 
-Sat Feb 21 02:45:51 1998  Erez Zadok  <ezk@mercer.psl.cs.columbia.edu>
+	* amd/nfs_subr.c (mp_to_fh): pathlen should be u_int because it is
+	later compared against an unsigned quantity (complaint from gcc
+	3.3 on SuSE 8.2)
 
-	* include/am_defs.h: don't include <sys/stat.h> and
-	<linux/stat.h>, just remaining definitions in <statbuf.h>
+	* include/am_utils.h: remove unnecessary (and conflicting) extern
+	for bind_resv_port2(), which is declared as static in
+	transp_tli.c.
 
-Thu Jan 29 00:44:28 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* doc/am-utils.texi, scripts/amd.conf.5, scripts/amd.conf-sample,
+	NEWS: document four new amd.conf options: nfs_retry_interval_udp,
+	nfs_retransmit_counter_udp nfs_retry_interval_tcp, and
+	nfs_retransmit_counter_tcp.
 
-	* released snapshot am-utils-6.0a16s5
+	* amd/ops_nfs.c (mount_nfs_fh): set timeo/retrans values based on
+	wether nfs_proto was "udp" or "tcp".
 
-	* conf/mount/mount_irix6.c (mount_irix): pass {u,e,x}fs_args to
-	mount(2).
+	* amd/amfs_toplvl.c (amfs_toplvl_mount): set retrans/timeo values
+	from default UDP settings (because toplvl mounts are UDP for now).
 
-	* check for <sys/fs/xfs_clnt.h> and include it when needed.
+	* amd/get_args.c (get_args): use parameters to -t option to set
+	both UDP and TCP timeo/retrans values.
 
-	* conf/mount/{mount_irix5.c,mount_irix6.c} (mount_irix): recognize
-	efs and xfs separately from "ufs".
+	* amd/conf.c: (gopt_nfs_retransmit_counter_udp,
+	(gopt_nfs_retransmit_counter_tcp, gopt_nfs_retry_interval_udp
+	(gopt_nfs_retry_interval_tcp): new functions to parse UDP and TCP
+	retrans/timeo parameters separately.
+	(gopt_nfs_retry_interval, gopt_nfs_retransmit_counter): if
+	specified, use it to set defaults for both UDP and TCP.
 
-	* amd/{ops_xfs.c,ops_efs.c}: new support for irix xfs/efs.
+	* amd/amd.c (init_global_options): initialize default values of
+	both UDP and TCP retrans/timeo values to -1.
 
-	* aux/configure.in: look for irix efs and xfs file systems.
+	* amd/amd.h (AMU_TYPE_{TCP,UDP,MAX}): define separate retrans and
+	timeo values, one for udp mounts and another for tcp mounts.
 
-	* scripts/amd.conf.5: new unmount_on_exit option documented.
+2005-02-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* doc/am-utils.texi (unmount_on_exit): new option documented.
+	* README.osx: new file with some instructions for Mac OS-X users,
+	courtesy Kevin Layer.
 
-	* amd/conf.c (gopt_unmount_on_exit): new function to handle new
-	amd.conf option.
+	* amd/get_args.c (get_args): move call to switch_to_logfile()
+	after processing -v, so we don't print "no logfile defined; using
+	stderr" when we're about to print version info and exit anyway.
 
-	* amd/map.c (umount_exported): if global amd.conf flag
-	unmount_on_exit is on, then try to unmount all mounted (or
-	restartable) file systems.
+	* minor new port: powerpc-ibm-aix5.3.0.0.
 
-	* amd/amd.c: if print_pid option is on, then normally print it to
-	stdout.  If also pid_file is specified, then print the process ID
-	into that file.
+	* hlfsd/hlfsd.c (main): rewrite code to avoid negative array
+	references.
 
-	* amd/get_args.c (get_args): print correct -l option depending if
-	system supports syslog and/or syslog facilities.  Patch from 
-	Tom Schmidt <tschmidt@micron.com>.
+	* conf/checkmount/checkmount_aix.c: remove extern definition for
+	mntctl(), since AIX 5.3 has it in <sys/vmount.h>.
 
-	* doc/am-utils.texi (opts Option): updates for documentation for
-	new cdfs options defperm, nodefperm, noversion, rrip.
+	* amd/info_union.c (union_reload): rewrite code to avoid negative
+	array references.
 
-	* amd/ops_cdfs.c (mount_cdfs): support cdfs options defperm,
-	nodefperm, noversion, rrip.
+	* amd/opts.c (split_opts, expand_op): rewrite code to avoid
+	negative array references.
 
-	* conf/nfs_prot/nfs_prot_osf.h: need to look at <cdfs/cdfsmount.h>
-	on osf.
+	* conf/mtab/mtab_aix.c: remove extern definition for mntctl(),
+	since AIX 5.3 has it in <sys/vmount.h>.
 
-	* aux/macros/{expand_cpp_hex.m4, expand_cpp_int.m4,
-	expand_cpp_string.m4}: use #error to make failed compilations
-	fail faster, rather than have the program fail during a run.
+	* libamu/xutil.c (real_plog): rewrite code to avoid negative array
+	references.
 
-	* include/am_compat.h: added a few new cdfs options: rrip,
-	noversion, defperm, and nodefperm (used in OSF).
+	* libamu/wire.c (is_network_member): rearrange code slightly to
+	avoid negative array references (AIX 5.3 xlC 7.0 compiler
+	complains about it).
 
-Wed Jan 28 20:24:09 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+2005-01-26  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* released snapshot am-utils-6.0a16s4
+	* doc/am-utils.texi (xhost Selector Function): document new
+	selector function.
 
-	* doc/am-utils.texi (Global Parameters): update manual for new
-	amd.conf global variable hesiod_base.
+	* amd/opts.c (f_xhost): new function for use when matching the
+	"host" selector for the current host's name.  This function will
+	now match the primary host name as well as all known aliases
+	(CNAMES) that gethostbyname() returns.  This function now supports
+	a new function selector called xhost(ARG); the old host==ARG
+	selector is unharmed.
 
-	* scripts/amd.conf.5: update man page for new amd.conf global
-	variable hesiod_base.
+2005-01-17  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* amd/get_args.c (get_args): use /etc/amd.conf file if exists by
-	default, else try command line options.  Patch from Randall
-	S. Winchester <rsw@Glue.umd.edu>.
+	* NEWS: document the ability to restart old mount points
 
-Wed Jan 28 12:20:56 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/map.c (mount_auto_node): force the fileid of the
+	root to be 1, so that it won't change between restarts; use the
+	root filesystem's own methods instead of hard-coding the use of
+	the default methods
 
-	* amd/info_hesiod.c (hesiod_search), amd/conf.c
-	(gopt_hesiod_base), amd/amd.h, amd/amd.c (init_global_options):
-	included patch from Randall S. Winchester <rsw@Glue.umd.edu>, to
-	support a hesiod base name in the amd.conf file.
+	* conf/transp/transp_tli.c (create_nfs_service): better cleanup on
+	error conditions.
+	(bind_resv_port2): allow the caller to request a certain port.
 
-	* doc/am-utils.texi (pid_file Parameter): document new global
-	amd.conf parameter.
+	* conf/transp/transp_sockets.c (bind_resv_port): allow the caller
+	to request a certain port.
+	(create_nfs_service): better cleanup on error conditions.
 
-	* scripts/amd.conf.5: document new global option pid_file.
+	* amd/restart.c (restart_automounter_nodes): new function, takes
+	care of restarting automounter NFS mount points (autofs will come
+	later).
+	(restart): skip all automounter mount points.
 
-	* amd/amd.c (daemon_mode): if cannot open pid_file, continue to
-	run, but print error message.
+	* amd/nfs_subr.c (fh_to_mp3, mp_to_fh): new filehandle
+	implementation: if the path to the node is shorter than sizeof(fh)
+	chars (currently 32 chars for a NFSv2 fh), simply store it inside
+	the fh. For longer paths, keep the old implementation.
 
-	* amd/conf.c (gopt_pid_file), amd/amd.h, amd/amd.c (daemon_mode,
-	init_global_options): Included patch from Randall S. Winchester
-	<rsw@Glue.umd.edu>, to support pid files in the amd.conf file.
+	* amd/nfs_start.c (mount_automounter): reorder things so that
+	restarting the toplvl filesystems occurs before anything else (so
+	that we can grab all the ports we need before we accidentally use
+	them for something else).
 
-	* amd/get_args.c (get_args): correct usage info on amd -t.
+	* amd/mntfs.c (locate_mntfs): remove dead code; add special
+	handling of restarted toplvl filesystems.
 
-	* amd/*.c: massive file name and symbol name changes.  All amd
-	file systems files and symbols are prefix with amfs_*.  Now using
-	real name of file system: amfs_auto instead of afs, amfs_inherit
-	instead of ifs, amfs_linkx instead of sfsx, etc.  This will enable
-	clear distinction between amd file system and generic ones like
-	nfs/ufs/pcfs/hsfs.  Also, now we can implement true afs (Andrew
-	f/s) and DFS (Distributed f/s).
+	* amd/mapc.c (root_keyiter): fix up a comment.
 
-	* amd/amfs_union.c: unionfs for amd is always defined, no need to
-	#ifdef it.
+	* amd/map.c (path_to_exported_ap): new function, searches for and
+	returns a node by the path to it.
+	(get_root_nfs_fh): remove unnecessary fiddling with the root fh.
 
-Mon Jan 26 16:51:38 1998  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
+	* config.guess.long: support Red Hat Enterprise Linux
 
-	* libamu/mount_fs.c (compute_nfs_args): set 'noconn' NFS option on
-	or off, based on the particular quirks of the OS in question.
+2005-01-17  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/check_nfs_socket_connection.m4: new macro to set the
-	correct wait of handling un/connected NFS sockets.
+	* libamu/util.c (rmdirs): prevent amd from logging 'Read-only
+	filesystem' errors when the mount point has an ancestor (i.e. '/')
+	that is mounted read-only.  Patch from David Rage <rage@ucl.ac.uk>.
 
-	* scripts/wait4amd.in: use rlogin instead of rsh.
+2005-01-17  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* amd/am_ops.c (ops_showfstypes): when showing F/S types in amd
-	-v, always show "nfs3" for NFS V.3.
+	* conf/umount/umount_linux.c (umount_fs): Linux doesn't need the
+	autofs space hack
 
-1998-01-25  Erez Zadok  <ezk@snoopy.cs.columbia.edu>
+	* conf/umount/umount_default.c (umount_fs): there is no need for
+	HAVE_LOOP_DEV, now that Linux has its own dedicated umount_linux.c
 
-	* lots of small fixes for solaris 2.6, since gcc 2.8.0 -Wall gets
-	more picky than 2.7.2.3 did.
+2005-01-17  Erez Zadok  <ezk@cs.sunysb.edu>
 
-1998-01-24  Erez Zadok  <ezk@snoopy.cs.columbia.edu>
+	* doc/am-utils.texi (Automatic Unmounting): document new umount2()
+	behavior on Linux.
+
+	* conf/umount/umount_linux.c (umount_fs): new file.  On Linux, if
+	umount(2) failed with EIO or ESTALE, try umount2(2) with
+	MNT_FORCE+MNT_DETACH.  Based on patch from Christos Zoulas
+	<christos@zoulas.com>.
 
-	* include/am_utils.h (dlog): amuDebug macros reduced to shorter
-	forms.
+	* m4/macros/check_umount_style.m4: pick new linux umount style.
 
-Fri Jan 23 18:38:30 1998  Erez Zadok  <ezk@goat.mcl.cs.columbia.edu>
+	* Makefile.am (EXTRA_DIST_CONF): distribute new umount_linux.c
+	file.
 
-	* released snapshot am-utils-6.0a16s3
+2005-01-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* include/am_defs.h: on Solaris 2.6, <sys/varargs.h> is included
-	in <sys/fs/autofs.h> but since stdargs.h is used, and varargs.h
-	must not, fake a definition for varargs.
+	* conf/nfs_prot/nfs_prot_aix{4_2,4_3,5_1,5_2}.h,
+	m4/macros/struct_nfs_args.m4: minor cleanups for quicker execution
+	of "nfs_args" test.
 
-Fri Jan 16 10:16:40 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-01-13  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* README: show how to configure in additional support such as
-	hesiod using various --enable-* flags.
+	* amd/get_args.c (show_usage): separate function to print usage
+	string.
+	(get_args) Call show_usage() from get_args when needed, then exit.
 
-Wed Jan 14 15:13:02 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/get_args.c (get_version_string): print also domain, host,
+	and hostd.
+	(get_args): print version string at the very end, after all other
+	values had been initialized.  Patch from Christos Zoulas
+	<christos@zoulas.com>.
 
-	* aux/configure.in: look for strcasecmp(), and replace it if not
-	available.
+	* conf/transp/transp_sockets.c (check_pmap_up, get_nfs_version),
+	conf/transp/transp_tli.c (check_pmap_up): correct an inconsistency
+	in timeouts in the RPC code between socket and TLI
+	implementations.  The clntudp_create timeout has a different
+	meaning than the clnt_call timeout.  Set the timeout of the create
+	to 2 seconds which means retry if no answer in two seconds, and
+	the timeout call to 6 seconds, which will give us consistently 2
+	to 3 pings.  This is useful on occasional network UDP loss where a
+	single packet loss would wrongfully mark a server down.  (The TLI
+	code is the one that had the problem occurs.)  Patch from Christos
+	Zoulas <christos@zoulas.com>.
 
-	* amd/ops_nfsl.c (nfsl_match): host names should be compared using
-	case insensitive.
+	* libamu/mount_fs.c (compute_nfs_attrcache_flags): make sure code
+	compiles even for systems that don't have the nfs_args
+	ac{reg,dir}{min,max} fields.
+
+	* amd/amfs_toplvl.c (set_auto_attrcache_timeout): just to be safe,
+	add "noac" if amd.conf option auto_attrcache was set to 0.  This
+	should hopefully make the compute_nfs_attrcache_flags patch even
+	safer.
+
+	* libamu/mount_fs.c (compute_nfs_attrcache_flags): separate
+	function to compute attribute-cache values.  This function now
+	computes attribute-cache flags for BOTH Amd's automount points
+	(NFS) as well as any normal NFS mount that Amd performs.
+	(compute_nfs_args, compute_automounter_nfs_args): call
+	compute_nfs_attrcache_flags to figure out attribute-cache related
+	flags.  Patch from Christos Zoulas <christos@zoulas.com>.
+
+	* scripts/amd.conf-sample: show examples of new global options
+	domain_strip and auto_attrcache.
 
-	* amd/opts.c: for each map variable, define if the comparison
-	needs to be done case insensitive.
+	* scripts/amd.conf.5: document new global options domain_strip and
+	auto_attrcache.  Add warning to auto_attrcache use in case of
+	ESTALE.
 
-	* include/am_utils.h (STRCEQ): a new macro to use strcasecmp().
-	Patch from Thomas Richter <richter@chemie.fu-berlin.de>
+	* doc/am-utils.texi: minor cleanups and document new global
+	options domain_strip and auto_attrcache.  Add warning to
+	auto_attrcache use in case of ESTALE.
 
-1998-01-14  Erez Zadok  <ezk@irt.cs.columbia.edu>
+	* amd/conf.c (gopt_auto_attrcache): parse new global amd.conf
+	option auto_attrcache.
+	(gopt_domain_strip): parse new global amd.conf option
+	domain_strip.  Part of a patch from Christos Zoulas
+	<christos@zoulas.com>.
+
+	* amd/autil.c (host_normalize): don't call domain_strip()
+	unconditionally, but depend on the new global amd.conf flag
+	domain_strip.
+
+	* amd/amfs_toplvl.c (set_auto_attrcache_timeout): new function to
+	set attribute cache timeout value given other configured global
+	defaults.
+	(amfs_toplvl_mount): set automount point attribute cache option
+	value to "noac" if attrcache=0, else set it to whatever
+	set_auto_attrcache_timeout() returns.
+
+	* amd/amd.h (CFM_DOMAIN_STRIP, CFM_DEFAULT_FLAGS): flag to decide
+	if to strip the domain from the host name or not, default options
+	set to strip the domain.
+	Store global value of automount attribute cache timeout value.
+
+	* amd/amd.c (init_global_options): add flag to record automount
+	point attribute cache value.
+
+	* amd/amd.c (do_memory_locking): new function to encapsulate all
+	of the memory-locking functionality, which was in main() before.
+	Also added a call to madvise(), just in case.
+	(main): call do_memory_locking() to pin process memory if amd.conf
+	asked for it, but do so after the main Amd process daemonizes,
+	because mlock/mlockall is not inherited by fork() by default.
+	Slightly restructured patch from Jonathan Chen
+	<jon+amd@spock.org>.
+
+	* configure.in: check for madvise(2).
+
+	* config.guess, config.sub: updates for latest official GNU
+	versions.
 
-	* aux/configure.in: look for "isofs" as a possible mount type for
-	cdfs (RedHat Linux).
+	* m4/GNUmakefile: update paths to "make update"
 
-Wed Jan 14 02:07:05 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2005-01-12  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/mount/mount_linux.c (parse_opts): don't look for cdfs mount
-	type if not defined.
+	* conf/nfs_prot/nfs_prot_hpux11.h: define an nfs_fh3 structure
+	that's compatible for HPUX11 as well as NFSv3.
 
-	* conf/nfs_prot/nfs_prot_linux.h: don't define __FD_* macros if
-	already defined.
+	* include/am_defs.h: On AIX 5.2, both <resolv.h> and
+	<arpa/nameser_compat.h> define MAXDNAME, if compiling with gcc
+	-D_USE_IRS (so that we get extern definitions for hstrerror() and
+	others).  So undef MAXDNAME before it gets redefined.
 
-	* aux/configure.in: look for ext2fs before ufs, b/c some linux
-	have both.
+	* include/am_defs.h: Solaris 10 (build 72) defines GROUP_OBJ in
+	<sys/acl.h>, which is included in many other header files.
+	<rpcsvc/nis.h> uses GROUP_OBJ inside enum zotypes.  So if you're
+	unlucky enough to include both headers, you get a compile error
+	because the two symbols conflict.  Temp hack: undefine acl.h's
+	GROUP_OBJ before including nis.h, because we don't need acl.h for
+	am-utils.
 
-Mon Jan 12 15:43:20 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* m4/macros/os_cflags.m4: turn -D_USE_IRS for AIX5+ so that
+	certain extern definitions of resolver functions become available.
 
-	* Makefile.am (snapshot): allow me to install snapshots into the
-	ftp directory.
+	* amd/opts.c (expand_op): use #define for expand_error string
+	because some compilers complain about the use of static const
+	char[] inside a varargs function.
 
-	* scripts/ctl-hlfsd.in: don't turn on -D mem by default.
+	* minor new port i386-unknown-netbsdelf1.6.2.
 
-	* amd/get_args.c (get_args): minor bug in output of amd -H.
+	* new port i386-unknown-netbsdelf2.0.
 
-Mon Jan 12 03:05:06 1998  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
+	* minor port i386-unknown-freebsd5.3.
 
-	*******************************************************************
-	*** Released am-utils-6.0a15					***
-	*******************************************************************
+	* libamu/mount_fs.c (compute_nfs_args): don't compare
+	nap->maxgrouplist against NULL but against 0 directly, because on
+	FreeBSD 4.3, NULL is defined is (void *)0 and gcc 3.4 complains
+	about a type mismatch.
 
-Sun Jan 11 15:06:34 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* minor port i386-pc-linux-fc3 (Fedora Core 3).
 
-	* amd/conf.c (*_browsable_dirs): allow specifying
-	browsable_dirs=full, which will print *all* entries (other than
-	/default), including  those with '*' and '/' characters.
+2005-01-11  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/info_file.c (MAX_LINE_LEN): up maximum readdir chain length
-	to 1500.
+	* hlfsd/hlfsd.c (main): use sigsuspend() over sigpause(), because
+	FC3 doesn't have proper extern definition for the defunct
+	sigpause().
 
-	* doc/am-utils.texi: fixed reversed documentation for NFS mount
-	options vers and proto.
+	* configure.in: look for sigsuspend().
 
-	* doc/Makefile.am (install-html): separate target just for
-	installing html files.  Another new target "alldocs" is just for
-	installing all files needed for the am-utils home page.
+2005-01-01  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* scripts/amd.conf-sample: updated example for log_file.
+	* updated copyright year to 2005 on all files.
 
-	* scripts/amd.conf.5: updated for new way to declare new syslog
-	facility in the log_file option.
+2004-11-29  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/amd.8: updated for new way to declare new syslog facility in
-	the -l option.
+	* scripts/amd.conf.5: Small fixes to typos in man page, from
+	Thomas Klausner <tk@giga.or.at>.
 
-	* libamu/xutil.c (get_syslog_facility): allow users to specify the
-	syslog facility as an appended string to the log device.  Ex. amd
-	-l syslog:local7 will use LOG_LOCAL7, while the older -l syslog
-	will use the default LOG_DAEMON facility.
+2004-10-22  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/get_args.c (get_args): updated new syntax for amd -l
-	syslog:facility.
+	* ldap.schema: add this file to distribution.
 
-Thu Jan  8 04:05:10 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2004-09-15  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/host_macros.m4: don't confuse sun3 (sparc) with sun3
-	(intel).
+	* doc/am-utils.texi: fix old URLs.
 
-	* libamu/wire.c (print_wires): bug fix.  Nullify output buffer
-	before appending to it, on systems with two or more network
-	interfaces.
+2004-09-01  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_sunos5_3.h: add missing definition for
-	the mntent for cachefs.
+	* conf/mtab/mtab_aix.c (read_mtab): avoid a race condition between
+	multiple calls to mntctl().  Patch suggested by Michael van Elst
+	<M.van.Elst@science-computing.de>.
 
-	* include/am_defs.h: external definition for strstr() should use
-	const for both arguments.
+2004-08-07  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/configure.in: add extern definitions for getwd() if missing.
+	* doc/am-utils.texi (Program Filesystem): document how to get
+	double slashes in Amd maps.
 
-	* include/am_defs.h: define the extern for strdup() even if the
-	function does not exist, for it will be filled in by
-	libamu/strdup.c
+	* amd/opts.c (normalize_slash): support escaped slashes, needed
+	for SMB mounts.  Use '\\\/\\\/' in a string to get a double slash.
 
-	* amq/pawd.c (cluster_server): don't use getccent() if the extern
-	for it isn't there.  On hpux 10.20, the function is in libc, but
-	<cluster.h> and struct cct_entry do not exist.
+2004-08-06  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/configure.in: check for an extern for getccent() b/c some
-	hpux systems don't have it (hpux 10.20).
+	* amd/amfs_program.c (amfs_program_match): bug fix.  Complain if
+	both opt_unmount and opt_umount are missing, not when just one of
+	them is missing.
 
-Wed Jan  7 00:09:19 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+2004-08-03  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* doc/am-utils.texi (Amq -T option): manual documentation updates
-	for new amq options -T/-U.
+	* amq/pawd.c (find_mt): recognize "linkx" type mounts.  Patch from
+	Hauke Fath <hauke@Espresso.Rhein-Neckar.DE>.  Support "nfsx" while
+	we're at it.
 
-	* amq/amq.8: updated man page for new amq options -T/-U.
+	* doc/am-utils.texi: mention bugzilla.  Fix broken URL HREF's.
 
-	* amq/amq.c: two new switches to amq. -U will contact amd using
-	UDP only.  -T will use TCP only.  Normally amq will try TCP and
-	if that failed, will try UDP.
+2004-08-02  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* doc/am-utils.texi (pawd): manual documentation for pawd.
+	* amq/pawd.c (find_mt): recognize "host" type mounts.  Patch from
+	Dan Nelson <dnelson@allantgroup.com>.
 
-	* amq/pawd.1: new man page for pawd.
+2004-07-30  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Tue Jan  6 04:21:59 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* doc/am-utils.texi, NEWS: minor typos fixed.
 
-	* amq/pawd.c: a new program, Print Automounter Working Directory,
-	to print the proper pathname of the cwd or any other pathname,
-	adjusted for automounter paths, while avoiding mount points.
+2004-07-30  Erez Zadok  <ezk@play.cs.columbia.edu>
 
-	* aux/macros/localconfig.m4: trivial support for am-utils
-	maintainers to adjust some of the configuration of am-utils after
-	it has been auto-configured by putting whatever definitions you
-	wish in a file called localconfig.h, located in the top build
-	directory (the same one where config.h is created for you).
+	* include/am_xdr_func.h: cannot have field-less structure; put a
+	dummy field in.
 
-	* doc/am-utils.texi (Caching Filesystem): updated documents for
-	cachefs file system.
+	* conf/autofs/autofs_solaris_v2_v3.c (xdr_autofs_rddirargs): cast
+	2nd arg of xdr_u_int to a u_int*, not int*.
+	(autofs_mount_2_req): don't use C++ // comments.
 
-	* amd/ops_cachefs.c: initial cachefs support, for solaris.
-	type:=cachefs, requires cachedir:=/cache/dir/name to be defined
-	and initialized with cfsadmin -c.  $rfs is backdir to be cached
-	from, and $fs is the local mount point of the cachefs.
+2004-07-30  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/mount/mount_svr4.c (mount_svr4): support mounting of
-	cachefs file systems.
+	* m4/macros/{try_compile_anyfs,check_field}.m4: include
+	<fs/msdosfs/msdosfsmount.h> if it exists.  Part of a set of
+	FreeBSD 5 patches from Martin Blapp <mb@imp.ch>.
 
-	* amd/ops_cdfs.c: cdfs should be named 'cdfs', not whatever the
-	mnttab type is.
+	* include/am_defs.h: include <fs/msdosfs/msdosfsmount.h> if it
+	exists.
 
-Mon Jan  5 23:22:49 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* amd/ops_pcfs.c (mount_pcfs): set pcfs_args_t.dirmask field to
+	0777 by default.
 
-	* amd/opts.c: added support for new variable $cachedir.
+	* configure.in: check for pcfs_args_t.dirmask field.  Check for
+	existence of <fs/msdosfs/msdosfsmount.h>, new on FreeBSD 5.
 
-	* include/am_utils.h: added opt_cachedir field to struct am_opts.
+2004-07-29  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Sat Jan  3 01:43:57 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* minor new port: i386-pc-linux-fc2 (Fedora Core 2).
 
-	* amd/ops_nfsl.c (nfsl_ffserver, nfsl_match): also check if the
-	local hostname does not match $rhost, and if so, also assume
-	type:=nfs.
+	* amd/info_ldap.c (amu_ldap_rebind): don't use ldap_enable_cache()
+	unless the function exists in libldap and the extern is in
+	<ldap.h>.  Recently, openldap removed the extern from ldap.h, but
+	left the function in libldap, for binary compatibility; however
+	ldap_enable_cache and related functions have been deprecated (and
+	no longer listed in the header files), and therefore should be
+	avoided.
 
-Fri Jan  2 01:00:40 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* m4/macros/check_extern_ldap.m4: new macro to check for
+	LDAP-specific externs.  This is separate from check_extern.m4 so
+	as to avoid breaking the general-purpose macro with LDAP-specific
+	headers.
 
-	* updated all source files to add 1998 as a copyright year.
+	* m4/macros/header_templates.m4: extern template for new
+	HAVE_EXTERN_LDAP_ENABLE_CACHE.
 
-	* amd/ops_nfsl.c: new amd meta file system "type:=nfsl".  Behaves
-	like type:=linkx if the pathname denoted by $fs exists, and like
-	type:=nfs if it does not.  A convenient shortcut for the most
-	popular amd map entry.
+	* configure.in: call new check_extern_ldap.m4 macro.
 
-	* amd/amd.c (main): amd should chdir to / before starting, to
-	avoid hanging on other NFS server if started elsewhere.
+	* Makefile.am (EXTRA_DIST_M4): distribute new check_extern_ldap.m4
+	macro.
 
-	* amd/ops_TEMPLATE.c: added an empty template file for developers
-	who wish to write new amd pseudo file systems.
+	* config.guess.long: distinguish between redhat and fedora-core
+	releases.
 
-Thu Jan  1 00:27:28 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2004-07-23  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* hlfsd/homedir.c (plt_init): make function exported, to save on
-	the unnecessary init_homedir() function which was removed.
-	(table_add): don't use xmalloc() when you can use strdup()
-	instead.
+	* Minor new port i386-pc-linux-suse8.2: minor new port to SuSE
+	8.2.  This systems' latest GCC (gcc version 3.3 20030226
+	prerelease) correctly caught a lot of possibly bad comparisons
+	between signed and unsigned quantities.
 
-Thu Jan  1 00:15:58 1998  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
+	* hlfsd/homedir.c (table_add, plt_search): changed first arg of
+	both functions to u_int.
 
-	* hlfsd/homedir.c (hlfsd_endpwent): Don't actually run this
-	because we will be making more passwd calls afterwards.  On
-	Solaris 2.5.1, making getpwent() calls after calling endpwent()
-	results in a memory leak! (and no, even Purify didn't detect
-	it...)
+	* hlfsd/hlfsd.h, hlfsd/hlfsd.c: change 'cache_interval' to u_int.
+	Changed proto for plt_search arg to u_int.
 
-Tue Dec 23 18:23:47 1997  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
+	* amq/amq.c (show_mi, main): change 'i' to u_int.
 
-	* hlfsd/hlfsd.c (main): Bug fix.  Don't try to free() an
-	automatically allocated address.
+	* amq/pawd.c (find_mlp): change 'i' to u_int.
 
-	* amd/ops_afs.c (mount_toplvl): Bug fix.  Don't try to free() an
-	automatically allocated address.
+	* amd/srvr_nfs.c (find_nfs_srvr): change proto_nfs_version to
+	u_int.
 
-	* ALL SOURCES: change every direct call to free() to xfree(), so
-	it can be mapped to the right debugging function as needed.
+	* amd/amd.h: change prototype of vreaddir and amfs_error_readdir
+	to use u_int count parameter.
 
-	* include/am_utils.h: new free() policy.  If debugging memory,
-	call dxfree(), which will print the file name and line number
-	where the free occurred and the pointer address.  if only regular
-	debugging, then free() and reset  the pointer to NULL so it cannot
-	be used afterwards inadvertently.  If not DEBUG at all, then just
-	run free().  Three different #define macros set the right mapping.
+	* amd/ops_TEMPLATE.c (foofs_readdir), amd/amfs_error.c
+	(amfs_error_readdir): change 'count' parameter in proto to u_int.
 
-	* libamu/xutil.c (dxfree): renamed function to dxfree(), so it can
-	be called only when debugging the memory.
+	* amd/amd.h: change proto of amfs_generic_readdir() to use u_int
+	count parameter.
 
-Tue Dec 23 04:24:28 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/readdir.c (make_entry_chain): preflen should be u_int.
+	(amfs_readdir_browsable): change 'count' to u_int.
+	(amfs_generic_readdir): change 'count' to u_int.
 
-	* wire-test/wire-test.c (main): use xmalloc() not malloc().
+	* amd/amd.h: amu_global_options's portmap_program field should be
+	u_long, not int (to match RPC conventions).  Change am_fh's
+	fhh_gen field to u_int, to match am_gen field in struct am_node.
 
-	* conf/transp/transp_tli.c (get_knetconfig): use xzalloc() not
-	calloc().
+	* amd/conf.c (gopt_portmap_program): use atol() instead of atoi()
+	to avoid size differences.
 
-	* conf/mtab/mtab_mach3.c (convert): use xzalloc() not calloc().
+	* conf/mount/mount_linux.c (find_unused_loop_device): cast to int
+	to avoid comparison between chars and integers.
 
-	* conf/mount/mount_linux.c (parse_opts): use xmalloc() not
-	malloc().
+	* libamu/mount_fs.c (get_hex_string): change 'i' to u_int to avoid
+	comparisons between signed and unsigned integers.
 
-	* amd/info_ldap.c: use xmalloc() not malloc().
+2004-07-13  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* libamu/xutil.c (xzalloc): new function to allocate memory and
-	zero its bytes.
+	* minor new port: i386-pc-linux-suse9.1.
 
-	* amq/amq.c: amq does not need its own definition of xfree().
+	* include/am_defs.h: don't use __kernel_dev_t for dev_t on Linux,
+	because SuSE wants __kernel_old_dev_t.  Instead, just define it
+	directly to what they both use: an unsigned short.
 
-	* aux/macros/opt_debug.m4: if used --enable-debug=mem, then also
-	look for function malloc_verify() in libmapmalloc.a, and function
-	mallinfo() in libmalloc.
+2004-05-27  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* libamu/xutil.c (checkup_mem): do not use mallinfo field
-	uordbytes, because it does not always exist.  Rather, compute it
-	from other fields..
+	* minor new port: i386-unknown-freebsd4.10
 
-	* include/am_utils.h: add external definition to xfree() function
-	used when debugging memory references.
+2004-04-29  Ion Badulescu  <ionut@moisil.badula.org>
 
-Mon Dec 22 03:01:30 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_generic.c (amfs_lookup_one_mntfs): fix the creation of
+	mountpoints for autofs-based sublinks the right way
 
-	* amd/ops_afs.c (afs_readdir_browsable): reduce the number of
-	bytes heuristically computed to be returned to the kernel.
-	Otherwise browsable_dirs fails on OpenBSD 2.2.
+2004-04-28  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* amd/mntfs.c (uninit_mntfs): bug fix.  Moved freeing of
-	mf_private field to AFTER it gets used.
+	Fixes for various memory management problems discovered by
+	Rainer's purify run:
 
-Sat Dec 20 00:51:21 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/transp/transp_tli.c (check_pmap_up): zero out struct
+	timeval before using;
+	(get_nfs_version): ditto
 
-	* amd/ops_host.c (host_umounted): don't use clnt_spcreateerror()
-	on systems that don't support it.
+	* amd/map.c (umount_exported): make sure we don't try to free the
+	same am_node multiple times, by setting its corresponding
+	exported_ap slot to null
 
-	* include/am_defs.h: add missing extern definition for free().
+	* amd/get_args.c (get_version_string): a static pointer is pretty
+	pointless, make it automatic
 
-	* aux/configure.in: check for external definition for free().
+	* amd/conf.c (gopt_debug_options): remove unnecessary strdup();
+	(gopt_log_options): ditto
+	(gopt_print_version): free version string after using it
 
-	* libamu/Makefile.am: add to comment a mention of strstr as an
-	optional function.
+	* amd/autil.c (mf_mounted): free mntfs->mf_fo instead of leaking
+	it
 
-	* libamu/xutil.c (switch_to_logfile): use openlog() options only
-	if they exist.
+	* amd/amfs_generic.c (amfs_lookup_one_mntfs): use the CALLOC macro
+	(amfs_lookup_mntfs): free def_opts on return
 
-	* conf/transp/transp_sockets.c (get_nfs_version): don't use
-	clnt_spcreateerror if it does not exist.
+	* amd/amd.c (daemon_mode): zero out struct sigaction before using
+	it;
+	(main): ditto
 
-	* aux/configure.in: check for missing functions clnt_create and
-	clnt_spcreateerror.  Check for missing strstr, and complete
-	its code.  Check for missing external definition for strstr.
+2004-04-27  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* aux/macros/host_macros.m4: normalize sun3* names.
+	* amd/amfs_generic.c (amfs_lookup_one_mntfs): force FS_MKMNT on
+	the real mount of an autofs-based sublink
 
-	* Makefile.am: updates for new sunos3 files distributed.
+2004-04-25  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* conf/nfs_prot/nfs_prot_sunos3.h: new file.
+	* amd/map.c (free_map_if_success): avoid dereferencing a pointer
+	to potentially freed memory
 
-	* conf/fh_dref/fh_dref_sunos3.h: new file.
+2004-02-26  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/check_nfs_prot_headers.m4: added sunos3 case.
+	* minor new port: i386-unknown-freebsd5.2.1.
 
-	* aux/macros/check_nfs_fh_dref.m4: added sunos3 case.
+2004-01-30  Ion Badulescu  <ion@guppy.limebrokerage.com>
 
-	* doc/am-utils.texi (wire Selector Variable): updated manual for
-	adjusted variables wire, network, and netnumber, all using the
-	in_network() function.
+	* scripts/ctl-hlfsd.in: don't run hlfsd with -D fork
 
-Fri Dec 19 04:37:36 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2004-01-25  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/opts.c: allow options to be processed by executing arbitrary
-	functions.  Converted wire, network, and netnumber all to use the
-	nomadic function in_network.  So from now on they perform a match
-	against all networks, not just primary.
+	* minor new port: sparc64-unknown-linux-deb3.0
 
-	* initial port to alpha-unknown-linux-gnu, probably works, but
-	untested yet.
+	* config.guess.long: recoognize Debian Linux.
 
-	* conf/nfs_prot/nfs_prot_linux.h: add special definitions for
-	__FD_* macros which for som strange reason do not get included
-	from <selectbits.h> on redhat alpha linux.  Also turn off usage of
-	<rpc/des_auth.h> because it is incomplete on the same systems.
+2004-01-22  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* hlfsd/homedir.c (table_add): cast uid field to int, for
-	comparison.
+	* conf/transp/transp_tli.c (amu_get_myaddress): use
+	htonl(INADDR_LOOPBACK) and define INADDR_LOOPBACK if not already
+	available.
 
-	* include/am_defs.h: more coflicts with redhat alpha linux
-	"resolved".
+2004-01-21  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/{mount_headers,try_compile_anyfs,try_compile_nfs}.m4:
-	There's a conflict of definitions on redhat alpha linux between
-	<netinet/in.h> and <linux/fs.h> which must be avoided.
+	* wire-test/wire-test.c, hlfsd/hlfsd.c (main): pass NULL as second
+	parameter to amu_get_myaddress().
 
-	* aux/configure.in: check for <socketbits.h>, which is in use on
-	redhat alpha linux.
+	* conf/transp/transp_tli.c (amu_get_myaddress): resolve value of
+	localhost_address amd.conf parameter, if defined (else default to
+	HOST_SELF_CONNECT).
+	Removed htonl() around socket address copying (I think it was
+	wrong) since plog("My IP address is...") in amd.c was printing
+	addresses wrong on Solaris x86..
 
-	* doc/am-utils.texi (Selectors): added documentation to describe
-	the new "!" (negated) nomadic functions.
+	* conf/transp/transp_sockets.c (amu_get_myaddress): comment out
+	old DEBUG code that warns if 127.0.0.1 isn't the same as what
+	get_myaddress() reports.  Add code to resolve value of
+	localhost_address amd.conf parameter, if defined (else default to
+	127.0.0.1).
 
-	* amd/opts.c (f_in_network): print debugging info that is correct,
-	rather than saying that any ARG is on a local network.
-	(eval_opts): added support for negating nomadic functions, by
-	prepending "!" to their name.  Example, !exists(/foo/bar).
+	* amd/conf.c (gopt_localhost_address): new function to parse
+	amd.conf parameter localhost_address.
 
-Thu Dec 18 20:57:19 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amd.h: global field to store amd.conf localhost_address
+	parameter.
 
-	* include/am_compat.h: ensure that all NFS3 systems have the mount
-	table entries (and amd opts switches) "proto" and "vers".
+	* amd/amd.c (main): call amu_get_myaddress with global option,
+	which could have been set in amd.conf.
 
-	* hlfsd/homedir.c (table_add): added some debugging info to try
-	and track down a serious memory leak in hlfsd.
+	* NEWS, doc/am-utils.texi, scripts/amd.conf-sample,
+	scripts/amd.conf.5: document new option localhost_address.
 
-1997-12-18  Erez Zadok  <ezk@t-rex.mcl.cs.columbia.edu>
+2004-01-20  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* libamu/mount_fs.c (compute_nfs_args): OpenBSD 2.2 requires that
-	you do NOT set the noconn option, and use connected sockets
-	always.  So I'm now forced not to set it at all, and have the user
-	specify it as "conn" or "noconn" in their /default entry.  Argh...
-	Finally, it looks as if OpenBSD 2.2's NFS 3 implementation may be
-	buggy (TCP hangs with "short receive" kernel errors).  I'd better
-	wait until they get it working in their version of the automounter
-	first.  So I'm putting the "noconn" option back.
+	* amd/conf.c (gopt_nfs_allow_insecure_port): support function for
+	the new "nfs_allow_insecure_port" amd.conf directive
 
-Thu Dec 18 02:39:39 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/nfs_prot_svc.c (nfs_program_2): complain about the insecure
+	port and drop the request only if the "nfs_allow_insecure_port"
+	option is not set in amd.conf
 
-	* libamu/mount_fs.c (compute_nfs_args): use maxgrps option and set
-	nfs_args field maxgrouplist accordingly.
+	* doc/am-utils.texi (Global Parameters): documented the new
+	amd.conf directive "nfs_allow_insecure_port"
 
-	* include/am_compat.h (MNTTAB_OPT_MAXGROUPS): complete definition
-	for mount table entry for maxgroups based on NFS mount option
-	maxgrp.
+	* scripts/amd.conf.5 (nfs_allow_insecure_port): ditto
 
-	* aux/configure.in: put back testing for NFS mount option
-	"maxgrps".  Added test for mount table entry "maxgroups".
+	* scripts/amd.conf-sample (nfs_allow_insecure_port): added the
+	"nfs_allow_insecure_port" directive
 
-	* libamu/mount_fs.c (compute_nfs_args): perform more careful tests
-	on nfs_proto, because it could be NULL.
+2004-01-20  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* doc/am-utils.texi (Selectors): added example of in_network()
-	selector.
+	* doc/am-utils.texi: amd-workers is defunct.
 
-	* aux/macros/check_hide_mount_type.m4: all hpux versions,
-	including 9.x, should use "ignore" as the mount type to hide from
-	amd.
+2004-01-19  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Wed Dec 17 13:09:21 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* cvs-server.txt: updated instructions
 
-	* include/am_utils.h (NSTREQ): use new macro instead of strncmp()
-	every where in the sources.
+2004-01-18  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Wed Dec 17 01:15:01 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* minor new port: i386-unknown-freebsd5.2.
 
-	* libamu/mount_fs.c (print_nfs_args): if -D trace is on, will
-	print as much info that is given in struct nfs_args as possible.
-	useful for detecting internal flags and options, as well as the
-	file handle used.
+2004-01-05  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* scripts/ctl-amd.in: look for amd.conf file in ${prefix}/etc
-	after /etc and before /etc/local.
+	* MIRRORS.{txt,html}: verify each mirror site, update to new
+	locations (if found), and remove stale mirrors URLs.
 
-Tue Dec 16 18:51:36 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* updated copyright year to 2004 on all files.
 
-	* aux/configure.in, libamu/Makefile.am: added support for linking
-	with specific versions of libamu.  Upped shared library version of
-	libamu to 1 (libamu.so.1.0.0)
+2004-01-03  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* include/am_defs.h: added external definition for mkstemp() as
-	needed.
+	* MIRRORS.txt: track status.
 
-	* minor new port to i386-unknown-netbsd1.3 (BETA version of
-	netbsd).
+	* Makefile.am (install-snapshot): new directory to install
+	snapshots (now that am-utils home page is moved).
 
-	* aux/config.guess: don't leave a trailing '.' on the system name
-	for NetBSD-1.3_BETA and similarly for OpenBSD.
+2004-01-02  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_netbsd1_3.h: new header for the slight
-	differences in ypall calling conventions.
+	* INSTALL, README.autofs: remove forced text-mode.
 
-	* mk-amd-map/mk-amd-map.c (main): use mkstemp() whenever possible
-	in preference over mktemp(), b/c it is more secure.
+	* doc/am-utils.texi: fix Amd book URL.
 
-	* aux/configure.in: check for mkstemp(), a more secure version of
-	mktemp().
+	* Makefile.am (EXTRA_DIST): include new mirror files in tarball.
 
-Mon Dec 15 02:32:14 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* AUTHORS, BUGS, README, README.y2k, configure.in,
+	doc/am-utils.texi: revisions to use newer URLs for Web site, FTP,
+	and mailing lists.
 
-	* amd/ops_nfs.c (mount_nfs_fh): Systems that include the mount
-	table "vers" option generally do not set the mnttab entry to
-	"nfs3", but to "nfs" and then they set "vers=3".  Setting it to
-	"nfs3" works, but it may break some things like "df -t nfs" and
-	the "quota" program (esp. on Solaris and Irix).  So on those
-	systems, set it to "nfs".
+	* MIRRORS.{html,txt}: updates.
 
-Sat Dec 13 01:36:27 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* doc/Makefile.am: install mirror lists officially.
 
-	* doc/am-utils.texi (Distrib): updates for new ports, location of
-	am-utils' home page, and URL cross references (now supported by my
-	version of texi2html).
+2004-01-01  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/check_mtype_type.m4: also use string type for file
-	system mount types under nextstep for mount(2).
+	* tasks: things to do after migrating ftp/Web sites.
 
-	* aux/macros/check_mtype_printf_type.m4}: nextstep can handle both
-	integer and string types for file system mount types in mount(2),
-	but it is better to use string types.
+2003-12-09  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_nextstep.h: set emum nfsstat's NFS_OK to
-	0, not 1!  Otherwise, all NFS calls (esp. mount) return errno 1
-	(EPERM) instead of 0 (OK).  Fixes m68k-next-nextstep3 which now
-	works.
+	* fsinfo/fsinfo.8: fixed typo (unbalanced []) in man page.  Bug
+	report from Eric S. Raymond <esr@thyrsus.com>.
 
-	* conf/nfs_prot/nfs_prot_bsdi2.h: set emum nfsstat's NFS_OK to 0,
-	not 1!  Otherwise, all NFS calls (esp. mount) return errno 1
-	(EPERM) instead of 0 (OK).
+2003-11-18  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* libamu/xdr_func.c (xdr_*): add debugging calls that are optioned
-	by -D trace (protocol trace).
+	* Makefile.am (EXTRA_DIST_M4): exclude removed file
+	m4/macros/struct_nfs_fh3.m4 from distro.
 
-1997-12-11  Erez Zadok  <ezk@bach.cs.columbia.edu>
+2003-10-24  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* A.m68k-next-nextstep3/amu_nfs_prot.h: define missing S_ISDIR
-	macro based on existence on others, and include <sys/stat.h>.
+	* libamu/xdr_func.c (xdr_am_nfs_fh3): Use AM_FHSIZE3 instead of
+	FHSIZE3 (may be undefined).
 
-Thu Dec 11 14:14:38 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-10-24  Ion Badulescu  <ion@guppy.limebrokerage.com>
 
-	* aux/macros/try_compile_nfs.m4 (AC_TRY_COMPILE): turn off
-	inclusion of <nfs/nfs_mount.h> which only affects nextstep3, on
-	which this header is broken (it tries to include non-existing
-	headers).
+	Compile fix for Solaris7 with LDAP:
 
-Wed Dec 10 16:09:07 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* include/am_defs.h: moved the ldap headers before am_nfs_prot.h
+	to facilitate using ldap types in it
 
-	* libamu/mount_fs.c (mnt_flags): support either nfs or generic
-	mount option for grpid.
+	* conf/nfs_prot/nfs_prot_sunos5_7.h: add a couple of ldap
+	definitions that Sun left out of their headers
 
-	* aux/configure.in: turn back on NFS mount option grpid.
+2003-10-24  Ion Badulescu  <ionut@moisil.badula.org>
 
-Sat Dec  6 04:36:05 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/nfs_prot/nfs_prot_*.h: remove all NFSv3-related
+	definitions, they are now defined globally
 
-	* doc/Makefile.am (install-ps): added target to install postscript
-	file in the am-utils' home page, as well as a few other useful
-	files for the new am-utils Web page.
+	* libamu/xdr_func.c: unconditionally define all xdr functions
+	needed for NFSv3, but with an am_ prefix to prevent namespace
+	collisions
 
-Mon Nov 17 05:22:56 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_host.c, amd/ops_nfs.c, amd/srvr_nfs.c,
+	libamu/mount_fs.c: added the am_ prefix to all
+	structures and functions having to do with NFSv3 to prevent
+	namespace collisions
 
-	*******************************************************************
-	*** Released am-utils-6.0a14					***
-	*******************************************************************
+	* include/am_utils.h: moved definition of am_nfs_handle to ...
 
-Sun Nov 16 21:56:16 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* include/am_xdr_func.h: ... here. Also define AM_FHSIZE3,
+	am_nfs_fh3, AM_NFSPROC3_LOOKUP, am_nfsstat3, am_fhandle3,
+	am_mountstat3, am_mountres3_ok, am_mountres3, am_filename3,
+	am_diropargs3, am_LOOKUP3args, am_LOOKUP3resok, am_LOOKUP3resfail,
+	am_LOOKUP3res here; remove cross-platform compile helper macros
+	AMU_LOOKUP3RES_*.
 
-	* doc/am-utils.texi (Supported Platforms): updated table of new
-	ports.
+	* include/am_defs.h: include am_xdr_func.h before am_utils.h to
+	provide definitions for NFS filehandles
 
-Sat Nov 15 06:36:27 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amd.h: removed declaration for xdr_mountres3
 
-	* libamu/mount_fs.c (compute_automounter_nfs_args): pass mnttab
-	options so that they can be printed in logs as needed.
+	* doc/am-utils.text: minor warning fix
 
-	* doc/am-utils.texi (osver Parameter): updated for the correct
-	usage of the -o/-O options.
+	* BUGS: document the autoconf warnings when trying to compile
+	system header files in isolation
 
-	* scripts/amd.conf.5: corrected info for -o/-O options.
+2003-10-23  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* amd/amd.8: updated man page for new -O op_sys_name option, and
-	corrected the usage of the -o op_sys_ver option
+	* m4/macros/struct_nfs_fh3.m4: removed, not needed
 
-	* amd/get_args.c (get_args): added new amd option -O to override
-	OS name.
-	(get_args): updated usage string.  Removed old -m option.  Added
-	-o and -O options.
+	* configure.in: check if struct mounta has the optptr field;
+	removed all NFSv3-related checks, we implement everything
+	internally now
 
-	* conf/nfs_prot/nfs_prot_irix5.h: add definition to FHSIZE in case
-	it is not there.  Reportedly, irix 5.2 does not define it.
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_mount_2_free): don't
+	touch mnt->optptr unless HAVE_MOUNTA_OPTPTR is defined
 
-	* scripts/lostaltmail.in: removed references to unused $hack
-	variable.
+2003-10-22  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* aux/macros/check_nfs_prot_headers.m4: Patch from Chris Metcalf
-	<metcalf@cag.lcs.mit.edu> to correctly set the nfs_prot headers
-	for solaris2.5.
+	* m4/macros/struct_nfs_fh3.m4: removed, not used anymore
 
-	* doc/am-utils.texi (Distrib): typo in the subscription
-	instructions to amd-dev.  Patch from Stefan Vogel
-	<vogel@physik-rzu.unizh.ch>.
+	* libamu/xdr_func.c (xdr_am_nfs_fh3): update xdr_am_nfs_fh3
+	comments
 
-1997-11-15  Erez Zadok  <ezk@amtrak.cs.columbia.edu>
+	* configure.in: don't check for xdr_nfs_fh3 and struct nfs_fh3, we
+	always use our own
 
-	* NFS3 works on powerpc-ibm-aix4.2.1.0.
+2003-10-22  Ion Badulescu  <ion@guppy.limebrokerage.com>
 
-	* libamu/mount_fs.c (compute_nfs_args): set fh3 variable to
-	static.  Some compilers (gcc from egcs  on aix 4.2.1) corrupt the
-	stack of an automatic variable when pointer to it is passed around
-	several times.
+	* BUGS: document the limitations of bind mounts on Linux
 
-Fri Nov 14 20:09:28 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-10-21  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* libamu/xutil.c (real_plog): syslog like behavior for normal
-	logging.  Will not print repeated strings, only a count "last
-	message repeated N times", but will always print something if
-	message is repeated more than 100 times.
+	* buildall: added support for -i (make install)
 
-	* scripts/lostaltmail.in: look for lostaltmail.conf files also in
-	/etc/global, /etc/os, and /etc/local (in that order).
+2003-10-16  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-Mon Nov 10 03:03:17 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* NEWS: New minor port i386-pc-solaris2.10 (Solaris 10).
+	* INSTALL: Mention its test status.
 
-	* conf/mount/mount_aix.c (mount_aix3): add support for NFS V.3
-	mounts.
+2003-10-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/struct_nfs_args.m4 (AC_TRY_COMPILE_NFS): test for
-	aix42_nfs_args, specially set in conf/nfs_prot/nfs_prot_aix4_2.h
+	* amd/ops_nfs.c (nfs_init): declare as static to match forward
+	definition at top of file.
 
-	* conf/sa_dref/sa_dref_*.h: from now on, the "dst" argument to the
-	NFS_SA_DREF macro is a pointer to the structure that used to be
-	passed to it before.  So now I have to dereference the pointer
-	before accessing its values.
+	* conf/nfs_prot/nfs_prot_{hpux11, netbsd1_4,openbsd,aix5_2}.h:
+	added missing definitions for LOOKUP3res, diropargs3, etc.
 
-	* hlfsd/hlfsd.c (main): use the new and cleaner
-	compute_nfs_args() and compute_automounter_nfs_args() functions.
+2003-10-15  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/ops_nfs.c (mount_nfs_fh): use the new and cleaner
-	compute_nfs_args() and compute_automounter_nfs_args() functions.
+	* libamu/xdr_func.c (xdr_LOOKUP3res, xdr_am_nfs_fh3),
+	libamu/mount_fs.c (compute_nfs_args), amd/ops_nfs.c
+	(got_nfs_fh_mount, got_nfs_fh_webnfs, prime_nfs_fhandle_cache,
+	webnfs_lookup), amd/amfs_host.c (fetch_fhandle): Attempt to
+	cleanup some inconsistencies with how we treat NFSv3 file handles.
+	Whenever we need to get data out of a filehandle given to us, we
+	assume that it uses the OS's native fhandle structure
+	(often struct nfs_fh3).  When we store the fhandle data for our
+	own use, however, we store it in one of two ways.  The first, is
+	that we use the system's default nfs_fh3 structure; the second is
+	that we define out own struct am_nfs_fh3 in nfs_prot.h (and go
+	through an elaborate autoconf song-and-dance to "discover" it as a
+	native fh3 handle structure).  It appears that we do the latter,
+	instead of using the system's default fhandle structure, simply to
+	avoid extra malloc's and free's, because whereas nfsv2's fhandle
+	structure is a simple 32-byte buffer, nfsv3's fhandle structures
+	often just define a "char *" for the fhandle data, and the caller
+	must malloc/free the space inside as needed.  Our code was never
+	written with constructor/destructor callbacks for these nfsv3
+	filehandles.  Moreover, we carefully wrote our own am_nfs_fh3
+	structure so IT JUST SO HAPPENS to align with most (hopefully all)
+	of the fhandle structures for v3: first four bytes are the length
+	fields and the next four bytes are the fhandle data.  Sigh.
+	Having this inconsistent use of v3 filehandles can be a real bear,
+	because we simply cannot avoid using the system's default fhandle
+	structure indirectly, through things like diropargs3 in
+	xdr_diropargs3(), which has inside of it a reference to the
+	system's default nfs_fh3 structure.  ANYWAY, the current fix I've
+	come up with is to generalize the way we dereference field names
+	within the nfs_fh3 structure (whether ours or the system's) and
+	the same for the system's LOOKUP3res structure.  I'm not pleased
+	with this fix; I'd rather we don't use our own am_nfs_fh3
+	structure at all.
 
-	* amd/ops_afs.c (mount_toplvl): MAJOR CODE REVISION.  Use the new
-	and cleaner compute_nfs_args() and compute_automounter_nfs_args()
-	functions.
+	* libamu/xdr_func.c (xdr_am_nfs_fh3): always define this
+	function if we have NFS3, because we often use our own,
+	incompatible am_nfs_fh3 structure.
+
+	* include/am_xdr_func.h: We cannot use the native system's
+	xdr_nfs_fh3 because we are defining our own incompatible
+	am_hfs_fh3 structure for some systems.
 
-	* libamu/mount_fs.c (compute_nfs_args): major code cleanup that
-	relates for struct nfs_args.  A new function sets the numerous
-	possible flags and fields of nfs_args_t in an orderly fashion.
-	Code cleaned up, organized, and moved from amd/hlfsd into
-	libamu.  This saves on overall size of code.
-	(compute_automounter_nfs_args): A variant of compute_nfs_args()
-	which sets special options/flags that need to be used when NFS
-	mounting an automounter's mount point.  Used by hlfsd and amd.
+	* include/am_xdr_func.h: Define default values for field names of
+	struct nfs_fh3 and LOOKUP3res.
 
-	* amq/amq.c (get_secure_amd_client): don't print any more
-	"get_secure_amd_client: using TCP, port 12345".  It's more
-	annoying than useful a message, even when assumed to be compiled
-	under DEBUG only.
+	* doc/am-utils.texi (debug_options Parameter): minor typo fixed.
 
-Thu Oct 30 14:33:38 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/nfs_prot/nfs_prot_freebsd3.h: FreeBSD uses different fields
+	names for struct nfs_fh3 and LOOKUP3res, so override the default
+	names here.
+
+	* configure.in: AMU_CHECK_FS_MNTENT(nfs3) test before
+	AMU_STRUCT_NFS_FH3, because the latter depends on the former.
+
+	* amd/ops_nfs.c (prime_nfs_fhandle_cache): add {} to disambiguate
+	and clarify if-the-else clauses.
+
+2003-10-13  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* amd/get_args.c (get_version_string): change "Built by" to
+	"Configured by", and add a new "Built by" line using the variables
+	below
+
+	* m4/update_build_version (vers): add BUILD_USER, BUILD_HOST, and
+	BUILD_DATE to build_version.h
 
-	* aux/macros/check_mnttab_type.m4: MAJOR BUG fixed for non-nfs
-	mount table entries.  The code used to define the /etc/mnttab name
-	for file systems based on physical media (disk, cdrom, floppy) to
-	the generic name, rather than the OS specific name.  For example
-	autoconf searches for all these types of mount table entries for a
-	floppy based file system: vfat pcfs pc msdos msdosfs fat.  But if
-	it found any, it hard-coded the mnttab name to "pcfs" rather than
-	the actual name found!  Same for ufs, cdfs, pcfs, tmpfs, lofs,
-	nullfs, unionfs, and umapfs.
+	* amd/mntfs.c (locate_mntfs): fix restarted filesystems: mf_fo
+	must be initialized even for them, otherwise we lose opt_sublink
+	(and perhaps other options as well). Report from Rainer Orth.
+
+	* amd/amfs_generic.c (amfs_bgmount): The fix for the mf_fo NULL
+	pointer dereferencing was a bit too aggressive and could end up
+	not processing the sublink option if the filesystem was already
+	mounted.
+
+2003-10-11  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* aux/configure.in: also test for xfs (for newer Irix) when
-	looking for mount type names, numbers, etc of a disk-based ufs.
+	Fix restarted filesystem by disabling the amfs_inherit filesystem
+	and moving the restarting logic into the generic code. The old
+	code is still there, will be removed sometime in the near future.
 
-Sun Oct 26 19:32:57 1997  Erez Zadok  <ezk@defiant.soscorp.com>
+	* amd/mntfs.c (locate_mntfs): disable amfs_inherit and simply
+	return the pointer to the restarted filesystem
+	(free_mntfs): check for the MFF_RESTART flag instead of the
+	amfs_inherit ops
+
+	* amd/autil.c (mf_mounted): remove the MFF_RESTART flag once the
+	filesystem is in use
+
+	* amd/amfs_nfsx.c (amfs_nfsx_init): only call fs_init() if the
+	filesystem is not being restarted
+	(amfs_nfsx_remount): if the filesystem is already mounted,
+	short-circuit the code and just continue
+
+	* amd/amfs_generic.c (amfs_bgmount): only call fs_init() if the
+	filesystem is not being restarted; remove hack that was used to
+	work around an amfs_inherit problem
+
+2003-10-09  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	Use WebNFS to obtain file handles for mount(2).
+
+	* NEWS: Document WebNFS support.
+
+	* configure.in: Check for public mount option.
+	* include/am_compat.h (MNTTAB_OPT_PUBLIC): Define if missing.
+	* doc/am-utils.texi (opts Option): Renamed webnfs to public,
+	update description.
 
-	* amq/amq.c (main): use pmap_ping() to test if remote host is up.
-	This works better on bsdi2 and bsdi3, because their portmapper
-	does not appear to like forwarding operations (it is generaly
-	insecure).
+	* amd/amd.h (FSF_WEBNFS): New mntfs flag.
+	* include/am_utils.h (RPC_XID_WEBNFS): New XID type.
 
-Sat Oct 25 04:55:56 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_host.c (amfs_host_mount, amfs_host_umounted): Reject
+	WebNFS mount/umount attempts.
+	* amd/ops_nfs.c (got_nfs_fh_mount): Renamed from got_nfs_fh.
+	(got_nfs_fh_webnfs): New function.
+	(flush_nfs_fhandle_cache): Don't invalidate port for WebNFS servers.
+	(prime_nfs_fhandle_cache): Likewise.
+	Remove unconditional return of public file handle for WebNFS, but
+	get NFS file handles via mountd or WebNFS instead.
+	(webnfs_lookup): New function.
+	(nfs_umounted): Don't inform mountd if MFF_WEBNFS.
+	* amd/rpc_fwd.c (fwd_packet, fwd_reply): Send/receive WebNFS
+	packets.
+	* amd/srvr_nfs.c (recompute_portmap): Don't contact portmap for
+	WebNFS servers.
+	Mention host in info message.
+	(find_nfs_srvr): Handle public mount option.
+	Prefer NFSv3/tcp if the client supports it.
+	Allow port mount option to override default or result from portmap
+	lookup.
 
-	*******************************************************************
-	*** Released am-utils-6.0a13					***
-	*******************************************************************
+	* libamu/xdr_func.c (xdr_diropargs3, xdr_filename3,
+	xdr_LOOKUP3args, xdr_LOOKUP3res, xdr_LOOKUP3resfail,
+	xdr_LOOKUP3resok, xdr_nfs_fh3, xdr_nfsstat3): New functions.
+	* include/am_xdr_func.h: Declare them.
+	* configure.in: Check for them.
+	* conf/nfs_prot/nfs_prot_linux.h: Provide missing NFSv3
+	definitions and types.
 
-Fri Oct 24 05:04:37 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-10-09  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* conf/nfs_prot/nfs_prot_ncr2.h: added missing definition for
-	struct datum typedef.
+	Support IRIX 6 private mount option.
 
-	* conf/nfs_prot/nfs_prot_netbsd.h: corrected typedef for
-	ypall_callback_fxn_t for netbsd.
+	* configure.in (AC_CHECK_MNTTAB_OPTS): Check for private option
+	name string.
+	(AC_CHECK_MNT2_NFS_OPTS): Check for private NFS mount option (IRIX 6).
+	* aux/macros/header_templates.m4 (MNTTAB_OPT_PRIVATE,
+	MNT2_NFS_OPT_PRIVATE): Provide templates.
+	* include/am_compat.h (MNTTAB_OPT_PRIVATE): Define if missing.
+	* doc/am-utils.texi (opts Option): Document it.
 
-	* aux/macros/type_auth_create_gidlist.m4: hpux10.10 uses int for
-	the 5th arg to authunix_create(), while before and after they used
-	gid_t.
+2003-10-09  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* conf/transp/transp_tli.c (amu_clnt_create_best_vers): don't use
-	clnt_create_timed() on older Solaris 2.3 systems that did not have
-	it.
+	* doc/am-utils.texi (opts Option): Fix Tru64 UNIX name in proplist
+	mount option.
 
-	* conf/nfs_prot/nfs_prot_bsdi2.h: <msdosfs/msdosfsmount.h> is for
-	kernel only on bsdi2, so do not include it.
+2003-10-09  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-Fri Oct 24 00:29:42 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* libamu/mount_fs.c (compute_nfs_args) [HAVE_NFS_ARGS_T_FH_LEN]:
+	Don't reference removed fh3.
 
-	* hlfsd/stubs.c (nfsproc_readlink_2_svc): avoid logging repeated
-	messages about resolution of mailboxes based on uid/gid.
+2003-10-09  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* scripts/ctl-hlfsd.in: check for alternate password file in
-	${prefix}/etc/passwd and use it in hlfsd's startup.
+	* NEWS: New minor port sparc-sun-solaris2.10 (Solaris 10).
 
-Thu Oct 23 22:48:50 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* INSTALL: Mention test status of various ports.
+	Describe IRIX 6 autofs status.
 
-	* hlfsd/homedir.c (hlfsd_getpwent): added support for -P
-	passwdfile option.  If hlfsd is started with -P passwdfile, then
-	the passwdfile is read and parsed just as a standard unix
-	passwd(4) file.  Only the username, uid, and homedir fields are
-	read and checked.  All the rest are ignored.  No NIS/netgroup
-	support!
+2003-10-09  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* hlfsd/hlfsd.c (main): check if hlfsd is run as root after
-	parsing command line options, so that usage() can be printed when
-	-h is invoked.
+	* NEWS: updated
 
-Wed Oct 22 00:16:39 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* amd/amfs_generic.c (amfs_bgmount): don't use mf_fo until after
+	we've done all the tests and we know we have a valid and mountable
+	mntfs. Otherwise we could end up dereferencing null pointers.
 
-	* amd/nfs_start.c (mount_automounter): if autofs service listener
-	fails to initialize it is OK if using a test amd.
+	* amd/amd.h: fixed a copy&paste comment bug
 
-	* amd/opts.c (f_in_network): new nomadic function in_network(arg),
-	which returns TRUE if 'arg' is any one of this host's networks.
+	* amd/am_ops.c (ops_match): minor code cleanup
 
-	* libamu/wire.c (getwire): rewritten parts of function, to store
-	all networks names and numbers in the order of the interface (not
-	in reverse).
+	* doc/am-utils.texi: fixed various typos; added warning about the
+	racy nature of nfsx; removed duplicated listing of debug options;
+	added paragraph about signals supported by hlfsd; removed the long
+	list of (maybe) supported platforms since it duplicates the list
+	in INSTALL.
 
-Mon Oct 20 01:59:25 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-10-02  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* aux/configure.in: don't add ops_ufs.o on AIX twice.  My code
-	would have worked had it not been due to AIX's buggy /bin/sh.
+	Simplify FD_SET etc. use.
 
-	* doc/Makefile.am (EXTRA_DIST): include am-utils.dvi and
-	am-utils.ps in the distribution sources.
-	(html): generate html documentation for
-	http://www.cs.columbia.edu/~ezk/am-utils/
+	* include/am_defs.h (FD_SET, FD_ISSET, FD_CLR, FD_ZERO): Provide
+	if missing.
+	(rpc_pending_now, run_rpc): Use them.
+	* configure.in: Check for fds_bits field in fd_set.
+	* amd/nfs_start.c (run_rpc): Use it.
 
-Sun Oct 19 12:35:49 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-10-02  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* conf/nfs_prot/nfs_prot_netbsd.h: override the definition of
-	ypall_callback_fxn_t.  The NetBSD team compiles all sources with
-	gcc -Wall -Wmissing-prototypes -Wstrict-prototypes.
+	Improve RPC XID handling.
 
-	* amd/info_nis.c: allow for override of ypall_callback_fxn_t
-	function typedef.
+	* amd/rpc_fwd.c (fwd_packet, fwd_reply): Always log xid.
+	Convert xid to/from host/network byte order.
 
-	* libamu/xutil.c (amu_release_controlling_tty): new function to
-	release the controlling tty in a clean and sane manner.  No longer
-	using setpgid() b/c it may not work.  Uses setsid(),
-	and ioctl() (in order).  This new function is used in amd/amd.c
-	and hlfsd/hlfsd.c.  Also avoid setpgrp(), because it works on some
-	systems, but on others it is the same as setpgid().
+2003-10-02  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-Sat Oct 18 23:42:40 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	Use NFS V2/V3 file handles instead of mount results.
 
-	* aux/acconfig.h: check for nfs mount option 'fsname'.  Code for
-	it was in amd/ops_afs.c, amd/ops_nfs.c, and hlfsd/hlfsd.c, but
-	never used, because the configure test for fsname flag wasn't
-	used.  This fixed a bug in HPUX 10, where syncer and manual mounts
-	left blank lines in /etc/mnttab.
+	* include/am_utils.h (am_nfs_fhandle): Use NFS V2/V3 file handles
+	only, not MOUNTPROC_MNT results.
+	* amd/amfs_host.c (fetch_fhandle): Use local variables to store
+	MOUNTPROC_MNT results.
+	* amd/autil.c (amfs_mount): Use new am_nfs_fhandle_t.
+	* amd/ops_nfs.c (struct fh_cache): New member fh_status.
+	(got_nfs_fh): Use local variables to store MOUNTPROC_MNT results.
+	Store MOUNTPROC_MNT errors in fh_status.
+	(prime_nfs_fhandle_cache): Get fh_error from fh_status.
+	* hlfsd/hlfsd.c (main): Use new am_nfs_fhandle_t.
+	* libamu/mount_fs.c (compute_nfs_args): Copy NFS V2/V3 file
+	handles straight from new am_nfs_fhandle_t.
 
-	* aux/configure.in: check for nfs mount option 'fsname'.
+2003-10-02  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-Fri Oct 17 13:30:27 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/clock.c (CID_ALLOC): Remove unused argument.
+	(timeout): Likewise.
 
-	* amd/ops_afs.c (mount_toplvl): turn on 'ignore' option in nfs
-	mount flags of toplvl mounts.  Important esp. for HPUX 10.  Now
-	hpux-10 will mount amd's mounts points as 'ignore' (by df).
+	* amd/ops_nfs.c (FHID_ALLOC): Remove unused argument.
+	(prime_nfs_fhandle_cache): Likewise.
+	(call_mountd): Use UDPMSGSIZE instead of magic constant.
 
-	* aux/configure.in: check for NFS mount option 'ignore', useful in
-	HPUX 10.
+	* amd/rpc_fwd.c (XID_ALLOC): Remove unused argument.
+	(fwd_packet): Likewise.
+	Handle TLOOK error from t_rcvudata().
 
-Thu Oct 16 03:28:33 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-09-30  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* aux/macros/check_hide_mount_type.m4: hpux 10 should use "ignore"
-	mount type and not NFS, for the amd mount points.
+	* NEWS: updated
 
-	* conf/transp/transp_tli.c (amu_clnt_create_best_vers): don't log
-	an RPC timeout as an error, but just an info message.  From
-	Andreas Stolcke <stolcke@speech.sri.com>
+	* libamu/mount_fs.c (mount_fs): don't try to recreate the mount
+	point if the mount fails with ENOENT: in the best case we would be
+	papering over a bug, and in the worst case we could cause a
+	deadlock (with autofs). If there are races, they need to be
+	exposed and fixed properly.
 
-	* If the NFS server is down or does not support the portmapper
-	call (such as certain Novell NFS servers) we mark it as version 2
-	and we let the nfs code deal with the case that is down.  If when
-	the server comes back up, it can support NFS V.3 and/or TCP, it
-	will use those.  From christos@deshaw.com (Christos Zoulas).
+	* conf/autofs/autofs_solaris_v1.h,
+	  conf/autofs/autofs_solaris_v2_v3.h,
+	  conf/autofs/autofs_linux.h: (AUTOFS_NFSX_FS_FLAGS): autofs
+	semantics don't allow us to mount nfsx directly onto an autofs
+	mountpoint, so disallow it
 
-	* hlfsd/homedir.c (plt_print): various compile time cleanups to
-	printfs that take a long, but pass an int to print.  From
-	christos@deshaw.com (Christos Zoulas).
+	* amd/amfs_nfsx.c (amfs_nfsx_match): more restrictive sanity check
+	to avoid trying to memmove(foo, bar, (unsigned)-1) due to invalid
+	map entries...
+	(amfs_nfsx_cont): amfs_retry does most of the cleanup work for us
+	in the upper layer, so don't do anything else beside wakeup() on
+	success
+	(amfs_nfsx_remount): only create the mountpoints as we need them,
+	avoids creating them on the wrong filesystem in the case of
+	hierarchical mounts; fix crash-generating typo (m should really be
+	mf and I swear I hate single-character variable names)
 
-	* aux/macros/func_bad_yp_all.m4 (ac_cv_func_yp_all_clean,): new
-	macro to determine if the OS has a bad yp_all(), based on the host
-	OS name.  So far only irix (all versions) have a bad yp_all, so
-	they will use am_yp_all() instead (which is slower as it
-	enumerates manually all of the map's entries).
+	* amd/amfs_generic.c (amfs_cont): one more dlog
+	(amfs_bgmount): amazingly enough, even foreground mounts can be
+	backgrounded (in the case of nfsx), so account for this
+	possibility and permit retries
 
-Thu Oct 16 03:14:37 1997  Erez Zadok  <ezk@subzero.cs.columbia.edu>
+	* m4/macros/check_autofs_style.m4 (AMU_AUTOFS_PROT_HEADER): define
+	and AC_SUBST it as ${top_builddir}/amu_autofs_prot.h
 
-	* amd/info_nis.c (am_yp_all): code for a replacement yp_all that
-	avoids using a file-descriptor leaking yp_all() on some systems
-	like irix.
+	* amd/Makefile.am ($(amd_OBJECTS) $(EXTRA_amd_OBJECTS)): depend on
+	@AMU_AUTOFS_PROT_HEADER@
 
-Wed Oct 15 21:52:35 1997  Erez Zadok  <ezk>
+2003-09-29  Erez Zadok  <ezk@urd.fsl.cs.sunysb.edu>
 
-	* fsinfo/fsinfo.h: avoid redefining yywrap incorrectly on DU-4.x
-	systems using /usr/bin/flex.
+	* minor new port mipsel-unknown-linux-rhPS2 (Linux on Sony
+	PlayStation 2)
 
-	* amd/conf_tok.l (yywrap): avoid redefining yywrap for systems
-	that have a modified GNU flex which does define yywrap (DU-4.x).
+	* amd/srvr_nfs.c (find_nfs_srvr): don't run code that expects
+	"char protocols[]" unless MNTTAB_OPT_PROTO is defined.
 
-Fri Sep 26 14:25:29 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-09-26  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* conf/checkmount/checkmount_bsd44.c: include prototype.
+	Consolidate alloca support.
 
-Fri Sep 26 01:26:24 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amq_svc.c: Move alloca support ...
+	* include/am_defs.h: ... here.
+	* amd/conf_parse.y: Remove alloca support.
+	* fsinfo/fsi_gram.y: Likewise.
 
-	*******************************************************************
-	*** Released am-utils-6.0a12					***
-	*******************************************************************
+2003-09-25  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-Fri Sep 26 00:13:48 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	Handle Solaris 10.
+	* m4/macros/check_nfs_prot_headers.m4
+	(AMU_CHECK_NFS_PROT_HEADERS): Don't use wildcards for
+	sunos5.[0-3], solaris 2.[0-3], there were no micro releases.
+	Explicitly match sunos5*, solaris2* for Solaris 8 and beyond.
 
-	* conf/nfs_prot/nfs_prot_irix6.h: completely turn off all autofs
-	code in irix6 until it can be tested correctly
+	* m4/macros/os_cflags.m4 (AMU_OS_CFLAGS): Dont use wildcards for
+	solaris2.[0-5], sunos5.[0-5], but explicitly handle Solaris 2.5
+	micro releases to cope with Solaris 2.5.1.
+	Explicitly match solaris2*, sunos5*.
 
-	* conf/transp/transp_tli.c (amu_clnt_create_best_vers): time out
-	on clnt_create for 3 seconds, rather than wait for the much longer
-	default.
+2003-09-25  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* conf/nfs_prot/nfs_prot_aix4_2.h: port to powerpc-ibm-aix4.2.1.0.
-	Includes NFS3, untested.
+	* amd/amq_svc.c: Provide alloca prerequisites.
 
-Thu Sep 25 11:03:11 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/transp/transp_tli.c (register_autofs_service): Fix typo.
 
-	* amd/ops_pcfs.c (mount_pcfs): fill in uid/gid fields of
-	pcfs_args_t if they exist.
+2003-09-23  Ion Badulescu  <ion@opteron.tower-research.com>
 
-	* amd/ops_cdfs.c (mount_cdfs): fill in ssector field of
-	cdfs_args_t if it exists.
+	* minor new port: x86_64-unknown-linux-rh2.9.5AS. (Red Hat
+	Enterprise Linux 3.0 beta running on a 64-bit AMD64 platform)
 
-	* new minor ports hppa1.1-hp-hpux10.10, hppa1.1-hp-hpux9.05,
-	hppa1.1-hp-hpux9.07, m68k-hp-hpux9.00, and sparc-sun-sunos4.1.4.
+2003-09-22  Ion Badulescu  <ionut@buggy.badula.org>
 
-Wed Sep 24 00:48:05 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/autofs/autofs_solaris_v1.c (autofs_mount_fs): compile fix
 
-	* doc/am-utils.texi (wire-test): updated documentation for the new
-	option.
+2003-09-19  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* wire-test/wire-test.8: updated man page for new option.
+	* amd/amfs_nfsl.c (amfs_nfsl_match): checking opt_fs is not always
+	enough, we should lstat() the sublink if it's defined.
+	(amfs_nfsl_ffserver): ditto
+	(ALL): Removed some obsolete comments. The nfsl code is now little
+	more than a very straight-forward switch between link and nfs.
 
-	* wire-test/wire-test.c (main): added a test for various
-	combinations of NFS proto/vers to a remote/local host.
+	* amd/amfs_link.c (amfs_link_match): more up-to-date explanation
+	for the prepend-the-dot hack for type link; also, the sublink is
+	already normalized and absolute, so take advantage of that
 
-	* aux/macros/try_compile_anyfs.m4 (AC_TRY_COMPILE): include
-	<isofs/cd9660/cd9660_mount.h> and <msdosfs/msdosfsmount.h> so that
-	freebsd will correctly set mount options for pcfs and cdfs.
+	* amd/amfs_generic.c (amfs_lookup_one_mntfs): the sublink is
+	already normalized and absolute, so take advantage of that
 
-	* amd/ops_pcfs.c (mount_pcfs): set mask field of pcfs_args to
-	0777 (if field exists).
+	* amd/am_ops.c (ops_match): normalize the sublink here, early into
+	the matching process
 
-	* aux/macros/try_compile_anyfs.m4 (AC_TRY_COMPILE): include
-	<msdosfs/msdosfsmount.h> if available.
+	* amd/autil.c (am_mounted): be consistent and accept both
+	"nounmount" and "noumount" as pseudo mount options (same as
+	"unmount" and "umount" nearby)
 
-	* minor new port: rs6000-ibm-aix4.1.4.0.
+	* amd/Makefile.am (build_version.h): fixed dependencies (depends
+	on amd_OBJECTS, not OBJECTS -- which doesn't even exist)
 
-	* libamu/mount_fs.c (mount_fs): fixed bug that caused HPUX not to
-	write the "time" field in /etc/mnttab.
+2003-09-19  Erez Zadok  <ezk@dhcp8.fsl.cs.sunysb.edu>
 
-	* conf/mtab/mtab_file.c (mnt_dup): fixed typo in macro names for
-	detecting mnt_time field of mntent_t.
+	* amd/amq_subr.c (amqproc_export_1_svc): force double casting to
+	avoid gcc-3.3 complaints on Solaris 9 about "dereferencing
+	type-punned pointer will break strict-aliasing rules".
 
-	* libamu/mtab.c (mnt_free): fixed typo in macro names for
-	detecting mnt_time field of mntent_t.
+2003-09-16  Ion Badulescu  <ionut@moisil.badula.org>
 
-Tue Sep 23 15:30:03 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* Released beta version 6.1b4
 
-	* conf/mtab/mtab_file.c (lock): Use flock() in preference over
-	fcntl() to lock the mtab file.
+2003-09-15  Ion Badulescu  <ionut@moisil.badula.org>
 
-Mon Sep 22 23:04:58 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* doc/am-utils.texi (opts Option): removed documentation for old
+	ignore_portmapper mount option, documented the new webnfs option
 
-	* conf/transp/transp_sockets.c (get_nfs_version): define
-	the try_again goto label only for NFS3.
-	(pmap_ping): assume timeout failure of clnt_stat.
+	* NEWS: webnfs support
 
-	* libamu/xdr_func.c (xdr_groupnode, xdr_exportnode): cast to
-	"groups *".
+	* amd/srvr_nfs.c (find_nfs_srvr): set MFF_WEBNFS if the "webnfs"
+	(former "ignore_portmapper") mount option is present
 
-Mon Sep 22 20:34:33 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* amd/ops_nfs.c (prime_nfs_fhandle_cache): generate a public
+	filehandle (all zeros) if MFF_WEBNFS is set
+	(nfs_umounted): don't talk to mountd if MFF_WEBNFS is set
 
-	* conf/transp/transp_sockets.c (pmap_ping): patch from Dan Riley
-	<dsr@mail.lns.cornell.edu> to make sure that amd works with more
-	secure portmappers that do not allow forwarding of RPC messages to
-	other services.
+	* amd/amd.h (MFF_WEBNFS): new flag, obvious meaning
 
-	* */Makefile.am: all source files should also depend on the new
-	include/am_xdr_func.h header.
+2003-09-13  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* include/am_xdr_func.h: new file as part of the code cleanup from
-	Christos Zoulas <christos@deshaw.com>.
+	* amd/srvr_nfs.c: renamed np_xid to global_xid; sanitized the
+	NPXID_ALLOC macro and renamed it to XID_ALLOC; renamed start_ping
+	to create_ping_payload; renamed nfs_pinged to
+	nfs_keepalive_callback; renamed nfs_timed_out to
+	nfs_keepalive_timeout; renamed nfs_srvr_port to get_mountd_port;
+	made ping_buf and ping_len arrays with one element for each
+	supported nfs version
 
-	* Lots of fixes from Christos Zoulas <christos@deshaw.com> that
-	involved missing prototypes, cleaned up ones, and removal of
-	unused variables.
+	* amd/amd.h: renamed nfs_srvr_port() to get_mountd_port()
 
-	* libamu/xdr_func.c (xdr_mountres3): some code cleanup.  A switch
-	statement with only one case is unclean.
+	* amd/amfs_host.c (amfs_host_init): ditto
 
-Mon Sep 22 17:26:38 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/ops_nfs.c (call_mountd): ditto
 
-	* amd/ops_<FOO>fs.c (mount_<FOO>fs): initialize mntent_t fields to
-	0 so that all fields are initialized to zero at first.  This way
-	SunOS 4.x and other systems don't get /etc/mtab entries with
-	random integers for the fsck/freq fields. Patch from Andreas
-	Stolcke <stolcke@speech.sri.com>.
+2003-09-03  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-Mon Sep 22 00:34:19 1997  Erez Zadok  <ezk@americas.psl.cs.columbia.edu>
+	* BUGS: Mention fix for broken Solaris 8 <rpcsvc/autofs_prot.h>
+	patches.
 
-	* conf/nfs_prot/nfs_prot_sunos4.h: include <nfs/nfs_clnt.h> so
-	that the important definition for HOSTNAMESZ will be found.
+2003-08-31  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-	* amd/ops_afs.c (mount_toplvl): limit hostname size to HOSTNAMESZ
-	(inside the nfs_args structure) if the system uses that macro.
-	Otherwise systems like SunOS refuse to NFS mount long pathnames
-	and result in ENAMETOOLONG errno's.
+	* amd/autil.c (strealloc): don't call malloc_verify() unless it
+	exists.
 
-Wed Sep 17 04:56:11 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: move "OPTION PROCESSING" section (opt_debug etc.)
+	after we figure out PROG_CC and other compiler features, because
+	some of the option processing macros need a compiler to function.
 
-	* doc/am-utils.texi (Supported Platforms): specify new support for
-	solaris 2.6, and hlfsd running on 2.5.1 too.
+	* libamu/xutil.c: don't define variables that won't be used unless
+	mallinfo() and malloc_verify() exist.
+	(real_plog): don't call checkup_mem unless
+	mallocinfo() and malloc_verify() exist.
+	(checkup_mem): don't define this function unless mallocinfo() and
+	malloc_verify() exist.
 
-Wed Sep 17 03:55:02 1997  Erez Zadok  <ezk@amsterdam.psl.cs.columbia.edu>
+	* m4/macros/opt_debug.m4: check for functions malloc_verify and
+	mallinfo in general libraries and then in libmapmalloc and
+	libmalloc.  These seem to have disappeared in FreeBSD 5.x.
 
-	* conf/mount/mount_svr4.c (mount_svr4): don't attemt an autofs
-	mount if it is not supported or was turned off.
+	* libamu/xutil.c (dxfree): print pointer using %p
 
-Wed Sep 17 03:19:36 1997  Erez Zadok  <ezk@americas.psl.cs.columbia.edu>
+2003-08-29  Erez Zadok  <ezk@a-opendarwin.fsl.cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_sunos4.h: fixed so that it will nfs mount
-	again.  Apparently at some previous release SunOS 4 supported was
-	broken and all nfs mounts resulted in ESTALE.
+	* configure.in: start 6.1b4-pre officially (belated)
 
-Wed Sep 17 00:26:25 1997  Erez Zadok  <ezk@amsterdam.psl.cs.columbia.edu>
+	* minor new port: i686-apple-darwin6.6
 
-	* conf/nfs_prot/nfs_prot_sunos5_6.h: nfs protocol headers for
-	solaris 2.6.
+2003-08-27  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* aux/macros/check_nfs_prot_headers.m4: added solaris 2.6 nfs
-	protocol header selection.
+	* conf/autofs/autofs_solaris_v1.c: convert relative targets to
+	absolute paths when using lofs mounts
 
-Sat Sep 13 14:31:51 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/autofs/autofs_solaris_v2_v3.c: ditto
 
-	* conf/transp/transp_tli.c (amu_clnt_create_best_vers): avoid
-	infinite loop.
+	* conf/autofs/autofs_linux.c: ditto
 
-Sun Sep  7 18:23:23 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-08-27  Ion Badulescu  <ionut@buggy.badula.org>
 
-	*******************************************************************
-	*** Released am-utils-6.0a11					***
-	*******************************************************************
+	* README.autofs: added a paragraph about the resource consumption
+	of auto maps over autofs
 
-Fri Sep  5 11:55:10 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_generic.c (amfs_lookup_one_mntfs): moved the setting of
+	the MFF_IS_AUTOFS flag from init_mntfs() to
+	amfs_lookup_one_mntfs(), where it belongs
 
-	* amd/amd.c (main): if plock() succeeded, don't try to display
-	errno message.   Patch from Chris Metcalf
-	<metcalf@catfish.lcs.mit.edu.
+	* amd/mntfs.c (init_mntfs): ditto
 
-Thu Sep  4 19:17:58 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-08-27  Ion Badulescu  <ion@guppy.limebrokerage.com>
 
-	* hlfsd/homedir.c (table_add): make sure duplicate passwd entries
-	are ignored.   Only the first entry should ever be used, because
-	that's how lookup in passwd database works.
+	* amd/ops_nfs.c (got_nfs_fh): make the error EACCES if we are
+	denied a filehandle by the server (used to be EIO)
 
-	* conf/transp/transp_sockets.c (get_nfs_version): when determining
-	if a remote host is up or down, use NFS v.2.  Fix suggested by
-	Enami Tsugutomo <enami@cv.sony.co.jp>.
+2003-08-27  Erez Zadok  <ezk@a-bsdi42.fsl.cs.sunysb.edu>
 
-	* conf/transp/transp_tli.c (amu_clnt_create_best_vers): new
-	function to get the best possible NFS version, but also timeout
-	faster than normal defaults, so remote hosts which are down can be
-	detected in a reasonable time.
-	(get_nfs_version): use the new "best" function.
+	* conf/nfs_prot/nfs_prot_bsdi3.h: support na_uid and na_gid.
 
-Tue Sep  2 00:41:00 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-08-27  Ion Badulescu  <ionut@moisil.badula.org>
 
-	*******************************************************************
-	*** Released am-utils-6.0a10					***
-	*******************************************************************
+	* conf/autofs/autofs_linux.c (autofs_mount_succeeded): force
+	daemon-initiated timeouts on autofs filesystems, since apparently
+	they appear as "always busy" to the kernel-based expiration routine
 
-Mon Sep  1 15:39:51 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-08-26  Ion Badulescu  <ionut@buggy.badula.org>
 
-	* conf/transp/transp_tli.c (get_nfs_version): don't use
-	clnt_tp_create_timed() on systems that don'e have it (Solaris 2.4
-	and earlier).
+	* NEWS: updated
 
-	* aux/configure.in: test for existence of clnt_tp_create_timed(),
-	since Solaris 2.4 (and possibly earlier) do not have it.
+	* conf/autofs/autofs_linux.h (AUTOFS_LINK_FS_FLAGS): remove
+	FS_ON_AUTOFS
+	(AUTOFS_LINKX_FS_FLAGS): ditto
 
-Mon Sep  1 15:23:18 1997  Erez Zadok  <ezk@felix.psl.cs.columbia.edu>
+	* conf/autofs/autofs_solaris_v1.h (AUTOFS_LINK_FS_FLAGS): remove
+	FS_ON_AUTOFS
+	(AUTOFS_LINKX_FS_FLAGS): ditto
 
-	* amd/ops_autofs.c (autofs_unmount_1_svc): only display rdevid
-	field if it exists (solaris 2.4's autofs does not have it).
+	* conf/autofs/autofs_solaris_v2_v3.h (AUTOFS_LINK_FS_FLAGS): remove
+	FS_ON_AUTOFS
+	(AUTOFS_LINKX_FS_FLAGS): ditto
 
-Mon Sep  1 14:45:09 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_generic.c (amfs_lookup_one_mntfs): don't modify the
+	original opt_fs, instead store the new mount point for autofs in a
+	temporary variable and pass it around. Fixes a problem with the
+	link side of nfsl.
 
-	* aux/macros/type_auth_create_gidlist.m4: a new test to determine
-	the correct type to the 5th argument of authunix_create().
+2003-08-25  Ion Badulescu  <ionut@moisil.badula.org>
 
-Mon Sep  1 03:44:32 1997  Erez Zadok  <ezk@felix.psl.cs.columbia.edu>
+	* NEWS: updated
 
-	* libamu/xdr_func.c (xdr_umntrequest): add test for autofs
-	structure umntrequest, if it has the field rdevid.  Seems Solaris
-	2.4 and earlier didn't have it.
+	* amd/ops_nfs.c (prime_nfs_fhandle_cache): use get_mntfs_wchan to
+	initialize the fh_wchan member of the cache entry
+	(prime_nfs_fhandle_cache): use get_mntfs_wchan for the wchan_t
+	argument of call_mountd()
 
-Mon Sep  1 01:10:53 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/map.c (free_map_if_success): use get_mntfs_wchan for the
+	wchan_t argument of wakeup()
 
-	* hlfsd/hlfsd.c (hlfsd_init): moved initialization upwards, so it
-	can be done before primary process forks.
-	(main): bug fix: wait a bit to give child a chance to initialize.
-	Without this, hlfsd got into a busy infinite loop while, never
-	completing the mount.
+	* amd/amfs_nfsx.c (amfs_nfsx_cont): use get_mntfs_wchan for the
+	wchan_t argument of wakeup_task() and wakeup()
 
-	* amd/info_nis.c: patch from Jason Thorpe <thorpej@nas.nasa.gov>
-	to make amd works when talking to NIS+ servers in NIS
-	compatibility mode.
+	* amd/amfs_host.c (amfs_host_init): use get_mntfs_wchan for the
+	wchan_t argument of nfs_srvr_port()
 
-Mon Sep  1 00:46:56 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* amd/amfs_generic.c (ALL): use get_mntfs_wchan for the wchan_t
+	argument of sched_task() and wakeup()
+	(amfs_retry): minor cleanup
+	(amfs_bgmount): call nfs_quick_reply on failure
 
-	* amd/mapc.c (MAX_CHAIN): increased maximum chain size to 1024.
+	* amd/sched.c (get_mntfs_wchan): new function which calls the
+	member function get_wchan if defined, otherwise returns the mntfs
+	pointer itself
 
-Sun Aug 31 20:20:40 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* amd/amfs_inherit.c (amfs_inherit_get_wchan): new function,
+	calls get_mntfs_wchan() on the inherited filesystem
 
-	* amd/conf.c (gopt_fully_qualified_hosts): a new function to
-	process another new global variable.
+	* amd/amfs_*.c, amd/ops_*.c: initialize the new get_wchan member
+	of the ops to 0
 
-	* amd/ops_nfs.c (make_nfs_auth): if a new global variable
-	fully_qualified_hosts is on, use FQHN in RPC/NFS authentications.
-	Patch from Chris Metcalf <metcalf@catfish.lcs.mit.edu>.
+	* amd/amd.h: new function type vget_wchan
+	(struct mntfs): new member get_wchan which returns the waiting
+	channel associated with the mntfs (normally itself)
 
-	* amd/conf.c (process_last_regular_map): If the amd.conf file only
-	has a [global] section (pretty useless IMHO), do not try to
-	process a map that does not exist.
+2003-08-22  Ion Badulescu  <ion@guppy.limebrokerage.com>
 
-	* scripts/amd.conf.5: fixed typos (repeated 'as' word).
+	* conf/mount/mount_linux.c (parse_opts): minor cleanup
 
-	* doc/am-utils.texi: MAJOR DOCUMENTATION REVISION COMPLETED!!!
+	* conf/autofs/autofs_linux.c (autofs_handle_fdset): added missing
+	break in case autofs_ptype_expire_multi
 
-	* amd/conf.c (reset_cf_map): Bug fix.  Reset 'tag' field of cfm
-	structure, so it does not carry over from map entry to another.
+2003-08-22  Ion Badulescu  <ionut@moisil.badula.org>
 
-Sat Aug 30 18:39:21 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* conf/autofs/autofs_solaris_v1.h: undefine autofs support if
+	autofs_args_t cannot be determined (hopefully fixes a reported
+	IRIX 6.5.4 problem).
 
-	* amd/amd.c (main): fixed the meaning of the plock option.  A bug
-	caused it to be reversed.
+	* conf/autofs/autofs_solaris_v1.c: wrap entire file in #ifdef
+	HAVE_FS_AUTOFS / #endif (see above)
 
-Sat Aug 30 15:13:18 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/autofs/autofs_linux.h: undefine autofs support if the
+	necessary header files are not found (fixes a reported RedHat 6.2
+	Sparc problem).
 
-	* hlfsd/stubs.c: don't initialize some statics here.  They are
-	better initialized in hlfsd_init_filehandles().
+	* conf/autofs/autofs_linux.c: wrap entire file in #ifdef
+	HAVE_FS_AUTOFS / #endif (see above)
 
-Fri Aug 22 14:47:16 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/mount_fs.c (compute_nfs_args): only use MNT2_NFS_OPT_SOFT
+	if autoconf detected it (fixes a reported RedHat 6.2 Alpha problem).
 
-	* amd/conf.c (gopt_show_statfs_entries): new function and a global
-	amd.conf key show_statfs_entries.  Defaults to 'no'.  If 'yes',
-	then all maps flagged as browsable will also show a count of the
-	number of entries (keys) in that map.
+	* amd/map.c (unmount_mp, unmount_exported): move the code that
+	changes the fattr from NFLNK to NFDIR from unmount_mp to
+	unmount_exported, it was causing troubles (ESTALE) after failed
+	unmounts. This is still very very unclean, but it's the same as the
+	old 6.0 code.
 
-	* amd/nfs_subr.c (count_map_entries): new function to count number
-	of entries in a map.  Now used if browsable is turned on in a map,
-	to return a count of available keys in a given map.
+2003-08-22  Nick Williams <Nick.Williams@morganstanley.com>
 
-	* hlfsd/stubs.c (eq_fh): use correct memcmp().  BUG fixed! hlfsd
-	confused the file handles for ".", "..", and the symlink, causing
-	mess.
+	* amd/info_ldap.c (amu_ldap_init): don't try to pass a null
+	pointer as a string to plog, Solaris (and other OS's) don't like
+	it and will dump core.
 
-	* aux/macros/func_bad_memcmp.m4: new test, based on autoconf 2.12,
-	but also defines HAVE_BAD_MEMCMP, so I avoid linkage conflicts
-	with bad memcmp() in libc's (nextstep3).
+2003-08-13  Ion Badulescu  <ion@guppy.limebrokerage.com>
 
-Thu Aug 21 17:38:41 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amd.h: introduced two new types, wchan_t and opaque_t, as
+	aliases of voidp. This makes reading the code easier on the eyes. :)
 
-	* aux/configure.in: check if autofs_args_t has a field named
-	addr.  Solaris has it for specifying the address of the daemon,
-	but Irix does not.  So how does irix tell the kernel the daemon's
-	address?  I suspect that it is hardcoded to "localhost" using a
-	"private well-known port" (#define AUTOFS_PORT 2048).
+	* ALL: replace various instances of voidp with wchan_t and
+	opaque_t, as appropriate
 
-	* conf/nfs_prot/nfs_prot_linux.h: added missing autofs
-	definitions.
+2003-08-13  Ion Badulescu  <ionut@nicu.badula.org>
 
-	* README.autofs: new file listing autofs support notes
+	* NEWS, configure.in: bumped version up to 6.1b4-pre
 
-	* very preliminary autofs code working.  Call it pre-alpha
-	quality.
+2003-08-13  Ion Badulescu  <ionut@moisil.badula.org>
 
-Sun Aug 17 02:25:09 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* Released beta version 6.1b3
 
-	* amd/conf.c (ropt_mount_type, gopt_mount_type): don't accept
-	"autofs" if system does not support it.
+2003-08-13  Ion Badulescu  <ion@guppy.limebrokerage.com>
 
-	* amd/amd.c (main): log am-utils version string (same as amd -v)
-	at start of run.
+	* conf/autofs/autofs_linux.c (autofs_mount_fs): HACK: always use
+	symlinks for host mounts; assorted fixes for the symlink mode
 
-	* conf/transp/transp_sockets.c (get_nfs_version): in order to tell
-	if a remote host is available, try to contact its portmapper and
-	timeout if no answer is received in 3 seconds.
+2003-08-05  Ion Badulescu  <ionut@moisil.badula.org>
 
-Thu Aug 14 16:12:04 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/umount/umount_default.c (umount_fs): enable space hack
+	handling for autofs v1
 
-	* aux/macros/check_extern.m4 (pattern): use a simpler pattern for
-	match for external function definitions.  The function could span
-	multiple lines, so only match the opening parenthesis, not the
-	closing one too.
+	* amd/map.c (get_first_exported_ap, get_next_exported_ap): new
+	functions that facilitate iterating through the list of
+	mountpoints
 
-	* aux/macros/os_cpp-flags.m4 (ac_cv_os_cppflags,): do NOT turn on
-	posix mode for nextstep3.  It is broken.
+	* amd/amfs_union.c (amfs_union_mounted): use get_first_exported_ap
+	and get_next_exported_ap
 
-	* amd/amd.c (init_global_options): run uname() only if
-	<sys/utsname.h> and uname(2) exist.
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_unmount_2_req): ditto
 
-	* amd/rpc_fwd.c (fwd_packet): if remote host is down, the
-	forwarding socket is null, so declare this an error.
+2003-08-04  Erez Zadok  <ezk@ulkesh.dyn.optonline.net>
 
-	* include/am_utils.h (AM_ERRNO_HOST_DOWN): find best errno to set
-	for when a remote host is down.  Try, in order, "host down", "host
-	unreachable", "invalid argument".
+	* configure.in: check if system stores mount tables in files
+	(usually in /etc), and configure couldn't find a definition for
+	either struct mntent or struct mnttab.  If so, abort configure
+	because this could be a new/misconfigured system, or a bug in
+	am-utils.
 
-	* amd/ops_nfs.c (discard_fh): don't dereference a null pointer
-	(happens when remote host is down, and fp->fh_fs is NULL).
-	(prime_nfs_fhandle_cache): ditto, and set fs flags to !FSF_VALID
-	and FSF_DOWN.
+2003-08-04  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* amd/sched.c: nobody uses "union wait" any more, or so it
-	appears, so clean up that code.
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_umount_fs): fix
+	compile warning
 
-	* conf/transp/transp_tli.c (get_nfs_version): if remote host is
-	down, time it out faster than default (3 seconds).
-	(get_mount_client): free netconfig entry when done with it.
+2003-08-04  Ion Badulescu  <ionut@buggy.badula.org>
 
-	* conf/nfs_prot/nfs_prot_nextstep.h: initial (and somewhat ugly)
-	port to nextstep3 (m68k-next-nextstep3).
+	* conf/autofs/autofs_linux.c (autofs_mount_fs): don't call
+	ops->mount_fs() for an already mounted filesystem
+	(autofs_umount_fs): only call ops->umount_fs() if we're holding
+	the last reference to the filesystem
 
-	* fsinfo/Makefile.am (LDADD): needs to link with libamu in case
-	system does not have strdup().
+	* conf/autofs/autofs_solaris_v1.c (autofs_mount_fs): ditto
+	(autofs_umount_fs): ditto
 
-	* include/am_defs.h: complete external definition for getlogin()
-	if needed.
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_mount_fs): ditto
+	(autofs_umount_fs): ditto
 
-	* conf/transp/transp_tli.c (get_nfs_version): no need to keep
-	static versout variable.
+	* amd/amfs_generic.c (amfs_lookup_mntfs): remove the shortcut for
+	already-mounted filesystems
+	(amfs_cont): only release the autofs_fh if the filesystem is not
+	mounted; add another comment about the NFS_SCALEDOWN hack
+	(amfs_bgmount): if the mntfs is already mounted, skip just the
+	filesystem initialization, but do call mount_node()
 
-	* amd/rpc_fwd.c (fwd_packet): if fwdto packet is null, remote
-	server is probably down.  Don't use sendto() in that case.
+	* amd/map.c (mount_node): always call autofs_mount_fs(), but only
+	call ops->mount_fs() if the mntfs is not yet mounted
+	(unmount_node): always call autofs_umount_fs(), but only call
+	ops->umount_fs() if the refcount on the mntfs equals 1.
 
-	* buildall (default): run gmake if found, before trying plain
-	make.  GNU make is always preferable.
+2003-08-02  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-Tue Aug 12 21:23:58 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/nfs_prot/nfs_prot_openbsd.h: include <ufs/ufs/ufsmount.h>
+	here with the proper workarounds for openbsd3.3 (define MAXQUOTAS,
+	define dummy struct netexport, and include <ufs/ufs/extattr.h>
+	wrapped in _KERNEL).
 
-	* aux/macros/host_macros.m4: cleanup of os_version and os
-	overrides.  Solaris 2.5.1 for example will come up as solaris2 and
-	2.5.1, rather than sunos5 and 5.5.1.  Both can be overridden in
-	the amd.conf file.
+	* conf/nfs_prot/nfs_prot_freebsd3.h: include <ufs/ufs/ufsmount.h>
+	here with the proper workarounds for freebsd5.1 (define dummy
+	struct ufs_extattr_per_mount).
 
-Fri Aug  8 14:37:30 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/nfs_prot/nfs_prot_bsdi2.h: include <ufs/ufs/ufsmount.h>
+	here with the proper workarounds for bsdi2 (define MAXQUOTAS and
+	dummy struct netexport).
 
-	*******************************************************************
-	*** Released am-utils-6.0a9					***
-	*******************************************************************
+	* include/mount_headers1.h: do not include <ufs/ufs/ufsmount.h>
+	here, b/c every *BSD system has some sort of problem in including
+	this header file, which includes ugly workarounds.  Inclusion of
+	this header was already moved out of am_defs.h (used to compile
+	amd), but we forgot to move it out of mount_headers1.h (used to
+	configure).  The specific inclusion of ufsmount.h is now in the OS
+	specific nfs_prot.h file.
 
-Thu Aug  7 00:52:14 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: if configure could not find any definition for
+	"struct nfs_args", abort configure with an explanatory message.
+	There's no point in continuing, as this could be a system bug,
+	buggy am-utils, or a new system to which am-utils wasn't ported to
+	yet.
 
-	* conf/nfs_prot/nfs_prot_ncr2.h: new file, for NCR2
-	(i486-ncr-sysv4.3.03) headers.  Needed to complete missing stuff
-	from <ndbm.h> and <sys/resource.h>.
+	* minor new port: i386-pc-solaris2.9
 
-	* scripts/amd.conf.5: new map page.
+2003-08-01  Ion Badulescu  <ionut@buggy.badula.org>
 
-	* amd/info_hesiod.c: define extern for hesiod_resolve, since bsdi3
-	does not.
+	* doc/am-utils.texi (NFS-Link Filesystem): make the documentation
+	match the code (as well as basic logic operations: the negation of
+	'a or b' is 'not a and not b', not 'not a or not b')
 
-	* amd/amd.8: updated man page.
+2003-08-01  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-	* amd/get_args.c (get_args): removed defunct -h option to amd.
+	* minor new port: i386-unknown-openbsd3.3.
 
-	* amq/amq.8: updated man page.
+	* m4/macros/check_libwrap_severity.m4: new macro to check if
+	libwrap includes the integer variables deny_severity and
+	allow_severity, since some libwrap implementations do and others
+	don't.  The test tries to compile and run a simple empty main()
+	program, then the same program while defining these two variables:
+	comparing the results of the two tests, we can tell whether we
+	should define NEED_LIBWRAP_SEVERITY_VARIABLES.
 
-	* amd/info_nisplus.c (nisplus_search): prototype fixes so Sun
-	SparcCompiler CC won't complain.
+	* Makefile.am (EXTRA_DIST_M4): distribute new macro
+	check_libwrap_severity.m4.
 
-	* amd/info_hesiod.c (hesiod_search): small fixes to compile with
-	hesiod-1.3, as per Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>.
+	* m4/macros/header_templates.m4: template for HAVE_LIBWRAP (which
+	we must define explicitly since we've overridden the
+	action-if-found in AC_CHECK_LIB(wrap).  Also template for
+	NEED_LIBWRAP_SEVERITY_VARIABLES.
 
-	* aux/macros/opt_ldflags.m4: new option added to configure
-	--enable-ldflags, to specify -L option for configuring/compiling.
-	The older one --enable-libs is now to be used only for -l options.
+	* amd/amq_svc.c: if libwrap does not include the severity
+	variables, then define and initialize them here.
 
-	* amd/ops_nfs.c (mount_nfs_fh): bug fixed.  Should initialize
-	nc_protoname from nfs_proto if available for all TLI systems, not
-	just those that have NFS V3.
+	* amd/Makefile.am (LIBS): explicitly include @WRAPLIB@ only for
+	Amd binary.  Other am-utils binaries don't need -lwrap.
 
-	* amd/info_ldap.c: ldap patches from Leif Johansson
-	<leifj@matematik.su.se>, adding two new amd.conf ldap variables:
-	ldap_cache_seconds and ldap_cache_maxmem.
+	* configure.in: if libwrap is found, only define it in @WRAPLIB@,
+	so we don't automatically link every am-utils binary with -lwrap.
+	Run test for existence of severity variables in libwrap.
 
-	* hlfsd/hlfsd.c (main): bug fixed. port number must be wrapped in
-	htons().
+2003-07-31  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-Sun Aug  3 17:20:05 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/nfs_prot/nfs_prot_openbsd.h: define struct fattr fields uid
+	and gid.
 
-	* amd/nfs_start.c (mount_automounter): register amd with the rpc
-	program number that may have been overridden by amd.conf.
+	* configure.in: move check for AC_CHECK_LIB(libwrap) as far down
+	as possible because on modern tcpwrapper systems such as openbsd,
+	the caller must provide two symbols: deny_severity and
+	allow_severity, which determine the logging level of rejected and
+	requested requests, respectively.  If this check happens too
+	early, then $LIBS includes -lwrap, which causes many subsequent
+	tests that need to run a compiled program to fail with missing
+	symbols.
 
-	* libamu/xutil.c (set_amd_program_number, get_amd_program_number):
-	allow storing and retrieving alternate amd program numbers.
+	* m4/macros/header_templates.m4: fix typo in template for
+	readdirplus.
 
-	* amd/conf.c (gopt_portmap_program): new function to parse
-	amd.conf entry portmap_program=1234.
+	* configure.in: check for <ufs/ufs/extattr.h> (OpenBSD 3.3)
 
-	* amq/amq.c (main): allow specifying an alternate rpc program
-	number for amd via -P prognum.
+	* minor new port: i386-unknown-netbsdelf1.6.1.
 
-	* new amq RPC to get the process id of the running amd.  This is
-	used in ctl-amd to quickly find the pid of the amd that is to be
-	killed.
+	* configure.in: save state before system-specific tests are run.
 
-	* expanded shared libraries support.  Using GNU libtool-1.0,
-	am-utils now builds shared libraries on many platforms that have
-	support for it and proper compilers/linkers.  See "INSTALL" file
-	for compatibility chart.
+	* m4/macros/check_gnu_getopt.m4: do NOT abort ./configure just
+	because the compiled test program failed to run.
 
-Thu Jul 31 13:07:23 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-08-01  Ion Badulescu  <ionut@buggy.badula.org>
 
-	* fsinfo/fsi_lex.l: removed code that was in support of very old
-	versions of flex.  No longer needed.
+	* NEWS, README.autofs: updated
 
-Tue Jul 29 12:00:13 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/mount_fs.c (mount_fs): added support for the space hack
 
-	* amd/amd.c (init_global_options): find the kernel architecture
-	from uname() if possible.
+	* doc/am-utils.texi: mention than UFS/XFS/EFS/CacheFS filesystems
+	are not expired by default; correct and expand the section
+	describing the program filesystem
 
-Mon Jul 28 03:53:59 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/autofs/autofs_solaris_v2_v3.h (AUTOFS_*_FS_FLAGS): add
+	FS_ON_AUTOFS for supported filesystems
 
-	* new working port: i386-unknown-openbsd2.1
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_mount_fs): call
+	mf->mount_fs()
+	(autofs_umount_fs): call mf->umount_fs()
 
-Fri Jul 25 03:16:31 1997  Erez Zadok  <ezk@felix.psl.cs.columbia.edu>
+	* conf/autofs/autofs_solaris_v1.h (autofs_strdup_space_hack): add
+	prototype for malloc()
+	(AUTOFS_*_FS_FLAGS): lose the FS_MKMNT flags, add FS_ON_AUTOFS for
+	supported filesystems
 
-	* working port: sparc-sun-solaris2.4.  Had to fix fhandle_t from
-	structure to actual char[], because the structure was passed to
-	xdr_fhandle as data and not a pointer.  Surprisingly, gcc
-	-fpcc-struct-return did not help.
-	
-	* conf/nfs_prot/nfs_prot_sunos5_4.h: special nfs protocol
-	definitions for solaris 2.4 have to be different from 2.3, and
-	different from 2.5.
+	* conf/autofs/autofs_solaris_v1.c (autofs_mount_fs): add support
+	for the space hack; call mf->mount_fs()
+	(autofs_umount_fs): add support for the space hack; call
+	mf->umount_fs()
+	(autofs_mount_succeeded): add support for the space hack
 
-	* libamu/xdr_fhstatus.c (xdr_fhstatus): minor code cleanup.
+	* conf/autofs/autofs_linux.h: lose the FS_MKMNT flags, add
+	FS_ON_AUTOFS for supported filesystems
 
-Thu Jul 24 16:22:39 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/autofs/autofs_linux.c (AUTOFS_MAX_VERSION): define to
+	AUTOFS_MAX_PROTO_VERSION instead of hardcoding to 4
+	(autofs_mounted): host mounts are now supported on all autofs
+	versions, remove the hack to turn it off on v3
+	(autofs_mount_fs): call mf->mount_fs(), create/remove mountpoints
+	as needed
+	(autofs_umount_fs): call mf->umount_fs(), remove mountpoints on
+	success
+	(ALL): use '#if AUTOFS_MAX_VERSION >= 4' instead of
+	'#ifdef autofs_ptype_expire_multi'
 
-	* conf/mount/mount_svr4.c (mount_svr4): use STREQ to compare mount
-	types, not ==.  Fix from Christos Zoulas <christos@deshaw.com>.
+	* amd/map.c (mount_node): autofs_mount_fs() now calls
+	mf->mount_fs() internally
+	(unmount_node): autofs_umount_fs() now calls mf->umount_fs()
+	internally
 
-	* mk-amd-map/mk-amd-map.8: man page taken from bsd44.
+	* amd/autil.c (am_mounted): minor cleanup
 
-Thu Jul 24 00:01:55 1997  Erez Zadok  <ezk@moisil.cs.columbia.edu>
+	* amd/amfs_program.c (amfs_program_ops): added FS_MKMNT to
+	nfs_fs_flags
 
-	* conf/mount/mount_linux.c: made the nfs error mapping code into a
-	small function.
+	* amd/amfs_generic.c (amfs_lookup_one_mntfs): use the FS_ON_AUTOFS
+	flag instead of hardcoding filesystem types
+	(amfs_bgmount): better mount_type logging
 
-Wed Jul 23 16:11:49 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amd.h (FS_ON_AUTOFS): new flag which tells the code that
+	this filesystem can be mounted directly onto an autofs mountpoint
 
-	* conf/nfs_prot/nfs_prot_linux.h (NFS_ERROR_MAPPING): special
-	error mappings from errno numbers to NFS errors.  From Debian
-	Linux.
+2003-07-31  Ion Badulescu  <ionut@buggy.badula.org>
 
-	* scripts/am-eject.in (fs): new script (taken from Debian Linux
-	folks) to auto-unmount floppy/cd devices before ejecting them.
+	* amd/amfs_nfsl.c (amfs_nfsl_umount): fix copy&paste error (was
+	calling amfs_link_ops.umount_fs() for NFS filesystems)
+	(amfs_nfsl_umounted): remove rmdirs() hack, it is now handled
+	properly elsewhere
+	(amfs_nfsl_ffserver): remove FS_MKMNT from mf_fsflags if we're
+	using link (not NFS)
 
-	* fsinfo/wr_exportfs.c (write_exportfs): from Debian folks, pass
-	'5' as second arg to show_area_being_processed.  I'm not sure why.
+2003-07-31  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* fsinfo/wr_atab.c (write_atab): from Debian folks, pass '5' as
-	second arg to show_area_being_processed.  I'm not sure why.
+	* README.autofs: Correct IRIX spelling.
+	AutoFS support exists only on IRIX 6.
+	Update IRIX 6 status.
 
-	* conf/mount/mount_linux.c (parse_opts): as per Debian Linux,
-	ensure that you have a buffer in *xopts to strcat onto.
-	(mount_linux): fixed from Debian folks to ensure that NFS mount
-	sockets are connected only for kernels prior to 1.3.10 (avoids
-	hangs for multi-homed hosts).
+	Allow AutoFS V1 support to compile on IRIX 6.
+	* conf/autofs/autofs_solaris_v1.c (autofs_mount_1_req): Add
+	SVCXPRT * arg.
+	Remove superfluous \n from dlog messages.
+	(autofs_unmount_1_req): Likewise.
+	Switch to get_exported_ap.
+	(autofs_program_1): Invoke handlers with additional transp arg.
+	* conf/autofs/autofs_solaris_v1.h: Use autofs_args_t to define
+	autofs_fh_t, struct auto_args doesn't exist on IRIX 6.
 
-	* amd/mapc.c (make_entry_chain): from Debian folks: don't skip
-	over amd map keys that have a prefix, and include the prefix in
-	the returned readdir().
+	* conf/mount/mount_irix6.c (mount_irix) [HAVE_FS_AUTOFS]: Support
+	AutoFS mounts.
+	[HAVE_FS_LOFS]: Likewise for lofs mounts.
 
-	* amd/info_passwd.c (passwd_init, passwd_search): format
-	enhancements from the Debian Linux folks.  They added
-	- var0:=pw-prefix:=anydir
-	- var1:=pw-rhost:=dom3.dom2.dom1
-	- var2:=pw-user:=user
-	- var3:=pw-home:=/anydir/dom1/dom2/dom3/user
+	* conf/nfs_prot/nfs_prot_irix6.h (AUTOFS_CONFTYPE): Define.
+	Don't disable AutoFS support any more.
 
-	* new ports: sparc-sun-solaris2.4 and sparc-sun-sunos4.1.1.
+	* conf/transp/transp_sockets.c [HAVE_FS_AUTOFS && AUTOFS_PROG]
+	(register_autofs_service): Define autofs_xprt.
 
-	* amd/ops_afs.c (afs_retry): patches from Debian Linux.  If
-	afs_mount timed out, then explicitly forbid further retries after
-	the timeout.  (afs_bgmount): buf fix from Debian Linux.  Timeout
-	values (17 and 5) were mistakenly swapped.
+	* m4/macros/check_autofs_style.m4 (AMU_CHECK_AUTOFS_STYLE): Update
+	Solaris 8+ comment to mention AutoFS V4.
+	(irix6*): Enable AutoFS V1 support on IRIX 6.
 
-Wed Jul 23 15:53:25 1997  Erez Zadok  <ezk@felix.psl.cs.columbia.edu>
+2003-07-30  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_sunos5_3.h: turn off non-existent NFS V.3
-	support for Solaris 2.4 (the header files incorrectly define parts
-	of the NFS V.3 protocol, but the kernel does not support it).
+	* NEWS, doc/am-utils.texi, scripts/amd.conf.5: revised explanation
+	of autofs_use_lofs.
 
-Wed Jul 23 00:07:12 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-07-30  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* amd/info_hesiod.c: minor cleanup to use hes_init and hesiod_init
-	for determining if using old or new hesiod libraries,
-	respectively.
+	* amd/ops_efs.c (efs_mount): Replace on_autofs arg with
+	MFF_ON_AUTOFS flag.
+	(efs_umount): Likewise.
 
-	* amd/ops_nfs.c (mount_nfs_fh): If "noconn" option exists in NFS
-	V.3 then use non-connected sockets (both TCP and UDP).  Otherwise
-	they cause hangs of mounts from multi-homed hosts when the return
-	route is not the same as the outgoing route (esp. on NetBSD
-	1.2.1).  If "conn" option was supplied, then don't turn on the
-	"noconn" mount option.  Otherwise default to "noconn" mount
-	option.
+2003-07-30  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-	* aux/configure.in: better check for systems that need libgdbm and
-	<ndbm.h>
+	* conf/umount/umount_bsd44.c (umount_fs): convert to new way of
+	unmounting which takes autofs into account.
 
-Tue Jul 22 04:02:05 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+2003-07-30  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* hlfsd/hlfsd.c (main), amd/ops_afs.c (mount_toplvl): ensure that
-	mounts are hidden from df(1) on systems that keep mount tables in
-	kernel, such as osf1.
+	* ALL: renamed MFF_AUTOFS to MFF_IS_AUTOFS; removed mf_real_mount
+	hack; pass a new on_autofs argument to mount/umount function,
+	based on the MFF_ON_AUTOFS mntfs flag
 
-Tue Jul 22 02:26:55 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* NEWS, README.autofs: updated
 
-	*******************************************************************
-	*** Released am-utils-6.0a8					***
-	*******************************************************************
+	* scripts/amd.conf.5: document new option autofs_use_lofs
 
-Mon Jul 21 21:33:19 1997  Erez Zadok  <ezk@stone.mcl.cs.columbia.edu>
+	* scripts/amd.conf-sample (autofs_use_lofs): document new option
 
-	* hlfsd/hlfsd.c (main): bug fixed: forgot to set sin_family to
-	AF_INET when hlfsd mounts itself, thus getting an errno "protocol
-	family not supported".
+	* m4/macros/check_autofs_style.m4 (am_utils_link_files): symlink
+	the autofs header as amu_autofs_prot.h instead of slurping it into
+	aux_conf.h
 
-Mon Jul 21 20:46:59 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/mount_fs.c (mount_fs): removed old stub, renamed
+	mount_fs2 to mount_fs, added new argument on_autofs
 
-	* verified that amd on NetBSD 1.2.1 (i386) works, but the OS
-	itself is flaky.
+	* doc/am-utils.texi (Direct Automount Filesystem): document
+	problems with nfs direct mounts on modern kernels, document good
+	autofs support for direct mounts on Solaris
+	(autofs_use_lofs Parameter): document this new option
+	(browsable_dirs Parameter): note that mount storms are avoided
+	when using autofs
 
-	* verified that amd AIX 3 works w/ the new readdir() code.
+	* conf/umount/umount_bsd44.c (umount_fs): removed old stub,
+	renamed umount_fs2 to umount_fs
 
-Mon Jul 21 18:59:30 1997  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
+	* conf/umount/umount_osf.c (umount_fs): removed old stub,
+	renamed umount_fs2 to umount_fs, added new argument on_autofs
 
-	* amd/mapc.c (maptypes): changed the default map caching type for
-	nis and ndbm maps to "MAPC_ALL", so that all possible entries will
-	be available to amd for browsable_dirs=yes.
+	* conf/umount/umount_default.c (umount_fs): ditto as above; return
+	an error on ENOENT instead of faking success
 
-Mon Jul 21 18:04:16 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_lookup_2_req): much
+	simplified, now only consults the map for existance of the key and
+	returns success if key is found
+	(autofs_mount_2_req): request symlinks if CFM_AUTOFS_USE_LOFS is
+	not on;
+	(autofs_mount_2_free): implemented
+	(autofs_unmount_2_req): use get_exported_ap() instead of
+	referencing export_ap directly
+	(autofs_mount_succeeded): remove code for replying to lookup
+	requests, now only mount requests can end up here
+	(autofs_mount_failed): ditto
 
-	* amd/ops_afs.c (afs_readdir, afs_readdir_browsable): split
-	afs_readdir into a browsable version and a non-browsable one.
-	Fixed bugs that resulted in an infinite nfs_readdir loop on the
-	localhost for some operating systems.
+	* conf/autofs/autofs_solaris_v1.h (AUTOFS_HOST_FS_FLAGS): removed
+	FS_AUTOFS
+	(AUTOFS_DIRECT_FS_FLAGS): added FS_DIRECTORY
 
-Sat Jul 19 19:38:38 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/autofs/autofs_solaris_v2_v3.h (AUTOFS_HOST_FS_FLAGS): removed
+	FS_AUTOFS
+	(AUTOFS_DIRECT_FS_FLAGS): added FS_DIRECTORY
+	(AUTOFS_LINK_FS_FLAGS): added FS_MBACKGROUND
 
-	* amd/ops_afs.c (afs_readdir): fixed up the browsable code to
-	comply with nfs_readdir specs.  It was returning all entries at
-	once, even if there was not enough space in the RPC packet.  Now,
-	it sends a reasonably sized chunk, and sets static state to resume
-	it for the next continuation RPC of readdir.
+	* conf/autofs/autofs_linux.c (autofs_bind_umount): new function,
+	factored out of autofs_umount_fs()
+	(autofs_mount_fs): renamed from autofs_link_mount() and expanded
+	to deal with filesystems mounted indirectly (via lofs/bind
+	mounts) on autofs and to observe the new CFM_AUTOFS_USE_LOFS flag
+	(autofs_umount_fs): ditto, from autofs_link_umount()
 
-	* amd/conf.c (set_conf_kv): fixed bug that resulted in the first
-	regular map not getting all of the [global] options defaulted from.
+	* conf/autofs/autofs_solaris_v1.c (autofs_mount_fs): ditto
+	* (autofs_umount_fs): ditto
 
-Fri Jul 18 00:45:12 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_mount_fs): ditto
+	* (autofs_umount_fs): ditto
 
-	* amq/amq.c (main): fixed so that portmapper "ping" will only fail
-	upon an RPC timeout
+	* amd/opts.c: made fs_static static
 
-	* scripts/ctl-{amd,hlfsd}.in (killproc): better method to find the
-	amd/hlfsd process to kill.
+	* amd/ops_nfs.c: made nfs_init, nfs_match, nfs_mount, nfs_umount
+	and nfs_umounted static
+	(mount_nfs_fh): removed unnecessary arguments
 
-	* amd/ops_afs.c (mount_toplvl), hlfsd/hlfsd.c (main): code to
-	determine how to avoid df from seeing amd's toplvl mounts.  Moved
-	from libamu/mount_fs.c and include/am_utils.h.  Ensure that hlfsd
-	is hidden from df.
-	(mount_toplvl): fixed df types for irix.
+	* amd/ops_cachefs.c (cachefs_ops): use amfs_generic_find_srvr for
+	the ffserver method, because using NULL causes problems
 
-Thu Jul 17 21:59:45 1997  Erez Zadok  <ezk@americas.psl.cs.columbia.edu>
+	* amd/ops_cdfs.c (cdfs_ops): ditto
 
-	* amq/amq.c (main): fixed bug that caused the 5 second timeout for
-	TLI amq using udp to be ignored.
-	(main): if amq cannot contact remote host's portmapper within 5
-	seconds, timeout and fail faster than the default longer timeout
-	(this is for non-TLI systems).
+	* amd/ops_efs.c (efs_ops): ditto
 
-Thu Jul 17 17:08:13 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/ops_lofs.c (lofs_ops): ditto
 
-	* amq/amq.c (get_secure_amd_client): if amq cannot contact
-	remote host's portmapper within 5 seconds, timeout and fail faster
-	than the default TLI timeout of over 4 minutes.
+	* amd/ops_pcfs.c (pcfs_ops): ditto
 
-	* amd/am_ops.c (ops_showfstypes): added styles for new bsd44
-	file systems nullfs, unionfs, and umapfs.
-	(ops_show1): cleanup code and and reuse this function.
-	(vops): empty placeholders for nullfs, unionfs, and umapfs.
+	* amd/ops_ufs.c (ufs_ops): ditto
 
-	* amd/ops_{nullfs, unionfs, umapfs}.c: 3 new empty templates for
-	bsd44 style file systems.
+	* amd/ops_xfs.c (xfs_ops): ditto
 
-	* fsinfo/fsinfo.8: man page for fsinfo rewritten from bsd44
-	sources.
+	* amd/nfs_subr.c (fh_to_mp3, fh_to_mp, mp_to_fh): moved here from
+	map.c
 
-	* amd/conf_tok.l, fsinof/fsi_lex.c: undefine ECHO to avoid
-	conflict with systems that define it in <sys/ioctl.h> and also
-	define a conflicting one via lex.  Newer versions of f/lex are ok.
+	* amd/nfs_start.c: use get_exported_ap() instead of referencing
+	exported_ap directly
 
-Wed Jul 16 00:17:45 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/mntfs.c (locate_mntfs): new function, factored out of
+	find_mntfs
+	(locate_mntfs): special-case FS_DIRECT filesystems: for direct
+	mounts we will have two filesystems mounted on the same m/p
+	(realloc_mntfs): removed the old EZK hack for failovers
 
-	* amd/ops_nfs.c (mount_nfs_fh): fill in nfs_args' fields
-	acdirmin/max and acregmin/max only if they exist.
+	* amd/map.c (get_exported_ap): new function that returns an
+	exported_ap member by its index
+	(root_node,exported_ap,exported_ap_size,first_free_map,last_used_map):
+	made static
+	(fh_to_mp3, fh_to_mp, mp_to_fh): moved to nfs_subr.c
+	(get_root_ap): removed unused second argument
+	(unmount_mp): moved the mk_fattr(NFDIR) here from umount_exported
+	to catch more cases
+	(mount_node): call autofs_mount_fs after ops->mount_fs for autofs
+	nodes
+	(unmount_node): call autofs_umount_fs before ops->umount_fs for
+	autofs nodes
 
-	* aux/configure.in: test for nfs_args fields acdirmin and
-	acregmin.
+	* amd/conf.c: new global option "autofs_use_lofs", takes yes/no
+	values
 
-Tue Jul 15 17:24:09 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/autil.c (amfs_mount): take an extra argument (mf)
+	(amfs_mount): call autofs_compute_mount_flags() for mounts
+	directly on autofs m/p
+	(am_unmounted): document and avoid the race between am_umounted()
+	at shutdown time and amfs_cont()
 
-	* aux/configure.in: commented out checking for MNT2_GEN_OPT_* for
-	"nondev" and commented back in checking for "nodev".  This was a
-	typo.
+	* amd/amfs_union.c (amfs_union_mounted): use get_exported_ap()
+	instead of referencing internal map variables directly
 
-	* include/am_compat.h: more compatibility options: define "ro"
-	mnttab option all the time.  Define "overlay" as needed.  Added
-	more fillers of mnttab options (as per Daniel S. Riley
-	<dsr@mail.lns.cornell.edu>), for acdirmax, acdirmin, acregmax,
-	acregmin, noac, grpid, nosuid, and actimo.
+	* amd/amq_subr.c (amqproc_export_1_svc): ditto
 
-	* libamu/mount_fs.c (mnt_flags): fixed a typo in "ro" option as
-	per dsr@mail.lns.cornell.edu (Daniel S. Riley).  Then cleaned up
-	the same code for other options in struct opt_tab.
+	* amd/amfs_toplvl.c (amfs_toplvl_ops): removed FS_AUTOFS from
+	nfs_fs_flags
+	(amfs_toplvl_mount): pass extra argument (mf) to amfs_mount()
+	(amfs_toplvl_umount): refuse to attempt the unmount if the
+	mountpoint is not a directory
 
-Mon Jul 14 22:36:37 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_nfsx.c (amfs_nfsx_init): propagate the MFF_ON_AUTOFS
+	flag into the nfs f/s at the bottom of the stack
 
-	* amd/get_args.c (get_args): moved amd.conf file parsing to before
-	the switching the default log/debug options.  Suggested by
-	dsr@mail.lns.cornell.edu (Daniel S. Riley).
+	* amd/amfs_nfsl.c: call nfs and link member functions through
+	their respective am_ops structures, not directly
 
-	* aux/update_build_version: new script to record the build version
-	of amd, along with the rest of the info thet comes up with amd -v.
+	* amd/amfs_linkx.c (amfs_linkx_umount): new static stub
 
-Sun Jul 13 00:30:24 1997  Erez Zadok  <ezk@decca.damtp.cam.ac.uk>
+	* amd/amfs_link.c: made amfs_link_mount() and amfs_link_umount()
+	static functions
+	(amfs_link_mount): removed call to autofs_link_mount()
+	(amfs_link_umount): removed call to autofs_link_umount()
 
-	* aux/macros/os_cflags.m4: new macro, to add additional
-	compilation options (also used during configuration), based on the
-	OS and the compiler.  Used for solaris-2.6, osf, and irix6.
+	* amd/amfs_host.c (amfs_host_ops): removed FS_AUTOFS from
+	nfs_fs_flags
+	(do_mount): removed superfluous function arguments
 
-Fri Jul 11 10:15:11 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amfs_direct.c (amfs_direct_ops): removed FS_AUTOFS from
+	nfs_fs_flags
 
-	* amd/conf_tok.l, conf_parse.y: allow values of keys to include
-	white spaces, if they are double-quoted (key="some value")
+	* amd/amfs_auto.c (amfs_auto_ops): removed FS_AUTOFS from
+	nfs_fs_flags
+	(amfs_auto_mount): pass extra argument (mf) to amfs_mount
 
-	* amd/info_hesiod.c (hesiod_search): cleanup and minor bug fixes
-	of hesiod from Danny Braniss <danny@cs.huji.ac.il>.
+	* amd/amd.h (CFM_AUTOFS_USE_LOFS): new flag, tells amd whether to
+	use lofs-mounts or symlinks when mounting on autofs
+	(CFM_DEFAULT_FLAGS): added CFM_AUTOFS_USE_LOFS
+	(VLOOK_LOOKUP): new flag, will merely check if a key exists
+	(MFF_IS_AUTOFS): renamed from MFF_AUTOFS
+	(MFF_ON_AUTOFS): new flag, tells amd if a f/s is mounted directly
+	on an autofs m/p, or indirectly via a lofs mount/symlink
+	(fh_to_mp2): macro expanded throughout the code and removed
+	(mntfs): removed mf_real_mount hack
+	(autofs_mount_fs): renamed from autofs_link_mount
+	(autofs_umount_fs): renamed from autofs_link_umount
+	(mount_lofs): exposed
+	various other cleanups, functions/variables made static and removed
 
-Fri Jul 11 02:16:06 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* aux_conf.h.in: removed @am_utils_autofs_style@, it is now
+	included directly as amu_autofs_prot.h
 
-	*******************************************************************
-	*** Released am-utils-6.0a7					***
-	*******************************************************************
+2003-07-24  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
 
-Thu Jul 10 12:19:25 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* doc/am-utils.texi, scripts/amd.conf.5: document that
+	use_tcpwrappers is "yes" by default.
 
-	* include/am_defs.h: fill in extern definition of innetgr() in
-	case system headers don't.
+	* amd/amd.c (init_global_options): set default global options.
 
-	* aux/macros/path_prog_lex.m4 aux/configure.in: using macros that
-	will show the full pathname to yacc/bison and f/lex.  Some systems
-	have older or bad versions of those and this way the user will
-	know for sure what is being invoked.
+	* amd/amd.h (CFM_DEFAULT_FLAGS): define default options which
+	are always on (plock and use_tcpwrappers).
 
-	* tasks: file populated with todo items.
+	* scripts/amd.conf-sample: reorganize values per option so default
+	one is listed first.
 
-	* scripts/amd2ldif.in: Script to convert amd maps to plain text
-	LDAP object files.  Contributed by Leif Johansson
-	<leifj@matematik.su.se>.
+2003-07-23  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-	* aux/config.guess: added recognition for sun3's running 4.2bsd,
-	from Tom Schmidt <tschmidt@micron.com>.  Fixed one small typo.
+	* tasks: trim old stuff.  Discuss new parser.
 
-	* amd/conf.c: several variables that were local to a map, were
-	also added to [global], where they apply to all maps.  Each map
-	can then individually override those defaults.  Flags
-	affected: browsable_dirs and mount_type.  Options affected:
-	map_type, map_options, and search_path.
+	* amd/conf.c (set_conf_kv): initialize the very first map in conf
+	file from global defaults.  Bug fix which was introduced after
+	conf.c code restructuring.
 
-	* amd/amd.h: eliminated several global flags each of which took an
-	int, in favor of one global flags variable used as a bit field.
+2003-07-18  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-	* amd/amd.c (init_global_options): moved all global variables into
-	a single struct amu_global_options, so it is easier to add new
-	ones and/or identify existing ones.
+	* m4/macros/header_templates.m4: template for
+	HAVE_EXTERN_HOSTS_CTL.
 
-	* amd/get_args.c (get_args): removed unused amd -m option.
+	* include/am_defs.h: define extern for hosts_ctl() if needed.
 
-	* amd/conf.c (gopt_cluster): added new amd.conf option for cluster
-	name, same as amd -C.
+	* configure.in (AMU_CHECK_EXTERNS): check for extern definition
+	for libwrap's hosts_ctl() (FreeBSD 5.0 doesn't have it).
 
-	* amd/info_ldap.c: LDAP info map functions from Leif Johansson
-	<leifj@matematik.su.se>.
+	* m4/macros/check_extern.m4: include tcpd.h if it and libwrap exist.
 
-	* amd/conf.c (gopt_ldap_base, gopt_ldap_hostports): put in global
-	amd.conf options for ldap_base and ldap_hostports.
+2003-07-18  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/opts.c (f_netgrp): new amd map function netgrp(ARG) to test
-	if the current host is in the ARG host netgroup.
+	* hlfsd/hlfsd.h: redundant extern for mboxfile removed.
 
-	* aux/configure.in: some systems replaced dbm in libc with GNU's
-	libgdbm, so check for libgdbm, but only if dbm_open is not in
-	libc already.  This was a recommendation from Tom Schmidt
-	<tschmidt@micron.com>.
+	* amd/amq_svc.c (amq_program_1): only check for tcpwrappers if
+	amd.conf global option use_tcpwrappers=yes.
 
-	* conf/nfs_prot/nfs_prot_sunos5_3.h: port to sparc-sun-solaris2.3
-	completed.
+	* scripts/amd.conf.5, scripts/amd.conf-sample (use_tcpwrappers),
+	doc/am-utils.texi (use_tcpwrappers Parameter): document new
+	amd.conf global option.
 
-Wed Jul  9 18:14:59 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/conf.c (gopt_use_tcpwrappers): define a new amd.conf global
+	option called use_tcpwrappers ("no" by default).
 
-	* port to sparc-unknown-netbsd1.2E done, not tested.  Includes NFS
-	V.3.
+	* amd/amq_svc.c (amqsvc_is_client_allowed): include tcpd/libwrap
+	code only if both libwrap and tcpd.h exist.
+	(amq_program_1): log warning when an Amq service client is denied,
+	and a debug message when a client is allowed.
 
-Tue Jul  8 17:35:07 1997  Erez Zadok  <ezk@elk.mcl.cs.columbia.edu>
+	* amd/amd.h (CFM_USE_TCPWRAPPERS): define [global] amd.conf flag.
+	(AMD_SERVICE_NAME): define AMD_SERVICE_NAME for tcpd/libwrap.
 
-	* port to i386-unknown-freebsd3.0 done and working.  Includes NFS
-	V.3.
+	* include/am_defs.h: include tcpd.h if available and libwrap
+	available.
 
-	* aux/macros/check_nfs_fh_dref.m4: freebsd3 should use
-	file handle dereferencing style similar to freebsd22.
+	* configure.in: check for tcpd.h.
 
-	* include/am_defs.h: need to include <net/if_var.h> before
-	<netinet/if_ether.h> on freebsd3.
+2003-07-18  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_freebsd3.h: new protocol header additions
-	for freeBSD 3.0.
+	* scripts/expn.1, amd/amd.8 amq/amq.8, fixmount/fixmount.8,
+	hlfsd/hlfsd.8, scripts/expn.1: remove ".PD 0" nroff command
+	because it removes useful spaces in between paragraphs.  Based on
+	smaller patch from Philippe Troin <phil@fifi.org>.
 
-Tue Jul  8 16:53:41 1997  Erez Zadok  <ezk@moisil.cs.columbia.edu>
+2003-07-17  Philippe Troin  <phil@fifi.org>
 
-	* amd/info_nis.c (nis_reload): cast nis' callback function so
-	picky compilers won't complain.
+	* amq/amq.8: Document the libwrap/amd behavior.
 
-	* libamu/xdr_mountres3.c (xdr_mountres3): make sure this function
-	gets compiled only if the system has NFS V3 and does not have
-	xdr_mountres3.
+	* amd/amq_svc.c (libwrap_check_client): New function to validate
+	an amq connection with libwrap.
+	(amq_program_1): Call libwrap_check_client() and close the
+	connection if libwrap does not allow it.
 
-Tue Jul  8 12:42:03 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* configure.in: Check for the tcp wrappers library.
 
-	* COPYING: put in some legal stuff in this file.
+2003-07-17  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-Mon Jul  7 19:10:44 1997  Erez Zadok  <ezk@prometheus.soscorp.com>
+	* amd/amq_subr.c (amqproc_mnttree_1_svc, amqproc_stats_1_svc,
+	amqproc_getmntfs_1_svc, xdr_amq_mount_tree), hlfsd/hlfsd.c
+	(hlfsd_init): cast pointers to void* before casting them to
+	another type, to avoid gcc-3.3 -Wall warnings.
 
-	* NFS V3 now works under Irix5, thanks to patches from 
-	Andreas Stolcke <stolcke@speech.sri.com>.
+	* fsinfo/*.[hc]: rename fsinfo function log() to fsi_log(), to
+	avoid conflict with builtin function in gcc-3.3.
 
-	* conf/mount/mount_irix5.c: sparate mount_irix.c into an irix5
-	version and an irix6 version, since irix5's NFS V3 code is broken
-	and hacky.
+2003-07-17  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* amd/info_hesiod.c (hs_zone_transfer): minor fixes to buffer
-	sizes for some hesiod queries.  Patch from Danny Braniss
-	<danny@cs.huji.ac.il>.
+	* scripts/amd.conf-sample: Remove obsolete comment.
 
-Mon Jul  7 19:04:14 1997  Erez Zadok  <ezk@glory.soscorp.com>
+2003-07-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/ops_nfs.c (mount_nfs_fh): fixed NFS V.3 support for bsdi3.
+	* amd/info_file.c (read_line): check for errors from fgets().
+	Although rare, they can occur upon disk or network failures.
+	Patch from Nick Williams <Nick.Williams@morganstanley.com>.
 
-Sun Jul  6 14:22:24 1997  Erez Zadok  <ezk@glory.soscorp.com>
+2003-07-16  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
-	* aux/{configure.in,acconfig.h}: added checks for struct
-	nfs_args's fields proto and sotype (bsdi3).
-	
-	* amd/ops_nfs.c (mount_nfs_fh): added nfsv3 option to
-	nfs_args.flags for bsdi3.  Set field proto to 0.  Set sotype field
-	to SOCK_STREAM or SOCK_DGRAM.
+	* BUGS (Solaris 8): Update patch revisions, mention old autofs
+	patches, fix filenames and rpcgen command.
 
-	* aux/macros/check_mount_style.m4: add case for bsdi3.
+2003-07-15  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
 
-	* amd/info_hesiod.c: got hesiod support for bsdi3.
+	* doc/am-utils.texi (map_defaults Parameter): document new
+	map_defaults option.
 
-Sun Jul  6 11:14:47 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* scripts/amd.conf.5: document new map_defaults option.
 
-	* aux/configure.in: look for hesiod on libc (bsdi3)
+	* scripts/amd.conf-sample (map_type): show examples of new
+	map_defaults option.
 
-	* amd/get_args.c (get_args): reformat usage so it fits in 80
-	columns.
+	* amd/mapc.c (mapc_create): initialize mnt_map->cfm field to NULL.
 
-	* scripts/ctl-amd.in: changed directory name for optional tftpboot
-	map to /tftpboot/.amd.
+	* amd/get_args.c (get_args): call process_all_regular_maps().
 
-Sat Jul  5 17:46:45 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/conf.c: keep head and tail of cfm list.
+	(init_cf_map): reworked reset_cf_map.  This one doesn't reset a
+	globaly reused cfm, but rather just inherits [global] options.
+	(set_conf_kv): just store global/map options without actually
+	creating any mnt_map's.  Essentially, we now parse the whole
+	amd.conf file, and then try to process the maps one at a time.
+	(process_one_regular_map): new function to process one map, just
+	renamed from process_regular_map.
+	(process_all_regular_maps): new exported function to process all
+	maps.  No need for hacky process_last_map().
+	(find_cf_map): new exported function to return a cf_map_t given a
+	map's mount point (e.g., /home or /net).
 
-	*******************************************************************
-	*** Released am-utils-6.0a6					***
-	*******************************************************************
+	* amd/amfs_generic.c (amfs_parse_defaults): find if amd.conf
+	specificed a map_defaults for a given map.  If so, use that
+	instead of the /defaults that came from the map itself.  Also
+	restructure code a bit so it's not one huge long "if" statement.
 
-Sat Jul  5 03:17:09 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	HACK ALERT: there's no easy way to find out what the map mount
+	point is at this point, so I am forced to initialize the
+	mnt_map->cfm field here for the first time, upon the very first
+	search for a /defaults entry in this map.  This initialization is
+	much better done in mapc_create(), but it's impossible to do that
+	there with the current code structure.
 
-	* scripts/ctl-amd.in: include -T tag for tftpboot.
+	* amd/amd.h: struct cf_map becomes linked list.  struct mnt_map
+	includes pointer to cf_map_t, amd.conf defaults and options for a
+	given map. extern cleanups.
 
-	* new port: mips-sgi-irix5.3.  Compiled with gcc, but NFS V3 code
-	is broken and needs work on the specific nfs_args that irix5 uses
-	for V3 mounts.
+2003-07-15  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-Sat Jul  5 01:44:25 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* amd/info_hesiod.c (hesiod_search): It's not possible to have a
+	key such as ".access" in a hesiod map as that would imply a null
+	node in the DNS tree.  So a lookup for such a key must clearly
+	fail.  With the current info_hesiod.c it does (after calling
+	hes{,iod}_resolve) but returns an error that confuses some
+	programs - eg. apache.  This patch shortcuts the process and just
+	returns ENOENT for any key starting with ".".  Patch submitted by
+	by Mark Davies <mark@mcs.vuw.ac.nz>.
 
-	* amd/get_args.c (get_args): new options amd -T tag.  A map with
-	tag=foo matching the -T tag will be processed.  All untagged maps
-	get processed all the time.
+	* include/am_utils.h (CALLOC): redefine macro to use xzalloc, not
+	fsinfo's own xcalloc.
 
-Fri Jul  4 16:19:26 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* fsinfo/fsi_util.c (xcalloc): remove redundant function.
 
-	* aux/configure.in: need to check for strcasecmp in libucb (ncr2)
+2003-07-14  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* aux/macros/check_os_libs.m4: a new macro to set the usage of
-	libnsl and libsocket based on the OS.
+	* include/am_compat.h (MNTTAB_OPT_XLATECOOKIE): The NetBSD
+	xlatecookie NFS option doesn't work as MNTTAB_OPT_XLATECOOKIE is
+	never defined.  Define it as needed.  Patch from Mark Davies
+	<mark@mcs.vuw.ac.nz>.
 
-	* libamu/mount_fs.c (mnt_flags): used MNTTAB_OPT_GRPID if it is
-	defined (problem on osf4).
+2003-07-14  Ion Badulescu  <lionut@gonzales.badula.org>
 
-	* conf/nfs_prot/nfs_prot_irix5.h: new file for irix5 headers.
+	* BUGS (Note): document the Solaris 8 bug (the upgrade to autofs
+	v4 without updating all the header files)
 
-	* include/am_defs.h, aux/macros/try_compile_nfs.m4,
-	aux/macros/mount_headers.m4: do include <sys/proc.h> because it
-	failes on irix5.  Rather, put in the individual
-	conf/nfs_prot/nfs_prot_*.h headers.
+2003-07-13  Ion Badulescu  <lionut@gonzales.badula.org>
 
-	* amd/conf.c: AIX3 doesn't like strdup() being passed a constant
-	char*, so cast all strdup()'s args to a non-const char*.
+	* NEWS, tasks: updated
 
-	* amd/mapc.c (root_newmap): don't try to strdup only a "const
-	char *".
+	* amd/amfs_generic.c (free_continuation): free _all_ mntfs's in
+	the am_mfarray, unconditionally
+	(amfs_bgmount): call free_mntfs when we're done with a mntfs, call
+	dup_mntfs when starting processing of a new one; make sure we
+	always go through 'goto failed' for a failed mntfs; use the error
+	code returned by autofs_get_fh()
 
-Fri Jul  4 15:47:10 1997  Erez Zadok  <ezk@americas.psl.cs.columbia.edu>
+	* conf/autofs/autofs_linux.c (autofs_get_fh): return proper error
+	codes in case of problems
 
-	* conf/nfs_prot/nfs_prot_sunos4.h: added rpc/rpc.h and
-	sys/errno.h.
+2003-07-13  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-Thu Jul  3 17:49:00 1997  Erez Zadok  <ezk@prometheus.soscorp.com>
+	* BUGS: Document buggy behavior of Solaris /usr/ccs/bin/lex.  In
+	short, use flex.
 
-	* made sure am-utils compiles, links, and runs properly on Irix
-	6.2 using "cc -32 -Wl,-woff,"
+2003-07-13  Erez Zadok  <ezk@a-hpux11.fsl.cs.sunysb.edu>
 
-	* aux/macros/check_lib2.m4: a bug fix version to autoconf 2.12
-	AC_CHECK_LIB.  If OTHER-LIBRARIES are defined and used, then add
-	them to $LIBS.
+	* fsinfo/fsi_lex.l, amd/conf_tok.l: allocate more output slots so
+	lex scanners don't run out of mem.
 
-	* aux/configure.in: some cleanup of which libraries are needed.
-	Espectially ensure that libnsl is included only on Solaris, where
-	so far it is the only system on which it is absolutely necessary.
-	Also no longer need to include libc explicitly. 
+2003-07-13  Ion Badulescu  <lionut@gonzales.badula.org>
 
-	* amd/amd.c,wire-test/wire-test.c (main): convert IP address to
-	network-long order before printing it.
+	* amd/amfs_generic.c (amfs_lookup_mntfs): ditto as below for the
+	special provision
 
-	* wire-test/wire-test.c (main): also check and report on the IP
-	address of the local host, since some systems have bad versions of
-	get_myaddress, or ones that conflict with other versions in
-	multiple libraries (SunOS 4 and Irix especially).
+	* amd/mntfs.c (find_mntfs): compare the filesystem type
+	(i.e. mf_ops) in addition to mf_info; the special provision
+	mentioned below is really for any filesystem already mounted on
+	our mount point, not just for inherited filesystems
 
-Wed Jul  2 18:19:02 1997  Erez Zadok  <ezk@starblazers.soscorp.com>
+2003-07-13  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
 
-	* scripts/ctl-amd.in: don't use full pathname so killproc() works
-	better.  Also run bsd44 and irix style ps programs. 
+	* doc/Makefile.am (install-html): build per-chapter HTML manual,
+	as well as manual in one big HTML file.
 
-	* aux/macros/check_lib_funcs.m4: bug fixed: used to define usage
-	of library no matter if it was found or not.
+	* doc/am-utils.texi: Minor corrections.  Ack Ion's autofs work.
+	Ack maintainers.  New section on How to get additionl info,
+	including the Amd book.  Correct stale URLs and Emails.
 
-Wed Jul  2 02:11:48 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amd.8, amq/amq.8, amq/pawd.1, fixmount/fixmount.8,
+	fsinfo/fsinfo.8, hlfsd/hlfsd.8, mk-amd-map/mk-amd-map.8,
+	scripts/amd.conf.5, scripts/automount2amd.8,
+	wire-test/wire-test.8: include references to info pages, proper
+	authors, am-utils Web page, and amd book.
 
-	* aux/macros/check_mnt2_gen_opt.m4: turned back on the checking
-	for M_* macros, but ensure that <sys/stream.h> is not included at
-	all so it won't conflict with other M_* macros.
+2003-07-13  Ion Badulescu  <lionut@gonzales.badula.org>
 
-Tue Jul  1 21:16:51 1997  Erez Zadok  <ezk@mako.cs.columbia.edu>
+	* amd/mntfs.c (find_mntfs): re-add the check for mf_info, but with
+	a special provision for inherited filesystems. This unbreaks the
+	handling of parallel mounts
 
-	* conf/mount/mount_irix.c (mount_irix): first arg to mount(2) on
-	irix should be "spec" (host:/path), not the dir of the mnt point.
+	* amd/amfs_generic.c (amfs_lookup_mntfs): for restarted
+	filesystems, there can be no alternative mntfs to try to mount
 
-	* amd/ops_afs.c (afs_lookuppn): bug in enable_default_selectors
-	fixed.  If on, it essentially ignored the setting in a
-	selector-controlled /defaults if there were 2 or more entries in it.
+2003-07-13  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Tue Jul  1 12:23:38 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amd.8: reference am-utils info page in amd man page, as per
+	Thomas Klausner <wiz@danbala.ifoer.tuwien.ac.at>.
 
-	* scripts/ctl-{amd,hlfsd}.in (killproc): if failed to find process
-	using BSD style ps, then try SVR4 style ps.
+	* fsinfo/fsinfo.h, fsinfo/fsinfo.c (fsi_get_args): don't use
+	yywrap() if it doesn't exist.
 
-	* include/am_utils.h (amuDebug): renamed Debug macro to amuDebug
-	etc., to avoid conflicts with similar named macros in <ldap.h>.
+	* amd/conf_parse.y, amd/conf_tok.l, fsinfo/fsi_gram.y,
+	fsinfo/fsi_lex.l: fixes to support old flex 2.5.4, as well as the
+	newer flex 2.5.31 (beta development).  These include resolving
+	conflicts with yylineno, unput() vs. nounput(), etc.
 
-	* aux/configure.in, amd/info_ldap.c, etc.: put in all the autoconf
-	support needed for LDAP.  Now the code has to be written mostly in
-	amd/info_ldap.c.
+2003-07-13  Ion Badulescu  <lionut@gonzales.badula.org>
 
-	* Included additional patches from Andreas Stolcke
-	<stolcke@speech.sri.com> to support using the best possible
-	combination of NFS version (2,3) and protocol (udp,tcp) for any
-	given host, since it appears that some Irix versions have NFS V3,
-	but do not support TCP.
+	* amd/amfs_generic.c (amfs_cont): check for (am_error > 0) before
+	calling assign_error_mntfs()
+	(amfs_generic_mount_child): ditto
 
-	* scripts/ctl-amd.in: updated amd control script to look for and
-	use amd.conf file.
+	* amd/autil.c (assign_error_mntfs): move the check for
+	(am_error > 0) up into the caller, it's less confusing that way
 
-Tue Jul  1 00:28:23 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* tasks: some updates
 
-	* amd/mapc.c (mapc_create): now, each map in the amd.conf can be
-	initialized off of a different type, or default to cycling through
-	all maps until one of them matches.
+	* conf/transp/transp_tli.c (check_pmap_up): new function which
+	detects if the remote portmapper is functional
+	(amu_clnt_create_best_version): removed
+	(get_nfs_version): use a much simplified version of the old
+	amu_clnt_create_best_version(), based on clnt_create_vers() and
+	its _timed() counterpart
 
-Mon Jun 30 20:49:13 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* conf/transp/transp_sockets.c (check_pmap_up): new function which
+	detects if the remote portmapper is functional
+	(pmap_ping): deleted
+	(get_nfs_version): removed calls to pmap_ping, already done by
+	caller
 
-	* amd/ops_afs.c (afs_readdir): per-map browsing (readdir) done.
-	if browsable_dirs=yes is set in the map section in amd.conf, that
-	map will return all entries back to a readdir(2).
+	* amd/srvr_nfs.c: call check_pmap_up() before continuing with
+	get_nfs_version()
 
-Sun Jun 29 16:22:11 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* amd/amfs_generic.c: updated a couple of log messages
 
-	* rudimentary amd.conf file support included.  You may even
-	override things like os=sos5, to get "backwards" compatibility with
-	upl102.
+	* configure.in: detect clnt_create_vers and clnt_create_vers_timed;
+	changed LIBTOOL versioning to 3:0:0
 
-Sat Jun 28 13:35:02 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+2003-07-12  Ion Badulescu  <lionut@gonzales.badula.org>
 
-	* amd/conf.c: new file to process amd.conf file.
+	* conf/autofs/autofs_linux.h (AUTOFS_HOST_FS_FLAGS): removed
+	FS_AUTOFS because the host mount cannot be a top level mount
+	(AUTOFS_DIRECT_FS_FLAGS): removed FS_AUTOFS because Linux autofs
+	doesn't support direct mounts
 
-	* amd/get_args.c (get_args): new options -H to print help.
+2003-07-12  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
 
-	* moved enable_default_selectors to be amd.conf controlled, and
-	not compiler controlled.
+	* amd/conf_parse.y, amd/conf_tok.l: pretty comments on # cpp
+	macros.
 
-	* amd/get_args.c (get_args): new options -F <conf-file> to parse an
-	amd configuration file.
+2003-07-10  Ion Badulescu  <ionut@buggy.badula.org>
 
-Wed Jun 25 23:15:42 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* include/am_utils.h (dlog): improved version for gcc, using
+	vararg macros
 
-	* converted all files that used strcmp() == 0 or != 0  to using
-	the STREQ() macro.
+	* amd/rpc_fwd.c (fwd_packet): unused variable when compiling
+	without debugging
 
-Mon Jun 23 22:31:14 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+2003-07-10  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-	* aux/macros/check_lib_funcs.m4: new M4 macro that can be used to
-	search for any number of functions in any given library.
+	* include/am_utils.h (dlog): change the #define of non-debugging
+	dlog to "nothing" so that all that'll be left behind is a list of
+	args in parenthesis (arg,arg,...).  GCC and other native C
+	compilers seem OK with it, even if it doesn't optimize away the
+	whole debugging line.
 
-Mon Jun 23 01:04:23 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* ltmain.sh: was from libtool 1.4.2.  updated to libtool 1.4.3,
+	the latest on RH9 systems (but is not the latest libtool
+	available).  Stay with stable version in preparation for 6.1
+	release.
 
-	* amd/mapc.c: Included patch from Leif Johansson
-	<leifj@matematik.su.se> to ensure that systems without an RE
-	library can compile.
+	* config.{guess,sub}, doc/texinfo.tex: update to latest off of
+	ftp.gnu.org.
 
-	* libamu/mount_fs.c (mount_fs): Included patch from Andreas
-	Stolcke <stolcke@speech.sri.com>, to ensure that mount options on
-	table are properly delimited by a comma.
+2003-07-09  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-	* amd/ops_nfs.c (mount_nfs_fh): Included patch from Andreas
-	Stolcke <stolcke@speech.sri.com>, to allow users to override the
-	proto= and vers= mount options.
+	* amd/amfs_inherit.c (amfs_inherit_inherit): don't use // C++
+	style comments: breaks non-C++ compilers (like AIX xlC 6)
 
-Sun Jun 22 01:00:11 1997  Eric Dana  (edana@ncr2.bgs.com)
+2003-07-02  Ion Badulescu  <ionut@buggy.badula.org>
 
-	* conf/nfs_prot/nfs_prot_svr4.h: port completed to
-	i486-ncr-sysv4.3.03.  Assorted source cleanups done.
+	* doc/am-utils.texi (opts Option): document ignore_portmapper option
 
-	* include/am_defs.h, aux/macros/mount_headers.m4: don't include
-	mnttab.h if sys/mnttab.h was already included, because on ncr2,
-	they contain conflicting entries for struct mnttab.
+	* conf/transp/transp_sockets.c (get_nfs_version): better
+	protocol/version cycling while probing remote server; better log
+	messages
 
-Sat Jun 21 23:52:15 1997  Eric Dana  (edana@ncr2.bgs.com)
+	* amd/srvr_nfs.c (start_ping): improved log message
+	(find_nfs_srvr): always use requested nfs_version/nfs_proto; make
+	sure we have a valid NFS port; start the server as "valid, down" if
+	the remote portmapper tells us the NFS service is not running;
+	implement the "ignore_portmapper" pseudo-mount option
 
-	* aux/macros/check_nfs_prot_headers.m4: added support for ncr2.
+	* amd/rpc_fwd.c (fwd_packet): better debug messages
 
-Fri Jun 20 06:14:17 1997  Erez Zadok  <ezk>
+	* amd/ops_nfs.c (got_nfs_fh): log a messages if a root fh is
+	denied; call wakeup even if mountd call fails
 
-	* amd/*.c: lots of 64-bit "ugly" ports like casts to long ints.
+	* amd/amq_subr.c (xdr_amq_mount_info_qelem): use FSRV_ISUP/ISDOWN
+	instead of checking the flags directly
+	* amd/srvr_amfs_auto.c (free_srvr): ditto
 
-	* aux/macros/struct_nfs_fh.m4: check for "struct nfssvcfh" because
-	on DU-4.0 it is better than the next one to be picked (nfsv2fh_t).
+	* amd/amfs_generic.c (amfs_bgmount): refined some error/debug
+	messages
 
-Wed Jun 18 18:59:49 1997  Erez Zadok  <ezk@defiant.soscorp.com>
+	* amd/amd.h (FSRV_ERROR): new macro
+	(FSRV_ISDOWN, FSRV_ISUP): a server that doesn't exist (i.e. it's a
+	local filesystem) is always up
 
-	* aux/macros/struct_nfs_fh.m4 (AC_TRY_COMPILE_NFS): check for
-	nfsv2fh_t before fhandle_t becasue on bsdi2.1 the former is
-	better.
+2003-06-30  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Tue Jun 10 17:06:58 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* amd/autil.c (am_mounted): set AMF_NOTIMEOUT if either unmount or
+	umount options are present.
 
-	* amd/rpc_fwd.c (fwd_packet): TLI bug fix. if fwdto socket is
-	NULL, set the maxlen and len fields in netbuf to zero.
+	* doc/am-utils.texi (Program Filesystem): document alias options
+	to unmount:=, umount:=.
 
-Wed May 28 22:52:28 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/opts.c (expansions): initialize opt_umount.
+	(to_free): initialize opt_umount.
 
-	* scripts/fix-amd-map.in (name): replace all matching patterns on
-	line.
+	* amd/amfs_program.c (amfs_program_match): ensure that only one of
+	umount:= or unmount:= options are specified, but that at least one
+	of them is listed.
 
-Sun May 25 19:33:41 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/amd.h: support unmount:=XXX as well as umount:=XXX (too
+	annoying in type:program, when one forgets the 'n' in "unmount").
+	They are two separate fields, so we can catch mistakes when
+	someone tries to define both options.
 
-	*******************************************************************
-	*** Released am-utils-6.0a5					***
-	*******************************************************************
+	* doc/am-utils.texi (Program Filesystem): explain that both mount
+	and unmount options must be specified.  Correct example to show
+	both.
 
-Sun May 25 13:37:24 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+2003-06-25  Erez Zadok  <ezk@cs.sunysb.edu>
 
-	* amd/amq_subr.c (amqproc_getvers_1_svc): amq's RPC service
-	procedure now returns the full string that amd -v returns.
+	* XXX: beginning of new amd.conf option map_defaults: will parse
+	the option and set remember it in the right places.  Need to
+	document this and actually hook it up with the rest of the code.
+	Any volunteers? :-)
 
-	* amd/get_args.c (get_version_string): new function to return
-	complete version/info string so it could be used more flexibly.
+	* scripts/amd.conf-sample (map_defaults): example of map_defaults
+	amd.conf option.
 
-	* amd/am_ops.c (ops_showamfstypes, ops_showfstypes): put the list
-	of Fs types into a string buffer, rather than a FILE*.
+	* amd/conf.c (reset_cf_map): initialize global and per-mount
+	map_defaults.
+	(gopt_map_defaults): parse global map_defaults.
+	(process_regular_option,ropt_map_defaults): parse per-map
+	map_defaults amd.conf option.
 
-	* amd/mapc.c (mapc_showtypes): put the list of map types into a
-	string buffer, rather than a FILE*.
+	* amd/amd.h: a place to store global and per-mount map_defaults.
 
-Sun May 25 01:25:36 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* BUGS: more notes about AIX 5.2 problems and how to overcome
+	them.
 
-	* amd/get_args.c (get_args): amd -v also prints user who built
-	amd, hostname built on, and date of configuration.
+2003-06-10  Erez Zadok  <ezk@cs.sunysb.edu>
 
-Sat May 24 13:40:50 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* doc/Makefile.am: force version.texi to be rebuilt regardless of
+	maintainer mode.  Silly Automake will not build version.texi if
+	maintainer mode is off (this is hardcoded into the automake perl
+	script!).  According to the Automake maintainers, users should
+	always build in CVS trees with maintainer-mode on; but what if I
+	don't want to?!  I don't want to distribute Makefiles with
+	maintained rules in them to users.  The Automake maintainers also
+	say that "make dist" will rebuild version.texi no matter what.  I
+	find that not to be the case.  It failed to run a "make" before
+	"make dist" because version.texi doesn't exist!  Chicken and Egg
+	situation.  So, until Automake deals with version.texi in a more
+	flexible and friendly manner, I adapted a rule to build
+	version.texi and inserted it in this Makefile.am.
 
-	* scripts/lostaltmail.conf-sample: sample lostaltmail
-	configuration file.
+2003-06-09  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
 
-	* scripts/lostaltmail.in: new script lostaltmail used to redeliver
-	"lost" mail that hlfsd redirected to a temp location because the
-	primary home file system of the user was full.
+	* mk-amd-map/mk-amd-map.c (main): open temp db file using O_EXCL,
+	next best thing to using mkstemp().  Patch from Hendrik Scholz
+	<hscholz@raisdorf.net>.
 
-	* scripts/amd2sun.in: new script amd2sun. Used to convert Sub
-	automount maps to amd maps.
+2003-05-08  Ion Badulescu  <ion@guppy.limebrokerage.com>
 
-	* scripts/ctl-hlfsd.in: new script ctl-hlfsd.  Used to start,
-	stop, or restart hlfsd.
-	
-	* scripts/expn.1: man page for expn command.
+	* libamu/mount_fs.c (compute_automounter_mount_flags): use
+	MNT2_GEN_OPT_AUTOMNTFS if available; minor cleanup
 
-	* scripts/ctl-amd.in: new script ctl-amd.  Used to start, stop, or
-	restart amd.
+	* m4/macros/header_templates.m4: added template for
+	MNT2_GEN_OPT_AUTOMOUNTED
 
-	* scripts/expn.in: new script expn.  Actually taken from David
-	Muir Sharnoff <muir@idiom.com>.  Used by hlfsd's mail re-delivery
-	script.
+2003-05-01  Ion Badulescu  <ionut@nicu.badula.org>
 
-	* scripts/wait4amd.in: new script wait4amd added.  Waits for amd
-	to come up on a host, and then runs a command (rsh $hostname by
-	default).
+	* amd/ops_xfs.c (mount_xfs): compile fix (s/genflags/flags/)
 
-	* scripts/Makefile.am: new directory now holds all shell/perl
-	scripts that belong to am-utils.
+2003-04-23  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
 
-	* conf/mount/mount_linux.c (parse_opts): new parser for
-	linux-specific mounts.  Handles fs-type specific mount-options
-	correctly.  Currently implemented: msdos, iso9660.
+	* conf/transp/transp_sockets.c (create_amq_service): minor cpp
+	directive indentation and commenting.
 
-	* amd/ops_pcfs.c (pcfs_ops): don't timeout cdfs mounts by default
-	(fix for linux).
+2003-04-22  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* amd/ops_cdfs.c (cdfs_ops): don't timeout cdfs mounts by default
-	(fix for linux).
+	* conf/transp/transp_sockets.c (create_amq_service): Ugly *BSD fix
+	for an RPC library DoS issue (original patch from Martin Blapp,
+	massaged into something more digestable by me)
 
-	* amd/mapc.c (make_entry_chain): fixed bug that resulted in amd
-	core dumps upon "ls" of a mount point; an invalid pointer was
-	being returned and dereferenced.
+2003-04-14  Ion Badulescu  <ionut@moisil.badula.org>
 
-	* port to Linux sparc working!
+	* conf/autofs/autofs_solaris_v2_v3.c: removed autofs_free_data(),
+	left over from the recent cleanup
 
-	* hlfsd/homedir.c (hlfsd_diskspace): close file descriptor if
-	failed to write test file, or else the fd will leak.
+2003-04-13  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
 
-Sun May 18 00:42:41 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* doc/Makefile.am (DVIPS): use proper options for dvips.
 
-	* amd/info_hesiod.c (hs_strip_our_domain): use strcasecmp()
-	instead of strcmp().
+	* doc/am-utils.texi (opts Option): document new 'unmount' option,
+	and better explain the 'nounmount' option.  Also some misc options
+	for better generation of html manual.
 
-	* Port to Digital Unix 4.0 (OSF) done.
+	* doc/Makefile.am (install-html): support newer texi2html 4.0
+	options, as older options were renamed or changed behavior.
 
-	* hlfsd/hlfsd.c: renamed dirname to dir_name to avoid conflicts
-	with dirname() function in <string.h> on OSF systems.
+	* amd/autil.c (am_mounted): support new 'unmount' option, to allow
+	all file system mounts to timeout and thus expire.  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).  Patch from
+	Christos Zoulas <christos@zoulas.com> (originally from Koji
+	Imada).
 
-	* fsinfo/fsi_util.c (set_ether_if): take out extern definition of
-	inet_addr().  It should come from <arpa/inet.h> instead.
+2003-04-10  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
 
-	* conf/mtab/mtab_osf.c: fixed macros and added NFS V3 specs.
+	* configure.in: use AM_MAINTAINER_MODE, so maintainer-only rules
+	do not get added to Makefiles by default (they are confusing to
+	users who don't have autotools installed).
 
-	* include/am_utils.h: renamed FIRST/LAST to AM_FIRST/AM_LAST to
-	avoid conflicts with DU 4.0 system header.
+2003-04-09  Ion Badulescu  <ion@guppy.limebrokerage.com>
 
-Thu May 15 22:49:12 1997  Erez Zadok  <ezk@subzero.cs.columbia.edu>
+	* amd/mntfs.c (find_mntfs): revert the "change of philosophy" (see
+	the 2001-05-23 entry) back to the 6.0 code
 
-	* libamu/mount_fs.c (mount_fs): pass along NFS version so I can
-	determine if to include additional options in the mount table file
-	entry (such as proto=tcp, and vers=3).
+2003-04-04  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
 
-Thu May 15 00:42:12 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* libamu/xutil.c (switch_to_logfile): don't try to print logfile
+	if it is null (strlen core dump on solaris).  Bug report from John
+	P. Rouillard <rouilj@ieee.org>.
 
-	* libamu/mount_fs.c (mount_fs): include NFS version number in the
-	mount table options, as well as proto={tcp,udp}.
+2003-03-31  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
 
-Wed May 14 14:30:19 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+	* fsinfo/fsinfo.8: typo co-ordinate -> coordinate.  Typo report
+	from Perry E. Metzger" <perry@piermont.com>.
 
-	* NFS V3 code ported to most other systems, so it compiles for V2
-	and V3 NFS systems.
+2003-03-25  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
 
-	* NFS VERSION 3 support, first pass.  Working for Solaris and
-	using TCP.
+	* include/am_defs.h: Don't include malloc.h if stdlib.h exists,
+	because modern systems (e.g., BSD) complain if you use malloc.h
+	instead of stdlib.h.  Let's hope there are no systems out
+	there that need both.
 
-Sun May 11 01:14:29 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+2003-03-20  Erez Zadok  <ezk@suse73.fsl.cs.sunysb.edu>
 
-	* amq/amq.c: many newline characters were missing from various
-	stderr printfs.
+	* minor new port: sparc64-unknown-linux-suse7.3.
 
-Sat May 10 13:09:06 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+2003-03-20  Erez Zadok  <ezk@a-freebsd5.fsl.cs.sunysb.edu>
 
-	* conf/nfs_prot/nfs_prot_sunos5.h: protocol defintions for
-	Solaris, which include NFS V3 support.
+	* minor new port: i386-unknown-freebsd5.0.
 
-	* conf/nfs_prot/nfs_prot_default.h: default NFS protocol headers.
-	*** Released am-utils-6.0a15					***
-	* conf/transp/transp_{tli,sockets}.c (get_mount_client): use NFS
-	protocol version while getting a mount client.
+	* configure.in: detect nfsclient/nfsargs.h.
 
-	* amd/ops_nfs.c (mount_nfs_fh): set the mount types, mnttab types,
-	file handle size, and proper file handle based on the correct NFS
-	version number.
-	browsable_dirs=full, which will print *all* entries (other than
-	* conf/mount/mount_svr4.c (mount_svr4): support NFS3 mounts under
-	Solaris and other SVR4 systems.
+	* conf/nfs_prot/nfs_prot_freebsd3.h: include
+	<nfsclient/nfsargs.h>, needed in FreeBSD 5.0.
 
-	* amd/ops_nfs.c: store NFS file handle version and version
-	specific handle in struct fh_cache.
-	(got_nfs_fh): pick the correct RPC reply based on the NFS version
-	of the server.
-	(prime_nfs_fhandle_cache): figure out the right NFS file handle
-	for a node, but now include NFS protocol version information.
-	(call_mountd): set the correct version for the mount protocol,
-	based on the NFS protocol version.
-	(nfs_init): use the NFS protocol generic structure
-	am_nfs_handle_t.
-	to 1500.
-	* include/am_utils.h: new structure am_nfs_handle_t to contain all
-	possible versions of NFS file handles.
-	* doc/am-utils.texi: fixed reversed documentation for NFS mount
-	* amd/srvr_nfs.c (start_ping): ping program performs NFS version
-	specific pings.
-	(recompute_portmap): figure out the correct portmap version mount.
-	(nfs_keepalive): call start_ping() with the correct NFS version.
-	(find_nfs_srvr): if mount option "vers=" is given, use it.  Get
-	the NFS server version and verify that it is up.
+2003-03-15  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
 
-	* conf/transp/transp_{tli,sockets}.c (get_nfs_version): a new
-	function to find the best NFS version for a particular host.
-	installing html files.  Another new target "alldocs" is just for
-	* libamu/amu.h: determine what is the highest version of NFS we
-	should try.
+	* amd/amd.8, amd/amd.8, fixmount/fixmount.8, hlfsd/hlfsd.8,
+	scripts/amd.conf.5, scripts/expn.1: minor spell checking and
+	extraneous space elimination.
 
-	* include/am_utils.h (NFS_VERSION3): added definition for NFS V3
-	protocol number.
-	Added field fs_version to struct fserver, so we can now store the
-	server protocol version.
-	facility in the log_file option.
-Fri May  9 01:09:45 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
-	* libamu/xutil.c (get_syslog_facility): allow users to specify the
-	* aux/macros/check_field.m4 (AC_MOUNT_HEADERS): map '.' (dot) into
-	underscores too, so I can test for sub-fields.
-	will use the default LOG_DAEMON facility.
-	* libamu/wire.c: use test that checks for sub-fields of struct
-	ifreq.
-Thu Jan  8 04:05:10 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-Sat May  6 10:20:17 2000  Erez Zadok  <ezk@glory.soscorp.com>
-	(intel).
-	* port to BSD/OS 3.0 completed!  Many xdr_ functions were broken
-	into smaller files.  M4 macros fixed to test for existence of
-	file systems using getvfsbyname().
-	before appending to it, on systems with two or more network
-	* amd/sched.c (sigchld): signal handler must waitpid() for all
-	possible children.
-	the mntent for cachefs.
-	* hlfsd/homedir.c: signal handler must waitpid() for all possible
-	children. 
-	const for both arguments.
-	* aux/macros/check_restartable_signals.m4: new macro to determine
-	if need to reinstall signal handlers per OS is better than trying
-	to figure these out based on system macros.
+2003-03-07  Ion Badulescu  <ionut@buggy.badula.org>
 
-Fri May  5 19:23:28 2000  Erez Zadok  <ezk@glory.soscorp.com>
-	* amq/pawd.c (cluster_server): don't use getccent() if the extern
-	* amd/ops_nfs.c (mount_nfs_fh): set nfs_args_t version number.
-	<cluster.h> and struct cct_entry do not exist.
-	* amd/ops_afs.c (mount_toplvl): set nfs_args_t version number.
+	* conf/autofs/autofs_linux.c (autofs_get_fh): don't leak file
+	descriptors if limit exceeded
+	(autofs_mounted): call autofs_get_mp(); init am_autofs_ttl
+	(autofs_release_fh): release pending_mounts and pending_umounts
+	queues
+	(autofs_timeout_mp): update am_autofs_ttl instead of am_ttl
+
+	* amd/mntfs.c (init_mntfs): delete initialization of removed
+	mf_autofs_fh
+	(uninit_mntfs): delete call to autofs_release_fh()
+
+	* amd/map.c (init_map): init autofs_fh to 0, delete initialization
+	of removed autofs_data
+	(free_map): release autofs_fh after unmounting map; delete call to
+	autofs_free_data()
+	(umount_exported): call autofs_release_mp() prior to unmounting
+	autofs f/s
+	(unmount_mp): ditto
+	(free_map_if_success): call autofs_get_mp() if unmounting fails
+	(timeout_mp): use the dedicated am_autofs_ttl timeout for f/s-wide
+	timeouts instead of the per-mountpoint am_ttl
+
+	* amd/autil.c (am_unmounted): release autofs_fh after unmounting
+	autofs f/s
+
+	* amd/amfs_generic.c (amfs_cont): release autofs_fh if mounting
+	autofs f/s fails;
+	(amfs_bgmount): ditto
+
+	* amd/amd.h: moved autofs_fh from mntfs to am_node, since it's
+	more related to the mount point than to the f/s mounted;
+	added am_autofs_ttl to am_node, for running expirations on entire
+	filesystems
+
+	* conf/autofs/autofs_*: autofs_get_fh() returns int instead of
+	autofs_fh_t *; autofs_release_fh() now takes an am_node * parameter
+	instead of autofs_fh_t *, in an effort to not deal with
+	autofs-specific data structures outside autofs code;
+	new methods autofs_get_mp() and autofs_release_mp(), which
+	acquire/release autofs resources to allow clean unmount attempts;
+	nuke autofs_data_t, never used
+
+	* amd/amd.h: prototypes for new and changed autofs functions
+
+2003-03-07  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* amd/nfs_subr.c (do_readlink): eliminate third argument, never used
+	(nfsproc_getattr_2_svc): reorganize the code a bit
+
+	* amd/map.c (mk_fattr): take a nfsfattr * argument instead of an
+	am_node * argument
+
+	* amd/amd.h: changed prototype for mk_fattr()
+
+	* amd/autil.c (am_unmounted): when remounting, use the parent
+	node's lookup_child() and mount_child() operations, not the
+	generic ones
+
+	* amd/amfs_generic.c (amfs_cont): minor code optimization
+
+2003-03-06  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* amd/amfs_auto.c: lots of renames and code moving:
+	amfs_auto_match() -> amfs_generic_match(), moved to generic;
+	amfs_auto_mkcacheref() -> amfs_mkcacheref(), moved to autil.c;
+	amfs_auto_mounted() -> amfs_generic_mounted(), moved to generic;
+	amfs_auto_umount() -> amfs_generic_umount(), moved to generic;
+	free_continuation(): moved to generic, made static;
+	assign_error_mntfs(): moved to autil.c;
+	amfs_auto_cont() -> amfs_cont(), moved to generic, made static;
+	amfs_auto_retry() -> amfs_retry(), moved to generic, made static;
+	try_mount() + mount_node() -> mount_node(), moved to map.c
+	amfs_auto_bgmount() -> amfs_bgmount(), moved to generic;
+	amfs_parse_defaults(): moved to generic;
+	amfs_auto_lookup_node() -> amfs_lookup_node(), moved to generic;
+	amfs_auto_lookup_one_mntfs() -> amfs_lookup_one_mntfs(), in generic;
+	amfs_auto_lookup_mntfs() -> amfs_lookup_mntfs(), moved to generic;
+	amfs_auto_mount_child() -> amfs_generic_mount_child(), in generic;
+	amfs_auto_lookup_child() -> amfs_generic_lookup_child(), in generic;
+	next_nonerror_node(): moved to autil.c;
+	amfs_auto_readdir() -> amfs_generic_readdir(), moved to readdir;
+	amfs_auto_readdir_browsable() -> amfs_readdir_browsable(), in readdir;
+
+	* amd/amfs_toplvl.c: mount_amfs_toplvl() renamed to amfs_mount()
+	and moved to autil.c
+
+	* amd/readdir.c, amd/amfs_generic.c: new files with stuff ripped
+	out of amd/amfs_auto.c
+
+	* amd/amd.h: struct continuation moved to generic.c; prototypes
+	for the renamed functions; NumChild renamed to NumChildren
+
+	* amd/map.c: collaped unmount_node_wrap() and unmount_node() into
+	the latter
+
+	* amd/mapc.c: key_already_in_chain(): moved to readdir.c;
+	make_entry_chain(): moved to readdir.c;
+
+	* amd/srvr_amfs_auto.c: find_amfs_auto_srvr() renamed to
+	amfs_generic_find_srvr()
+
+	* amd/amfs_*.c: adjustments for the renames above
+
+	* amd/ops_*.c: low-level filesystems don't need a find_server()
+	method
+
+	* amd/Makefile.am: added amfs_generic.c and readdir.c
+
+	* doc/am-utils.texi: minor clarification for auto maps
+
+2003-03-06  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* amd/amd.h: moved lots and lots of amd-only stuff here, from
+	include/am_utils.h; changed task_fun, cb_fun and fwd_fun typedefs
+	to be function typedefs, not pointer to function typedefs
+
+	* include/am_utils.h: see above
+
+	* amd/ops_nfs.c, amd/rpc_fwd.c, amd/sched.c: adjustments for
+	function typedef changes
+
+2003-03-05  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* BUGS: record IBM's patch number for the AIX 5.2 NFS over IPv6
+	bug.
+
+2003-02-02  Erez Zadok  <ezk@siamese.fsl.cs.sunysb.edu>
+
+	* NEWS: minor new port: ia64-unknown-linux-rh2.1AS
+
+2003-01-31  Ion Badulescu  <ion@console.limebrokerage.com>
+
+	* m4/macros/os_cflags.m4: rhapsody and darwin are the same
+
+	* amd/autil.c (mount_node): vastly simplified, just a wrapper now
+
+	* amd/amfs_inherit.c (amfs_inherit_mount): remove the am_mounted()
+	hack, we now do it properly in the generic code
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): get the autofs_fh _before_
+	forking the child; set and reset MFF_MOUNTING here, not in
+	mount_node(), because the latter might be running in child
+	context; call am_mounted() after a successful foreground mount
+
+2003-01-29  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* configure.in: new flag --with[out]-ndbm; don't pull in libldap
+	if building --without-ldap; look for the gdbm/ndbm.h header; make
+	explicit the dependency between the ndbm headers and libraries;
+	define NEW_DBM_H as the ndbm header that should be used
+
+	* include/am_defs.h: simply include NEW_DBM_H for ndbm stuff,
+	instead of trying to second-guess configure
+
+	* m4/macros/header_templates.m4: new template for NEW_DBM_H
+
+	* m4/macros/check_map_funcs.m4:
+	(ac_upcase_map_name): use the third argument correctly
+
+	* ltmain.sh: working version from libtool-1.4.2-7
+
+	* buildall: print the entire configure command, including extra
+	arguments; pass each of the extra arguments separately, not
+	commingled into one
+
+2003-01-28  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* include/am_utils.h (DEBUG_MNTTAB): define outside of #ifdef
+	DEBUG; it is not used without DEBUG, but it is referenced at
+	compile time. Bug report from John Kilburg <john@physics.unlv.edu>.
+	(D_ALL): don't include D_XDRTRACE, too verbose and normally
+	unnecessary
+
+2003-01-28  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* ltmain.sh, config.guess, config.sub, doc/texinfo.tex: updates
+	from latest official GNU versions.
+
+2003-01-25  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* BUGS (Note): document AIX-5.1 NFS-client side bug (hangs in
+	vmount).
+
+2003-01-25  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* Released beta version 6.1b2
+
+2003-01-24  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* amd/autil.c (am_unmounted): reset MFF_MKMNT from mf_flags when
+	calling rmdirs() on mountpoint
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): ditto
+
+	* amd/amfs_nfsl.c (amfs_nfsl_umounted): ditto
+
+	* doc/am-utils.texi (opts Option): "sftlookup" -> "softlookup"
+
+	* NEWS: "sftlookup" -> "softlookup"
+
+	* amd/ops_nfs.c (nfs_mount): "sftlookup" -> "softlookup", also
+	check for "nosoftlookup" in combination with "soft"
+
+2003-01-23  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* m4/macros/check_nfs_fh_dref.m4: darwin/rhapsody is another
+	freebsd22 derivative
+
+	* NEWS: updated for Darwin changes
+
+	* .cvsignore: added A.i386-apple-darwin6.0
+
+	* m4/macros/os_cflags.m4: add -D_P1003_1B_VISIBLE to cflags for
+	Darwin
+
+2003-01-23  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* conf/mount/mount_aix.c (mount_aix3): clean back this file from
+	all the debugging cruft that is no longer needed (and really was
+	never needed in the first place).
+
+2003-01-10  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* scripts/test-amd.{misc,conf}: simple amd.conf and amd.misc
+	(map) files for testing basic amd functionality such as whether it
+	can mount its own mount NFS points.
+
+2002-12-28  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* amd/srvr_nfs.c (start_nfs_pings): don't set FSF_PINGING if
+	pings are disabled
+
+	* libamu/xdr_func.c (xdr_ftype): use a local enum_t variable
+	instead of casting the pointer to (enum_t *)
+	(xdr_mountstat3): ditto
+	(xdr_nfsstat): ditto
+
+	* libamu/misc_rpc.c (make_rpc_packet): fix make_rpc_packet() on
+	64-bit big-endian platforms, bug report from Bill Fenner
+	<fenner@research.att.com>
+
+	* configure.in: increase library patchlevel
+
+	* libamu/xutil.c (amu_release_controlling_tty): close and reopen
+	file descriptors 0,1,2 before calling setsid()
+
+2002-12-27  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* updated copyright year to 2003 on all files
+
+2002-12-10  Erez Zadok  <ezk@localhost.localdomain>
+
+	* rename "aux/" subdir into "m4/" so as to avoid problems with
+	MS-DOS systems (where "AUX" is a reserved name).  This required
+	fixing numerous files.
+
+2002-12-10  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
+
+	* configure.in: don't check for bad hasmntopt() function if
+	hasmntopt() doesn't exist on the system, because we will replace
+	it with our own version anyway.
+
+	* conf/transp/transp_sockets.c (amu_get_myaddress): use "%lx" in
+	dlog because htonl() returns a u_long.
+
+2002-12-10  Erez Zadok  <ezk@localhost.localdomain>
+
+	* include/am_defs.h: use system's hasmntopt() only if it is found
+	and it is not buggy.
+
+	* libamu/hasmntopt.c (nextmntopt): isspace() takes an int, not a
+	char.
+
+	* amd/am_ops.c, amd/amfs_auto.c, amd/autil.c, amd/nfs_subr.c,
+	amd/ops_cdfs.c, amd/ops_nfs.c, amd/srvr_nfs.c, libamu/hasmntopt.c,
+	libamu/mount_fs.c, libamu/mtab.c: rename all uses of hasmntopt()
+	to amu_hasmntopt().  Don't use hasmntopt() directly any more!
+
+	* aux/macros/func_bad_hasmntopt.m4: new M4 macro to test for a bad
+	hasmntopt() function, which incorrectly finds the option "soft" in
+	a string "hard,softlookup,ro".
+
+	* libamu/hasmntopt.c (hasmntopt): use 'const' on two args to
+	hasmntopt(), to match what most systems use.
+
+	* aux/macros/header_templates.m4: template for HAVE_BAD_HASMNTOPT.
+
+	* configure.in: invoke test for bad hasmntopt()
+
+	* NEWS: minor new port, i386-pc-linux-rh8.0.
+	Mention autofs-v4 on solaris9 works.
+
+	* bootstrap: remove any autom4te-*.cache directories, now that
+	autoconf uses a version number for them.
+
+2002-12-09  Ion Badulescu  <ionut@moisil.badula.org>
+
+	Patches from Christos Zoulas:
+
+	-1- am_utils.h: add full prototypes
+	-2- amfs_auto.c make functions static and add prototypes
+	-3- map.c: kill double free
+	-5- transp_sockets.c: add full prototypes
+
+2002-12-09  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* NEWS: updated
+
+	* doc/am-utils.texi (opts Option): document sftlookup
+
+	* conf/autofs/autofs_solaris_v2_v3.c: compile fixes
+
+2002-11-22  Erez Zadok  <ezk@filer.fsl.cs.sunysb.edu>
+
+	* amd/info_ldap.c (amu_ldap_rebind): gopt.ldap_cache_seconds is
+	%ld not %d.
+
+2002-11-21  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* {amd,fsinfo}/Makefile.am: remove special rules for processing
+	yacc/lex files, now that autoconf/automake properly handle them
+	better (esp. now that bison 1.75 behaves differently than older
+	bison versions).
+
+2002-11-21  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* config.guess.long: updated script so it will properly find the
+	version number of the new Itanium 2 machines running "Red Hat
+	Linux Advanced Workstation release 2.1AW (Derry)".  The script now
+	will report ia64-unknown-linux-rh2.1AW.
+
+2002-11-20  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* amfs_auto_bgmount(): almost complete rewrite
+
+	* fixed amfs_inherit to do the right thing and not dereference
+	freed mntfs'es
+
+	* #if 0'ed bogus code in fh_to_mp3() -- it is now done properly in
+	amfs_autofs_lookup_child()
+
+	* release the autofs_fh only in one place
+
+	* remove the mountpoint only if mf_refc == 1
+
+	* print the mntfs type in free_mntfs()
+
+	* new pseudo-mount option 'sftlookup' which causes lookups to
+	mounted shares from downed servers to return EIO; the default
+	depends on whether the mount is 'hard' or 'soft'
+
+	* improved querying of supported NFS versions on the server --
+	don't even try if it's known to be down
+
+	* solaris autofs mount code moved to transp_{sockets,tli}.c
+
+	* incipient (non-functional) AIX autofs support
+
+2002-11-11  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* doc/am-utils.texi (Keep-alives): removed outdated info about not
+	maintaining the state of TCP NFS servers
+
+2002-11-04  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* include/am_utils.h: prototype for ops_search()
+
+	* amd/am_ops.c (ops_search): new function for searching the right
+	set of ops for a given filesystem type
+
+	* amd/restart.c (restart): cleanup and split into two functions in
+	preparation for handling the restart of amd's own mount points
+	(restart_fake_mntfs): new function, factored out from restart()
+
+2002-11-04  Ion Badulescu  <ionut@buggy.badula.org>
+
+	* amd/ops_cdfs.c (mount_cdfs): remove special code for loop device
+	(cdfs_umount): ditto
+
+	* conf/mount/mount_linux.c (mount_linux): factor it out to
+	mount_linux_nfs() and mount_linux_nonfs()
+	(mount_linux_nonfs): generalize loop device support to all
+	filesystems (not just cdfs); make it automatic for anything that's
+	a regular file
+	(parse_opts): deprecate the explicit "loop" mount option
+	(do_mount_linux): minor cleanup
+
+	* conf/umount/umount_default.c (umount_fs2): release loop device
+	on umount()
+
+2002-11-03  Erez Zadok  <ezk@cnm20>
+
+	* include/am_defs.h: moved #include of net/if.h above net/route.h,
+	because on AIX 5.2 if.h is needed for route.h (let's hope it
+	doesn't break things on other systems).
+
+	* include/am_defs.h: AIX 5.2 needs struct sigevent from signal.h
+	to be defined, but I don't want to move the inclusion of signal.h
+	this early into this file.  Luckily, amd doesn't need the size of
+	this structure in any other structure that it uses.  So we
+	sidestep it for now.
+
+	* conf/nfs_prot/nfs_prot_aix5_2.h: AIX 5.2 wants 'struct pathcnf',
+	but I couldn't find its definition anywhere.  Luckily, amd doesn't
+	need the size of this structure in any other structure that it
+	uses.  So we sidestep it for now.
+
+2002-11-02  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* config.guess, config.sub, doc/texinfo.tex: updates from
+	the latest GNU distributions (2002-09-05).
+
+2002-10-30  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* conf/nfs_prot/nfs_prot_aix5_2.h: add more definitions from
+	mount.h for NFSOPT_* and NFSMNT_*.
+	Don't use typedefs that aren't found in system header files.
+
+2002-10-30  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* Makefile.am (EXTRA_DIST_CONF): distribute nfs_prot_aix5_2.h.
+
+	* conf/nfs_prot/nfs_prot_aix5_2.h: new file.
+
+	* aux/macros/struct_nfs_args.m4 (ac_cv_have_struct_nfs_args): look
+	for "struct aux52_nfs_args".
+
+	* aux/macros/check_nfs_prot_headers.m4: define new header file for
+	AIX 5.2.
+
+2002-10-21  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* scripts/amd.conf.5 (ldap_proto_version): document in amd.conf
+	man page.
+
+	* scripts/amd.conf-sample (ldap_proto_version): show example of use
+
+	* doc/am-utils.texi (ldap_proto_version Parameter): document new
+	amd.conf option.
+
+	* amd/conf.c (gopt_ldap_proto_version): new conf function to
+	support ldap_proto_version amd.conf parameter.
+
+	* amd/amd.h: field to hold LDAP protocol version.
+
+	* amd/amd.c (init_global_options): set default for
+	ldap_proto_version.  ldap_proto_version patch from George Ross
+	<gdmr@dcs.ed.ac.uk> and Tim Colles <timc@inf.ed.ac.uk>.
+
+	* amd/info_ldap.c (amu_ldap_unbind): ignore SIGPIPE errors while
+	unbinding from an LDAP server that may have been restarted.  Fix
+	from George Ross <gdmr@dcs.ed.ac.uk>.
+
+2002-09-17  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* remove all autoconf stuff added for sys_nerr
+
+	* amq/amq.c, libamu/xutil.c, hlfsd/hlfsd.c: always use strerror
+
+	* libamu/strerror.c: more explicit text for unknown errno's
+
+2002-10-01  Erez Zadok  <ezk@cs.sunysb.edu>
+
+	* include/am_defs.h: define "extern int sys_err" if needed.
+
+	* aux/macros/header_templates.m4: template for
+	HAVE_EXTERN_SYS_NERR.
+
+	* hlfsd/hlfsd.h, libamu/xutil.c (expand_error), amq/amq.c
+	(show_mi): remove "extern int sys_err"
+
+	* configure.in: execute test for "extern int sys_err"
+
+	* Makefile.am (EXTRA_DIST_AUX): distribute new extern_sys_err.m4 file.
+
+	* aux/macros/extern_sys_nerr.m4: new test to check for existence
+	of "extern int sys_nerr" definition in system headers.
+
+2002-09-17  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* libamu/xutil.c (dbg_opt): bring comments in line with the code
+
+	* hlfsd/hlfsd.c (main): use amuDebug() instead of touching
+	debug_flags directly
+
+	* amd/amd.c (main): don't init debug_flags, leave it as zero (no
+	debugging by default)
+
+2002-09-11  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	Debug code sanitization:
+
+	- amuDebug() becomes an expression, and explicit if() statements
+	are added around it throughout the code
+	- amuDebugNo() goes away (ugh!)
+	- D_AMQ, D_DAEMON and D_FORK reverse their meaning
+	- D_ALL contains only options that don't affect amd's functionality
+
+2002-09-04  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* amd/amfs_auto.c (free_continuation): avoid double-free'ing the
+	mntfs if there was an error/timeout
+
+2002-09-04  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* amd/amfs_auto.c (amfs_auto_lookup_mntfs): use ereturn() instead
+	of "return NULL" to signal an error to the upper layers
+	(amfs_auto_mount): use strdup so the string can be free'd later on
+	[Debian bug report from Matt Chapman <matthewc@cse.unsw.edu.au>]
+
+2002-09-03  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	Patches from George Ross <gdmr@dcs.ed.ac.uk>:
+
+	* amd/amfs_auto.c (assign_error_mntfs): do not discard old mntfs,
+	it will be done in free_continuation(); assorted debugging messages
+
+	* amd/srvr_nfs.c (nfs_timed_out): allocate a new XID on server
+	timeout to avoid problems with late ping replies
+
+	* amd/mntfs.c (free_mntfs): sanity check for mf_refc; assorted
+	debugging messages
+
+	* amd/map.c (unmount_node): more verbose debug message
+
+2002-07-29  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* amd/amfs_auto.c (amfs_auto_lookup_mntfs): prevent deferencing
+	de-allocated memory in str3cat
+	(amfs_auto_lookup_mntfs): check for buffer overflow
+
+2002-07-11  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* scripts/expn.{1,in}: fixed typos as reported by Thomas Klausner
+	<wiz@danbala.ifoer.tuwien.ac.at>.
+
+2002-06-26  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* doc/Makefile.am (install-html): don't use locally hacked
+	texi2html features.
+
+	* conf/transp/transp_sockets.c (amu_get_myaddress): Most modern
+	systems should use 127.0.0.1 as the localhost address over which
+	you can do NFS mounts.  In the past we found that some NFS clients
+	may not allow mounts from localhost.  So we used get_myaddress()
+	and that seemed to work.  Alas, on some other systems,
+	get_myaddress() may return one of the interface addresses at
+	random, and thus use a less efficient IP address than 127.0.0.1.
+	The solution is to hard-code 127.0.0.1, but still check if
+	get_myaddress() returns a different value and warn about it.
+
+	* doc/am-utils.texi: don't use ':' in @cindex entries.
+
+2002-06-25  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* Released beta version 6.1b1
+
+2002-06-24  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* aux/macros/struct_nfs_args.m4: added test for aix51_nfs_args
+
+	* conf/nfs_prot/nfs_prot_aix5_1.h: rename aix42_nfs_args to
+	aix51_nfs_args, rename unknown fields to u<number>, add the
+	unknown new field into the middle of the old 4.2 structure
+
+2002-06-24  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* include/am_compat.h: better test for struct netconfig
+	(!HAVE_NETCONFIG_H && !HAVE_SYS_NETCONFIG_H)
+
+	* aux/macros/check_nfs_prot_headers.m4: added new header for aix5.1+
+
+	* buildall: fix 'buildall -b' on hpux9 and aix5.1
+
+2002-06-24  Ion Badulescu  <ionut@buggy.badula.org>
+
+	* INSTALL: updated
+
+	* conf/autofs/autofs_solaris_v1.c (autofs_link_mount): compile fix
+	(autofs_link_umount): ditto
+
+	* amd/mntfs.c (init_mntfs): don't use autofs if !amd_use_autofs
+
+2002-06-23  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* conf/autofs/autofs_linux.c: compile fixes for autofs v3
+
+2002-06-23  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_mounted): no
+	expirations needed;
+	(autofs_timeout_mp): likewise
+
+	* conf/autofs/autofs_solaris_v1.c (autofs_mounted): no expirations
+	needed;
+	(autofs_timeout_mp): likewise
+
+	* conf/autofs/autofs_linux.c (autofs_mounted): set the first
+	expiration interval
+
+	* amd/autil.c (am_mounted): call autofs_mounted here, instead of
+	in mf_mounted()
+
+	* amd/amd.h (NEVER): moved here from map.c
+	(autofs_mounted): change argument from mntfs* to am_node*
+
+2002-06-23  Ion Badulescu  <lionut@gonzales.badula.org>
+
+	* conf/autofs/autofs_linux.c (autofs_mounted): set the kernel
+	timeout on the autofs mountpoint to cache_duration (gopt.am_timeo)
+	(autofs_timeout_mp): don't update the ttl if we're going down
+
+	* amd/map.c (timeout_mp): don't call autofs_timeout_mp unless the
+	timeout on that particular am_node has expired
+
+	* conf/autofs/autofs_linux.c (autofs_timeout_mp): really update
+	the ttl, as per the comment (compilers are not very good at
+	translating comments into code...)
+
+	* amd/amfs_auto.c (amfs_auto_lookup_one_mntfs): strdup am_path
+	instead of opt_rfs into opt_fs for autofs, thus avoiding conflicts
+	between link mounts pointing to the same target
+
+2002-06-23  Ion Badulescu  <lionut@gonzales.badula.org>
+
+	* conf/autofs/autofs_linux.c (send_fail, send_ready): new helper
+	functions for sending messages back to the kernel
+	(autofs_expire_one): initial implementation of the kernel-based
+	expiration handler
+	(autofs_handle_expire): call autofs_expire_one()
+	(autofs_handle_expire_multi): ditto
+	(autofs_umount_succeeded): search pending_umounts, send message
+	back to the kernel
+	(autofs_umount_failed): ditto
+	(autofs_mount_succeeded): tell amd core not to expire autofs entries
+	(autofs_timeout_mp): expiration function for autofs filesystems
+	(autofs_timeout_mp_task): helper function for autofs_timeout_mp
+
+	* conf/autofs/autofs_linux.h: new struct autofs_pending_umount for
+	keeping tracking of pending umounts
+	(autofs_fh_t) rename pending to pending_mounts, add pending_umounts
+
+	* conf/autofs/autofs_solaris_v1.c (autofs_timeout_mp): stub
+
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_timeout_mp): stub
+
+	* amd/map.c (timeout_mp): call autofs_timeout_mp() for autofs
+	filesystems
+
+	* amd/autil.c (mf_mounted): move here the call autofs_mounted()
+	from amfs_auto_mounted().
+
+2002-06-22  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
+
+	* amd/nfs_start.c (mount_automounter): Security fix.  if user sets
+	-D noamq, don't even create listening socket.  Suggestion by Ed
+	Ravin <eravin@panix.com>.
+
+2002-06-22  Ion Badulescu  <lionut@gonzales.badula.org>
+
+	* hlfsd/homedir.c (homedir): use setgid() instead of setegid()
+
+	* ALL: #ifdef cleanups, unify some TLI/socket function prototypes
+
+2002-06-22  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
+
+	* conf/nfs_prot/nfs_prot_netbsd1_4.h: minor port to support
+	na_gid and na_uid.  NetBSD patch from Jun-ichiro itojun Hagino
+	<itojun@iijlab.net>.
+
+	* doc/am-utils.texi (Option): document xlatecookie mount option.
+
+	* libamu/mount_fs.c (compute_nfs_args): support "xlatecookie"
+	NFS mount option.  Patch from Matthias Scheler <tron@zhadum.de>
+	for NetBSD.
+
+2002-06-22  Ion Badulescu  <ionut@edgar.badula.org>
+
+	* conf/autofs/autofs_solaris_v1.h: add FS_MBACKGROUND to
+	AUTOFS_LINK_FS_FLAGS
+
+	* conf/autofs/autofs_solaris_v1.c: convert link mounts to lofs
+	mounts in autofs_link_mount/umount
+
+2002-06-22  Ion Badulescu  <lionut@gonzales.badula.org>
+
+	* configure.in: check for devid inside struct umntrequest
+
+	* conf/autofs/autofs_solaris_v2_v3.c (xdr_umntrequest): handle the
+	new umntrequest structure in v4.
+	(autofs_unmount_2_req): ditto
+
+	* README.autofs: updated for Solaris 2.5/2.5.1
+
+2002-06-22  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
+
+	* configure.in: only define LDAP/Hesiod if both the headers and
+	the libraries exist, and the user didn't explicitly disable those
+	maps.
+
+2002-06-22 Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* doc/am-utils.texi: fix typos.  Can't use ":" in @cindex entries.
+
+2002-06-22  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
+
+	* doc/am-utils.texi, scripts/amd.conf.5, scripts/amd.conf-sample,
+	amd/amd.8, amd/get_args.c (get_args): document amd -A option.
+
+	* amd/get_args.c (get_args): support "amd -A arg" option to
+	override the system's detected architecture.  Patch from George
+	Ross <gdmr@dcs.ed.ac.uk>.
+
+	* amd/info_ldap.c (amu_ldap_rebind): don't use ldap_enable_cache()
+	if the system doesn't have it.
+
+	* configure.in: detect existence of ldap_enable_cache function,
+	because it doesn't exist on Solaris 9's latest ldap libraries.
+
+	* amd/info_ldap.c: LDAP patches from George Ross
+	<gdmr@dcs.ed.ac.uk>.  Rework of old code, support for wildcards in
+	LDAP queries, and an FD leak fix.
+
+2002-06-22  Ion Badulescu  <lionut@gonzales.badula.org>
+
+	* buildall: use ksh for configure on aix5.1; pass the extra
+	arguments after "--" to configure, not to make
+
+	* Makefile.am: added nfs_prot_aix4_3.h to EXTRA_DIST_CONF
+
+	* conf/mount/mount_aix.c (mount_aix3): if the NFSv3 mount fails
+	with EINVAL and we have MOUNT_TYPE_NFS3_BIS defined, retry the
+	mount with the alternative nfs3_args structure
+
+	* conf/nfs_prot/nfs_prot_aix4_3.h: added alternative nfs3_args
+	structure, similar to that in aix5.1, for a hack that tries to
+	compensate for IBM's brain fart
+
+	* conf/nfs_prot/nfs_prot_aix5_1.h: new nfs_prot header for aix5.1+
+
+	* aux/macros/check_nfs_prot_headers.m4: added new header for aix5.1+
+
+	* BUGS: update for direct mounts on Linux; document the brokenness
+	of /bin/sh on AIX 5.1 and HP-UX 9
+
+	* NEWS: aix5.1 port, aix4.3 workaround
+
+2002-06-22 Erez Zadok <ezk@agora.fsl.cs.sunysb.edu>
+
+	* ltmain.sh: use libtool 1.4d, needed support for newer AIX.
+
+2002-06-21  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* aux/macros/check_autofs_style.m4: enable autofs_v2_v3 for
+	all solaris2.6+, not just for 2.[6-8]
+
+	* conf/autofs/autofs_default.h: disable autofs if configure
+	detects it
+
+2002-06-21  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* aux/macros/with_addon.m4: correct M4 quoting.
+
+	* aux/macros/cache_check_dynamic.m4: correct M4 quoting.
+
+	* bootstrap: show version of autotools being used.  Helps
+	maintainer debugging.
+
+	* configure.in: new proper syntax for libtool and
+	ansi2knr-filtering rules, required by autoconf 1.53 and higher.
+
+2002-06-21  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/GNUmakefile: new search paths for "update" target.
+
+	* config.guess, config.sub, doc/texinfo.tex, ltmain: updates from
+	the latest GNU distributions.
+
+2002-06-11  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* amd/amfs_auto.c (amfs_auto_lookup_child): split part of this
+	function into the new amfs_auto_lookup_one_child function; return
+	null if all ivecs failed to match
+
+2002-05-30  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* config.guess.long: support SuSE version names in long
+	config.guess format.
+
+2002-05-01  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/lostaltmail.in (vrfy_user): unlink temp files if too
+	small.
+
+2002-04-07  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* hlfsd/hlfsd.c (main): compile fix for --enable-debug=no
+
+2002-03-29  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* README.autofs: solaris 2.5/2.5.1 info, other minor changes
+
+	* doc/am-utils.texi (History): document solaris 2.5+ support
+
+	* include/am_utils.h: new member in struct mntfs: mfs_real_mount;
+	autofs_fs_flags becomes conditional of HAVE_AUTOFS_FS; new
+	prototype for umount_fs2(); extra argument for UMOUNT_FS()
+
+	* hlfsd/hlfsd.c: use the new mount_fs2() and UMOUNT_FS()
+
+	* libamu/mount_fs.c (mount_fs): wrapper around the new mount_fs2()
+	function; swap mntdir and real_mntdir as necessary for solaris 2.5
+	autofs support
+
+	* conf/umount/umount_default.c (umount_fs2): swap mntdir and
+	real_mntdir as necessary for solaris 2.5 autofs support
+
+	* conf/umount/umount_*.c (umount_fs): wrapper around the new
+	umount_fs2() function
+	(umount_fs2): new function which takes the real mountpoint as an
+	extra argument
+
+	* conf/nfs_prot/nfs_prot_sunos5_5.h: allow autofs support to be
+	compiled in
+
+	* conf/autofs/autofs_solaris_v1.h (autofs_strdup_space_hack): new
+	function that appends a space at the end of a string (the famous
+	"Autofs Space Protocol")
+
+	* conf/autofs/autofs_solaris_v1.c: almost complete reimplementation
+
+	* conf/autofs/autofs_*.h (AUTOFS_*_FS_FLAGS): add
+	system-specific definitions for these macros
+
+	* conf/autofs/autofs_linux.c (create_autofs_service): remove hacks
+	which are now handled properly by more generic code
+	(autofs_link_umount): complain if umount_fs() fails, rmdir the
+	mountpoint on success
+	(autofs_umount_succeeded): remove the rmdirs() code, now handled
+	by generic code
+	(autofs_mount_succeeded): ditto
+
+	* amd/nfs_start.c (checkup): implement it as an emtpy stub if
+	DEBUG is not defined
+	(run_rpc): call autofs_add_fdset() after umount_exported() to
+	avoid passing invalid file descriptors to select(); use plog()
+	instead of perror()
+
+	* amd/mntfs.c (init_mntfs): initialize mf_real_mount from mp
+	(uninit_mntfs): free mf_real_mount
+
+	* amd/autil.c (am_unmounted): don't remove the mount point if a
+	remount is pending, also don't make the removal conditional on not
+	being an autofs mount point
+
+	* amd/amfs_nfsx.c (amfs_nfsx_remount): call mkdirs() on
+	mf->mf_real_mount instead of mf->mf_mount
+
+	* amd/amfs_nfsl.c, amd/amfs_nfsx.c: (amfs_nfsl_umounted): call
+	rmdirs() on mf->mf_real_mount instead of mf->mf_mount
+
+	* amd/amfs_host.c (make_mntpt): change the third argument to be
+	the mountpoint, not the entire mntfs structure
+	(do_mount): takes real_mntdir as an extra argument
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): move the creation of the
+	mountpoint here from try_mount(), otherwise the change to mf_flags
+	is lost for background mounts; remove the mountpoint if we created
+	it and the mount fails
+	(amfs_auto_lookup_mntfs): re-initialize mf->mf_real_mount using
+	autofs_strdup_space_hack() if NEED_AUTOFS_SPACE_HACK is defined
+
+	* amfs_*.c, ops_*.c: initialize autofs_fs_flags using the
+	AUTOFS_*_FS_FLAGS macro defined in the system-specific autofs
+	header; UMOUNT_FS() takes mf->mf_real_mount as an extra argument;
+	mount_fs() becomes mount_fs2() and takes mf->mf_real_mount as an
+	extra argument
+
+	* amd/amd.h, amd/ops_nfs.c, amd/amfs_host.c: mount_nfs_fh takes
+	the real mountpoint as an additional argument
+
+2002-03-28  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* amd/ops_cdfs.c (mount_cdfs): correctly interpret error return
+	values back from mount_fs().  Return correct error number from
+	this function.
+
+	* conf/mount/mount_linux.c (do_mount_linux): cleanup loop mount
+	cruft from this function, moved elsewhere.
+	(mount_linux): prepare for loop-device mounts of ISO images.
+
+2002-03-28  Ion Badulescu  <ionut@buggy.badula.org>
+
+	* libamu/Makefile.am (EXTRA_DIST): added strerror.c
+
+	* libamu/strerror.c: strerror() implementation for systems lacking it
+
+	* doc/am-utils.texi (History): rewrote the history :) about autofs
+	support
+
+	* conf/autofs/autofs_solaris_v2_v3.c: updated copyright;
+	(autofs_unmount_2_req): minor cleanup
+	(create_autofs_service): print log message
+	(destroy_autofs_service): ditto
+
+	* conf/autofs/autofs_linux.c: updated copyright
+
+	* amd/nfs_start.c (mount_automounter): move the debug message into
+	create_autofs_service()
+
+	* amd/amd.c (main): call destroy_autofs_service() before
+	going_down(), not after
+
+	* configure.in: added strerror to AC_CHECK_FUNCS(); disable ldap
+	if the ldap headers are not found
+
+2002-03-28  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* amd/info_ldap.c: patch from "Sebastien Bahloul"
+	<sebastien.bahloul@medasys.org> to fix a simple initialization bug
+	and change "HE" to HE_ENT so as to compile on HPUX.
+
+2002-02-26  Erez Zadok  <ezk@t3.fsl.cs.sunysb.edu>
+
+	* conf/nfs_prot/nfs_prot_freebsd3.h (na_uid): freebsd4.5 uses nfs
+	atttributes field named "uid".  So #define na_uid to it.
+
+2002-02-12  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* scripts/lostaltmail.in: don't verify user if -noverify option
+	was turned on.  fix comment typo.
+
+2002-02-11  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* amd/Makefile.am (TESTS): enable one test script, test1.sh.
+
+	* amd/test1.sh: re-commit simple test script.
+
+2002-02-11  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* Released snapshot 6.1a5
+
+	* NEWS: Solaris autofs readdir() support, Linux autofs sublink fix
+
+	* README: require newer auto-tools, update mailing list address
+
+	* README.autofs: major update
+
+	* configure.in: version changed to 6.1a5
+
+2002-02-11  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* conf/autofs/autofs_linux.c (autofs_link_mount): don't do a
+	stat() on the am_link if called from the parent amd, to prevent
+	deadlocks
+
+	* amd/autil.c (am_unmounted): call amfs_link_ops.umount_fs if the
+	fstype is not link but we have a sublink (Linux autofs needs this)
+	(am_mounted): call amfs_link_ops.mount_fs if the fstype is not
+	link but we have a sublink (Linux autofs needs this)
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): print the real mountpoint,
+	not the amd entry point
+
+2002-02-09  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* conf/autofs/autofs_solaris_v2_v3.c (amd_rddirres): new custom
+	structure for returning the results from readdir_2()
+	(xdr_amd_putrddirres): renamed from xdr_autofs_putrddirres,
+	changed to process our internal format (which is essentially the
+	NFS readdir format)
+	(xdr_autofs_getrddirres): not needed, deleted
+	(xdr_amd_rddirres): renamed from xdr_autofs_rddirres, other
+	changes to handle amd_rddirres instead of autofs_rddirres
+	(autofs_lookup_2_req): return AUTOFS_NONE instead of
+	AUTOFS_MOUNT_RQ, to prevent mount storms during ls -F
+	(autofs_readdir_2_req): implemented
+	(autofs_readdir_2_free): not needed, deleted
+	(autofs_program_2): changes from autofs_rddirres to amd_rddirres
+	(autofs_get_fh): changed initialization of the fh->map member, it
+	now gets the mountpoint path because it makes it easier to
+	implement readdir
+	(autofs_release_fh): put #ifdef HAVE_AUTOFS_ARGS_T_ADDR around
+	code touching fh->addr
+	(destroy_autofs_service): new function, deregister the autofs
+	service with the portmapper on exit
+
+	* conf/autofs/autofs_linux.c (autofs_handle_missing): update
+	statistics
+	(destroy_autofs_service): new stub
+
+	* amd/mapc.c (mapc_find): fixed indentation
+
+	* amd/map.c (find_ap_recursive): renamed from find_ap2(), made
+	static
+
+	* amd/amd.h: removed prototype for find_ap2(), added prototype for
+	destroy_autofs_service()
+
+	* amd/amd.c (main): call destroy_autofs_service() before going
+	down
+
+2002-02-07  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_field.m4: need also a new version of
+	AC_CHECK_MEMBERS (plural).
+
+2002-02-06  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_field.m4: include a fixed version of
+	AC_CHECK_MEMBER.  g/cc will fail to check a member if the .member
+	is itself a data structure, because you cannot compare, in C, a
+	data structure against NULL; you can compare a native data type
+	(int, char) or a pointer.  Solution: do what I did in my original
+	member checking macro: try to take the address of the member.  You
+	can always take the address of anything.
+
+2002-01-31  Erez Zadok  <ezk@localhost.localdomain>
+
+	* remove old '%W%' SCCS IDs from all sources.
+
+2002-01-21  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* conf/mount/mount_linux.c (mount_linux): fix breakage introduced
+	by the loop device mount support. Linux mount takes a real string
+	as the last argument, unless the mount type is NFS, NCP, or SMB.
+
+2002-01-20  Erez Zadok  <ezk@localhost.localdomain>
+
+	* hlfsd/hlfsd.h (HLFSD_VERSION): up version of hlfsd to 1.2,
+	because we made some important changes.
+
+2002-01-20  Ion Badulescu  <lionut@gonzales.badula.org>
+
+	* include/am_utils.h (D_ALL): do not include D_MTAB and D_HRTIME
+	by default
+
+	* NEWS: document latest changes
+
+	* amd/map.c (unmount_mp): same fix as for hlfsd, update the
+	seconds field in mtime because Linux ignores the useconds field
+
+	* hlfsd/homedir.c: made some global vars static
+	(plt_init): remove all trailing '/' chars from root's home;
+	use root's home, not the username (silly bugfix)
+
+2002-01-20  Ion Badulescu  <lionut@gonzales.badula.org>
+
+	* hlfsd/homedir.c (homedir): don't special case uid 0 as having /
+	as home; instead use the root account's home
+	(plt_init): properly initialize root_home from the root account's
+	home directory, or as "" if root doesn't exist
+	(plt_reset): free root_home
+
+2002-01-20  Erez Zadok  <ezk@localhost.localdomain>
+
+	* hlfsd/stubs.c (nfsproc_{lookup,getattr}_2_svc): non-SYMTTL code.
+	Increment seconds, not microseconds (which are ignored by NFS).
+	Set symlink owner to euid.
+
+	* hlfsd/homedir.c (homedir): pass gid to this function, so we can
+	also change the effective GID of the process writing to the user's
+	home dir, as well as the group of the hlfsd symlink.
+	(homedir): run setegid in the right places.
+
+2002-01-15  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* scripts/redhat-ctl-amd.in: refer to @sbindir@ not
+	${prefix}/sbin.
+
+	* scripts/ctl-{amd,hlfsd}.in: refer to @sysconfdir@ not
+	${prefix}/etc.  Bug report from "A Braunsdorf"
+	<ab@eas.purdue.edu>.
+
+2002-01-13  Erez Zadok  <ezk@localhost.localdomain>
+
+	* configure.in: only check for clock_gettime if --enable-debug was
+	used.
+
+	* aux/macros/opt_debug.m4: define a cache variable to record value
+	of debug option used.
+
+	* libamu/xutil.c (show_time_host_and_name): do not use
+	clock_gettime unless debugging was compiled in.  This way, if
+	debugging is not compiled, we don't bother linking with librt,
+	libpthread, and a whole lot of other libraries that aren't that
+	necessary (esp. on Linux).
+
+2002-01-12  Erez Zadok  <ezk@wavy.dyn.optonline.net>
+
+	* doc/am-utils.texi (opts Option): document loop option.
+
+	* include/am_utils.h: each mounted file system (mntfs) should
+	optionally store the loop device used in the field mf_loopdev.
+
+	* conf/nfs_prot/nfs_prot_linux.h: define HAVE_LOOP_DEVICE and some
+	loop function extern definitions.  For now this code is here
+	because we only support loop devices on Linux.
+
+	* conf/mount/mount_linux.c: recognize "loop" as a valid iso9660
+	mount option.
+	(parse_opts): when skipping over unknown mount options, skip over
+	"loop" (since it was given in amd map entry), but not over
+	loop=/dev/loopX, because the latter will go into /etc/mtab.
+	(do_mount_linux): override actual cdfs mounted  device name
+	because with loop devices you don't mount the .iso file directly,
+	but the /dev/loopX device that was setup for it.
+	(show_loop, is_loop_device, find_unused_loop_device,
+	setup_loop_device, delete_loop_device): support code for loop
+	devices.
+
+	* amd/ops_cdfs.c (mount_cdfs): pass loop device name to function.
+	setup loop device before isofs mount, if "loop" option was given,
+	before actual mount(2).
+	(cdfs_mount): pass loopdev name to mount_cdfs().
+	(cdfs_umount): delete/unset loop device after a successful
+	unmount, if a loop device was used.
+
+	* amd/mntfs.c (init_mntfs): initialize mf_loopdev to NULL.
+
+	* include/am_compat.h: If loop device (header file) exists, define
+	mount table option MNTTTAB_OPT_LOOP.
+
+	* conf/nfs_prot/nfs_prot_linux.h: hack: define HAVE_LOOP_DEVICE
+	here until we have a better way to detect /dev/loop devices.
+
+	* include/am_defs.h: include <linux/loop.h> if it exists.  Define
+	LARGEFILE support macros, possibly needed for loop devices.
+	Redefine dev_t apropriately for loop devices.
+
+	* configure.in: check for <linux/loop.h>.
+
+2002-01-10  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* conf/mount/mount_linux.c (mount_linux): tcp _must_ have a timeo
+	parameter 2 orders of magnitude larger than udp (patch from Trond
+	Myklebust)
+
+2002-01-09  Erez Zadok  <ezk@localhost.localdomain>
+
+	* aux/macros/linux_headers.m4: properly [quote] a long string in
+	m4 and use AC_MSG_WARN.
+
+	* ALL: put /* comments */ on #else/#endif lines everywhere.
+
+	* configure.in, aux/macros/with_addon.m4: due to limitation of
+	AC_HELP_STRING, pass 2nd arg to AMU_WITH_ADDON, listing name of
+	package for help string.
+
+	* doc/am-utils.texi (FSinfo): fixed various texinfo errors in the
+	FSinfo section of the manual.
+	(map_reload_interval Parameter): document new amd.conf global
+	parameter.
+
+	* scripts/amd.conf.5 document new global option
+	map_reload_interval.  Sort entries for nfs_vers and nfs_proto
+	alphabetically.
+
+	* amd/nfs_start.c (do_select): increment do_mapc_reload's value by
+	global map_reload_interval value, not by fixed ONE_HOUR.
+
+	* amd/amd.c (main): increment do_mapc_reload's value by global
+	map_reload_interval value, not by fixed ONE_HOUR.
+
+	* scripts/amd.conf-sample (map_reload_interval): usage example
+
+	* amd/amd.c (init_global_options): initialize map_reload_interval
+	to 3600 seconds.
+
+	* amd/conf.c (gopt_map_reload_interval): support a new global
+	amd.conf option map_reload_interval, to determine how often (in
+	seconds) Amd should check if the map source has changed and then
+	reload it it.  This value was hard-coded to one hour, now it's the
+	default if not otherwise specified.
+
+	* doc/am-utils.texi (plock Parameter): document plock=yes option
+	as using mlockall(2) if found.
+
+	* scripts/amd.conf.5: document -S option as using mlockall(2) if
+	found.
+
+	* include/am_defs.h: include <sys/mman.h> if it exists.
+
+	* configure.in: check for mlockall() function.  Check for
+	sys/mman.h.
+
+	* amd/amd.c (main): support mlockall() on systems that have it and
+	don't have plock(3) for plock=yes.  On systems that have both,
+	will try plock() first and then mlockall(), until one of them (if
+	any) succeeds.
+
+2002-01-09  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
+
+	* aux/macros/opt_debug.m4, opt_cppflags.m4, opt_amu_cflags.m4,
+	with_addon.m4 (ac_upcase): fix help string formatting using
+	AC_HELP_STRING.
+
+	* amd/test1.sh: simple test script for "make check".  Runs "amd
+	-v".
+
+	* amd/Makefile.am (TESTS): add one simple test script, running
+	"amd -v" and checking its return value.  More tests can be added.
+
+	* aux/macros/linux_headers.m4: use AC_MSG_WARN directly.
+
+	* aux/macros/*.m4: avoid the cumbersome "changequote" M4 command.
+	Instead, list bracketed regexp patterns in [[double brackets]].
+
+	* aux/macros/header_templates.m4: remove all unnecessary
+	HAVE_FIELD_* definitions, now that we're using autoconf's new
+	AC_CHECK_MEMBERS.
+
+	* aux/macros/field_mntent_t_mnt_time_string.m4: don't call
+
+	* configure.in: use new syntax for AMU_CHECK_FIELD
+
+	* aux/macros/check_field.m4: use new and simpler macro
+	AC_CHECK_MEMBERS.  Change all sources to use HAVE_aggregate.member
+	instead of HAVE_FIELD_aggregate.member.
+
+	* aux/amdgrep: simple utility script to egrep the am-utils sources
+	for any pattern.
+
+	* aux/macros/{check_mnttab_style.m4, check_mount_style.m4,
+	check_umount_style.m4, check_network_transport_type.m4}: use newer
+	AC_LIBOBJ macros instead of modifying $LIBOBJS directly
+
+	* aux/macros/func_bad_memcmp.m4: redefine to use native
+	AC_FUNC_MEMCMP, and then define HAVE_BAD_MEMCMP as needed.
+
+	* fsinfo/fsi_gram.y, amd/conf_parse.y: indent #pragma command so
+	pre-ANSI C compilers will ignore it.
+
+	* conf/autofs/autofs_linux.c (autofs_link_mount): call s/getpgrp()
+	correctly depending on whether it takes a void or a 0.
+
+	* configure.in: check if s/getpgrp() takes void or a 0.
+
+2002-01-08  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
+
+	* configure.in: use the newer AC_CONFIG_LINKS instead of
+	AC_LINK_FILES.
+
+	* aux/macros/check_autofs_style.m4, check_checkmount_style.m4,
+	check_mnttab_style.m4, check_mount_style.m4,
+	check_network_transport_type.m4, check_umount_style.m4,
+	check_nfs_prot_headers.m4: removed backward compatible code for
+	pre-autoconf-2.14.
+
+2002-01-07  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
+
+	* doc/Makefile.am: define @SET_MAKE@ for AC_PROG_MAKE_SET macro, since
+	this Makefile could explicitly chdir to other directories and run
+	make there.
+	(install-ps): use ${MAKE} with ${MFLAGS}.
+
+	* Makefile.am (EXTRA_DIST_AUX): distribute new package_*.m4 files.
+	Define @SET_MAKE@ for AC_PROG_MAKE_SET macro, since this Makefile
+	could explicitly chdir to other directories and run make there.
+	(install-snapshot): use ${MAKE} ${MFLAGS}, not hardcoded "make".
+
+	* configure.in: call AC_PROG_MAKE_SET to check if make program
+	defines $MAKE variable.
+
+	* amd/get_args.c (get_version_string): use new PACKAGE_* macros
+	and also report the bug-reporting address.
+
+	* aux/macros/package_{name,version}.m4, header_templates.m4: using
+	new PACKAGE_{NAME,VERSION,BUGREPORT} macros.
+
+	* aux/macros/name_bugreport.m4: simple macro to print out the
+	bug-reporting address which was configured in AC_INIT.
+
+	* bootstrap: remove new autoconf messages about misuse of
+	m4_patsubst and m4_regexp (internal GNU M4 macros).
+
+	* configure.in: remove old comment above AC_OUTPUT.
+	Use AC_CONFIG_FILES and AC_OUTPUT separately.
+	Fix AC_REVISION use.
+	Add AC_COPYRIGHT.
+	Use new style for AC_INIT, listing package name, version, and
+	bug-reporting address.
+	Call new AMU_PACKAGE_* macros.
+
+	* updated copyright year to 2002 on all files
+
+	* configure.in: using newly renamed am-utils macros (AMU_*)
+
+	* aux/macros/*.m4: renamed ALL am-utils specific macros so they
+	start with AMU_*, not AC_*.  That way it is easier to distinguish
+	between macros that come with am-utils and those that are part of
+	Autoconf or Automake.  It helps to identify those am-utils macros
+	that can be removed once there is generic support for them in a
+	future version of Autoconf.
+
+	* bootstrap: run automake --copy
+	remove autom4te.cache dir before rerunning autoconf
+
+2001-12-13  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* scripts/amd.conf.5: correct title to section 5, not 8.  Correct
+	reversed meaning of nfs_proto and nfs_vers parameters.  Typos
+	reported by Peter Breitenlohner <peb@mppmu.mpg.de>.
+
+2001-12-02  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* scripts/ctl-amd.in: run "test" or "[" in front of -x/-f
+
+	* scripts/ctl-hlfsd.in: run "test" or "[" in front of -x/-f
+
+2001-12-02  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* hlfsd/homedir.c (plt_print): fix typo (s/plot/plog/) in
+	non-mkstemp code
+
+	* scripts/ctl-amd.in: touch/remove /var/lock/subsys/amd to make RH
+	happy
+
+	* scripts/ctl-hlfsd.in: ditto (for hlfsd)
+
+	* conf/mtab/mtab_file.c (rewrite_mtab): fchmod(644) the file we
+	get from mkstemp(), otherwise samba becomes very unhappy (sigsegv)
+
+	* conf/mtab/mtab_mach3.c (rewrite_mtab): ditto
+
+2001-11-29  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* tasks: updated
+
+	* NEWS: document the fixed autofs fd leak
+
+	* amq/amq.8: better document the -f option
+
+2001-11-29  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* libamu/mount_fs.c (mnt_flags): same this as for nolock option
+	handling, do for maxgrps.
+
+2001-11-29  Ion Badulescu  <ion@guppy.limebrokerage.com>
+
+	* conf/autofs/autofs_linux.c (hash_init): determine the max number
+	of fd's at runtime, use it to dynamically scale the hash and list
+	arrays
+	(autofs_get_fh): sanity check, don't allow a pipe() fd greater
+	than autofs_max_fds
+	(autofs_release_fh): close our end of the pipe here (no clue why
+	or when it got commented out)
+	(autofs_mounted): set kernelfd to -1 after closing it
+
+2001-11-28  Philippe Troin  <phil@fifi.org>
+
+	* libamu/mount_fs.c (mnt_flags): Drop nolock from generic mount
+	opts.
+	(compute_nfs_args): Added nolock handling.
+	Adapted from an original patch from Avery Pennarun <apenwarr@nit.ca>.
+
+2001-11-27  Erez Zadok  <ezk@a-hpux11i.fsl.cs.sunysb.edu>
+
+	* ported to ia64-hp-hpux11.20 using HP's ANSI/C compiler.
+	Couldn't use bison/flex because of 32-bit vs. 64-bit binaries
+	issues.  Had to use HP's own yacc/lex.
+
+2001-11-26  Erez Zadok  <ezk@a-hpux11i.fsl.cs.sunysb.edu>
+
+	* */Makefile.am: don't use $(OBJECTS) directly because it is no
+	longer automatically defined now that Automake has automatic
+	dependency tracking (which I turn off).  Instead, hard-code
+	minimal dependencies on am-utils' header files to depend on
+	PROG_OBJECTS (where PROG is the program name being built).  This
+	was discovered by using HP's non-GNU make program.
+
+	* amd/nfs_start.c (checkup): cast getpagesize() return val to
+	long, to avoid conflicts in division of a long by an int (on
+	hpux11i, with their ANSI/C compiler).
+
+ 	* INSTALL, doc/am-utils.texi: port updates
+
+	* minor new ports: ia64-hp-hpux11.20, i386-unknown-freebsd5.0,
+	i386-unknown-freebsd4.4, i386-pc-linux-rh7.2,
+	ia64-unknown-linux-rh7.1.
+
+	* include/am_defs.h: actually declare extern definition for
+	xdr_callmsg() if it doesn't already exist.
+
+	* aux/macros/header_templates.m4: declare template for
+	HAVE_EXTERN_XDR_CALLMSG.
+
+	* configure.in: check for extern definition for xdr_callmsg()
+	because hpux11 has that function but a bad <rpc/xdr.h> header file
+	that doesn't define it in the right place.
+
+	* libamu/mount_fs.c (print_nfs_args): cast ->rdev to u_long b/c
+	on hpux11 its type is dev_t.
+
+	* conf/nfs_prot/nfs_prot_hpux11.h: don't support autofs on hpux11
+	yet.
+
+2001-11-16  Erez Zadok  <ezk@fsl-gw.fsl.cs.sunysb.edu>
+
+	* buildall (Usage): separate $cnf_flags and $extra_cnf_flags due
+	to /bin/sh limitations.
+
+	* bootstrap (cmd): turn back on --ignore-deps (this Automake may
+	have problems)
+
+	* libamu/xutil.c: remove __attribute__ format_arg statement for
+	expand_error() because this function, although taking a
+	printf-like string, does not use it in a printf function; it only
+	expands a non-printf amd-special syntax %m.
+
+2001-11-14  Erez Zadok  <ezk@fsl-gw.fsl.cs.sunysb.edu>
+
+	* conf/nfs_prot/nfs_prot_linux.h: define KERNEL_VERSION macro
+	before using it because older Linux systems don't define this
+	(e.g., Red Hat 4.2)
+
+2001-11-13  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* configure.in: convert to using autoconfig 2.52.  Use new macros.
+	AC_MSG_NOTICE for messages; AH_TOP and AH_BOTTOM to top and bottom
+	parts of autogenerated config.h.in; increase autoconf
+	pre-requisite to version 2.50; use AC_DISABLE_SHARED not
+	AM_DISABLE_SHARED.
+
+	* aux/macros/cache_check_dynamic.m4: finally I can use the new
+	$ECHO_N syntax in macros instead of $ac_n, since I'm using a new
+	autoconf.  Isn't it nice to be such forward looking and having
+	placed a comment "XXX: use the next line for autoconf-2.14 and
+	newer"... :-)
+
+	* aux/macros/save_state.m4: highlight message with ***'s
+
+	* aux/macros/host_macros.m4: use proper M4 quoting ([], not "")
+
+	* config.{guess,sub}: upated from latest prep ftp distributions
+
+	* depcomp, missing, mkinstalldirs: upated from latest Automake 1.5
+
+	* ltmain.sh: updated from latest Libtool 1.4.2
+
+	* bootstrap: finally, new autoconf doesn't print silly "AC_TRY_RUN
+	called without default to allow cross compiling" warnings.  And,
+	it only took like 3+ years to fix this.  But, now it has anoter,
+	albeit less annoying warning (which the manual says to ignore):
+	"AC_PROG_LEX invoked multiple times".
+	When autoheader is run, don't treat the "all clear" message
+	"config.h.in is update" as an error.
+
+	* ltconfig: removed. not needed with latest version of libtool
+
+	* aux/macros/header_templates.m4: replaces acconfig.h and defines
+	all CPP macros we use in this package, including their
+	accompanying C /* comments */.
+
+	* acconfig.h: removed. replaced by new autoconf system to generate
+	header templates using AH_TEMPLATE macros and such.
+
+	* aux/macros/msg.m4: removed.  Replaced with new macro
+	AC_MSG_NOTICE
+
+	* Makefile.am (EXTRA_DIST_AUX): remove aux/macros/msg.m4.  Add
+	aux/macros/header_templates.m4
+
+	* configure.in: early, in host_macros.m4, I'm renaming silly linux
+	$host_os names such as linux-gnu and lignux to plain "linux".
+	Alas, RMS finally had his way and libtool will NOT recognize
+	"linux" as a valid system, only "linux-gnu".  Sigh.  Rich, I know
+	you're responsible to Linux's fame.  Kudos to you and your
+	cohorts.  But please don't force the rest of us to use those ugly
+	or long names.  Solution: temporarily name $host_os to "linux-gnu"
+	before calling the AC_PROG_LIBTOOL macro, then name it back to
+	"linux".  (That way I don't have to maintain my own version of
+	ltmain.sh.
+
+	* buildall: force running configure -C (to create and use a local
+	config.cache file).  New default behavior for autoconf is NOT to
+	use cache files.  Yeah, that's gonna fly real well with am-utils,
+	with its 700+ automatic tests.
+
+	* conf/mtab/mtab_mach3.c (rewrite_mtab): use mkstemp instead of
+	mktemp, if the former is available.
+
+	* conf/mtab/mtab_file.c (rewrite_mtab): use mkstemp instead of
+	mktemp, if the former is available.
+
+	* mk-amd-map/mk-amd-map.c (main): use mkstemp instead of mktemp,
+	if the former is available.
+
+	* aux/macros/check_nfs_socket_connection.m4: AC_DEFINE calls must
+	be on a separate line, as per new Autoconf manual, to avoid some
+	Bourne Shell syntactical bizarreness.
+
+2001-11-13  Erez Zadok  <ezk@a-rh71i.fsl.cs.suunysb.edu>
+
+	* amd/amfs_auto.c (amfs_auto_readdir_browsable): cast to u_long,
+	for IA64 Linux.
+
+2001-11-12  Ion Badulescu  <ionut@buggy.badula.org>
+
+	* libamu/mtab.c (hasmntval): strtol can return a non-NULL pointer
+	pointing to '\0' on success, so we need to allow for it. This
+	fixes the problem with rejecting numerical mount options if they
+	are the last option in the string.
+
+	* configure.in: increased library patchlevel
+
+	* NEWS: document the parsing bug
+
+2001-10-29  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* configure.in: bumped version up to 6.1a5-pre
+
+	* NEWS: fixed speeling mistaike
+
+2001-10-29  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* released snapshot am-utils-6.1a4
+
+2001-10-26  Ion Badulescu  <ionut@moisil.badula.org>
+
+	These changes fix autofs support for sublinks. While it is not
+	perfect by any means and is hardly better than non-autofs, at
+	least it works.
+
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_lookup_2_req): don't
+	reply if the mount is in progress
+	(autofs_mount_succeeded): handle both delayed lookups and mounts
+	(autofs_mount_failed): ditto
+
+	* amd/amfs_auto.c (amfs_auto_lookup_mntfs): don't dispose of the
+	original opt_fs if we have a sublink
+
+2001-10-23  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* amd/amfs_auto.c (amfs_auto_lookup_mntfs): fixed silly typo (mf
+	instead of new_mf) which was causing null pointer error when
+	sublinks were being used
+
+2001-10-22  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* README.autofs: updated
+
+	* NEWS: updated
+
+	* INSTALL: updated
+
+	* AUTHORS: added myself
+
+	* doc/am-utils.texi: updated
+
+	* conf/autofs/autofs_solaris_v2_v3.c (xdr_autofs_rddirargs): use
+	xdr_u_int() and cast things to (int) to appease Solaris 2.7 compile
+	(autofs_readdir_2_req): cast req->rda_offset to (int), same as
+	above
+
+2001-10-22  Ion Badulescu  <ionut@moisil.badula.org>
+
+	Autofs direct mounts have been verified to work on Solaris2.[67].
+
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_lookup_2_req):
+	retrieve the uid and gid from the lookup request
+	(autofs_mount_2_req): skip the first char in the name (it's a
+	leading '/') if this is a direct mount
+
+	* amd/amfs_direct.c (amfs_direct_ops): use amfs_auto_lookup_child
+	and amfs_auto_mount_child for amfs_direct's methods
+
+	* amd/amfs_auto.c (amfs_auto_lookup_child): don't leak an am_node
+	if the mntfs lookup fails
+
+2001-10-21  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* include/am_utils.h (AMF_REMOUNT): new flag, marks the node as
+	pending a remount
+	(mntfs): new member mf_fsflags, holds a copy of the filesystem's
+	fs_flags
+	(am_ops): new member autofs_fs_flags, holds the filesystem's flags
+	when mounted onto an autofs node; fs_flags renamed to nfs_fs_flags
+
+	* conf/autofs/autofs_linux.c (create_autofs_service): turn on
+	FS_MKMNT for amfs_auto and FS_MBACKGROUND for amfs_link
+	(autofs_umount_succeeded): don't rmdir the mountpoint if a remount
+	is needed [lest the access that triggered the remount will fail]
+
+	* amd/mntfs.c (init_mntfs): copy the filesystem's nfs_fs_flags
+	into mf_fsflags on initialization
+
+	* amd/autil.c (am_unmounted): start the remounting right away if
+	the node is marked as needing a remount [fixes the Linux autofs
+	deadlock when mount/unmount collide]
+
+	* amd/amfs_auto.c (amfs_auto_lookup_node): mark the node as
+	needing a remount if a mount request comes in while we're
+	unmounting it
+	(amfs_auto_lookup_mntfs): copy the filesystem's autofs_fs_flags
+	into mf_fsflags if this is an autofs node
+
+	* amd/amfs_*.c, amd/ops_*.c: added initialization for the new
+	autofs_fs_flags member of am_ops
+
+2001-10-20  Ion Badulescu  <ionut@moisil.badula.org>
+
+	With these changes, Solaris 2.[67] autofs support is finally
+	functional!
+
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_readdir_2_req): stub
+	(autofs_readdir_2_free, xdr_autofs_rddirargs, xdr_autofs_putrddirres,
+	xdr_autofs_getrddirres, xdr_autofs_rddirres): new functions
+	(autofs_lookup_2_req): do an actual lookup here, and tell the
+	kernel to create a symlink if necessary
+	(autofs_mount_2_req): no need to am_autofs_data
+	(autofs_program_2): enable AUTOFS_READDIR
+	(autofs_link_mount): no code needed here
+	(autofs_link_umount): return success
+	(autofs_mount_succeeded): lstat real mount points; don't mark
+	symlinks as NOTIMEOUT
+
+	* amd/mntfs.c (init_mntfs): mf_dev and mf_rdev don't exist anymore
+
+	* amd/map.c (init_map): init am_dev and am_rdev to -1
+	(free_map): free am_mfarray and all mntfs's listed
+
+	* amd/autil.c (mf_mounted): move the lstat of the node to the
+	autofs-specific code
+
+	* amd/amfs_link.c (amfs_link_ops): don't background symlink creation
+
+2001-10-18  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* aux/macros/os_cflags.m4 (irix6*): Enforce N32 ABI/mips3 ISA with cc.
+	* BUGS: Explain this.
+
+2001-10-02  Erez Zadok  <ezk@agora.fsl.cs.sunysb.edu>
+
+	* doc/am-utils.texi (redhat-ctl-amd): document new script.
+
+	* scripts/Makefile.am: build redhat-ctl-amd but do not install it.
+
+	* scripts/redhat-ctl-amd.in: new script, useful to correctly
+	control Amd on Red Hat Linux systems.  Script adapted from ctl-amd
+	and Red Hat's own rc.d script.
+
+2001-10-02  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* conf/nfs_prot/nfs_prot_osf5.h: Renamed from nfs_prot_osf5_1.h.
+	(MNT2_NFS_OPT_AUTO): Disable.
+	* Makefile.am (EXTRA_DIST_CONF): Reflect new name.
+	* aux/macros/check_nfs_prot_headers.m4: Use this file for all
+	Tru64 UNIX V5 and up releases.
+
+2001-09-24  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* include/mount_headers1.h (MFS): define as 1 instead of nothing,
+	to fix compile problems on OS X (patch from Ahmon Dancy)
+
+	* aux/macros/try_compile_anyfs.m4 (MFS): ditto
+
+2001-08-13  Erez Zadok  <ezk@fsl-gw.fsl.cs.sunysb.edu>
+
+	* doc/am-utils.texi (in_network Selector Variable): document
+	expanded syntax
+
+	* libamu/wire.c (is_network_member): support for network/netmask
+	as well as network/bits syntax in in_network()
+
+2001-08-11  Erez Zadok  <ezk@a-linux64.fsl.cs.sunysb.edu>
+
+	* amq/amq.c (show_mti): print full four digits for year, and print
+	it in MM/DD/YYYY format, not in YY/MM/DD format.
+
+2001-08-11  Ion Badulescu  <lionut@gonzales.badula.org>
+
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_lookup_2_req):
+	initial attempt to do something useful -- but commented out for now
+	(autofs_link_mount): create an action structure with a link
+	request and pass it up
+	(autofs_mount_2_req): pass the link request to the kernel
+	(autofs_free_data): new helper function
+
+	* conf/autofs/autofs_linux.h: added definition for autofs_data_t
+
+	* conf/autofs/autofs_solaris_v2_v3.h: ditto
+
+	* amd/map.c (init_map): initialize am_autofs_data
+	(free_map): call the autofs cleanup function if necessary
+
+	* include/am_utils.h (am_node): added private data and cleanup
+	function for autofs
+
+	* tasks: removed some obsolete entries
+
+2001-08-11  Erez Zadok  <ezk@a-solaris8.fsl.cs.sunysb.edu>
+
+	* amd/map.c (free_map_if_success): run autofs_umount_failed() only
+	if this mount node is of type autofs.
+
+2001-08-11  Ion Badulescu  <lionut@gonzales.badula.org>
+
+	* amd/amd.h: removed mf_array from struct continuation (moved into
+	am_node)
+
+	* include/am_utils.h: removed VLOOK_LOOKUP; renamed vlookuppn to
+	vlookup_child; added vmount_child; added mount_child to the fs_ops
+	API; added prototypes for amfs_auto_mount_child and
+	amfs_error_mount_child
+
+	* amd/map.c (init_map): initialize am_mfarray to 0
+
+	* amd/amfs_*, amd/ops_*: new API function mount_child, old API
+	function lookuppn renamed to lookup_child
+
+	* amd/amfs_auto.c: renamed amfs_auto_lookuppn1 to
+	amfs_auto_lookup_node; renamed amfs_auto_lookuppn2 to
+	amfs_auto_lookup_mntfs; renamed amfs_auto_lookuppn3 to
+	amfs_auto_mount_child; moved the freeing of the error mntfs in the
+	newly allocated am_node from lookup_mntfs to mount_child; make
+	sure lookup_child returns a negative error if the node needs to be
+	mounted; removed the call to lookuppn3 from lookup_child
+
+	* amd/amfs_error.c: added stub implementations of
+	amfs_error_lookup_child and amfs_error_mount_child
+
+	* amd/amfs_direct.c, amd/amfs_union.c, amd/map.c, amd/nfs_subr.c,
+	conf/autofs/autofs_linux.c, conf/autofs/autofs_solaris_v2_v3.c:
+	call both lookup_child and mount_child, instead of the old
+	lookuppn API method
+
+2001-07-19  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/get_args.c (get_args): a better way to handle GNU and
+	non-GNU getopts without strdup-ing the getopt string.
+
+2001-07-04  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/info_ldap.c (amu_ldap_rebind): The first time you called
+	amu_ldap_init, aldh->ldap is not set.  So when amu_ldap_rebind is
+	called, this function is absolutely sure to return 0.  Then
+	amu_ldap_init return 0 without having opened any LDAP connection.
+	This is not the correct behavior.
+	(get_ldap_timestamp, amu_ldap_search): error to free an object
+	("entry") that is automatically freed by the library.  Patch from
+	Sebastien Bahloul <sebastien.bahloul@mangoosta.fr>.
+
+2001-07-19  Ion Badulescu  <ionut@moisil.badula.org>
+
+	* AUTHORS (variables): added Philippe Troin
+
+	* Makefile.am (EXTRA_DIST): added bootstrap
+
+	* include/am_compat.h (xfs_args_t): define as u_int if the
+	filesystem is supported but we can't autodetect the type for
+	xfs_args_t. This allows Linux to mount xfs filesystems.
+
+2001-07-12  Philippe Troin  <phil@fifi.org>
+
+	* doc/am-utils.texi: Added @dircategory Administration.
+
+2001-07-12  Philippe Troin  <phil@fifi.org>
+
+	* aux/macros/with_addon.m4: Created. Wrapper around AC_ARG_WITH
+	with only the `yes' and `no' as possible answers.
+
+	* configure.in: Added support for disabling LDAP and HESIOD even
+	if the supporting libraries are found.
+
+	* Makefile.am (EXTRA_DIST_AUX): Added with_addon.m4 macro file.
+
+2001-07-12  Philippe Troin  <phil@fifi.org>
+
+	* include/am_compat.h: Removed forced definition of MNTTAB_OPT_DEV
+	if MNT2_GEN_OPT_NODEV was found. Actually, the dev= (SVR4) options
+	and the linux nodev options are different beasts.
+
+	* conf/mount/mount_linux.c (opt_map): Removed the MNTTAB_OPT_DEV
+	entry (not really necessary on linux).
+
+2001-07-12  Philippe Troin  <phil@fifi.org>
+
+	* amd/get_args.c (get_args): Prepend "+" to the getopt string if
+	HAVE_GNU_GETOPT to avoid getting all options (even the ones after
+	the first non-option argument) slurped in by GNU getopt.
+
+	* aux/macros/check_gnu_getopt.m4: Created. Defines HAVE_GNU_GETOPT
+	if GNU/glibc getopt implementation is detected.
+
+	* configure.in: Added call to AC_CHECK_GNU_GETOPT.
+
+	* acconfig.h: Document HAVE_GNU_GETOPT.
+
+	* Makefile.am (EXTRA_DIST_AUX): Added check_gnu_getopt.m4 macro file.
+
+2001-06-25  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* LSM.am-utils, NEWS, README.y2k, ChangeLog: make sure all
+	am-utils URL references use www.am-utils.org, not the columbia
+	URL.
+
+2001-06-08  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/transp/transp_sockets.c (create_nfs_service): cast to
+	u_long to ensure clean compile on freebsd5 and bsdi2.
+
+2001-05-23  Ion Badulescu  <ionut@moisil.badula.org>
+
+	WARNING: WORK IN PROGRESS
+
+	It works for me on Linux (both autofs and nfs mounts), for nfs and
+	link, but I won't make any guarantees outside those.
+
+	* amd/mntfs.c (find_mntfs): reuse the mntfs only if both the mount
+	point and the device/fileserver are the same. This is an important
+	change of philosophy, watch out for memory leaks!
+
+	* amd/map.c (get_ap_child): helper function for
+	amfs_auto_lookuppn, creates a new am_node for key fname, inits it,
+	and inserts it into all necessary structures
+
+	* amd/amfs_auto.c (free_continuation): free unused mntfs's; don't
+	free any of the removed fields
+	(amfs_auto_lookuppn, amfs_auto_bgmount): split lookuppn into three
+	subfunctions, including some code stolen from bgmount; lookuppn
+	now generates an array of possible mntfs to try mounting, and
+	bgmount will actually try to mount each of them.
+	(amfs_auto_lookuppn[123]): the three new subfunctions for lookuppn
+	(amfs_parse_defaults): new helper function for lookuppn
+
+2001-05-19  Erez Zadok  <ezk@kosh.dyn.optonline.net>
+
+	* conf/mount/mount_linux.c: typo: added comma after '0' element.
+
+2001-05-19  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* conf/autofs/autofs_linux.c (AUTOFS_MAX_VERSION): allow using
+	autofs-v4 again
+	(autofs_get_opts): don't pass pgrp, the kernel will get it
+	automatically anyway, not to mention that we were passing bogus
+	data if amd was not daemonized.
+
+	* conf/mount/mount_linux.c (linux_nfs_error): don't special case
+	the 0 result, just put it into the translation list
+
+2001-05-19  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* conf/mount/mount_linux.c (linux_nfs_error): don't report success
+	(0) as error (NE_IO)!
+
+2001-05-18  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* amd/amfs_host.c (amfs_host_mount): don't fail the mount if at
+	least one share is already mounted
+
+2001-05-17  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* libamu/util.c (str3cat): updated comment
+
+	* include/am_utils.h: added VLOOK_LOOKUP and FS_DIRECT
+
+	* conf/autofs/autofs_linux.c (autofs_get_fh): removed obsolete comment
+	(autofs_mounted): disable autofs support for host f/s if version < 4
+	(create_autofs_service): turn on FS_MKMNT on auto f/s if using autofs
+	(autofs_umount_succeeded): use rmdirs instead of rmdir
+	(autofs_mount_failed): ditto
+
+	* amd/opts.c (expand_op): align the debugging messages
+
+	* amd/map.c (mount_auto_node): use am_node *mp instead of casting
+	the void *arg; update the comment
+
+	* amd/autil.c (am_mounted): check the FS_DIRECT flag instead of
+	comparing to &amfs_direct_ops
+	(mount_node): ifs_mount doesn't exist, make note of it in the
+	comment
+
+	* amd/amfs_direct.c (amfs_direct_ops): added FS_DIRECT to fs_flags
+
+	* amd/amfs_auto.c (amfs_auto_mount): removed the autofs hack to
+	create the mountpoint directory for auto f/s; it is now handled in
+	autofs_linux.c
+	(amfs_auto_bgmount): renamed the mpe parameter to mp_error;
+	renamed dont_retry to retry and reverted its meaning as well;
+	moved the mp variable up one scope and made use of it throughout
+	the function;
+	(amfs_auto_readdir): whitespace
+	(amfs_auto_readdir_browsable): whitespace, also some debugging
+
+	* amd/am_ops.c (vops): updated a comment
+
+	* .cvsignore: added A.i386-pc-linux-rh7.[01]
+
+2001-05-01  Ion Badulescu  <ionut@gonzales.dev.hydraweb.com>
+
+	* conf/mount/mount_linux.c: fixed stupid error in the linux
+	nfs_errormap[], which was mapping ENOENT to success!!!
+
+2001-04-28  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* BUGS: added info about the direct mount problems on Linux and
+	about the kernel patches on www.am-utils.org.
+
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_unmount_2_req):
+	removed obsolete comment
+
+	* amd/autil.c (forcibly_timeout_mp): always log a message when the
+	forced unmount request is ignored
+	(mf_mounted): don't lstat unless this is an autofs mount point,
+	lest we deadlock
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): don't gratuitously add
+	MFF_MKMNT to the flags, it causes deadlocks later on when
+	unmounting
+
+2001-04-14  Erez Zadok  <ezk@whitestar.dyn.optonline.net>
+
+	* COPYING: update copyright year
+
+	* amd/amfs_auto.c, amd/amfs_host.c, amd/amfs_nfsx.c,
+	amd/amfs_toplvl.c, amd/amfs_union.c, amd/conf.c, amd/info_nis.c,
+	amd/info_nisplus.c, amd/mapc.c, amd/nfs_subr.c, amd/ops_nfs.c,
+	amd/rpc_fwd.c, amd/srvr_amfs_auto.c, amd/srvr_nfs.c,
+	conf/autofs/autofs_solaris_v1.c, conf/mtab/mtab_file.c,
+	conf/mtab/mtab_isc3.c, conf/mtab/mtab_svr4.c,
+	conf/transp/transp_sockets.c, conf/transp/transp_tli.c,
+	libamu/mount_fs.c, libamu/mtab.c: rewritten various dlog/plog
+	messages for clarity, to avoid duplication, to better recognize
+	what the message means and where it ran, and to fix typos.
+
+	* amd/nfs_subr.c (nfsproc_lookup_2_svc): moved trace message of
+	function's name to the beginning of the function, before any other
+	messages are logged.
+
+2001-04-14  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* conf/mount/mount_linux.c (do_mount_linux): removed plog() of
+	binary data
+
+2001-04-05  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* include/am_defs.h: define NFSCLIENT, NFS, PCFS, LOFS, RFS,
+	MSDOSFS, MFS and CD9660 to 1, so that both #if FOO and #ifdef FOO
+	work (needed for MacOS X); removed duplicate definition of NFS.
+
+2001-03-29  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* amd/amd.h, amd/amfs_auto.c, amd/conf.c,
+	doc/am-utils.texi,
+	scripts/amd.conf-sample, scripts/amd.conf.5:
+	renamed selectors_on_default to selectors_in_defaults,
+	kept the former as a deprecated option;
+	renamed CFM_ENABLE_DEFAULT_SELECTORS to CFM_SELECTORS_IN_DEFAULTS;
+	renamed gopt_selectors_on_default() to gopt_selectors_in_defaults()
+
+2001-03-19  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* amd/amfs_toplvl.c, amd/amfs_auto.c, amd/srvr_nfs.c,
+	include/am_utils.h: compile fixes for --enable-debug=no
+
+2001-03-15  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* NEWS: updated
+
+	* README.autofs: updated
+
+	* conf/mount/mount_linux.c (linux_version_code): export the fn
+
+	* conf/nfs_prot/nfs_prot_linux.h: ditto
+
+	* conf/autofs/autofs_linux.c (create_autofs_service): verify the
+	kernel version here, and turn off bind_works if the kernel is
+	older than 2.4.0.
+	(autofs_link_mount): don't touch bind_works here, it's useless
+	b/c we're in a child process; remove the mountpoint directory if
+	the bind mount fails
+
+	* amd/opts.c (eval_fs_opts): changed some annoying debugging plogs
+	into dlogs
+
+	* conf/autofs/autofs_linux.c (autofs_link_mount): zero out the
+	mntent struct before initializing it
+
+2001-03-14  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* conf/mount/mount_linux.c (parse_opts): added support for lofs
+	(mount_linux): support lofs through bind mounts and/or FiST lofs
+
+	* scripts/ctl-hlfsd.in: search for /var/spool/mail in addition to
+	/var/mail and /usr/spool/mail
+
+	* conf/nfs_prot/nfs_prot_linux.h (MS_BIND): add define for it, if
+	kernel is newer than 2.4.0
+	(MNTTYPE_LOFS): ditto
+
+	* conf/autofs/autofs_solaris_v2_v3.c (autofs_link_umount): new stub
+	(autofs_lookup_failed): removed stub
+
+	* conf/autofs/autofs_linux.c (autofs_lookup_failed): moved up in
+	the file, made static;
+	(autofs_link_mount): activate MNT2_GEN_OPT_BIND code; use stat()
+	and friends to determine if bind mounts can be used and to trigger
+	further cascading mounts; return proper error codes
+	(autofs_link_umount): distinguish between symlinks and bind mounts
+	and handle both correctly
+	(autofs_umount_succeeded): remove call to autofs_link_umount()
+
+	* amd/map.c (umount_exported): try to unmount all mount points on
+	an autofs filesystem; this isn't really needed and will be removed
+	when we start handling restarting autofs mounts
+
+	* amd/amfs_link.c (amfs_link_[u]mount): call autofs_link_[u]mount,
+	if necessary
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): fixed a bug that was
+	causing the wrong mntfs to be selected when using autofs; removed
+	call to autofs_link_mount() (moved where it belongs, in
+	amfs_link.c)
+
+	* amd/amfs_link.c: added FS_MBACKGROUND to fs flags -- cleaner
+	solution is needed, because background mounting is only necessary
+	for linux autofs + bind mounts
+
+	* amd/amd.h: removed prototype for autofs_lookup_failed (internal
+	static function for linux autofs); added prototype for
+	autofs_link_umount
+
+	* configure.in: bump up library patchlevel
+
+2001-02-28  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* aux/macros/check_mount_trap.m4,
+	aux/macros/check_nfs_fh_dref.m4,
+	aux/macros/check_nfs_prot_headers.m4,
+	aux/macros/type_recvfrom_fromlen.m4,
+	aux/macros/type_yp_order_outorder.m4:
+	Fixed newer freebsd's fh type, expanded more aix3, osf2, hpux9 to
+	aix[1-3], osf[1-3] and hpux[6-9].
+
+2001-02-28  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* check_mount_style.m4, check_mount_trap.m4,
+	check_network_transport_type.m4, check_nfs_fh_dref.m4,
+	check_nfs_prot_headers.m4, check_nfs_sa_dref.m4,
+	check_nfs_socket_connection.m4, os_cflags.m4,
+	type_yp_order_outorder.m4: small fixes to Ion's cleanup, and more
+	cleanup (use [[0-1]] instead of M4 changequote commands).
+
+	* Makefile.am: removed unused conf/trap/trap_hpux11.h
+
+2001-02-27  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* aux/macros/check_network_transport_type.m4,
+	aux/macros/check_mount_style.m4,
+	aux/macros/check_mount_trap.m4,
+	aux/macros/check_network_transport_type.m4,
+	aux/macros/check_nfs_fh_dref.m4,
+	aux/macros/check_nfs_prot_headers.m4,
+	aux/macros/check_nfs_sa_dref.m4,
+	aux/macros/check_nfs_socket_connection.m4,
+	aux/macros/os_cflags.m4,
+	aux/macros/type_auth_create_gidlist.m4,
+	aux/macros/type_recvfrom_fromlen.m4,
+	aux/macros/type_yp_order_outorder.m4:
+	Reworked the scripts, so that a new _unknown_ version of a known OS
+	will use the option for the newest _known_ version of that OS. For
+	example, when freebsd6 comes out, it will use the stuff for
+	freebsd5, not the stuff for freebsd2. This makes configure more
+	likely to succeed on new systems/versions.
+
+	* Makefile.am (EXTRA_DIST_AUX): added check_autofs_style.m4 (grr)
+
+2001-02-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* Makefile.am (install-snapshot): use a different symlink target
+	for the experimental snapshots.
+
+2001-02-23  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* Makefile.am (EXTRA_DIST_CONF): include nfs_prot_darwin.h in
+	distributions.
+
+2001-02-22  Erez Zadok  <ezk@earth.cs.columbia.edu>
+
+	* released snapshot am-utils-6.1a3
+
+	* amd/Makefile.am (EXTRA_amd_SOURCES): don't forget to distribute
+	get_args.c
+
+2001-02-21  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/mtab.c: added the functions hasmnteq and haseq to
+	ease checks for non-numeric values in opt=value strings.
+	Recoded hasmntval to qualify input as numeric, allow hex and
+	octal strings on rhs of =, and log when the value is missing
+	or invalid.
+
+	* conf/mount/mount_linux.c: revised mount_linux to use new
+	hasmnteq function to extract type of non-nfs mounts, and added
+	a log message to catch possible failure of strdup.
+
+	* amd/am_ops.c: revised merge_ops to use new haseq function
+
+	* amd/srvr_nfs.c: revised find_nfs_srvr to use hasmnteq to
+	discover protocol setting.
+
+	* include/am_utils.h: added function prototypes for hasmnteq
+	and haseq
+
+2001-02-19  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* include/mount_headers2.h (_LINUX_NFS3_H): define it, to avoid
+	pulling in unwanted declarations from 2.2.19pre and 2.4.1ac
+
+	* include/am_defs.h (_LINUX_NFS3_H): ditto
+
+	* conf/nfs_prot/nfs_prot_linux.h: whitespace, comments
+
+2001-02-19  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_fs_mntent.m4 (ac_safe): remove debugging "echo"
+	command.
+
+2001-02-18  Erez Zadok  <ezk@earth.cs.columbia.edu>
+
+	* aux/macros/mount_headers.m4, include/mount_headers[12].h: split
+	mount_headers.h in two because one relative header (nfs_prot.h)
+	file cannot be included inside another from the start directory of
+	the first (it's relative to the directory of the first).
+
+2001-02-09  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* AUTHORS: added Ahmon Dancy <dancy@franz.com>
+
+	* (all): added Darwin/Rhapsody/Apple OS X support from Ahmon Dancy
+
+	* aux/macros/mount_headers.m4: moved all the C code into a
+	separate file, include/mount_headers.h; the effect is that
+	configure goes down in size by a factor of 2.5!
+
+	* include/mount_headers.h: new file, with C code from
+	aux/macros/mount_headers.m4
+
+2001-02-01  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* conf/mount/mount_linux.c: made linux_nfs_error() more robust.
+
+2001-02-01  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.1a2
+
+	* updated ltmain.sh and ltconfig from latest stable version of
+	libtool-1.3.5
+
+2001-02-01  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* conf/nfs_prot/nfs_prot_linux.h (nfs_error): moved the definition
+	of nfs_error here, from mount_linux.c, so that it can actually be
+	used.
+
+	* conf/mount/mount_linux.c: added unused errno 41 to the
+	nfs_errormap array, lest the following errno's get shifted up by
+	one!
+
+Sat Jan 13 00:04:38 2001  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* amd/amd.h (autofs_lookuppn): Fixup whitespace.
+	* amd/amfs_auto.c (amfs_auto_bgmount): Likewise.
+	* amd/amfs_error.c: (amfs_error_match): Likewise.
+	* amd/amfs_host.c (fetch_fhandle): Fixup whitespace.  Remove
+	unnecessary temporary variable.
+	* amd/info_file.c (read_line): Likewise.
+	(search_or_reload_file): Likewise.
+	* amd/info_ldap.c (get_ldap_timestamp): Likewise.
+	* amd/map.c (get_root_ap): Likewise.
+	* amd/nfs_prot_svc.c: Likewise.
+	* amd/ops_TEMPLATE.c (foofs_match, foofs_lookuppn,
+	foofs_readlink, foofs_ffserver): Likewise.
+	* amd/ops_autofs.c (autofs_bgmount): Likewise.
+	* amd/ops_lofs.c (lofs_match): Likewise.
+	* amd/ops_nfs.c (got_nfs_fh): Fixup whitespace.
+	* amd/ops_xfs.c (xfs_match): Likewise.
+	* amd/srvr_amfs_auto.c (srvrlog): Line break.
+	* amd/srvr_nfs.c (got_portmap, call_portmap, nfs_pinged,
+	nfs_srvr_port): Fixup whitespace.
+	* conf/nfs_prot/nfs_prot_bsdi2.h: Likewise.
+	* conf/nfs_prot/nfs_prot_hpux.h: Likewise.
+	* conf/nfs_prot/nfs_prot_hpux11.h: Likewise.
+	* conf/nfs_prot/nfs_prot_irix5.h: Likewise.
+	* conf/nfs_prot/nfs_prot_irix6.h: Likewise.
+	* conf/nfs_prot/nfs_prot_nextstep.h: Likewise.
+	* conf/nfs_prot/nfs_prot_osf2.h: Likewise.
+	* conf/nfs_prot/nfs_prot_osf4.h: Likewise.
+	* conf/nfs_prot/nfs_prot_osf5_1.h: Likewise.
+	* conf/nfs_prot/nfs_prot_sunos3.h: Likewise.
+	* conf/nfs_prot/nfs_prot_sunos4.h: Likewise.
+	* conf/nfs_prot/nfs_prot_ultrix.h: Likewise.
+	* conf/transp/transp_tli.c (get_mount_client): Likewise.
+	* hlfsd/nfs_prot_svc.c: Likewise.
+	* include/am_defs.h (sys_errlist): Likewise.
+	* include/am_utils.h (am_get_progname, am_get_hostname,
+	amq_program_1): Likewise.
+	(nfsxprt): Moved declaration.
+
+Fri Jan 12 23:31:45 2001  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	Removed support for amq -M.
+
+	* acconfig.h (ENABLE_AMQ_MOUNT): Removed.
+	* aux/macros/opt_amq_mount.m4: Removed.
+	* Makefile.am (EXTRA_DIST_AUX): Don't distribute
+	opt_amq_mount.m4.
+	* configure.in (AC_OPT_AMQ_MOUNT): Removed invocation.
+
+	* amd/amq_subr.c (ok_security, amqproc_mount_1_svc): Removed.
+	* amd/amq_svc.c (amq_program_1): Removed amq -M support.
+	* amq/amq.c (mount_map): Removed.
+	(main): Removed -M option handling.
+	Removed transport-type specific CLIENT creation.
+	(get_secure_amd_client, amq_bind_resv_port, privsock): Removed.
+
+	* amq/amq.8: Removed -M documentation.
+	* doc/am-utils.texi (Top-level Filesystem): Removed amq -M
+	reference, but retain comment on mount -t amd.
+	(Controlling Amd): Likewise.
+
+	* tasks: Removed this task.
+
+Fri Jan 12 23:18:26 2001  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* conf/autofs/autofs_*.c: Bump copyright year to 2001.
+	* hlfsd/hlfsd.h (HLFSD_VERSION): Likewise.
+
+	* aux/macros/check_autofs_style.m4: Renamed solaris[12] styles to
+	solaris_v1, solaris_v2_v3 to reflect that these are AutoFS
+	protocol version numbers, not solaris versions.
+	* conf/autofs/autofs_solaris[12].[ch]: Renamed to
+	autofs_solaris_{v1, 2_v3}.[ch] to reflect this.
+	* Makefile.am (EXTRA_DIST_CONF): Likewise.
+
+	* aux/macros/check_autofs_style.m4: Use solaris2 style for both
+	versions 2 and 3 of the AutoFS protocol.
+
+	Handle missing AUTOFS_POSTUNMOUNT, AUTOFS_POSTMOUNT (unnecessary
+	with Solaris 8 mntfs).
+
+	* conf/autofs/autofs_solaris2.c (xdr_postumntreq, xdr_postumntres,
+	xdr_postmountreq, xdr_postmountres, autofs_postunmount_2_req,
+	autofs_postmount_2_req ): Don't define for version 3.
+	(autofs_program_2): Don't handle AUTOFS_POSTUNMOUNT,
+	AUTOFS_POSTMOUNT if missing.
+
+	* conf/nfs_prot/nfs_prot_sunos5_8.h: Enable AutoFS support.
+
+	* aux/macros/check_autofs_style.m4: Use empty autofs_default.[ch]
+	files on systems without existing autofs port.
+	* conf/autofs/autofs_default.[ch]: New files, empty.
+	* Makefile.am (EXTRA_DIST_CONF): Distribute them.
+	* INSTALL: With this change, Solaris 8 and Tru64 5.1 compile and
+	link.
+
+2001-01-12  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* Makefile.am (EXTRA_DIST): distribute new LDAP files.
+
+	* README.ldap, ldap-id.txt, ldap-id.ms: LDAP status information,
+	proposed Schema, and internet draft.
+
+Fri Jan 12 22:27:07 2001  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* Support Tru64 UNIX V5.1:
+
+	* conf/nfs_prot/nfs_prot_osf5_1.h: New file.
+
+	* Makefile.am (EXTRA_DIST_CONF): Distribute it.
+
+	* aux/macros/check_nfs_prot_headers.m4: Tru64 UNIX V5.1 has
+	AutoFS, need to disable it until a port exists.
+
+	* INSTALL, doc/am-utils.texi (Supported Platforms): Mention new
+	minor port.
+
+2001-01-09  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* ALL: bump copyright year to 2001.
+
+2001-01-05  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* acconfig.h: correct comments for NODEV/NONDEV mount options
+
+Fri Jan  5 05:12:02 2001  Erez Zadok  <ezk@subzero.cs.columbia.edu>
+
+	* libamu/xdr_func.c: removed ugly casts to "groups*", now that
+	irix6's nfs_prot.h is fixed.
+
+	* conf/nfs_prot/nfs_prot_irix6.h: copied relevant parts of
+	<rpcsvc/mount.h> here so we don't have to include this header.
+
+2001-01-04  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/nfs_prot/nfs_prot_irix6.h: redefine "groups" typedef to
+	struct groups, not the pointer to this struct.
+
+	* include/am_xdr_func.h: prototype should take "groups *" as 2nd
+	arg.
+
+	* libamu/xdr_func.c (xdr_groupnode, xdr_exportnode): change
+	casting of second arg of xdr_groups to "groups *".  It's only
+	needed for irix6, due to problems with xdr_groups on that platform.
+	(xdr_groups): prototype should take "groups *" as 2nd arg.
+
+	* conf/nfs_prot/nfs_prot_aix*.h: correct xdr_groups extern
+	definition.  Report from Ahmon Dancy <dancy@franz.com>.
+
+2000-12-06  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* include/am_defs.h: force non-inclusion of <linux/fs.h> via
+	<linux/auto_fs.h>
+
+	* conf/autofs/autofs_linux.c (autofs_mounted): rename
+	AUTOFS_MIN_PROTO_VERSION to AUTOFS_MIN_VERSION (leftover from
+	previous commit)
+
+	* configure.in: fixed libtool version
+
+2000-12-02  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* doc/am-utils.texi (opts Option): document lock/nolock
+
+2000-12-02  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* conf/autofs/autofs_linux.h: added struct autofs_pending_mount;
+	modified autofs_fh_t to have a linked list of autofs_pending_mount;
+	added some support for autofs4
+
+	* conf/autofs/autofs_linux.c: use a linked list for pending
+	request, to allow for handling multiple simultaneous request;
+	incipient non-functional support for autofs4; incipient
+	non-functional support for bind-mounting
+
+	* amd/amd.c (main): print a warning if PROCLOCK is requested but
+	the O/S doesn't support it
+
+	* libamu/mount_fs.c (mnt_flags): allow the use of the "nolock"
+	option
+
+	* include/am_defs.h: don't include <linux/fs.h> on a glibc2
+	system; include <linux/auto_fs4.h> if it exists, instead of
+	<linux/auto_fs.h>
+
+	* include/am_compat.h: define the "nolock" mnttab option if the
+	NONLM NFS mount option is defined
+
+	* acconfig.h: added MNT2_NFS_OPT_NONLM, MNT2_GEN_OPT_BIND
+
+	* configure.in: added detection of the NONLM Linux NFS mount
+	option; added a clarification for the library versioning rules and
+	increased the minor level; added detection of <linux/auto_fs4.h>
+	and the MS_BIND generic mount option
+
+2000-11-29  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* Enabled Solaris 2.7 autofs support (tested, works)
+
+	* Updated NEWS, README.autofs
+
+	* Updated Makefile's, make dist is now fixed
+
+	* Fixed potential memory leak in map.c
+
+	* Fixed autofs style detection for solaris 2.[67]
+
+	* Added a few casts in autofs_solaris2.c, needed on Solaris 2.7
+
+2000-11-28  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	More Solaris 2.[67] work in progress:
+
+	* changed the API for the mount/umount methods: fmount/fumount are
+	gone, and mount/umount now take two arguments (am_node and mntfs)
+
+	* changed the semantics of the MFF_AUTOFS flag: MFF_AUTOFS now
+	means the mntfs is a filesystem of type autofs, and AMF_AUTOFS
+	means the am_node is a node on a filesystem of type autofs.
+
+	* renamed nfs_program_2_transp to current_transp so it can be used
+	with autofs
+
+	* renamed quick_reply() to nfs_quick_reply()
+
+	* added two more autofs methods: autofs_umount_failed() and
+	autofs_compute_mount_flags() -- it turns out that on sol2.6 the
+	autofs mounts MUST be overlay'ed
+
+	* moved the autofs_mount_succeeded() into am_mounted()
+
+	* made amd *not* timeout autofs mounts -- the kernel will do it
+	for us
+
+	* store dev and rdev of a mounted filesystem in the mntfs
+	structure, to help autofs
+
+	* moved the rmdirs() call from uninit_mntfs() to am_umounted(), to
+	prevent deadlocking with autofs
+
+	* amd/Makefile.am: shuffled things around to make
+	update_build_version be the last thing that runs
+
+2000-11-27  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* split amd/ops_autofs.c into conf/autofs/autofs_<system>.c files
+	and made configure create a symlink to the appropriate one
+
+	* moved the xdr autofs functions from libamu/xdr_func.c into the
+	system-specific conf/autofs/autofs*.c
+
+	* added some more experimental code to the sol2.6 autofs support,
+	but it's by no means functional
+
+2000-11-27  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* libamu/wire.c (getwire_lookup): truncate the hostname to
+	MAXHOSTNAMELEN characters.
+
+2000-11-26  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* include/am_utils.h (MAXHOSTNAMELEN): if not defined, set this to
+	256 bytes, not 64.   Suggestion form Kris Kennaway
+	<kris@FreeBSD.org>.
+
+2000-11-26  Erez Zadok  <ezk@dmath5.geometrie.tuwien.ac.at>
+
+	* configure.in (AC_CHECK_MNT2_NFS_OPTS): check for NFS mount
+	options kerb, rdirplus, readdirsize, and xlatecookie
+	(NetBSD-1.5K).
+
+	* acconfig.h: recognize NFS mount options rdirplus, readdirsize,
+	and xlatecookie (NetBSD-1.5K)
+
+2000-11-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/srvr_nfs.c: comment on NFS proto search order.
+
+	* libamu/xutil.c (real_plog): don't try to write the last byte of
+	the fmt buf.  security suggtion from NetBSD: Thomas Klausner
+	<wiz@danbala.ifoer.tuwien.ac.at>
+
+2000-11-22  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): removed the initialization of
+	fattr.na_fileid, it is now done in map.c when the map is initialized
+
+	* amd/map.c (init_map): initialize fattr.na_fileid to am_gen, not
+	to 0, to avoid cache aliasing problems on Linux (and to follow the
+	NFS spec!)
+
+2000-11-22  Thomas Klausner <wiz@danbala.ifoer.tuwien.ac.at>
+
+	* libamu/mount_fs.c (mount_fs): avoid using extra limited-size buf
+	(security)
+
+	* libamu/xutil.c, fsinfo/fsinfo.h, include/am_utils.h: use
+	__attribute__, __format__, and __printf__ for GCC string auditing.
+
+	* wire-test/wire-test.8: this is not a section 8L man page.
+
+	* libamu/xutil.c (expand_error): don't use sys_nerr on systems
+	that support strerror().
+	(dplog): fmt is const
+	(plog): fmt is const
+	(real_plog): fmt is const.  use new expand_error function with its
+	new return value. be more careful about running off the end of
+	char[] fixed size buffers.
+
+	* libamu/wire.c (getwire): fix alignment error on alpha using an
+	extra automatic storage variable ifrpool.
+
+	* hlfsd/hlfsd.c (fatal): use proper printf style to plog.
+
+	* fsinfo/fsinfo.c (find_username): getlogin() returns a const.
+
+	* fsinfo/fsi_util.c (error, lerror, lwarning, fatal, log): use
+	vfprintf.
+
+	* fsinfo/fsi_lex.l (yyerror): use vfprintf.
+
+	* fixmount/fixmount.8: this is not a section 8L man page.
+
+	* doc/am-utils.texi (Hesiod maps): fixed typo.
+
+	* amd/sched.c (do_task_notify): typo in comment.
+
+	* amd/opts.c (expand_op): expand_error[] is a const char *.
+
+	* amd/amd.c (main): use proper printf style to plog.
+
+2000-11-22  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/mount_fs.c (mnt_flags, compute_nfs_args): recognize
+	proplist mnttab flag.  Bug fix from Wolfram Klaus
+	<klaus@physik.fu-berlin.de>.
+
+2000-11-19  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* updated config.guess, config.sub, and doc/texinfo.tex from
+	mirrors
+
+	* Makefile.am (update): proper updating of config.* and texinfo
+	from mirrors.
+
+	* aux/macros/check_nfs_prot_headers.m4: newer netbsd systems
+	reports their system name as "netbsdelf" in config.guess.
+
+2000-11-13  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (opts Option): document new mount option
+	"proplist"
+
+	* include/am_compat.h: define amd mount option "proplist" if the
+	system doesn't recognize it, but the NFS bit flag exists.
+
+	* configure.in, acconfig.h: recognize/support "proplist" NFS mount
+	option in Amd, useful under DU-4.0 to process ACLs over NFS
+	mounts.
+
+2000-11-10  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	* conf/mount/mount_linux.c (mount_linux): removed unnecessary
+	rsize/wsize defaults -- performance killers on 2.2.18+ and 2.4.0+
+
+2000-10-16  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/am-eject.in: accept "cdrom" and "floppy" as arguments.
+
+2000-11-05  Ion Badulescu  <ionut@moisil.dev.hydraweb.com>
+
+	Too many changes to list them here. Here's a high level
+	description:
+
+	* Forward-ported the Linux fixes from 6.0.5pre
+
+	* Got rid of a mountain of #ifdef DEBUG, replaced with smart
+	header-file #ifdef's
+
+	* and, the grand finale: initial Solaris 2.6 autofs
+	support. Compiles, mounts, gets requests; all the
+	infrastructure is in place to actually implement the calls. Linux
+	autofs might be a bit broken, but only compile-time so it'll be
+	easy to fix.
+
+2000-11-01  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* MIRRORS (Note): added a mirror at ufl.edu
+
+2000-10-11  Erez Zadok  <ezk@lorien.dev.hydraweb.com>
+
+	* amq/amq.8: synchronize Amq's options with reality
+
+	* amq/amq.c (main): synchronize Amq's usage() string with reality
+
+2000-10-10  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/ctl-amd.in: add targets condrestart (redhat) and
+	reload.
+
+2000-10-04  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/lostaltmail.in (vrfy_user): ensure that MAILDIR is
+	defined.
+
+2000-09-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/opts.c (backslash): Bell char (ASCII 007) should be \g, not
+	\a.
+
+2000-09-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* include/am_utils.h: removed unused field opt_autopref
+
+	* amd/opts.c: removed unused variable $autopref
+
+2000-09-05  Erez Zadok  <ezk@aladdin.dev.hydraweb.com>
+
+	* conf/mtab/mtab_svr4.c (lockfile): function not needed unless
+	MOUNT_TABLE_ON_FILE is defined.
+	mtlckname static var is onlyneeded if MOUNT_TABLE_ON_FILE.
+	(update_mnttab_fields): only needed if MOUNT_TABLE_ON_FILE.
+
+2000-09-03  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* buildall (Usage): typo in usage string
+
+2000-08-25  Erez Zadok  <ezk@lynn.soscorp.com>
+
+	* conf/mount/mount_linux.c (mount_linux): MNT2_NFS_OPT_VER3 may
+	is no defined on older Linux systems (kernel 2.0.36)
+
+2000-08-19  Erez Zadok  <ezk@earth.cs.columbia.edu>
+
+	* scripts/amd.conf.5: correct swapped descriptions for ldap_base
+	and ldap_hostports.
+
+	* doc/am-utils.texi: correct swapped descriptions for ldap_base
+	and ldap_hostports.
+
+	* scripts/amd.conf-sample: swap examples for ldap_base and
+	ldap_hostports.
+
+2000-08-13  Erez Zadok  <ezk@earth.cs.columbia.edu>
+
+	* scripts/amd.conf-sample: -O is CLI equivalent to "os"
+	amd.conf parameter
+
+2000-07-30  Erez Zadok  <ezk@earth.cs.columbia.edu>
+
+	* scripts/amd.conf-sample (nfs_retransmit_counter): correct
+	meaning and use of parameter
+
+2000-07-23  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi: updated URLs to www.am-utils.org.
+
+2000-07-04  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (Supported Platforms): document osf4.0f
+
+2000-06-19  Erez Zadok  <ezk@vir.cs.columbia.edu>
+
+	* doc/am-utils.texi (dollar Selector Variable): document
+	${dollar}.
+
+	* amd/opts.c: special new variable ${dollar} which expands into a
+	literal '$' sign.  Otherwise there is no way to include a literal
+	dollar symbol in an amd map.
+
+2000-06-11  Ion Badulescu  <ib42@moisil.cs.columbia.edu>
+
+	* amd/opts.c (eval_selectors): don't deref opt after it's been
+	XFREE'd
+
+2000-06-11  Erez Zadok  <ezk@earth.cs.columbia.edu>
+
+	* amd/opts.c: move mount_type expansion until later in the list,
+	so common variable are "hit" first.
+
+2000-06-11  Ion Badulescu  <ib42@moisil.cs.columbia.edu>
+
+	* amd/opts.c (split_opts, eval_selectors): split old function
+	eval_opts into two, one that only splits non-selectors and
+	assigns the values to fs_static, and one that only evaluates
+	selectors; also simplified the rather obfuscated logic inside
+	these functions
+	(expand_op): made it take a char * instead of a structure from
+	which it was using only one field (a char *). Also now returns a
+	char * instead of modifying said structure in place
+	(expand_opts): deal with the change above
+	(expand_selectors): renamed from expand_key
+	(expand_options): new function, expands non-selectors; it's the
+	complement of expand_selectors, both of which are just wrappers
+	around expand_op()
+	(eval_fs_opts): use the new split_opts, eval_selectors to allow
+	using options (like ${rhost}) in selectors
+
+2000-06-11  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* config.guess.long: munge config.guess' output so that intel
+	linux appears as i386-pc-linux
+
+Fri Jun  9 16:06:56 2000  Erez Zadok  <ezk@defiant.dev.hydraweb.com>
+
+	* conf/nfs_prot/nfs_prot_bsdi2.h: getifaddrs() on bsdi2 is broken.
+	Don't use it.
+
+2000-06-09  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* amd/mapc.c (maptypes): Change default allocation mode to
+	MAPC_INC where reload support is missing to avoid warning in
+	mapc_create().
+
+2000-06-09  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/nfs_prot/nfs_prot_sunos5_5.h: turn off autofs support for
+	solaris 2.5 until a full port can be done.
+
+2000-06-07  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* Makefile.am, aux/GNUmakefile: fix maintainer rules to update
+	config.* and texinfo.tex files.
+
+	* amd/nfs_subr.c (nfsproc_getattr_2_svc): Don't conditionalize the
+	mtime update of the symlinks on the SYMTTL option, but rather
+	delay unmount of what was looked up using am_timeo_w.  Patch from
+	Nick Williams <Nick.Williams@msdw.com>.  As Nick says "Basically:
+	during unmount, increment the parent dir's mtime (fixes
+	people doing amq -u). During stat, increase the TTL (to fix bad-luck
+	timeouts), but leave the mtime alone."
+
+	(nfsproc_lookup_2_svc, nfsproc_readlink_2_svc, unlink_or_rmdir,
+	nfsproc_readdir_2_svc): correctly update d_drops stats for amq -s.
+	Patch from Nick Williams <Nick.Williams@msdw.com>.
+
+	* amd/map.c (unmount_mp): update mtime of amd symlink to further
+	reduce the chances of race conditions between unmounting and
+	looking up an entry again.  Patch from Nick Williams
+	<Nick.Williams@msdw.com>.
+
+	* README: updated instructions
+
+	* bootstrap: remove log file before existing
+
+2000-06-06  Erez Zadok  <ezk@aladdin.dev.hydraweb.com>
+
+	* configure.in: no longer using aux/ subdir. don't force autoconf
+	2.14. comment out (but leave explanation) everything that's needed
+	for autoconf 2.14, so for now it works with autoconf-2.13, but the
+	code is ready for 2.14 when it is released.  Similar changes to
+	make code work with automake-1.4, until the next release comes
+	out.
+
+	* libamu/Makefile.am: include definitions that are required in
+	automake 1.4, but won't be necessary when the next release of
+	automake comes out (see XXX comments).
+
+	* cache_check_dynamic.m4, check_checkmount_style.m4,
+	check_mnttab_style.m4, check_mount_style.m4,
+	check_network_transport_type.m4, check_nfs_prot_headers.m4,
+	check_umount_style.m4: use symlink creation code that works for
+	both autoconf 2.13 and 2.14 (when the latter comes out).
+
+	* bootstrap: new script for maintainers to run to update autoconf,
+	automake, and libtool related files.  Has the same effect as
+	"buildall -K".
+
+	* removed dependencies on CVS versions of autoconf, automake, and
+	libtool, especially the modified automake I had.  This is so that
+	maintainers could built the auto* files out of the latest released
+	GNU autoconf, automake, and libtool.  However, without my nice
+	patches to automake, many files that used to live in the aux/
+	subdir now were moved to the top level source directory: acconfig.h,
+	acinclude.m4, aclocal.m4, aux_conf.h.in, config.guess,
+	config.guess.long, config.h.in, config.sub, configure.in, depcomp,
+	install-sh, ltconfig, ltmain.sh, missing, and mkinstalldirs.  Also
+	texinfo.tex and mdate-sh moved from aux/ dir to doc/ dir.
+
+2000-06-05  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* cvs-server.txt: instructions for maintainers to access the CVS
+	server for am-utils.
+
+2000-06-03  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* amd/restart.c (restart): grr.. passing around initialized
+	structures is *really* bad habit. memset(mo, 0) so at least we can
+	test for NULL pointers...
+
+2000-06-02  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/am_ops.c (ops_match): changed XLOG_USER messages about
+	merging addopts options to the more appropriate XLOG_INFO.  Patch
+	submitted by Tom Schmidt <tschmidt@micron.com>.
+
+	* config.{guess,sub}: make sure chmod'ed a+rx.  Updated from
+	latest GNU copies.
+
+2000-05-30  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* aux/configure.in: bump up the version to 6.1a2
+
+2000-05-29  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* released snapshot am-utils-6.1a1
+
+2000-05-29  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* amd/ops_autofs.c (autofs_mounted): retrieve the autofs protocol
+	version and store it in the fh
+	(autofs_get_opts): support protocol version 4
+
+	* amd/mntfs.c (uninit_mntfs): clear the autofs fh pointer after
+	releasing it
+
+	* conf/transp/transp_sockets.c (amu_svc_getcaller): cast result of
+	svc_getcaller() to sockaddr_in, to appease glibc 2.2
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): if the filesystem wants
+	autofs handling and the parent is already handled by autofs,
+	handle this filesystem as well
+	(amfs_auto_mount): create the mountpoint for an autofs mount
+	(amfs_auto_umount): do a real UMOUNT_FS() call for autofs mounts
+
+	* include/am_utils.h (FS_AUTOFS): new flag signalling that the
+	filesystem wants autofs handling; toplvl, auto, host and direct
+	have this flag, at least for now
+
+2000-05-28  Erez Zadok  <ezk@mulberry.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (Network Filesystem Group): minor typos
+
+2000-05-28  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* amd/autil.c (am_unmounted): check mp->am_parent before dereferencing
+
+	* amd/srvr_nfs.c (find_nfs_srvr): if NFS_SCALEDOWN, force
+	version=2 and proto=udp and try again
+
+	* amd/ops_nfs.c (prime_nfs_fhandle_cache): take an explicit mntfs
+	instead of a voidp; handle the NFS_SCALEDOWN case by removing the
+	cached server entry and re-querying the server
+
+	* amd/amfs_toplvl.c (amfs_toplvl_mount): removed ugly if
+	statement, assign mnttype from the fs-specific mf_ops->fs_type
+	instead
+
+	* amd/amfs_nfsx.c (amfs_nfsx_init): call fs_init() only if it's
+	defined;
+	(amfs_nfsx_remount): removed superfluous check for fmount_fs -- it
+	always exists
+	(amfs_nfsx_umount): removed the hacked am_node -- umounted() now
+	takes an mntfs; call umounted() only if it's defined
+
+	* amd/amfs_auto.c: removed amfs_auto_umounted and moved its
+	functionality into am_umounted().
+	(amfs_auto_cont): Linux hack: if we got an EINVAL, mark the mntfs
+	as needing an "NFS scaledown" and retry the operation
+
+	* amd/amfs_*.c: changed all fmount/fumount functions to
+	mount/umount and made them take an am_node instead of an
+	mntfs. This is a first step towards an amfs/ops API separation.
+
+	* amd/{amfs,ops}_*.c: changed the umounted() function to take an
+	mntfs instead of an am_node
+
+2000-05-28  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* amd/amfs_toplvl.c (mount_amfs_toplvl): init error to 0 to shut
+	up gcc
+
+	* aux/macros/check_hide_mount_type.m4: revert to the 6.0 version
+	which always defines HIDE_MOUNT_TYPE
+
+	* amd/ops_autofs.c (autofs_mounted): remove MFF_AUTOFS
+	initialization -- now done in init_mntfs()
+
+	* amd/mntfs.c (init_mntfs): init mf_flags to MFF_AUTOFS if we are
+	mounting an autofs-style map
+
+	* amd/*.c: use the MFF_AUTOFS flag instead of doing a costly STREQ
+
+	* amd/amfs_toplvl.c (mount_amfs_toplvl): MTYPE_TYPE is not
+	necessarily a string type, so handle the nfs/autofs separation
+	differently
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): removed initialization of
+	opt_mount_type (now done in ops_match())
+
+	* amd/am_ops.c (ops_match): need to initialize opt_mount_type if
+	it's not initialized yet
+
+2000-05-27  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/wire.c (getwire_lookup): handle calling irs_gen_acc with
+	one or two arguments (bsdi3 vs. bsdi4)
+
+2000-05-27  Ion Badulescu  <ib42@chestnut.mcl.cs.columbia.edu>
+
+	* libamu/xutil.c (amu_release_controlling_tty): removed an unused
+	variable from the previous patch
+
+2000-05-26  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* aux/macros/check_autofs_style.m4: fixed substitution for default
+	case
+
+	* libamu/xutil.c (amu_release_controlling_tty): close standard
+	file descriptors, re-open them as /dev/null
+
+	* include/am_defs.h: don't try to include both <ndbm.h> and
+	<db1/ndbm.h>, it really doesn't work
+
+2000-05-16  Ion Badulescu  <ib42@earth.cs.columbia.edu>
+
+	* hlfsd/stubs.c (nfsproc_lookup_2_svc): added code to update mtime
+	on lookup if MNT2_NFS_OPT_SYMTTL is not defined (copied from
+	getattr).  This fixes the problem introduced by the Linux nfsv3
+	patches.
+
+2000-05-12  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* Makefile.am (EXTRA_DIST_CONF): added conf/autofs/autofs_linux.h
+
+2000-05-10  Ion Badulescu  <ib42@earth.cs.columbia.edu>
+
+	* amd/ops_autofs.c (autofs_handle_fdset): call
+	autofs_lookup_failed instead of autofs_mount_failed, if the name
+	is not in the map
+	(autofs_umount_{succeeded,failed}): pass the actual mount point,
+	not its parent, as it's needed for clean-up;
+
+	* amd/autil.c (am_unmounted): notify autofs that the umount
+	succeeded
+
+	* amd/amfs_link.c (amfs_link_[u]mount): autofs link notification
+	moved elsewhere
+
+2000-05-09  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): initialize opt_mount_type
+	if necessary;
+	(amfs_auto_mounted): test if opt_mount_type is NULL first
+	(amfs_auto_mount): revert earlier change
+
+	* amd/ops_autofs.c (autofs_mount_failed): remove autofs directory
+	if mount failed
+
+2000-05-09  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* amd/ops_autofs.c (autofs_link_mount): use am_link as target
+
+	* amd/map.c (unmount_mp): release file handle for autofs f/s about
+	to be unmounted; this leak was preventing the unmount altogether
+
+	* amd/amfs_auto.c (amfs_auto_umount): removed autofs-specific
+	code, was broken
+	(amfs_auto_bgmount): nfs mounts + sublinks is a valid combination,
+	handle it
+
+2000-05-07  Ion Badulescu  <ib42@moisil.cs.columbia.edu>
+
+	* Merged changes from stable branch
+
+2000-04-30  Erez Zadok  <ezk@beetle.mcl.cs.columbia.edu>
+
+	* include/am_defs.h, aux/macros/mount_headers.m4,
+	aux/macros/try_compile_anyfs.m4: include linux/kdev_t.h and
+	linux/list.h before including linux/fs.h, and define __KERNEL__
+	for those two headers.  All of this to get a couple of definitions
+	that are needed in the new struct vfsmount.
+
+	* aux/configure.in: look for <linux/kdev_t.h> and <linux/list.h>.
+
+	* include/am_defs.h, aux/macros/mount_headers.m4: avoid conflicts
+	between linux/in.h. and netinet/in.h (linux-2.3.99-pre6), by
+	defining _LINUX_IN_H so it doesn't get included.
+
+2000-04-03  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor new ports: i686-pc-linux-gnu-rh6.2,
+	i386-unknown-freebsdelf3.4, i586-pc-linux-gnu-rh6.2.
+
+2000-04-03  Erez Zadok  <ezk@vir.cs.columbia.edu>
+
+	* aux/acconfig.h: move all #undef macros above @TOP@, so they can
+	be recognized by pickier autoconf.
+
+2000-04-03  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/cache_check_dynamic.m4 (ac_tmp): use correct echo -n
+	or \c.
+
+2000-03-25  Erez Zadok  <ezk@beetle.mcl.cs.columbia.edu>
+
+	* include/am_defs.h: ditto
+
+	* aux/macros/{mount_headers,try_compile_anyfs}.m4: force
+	non-inclusion of <linux/string.h>.  Breaks build on newer 2.3
+	kernels.
+
+2000-02-26  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (Amq -w option): document new amq -w option.
+
+	* amq/amq.8: document new amq -w option.
+
+	* amq/amq.c: disable last remains of insecure amq -M code.
+	(main): add amq -H option to show usage.
+	(main): new amq -w option, translates getpwd() into an amd path.
+
+2000-02-25  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* libamu/util.c (get_server_pid): new function
+
+	* hlfsd/hlfsd.c (main): make use of HIDE_MOUNT_TYPE
+
+	* conf/transp/transp_sockets.c: removed create_autofs_service
+
+	* conf/mount/mount_linux.c: added autofs mount options; split
+	mount_linux into two functions, itself and do_mount_linux
+
+	* aux/macros/check_hide_mount_type.m4: better failover
+
+	* aux/configure.in: changed version to 6.1a1; added
+	AC_CHECK_AUTOFS_STYLE
+
+	* aux/aux_conf.h.in: added @am_utils_autofs_style@
+
+	* amd/opts.c: added "mount_type" option
+
+	* amd/ops_autofs.c: ifdef-ed out solaris code; moved all autofs
+	variables in here; split create_autofs_service into sun and linux
+	specific functions
+
+	* amd/nfs_start.c: removed autofs-specific variables
+
+	* amd/map.c (get_root_nfs_fh): renamed root_fh to get_root_nfs_fh
+	(get_root_ap): renamed root_ap to get_root_ap
+
+	* amd/amfs_toplvl.c (amfs_toplvl_ops): replaced
+	amfs_toplvl_mounted with amfs_auto_mounted
+	(mount_amfs_toplvl): moved code around, added autofs handling
+	(amfs_toplvl_mounted): removed
+
+	* amd/amfs_nfsl.c (amfs_nfsl_ops): removed amfs_auto_fu?mount,
+	replaced with amfs_nfsl_u?mount
+
+	* amd/amfs_linkx.c (amfs_linkx_ops): removed amfs_auto_fumount,
+	replaced with amfs_link_umount
+
+	* amd/amfs_link.c (amfs_link_ops): removed amfs_auto_fu?mount,
+	replaced with amfs_link_u?mount
+
+	* amd/amfs_direct.c (amfs_direct_ops): changed "mounted" function
+	from amfs_toplvl_mounted to amfs_auto_mounted
+
+	* all: added autofs hooks throughout the code
+
+	* amd/am_ops.c (vops): autofs_ops doesn't belong in here, removed
+
+	* README.autofs: linux status update
+
+2000-02-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor new port: alphaev6-dec-osf5.0
+
+	* doc/am-utils.texi (Supported Platforms): hpux-11 supports NFSv3,
+	but only for UDP.
+
+	* released snapshot am-utils-6.0.4s3
+
+	* conf/nfs_prot/nfs_prot_hpux11.h: support NFSv3 in hpux-11.  Note
+	that hpux-11 NFSv3 supports UDP only, and trying TCP locks up the
+	kernel!  Must set nfs_proto=udp in amd.conf [global].
+
+	* aux/config.guess.long: set and export PATH separately.  DU5
+	/bin/sh doesn't like setting it on the command line in a
+	back-tick'ed `script`.
+
+2000-02-24  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* Makefile.am: removed struct_nfs_mount_data.m4
+
+	* aux/macros/struct_nfs_mount_data.m4: deleted
+
+	* aux/acconfig.h: removed definition for HAVE_NFS_MOUNT_DATA
+
+	* aux/configure.in: removed check for struct nfs_mount_data
+
+2000-02-24  Ion Badulescu  <ib42@beetle.mcl.cs.columbia.edu>
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): changed log message to
+	avoid having 'failed' in a message not indicating a failure
+	(amfs_auto_lookuppn): ditto
+
+	* amd/ops_autofs.c (autofs_bgmount): ditto
+	(autofs_lookuppn): ditto
+
+2000-02-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* added .cvsignore files into the CVS repository.
+
+	* remove files which can be regenerated: .in, configure, some
+	files in aux/, and more.
+
+2000-02-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (nfs_vers/nfs_proto): description of two
+	parameters was reversed.  Reported by Paul Jenner
+	<p.jenner@eim.surrey.ac.uk>.
+
+2000-02-16  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.4s2
+
+	* amd/mntfs.c (realloc_mntfs): don't fallback on certain ops such
+	as inherit, error, and toplvl (failover code).
+
+	* amd/conf.c (gopt_nfs_vers, gopt_nfs_proto): two new (documented)
+	global options in amd.conf: one to set the NFS version globally
+	(i.e., nfs_vers=2), and one to set the NFS protocol globally
+	(i.e., nfs_proto=udp).
+
+	* amd/mntfs.c (realloc_mntfs): attempt to fix the failover code,
+	so when a matching mount entry failed, try the next one.
+
+2000-02-15  Erez Zadok  <ezk@moisil.cs.columbia.edu>
+
+	* amd/amfs_auto.c: a new debug option "readdir" to trace the
+	progress of the browsable_dirs code.
+
+	* conf/mount/mount_linux.c (mount_linux): ensure that the new
+	linux NFSv3 code works for v2-only machines.
+
+2000-02-14  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/configure.in: cleanup unused dnl entries.
+
+	* conf/mount/mount_linux.c (parse_opts): typo: check for string
+	equality, not string inequality for pcfs and cdfs.
+
+	* aux/acconfig.h: look for MNT2_NFS_OPT_INTR as well.
+
+	* libamu/mount_fs.c (compute_mount_flags): check for INTR and
+	NOINTR options as well (intr was never passed to linux mount
+	syscall).
+
+2000-02-10  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.4s1
+
+	* aux/GNUmakefile: buildall -k (for maintainers) temporarily now
+	ignores autoconf warnings: "The macro `AC_OUTPUT_COMMANDS' is
+	obsolete".  It is harmless but annoying, and will be fixed when
+	autoconf and automake in their respective CVS trees are working
+	and in sync again.
+
+	* scripts/amd.conf.5: document -D hrtime,xdrtrace
+
+	* all man pages: update copyright to 2000.
+
+	* doc/am-utils.texi: update copyright to 2000.
+
+Wed Feb  9 14:22:31 2000  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* include/am_utils.h (D_XDRTRACE): Define.
+	(D_TEST): Disable here.
+
+	* libamu/xutil.c (dbg_opt): Handle it.
+
+	* doc/am-utils.texi (-D-Option): Document it.
+
+	* libamu/xdr_func.c: Use it instead of D_TRACE.
+
+	* include/am_utils.h (D_HRTIME): Define.
+
+	* doc/am-utils.texi (-D-Option): Document it.
+
+	* libamu/xutil.c (show_time_host_and_name): Print high-resolution
+	timestamp if available and activated.
+
+	* aux/configure.in (clock_gettime): Check for it in -lrt and
+	-lposix4.
+
+	* hlfsd/hlfsd.c (mnttab_file_name): Initialize to MNTTAB_FILE_NAME
+	if defined, even for some systems with in kernel mount tables.
+
+2000-02-08  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* aux/macros/mount_headers.m4: remove #if 0 around linux/nfs.h to
+	allow compiles against libc5
+
+	* aux/macros/check_mnttab_type.m4: avoid detecting nfs3 under
+	linux when the kernel doesn't support it
+
+	* include/am_compat.h: add workaround for linux efs
+
+2000-02-08  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/configure.in: test for ANSI C compiler (before AC_C_CONST).
+	Comment out unused AC_STRUCT_ST_RDEV (which is obsolete anyway).
+
+2000-02-07  Ion Badulescu  <ionut@moisil.cs.columbia.edu>
+
+	* libamu/mount_fs.c (compute_nfs_args): turn on VER3 option for
+	nfs (linux NFSv3).
+
+	* include/am_defs.h: avoid reinclusion of some header files under
+	linux.
+
+	* conf/nfs_prot/nfs_prot_linux.h: support NFSv3.
+
+	* conf/mount/mount_linux.c (mount_linux): support nfs mount
+	 (implementation) version 4 for NFSv3.
+
+	* aux/macros/try_compile_nfs.m4: use AC_MOUNT_HEADERS.
+
+	* aux/macros/mount_headers.m4: don't include <linux/fs.h> (may
+	need to fix the code on other linux machines).
+
+	* aux/macros/check_mnttab_type.m4 (ac_safe): ditto.
+
+	* aux/macros/check_fs_mntent.m4 (ac_safe): check for nfs3 option
+	under linux (depends on ac_cv variable, is that a good idea?)
+
+	* added NFSv3 support for linux
+
+	* aux/{configure.in,acconfig.h}: new option ver3
+
+	* aux/macros/mount_headers.m4: commented out inclusion of
+	linux/fs.h, it's not needed on rh61 (and actually generates
+	conflicts), we should see if it's still needed on libc5 systems
+
+	* aux/macros/try_compile_nfs.m4: use AC_MOUNT_HEADERS rather than
+	try to have its own (out of date) list of headers and ifdef's and
+	...
+
+2000-02-07  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	*******************************************************************
+	*** Released am-utils-6.0.3					***
+	*******************************************************************
+
+2000-02-06  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/mount/mount_default.c: dummy empty file to work around a
+	limitation of automake (it looks for LIBBOBJS in aclocal.m4 and
+	processes them even if they are optional, enclosed in if/else).
+
+2000-01-29  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.3s5
+
+2000-01-25  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* update to use latest version of autoconf, automake, and libtool.
+
+	* aux/GNUmakefile (depcomp): "make update" should also update the
+	depcomp script.
+
+	* Makefile.am (EXTRA_DIST_AUX): include depcomp in distribution.
+
+	* aux/configure.in: use renamed AC_CHECK_AMU_FS.
+
+	* aux/macros/check_amu_fs.m4: renamed macro name and file name to
+	say AMU_FS, not AM_FS.
+
+	* aux/acconfig.h: renamed HAVE_AM_FS_* to HAVE_AMU_FS_* because
+	latest version of autoconf doesn't handle it (bug in 2.14a)
+
+	* aux/configure.in: require version 2.14 of autoconf.
+
+	* amd/mapc.c (mapc_reload_map): more fixes from Nick Williams.
+
+	* doc/am-utils.texi (Automount Filesystem): document type:=auto
+	map browsability option.
+
+	* amd/mapc.c (make_entry_chain): patch from Steven Danz
+	<sdanz@awc.kc.noaa.gov> to allow browsable auto maps.
+
+2000-01-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.3s4
+
+	* amd/mapc.c (mapc_reload_map): fixes to sync maps even if they
+	are set to mapcache:=sync.  Fix from Nick Williams
+	<Nick.Williams@msdw.com>.
+
+2000-01-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.3s3
+
+	* minor port to i386-unknown-netbsd1.4.1
+
+	* amd/nfs_subr.c (nfsproc_getattr_2_svc): patch from Nick Williams
+	<Nick.Williams@msdw.com> to fix (or reduce the incidence of) stale
+	file handles when doing rapid mounts and umounts in succession
+	such as "ls /vol/foo ; amq -u /vol/foo ; ls /vol/foo"
+
+2000-01-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor port to i386-pc-bsdi4.1.
+
+2000-01-13  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/wire.c (getwire_lookup): pass NULL as conf_file (2nd)
+	argument to irs_gen_acc(), which was changed in bsdi 4.1.
+
+2000-01-12  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/get_args.c (get_args): don't use MNTTAB_FILE_NAME for
+	systems with in-kernel mount tables unless this macro is defined
+	(Solaris 8).
+
+2000-01-01  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* ALL: bump copyright year to 2000.
+
+1999-12-16  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/mount/mount_svr4.c (mount_svr4): optionstr exists on
+	solaris 7, but should not be used unless MAX_MNTOPT_STR also
+	exists (solaris 8).
+
+	* doc/am-utils.texi (opts Option): document new mount option:
+	optionstr.
+
+Fri Dec 10 01:31:53 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* conf/trap/trap_svr4.h (MOUNT_TRAP): Pass mount option string to
+	mount_svr4().
+	(mount_svr4): Adapt prototype.
+	* conf/mount/mount_svr4.c (mount_svr4): Pass them to kernel so
+	they are evaluated and show up in Solaris 8 in-kernel mnttab.
+
+	* aux/configure.in: Check for new Solaris 8 MS_OPTIONSTR mount(2)
+	option.
+	* aux/acconfig.h (MNT2_GEN_OPT_OPTIONSTR): Provide template.
+
+1999-12-10  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.3s2
+
+1999-12-09  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (opts Option): document noexec and nomnttab
+	(new to Solaris 8).
+
+	* Makefile.am (EXTRA_DIST_CONF): include nfs_prot_sunos5_8.h in
+	distribution.
+
+	* applied fixes from Rainer Orth for Solaris 8.
+
+	* libamu/wire.c (getwire): increment the cp pointer in the loop
+	body, because the ioctl() inside the "for" loop will overwrite the
+	ifr structure, thus not detecting all of the interfaces.  Bug
+	reported and fixed by Amitha Perera <perera@cs.rpi.edu>.
+
+Thu Dec  9 19:09:38 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* conf/mtab/mtab_svr4.c (unlockmnttab, lockmnttab): No-ops if
+	MOUNT_TABLE_ON_FILE.
+
+	* amd/get_args.c (get_args): Initialize mnttab_file_name even for
+	in-kernel mount table.  conf/mtab/mtab_svr4.c (read_mtab) depends
+	on a non-NULL value.
+
+	* amd/info_ldap.c (get_ldap_timestamp): Don't peek into opaque
+	LDAP structure to get error code, but use it directly.
+	(amu_ldap_search): Likewise.
+
+	* conf/nfs_prot/nfs_prot_sunos5_7.h: Rip superfluous and wrong
+	ldap support.
+	* conf/nfs_prot/nfs_prot_sunos5_8.h: Likewise.
+
+	* conf/nfs_prot/nfs_prot_sunos5_8.h: New file, doesn't typedef
+	nfsstat, already in <nfs/nfs.h>.
+	* aux/macros/check_nfs_prot_headers.m4: Use it for all Solaris
+	versions beyond 7.
+	Allow for micro versions of SunOS 5.[67].
+
+	* aux/configure.in: Check for new Solaris 8 Beta Refresh
+	MS_NOMNTTAB mount(2) option.
+	* aux/macros/check_mnttab_location.m4: Use it to test for
+	mntfs-based in-kernel mnttab.
+
+	* aux/macros/os_cflags.m4: Treat Solaris 8 and higher like 2.6/7.
+
+	* aux/macros/check_fs_headers.m4: Revert test for duplicate
+	objects.
+	* aux/macros/check_fs_mntent.m4: Likewise
+
+	* aux/macros/HEADER: Fixed typo.
+
+	* include/am_defs.h: Likewise.
+
+1999-12-01  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/*.m4: prepare for hpux-12 (assume same as hpux-11)
+
+1999-11-16  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* BUGS: document glibc-2.1 nis file descriptor leak in yp_bind.
+
+	* amd/info_ldap.c (string2he): updated function which does not
+	corrupt strings when called more than once.  Patch from
+	JOHANN.PFEFFERL.JP@germany.agfa.com.
+
+1999-11-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* MIRRORS (Asia): two new mirrors in Japan.
+
+1999-11-10  Erez Zadok  <ezk@kosh.cs.columbia.edu>
+
+	* doc/am-utils.texi: document new variables for ${uid} and ${gid}.
+
+	* amd/nfs_subr.c (nfsproc_lookup_2_svc): find the uid/gid of the
+	last lookup from the RPC credentials.
+
+	* aux/configure.in: upped version-info to 4:0:2 because I've added
+	a new interface to libamu.
+
+	* libamu/misc_rpc.c (getcreds): moved function from hlfsd to here,
+	so it can be used by amd.
+
+	* amd/opts.c: new variables ${uid} and ${gid}.
+
+1999-10-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/ctl-amd.in: add "status" command that tells you if amd
+	is running on not (same output as RedHat scripts).
+	Added start_msg and stop_msg targets as they are used on HPUX.
+	reported by Jon Peatfield <J.S.Peatfield@damtp.cam.ac.uk>.
+
+1999-10-13  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.3s1
+
+1999-10-12  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/amd.c (main): On AIX you must lower the stack size using
+	ulimit() before calling plock.  Otherwise plock will reserve a lot
+	of memory space based on your maximum stack size limit.  Since it
+	is not easily possible to tell what should the limit be, I print a
+	warning before calling plock(). See the manual pages for
+	ulimit(1,3,4) on your AIX system.
+
+	* include/am_defs.h: define default extern for vsnprintf()
+
+	* aux/configure.in: check for extern definition for vsnprintf()
+
+1999-10-08  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): patch from Nick Williams
+	<njw@ms.com>.  SYMPTOMS: 'occasionally' sublinks do not point to
+	the correct location, but to the top level of the mountpoint and
+	an (error-hook) is seen being mounted in the log file. This causes
+	things to Go Wrong(TM).
+	CAUSE: When evaluating two locations which are requested
+	'practically simultaneously', and the two locations resolve to the
+	same NFS mountpoint (but different sublinks), the later request
+	will be "deferred" and retried after wakeup when the first mount
+	succeeds. To do this, it rewinds the options location string to
+	re-evaluate the location when the mount is retried. However, it
+	shouldn't rewind the options for two reasons: (a) the semantics of
+	the map language say you shouldn't and (b) the NFS mount reference
+	is not reset at the same time, meaning that on the retry it will
+	have an options structure out-of-sync with the mount
+	structure. The "shortcut" code when retrying the mount sees the
+	mount structure is already filled in and does not fully evaluate
+	the options structure.... so if the first location is not the one
+	which ties in with the mountpoint (see ordering in the
+	recreate-by), you're now well messed up.
+
+	* BUGS: mention aix4.3 plock() bug (memory usage blows up and
+	plock fails)
+
+1999-10-07  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/GNUmakefile: certain files should be copied if they are
+	newer, not also if they are bigger: install-sh, ltconfig,
+	ltmain.sh, mdate-sh, missing, mkinstalldirs, and texinfo.tex.
+
+	* minor new port: i586-pc-linux-gnu-rh6.1 (RedHat Linux 6.1)
+
+1999-10-05  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_nfs_prot_headers.m4: prepare for OSF-5.
+
+	* aux/macros/check_nfs_fh_dref.m4: prepare for Tru64, aka OSF-5.
+
+1999-09-30  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	*******************************************************************
+	*** Released am-utils-6.0.2					***
+	*******************************************************************
+
+1999-09-27  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/mount/mount_linux.c (mount_linux): print the updated mount
+	flags.
+
+	* doc/am-utils.texi: document $full_os and $vendor.
+
+	* scripts/amd.conf-sample: examples of $full_os and $vendor.
+
+	* scripts/amd.conf.5: document $full_os and $vendor.
+
+	* amd/conf.c: add support for $full_os and $vendor.
+
+1999-09-26  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (netgrp Selector Function): don't give
+	examples with old single '=' assignment variable.  Use foo:=bar.
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): corectly indent long
+	comment describing this complex function.
+
+	* doc/Makefile.am (alldocs): do install-ps last (because distiller
+	is slow) and install-html next to last (because texi2html is also
+	slow).
+
+	* amd/amd.8: Major fixes to the description of the option -t
+	timeout.retransmit.
+
+	* doc/am-utils.texi: better description of "trace" debug option.
+	amd -H (not -v) shows log_options and debug_options.  Major fixes
+	to the description of amd -t timeout.retransmit, and the amd.conf
+	parameters nfs_retransmit_counter and nfs_retry_interval.
+
+	* scripts/amd.conf.5: better description of "trace" debug option.
+	amd -H (not -v) shows log_options and debug_options.  Major fixes
+	to the description of the parameters nfs_retransmit_counter and
+	nfs_retry_interval.
+
+1999-09-25  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (Automount Filesystem): cache:= is not a mount
+	option, but a mount map option.
+
+	* libamu/xutil.c (switch_to_logfile): log the name of the log file
+	we switched into, after the log file had been [re]opened.
+
+1999-09-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/mapc.c (mapc_reload_map): count and show the number of times
+	a map was reloaded.  Only reload a map if its modify-time was
+	updated.  But amq -f forced a reload no matter what.
+
+	* amd/amd.h: new flag to struct mnt_map to count number of times a
+	map was reloaded.
+
+	* amd/mapc.c (mapc_reload_map): attempt to reload the map without
+	losing current data by reloading into a temp copy, and switching
+	the hashes round only if the reload was successful.  Patch from Jon
+	Peatfield <J.S.Peatfield@damtp.cam.ac.uk>.
+	(mapc_sync): mapc_reload_map() always succeeds.
+
+1999-09-22  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/info_ldap.c (amu_ldap_rebind): don't busy-loop trying to
+	rebind to an LDAP server forever.  Try up to 10 times.
+
+	* fsinfo/fsi_lex.l (yyerror): rework code that will never happen
+
+	* released snapshot am-utils-6.0.2s2
+
+	* aux/configure.in: bumped library version-info to 3:2:1, since
+	some libamu code got changed.
+
+	* libamu/xutil.c (real_plog): use vsnprintf, not vsprintf, which
+	is better and more secure.  Fix from "David O'Brien"
+	<obrien@NUXI.com>.
+
+	* aux/configure.in: check for vsnprintf.
+
+1999-09-21  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/linux_headers.m4: use AC_MSG_ERROR.
+
+	* aux/macros/opt_{cppflags,ldflags,libs,amu_cflags}.m4: the ARG is
+	not optional.  Make sure ARG is supplied else flag an error.
+
+1999-09-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor port i386-unknown-freebsdelf3.3
+
+	* released snapshot am-utils-6.0.2s1
+
+1999-09-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/configure.in (AC_CHECK_FUNCS): check for getitimer().
+
+	* include/am_defs.h: extern definition for getitimer().
+
+	* aux/configure.in: use AC_CHECK_EXTERNS.  Look for getitimer()
+	extern.
+
+	* aux/macros/check_extern.m4: define a simple AC_CHECK_EXTERNS
+	that calls AC_CHECK_EXTERN in a loop.  This saves repeated code in
+	configure.
+
+	* aux/macros/type_auth_create_gidlist.m4: AIX 4.x systems use
+	'int' as the 5th arg to authunix_create().
+
+	* aux/macros/type_recvfrom_fromlen.m4: all AIX 4.x systems use a
+	size_t for the 6th arg of recvfrom().
+
+	* aux/macros/os_cflags.m4: define _XOPEN_EXTENDED_SOURCE for
+	aix4.x systems.
+
+	* libamu/mount_fs.c (print_nfs_args): cast some values to int, to
+	avoid gcc -Wall errors.
+
+	* scripts/expn.in: use sockaddr_in(), not pack() to correctly fill
+	in a struct sockaddr_in.  On Solaris x86 hosts, using pack()
+	results in byte-misaligned values.   Bug fix from Jeffrey C Honig
+	<jch@BSDI.COM>.
+
+	* libamu/mount_fs.c (compute_automounter_mount_flags): turn on
+	automntfs (ignore on bsdi-4.1) flag.
+	(compute_automounter_nfs_args): ditto.
+
+	* aux/acconfig.h: add new flag for automntfs (ignore)
+
+	* aux/configure.in: check for new automntfs flag (bsdi-4.1).
+
+1999-09-14  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* MIRRORS: added new site in Germany.  Updated status of umn.edu
+	and ferginc.com, who may no longer be mirroring am-utils.
+
+1999-09-08  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	*******************************************************************
+	*** Released am-utils-6.0.1					***
+	*******************************************************************
+
+1999-09-08  Erez Zadok  <ezk@cs.columbia.edu>
+
+	* aux/macros/mount_headers.m4: bsdi-2.1 needs MAXQUOTAS and struct
+	netexport defined.
+
+	* aux/macros/try_compile_anyfs.m4: bsdi-2.1 needs MAXQUOTAS and
+	struct netexport defined.
+
+1999-09-07  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_field.m4 (ac_upcase_var_name): include
+	<ifaddrs.h> so we can detect fields within struct ifaddrs.
+
+	* libamu/wire.c (getwire): bsdi-2.1 uses a second arg to
+	getifaddrs() and struct ifaddrs has no ifa_next field.
+
+	* aux/configure.in: check if 'struct ifaddrs' has a field
+	ifa_next.
+
+	* include/amq_defs.h (AMQ_STRLEN): double size of amq string
+	length to 2048 bytes.
+
+	* conf/nfs_prot/nfs_prot_netbsd1_4.h: include several more nfs
+	header files and ufs/ufs/ufsmount.h.  Bug reported by <Christos
+	Zoulas> christos@zoulas.com.
+
+	* aux/macros/try_compile_anyfs.m4: include <ufs/ufs/ufsmount.h>.
+	Bug reported by <Christos Zoulas> christos@zoulas.com.
+
+	* aux/macros/mount_headers.m4: include <ufs/ufs/ufsmount.h>
+
+1999-09-06  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/xutil.c (expand_error): use strerror if available instead
+	of sys_errlist.  Bug reported by <Christos Zoulas>
+	christos@zoulas.com.
+
+	* hlfsd/hlfsd.c (fatal): use strerror if available instead of
+	sys_errlist.
+
+	* amq/amq.c (show_mi): use strerror if available instead of
+	sys_errlist.
+
+	* aux/macros/check_nfs_prot_headers.m4: make sure netbsd1.4
+	nfs_prot header is used for any future (1.5 etc.) netbsd systems.
+
+	* amq/pawd.c (find_mt): check for type nfsl as well.  Fix from
+	"Andrew J. Korty" <ajk@purdue.edu>
+
+1999-08-29  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (Supported Platforms): updates for redhat
+	systems.
+
+	* INSTALL: updates for redhat systems.
+
+	* libamu/wire.c (getwire_lookup): spell "succeeded" correctly
+
+1999-08-28  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/ctl-amd.in: sleep 1 second between killing amd and
+	restarting it, because amq may respond that amd is down, where in
+	fact it is still trying to unmount itself after unmapping itself
+	from the portmapper.
+
+	* aux/config.guess.long: new script to print long version of
+	config.guess output.
+
+	* buildall (host_alias): use long version of config.guess.
+
+1999-08-27  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/ctl-{amd,hlfsd}.in: update RH tags for start/stop
+	scripts.
+
+1999-08-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.1s11
+
+	* libamu/xutil.c (expand_error): make sure expanding the string
+	with textual version of errno doesn't overrun the 1024 bytes
+	buffer.
+	(real_plog): null terminate msg, just in case.
+
+	* amq/amq.c (main): don't getopt -M option and don't process it
+	unless ENABLE_AMQ_MOUNT is on.
+
+	* amd/amq_svc.c (amq_program_1): all code that relates to amq -M
+	is conditional on #ifdef ENABLE_AMQ_MOUNT.
+
+	* amd/amq_subr.c: remove amqproc_mount_1_svc() function invoked
+	when amq -M code is disabled.  Not taking any chances.
+
+1999-08-23  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.1s10
+
+Sun Aug 22 16:18:59 1999  Erez Zadok  <ezk@subzero.cs.columbia.edu>
+
+	* libamu/wire.c (getwire_lookup): if getnetbyaddr failed (e.g., on
+	128.59.16.0), try to shift the network out of zeros (e.g.,
+	128.59.16) and try again.  Irix 6.4 requires short network
+	numbers.
+
+1999-08-22  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/wire.c (getwire_lookup): correctly compute subnet using
+	netmask.
+
+	* libamu/mount_fs.c (compute_automounter_nfs_args): require that
+	Amd's own NFS mounts use reserved ports (if possible).  IP packet
+	security fix from Jeffrey C Honig <jch@BSDI.COM>.
+
+	* conf/transp/transp_tli.c (create_autofs_service): use correct
+	autofs_port.  IP packet security fix from Jeffrey C Honig
+	<jch@BSDI.COM>.
+
+	* conf/transp/transp_sockets.c (bindnfs_port): remove unnecessary
+	function.  IP packet security fix from Jeffrey C Honig
+	<jch@BSDI.COM>.
+	(create_nfs_service): use bind_resv_port() directly.  ensure that
+	privileged ports are used.  IP packet security fix from Jeffrey C
+	Honig <jch@BSDI.COM>.
+
+	* amd/nfs_prot_svc.c (nfs_program_2): verify that requests come
+	from reserved ports and from a local IP address.  IP packet
+	security fix from Jeffrey C Honig <jch@BSDI.COM>.
+
+	* amd/amq_subr.c (ok_security): use IPPORT_RESERVED, instead of
+	hard-coded 1024.  IP packet security fix from Jeffrey C Honig
+	<jch@BSDI.COM>.
+	(amqproc_mount_1_svc): provide information on the caller making an
+	amq -M request.  IP packet security fix from Jeffrey C Honig
+	<jch@BSDI.COM>.
+
+	* amd/map.c (free_map_if_success): If the program doing an unmount
+	of a program filesystem fails, amd tries to interpret the return
+	code as an errno.  Fix from Jeffrey C Honig <jch@BSDI.COM>.
+
+	* amd/info_nis.c (determine_nis_domain): don't always print
+	warning about NIS domain name not being set, even if NIS is not in
+	use.
+
+1999-08-21  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/info_ldap.c (get_ldap_timestamp): initialize variable err.
+	(amu_ldap_search): initialize variable err.
+
+1999-08-16  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/wire.c: written using getifaddrs() for BSD systems,
+	contributed by BSDI, Jeffrey C Honig <jch@BSDI.COM>).
+
+1999-08-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* include/am_utils.h (SALLOC): a simple macro to allocate N bytes.
+
+	* aux/configure.in: check for irs.h and ifaddrs.h.
+	Increase libamu.so --version-info to 3:1:1 since we've changed the
+	source code for the library.
+	Check for getifaddrs() function.
+
+1999-08-14  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/mount_fs.c (print_nfs_args): print fields namlen and
+	bsize if they exist.
+
+	* conf/mount/mount_linux.c (mount_linux): set nfs_args_t->namlen
+	and ->bsize fields correctly, if those fields exist.  This is a
+	bug in that amd neglected to set these fields, but told the
+	kernel it is mounting the nfs_args_t structure using mount version
+	3 (which requires both bsize and namlen fields).
+
+	* aux/configure.in: test for two new nfs_args_t fields (used on
+	newer linux with mount versions 2 and 3): bsize and namlen.
+
+	* doc/am-utils.texi (netgrpd Selector Function): document new
+	selector function.
+
+	* amd/opts.c (f_netgrpd): new amd map function netgrpd(ARG) to
+	test if the current host (fully-qualified name) is in the ARG host
+	netgroup.  The netgrp() function uses the short form of a host
+	name.  Patch from Christophe Kalt <Christophe-Kalt@deshaw.com>.
+
+	* doc/am-utils.texi (automount2amd): document new script.
+
+	* scripts/Makefile.am: create, install, and distribute
+	automount2amd perl script and its man page.
+
+	* scripts/automount2amd.8: new man page for automount2amd.
+
+	* scripts/automount2amd.in: new file, contributed a in 1993 by
+	Mike Walker <mike@tab00.larc.nasa.gov>.  Fixed to use addopts for
+	any automount map options specified.
+
+1999-08-09  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.1s9
+
+1999-08-09  Erez Zadok  <ezk@beetle.mcl.cs.columbia.edu>
+
+	* amd/amfs_auto.c (DOT_DOT_COOKIE): set the NFS cookie of '..' to
+	1.
+	(amfs_auto_readdir): use DOT_DOT_COOKIE instead of (u_int)~0.
+	(amfs_auto_readdir_browsable): use DOT_DOT_COOKIE instead of
+	(u_int)~0.
+
+	* amd/mapc.c (make_entry_chain): NFS cookies should be
+	monotonically increasing, because Linux 2.3 expects that, even
+	though it is not in the spec (RFC-1094) for NFS V2.
+
+1999-08-06  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_lib_funcs.m4: removed unused macro.
+
+	* aux/macros/linux_headers.m4: new macro to ensure that linux
+	kernel headers match running kernel version.
+
+	* aux/acconfig.h: define HOST_HEADER_VERSION so we can check if
+	amd is configured on linux hosts that run one kernel but have
+	headers for a different version.
+
+	* amd/info_nis.c (nis_isup, nis_search, nis_init): fixes for the
+	logic which uses nis_isup and has_yp_order.  Make sure it is used
+	correctly , esp. for NIS+ in NIS-compatibility mode.  Bug fix from
+	Peter Breitenlohner <peb@mppmu.mpg.de>.
+
+	* include/am_defs.h: fix conflicts on linux 2.2 systems with older
+	libc5.  Bug fix from Peter Breitenlohner <peb@mppmu.mpg.de>.
+
+	* scripts/lostaltmail.in: use sockaddr_in(), not pack() to
+	correctly fill in a struct sockaddr_in.  On Solaris x86 hosts,
+	using pack() results in byte-misaligned values.
+
+1999-08-02  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/mtab/mtab_aix.c (mnt_dup): add support for nfs3
+	mounting, as per Dale Talcott <aeh@quest.cc.purdue.edu>.  Also use
+	better macros for case statement.
+
+	* conf/nfs_prot/nfs_prot_sunos5_7.h: don't include ldap structures
+	unless ldap is actually available.
+
+	* use updated config.guess and config.sub.  Use newer automake
+	that fixes problems with distributing optional libamu files
+	(clnt_sperrno.c, hasmntopt.c, strcasecmp.c, strdup.c, strstr.c,
+	and ualarm.c)
+
+1999-07-19  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor port i386-unknown-openbsd2.5
+
+1999-07-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor ports to freebsdelf 3.[0-2] and 4.0 completed
+
+	* aux/macros/check_nfs_prot_headers.m4: support freebsdelf
+
+	* aux/macros/check_nfs_socket_connection.m4: support freebsdelf
+
+1999-06-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.1s8
+
+1999-06-23  Erez Zadok  <ezk@beetle.mcl.cs.columbia.edu>
+
+	* include/am_defs.h: avoid various header conflicts on
+	RedHat/Linux 6.0 and kernels 2.2.10 or newer.
+
+	* aux/configure.in: look for <db1/ndbm.h> (RedHat/Linux 6.0 and
+	kernel 2.2.10)
+
+	* amd/amfs_program.c (amfs_program_exec): make sure logfp is
+	initialized dynamically to stderr if needed.
+
+	* libamu/xutil.c (dplog): make sure logfp is initialized
+	dynamically to stderr if needed.
+	(plog): ditto.
+
+	* amd/amfs_program.c (amfs_program_exec): set logfp to stderr if
+	not initialized.
+
+	* libamu/xutil.c: don't initialize logfp statically to stderr,
+	because on RedHat/Linux 6.0 (kernel 2.2.10) stderr can no longer
+	be manipulated like a variable.
+
+	* include/am_defs.h: avoid more conflicts between <linux/fs.h> and
+	<sys/mount.h> on 2.2 linux kernels.
+	include <db1/ndbm.h> as needed (RedHat/Linux 6.0)
+
+1999-04-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* all Makefile.am: use AMU_NFS_PROT_HEADER (not *_HEADERS)
+
+	* aux/macros/check_nfs_prot_headers.m4 (AMU_NFS_PROT_HEADER):
+	renamed AC_SUBST name from *_HEADERS to *_HEADER so that automake
+	won't attempt to add it to the header files to distribute.
+
+1999-04-19  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/GNUmakefile: invoke aclocal with new --altdir flag.
+
+1999-04-16  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor new port: i386-unknown-netbsd1.4 (ALPHA)
+
+	* aux/macros/check_field.m4: no need to include <cdfs/cdfsmount.h>
+	and <isofs/cd9660/cd9660_mount.h> because they are also included
+	from MOUNT_HEADERS.  Causes multiple inclusion of unprotected
+	headers on netbsd-1.4_ALPHA.
+
+1999-04-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/extern_sys_errlist.m4 (pattern): netbsd-1.4_ALPHA's
+	sys_errlist extern doesn't end with [].
+
+	* aux/macros/check_nfs_prot_headers.m4: netbsd 1.4 support.
+
+1999-04-11  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* newer automake wants texinfo.tex to be in aux/ not doc/
+
+1999-03-30  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/conf_parse.y: alloca support.
+
+	* fsinfo/fsi_gram.y: alloca support.
+
+	* libamu/Makefile.am (libamu_la_LIBADD): compile alloca.o if
+	needed.
+
+	* aux/configure.in: test for alloca support.  Needed because bison
+	generates parsers that use alloca, and hpux9 does have alloca and
+	its /bin/cc doesn't support it builtin (the way gcc does).
+
+	* libamu/alloca.c: new file, needed on hpux9 with /bin/cc.  Taken
+	verbatim from bison-1.25.
+
+	* include/am_defs.h: fixed typo #errir -> #error
+
+	* released snapshot am-utils-6.0.1s7
+
+	* README.y2k: more information about am-utils' compatibility, from
+	Paul Balyoz <pbalyoz@sedona.ch.intel.com>.
+
+	* scripts/lostaltmail.in (Splice_in_resent_headers): ensure Y2K
+	compliant format.  Patch from Paul Balyoz
+	<pbalyoz@sedona.ch.intel.com>
+
+	* doc/am-utils.texi (Supported Platforms): hpux10.20 could have
+	nfs v.3 support (with some vendor patches), but it is turned off.
+
+	* aux/macros/os_cflags.m4: use ansi compiler options on hpux.
+
+	* conf/nfs_prot/nfs_prot_hpux.h: Turn off NFS V.3 support to avoid
+	confusing am-utils.  10.20 with some patches has incomplete
+	support.  Patch from Jon Peatfield
+	<J.S.Peatfield@damtp.cam.ac.uk>.
+
+1999-03-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor port i386-pc-bsdi4.0.1
+
+1999-03-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (Supported Platforms): add forgotten listing
+	for powerpc-linux.
+
+1999-03-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/amd.conf.5: fix typo.  From Jeffrey C Honig
+	<jch@BSDI.COM>.
+
+	* doc/am-utils.texi: document iso9660 options norrip, gens, and
+	extatt.
+	(opts Option): documented dumbtimr and noauto options.  From
+	Jeffrey C Honig <jch@BSDI.COM>.
+
+	* include/am_compat.h: define default strings for options norrip,
+	gens, and extatt.
+
+	* amd/ops_cdfs.c (mount_cdfs): support options norrip, gens, and
+	extatt.
+
+	* aux/macros/mount_headers.m4: also include
+	<isofs/cd9660/cd9660_mount.h> as needed.
+
+	* aux/configure.in: check for isofs mount options for bsdi4:
+	norrip, gens, and extatt.  Reported by Jeffrey C Honig
+	<jch@BSDI.COM>.
+
+	* aux/macros/check_mnt2_cdfs_opt.m4: check for ISOFSMNT_* flags
+	(bsdi4).
+
+1999-03-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/nfs_prot/nfs_prot_freebsd3.h: ditto.
+
+	* conf/nfs_prot/nfs_prot_bsdi3.h: include <ufs/ufs/ufsmount.h>,
+	for bsdi4, as per Jeffrey C Honig <jch@BSDI.COM>.
+
+1999-03-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* get latest copies of config.guess, config.sub, ltconfig, and
+	ltmain.sh from libtool-1.2f.
+
+	* all Makefile.am: don't use continuation lines (using \) for
+	short lists of files.
+
+	* libamu/Makefile.am (DISTCLEANFILES): make distclean should
+	remove mountutil.c, mtabutil.c, transputil.c, and umount_fs.c.
+	Reported by Jeffrey C Honig <jch@BSDI.COM>.
+
+	* fixmount/Makefile.am (DISTCLEANFILES): make distclean should
+	remove checkmount.c.  Reported by Jeffrey C Honig <jch@BSDI.COM>.
+
+	* Makefile.am (DISTCLEANFILES): make distclean should remove
+	amu_nfs_prot.h, config.cache.old, and dbgcf.h.  Reported by
+	Jeffrey C Honig <jch@BSDI.COM>.
+
+1999-03-13  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.1s6
+
+1999-03-12  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* INSTALL: document freebsdelf.
+
+	* doc/am-utils.texi (Supported Platforms): document freebsdelf.
+
+1999-03-08  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor new ports: i386-unknown-freebsdelf3.1 and
+	i386-unknown-freebsdelf4.0
+
+	* aux/macros/check_nfs_prot_headers.m4: freebsd4 support.
+
+	* aux/macros/check_nfs_socket_connection.m4: freebsd4 support.
+
+	* aux/macros/check_nfs_fh_dref.m4: freebsd4 support.
+
+	* amd/opts.c (eval_opts): changed log level of "executing
+	negated..." message from USER to INFO, as per Guntram Wolski
+	<gwolsk@sei.com>.
+
+1999-02-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* */Makefile.am (LDADD): force linking against an installed
+	libamu.{a,so}.
+
+	* doc/am-utils.texi (addopts Option): document remopts interaction
+	with addopts.
+
+	* amd/am_ops.c (ops_match): if addopts are specified, apply them
+	to the value of remopts as well as opts.
+
+	* amd/ops_nfs.c (mount_nfs_fh): tell users when remopts are used.
+
+1999-02-05  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.1s5
+
+	* conf/mount/mount_linux.c (mount_linux): set default nfs_args
+	options for ac{reg,dir}{min,man} as per the mount-2.8a package,
+	but only if noac option was not used.
+
+1999-02-05  Erez Zadok  <ezk@retro.cs.columbia.edu>
+
+	* conf/mount/mount_linux.c (mount_linux): print nfs_args again
+	since it was updated.
+	(mount_linux): use 4KB for NFS rsize/wsize on 2.1.0 linux kernels
+	and newer.  Bug was found by Neil Conway
+	<nconway.list@ukaea.org.uk>
+
+1999-02-04  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.1s4
+
+1999-02-03  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amq/amq.c (main): don't list -M as a valid amq option unless
+	configure'd with --enable-amq-mount.
+
+Wed Feb  3 18:11:18 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* amd/nfs_start.c (amd_use_autofs): Define.
+	(mount_automounter): Create autofs service listener only if
+	necessary to avoid unnecessary clashes with e.g. automountd.
+
+	* amd/amd.h (amd_use_autofs): Declare.
+
+	* amd/conf.c (gopt_mount_type): Set amd_use_autofs.
+	(ropt_mount_type): Likewise.
+
+1999-02-02  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_mnt2_nfs_opt.m4:: ditto
+
+	* aux/macros/check_mnt2_cdfs_opt.m4: ditto
+
+	* aux/macros/check_mnt2_gen_opt.m4: ditto
+
+	* aux/macros/check_mnttab_opt.m4: new macro in this file to loop
+	over AC_CHECK_MNTTAB_OPT.  Reduces size of configure script a lot.
+
+	* conf/nfs_prot/nfs_prot_netbsd1_3.h: include nfs/rpcv2.h,
+	nfs/nfs.h and nfs/nfsmount.h if they exist.  Patch from
+	christos@zoulas.com (Christos Zoulas).
+
+	* amd/info_hesiod.c: some forward declarations.  Patch from
+	christos@zoulas.com (Christos Zoulas).
+
+1999-01-28  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/mount_fs.c (compute_nfs_args): don't turn on/off noconn
+	option if it was already in that state.  Patch from David
+	Wolfskill <dhw@whistle.com>.
+
+1999-01-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/configure.in: automake nowadays supports LTLIBOBJS (but not
+	LTALLOCA yet).  Substitute value of LIBTOOL_DEPS for libtool
+	rebuild make rules.
+
+	* Makefile.am: new rules to remake libtool (maintainers only)
+
+	* amd/amfs_toplvl.c (mount_amfs_toplvl): print generic mount flags
+	if -D trace was used.
+
+1999-01-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* buildall: all if statements should have an else clause because
+	of Ultrix's /bin/sh.
+
+1999-01-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amq/amq.c: removed dummy variables.
+
+	* amq/pawd.c: removed dummy variable.s
+
+	* fixmount/fixmount.c (usage): removed dummy variables.
+
+	* fsinfo/fsinfo.c: removed dummy variables.
+
+	* hlfsd/hlfsd.c: removed dummy variables.
+
+	* wire-test/wire-test.c: removed dummy variables.
+
+	* mk-amd-map/mk-amd-map.c: removed dummy variables.
+
+	* doc/texinfo.tex: updates from GNU mirror.
+
+	* aux/GNUmakefile (../doc/texinfo.tex): new rule to update
+	doc/texinfo.tex from GNU mirror.
+
+	* released snapshot am-utils-6.0.1s3
+
+	* Makefile.am (install-snapshot): better snapshot and new
+	install-snapshot and test-snapshot rules (maintainer).
+
+	* amd/info_ldap.c (amu_ldap_init): don't run STREQ if one of the
+	args may be NULL.
+	Some dlog() entries were not enclosed in #ifdef DEBUG.  Fix from
+	Bill Paul <wpaul@ctr.columbia.edu>
+
+1999-01-13  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* check for experimental generic 'ignore' mount flag on freebsd3.
+
+	* Update library -version-info to 3:0:1 (will result in 2.1.0 .so
+	version, which is backwards compatible with older versions.)  Only
+	one new interface was added to libamu.
+
+	* amd/amfs_toplvl.c (mount_amfs_toplvl): add generic mount flags
+	that are specific to automounter mounts.
+
+	* aux/configure.in: update libamu.so age and revision since a new
+	interface was added to libamu/mount_fs.c
+	(compute_automounter_mount_flags).
+
+	* libamu/mount_fs.c (compute_automounter_mount_flags): new
+	function to compute generic mount flags that are specific to mount
+	points only.
+
+	* aux/{configure.in,acconfig.h}: add support for generic mount
+	entry ignore option.
+
+	* released snapshot am-utils-6.0.1s2
+
+	* amd/info_ldap.c (get_ldap_timestamp): dlog format fixes.
+
+	* libamu/mount_fs.c (print_nfs_args): solaris 2.7 changed format
+	of knc_semantics from u_long to u_int.
+
+	* aux/macros/check_mount_style.m4: freebsd3 no longer needs a
+	special mount helper.
+
+1999-01-12  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_nfs_prot_headers.m4 (AMU_NFS_PROT_HEADERS):
+	amu_nfs_conf.h should always be found in $top_builddir.
+
+Tue Jan 12 00:05:42 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* conf/nfs_prot/nfs_prot_sunos5_7.h (MNTTAB_TYPE_AUTOFS): Undefine
+	to avoid wrong reports from show_fstypes.
+
+	* conf/nfs_prot/nfs_prot_irix5.h (MNTTAB_TYPE_XFS): Likewise.
+
+	* conf/nfs_prot/nfs_prot_hpux11.h (MNTTAB_TYPE_NFS3): Likewise.
+
+Tue Jan 12 00:05:42 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* BUGS (mips-dec-ultrix4.3): Update Ultrix caveats.
+
+Tue Jan 12 00:05:42 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* hlfsd/homedir.c (delay): Cast child to long, adapt format.
+	(hlfsd_getpwent): Likewise for pw_uid.
+
+	* amd/info_nis.c (nis_init): Cast order to unsigned long, adapt
+	format.
+
+	* conf/transp/transp_tli.c (amu_clnt_create_best_vers): Cast
+	tv_sec to int to match format.
+	(get_nfs_version): Cast nfs_version, NFS_VERSION to int to match
+	formats.
+
+	* amd/amfs_program.c (amfs_program_exec): Cast ptr difference to
+	long, adapt format.
+
+	* include/am_defs.h: Handle __attribute__ if available.  From
+	GNU fileutils 4.0 lib/errors.h.
+
+Mon Jan 11 13:46:44 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* libamu/mount_fs.c (print_nfs_args): Cast sizeof() to int to
+	match format.
+
+	* hlfsd/stubs.c (nfsproc_getattr_2_svc): Cast uid, gid to long,
+	adapt format.
+	(nfsproc_lookup_2_svc): Likewise.
+	(nfsproc_readlink_2_svc): Likewise for userid, groupid.
+
+	* hlfsd/nfs_prot_svc.c (nfs_program_2): Cast args to int to match
+	format.
+
+	* hlfsd/homedir.c (homedir): Cast uid, child to long, adapt
+	format.
+
+	* amd/info_hesiod.c (hesiod_search): Cast m, pval, tp to unsigned
+	long, adapt format.
+
+	* amd/ops_nfs.c (find_nfs_fhandle_cache): Cast fh_wchan to
+	unsigned long, adapt format.
+	(got_nfs_fh): Likewise.
+	(prime_nfs_fhandle_cache): Cast fh_nfs_version to int to match
+	format.
+	(call_mountd): Likewise, mnt_version also.
+	(mount_nfs_fh): Likewise.
+
+	* amd/ops_autofs.c (autofs_program_1): Cast args to int to match
+	format.
+	(autofs_unmount_1_svc): Cast ur->devid, ur_rdevid, ur->next to
+	unsigned long, adapt formats.
+	(autofs_bgmount): Cast opt_fs to unsigned to, adapt format.
+	(autofs_bgmount): Use long format to match arg.
+	(autofs_lookuppn): Removed superfluous arg.
+
+	* amd/srvr_nfs.c (start_ping): Cast nfs_version to int to match
+	format.
+	(got_portmap): Likewise for port.
+	(recompute_portmap): Likewise for fs->fs_version, mnt_version.
+	(find_nfs_srvr): Likewise for nfs_version.
+
+	* amd/sched.c (sched_task): Cast wchan to unsigned long, adapt
+	format.
+
+	* amd/nfs_start.c (checkup): Cast ptr difference to long, next_mem
+	to unsigned long, adapt format.
+	Cast tvv.tv_sec to int to match format.
+
+	* amd/nfs_prot_svc.c (nfs_program_2): Cast args to int to match
+	format.
+
+	* amd/map.c (root_fh): Cast pid to long, adapt format.
+	(timeout_mp): Cast time_t to long, adapt format.
+
+	* amd/clock.c (reschedule_timeouts): Use long format, cast time_t
+	arg.
+
+	* amd/amfs_host.c (fetch_fhandle): Cast nfs_version to int to
+	match format.
+	(amfs_host_fmount): Likewise.
+	(amfs_host_umounted): Likewise.  Removed superfluous arg.
+
+	* amd/amfs_auto.c (amfs_auto_bgmount): Cast pointer to unsigned
+	long, adapt format.
+	(amfs_auto_bgmount): Use long format, cast time_t arg.
+	(amfs_auto_lookuppn): Removed superfluous arg.
+
+	* amd/amd.c (main): Cast geteuid() result to long, adapt format.
+
+	* conf/transp/transp_sockets.c (get_nfs_version): Cast nfs_version
+	to int to match format.
+
+	* include/am_utils.h: Declare plog, dplog as printf-like.
+
+	* conf/mount/mount_irix6.c (mount_irix): Print type as char *.
+
+Mon Jan 11 13:46:44 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* amd/info_hesiod.c (hesiod_isup): New function.
+	* amd/mapc.c (maptypes): Add it.
+
+1999-01-10  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0.1s1
+
+1999-01-09  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* ALL: bump copyright year to 1999.
+
+Fri Jan  8 15:24:15 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* aux/macros/check_mtype_type.m4: Ultrix uses an int mount type,
+	too.
+
+	* aux/macros/check_mtype_printf_type.m4: Adapt corresponding
+	printf type.
+
+Fri Jan  8 15:24:15 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* aux/acconfig.h: Removed HAVE_AM_FS_AUTOFS, unused.
+
+	* conf/nfs_prot/nfs_prot_irix6.h: Likewise.
+
+	* conf/nfs_prot/nfs_prot_sunos5_6.h: Likewise.
+
+	* conf/nfs_prot/nfs_prot_sunos5_7.h: Likewise.
+
+	* Makefile.am (EXTRA_DIST_DIRS): Removed, not needed by current
+	automake.
+
+Thu Jan  7 02:55:18 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* aux/configure.in (AM_PROG_YACC): Replaced by AC_PROG_YACC, not
+	in current automake.
+
+Thu Jan  7 02:55:18 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* doc/am-utils.texi: Added some missing inter-punctation after
+	@xref, or use @pxref/@ref as appropriate.  Spotted by makeinfo
+	from texinfo 3.12b.
+
+1999-01-07  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/texinfo.tex: updated off of latest GNU mirror.
+
+1999-01-04  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (Supported Platforms): update platforms that
+	support NFS v.3.  Nicer postscript printing on double-sided pages.
+
+	* amd/info_hesiod.c: add extern definition for hesiod_init()
+
+1999-01-01  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	*******************************************************************
+	*** Released am-utils-6.0					***
+	*******************************************************************
+
+1998-12-28  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/nfs_prot/nfs_prot_sunos5_7.h: support ldap in solaris 2.7.
+
+1998-12-27  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/nfs_prot/nfs_prot_bsdi3.h: don't use reserved ports on
+	bsdi4 for NFS V3/nfs mounts.
+
+1998-12-26  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* using latest libtool (1.2e + patches), now supporting shared
+	libraries on many more systems.  Also using latest autoconf and
+	automake (unreleased GNU CVS'd versions.)
+
+	* minor new ports: hppa2.0w-hp-hpux11.00,
+	i386-unknown-netbsd1.3.3, mips-sgi-irix6.5.
+
+	* fsinfo/fsinfo.h (yywrap): define it for systems (osf4) that
+	have /usr/bin/flex but not libfl.
+
+1998-12-24  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* lots of code cleanup, to make sure libamu.so does not use
+	undefined symbols.  Some system's shared libraries cannot handle
+	that.
+
+1998-12-23  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* include/am_defs.h: only defined seteuid extern if function also
+	exists and is not superceded by setresuid (hpux).
+
+	* amd/ops_autofs.c (autofs_bgmount, autofs_lookuppn): put explicit
+	braces to avoid confusion with nested if-then-else clauses.
+
+	* aux/config.{sub,status}, aux/{ltmain.sh,ltconfig,mkinstalldirs:
+	updated from latest versions.
+
+1998-12-22  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor new port: i386-pc-bsdi4.0
+
+	* conf/nfs_prot/nfs_prot_bsdi3.h: add missing hesiod header
+	definitions for bsdi4.
+
+	* {amd,fsinfo}/Makefile.am: force path to .y/.l files, because
+	some make programs (bsdi4) do not support VPATH correctly.
+
+1998-12-16  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/mount/mount_aix.c: minor code cleanup
+
+	* aux/configure.in: check for extern definition to xdr_groups.
+
+1998-12-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor new port: powerpc-ibm-aix4.3.1.0
+
+	* aux/macros/*.m4: updates for aix 4.3
+
+1998-12-14  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* minor new port: i386-unknown-openbsd2.4
+
+	* aux/configure.in: don't check for xfs on openbsd because
+	openbsd-2.4 introduces a new file system named xfs, but different
+	than Irix's XFS.  Sigh.
+
+	* minor new port: i386-unknown-freebsd2.2.8
+
+1998-12-03  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/amfs_nfsl.c (amfs_nfsl_ffserver): use case insensitive host
+	name match.  Bug fix from Douglas K. Rand" <rand@aero.und.edu>.
+
+1998-11-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/ctl-amd.in: wait4amd2die runs in the stop action, to
+	avoid race conditions when shutting down systems running amd.
+
+	* Makefile.am: add a dist-hook to change modes of the directories
+	in the tar file so they are not world writable.
+
+	* conf/nfs_prot/nfs_prot_freebsd3.h: turned on NFSv3 support,
+	since it is now finally defined in the header files and
+	(hopefully) stable.
+
+	* amd/srvr_nfs.c (find_nfs_srvr): allow overriding if nfsv2 option
+	is specified in mount options.  freebsd patches from David
+	O'Brien.
+
+	* amq/amq.c (main), fixmount/fixmount.c (main), hlfsd/hlfsd.c
+	(main), fsinfo/fsinfo.c (fsi_get_args), hlfsd/hlfsd.c (main),
+	amd/get_args.c (get_args): posix: use -1 to check for return from
+	getopt() (not EOF), as per posix.
+
+	* amd/amq_subr.c (xdr_amq_mount_tree_node): patches from "David
+	O'Brien" <obrien@NUXI.com>, from the FreeBSD source tree.  Use
+	real variable whose pointer is on the stack for decoding a long
+	int.
+
+1998-11-11  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/ctl-{amd,hlfsd}.in: include comments useful for redhat's
+	chkconfig utility.
+
+1998-11-10  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0b2s3
+
+	* conf/transp/transp_sockets.c (create_nfs_service): remove C++
+	style comments.
+
+1998-11-04  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0b2s2
+
+	* created CVS package
+
+	* amd/nfs_subr.c (nfsproc_lookup_2_svc): try to avoid a race
+	condition between unmounting and re-mounting an entry, by
+	increasing the ttl of a looked up entry before unmounting it.
+	Patch from Mike Mitchell <mcm@unx.sas.com>.
+
+	* All files: spell comments and strings.
+
+1998-11-03  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/configure.in: look for yp_all in libnsl only if yp_all not
+	already found elsewhere (in libc or other default libraries).
+	This is so RedHat 5.1 systems could find yp functions in libnsl,
+	but also so AIX 4.2.1 will NOT include libnsl, because the latter
+	has broken nis functionality that also exists and works ok in libc.
+
+1998-10-29  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/amd.c (main): bug fix: swapped arguments to kill(2).  Fix
+	from Danny Rathjens <dkr@cs.fiu.edu>.
+
+1998-10-28  Erez Zadok  <ezk@spruce.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0b2s1
+
+1998-10-27  Erez Zadok  <ezk@spruce.mcl.cs.columbia.edu>
+
+	* aux/macros/*.m4: support bsdi4 as bsdi3.
+
+	* aux/macros/os_ldflags.m4: enable detection of LDAP on solaris
+	2.7 (libraries located in /usr/lib/fn).  This is off until Sun
+	includes LDAP header information.
+
+1998-10-20  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	*******************************************************************
+	*** Released am-utils-6.0b1					***
+	*******************************************************************
+
+1998-10-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* mk-amd-map/mk-amd-map.c (main): use perror not strerror.
+	(main): set return type to int if no ndbm maps.
+
+	* include/am_defs.h: avoid conflicts with <sys/mount.h> in 2.1
+	kernels.
+
+1998-10-18  Erez Zadok  <ezk@london.mcl.cs.columbia.edu>
+
+	* A.i386-unknown-netbsd1.3.2/amu_nfs_prot.h: trim down and cleanup
+	for netbsd 1.3.2.
+
+1998-10-17  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/configure.in: check for yp_all in libnsl, b/c redhat 5.1
+	systems put NIS functions there.
+
+	* mk-amd-map/mk-amd-map.c: patch from "David O'Brien"
+	<obrien@NUXI.com> merged in.  Use POSIX -1 return code from
+	getopt(), not EOF.  Use .db extentions for systems that use it,
+	instead of .{pag,dir}.
+
+1998-10-15  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* wire-test/wire-test.c, hlfsd/hlfsd.c, fixmount/fixmount.c,
+	amd/amd.c (main): avoid overrunning hostname buffer.  Bug fix from
+	"David O'Brien" <obrien@NUXI.com>.
+
+	* scripts/amd.conf.5: minor typo reported by "David O'Brien"
+	<obrien@NUXI.com> in .TH section of man page.
+
+	* amd/info_nis.c (am_yp_all): don't leak key-val entries.  Patch
+	from Thomas Richter <richter@chemie.fu-berlin.de>.
+
+1998-10-12  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (Program Filesystem): minor typo fixed as per
+	Andreas Stolcke <stolcke@speech.sri.com>.
+
+	* minor new ports: sparc64-unknown-linux-gnu, i386-pc-solaris2.7,
+	and sparc-sun-solaris2.7.
+
+	* conf/mount/mount_freebsd3.c (mount_freebsd3): freebsd 3.0 is now
+	a 4.4lite kernel, and somethings were removed, such as
+	INITMOUNTNAMES.
+
+	* amd/ops_autofs.c (autofs_lookuppn): don't leak memory while
+	processing /defaults.  Free temporary opts.  Patch from
+	dsr@mail.lns.cornell.edu (Daniel S. Riley)
+
+	* amd/amfs_auto.c (amfs_auto_lookuppn): don't leak memory while
+	processing /defaults.  Free temporary opts.  Patch from
+	dsr@mail.lns.cornell.edu (Daniel S. Riley)
+
+	* conf/mtab/mtab_osf.c (read_mtab): patch from
+	 dsr@mail.lns.cornell.edu (Daniel S. Riley) not to access
+	 uninitialized memory on Digital Unix.
+
+1998-10-09  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/{check_mtype_type,check_mtype_printf_type}.m4: most
+	systems now use "char *" as their mount type.
+
+1998-10-08  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/conf.c (gopt_map_type, ropt_map_type): check if map type
+	exists.
+
+	* amd/mapc.c (mapc_type_exists): function to test if a map of
+	certain type exists.
+
+1998-10-08  Erez Zadok  <ezk@horatio.mcl.cs.columbia.edu>
+
+	* aux/macros/{mount_headers,try_compile_anyfs,try_compile_nfs}.m4,
+	include/am_defs.h: Avoid a conflict in definitions of ntohl/htonl
+	in RH-5.1 sparc64 between <netinet/in.h> and
+	<linux/byteorder/generic.h> (2.1 kernels).
+
+1998-09-28  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/func_bad_yp_all.m4 (ac_cv_func_yp_all_clean): RedHat
+	5.1 systems with glibc glibc-2.0.7-19 or below leak a UDP socket
+	from yp_all().
+
+1998-09-25  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/mount/mount_linux.c (parse_opts): check for pcfs support
+	only if autoconfigured.
+
+1998-09-18  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* Makefile.am (EXTRA_DIST): distribute README.yk2 file.
+
+	* README.y2k: explain y2k compliance status of am-utils.
+
+1998-09-16  Erez Zadok  <ezk@iguana.mcl.cs.columbia.edu>
+
+	* amd/amfs_host.c (fetch_fhandle, amfs_host_fmount,
+	amfs_host_umounted): clnt_sperrno() may return a const.
+
+Sat Aug  8 23:28:32 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/configure.in: check for <nfs/nfsmount.h>, as per Christos
+	Zoulas. Turned on checking for mount options: async, synchronous,
+	deadthresh, leasterm, nqnfs, and readahead.
+
+	* amd/info_nis.c: patch from christos@zoulas.com (Christos Zoulas)
+	to include prototype definition for nis_isup().
+
+Sun Jul 19 18:50:10 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* hlfsd/stubs.c (getcreds): force sscanf arg to u_long.
+
+Tue Jul 14 20:34:25 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0a17s1
+
+Wed Jul  8 21:49:15 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/host_macros.m4: all x86 hosts should have $arch be
+	i386, not i[456]86.
+
+Tue Jul  7 18:55:09 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/{mount_headers,try_compile_anyfs,try_compile_nfs}.m4,
+	include/am_defs.h: include <linux/posix_types.h> before
+	<linux/fs.h> because on redhat 5.1, there is a bug (misuse) of
+	headers in <socketbits.h> (it defines _LINUX_TYPES_H instead of
+	__KERNEL_STRICT_NAMES).
+
+	* aux/configure.in: check for <linux/posix_types.h> because it is
+	need for RedHat 5.1.
+
+Wed Jun 17 00:05:33 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/Makefile.am (EXTRA_DIST): have fixrmtab generated from
+	.in as well, so it doesn't get removed by make clean.
+
+Tue Jun 16 22:00:15 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/{check_fs_mntent.m4, check_mnttab_type.m4,
+	check_mount_type.m4}: redhat 5.1 puts some modules in
+	/lib/modules/preferred/.
+
+Wed May 13 16:33:57 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/ops_autofs.c (mount_autofs): cast pid to long.
+
+Tue Apr 28 15:12:36 1998  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* conf/nfs_prot/nfs_prot/nfs_prot_irix6.h,
+	conf/nfs_prot/nfs_prot_sunos5_6.h: Undef MNTTAB_TYPE_AUTOFS too to
+	avoid amd/am_ops.c (show_fstypes) from erroneously claiming
+	support.
+
+Fri Apr 24 23:02:11 1998  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* libamu/xutil.c (get_syslog_facility): Don't use LOG_DAEMON
+	unconditionally, may be missing on Ultrix V4.3.
+
+Thu Apr 23 20:24:33 1998  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+	* conf/nfs_prot/nfs_prot_sunos5_4.h (MNTTYPE_CACHEFS): Define,
+	missing from <sys/mntent.h>.
+
+	* conf/mtab/mtab_ultrix.c: Need separate inclusion of <sys/fs_types.h>
+	without KERNEL defined here.
+
+	* aux/macros/mount_headers.m4: Need to include <ufs/ufs_mount.h>,
+	<cdfs/cdfs_mount.h>, <cdfs/cdfsmount.h> so autoconfiguration of
+	ufs_args_t, cdfs_args_t fields and cdfs mount options can succeed.
+
+	* amd/ops_ufs.c (mount_ufs): Removed obsolete comment.
+
+	* ChangeLog: Fixed confusing linebreaks from ChangeLog imports.
+	Removed purely local (and obsolete) entry.
+
+Thu Apr 23 00:22:17 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	*******************************************************************
+	*** Released am-utils-6.0a16					***
+	*******************************************************************
+
+Wed Apr 22 01:20:39 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_mount_style.m4: define freebsd3 mount style.
+
+	* aux/macros/check_mount_trap.m4: new mount trap for freebsd3.
+
+	* aux/macros/check_mtype_printf_type.m4,
+	aux/macros/check_mtype_type.m4 (ac_cv_mtype_type,): freebsd3 (as
+	of snapshot 3.0-980311-SNAP) uses char * types for mount(2), not
+	integers, but I'll keep them as integers and do the mapping in
+	conf/mount/mount_freebsd3.c
+
+	* minor new port to i386-pc-bsdi3.1.
+
+	* minor new port to i386-unknown-netbsd1.3.1.
+
+	* amd/opts.c: new option addopts:=ARG, which smartly merges ARG
+	options with whatever the /default ones for a key are.  This
+	allows adding or overriding /default options individual keys.
+
+	* amd/am_ops.c (ops_match): strdup/malloc string assigned to
+	opt_opts because it'll get free()'d upon next use.
+	(merge_opts): new function to merge two sets of options.
+	(ops_match): if addopts option exist, append and merge it to the
+	current default options.
+
+Tue Apr 21 12:54:59 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* wire-test/wire-test.c (main): use dynamically allocated returned
+	string with list of interfaces.
+
+	* amd/get_args.c (get_version_string): allocate enough space for
+	header version string and a list of network interfaces of any
+	length.
+
+	* libamu/wire.c (print_wires): return dynamically allocated string
+	containing list of networks.  Must be dynamic because some sites
+	had potentially dozens of network interfaces.  Patch from Matthew
+	Crosby <mcrosby@ms.com> slightly modified.
+
+Mon Apr 20 00:37:20 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/nfs_prot/nfs_prot_irix5.h: underfine MNTTYPE_XFS because
+	irix 5.3 does not have full header definitions for it.
+
+	* fsinfo/fsi_lex.l (yywrap): define yywrap if needed, and
+	undefined it when not needed (similar to amd/conf_tok.l)
+
+	* hlfsd/hlfsd.h (ROOTID, SLINKID, INVALID): reduced maximum size
+	of these to unsigned short (because uid_t on some linux systems is
+	small).
+
+	* released snapshot am-utils-6.0a16s10
+
+	* doc/am-utils.texi (opts Option): documented resvport mount
+	option.
+
+Sun Apr 19 18:17:03 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (-D-Option): document behavior of -D info and
+	especially what it does to hesiod (turn on RES_DEBUG).
+
+	* scripts/amd.conf.5: document info debugging option.
+
+	* libamu/xutil.c (dbg_opt): parse info debugging option.
+
+	* include/am_utils.h (D_INFO): define new trace option.
+
+	* Makefile.am (EXTRA_DIST): include list of official mirrors in
+	distribution.
+
+	* libamu/wire.c (SIZE): in the simple case, just compute
+	sizeof(struct ifreq).
+
+Sun Apr 19 16:30:35 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+
+	* amd/amd.c (daemon_mode): set a temporary secure umask(0022)
+	before writing log file and restore it afterwards.  Patch from
+	Donald Buczek <buczek@MPIMG-Berlin-Dahlem.MPG.DE>.
+
+	* amd/get_args.c (get_args):
+
+	* doc/am-utils.texi (-F Option), amd/amd.8: mention that amd.conf
+	file specified by -F is always processed last.
+
+	* amd/amd.c (daemon_mode): do not fclose(stdout) so that the fd
+	won't be reused.  Allows startup script to redirect stdout.  Patch
+	from Donald Buczek <buczek@MPIMG-Berlin-Dahlem.MPG.DE>.
+
+	* libamu/xutil.c (switch_to_logfile): compare logfile name and
+	syslog string with correct length.  Patch from Donald Buczek
+	<buczek@MPIMG-Berlin-Dahlem.MPG.DE>.
+
+	* amd/restart.c (restart): correctly inherit existing NFS V.3
+	mounts upon restart.  Patch from Donald Buczek
+	<buczek@MPIMG-Berlin-Dahlem.MPG.DE>.
+
+Sat Apr 18 19:01:19 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+
+	* using libtool 1.2 and automake 1.3 (with my patches).
+
+	* aux/macros/opt_am_cflags.m4, */Makefile.in: rename AM_CFLAGS to
+	AMU_CFLAGS to avoid conflicts with automake-1.3.
+
+Sun Apr  5 23:09:08 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* converted to using libtool-1.2.
+
+Tue Mar 10 16:52:09 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* fsinfo/fsi_analyze.c (fixup_required_mount_info): replaced silly
+	for loop (ITER) which used to run only to initialize the variable
+	dd once and then break; with a simple assignment.
+
+	* hlfsd/hlfsd.h: cleanup so it compiles with Solaris
+	/opt/SUNWspro/bin/cc, and use gid_t not int.
+
+	* amd/mapc.c (mapc_sync): don't dereference pointer (so it
+	compiles with Solaris /opt/SUNWspro/bin/cc)
+
+Sun Mar  8 15:54:22 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/config.{guess,sub}: used from gcc-2.8.1.
+
+Sat Mar  7 15:33:27 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0a16s9
+
+	* INSTALL, doc/am-utils.texi (Supported Platforms): updated names
+	based on new output of new config.guess.
+
+	* aux/config.{sub,guess}: used newer versions from gcc-2.8.0.
+
+	* amd/amd.8,doc/am-utils.texi: document correct usage of default
+	/etc/amd.conf file.
+
+	* fixmount/fixmount.c (inetresport,privsock): use some more
+	portable code from amq/amq.c.
+
+	* amd/get_args.c (get_args): use default /etc/amd.conf file only
+	if no arguments had been passed to amd.
+
+	* fixmount/fixmount.c (clnt_create_timeout): use tli/socket code
+	ala amq/amq.c so that fixmount will work on both types of systems.
+
+	* amq/amq.c (main): do no close tcp socket before running udp try,
+	because we're not sure if it was opened at all.
+
+	* mips-dec-ultrix* port merged in and cleaned up.
+
+	* aux/configure.in: up minor shared library revision number, since
+	it has changed enough.
+
+	* hlfsd/hlfsd.c (main): don't check for overlay mount option here,
+	as it is now done in compute_nfs_args().  Remove ultrix specific
+	code also because it was moved to compute_nfs_args().
+
+	* conf/mount/mount_svr4.c: removed DEBUG_MOUNT_SVR4 code, now that
+	we have more generic code in print_nfs_args().
+
+	* libamu/mount_fs.c (print_nfs_args): print maxlen of
+	nfs_args.addr, and also syncaddr (which is mostly NULL).  Print
+	struct knetconfig from nfs_args->knconf.
+
+	* aux/macros/mount_headers.m4 (define): do not check for ufs/cdfs
+	headers here, but in try_compile_anyfs.m4.
+
+	* aux/macros/type_ufs_args.m4: move test for struct ufs_specific
+	(for ultrix) here from its own macro.
+
+	* aux/macros/type_cdfs_args.m4: move test for struct iso_specific
+	(for ultrix) here from its own macro.
+
+	* amd/ops_nfs.c (mount_nfs_fh): no need to run code again checking
+	for overlay mount option.  Remove code which checks for overlay
+	option, as it is now done in compute_nfs_args().
+
+	* libamu/mount_fs.c (compute_mount_flags): move here code which
+	checks for overlay mount option which was in amd/amfs_toplvl.c:
+	mount_amfs_toplvl().
+
+Wed Feb  7 15:35:51 1998  Rainer Orth  <ro@xayide.TechFak.Uni-Bielefeld.DE>
+
+	* The following are Rainer's ChangeLog entries for his ultrix
+	port, added manually. -Erez.
+
+	* merged Ultrix port with am-utils 6.0 a16s5: amd/ops_afs.c
+	(mount_toplvl) -> amd/amfs_toplvl.c (mount_amfs_toplvl)
+
+	* include/am_defs.h: include cdfs specific mount headers
+	avoid duplication definition of gt_names[] in <sys/fs_types.h> (Ultrix)
+
+	* include/am_compat.h: define several mount options corresponding
+	to mount flags: pgthresh, hard (nfs), defperm, nodefperm,
+	noversion, rrip (cdfs), nocache, quota, sync (generic) removed
+	duplicate MNTTAB_OPT_RO definition
+
+	* aux/macros/try_compile_anyfs.m4: include Ultrix specific
+	ufs/cdfs mount headers
+
+	* aux/macros/mount_headers.m4: include several Ultrix/Digital UNIX
+	specific mount headers
+
+	* aux/macros/check_{fs_mntent, mount_type}.m4: check for GT_*
+	mount types in mount headers (Ultrix)
+
+	* aux/configure.in: Ultrix/Digital UNIX specific checks: new
+	headers, mount structures and fields, filesystem and mount types,
+	mount flags
+
+	* aux/acconfig.h: placeholders for new mount options: quota
+	(generic), ro (nfs), defperm, nodefperm, noversion, rrip (cdfs)
+	cdfs, nfs, ufs mount structure fields new ufs, cdfs mount
+	structures
+
+	* amd/ops_ufs.c (mount_ufs): Ultrix stores generic mount flags in
+	ufs_args.ufs_flags and has ufs specific pgthresh option
+
+	* amd/ops_cdfs.c (mount_cdfs): handle Ultrix/Digital UNIX specific
+	CDFS mount flags and options
+
+	* amd/ops_afs.c (mount_toplvl), amd/ops_nfs.c (mount_nfs_fh),
+	hlfsd/hlfsd.c (main): store generic mount flags in
+	nfs_args.gfs_flags, handle separate NFS ro flag
+
+	* aux/macros/{check_mnt2_cdfs_opt, struct_iso_specific,
+	struct_ufs_specific}.m4: new files; check for Ultrix specific
+	mount structures
+
+	* conf/trap/trap_ultrix.h: arg 3 to mount(2) is rwflag
+
+	* aux/macros/type_auth_create_gidlist.m4 (ultrix*):
+	AUTH_CREATE_GIDLIST_TYPE is int (not short == gid_t) from a
+	comment in <rpc/auth.h>
+
+	* include/am_defs.h: #define KERNEL to avoid definition of
+	gt_names[] conf/mtab/mtab_ultrix.c: #include <sys/fs_types> before
+	<config.h> to force single definition here
+
+	* libamu/mount_fs.c (compute_nfs_args): Ultrix support for
+	nfs_args.gfs_flags moved to callers store mount options in
+	nap->optstr
+
+	* include/am_defs.h: fix _am_mntent mnt_{type, opts} field
+	descriptions
+
+	* aux/macros/mount_headers.m4, aux/macros/try_compile_nfs.m4:
+	include <rpc/rpc.h> before AMU_NFS_PROTOCOL_HEADER for svc_req
+	definition in prototypes
+
+	* aux/macros/mount_headers.m4: include <sys/errno.h> before
+	AMU_NFS_PROTOCOL_HEADER: <nfs/nfs.h> needs it for NFSERR_*
+	definitions
+
+	* conf/nfs_prot/nfs_prot_ultrix.h: new file
+
+	* aux/macros/check_nfs_prot_headers.m4: use nfs_prot_ultrix.h
+
+	* aux/macros/mount_headers.m4, aux/macros/try_compile_nfs.m4,
+	aux/macros/try_compile_rpc.m4, include/am_defs.h: avoid multiple
+	inclusion of <rpc/xdr.h>
+
+Sat Mar  7 13:56:05 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/configure.in: save state of config.cache and confdefs.h
+	(as dbgcf.h) at various points of the configure.
+
+	* aux/macros/save_state.m4: new macro to save state of configure,
+	esp. useful in long ones.  Saves confdefs.h and write $ac_cv_*
+	cache variables that are known so far.
+
+	* released snapshot am-utils-6.0a16s8
+
+1998-03-06  Erez Zadok  <ezk@mercer.psl.cs.columbia.edu>
+
+	* fsinfo/fsi_lex.l,amd/conf_tok.l: define ECHO after undefining
+	it, but only for flex.
+
+Fri Mar  6 17:23:17 1998  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
+
+	* hlfsd/homedir.c (plt_print): change pathname of hlfsd dump file
+	to /usr/tmp/hlfsd.dump.XXXXXX, and use a safe method (if possible)
+	to write the dump file.
+
+	* doc/am-utils.texi,amd/opts.c: rename all references to nomadic
+	functions to boolean functions, which is what they really are.
+
+	* aux/configure.in: don't look for strcasecmp in libucb at all,
+	but rather complete it from libamu/strcasecmp.c as needed.
+
+Fri Mar  6 03:29:20 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/nfs_prot/nfs_prot_osf4.h: avoid conflicts with Irix's EFS.
+
+	* libamu/wire.c (getwire): fix for 0.0.0.0 loopback on SunOS 3.X
+	which defines IFF_ROUTE instead of IFF_LOOPBACK.  Patch from Tom
+	Schmidt <tschmidt@micron.com>.
+
+	* released snapshot am-utils-6.0a16s7
+
+	* conf/nfs_prot/nfs_prot_hpux11.h: a first working port of amd to
+	hppa1.0-hp-hpux11.00.tgz.
+
+Thu Mar  5 21:59:03 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* converted all sources to use mntent field names, and map mnttab
+	field names to mntent's.
+
+	* include/am_defs.h (mnt_special): map struct mnttab field names
+	to struct mntent field names.
+
+	* aux/macros/check_mount_trap.m4: hpux11's mount trap style is
+	identical to svr4/solaris2.
+
+	* aux/macros/check_mount_style.m4: hpux11's mount style is
+	identical to svr4/solaris2.
+
+	* aux/macros/check_network_transport_type.m4: hpux11 is a TLI
+	system!
+
+	* aux/macros/check_nfs_sa_dref.m4: hpux11's NFS host address
+	dereferencing style is same as svr4.
+
+	* aux/macros/check_nfs_fh_dref.m4: hpux11's NFS file fh
+	dereferencing style is same as svr4.
+
+	* conf/transp/transp_tli.c (create_nfs_service): if failed to
+	getnetconfigent() of ticlts, then try udp (hpux11).
+
+	* conf/nfs_prot/nfs_prot_hpux11.h: added correct definitions for
+	struct nfs_args, nfs_fh, and NFSMNT_* flags, taken from solaris
+	2.5.1 (HP used them).
+
+	* amd/rpc_fwd.c (fwd_init): don't use O_NDELAY for t_open()
+	because hpux11 doesn't like it. if t_open failed, print error
+	based on t_errlist, not sys_errlist.
+
+Wed Mar  4 22:01:55 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi: lots of documentation fixes from Rainer Orth
+	<ro@TechFak.Uni-Bielefeld.DE>.
+
+Sat Feb 28 22:16:35 1998  Erez Zadok  <ezk@kosh.cs.columbia.edu>
+
+	* fsinfo/fsi_lex.l: undefine ECHO again, so it doesn't get used
+	later.
+
+	* include/am_defs.h: defined the extern for ualarm() if it isn't
+	found, regardless if the function isn't found in standard
+	libraries, because otherwise libamu will include it.
+
+1998-02-28  Erez Zadok (per Ron Snyder)  <ezk@short.cvo.roguewave.com>
+
+	* initial port to hpux-11 completed.  Compiles cleanly, but
+	probably does not work, because of missing NFS V.2/3 headers.
+
+	* amd/conf_tok.l: cast yytext to char* when passed to strlen and
+	strdup, for hpux-11's ansi-cc compiler.
+
+	* include/am_utils.h: renamed all xfree() to XFREE() to avoid
+	conflict with hpux-11's system headers.  Also move (voidp) cast
+	from sources to inside the macro itself.
+
+Sat Feb 28 13:44:21 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0a16s6
+
+	* amd/info_nis.c (nis_isup): new function to test if NIS is up
+	without hanging amd.  Used to ensure that amd does not clear the
+	maps when the expiration period arrived, if the service is down.
+	Otherwise it would be left with empty maps.  It is better to stay
+	with possibly old information than none at all.
+
+	* amd/mapc.c (mapc_sync): check to see if map service is up.
+
+Tue Feb 24 02:19:42 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_lib2.m4 (AC_CHECK_LIB2): fix macro so it
+	includes auxiliary library only if needed.
+
+1998-02-22  Erez Zadok  <ezk@mercer.psl.cs.columbia.edu>
+
+	* amd/conf_tok.l: undefine ECHO again, so it doesn't get used
+	later.
+
+Sun Feb 22 01:41:08 1998  Erez Zadok  <ezk@zen.cs.columbia.edu>
+
+	* conf/nfs_prot/nfs_prot_osf2.h: port to alpha-dec-osf2.1
+	completed.
+
+	* conf/mtab/mtab_osf.c (mnt_dup): not all OSF have NFS3.
+
+Sat Feb 21 19:45:48 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (Network Host Filesystem): correct example for
+	type:=host map.
+
+	* aux/macros/os_cflags.m4: only osf4 should compile with
+	-D_SOCKADDR_LEN.
+
+	* aux/macros/check_nfs_prot_headers.m4: distinguish between OSF2
+	and OSF4.
+
+	* BUGS: include a new file listing known bugs.
+
+Sat Feb 21 03:50:48 1998  Erez Zadok  <ezk@mercer.psl.cs.columbia.edu>
+
+	* conf/nfs_prot/nfs_prot_linux.h: turn DES off on all linux
+	versions.
+
+	* aux/macros/type_recvfrom_fromlen.m4: linux alpha should use
+	size_t for recvfrom fromlen arg.
+
+Sat Feb 21 03:33:59 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* scripts/ctl-hlfsd.in: turn -D fork so primary process never
+	hangs.
+
+Sat Feb 21 02:45:51 1998  Erez Zadok  <ezk@mercer.psl.cs.columbia.edu>
+
+	* include/am_defs.h: don't include <sys/stat.h> and
+	<linux/stat.h>, just remaining definitions in <statbuf.h>
+
+Thu Jan 29 00:44:28 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0a16s5
+
+	* conf/mount/mount_irix6.c (mount_irix): pass {u,e,x}fs_args to
+	mount(2).
+
+	* check for <sys/fs/xfs_clnt.h> and include it when needed.
+
+	* conf/mount/{mount_irix5.c,mount_irix6.c} (mount_irix): recognize
+	efs and xfs separately from "ufs".
+
+	* amd/{ops_xfs.c,ops_efs.c}: new support for irix xfs/efs.
+
+	* aux/configure.in: look for irix efs and xfs file systems.
+
+	* scripts/amd.conf.5: new unmount_on_exit option documented.
+
+	* doc/am-utils.texi (unmount_on_exit): new option documented.
+
+	* amd/conf.c (gopt_unmount_on_exit): new function to handle new
+	amd.conf option.
+
+	* amd/map.c (umount_exported): if global amd.conf flag
+	unmount_on_exit is on, then try to unmount all mounted (or
+	restartable) file systems.
+
+	* amd/amd.c: if print_pid option is on, then normally print it to
+	stdout.  If also pid_file is specified, then print the process ID
+	into that file.
+
+	* amd/get_args.c (get_args): print correct -l option depending if
+	system supports syslog and/or syslog facilities.  Patch from
+	Tom Schmidt <tschmidt@micron.com>.
+
+	* doc/am-utils.texi (opts Option): updates for documentation for
+	new cdfs options defperm, nodefperm, noversion, rrip.
+
+	* amd/ops_cdfs.c (mount_cdfs): support cdfs options defperm,
+	nodefperm, noversion, rrip.
+
+	* conf/nfs_prot/nfs_prot_osf.h: need to look at <cdfs/cdfsmount.h>
+	on osf.
+
+	* aux/macros/{expand_cpp_hex.m4, expand_cpp_int.m4,
+	expand_cpp_string.m4}: use #error to make failed compilations
+	fail faster, rather than have the program fail during a run.
+
+	* include/am_compat.h: added a few new cdfs options: rrip,
+	noversion, defperm, and nodefperm (used in OSF).
+
+Wed Jan 28 20:24:09 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0a16s4
+
+	* doc/am-utils.texi (Global Parameters): update manual for new
+	amd.conf global variable hesiod_base.
+
+	* scripts/amd.conf.5: update man page for new amd.conf global
+	variable hesiod_base.
+
+	* amd/get_args.c (get_args): use /etc/amd.conf file if exists by
+	default, else try command line options.  Patch from Randall
+	S. Winchester <rsw@Glue.umd.edu>.
+
+Wed Jan 28 12:20:56 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/info_hesiod.c (hesiod_search), amd/conf.c
+	(gopt_hesiod_base), amd/amd.h, amd/amd.c (init_global_options):
+	included patch from Randall S. Winchester <rsw@Glue.umd.edu>, to
+	support a hesiod base name in the amd.conf file.
+
+	* doc/am-utils.texi (pid_file Parameter): document new global
+	amd.conf parameter.
+
+	* scripts/amd.conf.5: document new global option pid_file.
+
+	* amd/amd.c (daemon_mode): if cannot open pid_file, continue to
+	run, but print error message.
+
+	* amd/conf.c (gopt_pid_file), amd/amd.h, amd/amd.c (daemon_mode,
+	init_global_options): Included patch from Randall S. Winchester
+	<rsw@Glue.umd.edu>, to support pid files in the amd.conf file.
+
+	* amd/get_args.c (get_args): correct usage info on amd -t.
+
+	* amd/*.c: massive file name and symbol name changes.  All amd
+	file systems files and symbols are prefix with amfs_*.  Now using
+	real name of file system: amfs_auto instead of afs, amfs_inherit
+	instead of ifs, amfs_linkx instead of sfsx, etc.  This will enable
+	clear distinction between amd file system and generic ones like
+	nfs/ufs/pcfs/hsfs.  Also, now we can implement true afs (Andrew
+	f/s) and DFS (Distributed f/s).
+
+	* amd/amfs_union.c: unionfs for amd is always defined, no need to
+	#ifdef it.
+
+Mon Jan 26 16:51:38 1998  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
+
+	* libamu/mount_fs.c (compute_nfs_args): set 'noconn' NFS option on
+	or off, based on the particular quirks of the OS in question.
+
+	* aux/macros/check_nfs_socket_connection.m4: new macro to set the
+	correct wait of handling un/connected NFS sockets.
+
+	* scripts/wait4amd.in: use rlogin instead of rsh.
+
+	* amd/am_ops.c (ops_showfstypes): when showing F/S types in amd
+	-v, always show "nfs3" for NFS V.3.
+
+1998-01-25  Erez Zadok  <ezk@snoopy.cs.columbia.edu>
+
+	* lots of small fixes for solaris 2.6, since gcc 2.8.0 -Wall gets
+	more picky than 2.7.2.3 did.
+
+1998-01-24  Erez Zadok  <ezk@snoopy.cs.columbia.edu>
+
+	* include/am_utils.h (dlog): amuDebug macros reduced to shorter
+	forms.
+
+Fri Jan 23 18:38:30 1998  Erez Zadok  <ezk@goat.mcl.cs.columbia.edu>
+
+	* released snapshot am-utils-6.0a16s3
+
+	* include/am_defs.h: on Solaris 2.6, <sys/varargs.h> is included
+	in <sys/fs/autofs.h> but since stdargs.h is used, and varargs.h
+	must not, fake a definition for varargs.
+
+Fri Jan 16 10:16:40 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* README: show how to configure in additional support such as
+	hesiod using various --enable-* flags.
+
+Wed Jan 14 15:13:02 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/configure.in: look for strcasecmp(), and replace it if not
+	available.
+
+	* amd/ops_nfsl.c (nfsl_match): host names should be compared using
+	case insensitive.
+
+	* amd/opts.c: for each map variable, define if the comparison
+	needs to be done case insensitive.
+
+	* include/am_utils.h (STRCEQ): a new macro to use strcasecmp().
+	Patch from Thomas Richter <richter@chemie.fu-berlin.de>
+
+1998-01-14  Erez Zadok  <ezk@irt.cs.columbia.edu>
+
+	* aux/configure.in: look for "isofs" as a possible mount type for
+	cdfs (RedHat Linux).
+
+Wed Jan 14 02:07:05 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/mount/mount_linux.c (parse_opts): don't look for cdfs mount
+	type if not defined.
+
+	* conf/nfs_prot/nfs_prot_linux.h: don't define __FD_* macros if
+	already defined.
+
+	* aux/configure.in: look for ext2fs before ufs, b/c some linux
+	have both.
+
+Mon Jan 12 15:43:20 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* Makefile.am (snapshot): allow me to install snapshots into the
+	ftp directory.
+
+	* scripts/ctl-hlfsd.in: don't turn on -D mem by default.
+
+	* amd/get_args.c (get_args): minor bug in output of amd -H.
+
+Mon Jan 12 03:05:06 1998  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
+
+	*******************************************************************
+	*** Released am-utils-6.0a15					***
+	*******************************************************************
+
+Sun Jan 11 15:06:34 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/conf.c (*_browsable_dirs): allow specifying
+	browsable_dirs=full, which will print *all* entries (other than
+	/default), including  those with '*' and '/' characters.
+
+	* amd/info_file.c (MAX_LINE_LEN): up maximum readdir chain length
+	to 1500.
+
+	* doc/am-utils.texi: fixed reversed documentation for NFS mount
+	options vers and proto.
+
+	* doc/Makefile.am (install-html): separate target just for
+	installing html files.  Another new target "alldocs" is just for
+	installing all files needed for the am-utils home page.
+
+	* scripts/amd.conf-sample: updated example for log_file.
+
+	* scripts/amd.conf.5: updated for new way to declare new syslog
+	facility in the log_file option.
+
+	* amd/amd.8: updated for new way to declare new syslog facility in
+	the -l option.
+
+	* libamu/xutil.c (get_syslog_facility): allow users to specify the
+	syslog facility as an appended string to the log device.  Ex. amd
+	-l syslog:local7 will use LOG_LOCAL7, while the older -l syslog
+	will use the default LOG_DAEMON facility.
+
+	* amd/get_args.c (get_args): updated new syntax for amd -l
+	syslog:facility.
+
+Thu Jan  8 04:05:10 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/host_macros.m4: don't confuse sun3 (sparc) with sun3
+	(intel).
+
+	* libamu/wire.c (print_wires): bug fix.  Nullify output buffer
+	before appending to it, on systems with two or more network
+	interfaces.
+
+	* conf/nfs_prot/nfs_prot_sunos5_3.h: add missing definition for
+	the mntent for cachefs.
+
+	* include/am_defs.h: external definition for strstr() should use
+	const for both arguments.
+
+	* aux/configure.in: add extern definitions for getwd() if missing.
+
+	* include/am_defs.h: define the extern for strdup() even if the
+	function does not exist, for it will be filled in by
+	libamu/strdup.c
+
+	* amq/pawd.c (cluster_server): don't use getccent() if the extern
+	for it isn't there.  On hpux 10.20, the function is in libc, but
+	<cluster.h> and struct cct_entry do not exist.
+
+	* aux/configure.in: check for an extern for getccent() b/c some
 	hpux systems don't have it (hpux 10.20).
-	* amd/ops_nfs.c (mount_nfs_fh): process nfs mount option resvport
-	(must be supplied for bsdi 3.0)
 
-	* libamu/wire.c: use HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR (and
-	associated new macro) for determining the right way to compute the
-	size of the interface structure.
+Wed Jan  7 00:09:19 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+
+	* doc/am-utils.texi (Amq -T option): manual documentation updates
 	for new amq options -T/-U.
-Fri Apr 11 15:56:13 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
-	* aux/configure.in: need to include libc before libnsl if
-	get_myaddress() is available because on irix libnsl has a buggy
-	get_myaddress().
+	* amq/amq.8: updated man page for new amq options -T/-U.
+
+	* amq/amq.c: two new switches to amq. -U will contact amd using
+	UDP only.  -T will use TCP only.  Normally amq will try TCP and
+	if that failed, will try UDP.
+
+	* doc/am-utils.texi (pawd): manual documentation for pawd.
+
+	* amq/pawd.1: new man page for pawd.
+
+Tue Jan  6 04:21:59 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
 
-	* include/am_defs.h: make sure REINSTATE_SIGNAL_HANDLER is defined
-	on Irix 6 (an SVR4 variant)
 	* amq/pawd.c: a new program, Print Automounter Working Directory,
-Thu Mar 27 02:28:40 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	to print the proper pathname of the cwd or any other pathname,
+	adjusted for automounter paths, while avoiding mount points.
+
 	* aux/macros/localconfig.m4: trivial support for am-utils
-	*******************************************************************
-	*** Released am-utils-6.0a4					***
-	*******************************************************************
+	maintainers to adjust some of the configuration of am-utils after
+	it has been auto-configured by putting whatever definitions you
 	wish in a file called localconfig.h, located in the top build
-Wed Mar 26 21:15:36 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	directory (the same one where config.h is created for you).
+
 	* doc/am-utils.texi (Caching Filesystem): updated documents for
-	* amd/amq_subr.c (ok_security): turned off insecure code unless
-	user explicitly runs configure --enable-amq-mount.
+	cachefs file system.
+
 	* amd/ops_cachefs.c: initial cachefs support, for solaris.
-	* hlfsd/hlfsd.c (main): use new protoypes dor create_nfs_service().
+	type:=cachefs, requires cachedir:=/cache/dir/name to be defined
+	and initialized with cfsadmin -c.  $rfs is backdir to be cached
+	from, and $fs is the local mount point of the cachefs.
 
-	* amd/nfs_start.c (mount_automounter): use code that separately
-	creates the NFS and the amq service.  Register tcp and udp
-	services for amd.
+	* conf/mount/mount_svr4.c (mount_svr4): support mounting of
 	cachefs file systems.
-	* conf/transp/transp_*.c (create_amq_service): new function to
-	separately create the amq service for amd.  Simplified prototypes
-	for create_nfs_service().
+
+	* amd/ops_cdfs.c: cdfs should be named 'cdfs', not whatever the
 	mnttab type is.
-Wed Mar 19 20:40:56 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
 Mon Jan  5 23:22:49 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
-	*******************************************************************
-	*** Released am-utils-6.0a3					***
-	*******************************************************************
 
-Wed Mar 19 17:49:18 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* amd/opts.c: added support for new variable $cachedir.
+
+	* include/am_utils.h: added opt_cachedir field to struct am_opts.
+
+Sat Jan  3 01:43:57 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+
 	* amd/ops_nfsl.c (nfsl_ffserver, nfsl_match): also check if the
-	* new port: rs6000-ibm-aix3.2.5 and rs6000-ibm-aix4.1.5.0.  Lots
-	of small changes to support these two.
+	local hostname does not match $rhost, and if so, also assume
 	type:=nfs.
-Wed Mar 19 14:33:30 1997  Erez Zadok  <ezk@grande.cs.columbia.edu>
+
+Fri Jan  2 01:00:40 1998  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+
 	* updated all source files to add 1998 as a copyright year.
-	* conf/umount/umount_default.c (umount_fs): bug: unlock_mntlist()
-	should run if MOUNT_TABLE_ON_FILE, not otherwise.
+
+	* amd/ops_nfsl.c: new amd meta file system "type:=nfsl".  Behaves
 	like type:=linkx if the pathname denoted by $fs exists, and like
-Mon Mar 17 22:02:43 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	type:=nfs if it does not.  A convenient shortcut for the most
+	popular amd map entry.
 
-	* hlfsd/hlfsd.c (main): fill in fhsize field if exists
-	(freebsd-2.2).
+	* amd/amd.c (main): amd should chdir to / before starting, to
+	avoid hanging on other NFS server if started elsewhere.
 
-	* amd/ops_{nfs,afs}.c (mount_toplvl): fill in fhsize field if
-	exists (freebsd-2.2).
+	* amd/ops_TEMPLATE.c: added an empty template file for developers
+	who wish to write new amd pseudo file systems.
+
+Thu Jan  1 00:27:28 1998  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
-Sat Mar 15 19:37:48 1997  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 	* hlfsd/homedir.c (plt_init): make function exported, to save on
-	* new port: i386-unknown-freebsd2.2.  FreeBSD 2.2 and higher
-	changed the filehandle type in struct nfs_args from nfsv2fh_t to
-	u_char.
+	the unnecessary init_homedir() function which was removed.
+	(table_add): don't use xmalloc() when you can use strdup()
 	instead.
-Sat Mar 14 10:11:03 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+
 Thu Jan  1 00:15:58 1998  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
-	* SHARED LIBRARIES: too many change to list individually.  Now,
-	libamu can be built as a shared library, and other programs link
-	with it.
 
-Tue Mar 11 22:24:09 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	* hlfsd/homedir.c (hlfsd_endpwent): Don't actually run this
+	because we will be making more passwd calls afterwards.  On
+	Solaris 2.5.1, making getpwent() calls after calling endpwent()
+	results in a memory leak! (and no, even Purify didn't detect
+	it...)
+
+Tue Dec 23 18:23:47 1997  Erez Zadok  <ezk@chestnut.mcl.cs.columbia.edu>
+
+	* hlfsd/hlfsd.c (main): Bug fix.  Don't try to free() an
+	automatically allocated address.
 
-	* aux/macros/opt_shared.m4: new macro for setting options for
-	building shared am-utils libraries.
 	* amd/ops_afs.c (mount_toplvl): Bug fix.  Don't try to free() an
-Sun Mar  9 19:17:46 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	automatically allocated address.
+
 	* ALL SOURCES: change every direct call to free() to xfree(), so
-	* fixmount/fixrmtab: cleaned up the script.
+	it can be mapped to the right debugging function as needed.
+
+	* include/am_utils.h: new free() policy.  If debugging memory,
 	call dxfree(), which will print the file name and line number
-	* fixmount/Makefile.am (EXTRA_DIST): adde $(sbin_SCRIPTS) so that
-	fixrmtab gets distributed too.
+	where the free occurred and the pointer address.  if only regular
+	debugging, then free() and reset  the pointer to NULL so it cannot
+	be used afterwards inadvertently.  If not DEBUG at all, then just
+	run free().  Three different #define macros set the right mapping.
+
+	* libamu/xutil.c (dxfree): renamed function to dxfree(), so it can
+	be called only when debugging the memory.
 
-	* conf/nfs_prot/nfs_prot_bsdi2.h: added support for MOUNTPROC_DUMP.
-	Added extern for xdr_mountlist().
 Tue Dec 23 04:24:28 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-	* aux/configure.in: trimmed down many tests for MNT2_GEN_OPT,
-	MNT2_NFS_OPT, and MNTTAB_OPT that were not referenced anywhere in
-	the sources.
 
-Sat Mar  8 00:23:58 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* wire-test/wire-test.c (main): use xmalloc() not malloc().
+
+	* conf/transp/transp_tli.c (get_knetconfig): use xzalloc() not
 	calloc().
-	* fixmount/hlfsd ported to bsd44, hpux, and linux systems.
 
-	* aux/macros/check_fixmount_style.m4: add check for bsd44 systems.
+	* conf/mtab/mtab_mach3.c (convert): use xzalloc() not calloc().
+
+	* conf/mount/mount_linux.c (parse_opts): use xmalloc() not
 	malloc().
-	* conf/fixmount/fixmount_default.c: use lockf() if flock() is
-	unavailable.
+
+	* amd/info_ldap.c: use xmalloc() not malloc().
+
+	* libamu/xutil.c (xzalloc): new function to allocate memory and
 	zero its bytes.
-	* include/am_defs.h: include <string.h> even if don't have
-	STDC_HEADERS defined (sunos4).
-	(seteuid): define seteuid() to be setresuid() for systems that
-	have but not the other (hpux).
+
 	* amq/amq.c: amq does not need its own definition of xfree().
-	* aux/macros/check_extern.m4: test should include <strings.h>.
+
+	* aux/macros/opt_debug.m4: if used --enable-debug=mem, then also
 	look for function malloc_verify() in libmapmalloc.a, and function
-Tue Mar  4 17:16:52 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	mallinfo() in libmalloc.
 
-	* lib/xutil.c (debug_option): moved from amd/getargs.c to this
-	more proper file.
+	* libamu/xutil.c (checkup_mem): do not use mallinfo field
 	uordbytes, because it does not always exist.  Rather, compute it
-	* include/am_utils.h: put in structure for debug options, for all
-	progams to use.
+	from other fields..
+
+	* include/am_utils.h: add external definition to xfree() function
 	used when debugging memory references.
-	* amd/get_args.c: moved structure for debug options out.
+
 Mon Dec 22 03:01:30 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-Sun Mar  2 00:13:07 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+
+	* amd/ops_afs.c (afs_readdir_browsable): reduce the number of
+	bytes heuristically computed to be returned to the kernel.
 	Otherwise browsable_dirs fails on OpenBSD 2.2.
-	* ported fixmount.
+
 	* amd/mntfs.c (uninit_mntfs): bug fix.  Moved freeing of
-	* lib/ualarm.c: replacement function for systems that don't have a
-	ualarm().
+	mf_private field to AFTER it gets used.
+
 Sat Dec 20 00:51:21 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-	* ported fsinfo.
+
 	* amd/ops_host.c (host_umounted): don't use clnt_spcreateerror()
-Sun Mar  1 10:23:34 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	on systems that don't support it.
+
 	* include/am_defs.h: add missing extern definition for free().
-	* ported mk-amd-map.
 
-	* buildall: added -K option to buildall, to run mkconf.
+	* aux/configure.in: check for external definition for free().
+
+	* libamu/Makefile.am: add to comment a mention of strstr as an
 	optional function.
-Fri Feb 28 01:10:25 1997  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/xutil.c (switch_to_logfile): use openlog() options only
 	if they exist.
-	*******************************************************************
-	*** Released am-utils-6.0a2					***
-	*******************************************************************
+
+	* conf/transp/transp_sockets.c (get_nfs_version): don't use
+	clnt_spcreateerror if it does not exist.
+
 	* aux/configure.in: check for missing functions clnt_create and
-Thu Feb 27 13:58:59 1997  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	clnt_spcreateerror.  Check for missing strstr, and complete
+	its code.  Check for missing external definition for strstr.
+
+	* aux/macros/host_macros.m4: normalize sun3* names.
 
-	* all *.[hcyl] files: add copyright line.
 	* Makefile.am: updates for new sunos3 files distributed.
-	* aux/macros/check_mount_type.m4: test for mount type for
-	linux-like systems, by checking for loadable or statically linked
-	kernel filesystem modules.
+
+	* conf/nfs_prot/nfs_prot_sunos3.h: new file.
+
 	* conf/fh_dref/fh_dref_sunos3.h: new file.
-	* aux/macros/check_mnttab_type.m4: test for mount table entry
-	for linux-like systems, by checking for loadable or statically
-	linked kernel filesystem modules.
+
+	* aux/macros/check_nfs_prot_headers.m4: added sunos3 case.
+
 	* aux/macros/check_nfs_fh_dref.m4: added sunos3 case.
-	* aux/configure.in: pcfs filesystems can use vfat type (linux)
+
 	* doc/am-utils.texi (wire Selector Variable): updated manual for
-	* aux/macros/check_fs_mntent.m4: test for filesystem existence for
-	linux-like systems, by checking for loadable or statically linked
-	kernel filesystem modules.
+	adjusted variables wire, network, and netnumber, all using the
 	in_network() function.
-	* conf/trap/trap_hpux.h: ugly hack added because of stupide HPUX
-	9.0 header files.  This should be removed when HPUX 9.0 is deemed
-	defunct.
+
+Fri Dec 19 04:37:36 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* amd/opts.c: allow options to be processed by executing arbitrary
 	functions.  Converted wire, network, and netnumber all to use the
-	* aux/acconfig.h: set an undefined variable for having an extern
-	to clnt_sperrno().
+	nomadic function in_network.  So from now on they perform a match
 	against all networks, not just primary.
-	* include/am_defs.h: define extern for clnt_sperrno() if needed.
+
+	* initial port to alpha-unknown-linux-gnu, probably works, but
+	untested yet.
+
 	* conf/nfs_prot/nfs_prot_linux.h: add special definitions for
-	* aux/configure.in: test for extern clnt_sperrno().
+	__FD_* macros which for som strange reason do not get included
+	from <selectbits.h> on redhat alpha linux.  Also turn off usage of
 	<rpc/des_auth.h> because it is incomplete on the same systems.
-	* aux/macros/check_nfs_fh_dref.m4: HPUX's NFS fhandle dref is
-	similar to irix.
+
 	* hlfsd/homedir.c (table_add): cast uid field to int, for
-	* aux/macros/check_mount_style.m4: use mount helper on HPUX.
+	comparison.
+
 	* include/am_defs.h: more coflicts with redhat alpha linux
-	* aux/macros/check_mtype_type.m4: hpux's mount type is a char*,
-	not integer (but may be mapped to one later).
+	"resolved".
+
 	* aux/macros/{mount_headers,try_compile_anyfs,try_compile_nfs}.m4:
-	* conf/mount/mount_hpux.c (mount_hpux): HPUX has confusing header
-	files.  They have mount(2) and vfsmount(2) which don't take same
-	arguments, and they have string mount types MNTTYPE_* as well as
-	integer types MOUNT_*.  So I need this new mount function to map
-	from string types to integer types for the vfsmount() function.
+	There's a conflict of definitions on redhat alpha linux between
+	<netinet/in.h> and <linux/fs.h> which must be avoided.
+
+	* aux/configure.in: check for <socketbits.h>, which is in use on
 	redhat alpha linux.
-	* conf/trap/trap_hpux.h (MOUNT_TRAP): instead of calling
-	vfsmount(), call mount_hpux().
+
+	* doc/am-utils.texi (Selectors): added documentation to describe
 	the new "!" (negated) nomadic functions.
-Thu Feb 27 03:34:14 1997  Erez "HWank1" Zadok  <ezk@okeeffe.cs.columbia.edu>
+
+	* amd/opts.c (f_in_network): print debugging info that is correct,
 	rather than saying that any ARG is on a local network.
-	* lib/mount_fs.c (mnt_flags): make sure SYNC option is on only if
-	both MNTTAB_OPT_SYNC and MNT2_GEN_OPT_SYNC are defined.
+	(eval_opts): added support for negating nomadic functions, by
+	prepending "!" to their name.  Example, !exists(/foo/bar).
 
-Thu Feb 27 00:26:00 1997  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 Thu Dec 18 20:57:19 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-	* conf/nfs_prot/nfs_prot_hpux.h: NFS protocol definitions for
-	hpux.
 
-	* include/am_defs.h: no need to include rpc/auth.h or rpc/clnt.h.
+	* include/am_compat.h: ensure that all NFS3 systems have the mount
+	table entries (and amd opts switches) "proto" and "vers".
+
+	* hlfsd/homedir.c (table_add): added some debugging info to try
+	and track down a serious memory leak in hlfsd.
+
+1997-12-18  Erez Zadok  <ezk@t-rex.mcl.cs.columbia.edu>
+
+	* libamu/mount_fs.c (compute_nfs_args): OpenBSD 2.2 requires that
+	you do NOT set the noconn option, and use connected sockets
+	always.  So I'm now forced not to set it at all, and have the user
+	specify it as "conn" or "noconn" in their /default entry.  Argh...
 	Finally, it looks as if OpenBSD 2.2's NFS 3 implementation may be
-	* aux/configure.in: no need to test for rpc/auth.h and rpc/clnt.h.
+	buggy (TCP hangs with "short receive" kernel errors).  I'd better
 	wait until they get it working in their version of the automounter
-	* buildall: added ability to configure using other shells than
-	/bin/sh, on those systems where /bin/sh is buggy or limited
-	(HPUX).
+	first.  So I'm putting the "noconn" option back.
+
+Thu Dec 18 02:39:39 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/mount_fs.c (compute_nfs_args): use maxgrps option and set
+	nfs_args field maxgrouplist accordingly.
+
+	* include/am_compat.h (MNTTAB_OPT_MAXGROUPS): complete definition
+	for mount table entry for maxgroups based on NFS mount option
 	maxgrp.
-	* aux/macros/struct_nfs_fh.m4: reinstated the macro but have it
-	defined am_nfs_fh, and also test for plain typedef "nfs_fh".
+
+	* aux/configure.in: put back testing for NFS mount option
 	"maxgrps".  Added test for mount table entry "maxgroups".
-	* aux/acconfig.h: #undef am_nfs_fh, which is being defined by a
-	reinstated macro.
+
 	* libamu/mount_fs.c (compute_nfs_args): perform more careful tests
-	* aux/configure.in: check for <nfs/export.h>
+	on nfs_proto, because it could be NULL.
 
-	* include/am_defs.h: include <nfs/export.h> (HPUX) if exists.
+	* doc/am-utils.texi (Selectors): added example of in_network()
+	selector.
+
+	* aux/macros/check_hide_mount_type.m4: all hpux versions,
 	including 9.x, should use "ignore" as the mount type to hide from
-	* aux/macros/try_compile_nfs.m4: include <nfs/export.h> (HPUX) if
-	exists.
+	amd.
 
-	* aux/macros/mount_headers.m4 (define): removed some non-working
-	(on HPUX) code that attempts to recreate the fhandle_t rather than
-	load it up from system headers.  Also added some NFS protocol
-	header inclusion.  include <nfs/export.h> (HPUX) if exists.
+Wed Dec 17 13:09:21 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* include/am_utils.h (NSTREQ): use new macro instead of strncmp()
 	every where in the sources.
-Wed Feb 26 00:32:35 1997  Erez "HWank1" Zadok  <ezk@okeeffe.cs.columbia.edu>
 
-	* aux/macros/mount_headers.m4 (define): Use M4 changequote to
-	ensure [] brackets are correctly used.
+Wed Dec 17 01:15:01 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+
+	* libamu/mount_fs.c (print_nfs_args): if -D trace is on, will
+	print as much info that is given in struct nfs_args as possible.
 	useful for detecting internal flags and options, as well as the
-	* aux/macros/expand_cpp_{string,hex,int}.m4: encapsulate
-	multi-line M4 inclusions in [].
+	file handle used.
+
+	* scripts/ctl-amd.in: look for amd.conf file in ${prefix}/etc
 	after /etc and before /etc/local.
-Tue Feb 25 22:19:44 1997  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+Tue Dec 16 18:51:36 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
 	* aux/configure.in, libamu/Makefile.am: added support for linking
-	* conf/mtab/mtab_bsd.c (mnt_dup): use statfs field f_fstypename if
-	it exists.
+	with specific versions of libamu.  Upped shared library version of
+	libamu to 1 (libamu.so.1.0.0)
 
-	* aux/acconfig.h: HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME, new
-	config.h macro for field f_fstypename of struct statfs.
+	* include/am_defs.h: added external definition for mkstemp() as
 	needed.
-	* aux/configure.in: testing for field f_fstypename field of struct
-	statfs (NetBSD).
+
+	* minor new port to i386-unknown-netbsd1.3 (BETA version of
 	netbsd).
-	* aux/acconfig.h: moved all of the "static" definitions out to a
-	fixed file called include/am_defs.h.  Added to all */Makefile.am
-	files a dependency on am_defs.h.  Created am_defs.h of course, and
-	then added #include <amd_defs.h> to all of the source and header
-	files that required it.
+
+	* aux/config.guess: don't leave a trailing '.' on the system name
 	for NetBSD-1.3_BETA and similarly for OpenBSD.
-Mon Feb 24 01:27:02 1997  Erez Zadok  <ezk@defiant.soscorp.com>
+
 	* conf/nfs_prot/nfs_prot_netbsd1_3.h: new header for the slight
-	* aux/acconfig.h: two more externals for xdr functions that may be
-	implemented by libamu.
+	differences in ypall calling conventions.
+
+	* mk-amd-map/mk-amd-map.c (main): use mkstemp() whenever possible
+	in preference over mktemp(), b/c it is more secure.
+
+	* aux/configure.in: check for mkstemp(), a more secure version of
 	mktemp().
-	* conf/nfs_prot/nfs_prot_bsdi2.h: added missing RPC and XDR
-	definitions.
+
+Mon Dec 15 02:32:14 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
 	* amd/ops_nfs.c (mount_nfs_fh): Systems that include the mount
-Sun Feb 23 15:25:26 1997  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	table "vers" option generally do not set the mnttab entry to
 	"nfs3", but to "nfs" and then they set "vers=3".  Setting it to
-	* buildall (default): added -D option for turning on even stricker
-	developer options.
+	"nfs3" works, but it may break some things like "df -t nfs" and
+	the "quota" program (esp. on Solaris and Irix).  So on those
 	systems, set it to "nfs".
-	* */Makefile.am: make sure @AMU_NFS_PROT_HEADERS@ is used to
-	determine dependencies on optional NFS protocol headers.
 
-	* aux/acconfig.h: define and use HAVE_NFS_PROT_HEADERS as needed.
+Sat Dec 13 01:36:27 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
-	* aux/macros/check_nfs_prot_header.m4: new test to determine what
-	NFS protocol headers to use. 
+	* doc/am-utils.texi (Distrib): updates for new ports, location of
+	am-utils' home page, and URL cross references (now supported by my
+	version of texi2html).
+
+	* aux/macros/check_mtype_type.m4: also use string type for file
 	system mount types under nextstep for mount(2).
-	* conf/nfs_prot/nfs_prot_{irix6,sunos4,bsdi2}.h: new headers to
-	complete missing system headers for NFS protocol definitions.
+
+	* aux/macros/check_mtype_printf_type.m4}: nextstep can handle both
 	integer and string types for file system mount types in mount(2),
-Sun Feb 16 15:58:42 1997  Erez "HWank1" Zadok  <ezk@vir.cs.columbia.edu>
+	but it is better to use string types.
+
+	* conf/nfs_prot/nfs_prot_nextstep.h: set emum nfsstat's NFS_OK to
+	0, not 1!  Otherwise, all NFS calls (esp. mount) return errno 1
 	(EPERM) instead of 0 (OK).  Fixes m68k-next-nextstep3 which now
-	* amd/ops_nfs.c (mount_nfs_fh): encapsulated some more code in
-	#ifdef's as needed.
+	works.
 
-	* amd/ops_afs.c (mount_toplvl): make sure TIMEO/RETRANS code is
-	suitable #ifdef'ed.
+	* conf/nfs_prot/nfs_prot_bsdi2.h: set emum nfsstat's NFS_OK to 0,
+	not 1!  Otherwise, all NFS calls (esp. mount) return errno 1
+	(EPERM) instead of 0 (OK).
 
-	* include/am_compat.h: a couple more mnttab options
-	(timeo/retrans) setting just in case.
+	* libamu/xdr_func.c (xdr_*): add debugging calls that are optioned
+	by -D trace (protocol trace).
 
-	* amd/autil.c (host_normalize): make sure hostent->h_name is
-	passed a non-const char *.
+1997-12-11  Erez Zadok  <ezk@bach.cs.columbia.edu>
 
-	* conf/mount/mount_linux.c (mount_linux): cleaned up a block of code.
+	* A.m68k-next-nextstep3/amu_nfs_prot.h: define missing S_ISDIR
+	macro based on existence on others, and include <sys/stat.h>.
+
+Thu Dec 11 14:14:38 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/try_compile_nfs.m4 (AC_TRY_COMPILE): turn off
 	inclusion of <nfs/nfs_mount.h> which only affects nextstep3, on
-	* {lib,amq,amd}/*.c (many functions): cast xdr_entry to
-	XDRPROC_T_TYPE.
+	which this header is broken (it tries to include non-existing
+	headers).
+
+Wed Dec 10 16:09:07 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
 	* libamu/mount_fs.c (mnt_flags): support either nfs or generic
-	* lib/nfs_prot_svc.c (nfs_program_2): cast xdr_entry to
-	XDRPROC_T_TYPE.
+	mount option for grpid.
 
-	* lib/nfs_prot_xdr.c (xdr_entry): cast xdr_entry to
-	XDRPROC_T_TYPE.
+	* aux/configure.in: turn back on NFS mount option grpid.
 
-	* lib/wire.c (getwire): Make sure safe assignment from const to
-	none is done.
+Sat Dec  6 04:36:05 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/Makefile.am (install-ps): added target to install postscript
 	file in the am-utils' home page, as well as a few other useful
-Sat Feb 15 19:38:51 1997  Erez "HWank1" Zadok  <ezk@vir.cs.columbia.edu>
+	files for the new am-utils Web page.
+
 Mon Nov 17 05:22:56 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-	* aux/macros/expand_cpp_int.m4: new macro for expanding integers.
+
+	*******************************************************************
+	*** Released am-utils-6.0a14					***
 	*******************************************************************
-	* aux/configure.in: added linux/fs.h support in configure and
-	several M4 macros.
 
-	* conf/mount/mount_linux.c (mount_linux): use macro instead of
-	"ugly" fixed hex number for mount() arguments.
+Sun Nov 16 21:56:16 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* doc/am-utils.texi (Supported Platforms): updated table of new
 	ports.
-Sat Feb 15 02:09:47 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
 
-	* amd/info_hesiod.c: removed macro HAVE_HS_ZONE_TRANSFER and
-	turned all of its code always on.  That code always seems to
-	compile, as long as you have hesiod and libresolv.
+Sat Nov 15 06:36:27 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* libamu/mount_fs.c (compute_automounter_nfs_args): pass mnttab
+	options so that they can be printed in logs as needed.
+
+	* doc/am-utils.texi (osver Parameter): updated for the correct
+	usage of the -o/-O options.
+
 	* scripts/amd.conf.5: corrected info for -o/-O options.
-	* amd/mapc.c: removed macro HAVE_HS_ZONE_TRANSFER and turned all
-	of its code always on.
+
+	* amd/amd.8: updated man page for new -O op_sys_name option, and
+	corrected the usage of the -o op_sys_ver option
+
+	* amd/get_args.c (get_args): added new amd option -O to override
 	OS name.
-	* aux/configure.in: removed superfluous test for hs_zone_transfer
-	function (will never find it because it is an amd-internal
-	function).
+	(get_args): updated usage string.  Removed old -m option.  Added
 	-o and -O options.
-	* amd/mapc.c (maptypes): must used correct new name for am-utils'
-	hesiod initialization function: hesiod_am_init.
 
-	* amd/info_hesiod.c (hesiod_am_init): renamed hesiod_init to
-	hesiod_am_init so as not to conflict with libhesiod's
-	hesiod_init() function.
+	* conf/nfs_prot/nfs_prot_irix5.h: add definition to FHSIZE in case
+	it is not there.  Reportedly, irix 5.2 does not define it.
+
+	* scripts/lostaltmail.in: removed references to unused $hack
 	variable.
-	* aux/configure.in: added test and explicit inclusion of
-	libresolv.a for later resolution of library references with
-	libhesiod.
+
+	* aux/macros/check_nfs_prot_headers.m4: Patch from Chris Metcalf
 	<metcalf@cag.lcs.mit.edu> to correctly set the nfs_prot headers
-	* aux/macros/opt_cppflags.m4: new file.  configure/compile C
-	preprocessor flags.
+	for solaris2.5.
+
 	* doc/am-utils.texi (Distrib): typo in the subscription
-	* aux/macros/opt_libs.m4: new file.  configure/compile library
-	flags.
+	instructions to amd-dev.  Patch from Stefan Vogel
 	<vogel@physik-rzu.unizh.ch>.
-	* Makefile.am (EXTRA_DIST_AUX): include two new macros
-	opt_cppflags.m4 and opt_libs.m4.
+
 1997-11-15  Erez Zadok  <ezk@amtrak.cs.columbia.edu>
-	* aux/configure.in: test for libhesiod needs to additional
-	libresolv to link completely.  Additional configuration time
-	options added for setting initial CPPFLAGS and LIBS.
 
-Tue Feb 10 02:15:40 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
 	* NFS3 works on powerpc-ibm-aix4.2.1.0.
 
-	*** Released am-utils-6.0a1					***
+	* libamu/mount_fs.c (compute_nfs_args): set fh3 variable to
 	static.  Some compilers (gcc from egcs  on aix 4.2.1) corrupt the
 	stack of an automatic variable when pointer to it is passed around
-Thu Feb  6 02:55:19 1997  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	several times.
+
+Fri Nov 14 20:09:28 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
-	* amd/info_ndbm.c (ndbm_search,ndbm_init): fixed the code so that
-	it works on freebsd, where they map dbm_pagfno a non-existing
-	macro on purpose, to force you to port the code to Berkeley DB.
 	* libamu/xutil.c (real_plog): syslog like behavior for normal
-Fri Jan 31 01:35:09 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	logging.  Will not print repeated strings, only a count "last
+	message repeated N times", but will always print something if
+	message is repeated more than 100 times.
 
-	* amd/ops_afs.c (mount_toplvl): added a sleep(1) right before the
-	actual mount_toplvl, to avoid some possible race conditions.
+	* scripts/lostaltmail.in: look for lostaltmail.conf files also in
+	/etc/global, /etc/os, and /etc/local (in that order).
 
-Thu Jan 30 02:31:49 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+Mon Nov 10 03:03:17 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
 
-	* amd/rpc_fwd.c: removed all TLI (HAVE_T_OPEN) code.
+	* conf/mount/mount_aix.c (mount_aix3): add support for NFS V.3
+	mounts.
 
-Wed Jan 29 18:25:07 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	* aux/macros/struct_nfs_args.m4 (AC_TRY_COMPILE_NFS): test for
+	aix42_nfs_args, specially set in conf/nfs_prot/nfs_prot_aix4_2.h
 
-	* lib/wire.c (getwire): removed HAVE_T_OPEN (TLI code)
+	* conf/sa_dref/sa_dref_*.h: from now on, the "dst" argument to the
+	NFS_SA_DREF macro is a pointer to the structure that used to be
 	passed to it before.  So now I have to dereference the pointer
-	* amd/amd.c (main): fix local address using htonl(). Free up
-	buffers allocated by netdir_*() functions.
+	before accessing its values.
 
-Wed Jan 22 23:53:24 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	* hlfsd/hlfsd.c (main): use the new and cleaner
+	compute_nfs_args() and compute_automounter_nfs_args() functions.
 
-	* amd/fix-amd-map.in: new script that will convert old-style amd
-	maps to new one.
+	* amd/ops_nfs.c (mount_nfs_fh): use the new and cleaner
 	compute_nfs_args() and compute_automounter_nfs_args() functions.
-Tue Jan 21 01:18:16 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+
+	* amd/ops_afs.c (mount_toplvl): MAJOR CODE REVISION.  Use the new
 	and cleaner compute_nfs_args() and compute_automounter_nfs_args()
-	* FIRST AMD IN AM-UTILS FINALLY WORKS (mounts itself as toplvl,
-	and replies back to simple nfs/link type mount queries).
+	functions.
+
+	* libamu/mount_fs.c (compute_nfs_args): major code cleanup that
 	relates for struct nfs_args.  A new function sets the numerous
-	* conf/mtab/mtab_svr4.c: reorganized the code in this file to be
-	easier to read, and fixed a few bugs with un/setting the lock file
-	descriptor.
+	possible flags and fields of nfs_args_t in an orderly fashion.
+	Code cleaned up, organized, and moved from amd/hlfsd into
 	libamu.  This saves on overall size of code.
-Wed Jan  8 15:27:49 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	(compute_automounter_nfs_args): A variant of compute_nfs_args()
+	which sets special options/flags that need to be used when NFS
 	mounting an automounter's mount point.  Used by hlfsd and amd.
-	* amd/sched.c: removed HAS_SVR3_SIGNALS code to handle older
-	signals in Svr3 systems.  Only stellix ever used this.
+
 	* amq/amq.c (get_secure_amd_client): don't print any more
-	* amd/rpc_fwd.c (fwd_reply): removed all code that was triggered
-	by DYNAMIC_BUFFERS, since it was not in use.
+	"get_secure_amd_client: using TCP, port 12345".  It's more
+	annoying than useful a message, even when assumed to be compiled
 	under DEBUG only.
-Tue Jan  7 00:45:59 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
 
-	* amd/opts.c (eval_opts): removed AMD_COMPAT code.  Amd no longer
-	takes '=' sign as old selector.  Fix your maps.
-	(deslashify): removed APOLLO code that treated two '//' as one.
+Thu Oct 30 14:33:38 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* aux/macros/check_mnttab_type.m4: MAJOR BUG fixed for non-nfs
+	mount table entries.  The code used to define the /etc/mnttab name
 	for file systems based on physical media (disk, cdrom, floppy) to
-Sun Jan  5 01:25:09 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	the generic name, rather than the OS specific name.  For example
 	autoconf searches for all these types of mount table entries for a
-	* amd/ops_nfsx.c (nfsx_init): removed HARD_NFSX_ERRORS, code which
-	was not used.  It made any submount error fail the whole group.
+	floppy based file system: vfat pcfs pc msdos msdosfs fat.  But if
+	it found any, it hard-coded the mnttab name to "pcfs" rather than
 	the actual name found!  Same for ufs, cdfs, pcfs, tmpfs, lofs,
-	* amd/ops_nfs.c (make_nfs_auth): removed code dependent on
-	HAS_NFS_QUALIFIED_NAMES.
-	(mount_nfs_fh): removed macro for NFS_ARGS_NEEDS_PATH, assuming it
-	is never on.  So code that was triggered by #ifndef
-	NFS_ARGS_NEEDS_PATH (osf1, aix3, and bsd44 variants) may have to
-	be fixed later.
-	Removed all ULTRIX_HACK code.  Ultrix is DEAD!
-	removed all PRESET_AC code, which was only on for Linux to preset
-	the attribute cache values (otherwise they default to zero).
-	(nfs_umounted): revobed KICK_KERNEL code (IRIX systems).  Will
-	have to fixed up later.
-	(mount_nfs_fh): removed code that was never included, which
-	attempted to set the port on which amd's nfs mounts on.  This
-	isn't supported by the ping algorithm yet.  In any case, it is all
-	done in nfs_init().
+	nullfs, unionfs, and umapfs.
+
+	* aux/configure.in: also test for xfs (for newer Irix) when
+	looking for mount type names, numbers, etc of a disk-based ufs.
 
-	* amd/srvr_nfs.c (find_nfs_srvr), amd/ops_nfs.c (mount_nfs_fh):
-	removed HAS_TCP_NFS code.  The whole use of NFS V.3 with TCP or
-	specially hacked NFS V.2 that uses TCP (BSD 4.4 variants) will
-	have to be addressed later.
 Sun Oct 26 19:32:57 1997  Erez Zadok  <ezk@defiant.soscorp.com>
-	* amd/nfs_subr.c (nfsproc_getattr_2): removed all code dependent
-	on PRECISE_SYMLINKS.
+
+	* amq/amq.c (main): use pmap_ping() to test if remote host is up.
 	This works better on bsdi2 and bsdi3, because their portmapper
-	* amd/mapc.c (mapc_meta_search): removed code that depended on
-	HAS_DEPOT.  It is known buggy code.  The whole DEPOT support needs
-	to be rethought.
-	(mapc_add_kv): ported code to use standard regular expression
-	(regexp) library.
+	does not appear to like forwarding operations (it is generaly
 	insecure).
-	* amd/{map.c,ops_sfs.c,ops_ufs.c}: removed all code dependent on
-	FLUSH_KERNEL_NAME_CACHE and the macro itself.
+
+Sat Oct 25 04:55:56 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	*******************************************************************
 	*** Released am-utils-6.0a13					***
-Sat Jan  4 15:46:58 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	*******************************************************************
+
 Fri Oct 24 05:04:37 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-	* amd/map.c (exported_ap_alloc): removed all code triggered by
-	SHRINK_EXPORTED_AP and the macro itself.
+
+	* conf/nfs_prot/nfs_prot_ncr2.h: added missing definition for
 	struct datum typedef.
-	* amd/info_nis.c: removed HAS_NIS_RELOAD macro, and left the code
-	in all the time.  Assuming that there is always NIS realod
-	available.
-	(yp_all_fixed): removed code for BROKEN_YP_ALL.  If your yp_all()
-	function is broken such that it does not release filedescriptors
-	it created, then you are hosed.  Get a fix for yp_all from your
-	vendor or switch operating systems.
 
-Tue Dec 31 15:34:36 1996  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	* conf/nfs_prot/nfs_prot_netbsd.h: corrected typedef for
+	ypall_callback_fxn_t for netbsd.
+
+	* aux/macros/type_auth_create_gidlist.m4: hpux10.10 uses int for
+	the 5th arg to authunix_create(), while before and after they used
 	gid_t.
-	* amd/info_hesiod.c: renamed macro HAS_HESIOD_RELOAD to
-	HAVE_HS_ZONE_TRANSFER.
+
 	* conf/transp/transp_tli.c (amu_clnt_create_best_vers): don't use
-Mon Dec 30 17:33:23 1996  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	clnt_create_timed() on older Solaris 2.3 systems that did not have
+	it.
 
-	* amd/{nfs,host}_ops.cremoved INFORM_MOUNTD macro, so its code is
-	always included.  We should always try to inform the remove mount
-	daemon of mounts we performed.  If we want an option for this, it
-	should be a run-time option.
+	* conf/nfs_prot/nfs_prot_bsdi2.h: <msdosfs/msdosfsmount.h> is for
+	kernel only on bsdi2, so do not include it.
 
-	* amd/host_ops.c: removed all that optionally did not make the
-	directory mount points for amd.
+Fri Oct 24 00:29:42 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
 
-	* HOST_EXEC code removed from everywhere.  There is no indication
-	that it was used anywhere.  If it needs to be used, then a
-	run-time switch should control it.
+	* hlfsd/stubs.c (nfsproc_readlink_2_svc): avoid logging repeated
+	messages about resolution of mailboxes based on uid/gid.
 
-Thu Dec 26 00:06:52 1996  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	* scripts/ctl-hlfsd.in: check for alternate password file in
+	${prefix}/etc/passwd and use it in hlfsd's startup.
+
+Thu Oct 23 22:48:50 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
+
+	* hlfsd/homedir.c (hlfsd_getpwent): added support for -P
 	passwdfile option.  If hlfsd is started with -P passwdfile, then
-	* amd/*_ops.c: removed all references to mntent_t's fields
-	mnt_freq and mnt_passno, since they are no longe rused (and never
-	have been).
+	the passwdfile is read and parsed just as a standard unix
+	passwd(4) file.  Only the username, uid, and homedir fields are
 	read and checked.  All the rest are ignored.  No NIS/netgroup
-	* amd/am_ops.c: removed function sunos4_match, which was off
-	anyway.  This was one of the places where an '=' sign was allowed
-	as an assignment operator (which is now ':=').
+	support!
 
-	* amd/afs_ops.c (afs_bgmount): removed SUNOS4_COMPAT code which
-	was off anyway.  This was one of the places where an '=' sign was
-	allowed as an assignment operator (which is now ':=').
+	* hlfsd/hlfsd.c (main): check if hlfsd is run as root after
+	parsing command line options, so that usage() can be printed when
 	-h is invoked.
-Tue Dec 24 01:53:52 1996  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+
 Wed Oct 22 00:16:39 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
-	* amq/amq.c: ported to am-utils.  Working.
 
-	* conf/mount/mount_svr4.c (mount_svr4): changed mount type on svr4
-	to be string, as it should be (rather than a string mapped to int
-	and back mapped to string).
+	* amd/nfs_start.c (mount_automounter): if autofs service listener
+	fails to initialize it is OK if using a test amd.
+
+	* amd/opts.c (f_in_network): new nomadic function in_network(arg),
 	which returns TRUE if 'arg' is any one of this host's networks.
-Sun Dec 22 13:26:05 1996  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+
+	* libamu/wire.c (getwire): rewritten parts of function, to store
 	all networks names and numbers in the order of the interface (not
-	* lib/mount_fs.c (mount_fs): removed MNTINFO_PREF code.
+	in reverse).
+
 Mon Oct 20 01:59:25 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-	* lib/umount_fs.c: split this into three files: default, osf, and
-	bsd44, that are in conf/umount/umount_*.c.
+
 	* aux/configure.in: don't add ops_ufs.o on AIX twice.  My code
-Thu Dec 19 17:33:46 1996  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
+	would have worked had it not been due to AIX's buggy /bin/sh.
+
 	* doc/Makefile.am (EXTRA_DIST): include am-utils.dvi and
-	* aux/configure.in, aux/aclocal.m4, aux/acconfig.h: added new
-	macro to automatically figure out if an external definition for
-	sys_errlist[] exists.
+	am-utils.ps in the distribution sources.
 	(html): generate html documentation for
-	* lib/xutil.c (xfree): removed "#undef free" because it's not
-	needed there.  Any system that redefines free() needs help.
+	http://www.am-utils.org
 
-	* conf/mtab/mtab_file.c (REWRITE_MTAB_IN_PLACE): removed code that
-	was dependent on REWRITE_MTAB_IN_PLACE.  It does not appear to be
-	in active use anywhere.  If added later, it should be a run-time
-	configuration option.
+Sun Oct 19 12:35:49 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	* conf/nfs_prot/nfs_prot_netbsd.h: override the definition of
 	ypall_callback_fxn_t.  The NetBSD team compiles all sources with
-	* conf/mtab/mtab_mach3.c: removed code that was #ifdef'ed not to
-	be MOUNT_TABLE_ON_FILE, since mach2 always stores its mount tables
-	in a file in /etc.
+	gcc -Wall -Wmissing-prototypes -Wstrict-prototypes.
+
+	* amd/info_nis.c: allow for override of ypall_callback_fxn_t
 	function typedef.
-	* lib/util.c (str3cat): removed _AIX code.  AIX should have a
-	working realloc, or else find a cleaner solution to this.
-	(mkdirs): removed SUNOS4_WORKAROUND code.  This was to do a sync()
-	after immediately making directories so that fsck will be able to
-	fix the filesystem in the event of an immediate crash.  This was
-	because a bug in UFS which is fixed by now.
+
 	* libamu/xutil.c (amu_release_controlling_tty): new function to
-	* lib/hutil.c (domain_strip): removed PARTIAL_DOMAINS triggered
-	code.  Does not appear to be on and used anywhere.
-	(dofork): removed MACH3 code, b/c mach3 NFS bugs are fixed by now.
+	release the controlling tty in a clean and sane manner.  No longer
+	using setpgid() b/c it may not work.  Uses setsid(),
+	and ioctl() (in order).  This new function is used in amd/amd.c
 	and hlfsd/hlfsd.c.  Also avoid setpgrp(), because it works on some
-	* lib/resvport.c: split the binding of reserved ports code to a
-	separate file.  A #define (HAVE_T_OPEN) separates the TLI (SVR4)
-	from the BSD code.
-
-Thu Dec 19 02:08:35 1996  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-
-	* lib/Makefile.am (amu_LIBADD): includs @LIBOBJS@ now, auto-filled
-	in by automake and configure, for optional sources that need to be
-	built as part of libamu.a.
-
-	* aux/aclocal.m4: Make sure AC_CHECK_MOUNT_STYLE adds mountutil.o
-	to LIBOBJS.
-
-	* lib/memcmp.c (memcmp): new file added to replace a possible bad
-	implementation of memcmp.
-
-Wed Dec 18 22:20:23 1996  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
-
-	* converted the sources to use memset/memmove/memcmp instead of
-	bzero/bcopy/bcmp.
-
-	* ran all sources through gnu Indent w/ options specified in
-	aux/amindent.
+	systems, but on others it is the same as setpgid().
 
-Wed Dec 11 22:19:29 1996  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+Sat Oct 18 23:42:40 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
-	* At this point the initial genration of config.h via autoconf and
-	some preliminary makefiles via automake is done.  I will not begin
-	modifying sources, so it's a good time to document from here.
+	* aux/acconfig.h: check for nfs mount option 'fsname'.  Code for
+	it was in amd/ops_afs.c, amd/ops_nfs.c, and hlfsd/hlfsd.c, but
+	never used, because the configure test for fsname flag wasn't
+	used.  This fixed a bug in HPUX 10, where syncer and manual mounts
+	left blank lines in /etc/mnttab.
 
-Wed Dec 10 22:19:29 1996  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+	* aux/configure.in: check for nfs mount option 'fsname'.
 
-	*******************************************************************
-	*** Initial ChangeLog Entry					***
-	*******************************************************************
+Fri Oct 17 13:30:27 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
 	* amd/ops_afs.c (mount_toplvl): turn on 'ignore' option in nfs
 	mount flags of toplvl mounts.  Important esp. for HPUX 10.  Now
@@ -4841,7 +10707,7 @@ Fri Jul 25 03:16:31 1997  Erez Zadok  <ezk@felix.psl.cs.columbia.edu>
 	structure to actual char[], because the structure was passed to
 	xdr_fhandle as data and not a pointer.  Surprisingly, gcc
 	-fpcc-struct-return did not help.
-	
+
 	* conf/nfs_prot/nfs_prot_sunos5_4.h: special nfs protocol
 	definitions for solaris 2.4 have to be different from 2.3, and
 	different from 2.5.
@@ -4896,7 +10762,7 @@ Wed Jul 23 16:11:49 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
 	* amd/ops_afs.c (afs_retry): patches from Debian Linux.  If
 	afs_mount timed out, then explicitly forbid further retries after
-	the timeout.  (afs_bgmount): buf fix from Debian Linux.  Timeout
+	the timeout.  (afs_bgmount): bug fix from Debian Linux.  Timeout
 	values (17 and 5) were mistakenly swapped.
 
 Wed Jul 23 15:53:25 1997  Erez Zadok  <ezk@felix.psl.cs.columbia.edu>
@@ -5155,7 +11021,7 @@ Tue Jul  8 12:42:03 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
 Mon Jul  7 19:10:44 1997  Erez Zadok  <ezk@prometheus.soscorp.com>
 
-	* NFS V3 now works under Irix5, thanks to patches from 
+	* NFS V3 now works under Irix5, thanks to patches from
 	Andreas Stolcke <stolcke@speech.sri.com>.
 
 	* conf/mount/mount_irix5.c: sparate mount_irix.c into an irix5
@@ -5174,7 +11040,7 @@ Sun Jul  6 14:22:24 1997  Erez Zadok  <ezk@glory.soscorp.com>
 
 	* aux/{configure.in,acconfig.h}: added checks for struct
 	nfs_args's fields proto and sotype (bsdi3).
-	
+
 	* amd/ops_nfs.c (mount_nfs_fh): added nfsv3 option to
 	nfs_args.flags for bsdi3.  Set field proto to 0.  Set sotype field
 	to SOCK_STREAM or SOCK_DGRAM.
@@ -5253,7 +11119,7 @@ Thu Jul  3 17:49:00 1997  Erez Zadok  <ezk@prometheus.soscorp.com>
 	* aux/configure.in: some cleanup of which libraries are needed.
 	Espectially ensure that libnsl is included only on Solaris, where
 	so far it is the only system on which it is absolutely necessary.
-	Also no longer need to include libc explicitly. 
+	Also no longer need to include libc explicitly.
 
 	* amd/amd.c,wire-test/wire-test.c (main): convert IP address to
 	network-long order before printing it.
@@ -5266,7 +11132,7 @@ Thu Jul  3 17:49:00 1997  Erez Zadok  <ezk@prometheus.soscorp.com>
 Wed Jul  2 18:19:02 1997  Erez Zadok  <ezk@starblazers.soscorp.com>
 
 	* scripts/ctl-amd.in: don't use full pathname so killproc() works
-	better.  Also run bsd44 and irix style ps programs. 
+	better.  Also run bsd44 and irix style ps programs.
 
 	* aux/macros/check_lib_funcs.m4: bug fixed: used to define usage
 	of library no matter if it was found or not.
@@ -5322,7 +11188,7 @@ Mon Jun 30 20:49:13 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
 Sun Jun 29 16:22:11 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
 
 	* rudimentary amd.conf file support included.  You may even
-	override things like os=sos5, to get "backwards" compatibilty with
+	override things like os=sos5, to get "backwards" compatibility with
 	upl102.
 
 Sat Jun 28 13:35:02 1997  Erez Zadok  <ezk@lorien.cs.columbia.edu>
@@ -5436,7 +11302,7 @@ Sat May 24 13:40:50 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
 	* scripts/ctl-hlfsd.in: new script ctl-hlfsd.  Used to start,
 	stop, or restart hlfsd.
-	
+
 	* scripts/expn.1: man page for expn command.
 
 	* scripts/ctl-amd.in: new script ctl-amd.  Used to start, stop, or
@@ -5457,7 +11323,7 @@ Sat May 24 13:40:50 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 	linux-specific mounts.  Handles fs-type specific mount-options
 	correctly.  Currently implemented: msdos, iso9660.
 
-	* amd/ops_pcfs.c (pcfs_ops): don't timeout cdfs mounts by default
+	* amd/ops_pcfs.c (pcfs_ops): don't timeout pcfs mounts by default
 	(fix for linux).
 
 	* amd/ops_cdfs.c (cdfs_ops): don't timeout cdfs mounts by default
@@ -5482,7 +11348,7 @@ Sun May 18 00:42:41 1997  Erez Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 	* hlfsd/hlfsd.c: renamed dirname to dir_name to avoid conflicts
 	with dirname() function in <string.h> on OSF systems.
 
-	* fsinfo/fsi_util.c (set_ether_if): take out extern defintion of
+	* fsinfo/fsi_util.c (set_ether_if): take out extern definition of
 	inet_addr().  It should come from <arpa/inet.h> instead.
 
 	* conf/mtab/mtab_osf.c: fixed macros and added NFS V3 specs.
@@ -5581,7 +11447,7 @@ Sat May  6 10:20:17 2000  Erez Zadok  <ezk@glory.soscorp.com>
 	possible children.
 
 	* hlfsd/homedir.c: signal handler must waitpid() for all possible
-	children. 
+	children.
 
 	* aux/macros/check_restartable_signals.m4: new macro to determine
 	if need to reinstall signal handlers per OS is better than trying
@@ -5662,7 +11528,7 @@ Sat Mar 15 19:37:48 1997  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
 Sat Mar 14 10:11:03 1997  Erez "HWank1" Zadok  <ezk@lorien.cs.columbia.edu>
 
-	* SHARED LIBRARIES: too many change to list individually.  Now,
+	* SHARED LIBRARIES: too many changes to list individually.  Now,
 	libamu can be built as a shared library, and other programs link
 	with it.
 
@@ -5858,7 +11724,7 @@ Sun Feb 23 15:25:26 1997  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 	* aux/acconfig.h: define and use HAVE_NFS_PROT_HEADERS as needed.
 
 	* aux/macros/check_nfs_prot_header.m4: new test to determine what
-	NFS protocol headers to use. 
+	NFS protocol headers to use.
 
 	* conf/nfs_prot/nfs_prot_{irix6,sunos4,bsdi2}.h: new headers to
 	complete missing system headers for NFS protocol definitions.
@@ -6141,13 +12007,19 @@ Thu Dec 19 02:08:35 1996  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 Wed Dec 18 22:20:23 1996  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
 	* converted the sources to use memset/memmove/memcmp instead of
-	bzero/becopy/bcmp.
+	bzero/bcopy/bcmp.
 
 	* ran all sources through gnu Indent w/ options specified in
 	aux/amindent.
 
 Wed Dec 11 22:19:29 1996  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
 
-	* At this point the initial genration of config.h via autoconf and
+	* At this point the initial generation of config.h via autoconf and
 	some preliminary makefiles via automake is done.  I will not begin
 	modifying sources, so it's a good time to document from here.
+
+Wed Dec 10 22:19:29 1996  Erez "HWank1" Zadok  <ezk@shekel.mcl.cs.columbia.edu>
+
+	*******************************************************************
+	*** Initial ChangeLog Entry					***
+	*******************************************************************
diff --git a/contrib/amd/FAQ b/contrib/amd/FAQ
new file mode 100644
index 0000000..18e73a3
--- /dev/null
+++ b/contrib/amd/FAQ
@@ -0,0 +1,69 @@
+		    Am-utils Frequently Asked Questions
+
+Note: we started this FAQ only on March 15, 2005; so it's not long or
+comprehensive, yet.  Amd is much older than that, and so there's a lot of
+information that's already available in other forms.  If this FAQ doesn't
+answer your questions, see information in the following sources:
+
+1. The Am-utils book: http://www.am-utils.org/docs/amd-book/
+
+2. The Am-utils user manual, which is part of the distribution and is also
+   available from www.am-utils.org.
+
+3. The www.am-utils.org Web site resources, especially the "am-utils" mailing
+   list (and its archives).
+
+4. In the am-utils distribution (always use the latest ones), see all of the
+   various README files (README, README.autofs, README.ldap, README.osx, and
+   README.y2k).  The "BUGS" file also lists useful information about bugs
+   and problems with specific OSs which affect Amd.  All of these text files
+   are also available from www.am-utils.org.
+
+5. Some FAQ questions (including newbie questions) are available here:
+   http://www.kernelcorp.com/resources_faqs.html
+
+6. Some problems are known bugs but have not been fixed yet: this are
+   listed in bugzilla in https://bugzilla.am-utils.org/
+
+If you have additions to this FAQ, please let us know at
+am-utils@am-utils.org.
+
+Thank you,
+The Am-utils development team.
+
+<FAQ>
+
+*** Linux Questions
+
+Q1. When I use Amd with Autofs and I restart Amd, how come it cannot remount
+    the Autofs partitions?
+
+A1. This is a limitation of the Linux Autofs kernel module (for both autofs
+    v2. and v3).  The Linux Autofs does not allow restarting automounted
+    points.  There's nothing Amd can do about this.  In fact, the same
+    problem exists if you use the userland "automount" daemon instead of
+    Amd.  Hopefully Autofs-v4 or the separate effort of Autofs-NG will
+    address this serious problem.
+
+    Note that Amd itself can restart autofs automounted points just fine on
+    OSs that support it, for example Solaris.
+
+
+Q2. When I use Amd, I get this console message frequently: "mount version
+    older than kernel."  Is it a problem?
+
+A2. No, it's a harmless warning message that the Linux kernel prints for NFS
+    mounts.  The intent was to alert administrators that the kernel has
+    supposedly a different version of the mount(2) code than a userland
+    program used.  This happens if you compile Amd against kernel headers
+    that are different than the kernel you're running.  If the message
+    really bothers you, then one way to "fix" the problem is to recompile
+    Amd against the same kernel headers as the running kernel.
+
+    Nevertheless, it is a relatively useless message because as far as we
+    know, the NFS v2 and v3 mount codes have been in perfect sync between
+    the userland and kernel sides, and were "standardized" for years
+    already.  This warning message caused more unnecessary worry among
+    administrators than helping alert them to legitimate problems.
+
+</FAQ>
diff --git a/contrib/amd/FREEBSD-Xlist b/contrib/amd/FREEBSD-Xlist
index bc6bc91..7baf2af 100644
--- a/contrib/amd/FREEBSD-Xlist
+++ b/contrib/amd/FREEBSD-Xlist
@@ -1,12 +1,26 @@
-$FreeBSD: src/contrib/amd/FREEBSD-Xlist,v 1.1 1999/09/18 09:25:20 obrien Exp $
-$DragonFly: src/contrib/amd/FREEBSD-Xlist,v 1.2 2003/06/17 04:23:51 dillon Exp $
+$FreeBSD: src/contrib/amd/FREEBSD-Xlist,v 1.7 2012/11/17 01:48:41 svnexp Exp $
+*LSM.am-utils
 *Makefile.*
 *README.autofs
+*README.osx
+*ac*.m4
+*.old
+*acconfig.h
 *aux
+*autom4te.cache*
 *buildall
-*configure
+*config*
+*depcomp
+*install-sh
+*lt*
+*missing
+*mkinstalldirs
+*stamp-h.in
+*amd/test1.sh
 *amd/Makefile.*
 *amq/Makefile.*
+*commit
+*cvs-server.txt
 *conf/checkmount/checkmount_aix.c
 *conf/checkmount/checkmount_default.c
 *conf/checkmount/checkmount_osf.c
@@ -26,10 +40,13 @@ $DragonFly: src/contrib/amd/FREEBSD-Xlist,v 1.2 2003/06/17 04:23:51 dillon Exp $
 *conf/fh_dref/fh_dref_sunos3.h
 *conf/fh_dref/fh_dref_sunos4.h
 *conf/fh_dref/fh_dref_svr4.h
+*conf/hn_dref/hn_dref_default.h,
 *conf/hn_dref/hn_dref_isc3.h
 *conf/hn_dref/hn_dref_linux.h
 *conf/mount/mount_aix.c
+*conf/mount/mount_aix3.c
 *conf/mount/mount_bsdi3.c
+*conf/mount/mount_default.c
 *conf/mount/mount_freebsd3.c
 *conf/mount/mount_hpux.c
 *conf/mount/mount_irix5.c
@@ -42,6 +59,7 @@ $DragonFly: src/contrib/amd/FREEBSD-Xlist,v 1.2 2003/06/17 04:23:51 dillon Exp $
 *conf/mtab/mtab_aix.c
 *conf/mtab/mtab_file.c
 *conf/mtab/mtab_isc3.c
+*conf/mtab/mtab_linux.c
 *conf/mtab/mtab_mach3.c
 *conf/mtab/mtab_osf.c
 *conf/mtab/mtab_svr4.c
@@ -50,8 +68,11 @@ $DragonFly: src/contrib/amd/FREEBSD-Xlist,v 1.2 2003/06/17 04:23:51 dillon Exp $
 *conf/nfs_prot/nfs_prot_aix4.h
 *conf/nfs_prot/nfs_prot_aix4_2.h
 *conf/nfs_prot/nfs_prot_aix4_3.h
+*conf/nfs_prot/nfs_prot_aix5_1.h
+*conf/nfs_prot/nfs_prot_aix5_2.h
 *conf/nfs_prot/nfs_prot_bsdi2.h
 *conf/nfs_prot/nfs_prot_bsdi3.h
+*conf/nfs_prot/nfs_prot_darwin.h
 *conf/nfs_prot/nfs_prot_default.h
 *conf/nfs_prot/nfs_prot_hpux.h
 *conf/nfs_prot/nfs_prot_hpux11.h
@@ -66,6 +87,8 @@ $DragonFly: src/contrib/amd/FREEBSD-Xlist,v 1.2 2003/06/17 04:23:51 dillon Exp $
 *conf/nfs_prot/nfs_prot_openbsd.h
 *conf/nfs_prot/nfs_prot_osf2.h
 *conf/nfs_prot/nfs_prot_osf4.h
+*conf/nfs_prot/nfs_prot_osf5.h
+*conf/nfs_prot/nfs_prot_osf5_1.h
 *conf/nfs_prot/nfs_prot_sunos3.h
 *conf/nfs_prot/nfs_prot_sunos4.h
 *conf/nfs_prot/nfs_prot_sunos5_3.h
@@ -73,8 +96,15 @@ $DragonFly: src/contrib/amd/FREEBSD-Xlist,v 1.2 2003/06/17 04:23:51 dillon Exp $
 *conf/nfs_prot/nfs_prot_sunos5_5.h
 *conf/nfs_prot/nfs_prot_sunos5_6.h
 *conf/nfs_prot/nfs_prot_sunos5_7.h
+*conf/nfs_prot/nfs_prot_sunos5_8.h
 *conf/nfs_prot/nfs_prot_svr4.h
 *conf/nfs_prot/nfs_prot_ultrix.h
+*conf/autofs/autofs_linux.h
+*conf/autofs/autofs_linux.c
+*conf/autofs/autofs_solaris_v1.h
+*conf/autofs/autofs_solaris_v1.c
+*conf/autofs/autofs_solaris_v2_v3.h
+*conf/autofs/autofs_solaris_v2_v3.c
 *conf/sa_dref/sa_dref_386bsd.h
 *conf/sa_dref/sa_dref_aix3.h
 *conf/sa_dref/sa_dref_aoi.h
@@ -99,7 +129,9 @@ $DragonFly: src/contrib/amd/FREEBSD-Xlist,v 1.2 2003/06/17 04:23:51 dillon Exp $
 *conf/trap/trap_stellix.h
 *conf/trap/trap_svr4.h
 *conf/trap/trap_ultrix.h
+*conf/umount/umount_aix.c
 *conf/umount/umount_default.c
+*conf/umount/umount_linux.c
 *conf/umount/umount_osf.c
 *doc/Makefile.am
 *doc/Makefile.in
@@ -114,15 +146,123 @@ $DragonFly: src/contrib/amd/FREEBSD-Xlist,v 1.2 2003/06/17 04:23:51 dillon Exp $
 *doc/am-utils.info-7
 *doc/am-utils.ps
 *doc/hlfsd.ps
+*doc/mdate-sh
 *fixmount/Makefile.*
 *fsinfo/Makefile.*
 *hlfsd/Makefile.*
 *libamu/Makefile.*
+*libamu/alloca.c
 *libamu/clnt_sperrno.c
 *libamu/memcmp.c
 *libamu/strcasecmp.c
 *libamu/strdup.c
 *libamu/strstr.c
+*libamu/strlcat.c
+*libamu/strlcpy.c
 *libamu/ualarm.c
 *mk-amd-map/Makefile.*
 *wire-test/Makefile.*
+*m4/GNUmakefile
+*m4/amdgrep*
+*m4/amindent*
+*m4/autopat*
+*m4/chop-aclocal.pl*
+*m4/copy-if-newbig*
+*m4/mk-aclocal*
+*m4/mkconf*
+*m4/rmtspc*
+*m4/update_build_version*
+*m4/macros/HEADER
+*m4/macros/TRAILER
+*m4/macros/c_void_p.m4
+*m4/macros/cache_check_dynamic.m4
+*m4/macros/check_amu_fs.m4
+*m4/macros/check_checkmount_style.m4
+*m4/macros/check_extern.m4
+*m4/macros/check_fhandle.m4
+*m4/macros/check_field.m4
+*m4/macros/check_fs_headers.m4
+*m4/macros/check_fs_mntent.m4
+*m4/macros/check_gnu_getopt.m4
+*m4/macros/check_hide_mount_type.m4
+*m4/macros/check_lib2.m4
+*m4/macros/check_map_funcs.m4
+*m4/macros/check_mnt2_cdfs_opt.m4
+*m4/macros/check_mnt2_gen_opt.m4
+*m4/macros/check_mnt2_nfs_opt.m4
+*m4/macros/check_mnttab_file_name.m4
+*m4/macros/check_mnttab_location.m4
+*m4/macros/check_mnttab_opt.m4
+*m4/macros/check_mnttab_style.m4
+*m4/macros/check_mnttab_type.m4
+*m4/macros/check_mount_style.m4
+*m4/macros/check_mount_trap.m4
+*m4/macros/check_mount_type.m4
+*m4/macros/check_mtype_printf_type.m4
+*m4/macros/check_mtype_type.m4
+*m4/macros/check_network_transport_type.m4
+*m4/macros/check_nfs_fh_dref.m4
+*m4/macros/check_nfs_hn_dref.m4
+*m4/macros/check_nfs_prot_headers.m4
+*m4/macros/check_nfs_sa_dref.m4
+*m4/macros/check_nfs_socket_connection.m4
+*m4/macros/check_os_libs.m4
+*m4/macros/check_restartable_signal_handler.m4
+*m4/macros/check_umount_style.m4
+*m4/macros/check_unmount_args.m4
+*m4/macros/check_unmount_call.m4
+*m4/macros/expand_cpp_hex.m4
+*m4/macros/expand_cpp_int.m4
+*m4/macros/expand_cpp_string.m4
+*m4/macros/expand_run_string.m4
+*m4/macros/extern_optarg.m4
+*m4/macros/extern_sys_errlist.m4
+*m4/macros/field_mntent_t_mnt_time_string.m4
+*m4/macros/func_bad_memcmp.m4
+*m4/macros/func_bad_yp_all.m4
+*m4/macros/header_templates.m4
+*m4/macros/host_macros.m4
+*m4/macros/linux_headers.m4
+*m4/macros/localconfig.m4
+*m4/macros/mount_headers.m4
+*m4/macros/name_package.m4
+*m4/macros/name_version.m4
+*m4/macros/opt_amu_cflags.m4
+*m4/macros/opt_cppflags.m4
+*m4/macros/opt_debug.m4
+*m4/macros/opt_ldflags.m4
+*m4/macros/opt_libs.m4
+*m4/macros/os_cflags.m4
+*m4/macros/os_cppflags.m4
+*m4/macros/os_ldflags.m4
+*m4/macros/package_bugreport.m4
+*m4/macros/package_name.m4
+*m4/macros/package_version.m4
+*m4/macros/save_state.m4
+*m4/macros/struct_field_nfs_fh.m4
+*m4/macros/struct_mntent.m4
+*m4/macros/struct_mnttab.m4
+*m4/macros/struct_nfs_args.m4
+*m4/macros/struct_nfs_fh.m4
+*m4/macros/struct_nfs_fh3.m4
+*m4/macros/struct_nfs_gfs_mount.m4
+*m4/macros/try_compile_anyfs.m4
+*m4/macros/try_compile_nfs.m4
+*m4/macros/try_compile_rpc.m4
+*m4/macros/type_auth_create_gidlist.m4
+*m4/macros/type_cachefs_args.m4
+*m4/macros/type_cdfs_args.m4
+*m4/macros/type_efs_args.m4
+*m4/macros/type_lofs_args.m4
+*m4/macros/type_mfs_args.m4
+*m4/macros/type_pcfs_args.m4
+*m4/macros/type_recvfrom_fromlen.m4
+*m4/macros/type_rfs_args.m4
+*m4/macros/type_svc_in_arg.m4
+*m4/macros/type_time_t.m4
+*m4/macros/type_tmpfs_args.m4
+*m4/macros/type_ufs_args.m4
+*m4/macros/type_xdrproc_t.m4
+*m4/macros/type_xfs_args.m4
+*m4/macros/type_yp_order_outorder.m4
+*m4/macros/with_addon.m4
diff --git a/contrib/amd/FREEBSD-upgrade b/contrib/amd/FREEBSD-upgrade
index 8027e2f..297ca0e 100644
--- a/contrib/amd/FREEBSD-upgrade
+++ b/contrib/amd/FREEBSD-upgrade
@@ -1,20 +1,19 @@
 # ex:ts=8
-$FreeBSD: src/contrib/amd/FREEBSD-upgrade,v 1.11 1999/11/05 11:59:47 obrien Exp $
-$DragonFly: src/contrib/amd/FREEBSD-upgrade,v 1.2 2003/06/17 04:23:51 dillon Exp $
-
-AMD (am-utils) 6.0.3s1
-    originals can be found at: ftp://shekel.mcl.cs.columbia.edu/pub/am-utils/
-    (http://www.cs.columbia.edu/~ezk/am-utils/index.html)
+$FreeBSD: src/contrib/amd/FREEBSD-upgrade,v 1.17 2012/11/17 01:48:41 svnexp Exp $
 
+AMD (am-utils) 6.1.5
+    originals can be found at: ftp://ftp.am-utils.org/pub/am-utils/
 
 For the import of AMD many files were pruned by:
 
-	tar -X FREEBSD-Xlist -xzf am-utils-6.0.3s1.tar.gz
+	tar -X FREEBSD-Xlist -xf am-utils-6.1.5.tar.gz
+
+and `find . -name '.cvsignore' -delete`
 
 Then imported by:
 
-	cvs import -m 'Virgin import of AMD (am-utils) v6.0.3s1' \
-		src/contrib/amd COLUMBIA amd_6_0_3s1
+	cvs import -m 'Virgin import of AMD (am-utils) v6.1.5' \
+		src/contrib/amd COLUMBIA amd_6_1_5
 
 After the import, a separate extraction of am-utils was GNU configured in
 the "normal" way.  The resulting config.h file should be compared with
@@ -24,8 +23,78 @@ updated as needed.
 To make local changes to amd, simply patch and commit to the main
 branch (aka HEAD).  Never make local changes on the vendor (COLUMBIA) branch.
 
-All local changes should be submitted to "amd-dev@majordomo.cs.columbia.edu"
-for inclusion in the next vendor release.
+Note, we don't trim anything in scripts/ as sysadmins may find the bits
+as a useful reference.
+
+All local changes should be submitted to "am-utils@am-utils.org" or
+https://bugzilla.am-utils.org for inclusion in the next vendor release.
+
+Local changes:
+
+	amd/amd.8
+	  r1.17 Uniformly refer to a file system as "file system"
+	  r1.16 Add the am-utils homepage to SEE ALSO
+	  r1.15 s/BSD/.Bx/ where appropriate
+	  r1.14 Avoid using parenthesis enclosure macros
+	  r1.13 split punctuation characters + misc fixes
+	  r1.12 mdoc(7)NG
+	  r1.11 Catch a left over reference to "/a"
+	  r1.10 Document change to the default mount dir.
+	  r1.9 Mention "amd -H" in the synopsis
+	  r1.8 Fix miscellaneous mdoc macro argument limit infringements
+	  r1.7 Don't refer to non-existent automount(8)
+	  r1.6 Fix errors in .Xr usage
+	  r1.3 un-mandocafied, un4.4BSD'ed
+	  r1.2 sort cross references
+	amd/amd.c
+	  r1.7 use /.amd_mnt as default for -a
+	amq/amq.8
+	  r1.9 Uniformly refer to a file system as "file system".
+	  r1.8 s/BSD/.Bx/ where appropriate.
+	  r1.6 mdoc(7)NG.
+	  r1.5 Remove reference to non-existent manpage
+	  r1.4 Fix typos
+	  r1.3 un-mandocafied, un4.4BSD'ed
+	amq/pawd.1
+	  r1.3 un-mandocafied, un4.4BSD'ed
+	  r1.2 sorting of references
+	conf/nfs_prot/nfs_prot_freebsd3.h
+	  r1.11 Userland part of nfs client/server split and cleanup
+	  r1.6 restore the standard name nfs_fh3
+	  r1.3 Fully use our own generated files for NFSv3
+	  r1.2 rpcgen our own files for NFSv3 support
+	fixmount/fixmount.8
+	  r1.8 Uniformly refer to a file system as "file system"
+	  r1.6 split punctuation characters + misc fixes.
+	  r1.5 mdoc(7)NG.
+	  r1.4 ".Mn mountd" -> ".Nm mountd"
+	  r1.3 un-mandocafied, un4.4BSD'ed
+	  r1.2 More sorting of references.
+	fsinfo/fsinfo.8
+	  r1.9 add section number to .Xr directive
+	  r1.7 Uniformly refer to a file system as "file system"
+          r1.6 split punctuation characters + misc fixes
+	  r1.5 mdoc(7)NG
+	  r1.3 describe all of the command line options
+	  r1.2 un-mandocafied, un4.4BSD'ed
+	mk-amd-map/mk-amd-map.8
+	  r1.4 removed HISTORY info from the .Os call.
+	  r1.2 un-mandocafied, un4.4BSD'ed
+	scripts/amd.conf.5
+	  r1.15 Bring man page back in shape
+	  r1.13 Uniformly refer to a file system as "file system"
+	  r1.12 Avoid using parenthesis enclosure macros
+	  r1.11 mdoc(7)NG
+	  r1.10 Fix miscellaneous mdoc macro argument limit infringements
+	  r1.8 Fix a bunch of broken cross-references
+	  r1.7 Bad reference of uname(2) -> uname(3)
+	  r1.6 Grammer fix and style nits.
+	  r1.5 xfer typo
+	  r1.4 un-mandocafied, un4.4BSD'ed
+	  r1.3 More sorting of references.
+	wire-test/wire-test.8
+	  r1.2 un-mandocafied, un4.4BSD'ed
 
+mbr@FreeBSD.org
 obrien@NUXI.com
 05-November-1999
diff --git a/contrib/amd/INSTALL b/contrib/amd/INSTALL
index 8a21b41..273fe02 100644
--- a/contrib/amd/INSTALL
+++ b/contrib/amd/INSTALL
@@ -1,108 +1,99 @@
-# -*- text -*-
-		      am-utils 6.0 compatibility list
+		      am-utils 6.1 compatibility list
 
 For each system, list if it autoconfigures, compiles, or runs.  Fill in
 email id of person who confirms the fact.  A missing entry means unverified.
-A 'no' or '!' means verified broken or nonexistent (static library).
+A 'no' or 'X' means verified broken or nonexistent (static library).
+
+SYSTEM				CONFIG	COMPILE	RUN	SHLIB	AUTOFS
+=========================	=======	=======	=======	=======	======
+alpha-dec-osf4.0f		ro	ro	ro	-	-
+alpha-dec-osf5.1		ro	ro	ro	-	-
+alpha-unknown-linux-gentoo1.4.16 ezk	ezk	ezk	ezk	-
+alphaev56-dec-osf4.0f		ezk	ezk	ezk	ezk	-
+i386-apple-darwin6.0		ezk	ezk	ezk	ezk	-
+i386-pc-bsdi2.1			ion	ion	ion	ion[X]	ion[X]
+i386-pc-linux-deb3.0		ezk	ezk	ezk	ezk	-
+i386-pc-linux-deb3.1		ezk	ezk	ezk	ezk	-
+i386-pc-linux-fc1		ezk	ezk	ezk	ezk	-
+i386-pc-linux-fc2		ezk	ezk	ezk	ezk	-
+i386-pc-linux-fc3		ezk	ezk	ezk	ezk	-
+i386-pc-linux-fc4		ezk	ezk	ezk	ezk	-
+i386-pc-linux-gentoo1.4.16	ezk	ezk	ezk	ezk	-
+i386-pc-linux-rh6.2		ion	ion	ion	ion	ion
+i386-pc-linux-rh7.1		ion	ion	ion	ion	ion
+i386-pc-linux-rh7.2		ion	ion	ion	ion	ion
+i386-pc-linux-rh7.3		ion	ion	ion	ion	ion
+i386-pc-linux-rh8.0		ezk	ezk	ezk	ezk	-
+i386-pc-linux-rh9		ion	ion	ion	ion	ion
+i386-pc-linux-rhel3		ezk	ezk	ezk	ezk	-
+i386-pc-linux-rhel4		ezk	ezk	ezk	ezk	-
+i386-pc-linux-suse8.2		ezk	ezk	ezk	ezk	-
+i386-pc-linux-suse9.1		ezk	ezk	ezk	ezk	-
+i386-pc-linux-suse9.2		ezk	ezk	ezk	ezk	-
+i386-pc-linux-suse9.3		ezk	ezk	ezk	ezk	-
+i386-pc-solaris2.10		ro	ro	ro	-	-
+i386-pc-solaris2.9		ro	ro	ro	-	-
+i386-unknown-freebsd4.10	ezk	ezk	ezk	ezk	-
+i386-unknown-freebsd4.11	ezk	ezk	ezk	ezk	-
+i386-unknown-freebsd4.8		ezk	ezk	ezk	ezk	-
+i386-unknown-freebsd4.9		ezk	ezk	ezk	ezk	-
+i386-unknown-freebsd5.0		ezk	ezk	-	ezk	-
+i386-unknown-freebsd5.1		ezk	ezk	ezk	ezk	-
+i386-unknown-freebsd5.2		ezk	ezk	ezk	ezk	-
+i386-unknown-freebsd5.2.1	ezk	ezk	ezk	ezk	-
+i386-unknown-freebsd5.3		ezk	ezk	ezk	ezk	-
+i386-unknown-freebsd5.4		ezk	ezk	ezk	ezk	-
+i386-unknown-freebsd6 (BETA5)	ezk	ezk	ezk	ezk	-
+i386-unknown-netbsd1.6A		ezk	ezk	ezk	ezk	-
+i386-unknown-netbsdelf1.6.1	ezk	ezk	ezk	ezk	-
+i386-unknown-netbsdelf1.6.2	ezk	ezk	ezk	ezk	-
+i386-unknown-netbsdelf2.0	ezk	ezk	ezk	ezk	-
+i386-unknown-netbsdelf2.0.2	ezk	ezk	ezk	ezk	-
+i386-unknown-netbsdelf3.0	ezk	ezk	ezk	ezk	-
+i386-unknown-openbsd3.3		ezk	ezk	ezk	ezk	-
+i386-unknown-openbsd3.6		ezk	ezk	ezk	ezk	-
+i386-unknown-openbsd3.7		ezk	ezk	ezk	ezk	-
+i686-apple-darwin6.6		ezk	ezk	ezk	ezk	-
+ia64-hp-hpux11.20		ezk	ezk	ezk	ezk	-
+ia64-unknown-linux-rh2.1AS	ezk	ezk	-	ezk	-
+ia64-unknown-linux-rh2.1AW	ezk	ezk	ezk	ezk	-
+ia64-unknown-linux-rhel4	ezk	ezk	ezk	ezk	-
+mips-sgi-irix6.2		ro	ro	ro	-	-[3]
+mips-sgi-irix6.5		ro	ro	ro	-	-[3]
+mips-unknown-linux-gentoo1.4.16	ezk	ezk	ezk	ezk	-
+mipsel-unknown-linux-rhPS2	ezk	ezk	ezk	ezk	-
+powerpc-apple-darwin7.6.0	ezk	ezk	ezk	ezk	-
+powerpc-apple-darwin7.7.0	ezk	ezk	ezk	ezk	-
+powerpc-apple-darwin7.8.0	ezk	ezk	ezk	ezk	-
+powerpc-apple-darwin7.9.0	ezk	ezk	ezk	ezk	-
+powerpc-apple-darwin8.2.0	ezk	ezk	ezk	ezk	-
+powerpc-ibm-aix5.1.0.0		ion	ion	ion	ion[X]	ion[1,2]
+powerpc-ibm-aix5.2.0.0		ezk	ezk	ezk	ezk	-
+powerpc-ibm-aix5.3.0.0		ezk	ezk	ezk	ezk	-
+powerpc-unknown-linux-yellowdog2.3 ezk	ezk	ezk	ezk	-
+sparc-sun-solaris2.10		ro	ro	ro	-	-
+sparc-sun-solaris2.5.1		ion	ion	ion	ion	ion[1]
+sparc-sun-solaris2.6		ion	ion	ion	ion	ion
+sparc-sun-solaris2.7		ion	ion	ion	ion	ion
+sparc-sun-solaris2.8		ion	ion	ion	ion	ion
+sparc-sun-solaris2.9		ro	ro	ro	-	-
+sparc-unknown-linux-rh62	ion	ion	ion	ion	ion
+sparc64-unknown-linux-aurora10	ion	ion	ion	ion	ion
+sparc64-unknown-linux-deb3.0	ezk	ezk	ezk	ezk	-
+sparc64-unknown-linux-gentoo1.4.16 ezk	ezk	ezk	ezk	-
+sparc64-unknown-linux-rh62	ion	ion	ion	ion	ion
+sparc64-unknown-linux-suse7.3	ezk	ezk	-	ezk	-
+x86_64-unknown-linux-rh2.9.5AS	ezk	ezk	ezk	ezk	-
+x86_64-unknown-linux-rh3.0.0AS	ion	ion	ion	ion	ion
 
-SYSTEM				AUTOCONF  COMPILE    RUN      SHLIB
-=========================	========  =========  =======  =====
-alpha-dec-osf2.1		ezk       ezk        ezk     !ezk
-alpha-dec-osf4.0		ezk       ezk        dsr[3]   ezk
-alphaev5-unknown-linux-gnu	ezk       ezk        finkel   ezk
-alphaev5-unknown-linux-gnu-rh5.2 ezk      ezk        ezk      ezk
-hppa1.0-hp-hpux11.00		ezk       ezk        ezk
-hppa1.1-hp-hpux10.10		ezk       ezk        ezk      ezk
-hppa1.1-hp-hpux10.20		ezk       ezk        ezk      ezk
-hppa1.1-hp-hpux9.01		ezk[4]    ezk[4]     nrh/ezk  ezk
-hppa1.1-hp-hpux9.05		ezk[4]    ezk[4]     nrh/ezk  ezk
-hppa1.1-hp-hpux9.07		ezk[4]    ezk[4]     nrh/ezk  ezk
-hppa2.0w-hp-hpux11.00		ezk       ezk        ezk      ezk
-i386-pc-bsdi2.1			ezk       ezk        ezk     !ezk
-i386-pc-bsdi3.0			ezk       ezk        ezk     !ezk
-i386-pc-bsdi3.1			ezk       ezk        ezk     !ezk
-i386-pc-bsdi4.0			ezk       ezk        ezk      ezk
-i386-pc-bsdi4.0.1		ezk       ezk        ezk      ezk
-i386-pc-solaris2.5.1		ezk       ezk        ezk      ezk
-i386-pc-solaris2.6		ezk       ezk        ezk      ezk
-i386-pc-solaris2.7		ezk       ezk        ezk      ezk
-i386-unknown-freebsd2.1.0	ezk       ezk        ezk
-i386-unknown-freebsd2.2.1	ezk       ezk        ezk      ezk
-i386-unknown-freebsd2.2.6	ezk       ezk        ezk      ezk
-i386-unknown-freebsd2.2.7	ezk       ezk        ezk      ezk
-i386-unknown-freebsd2.2.8	ezk       ezk        ezk      ezk
-i386-unknown-freebsd3.0		ezk       ezk        ezk      ezk
-i386-unknown-freebsdelf3.0	ezk       ezk        ezk      ezk
-i386-unknown-freebsdelf3.1	ezk       ezk        ezk      ezk
-i386-unknown-freebsdelf3.2	ezk       ezk        ezk      ezk
-i386-unknown-freebsdelf3.3	ezk       ezk        ezk      ezk
-i386-unknown-freebsdelf4.0	ezk       ezk        ezk      ezk
-i386-unknown-netbsd1.2.1	ezk       ezk        ezk      ezk
-i386-unknown-netbsd1.3		ezk       ezk        ezk      ezk
-i386-unknown-netbsd1.3.1	ezk       ezk        ezk      ezk
-i386-unknown-netbsd1.3.2	ezk       ezk        ezk      ezk
-i386-unknown-netbsd1.3.3	ezk       ezk        ezk      ezk
-i386-unknown-netbsd1.4		ezk       ezk        ezk      ezk
-i386-unknown-openbsd2.1		ezk       ezk        ezk      ezk
-i386-unknown-openbsd2.2		ezk       ezk        ezk      ezk
-i386-unknown-openbsd2.3		ezk       ezk        ezk      ezk
-i386-unknown-openbsd2.4		ezk       ezk        ezk      ezk
-i386-unknown-openbsd2.5		ezk       ezk        ezk      ezk
-i486-ncr-sysv4.3.03		ezk       ezk                 ezk
-i486-pc-linux-gnu-rh6.0		ezk       ezk        ezk      ezk
-i486-pc-linux-gnulibc1		ezk       ezk        ezk      ezk
-i486-pc-linux-gnulibc1-rh4.2	ezk       ezk        ezk      ezk
-i486-pc-linux-gnuoldld		ezk       ezk        ezk      ezk
-i586-pc-linux-gnu		ezk       ezk        ezk      ezk
-i586-pc-linux-gnu-rh5.2		ezk       ezk        ezk      ezk
-i586-pc-linux-gnu-rh6.0		ezk       ezk        ezk      ezk
-i586-pc-linux-gnu-rh6.1		ezk       ezk        ezk      ezk
-i586-pc-linux-gnulibc1		ezk       ezk        ezk      ezk
-i586-pc-linux-gnulibc1-rh4.2	ezk       ezk        ezk      ezk
-i686-pc-linux-gnu		ezk       ezk        ezk      ezk
-i686-pc-linux-gnu-rh5.2		ezk       ezk        ezk      ezk
-i686-pc-linux-gnu-rh6.0		ezk       ezk        ezk      ezk
-i686-pc-linux-gnulibc		ezk       ezk        ezk      ezk
-i686-pc-linux-gnulibc1		ezk       ezk        ezk      ezk
-m68k-hp-hpux9.00		ezk[4]    ezk[4]     nrh/ezk
-m68k-next-nextstep3		ezk       ezk        ezk     !ezk
-m68k-sun-sunos4.1.1		ezk       ezk                !ezk
-mips-dec-ultrix4.3		ro        ro         ro
-mips-sgi-irix5.2
-mips-sgi-irix5.3		ezk       ezk        ezk     ezk
-mips-sgi-irix6.2		ezk[1]    ezk[1]     ezk[1]  ezk
-mips-sgi-irix6.4		ezk       ezk        ezk     ezk
-mips-sgi-irix6.5		ezk       ezk                ezk
-powerpc-ibm-aix4.1.5.0		ezk       ezk        wpaul  !ezk
-powerpc-ibm-aix4.2.1.0		ezk       ezk        ezk    !ezk
-powerpc-ibm-aix4.3.1.0		ezk       ezk               !ezk
-powerpc-unknown-linux-gnu	jose      jose       jose
-rs6000-ibm-aix3.2		ezk       ezk        ezk
-rs6000-ibm-aix3.2.5		ezk       ezk        ezk
-rs6000-ibm-aix4.1.4.0		ezk       ezk               !ezk
-rs6000-ibm-aix4.1.5.0		ezk       ezk               !ezk
-sparc-sun-solaris2.3		ezk       ezk        ezk     ezk
-sparc-sun-solaris2.4		ezk       ezk        ezk     ezk
-sparc-sun-solaris2.5		ezk       ezk        ezk     ezk
-sparc-sun-solaris2.5.1		ezk       ezk        ezk     ezk
-sparc-sun-solaris2.6		ezk       ezk[2]     ezk     ezk
-sparc-sun-solaris2.7		ezk       ezk[2]     ezk     ezk
-sparc-sun-sunos4.1.1		ezk       ezk        ezk     ezk
-sparc-sun-sunos4.1.3		ezk       ezk        ezk     ezk
-sparc-sun-sunos4.1.3C		ezk       ezk        ezk     ezk
-sparc-sun-sunos4.1.3_U1		ezk       ezk        ezk     ezk
-sparc-sun-sunos4.1.4		ezk       ezk        ezk     ezk
-sparc-unknown-linux-gnulibc1	ezk       ezk        ezk     ezk
-sparc-unknown-netbsd1.2E	ezk       ezk        ezk
-sparc-unknown-netbsd1.2G	ezk       ezk        ezk
-sparc64-unknown-linux-gnu	ezk	  ezk	     ezk     ezk
 
 EMAIL ID LEGEND:
 
-bking:	Bevis R W King <B.King@ee.surrey.ac.uk>                
+bking:	Bevis R W King <B.King@ee.surrey.ac.uk>
 dsr:	Dan Riley <dsr@mail.lns.cornell.edu>
 ezk:	Erez Zadok <ezk@cs.columbia.edu>
 finkel:	Raphael Finkel <raphael@cs.uky.edu>
+ion:	Ion Badulescu <ion@cs.columbia.edu>
 jose:	Jose Nazario <jose@biocserver.BIOC.CWRU.Edu>
 nrh:	Nick Hall <nrh@dcs.ed.ac.uk>
 ro:	Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
@@ -112,42 +103,22 @@ wpaul:	Bill Paul <wpaul@ctr.columbia.edu>
 
 FOOTNOTES:
 
-[1] If compiling with cc on Irix 6, then use
-
-	CC="cc -32 -Wl,-woff,84" ./buildall
-
-to build (good) "old style" 32 bit code and suppress stupid linker warnings
-about unused libraries.
-
-Also, to get NFS V3 working, you need these two patches from SGI:
-
-	patch 1615: NFS over TCP 
-	patch 2041: NFS roll-up patch
-
-and then add "-p tcp" to /etc/config/nfsd.options.
-
-[2] If compiling on Solaris 2.6, you need to add -D_LARGEFILE64_SOURCE to
-CFLAGS to enable the 64bit file offset interface:
-
-	make CFLAGS="-O2 -g -D_LARGEFILE64_SOURCE"
-
-If you're using the standard configure script, it will add this flag for you
-automatically.
-
-[3] DU-4.0 may not use NFS (server-side) V3 by default.  You may need to
-adjust /etc/init.d/nfs, and change the nfsd startup line from to
- 
-	if /usr/sbin/nfsd $NUM_NFSD; then
-to
-	if /usr/sbin/nfsd -t 8 -u 8 ; then
-
-[4] HPUX 9.X has a bad /bin/sh that runs out of fixed memory allocations.
-If you use the configure script, you must run it as
-
-	/bin/ksh ./configure
-
-Also, this system has a bad /bin/make that cannot handle VPATH well.  You
-cannot use --srcdir or the buildall script with it.  I suggest you install
-GNU make or configure locally with "/bin/ksh ./configure".
-
-Erez.
+[1] Due to limitations in the Sun autofs v1 implementation, some amd features
+cannot be properly supported. More precisely, trying to access a link mount
+pointing to another amd entry will result in failure and/or deadlock.
+Ordinary nfs and link mounts work well, however.
+
+[2] AIX autofs appears to be a variant of the Sun autofs v1 protocol, but
+IBM don't provide any sort of documentation or even header files from it.
+It is currently unsupported; we may add some experimental support for it at
+some point, though it won't be pretty. Assistance from IBM-ers would be
+highly appreciated, hint hint.
+
+[3] IRIX 6 autofs uses the Sun autofs v1 protocol, too.  The header files
+are part of the onc3_eoe.sw.autofs (IRIX 6.2) or nfs.sw.autofs (IRIX 6.5)
+package, which may not be installed.  The autofs code is known to compile,
+but hasn't been run yet.  SGI's autofsd uses a barely documented system
+call, syssgi(SGI_AUTOFS_SYS, ...), which may be required to get working
+autofs support.  Additional help from SGI would be highly appreciated.
+
+Erez & Ion
diff --git a/contrib/amd/MIRRORS b/contrib/amd/MIRRORS
deleted file mode 100644
index f1f163e..0000000
--- a/contrib/amd/MIRRORS
+++ /dev/null
@@ -1,50 +0,0 @@
-# -*- text -*-
-
-			  AM-UTILS-6.0 MIRRORS
-
-Note: in case of any problems accessing the individual FTP sites, please
-contact their respective maintainers.  If you wish to be added to the
-official mirror list, please send mail to amd-dev@cs.columbia.edu with the
-full URL, maintainer's email, and geographical location.
-
-U.S.A:
-	New York (Primary Site):
-		ftp://shekel.mcl.cs.columbia.edu/pub/am-utils
-		Maintainer: ezk@cs.columbia.edu
-	Minnesota:
-		ftp://ftp.cs.umn.edu/pub/am-utils
-		Maintainer: dokas@cs.umn.edu
-	Virginia (Newport News):
-		ftp://ftp.ferginc.com/pub/unix/am-utils
-		Maintainer: Branson.Matheson@FergInc.com
-		Avoid for now: empty directory
-	Ohio (Kent State University):
-		ftp://info.mcs.kent.edu/pub/am-utils
-		Maintainer: root@mcs.kent.edu
-
-Europe:
-	Germany:
-		ftp://ftp.fu-berlin.de/pub/unix/network/am-utils
-		Maintainer: ftp-adm@ftp.fu-berlin.de
-	Germany:
-		ftp://ftp.tu-darmstadt.de/pub/networking/filesystems/am-utils/
-		Maintainer: networking@ftp.tu-darmstadt.de
-	Sweden:
-		ftp://ftp.sunet.se/pub/unix/admin/am-utils
-		Maintainer: archive@ftp.sunet.se
-	Sweden (Stockholm University, Math Depat):
-		ftp://mirror.matematik.su.se/pub/am-utils
-		Maintainer: leifj@matematik.su.se
-	UK:
-		ftp://sunsite.org.uk/packages/am-utils
-		Maintainer: lmjm@icparc.ic.ac.uk
-
-Asia:
-	Japan:
-		ftp://ftp.u-aizu.ac.jp/pub/net/amd/am-utils
-		Maintainer: ftp-admin@u-aizu.ac.jp
-
-Australia:
-	Melbourne:
-		ftp://ftp.sage-au.org.au/pub/network/filesystem/am-utils
-		Maintainer: mirror@ftp.sage-au.org.au
diff --git a/contrib/amd/MIRRORS.html b/contrib/amd/MIRRORS.html
new file mode 100644
index 0000000..0deeefe
--- /dev/null
+++ b/contrib/amd/MIRRORS.html
@@ -0,0 +1,106 @@
+<HTML>
+<HEAD>
+   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+   <META NAME="Author" CONTENT="Erez Zadok">
+   <TITLE>Am-Utils 6.x Mirror Sites</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF">
+
+<CENTER>
+<H1> Am-Utils 6.x Software Mirror Sites</H1></CENTER>
+
+Note: in case of any problems accessing the individual FTP sites, please
+contact their respective maintainers.  If you wish to be added to the
+official mirror list, please send mail to <A
+HREF="mailto:am-utils-developers@am-utils.org">am-utils-developers@am-utils.org</A> with the
+full URL, maintainer's email, and geographical location.
+
+<P>
+
+<H2>North America</H2>
+<UL>
+
+<LI> New York (Stony Brook, Primary Site)
+ <UL>
+ <LI> FTP: <A
+ HREF="ftp://ftp.am-utils.org/pub/am-utils">ftp.am-utils.org</A>.
+ Contact person in case of problems <A
+ HREF="mailto:am-utils-developers@am-utils.org">am-utils-developers@am-utils.org</A>.
+ </LI>
+ </UL>
+
+<LI> Minnesota
+ <UL>
+ <LI> FTP: <A
+ HREF="ftp://ftp.cs.umn.edu/pub/am-utils">ftp.cs.umn.edu</A>.
+ Maintainer <A HREF="mailto:dokas@cs.umn.edu">dokas@cs.umn.edu</A>.
+ </LI>
+ </UL>
+
+<LI> Florida (University of Florida)
+ <UL>
+ <LI> FTP: <A HREF="ftp://ftp.cise.ufl.edu/pub/mirrors/am-utils">ftp.cise.ufl.edu</A>.
+  Maintainer <A HREF="mailto:mirror@cise.ufl.edu">mirror@cise.ufl.edu</A>.
+ </LI>
+ </UL>
+
+</UL>
+
+<H2>Europe</H2>
+<UL>
+
+<LI> Germany
+ <UL>
+ <LI> FTP: <A HREF="ftp://ftp.fu-berlin.de/unix/network/am-utils">ftp.fu-berlin.de</A>.
+  Maintainer <A HREF="mailto:ftp-adm@ftp.fu-berlin.de">ftp-adm@ftp.fu-berlin.de</A>.
+ </LI>
+ <LI> FTP: <A HREF="ftp://ftp.tu-darmstadt.de/pub/networking/filesystems/am-utils/">ftp.tu-darmstadt.de</A>.
+  Maintainer <A HREF="mailto:networking@ftp.tu-darmstadt.de">networking@ftp.tu-darmstadt.de</A>.
+ </LI>
+ </UL>
+
+<LI> Sweden
+ <UL>
+ <LI> FTP: <A HREF="ftp://ftp.sunet.se/pub/unix/admin/am-utils">ftp.sunet.se</A>.
+ Maintainer <A HREF="mailto:archive@ftp.sunet.se">archive@ftp.sunet.se</A>.
+ </LI>
+ </UL>
+
+<LI> UK
+ <UL>
+ <LI> FTP: <A HREF="ftp://sunsite.org.uk/package/am-utils">sunsite.org.uk</A>.
+ Maintainer <A HREF="mailto:lmjm@icparc.ic.ac.uk">lmjm@icparc.ic.ac.uk</A>.
+ </LI>
+ </UL>
+
+</UL>
+
+<H2>Asia</H2>
+<UL>
+
+<LI> Japan
+ <UL>
+ <LI> FTP: <A HREF="ftp://ftp.u-aizu.ac.jp/pub/net/amd/am-utils">ftp.u-aizu.ac.jp</A>.
+  Maintainer <A HREF="mailto:ftp-admin@u-aizu.ac.jp">ftp-admin@u-aizu.ac.jp</A>.
+ </LI>
+
+ <LI> FTP: <A HREF="ftp://core.ring.gr.jp/pub/net/am-utils/">core.ring.gr.jp</A>.
+  Maintainer <A HREF="mailto:ftpadmin@ring.gr.jp">ftpadmin@ring.gr.jp</A>.
+ </LI>
+
+ <LI> FTP: <A HREF="ftp://ftp.ring.gr.jp/pub/net/am-utils/">ftp.ring.gr.jp</A>.
+  Maintainer <A HREF="mailto:ftpadmin@ring.gr.jp">ftpadmin@ring.gr.jp</A>.
+ </LI>
+ </UL>
+</UL>
+
+<HR>
+<I> Last updated: Jan 5, 2004</I>
+
+</BODY>
+</HTML>
+
+<!---
+ <LI> FTP: <A HREF="X">X</A>.
+ Maintainer <A HREF="mailto:X">X</A>.
+-->
diff --git a/contrib/amd/MIRRORS.txt b/contrib/amd/MIRRORS.txt
new file mode 100644
index 0000000..b5093e8
--- /dev/null
+++ b/contrib/amd/MIRRORS.txt
@@ -0,0 +1,60 @@
+			  AM-UTILS-6.x MIRRORS
+
+Note: in case of any problems accessing the individual FTP sites, please
+contact their respective maintainers.  If you wish to be added to the
+official mirror list, please send mail to am-utils-developers@am-utils.org
+with the full URL, maintainer's email, and geographical location.
+
+U.S.A:
+	New York (Stony Brook, Primary Site):
+		ftp://ftp.am-utils.org/pub/am-utils
+		Maintainer: ezk@am-utils.org
+	Minnesota:
+		ftp://ftp.cs.umn.edu/pub/am-utils
+		Maintainer: dokas@cs.umn.edu
+#Avoid for now: empty directory
+# 	Virginia (Newport News):
+# 		ftp://ftp.ferginc.com/pub/unix/am-utils
+# 		Maintainer: Branson.Matheson@FergInc.com
+#server gone? (Jan 5, 2004)
+# 	Ohio (Kent State University):
+# 		ftp://info.mcs.kent.edu/pub/am-utils
+# 		Maintainer: root@mcs.kent.edu
+	Florida (University of Florida)
+		ftp://ftp.cise.ufl.edu/pub/mirrors/am-utils
+		Maintainer: mirror@cise.ufl.edu
+
+Europe:
+	Germany:
+		ftp://ftp.fu-berlin.de/unix/network/am-utils
+		Maintainer: ftp-adm@ftp.fu-berlin.de
+	Germany:
+		ftp://ftp.tu-darmstadt.de/pub/networking/filesystems/am-utils/
+		Maintainer: networking@ftp.tu-darmstadt.de
+	Sweden:
+		ftp://ftp.sunet.se/pub/unix/admin/am-utils
+		Maintainer: archive@ftp.sunet.se
+# not responding (Jan 5, 2004)
+# 	Sweden (Stockholm University, Math Depat):
+# 		ftp://mirror.matematik.su.se/pub/am-utils
+# 		Maintainer: leifj@matematik.su.se
+	UK:
+		ftp://sunsite.org.uk/package/am-utils
+		Maintainer: lmjm@icparc.ic.ac.uk
+
+Asia:
+	Japan:
+		ftp://ftp.u-aizu.ac.jp/pub/net/amd/am-utils
+		Maintainer: ftp-admin@u-aizu.ac.jp
+	Japan:
+		ftp://core.ring.gr.jp/pub/net/am-utils/
+		Maintainer: ftpadmin@ring.gr.jp
+	Japan:
+		ftp://ftp.ring.gr.jp/pub/net/am-utils/
+		Maintainer: ftpadmin@ring.gr.jp
+
+# gone? (Jan 5, 2004)
+# Australia:
+# 	Melbourne:
+# 		ftp://ftp.sage-au.org.au/pub/network/filesystem/am-utils
+# 		Maintainer: mirror@ftp.sage-au.org.au
diff --git a/contrib/amd/NEWS b/contrib/amd/NEWS
index c33358f..5cde984 100644
--- a/contrib/amd/NEWS
+++ b/contrib/amd/NEWS
@@ -1,4 +1,731 @@
-# -*- text -*-
+*** Notes specific to am-utils version 6.1.5
+
+New amd.conf global parameter: nfs_allow_any_interface.  By default it is
+set to 'no' which means that Amd accepts local NFS packets only from
+127.0.0.1.  If set to 'yes' then 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.
+
+Add support for specifying the host to match in the mount selectors netgrp
+and netgrpd.  Now one can use either netgrp(<group-name>) or
+netgrp(<group-name>,<host-name>).
+
+- Bugs fixed:
+	* handle old-style filehandles correctly (for mount points longer
+	  than 28 chars)
+	* don't turn off attribute cache for regular NFS mounts (improves
+	  performance)
+	* detect G/DBM support via gdbm_compat library (Debian)
+	* detect NDBM support in libc (FreeBSD 6)
+
+- minor new ports:
+	i386-unknown-freebsd6.1 (RELEASE)
+	i386-unknown-openbsd3.9
+	powerpc-apple-darwin8.6.0
+
+*** Notes specific to am-utils version 6.1.4
+
+Support new mount options for type:=pcfs mounts: longname, nowin95,
+shortname, user=N, group=N, mask=N, and dirmask=N.
+
+Two new amd.conf [global] parameters: nfs_retry_interval_toplvl and
+nfs_retransmit_counter_toplvl.  They are similar to nfs_retry_interval and
+nfs_retransmit_counter, and allow you to set the "timeo" and "retrans" NFS
+mount parameters, respectively, but ONLY for Amd's top-level mounts (which
+are NFSv2/UDP currently).  This is useful because on some systems you may
+wish to set these parameters differently than the OS default, so as to
+better tune Amd's responsiveness under heavy scheduler loads.
+
+- minor new ports:
+	i386-pc-linux-fc5 (Fedora Core 5)
+	i386-pc-linux-suse10.1 (beta 8)
+	i386-unknown-freebsd6.0 (RELEASE)
+	i386-unknown-netbsdelf2.1
+	i386-unknown-netbsdelf3.0 (RELEASE)
+	i386-unknown-openbsd3.8
+	powerpc-apple-darwin8.5.0
+
+- Bugs fixed:
+	* one serious memory leak in amfs_generic (caught by Coverity)
+	* assorted potential (but rare) NULL pointer dereferences (Coverity)
+	* correctly print nfs_args->addr info (sin_family/port/addr)
+	* pawd should resolve path repeatedly until no more to do
+	* use-after-free bug in amfs_lookup_mntfs (Coverity)
+
+*** Notes specific to am-utils version 6.1.3
+
+- Bugs fixed:
+	* amq should de-register properly on exit
+	* convert all sprintf to safer xsnprintf
+	* convert all strcat to safer xstrlcat
+	* convert all strcpy to safer xstrlcpy
+	* fix three buffer overruns in expand_op (amd/opts.c)
+	* pawd was trying UDP only, now try TCP if UDP failed
+
+Moved pawd's path-matching functionality into Amd, where it can be done a
+lot more efficiently (we no longer need to construct and send the whole
+mounted tree, only to match small parts of it).  This will lessen the CPU
+and network load on systems that use pawd heavily, and also minimize the
+chance that we exceed default or hard-coded UDP/TCP RPC packet sizes.
+
+*** Notes specific to am-utils version 6.1.2.1
+
+- Bugs fixed:
+	* properly turn off the attrcache in freebsd and openbsd
+	* can turn off attrcache on netbsd, but need kernel patch, see
+	  README.attrcache
+	* pawd goes into an infinite loop on type:=auto
+	* consistent search for file system mnttab/mount names
+
+*** Notes specific to am-utils version 6.1.2
+
+MAJOR BUG FIXES: Synchronize Amd's view of its file systems with the
+kernel's NFS client-side DNLC/dcache.  Amd changes its view when it reloads
+maps (automatically or via "amq -f") because new map entries could be added,
+old one removed, or existing ones changed.  Amd also changes its view when a
+simple entry has expired and was flushed, or was forced out via "amq -u".
+Amd was not updating the mtime of its parent directory (often the amd
+automount point): this resulted in the kernel re-using cached entries, which
+are now possibly stale.  Many users had seen this problem in the form of
+occasional ESTALE errors, or dangling/broken automounted symlinks,
+especially on systems under heavy use.  To tell the kernel to ignore (flush)
+its old entries for an directory, the mtime of the directory must be updated
+(monotonically incremented).  Amd was indeed doing so in several places, but
+unfortunately it was using time(2) which only provides a one-second
+resolution clock: this was fine a decade ago, but not good enough on today's
+fast systems; using only a one-second resolution clock meant that on busy
+systems that invoke Amd many times a second, some rapidly changing entries
+do not get flushed from the kernel, and the kernel thus uses stale entries.
+The solution to all of these was to rework the whole clock timer updates to
+use gettimeofday(), using a micro-second resolution timer, and to use that
+time whenever Amd needs to update an mtime/atime/ctime of any node.
+Finally, we now update the mtime in places that were never updated before
+(when a whole map is flushed or a single entry times out).
+
+Warning: some OSs, we discovered, are incapable of turning off their
+NFS attribute cache entirely.  This means that Amd cannot work fully
+reliability on these systems, not under heavy load.  This is documented in
+detail in the README.attrcache file included with this distribution.
+
+Include test-attrcache script to test the NFS attribute cache behavior using
+Amd.
+
+Tell syslog not to log automatically to /dev/console; it's unfriendly.  If
+user really wants to, they can set it in /etc/syslog.conf.
+
+- minor new ports:
+	i386-pc-linux-deb3.1
+	i386-unknown-netbsdelf3.0
+	powerpc-apple-darwin8.2.0
+
+- bugs fixed:
+	* minor documentation corrections
+
+*** Notes specific to am-utils version 6.1.1
+
+New amd.conf global parameter: forced_unmounts (default to "no").  If set to
+"yes," and the client OS supports forced or lazy unmounts, then Amd will
+attempt to use them if it gets any of three serious error conditions when
+trying to unmount an existing mount point or mount on top of one: EIO,
+ESTALE, or EBUSY.  This could be useful to recover from serious conditions
+such as hardware failure of mounted disks, or NFS servers which are down
+permanently, were migrated, or changed their IP address.  Only
+"type:=toplvl" mounts hung with EBUSY are forcibly unmounted using this
+option: this is useful to ensure that a new Amd can mount itself even if a
+previous Amd died and left its mount points hung, or to force Amd to
+shutdown cleanly, even if some processes (i.e., user shells) have their CWD
+on Amd's own mount point.  This functionality is available for Linux, BSD44
+systems, Solaris, OSF/1, and partially for AIX.
+
+New amd.conf global parameter: truncate_log (default to "no").  If set to
+"yes", then Amd will truncate the log file (if it's a regular file) on
+startup.  This could be useful when conducting extensive testing on Amd maps
+(or Amd itself) and you don't want to see log data from a previous run in
+the same file.
+
+- minor new ports:
+	i386-pc-linux-fc4
+	i386-pc-linux-suse9.3
+	i386-pc-linuxoldld-deb3.1
+
+- bugs fixed:
+	* safer mtab handling for Linux (locks + handles /proc/mounts)
+	* small compile problems on Solaris 6 (rpcvers_t)
+	* small compile problems on HPUX 10 (h_errno)
+	* possibly missing definition of INADDR_NONE in wire.c
+	* extern for sleep(3) may be missing on older gcc systems
+	* updated nfs_args structure on aix4.
+	* possible running off end of exported_ap[] array.
+	* buffer overflow in pawd.
+	* aix4 clean build.
+	* use strlcat/snprintf in a few places for safety.
+	* recover from IP address change of a down NFS server
+	* don't discard restarted mntfs that was used.
+
+*** Notes specific to am-utils version 6.1
+
+- bugs fixed:
+	* set timeo/retrans for type:=nfs only if user asked
+
+Also, if you want to know what's new in 6.1 compared to 6.0.x, it's
+EVERYTHING below this line, up to "6.0.4."  Yes, that's a lot of stuff.
+
+*** Notes specific to am-utils version 6.1-rc7
+
+Remove alloca from am-utils, and rewrite code that used it.
+
+Assorted minor code cleanups.
+
+- minor new ports:
+	alpha-unknown-linux-gentoo1.4.16
+	alphaev56-dec-osf4.0f (using both cc and gcc)
+	mips-sgi-irix6.5 (using both cc and gcc)
+	mips-unknown-linux-gentoo1.4.16
+	sparc64-unknown-linux-gentoo1.4.16
+
+- bugs fixed:
+	* getwire() detects networks correctly on OSF/1
+
+*** Notes specific to am-utils version 6.1-rc6
+
+- minor new ports:
+	i386-pc-linux-deb3.0
+	i386-pc-linux-gentoo1.4.16
+	i386-pc-linux-suse9.2
+	i386-unknown-freebsd5.4
+	i386-unknown-netbsdelf2.0.2
+	i386-unknown-openbsd3.7
+	powerpc-unknown-linux-yellowdog2.3
+
+- bugs fixed:
+	* minor compile error of nfs_subr.c on some systems.
+	* AIX 5.2/5.3 PPC compile fixes.
+
+*** Notes specific to am-utils version 6.1-rc5
+
+For NetBSD systems, $os used to say "netbsdelf1" or "netbsdelf2."  Now it
+just says "netbsd."
+
+- minor new ports:
+	powerpc-apple-darwin7.9.0
+
+- bugs fixed:
+	* silly (but nasty) null pointer dereferencing
+	* improved fix for '-opts' syntax for resetting map options
+
+*** Notes specific to am-utils version 6.1-rc4
+
+- bugs fixed:
+	* check for "macosx" in M4 macros properly
+	* minor memory leaks (thanks to Valgrind)
+
+*** Notes specific to am-utils version 6.1-rc3
+
+Minor fix to configure.in.  Reran bootstrap to get a working configure
+script that indeed checks for certain Linux nfs/autofs headers.
+
+*** Notes specific to am-utils version 6.1-rc2
+
+New amd.conf global parameter: normalize_slashes (default to "yes").  If set
+to "no," then Amd will not condense repeated slashes or remove trailing ones
+from strings representing pathnames.  This is sometimes useful with SMB
+mounts, which often require multiple slash characters in pathnames.
+
+Using a custom version of strlcpy instead of strncpy (but only where it
+makes sense), to minimize string overflow changes.  Audited all use of
+strncpy/strlcpy to ensure safety.
+
+On Apple machines, use "powerpc" for $arch, instead of "Power Macintosh".
+Also, use sw_vers to find out more appropriate OS name (macosx) and OS
+version (10.3.x) than uname(3) reports.
+
+- minor new ports:
+	powerpc64-unknown-linux-rhel4
+	powerpc64-unknown-linux-sles9
+
+- bugs fixed:
+	* pawd handles all file systems
+	* fix double-free in type:=nfsx
+	* timeo and retrans shouldn't be set for type:=toplvl
+	* fix inconsistency in handling filehandle generation number
+	* document proper use of hosts.allow (don't spawn)
+	* single dash '-' map entry now resets the defaults
+
+*** Notes specific to am-utils version 6.1-rc1
+
+- minor new ports:
+	i386-pc-linux-fc2 (Fedora Core 2).
+	i386-pc-linux-fc3 (Fedora Core 3).
+	i386-pc-linux-rhel3
+	i386-pc-linux-rhel4
+	i386-pc-linux-suse8.2
+	i386-pc-linux-suse9.1
+	i386-pc-solaris2.10
+	i386-unknown-freebsd4.8
+	i386-unknown-freebsd4.9
+	i386-unknown-freebsd4.10
+	i386-unknown-freebsd4.11
+	i386-unknown-freebsd5.1 (5.1-RELEASE)
+	i386-unknown-freebsd5.2 (5.2-RELEASE)
+	i386-unknown-freebsd5.2.1 (5.2.1-RELEASE)
+	i386-unknown-freebsd5.3 (5.3-RELEASE)
+	i386-unknown-freebsd6.0 (6.0-CURRENT-SNAP001)
+	i386-unknown-netbsdelf1.6.1
+	i386-unknown-netbsdelf2.0
+	i386-unknown-openbsd3.6
+	ia64-hp-hpux11.20
+	ia64-unknown-linux-rhel4
+	mipsel-unknown-linux-rhPS2 (Linux on Sony PlayStation 2)
+	powerpc-apple-darwin7.6.0
+	powerpc-apple-darwin7.7.0
+	powerpc-apple-darwin7.8.0
+	powerpc-ibm-aix5.2.0.0
+	powerpc-ibm-aix5.3.0.0
+	sparc-sun-solaris2.10
+	sparc64-unknown-linux-deb3.0
+	x86_64-unknown-linux-rh2.9.5AS
+
+- support for executable maps ala Sun automounter.  Set map_type=exec in
+  amd.conf, and map_name to a program/script that takes a key as argv[1],
+  and returns key-value pair on stdout.  See also exec_map_timeout [global]
+  parameter which defines how many seconds (default 10 sec) Amd will wait
+  for an executable map program to return output before timing out.  See
+  am-utils manual for full details.
+
+- new amd.conf parameter "nfs_allow_insecure_port".  Used to work around
+  bugs in certain kernels, which cause them to try and talk to amd from
+  unprivileged ports.
+
+- new amd.conf parameter: localhost_address.  Used to override the localhost
+  (often 127.0.0.1) address Amd uses to connect to for the local NFS server
+  and RPC server.
+
+- new amd.conf [global] parameter: domain_strip (default "yes").  If set to
+  "no," Amd won't strip domain names from host names, which is useful if
+  your Amd maps are served by multiple domains and you want to tell from the
+  logs which exact host did what.
+
+- new amd.conf [global] parameter: auto_attrcache (default to 0).  Sets
+  Amd's own NFS attribute-cache timeout in seconds.  A value of 0 turns off
+  attribute caching, meaning that 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).  If you're concerned, set this to something
+  greater than zero (a value of 1 second is currently recommended).
+  Warning: if you set this option to any non-zero value, especially a large
+  value, and you get ESTALE errors on your particular OS, then set this
+  value back to 0 seconds.
+
+- four new amd.conf [global] parameters, similar to nfs_retry_interval and
+  nfs_retransmit_counter, which allow you to set the "timeo" and "retrans"
+  NFS mount parameters, respectively.  Now you can set those parameters
+  globally and separately for UDP vs. TCP, using any of these:
+  nfs_retry_interval_udp, nfs_retransmit_counter_udp nfs_retry_interval_tcp,
+  and nfs_retransmit_counter_tcp.
+
+- new amd.conf [global] parameter: preferred_amq_port.  Allows you to select
+  the UDP+TCP port that Amd's amq service will use with the RPC portmapper.
+  Useful with firewalls and NAT'ed environments.
+
+- new amd.conf option "debug_mtab_file".  Allows user to define the mtab
+  file during debug-mtab mode.  The default path is "/tmp/mnttab".
+
+- new function selector xhost(ARG) which will match ARG against the current
+  host name.  This works even if ARG is a CNAME (unlike the host==ARG
+  selector).
+
+- support restarting the automounter's own mount points (only over NFS,
+  for now).
+
+- fully support WebNFS as per RFC 2054.  It now tries v3/TCP first, falling
+  back to v2/UDP if this doesn't work.  The "webnfs" pseudo-mount options
+  has been renamed (again) to "public" to match Solaris 2.
+
+- restructured the restarting of already-mounted filesystems, in the process
+  also fixing a problem with restarting nfsx components.
+
+- support escaped slashes, needed for SMB mounts.  Use '\\\/\\\/' in a
+  string to get a double slash.
+
+- amd -v now prints domain, host, and hostd values: foo, example.com, and
+  foo.example.com, respectively.
+
+- On Linux, if umount(2) failed with EIO or ESTALE, try the new umount2(2)
+  system call with MNT_FORCE+MNT_DETACH.  This could be quite helpful to
+  unmounting hung mount points that otherwise cannot be fixed without a
+  reboot.
+
+- The ping=N mount option now works.  N defaults to 30 seconds for all NFS
+  servers.  It can now be set to any value for each server separately.
+  Setting it to a large value can reduce the amount of NFS_NULL chatter on
+  your network considerably, especially in large sites.  Setting this to -1
+  will turn off pings for that server (useful in NFS-HA setups).  Setting N
+  to 0 will pick the default ping value in Amd (currently 30 seconds).  Note
+  that if you have multiple 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).  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.
+
+- file system inheritance code restructured, so it's no longer a pseudo file
+  system, but actually integrated into Amd (as it should have been).
+
+- for type:=program, the "umount" program doesn't have to be defined; it'll
+  default to "unmount ${fs}".
+
+- "amd -v" now prints the distribution name if it's known (e.g., rh9, fc3,
+  suse8, etc.).
+
+- bugs fixed:
+	* various memory management problems (leaks, etc)
+	* fixed nfsx support
+	* fixed a race involving late replies to network queries which
+	  arrive after the file system has already been mounted
+	* recognize pcfs_args_t fields in FreeBSD 5
+	* recognize other mount types in pawd: host, linkx, and nfsx
+	* allow exactly one of umount and unmount in type:=program
+	* race condition between calls to mntctl() on AIX
+	* plock/mlockall wasn't inherited by fork(); moved after
+	  daemonizing.
+	* fix inconsistency between Socket and TLI RPC timeouts.
+	* don't warn when couldn't rmdir a dir with a readonly ancestor.
+	* avoid hangs of amd in ctl-amd (must chdir to /)
+	* workaround occasional daemonizing problems (parent won't die)
+	* don't hang on exit if debug_options=mtab was used
+	* utimeout=N mount option works with non-nfs types (ufs, pcfs, etc.)
+	* SEGV (null pointer deref) in type:=program and type:=cachefs
+	* unmount_on_exit of type:=program caused amd to hang
+	* match amd2ldif output with ldap.schema
+
+*** Notes specific to am-utils version 6.1b4
+
+- minor new ports:
+	i686-apple-darwin6.6
+
+- speed up the recovery of inherited (restarted) filesystems by using the
+  proper waiting channels
+
+- added support for mounting webnfs filesystems, see entry below. It doesn't
+  do any probing currently, so it will default to v2/UDP unless another
+  version and/or protocol are explicitly specified.
+
+- pseudo-mount option "ignore_portmapper" renamed to "webnfs"
+
+- bugs fixed:
+	* properly time out autofs filesystems on Linux
+	* link mounts with relative targets weren't working on autofs
+	* the link side of the nfsl file system wasn't working on autofs
+	* umount code was accidentally turning all symlinks into directories
+	  during attempted umounts, causing stale filehandles
+	* various minor build fixes for "impossible" configurations
+	* prevent ldap code from dereferencing a null pointer
+
+*** Notes specific to am-utils version 6.1b3
+
+- new amd.conf option autofs_use_lofs, set by default to "yes".  "yes" means
+  using in-place mounts (lofs, bind mounts, etc.), thus utilizing one of
+  Autofs's main advantages.  "no" means using symlinks instead, which has
+  the "/bin/pwd" problem and certain efficiency issues on Solaris 2.6+ and
+  is also not supported on Solaris Autofs v1 and derivatives; however, the
+  autofs code that uses symlinks is simpler and more thoroughly tested.
+
+- new amd.conf option map_default (can be used in [global] and overwritten
+  in the per-map section).  This will overwrite the /defaults entry of the
+  map itself, to allow people to set defaults in amd.conf (useful when you
+  cannot control your amd maps, or you'd rather not modify them globally).
+
+- for type:=program, you can use either unmount:=XXX or umount:=XXX (but not
+  both).  This new 'unmount' name is an alias for convenience.
+
+- fixed the "multiple matching sub-entries in a map entry" semantics to try
+  mounting those sub-entries one by one, until either one succeeds or all
+  fail.  The old semantics of trying to mount everything in parallel and use
+  the one that mounted fastest hasn't worked in a long time; in fact, 6.0
+  currently simply ignores all but the first matching sub-entry.
+
+- made amd fail much faster (instantly, in fact) if the remote server
+  doesn't have a functional portmapper or NFS service.  Also reduced the
+  total timeout to 3 seconds for a completely downed server.
+
+- new pseudo-mount option "ignore_portmapper"; not very useful currently,
+  will make more sense when we also accept hard-coded ports for mountd and
+  nfsd.
+
+- amd will no longer query the portmapper for all possible NFS versions and
+  protocols if the user requested to use specific ones.
+
+- increased the major number for the library, so that 6.0 and 6.1 can't
+  share libraries anymore.
+
+- support tcpd/libwrap tcpwrappers.  If your system supports libwrap, then
+  you can use /etc/hosts.allow and /etc/hosts.deny to control remote Amq
+  access to Amd.  The new amd.conf parameter use_tcpwrappers is set to "yes"
+  by default.
+
+- support NULL entries in Hesiod maps, if they start with a ".".
+
+- code reorganization
+
+- documentation cleanup, corrections, and general updates.  Better
+  references to all man pages.  Support newer texi2html.  Proper building of
+  DVI and PSI files.  Allow building of am-utils manual in one long Web
+  page.
+
+- minor new ports:
+
+	ia64-unknown-linux-rh2.1AS (Red Hat Itanium Advanced Server)
+	i386-unknown-freebsd5.0 (5.0-RELEASE)
+	sparc64-unknown-linux-suse7.3
+	i386-unknown-netbsdelf1.6.1
+	i386-unknown-openbsd3.3
+	i386-pc-solaris2.9
+
+- bugs fixed:
+
+	* autofs mode on Linux was segfaulting on a silly error (and noone
+	  complained, which proves that I'm probably the only one testing
+	  these beta releases, tsk tsk).
+	* fixed handling of host entries over autofs.
+	* fixed handling of nfsl entries over autofs.
+	* the matching in find_mntfs() was causing problems for inherited
+	  filesystems, so make an exception for them. Tighten the
+	  matching even more, to take into account the f/s type as well.
+	* recognize xlatecookie mnttab option on netbsd
+	* document Solaris lex bug (use flex)
+	* document AIX 5.x NFS bug (need patch)
+	* document Solaris 8 autofs version change (need to fix system
+	  header file)
+	* ensure lex doesn't run out of output slots
+	* support GNU flex-2.5.31+
+	* force version.texi to be rebuilt unconditionally
+	* mk-amd-map open db file exclusively (security)
+	* turn off maintainer-only rules in distros
+	* don't core dump if log_file is NULL (Solaris)
+	* don't include malloc.h if stdlib.h exists
+	* recognize file system failures (EIO) upon reading file maps
+
+*** Notes specific to am-utils version 6.1b2
+
+- new mount flag "softlookup", which determines how amd will respond to
+  lookups of NFS shares already mounted (return a valid symlink or return
+  EIO). The default, if "softlookup" is not specified, depends on whether the
+  mount is "soft" or "hard".
+
+- return EIO instead of ENOENT if amd thinks the server is down; this allows
+  well-written applications to sleep and retry the operation.
+
+- minor new ports:
+
+	i386-apple-darwin6.0
+	i386-pc-linux-rh8.0
+	ia64-unknown-linux-rh2.1AW
+	sparc-sun-solaris2.9
+
+- automatic support for loop mounts on Linux (deprecates the "loop" mount
+  option)
+
+- new amd.conf parameter ldap_proto_version (default 2) for setting the LDAP
+  protocol version to use.
+
+- bugs fixed:
+
+	* redundancy mode (multiple servers for the same share) wasn't working
+	* non-autofs mode had some rather nasty hangs on downed file servers
+	* double-free'ing problem in assign_error_mntfs and free_continuation
+	* free'ing non-malloc'ed memory in amfs_auto_mount
+	* late server ping replies were not ignored
+	* amfs_auto_lookup_mntfs wasn't propagating errors up to callers
+	* autofs-v4 on Solaris 9 works
+	* handle std{in,out,err} correctly when releasing controlling tty
+	  (for real this time)
+	* don't cast pointers between enum_t and u_long, it doesn't work on
+	  64-bit big-endian platforms
+	* fix compile problem with mlockall() on Darwin
+
+*** Notes specific to am-utils version 6.1b1
+
+- Major Autofs work
+	Partial support for Sun Autofs v1
+	Documented known problems with Sun Autofs v1 (possible deadlocks)
+	Fixes for Sun Autofs v2/v3
+	Preliminary support for Sun Autofs v4 (Solaris 9)
+	Kernel-based expirations for Linux Autofs
+
+- Minor new ports:
+	powerpc-ibm-aix5.1.0.0
+	i386-unknown-netbsd1.6A
+
+- Work around IBM's NFSv3 ABI change in aix4.3
+
+- trivial regression test suite started: run "make check" on a built
+  am-utils to execute tests.  Currently only one test which checks to see if
+  "amd -v" executes correctly.
+
+- new command line option "amd -A arch" to overwrite the value of $arch.
+
+- bugs fixed:
+
+	* Linux loop mounts of ISO images
+	* assorted LDAP fixes
+	* strerror not found on some systems
+	* small fixes for hpux9 and aix43
+	* exclude ldap/hesiod support unless both libraries+headers exist
+	* fully support "xlatecookie" mount option
+	* security: if -D noamq option, don't listen on socket.
+
+*** Notes specific to am-utils version 6.1a5:
+
+- browsable_dirs support for Solaris autofs, *without* mount storms!
+
+- new amd.conf global parameter: map_reload_interval (default 1 hour).
+  Determines how often Amd checks to see if maps have changed at the source
+  (and then reloading only those that have changed).
+
+- "amd -v" now lists bug-reporting address.
+
+- assorted code cleanups and porting to use latest versions of GNU
+  Autotools.
+
+- opts:=loop works for type:=cdfs, for mounting ISO-9660 files on Linux.
+
+- bugs fixed:
+
+	* fixed sublink support in Linux autofs (broken in a4)
+	* hlfsd takes uid 0's home from root's passwd entry instead of
+	  defaulting to '/'
+	* (not really our bug) Linux ignores the microseconds field in
+	  mtime, so hlfsd and amd need to increment the seconds field all
+	  the time to prevent symlink caching
+	* generic map parsing bug which was rejecting a numerical mount
+	  option if it was the last option in the string.
+	* file descriptor leak in Linux autofs.
+	* "nolock" is an NFS mount option, not a generic one.
+	* use mlockall(2) on systems that have it, for plock=yes.  Now
+	  pinning Amd's pages in memory works on Linux.
+	* ctl-amd/ctl-hlfsd correctly refer to @sysconfdir@ for alternate
+	  location of configuration files.
+
+*** Notes specific to am-utils version 6.1a4:
+
+- full autofs support for Solaris 2.[67], including symlinks, sublinks and
+  direct mounts
+
+- fixed mount/umount deadlock in Linux autofs
+
+- fixed sublinks in Linux autofs
+
+- support for network/netmask pairs in the in_network() selector
+
+- support disabling LDAP and Hesiod support using configure
+
+- forward-ported all the fixes from the stable branch (MacOS X support,
+  minor Linux fixes)
+
+- bind-mount support for type==link and type==lofs with Linux 2.4+
+
+- FiST lofs support under Linux (also in 6.0.6s2)
+
+*** Notes specific to am-utils version 6.1a3:
+
+- various things from the 6.0 branch:
+	compile fixes for Linux 2.4-ac and 2.2.19pre+
+	Darwin/Rhapsody/OS X support
+	much reduced configure script (works around a bug in Darwin's cpp)
+
+*** Notes specific to am-utils version 6.1a2:
+
+- working autofs support for Solaris 2.[67], but incomplete
+
+- forward-ported all the changes up to 6.0.5s2
+
+- removed support for amq -M
+
+- known bugs
+	nfsx support is broken
+	linux NFS codes fixes
+	NFS cache aliasing fixes
+	lots of stuff ported from 6.0 branch
+
+*** Notes specific to am-utils version 6.1a1:
+
+- working autofs (v3 and v4) support for Linux!
+
+- forward-ported all the changes in 6.0.4s4
+
+- bugs fixed
+	client-side fail-over to NFSv2/UDP
+
+- known bugs
+	autofs v3 will probably break with host maps
+
+*** Notes specific to am-utils version 6.0.4:
+
+- NFSv3 support for Linux and HPUX-11
+
+- new amd.conf [global] options:
+	nfs_vers: force all NFS mounts to version 2 or 3
+	nfs_proto: force all NFS mounts to udp or tcp
+
+- new debug_options (amd -D):
+	hrtime: turns on high-resolution timer if available
+	readdir: traces browsable_dirs code
+	xdrtrace: traces XDR routines
+	(trace: only traces NFS and RPC)
+
+- new amq options:
+	-H: shows usage
+	-w: translate getpwd() into an Amd path
+
+- new map syntax:
+	${dollar}: to include a literal '$' in assignments
+
+- new "opts:=" options:
+	ver3: turns on NFS version 3 on some systems (linux)
+
+- updated or minor new ports:
+	alpha-dec-osf4.0f
+	alphaev6-dec-osf5.0
+	i386-pc-linux-rh6.2
+	i386-unknown-freebsd3.4
+
+- bugs fixed:
+	symlink mtime fixes to avoid u/mount race conditions
+	update amq -s failed umounts count correctly
+	linux compiles even if efs is available
+	linux works with mount(2) option "intr"
+	linux works with pcfs and cdfs
+	handle std{in,out,err} correctly when releasing controlling tty
+	browsable_readdir works on 64-bit kernel architectures
+	irs/wire routines compile for bsdi{2,3,4}
+
+*** Notes specific to am-utils version 6.0.3:
+
+- updated or minor new ports:
+	hppa1.0-hp-hpux11.00
+	i386-pc-bsdi4.1
+	i386-unknown-netbsd1.4.1
+	sparc-sun-solaris2.8
+	i*86-pc-linux-gnu-rh6.1
+	(some preparations for Compaq Tru64)
+
+- new variables ${uid} and ${gid}, return the numeric UID/GID of the user
+  (not root) who invokes an amd pathname.  Similar to what hlfsd does.
+
+- automake now uses automatic dependency tracking
+
+- new mount options: optionstr, noexec, nomnttab
+
+- maps of type:=auto are now browsable (using map option "browsable")
+
+- ctl-amd has "status" argument (same as RedHat)
+
+- bugs fixed:
+	document buggy AIX 4.3 plock() behavior
+	fixes to stale file handle on symlinks
+	reduce race conditions upon rapid umount/mount sequences
+	use vsnprintf, more secure than vsprintf
+	more assorted and smaller bugs
 
 *** Notes specific to am-utils version 6.0.2:
 
@@ -303,7 +1030,7 @@ the functions compute_nfs_args() and compute_automounter_nfs_args().
 - bugs fixed:
 	mnttab name ufs/cdfs/pcfs/etc filesystems corrected
 	use pmap_ping for amq (a must for secure portmappers, bsdi2/3)
-	test for xfs (irix) as a disk-based filesystem
+	test for xfs (irix) as a disk-based file system
 	set correct nfs_prot headers for Solaris 2.5
 	removed stale code from lostaltmail.in
 	lostaltmail will look for conf file in multiple locations
@@ -340,7 +1067,7 @@ machine to NFS V.2 and retry again later.
 
 - minor code cleanups for netbsd
 
-- html docs now in http://www.cs.columbia.edu/~ezk/am-utils/
+- html docs now in http://www.am-utils.org
 
 - added README file in binaries ftp directory
 
@@ -720,11 +1447,11 @@ used anywhere were removed.
 	--enable-libs[=ARG]
 		configure/compile with ARG (-L/-l) library flags
 
-- filesystem, mount table entries, and mount type tests can now look in
+- file system, mount table entries, and mount type tests can now look in
 /lib/modules and /proc/filesystems for statically/dyadically loadable kernel
 modules (linux)
 
-- prefer vfat over msdos/pc/etc filesystem for PCFS.
+- prefer vfat over msdos/pc/etc file system for PCFS.
 
 - moved all fixed headers to include/am_defs.  Left only #define/#undef
 entries in aux/acconfig.h.
diff --git a/contrib/amd/README b/contrib/amd/README
index b7d1406..0b3ce46 100644
--- a/contrib/amd/README
+++ b/contrib/amd/README
@@ -1,5 +1,3 @@
-# -*- text -*-
-
 This is the official version of am-utils.
 
 See the file NEWS for news on this and previous releases.
@@ -61,7 +59,7 @@ This is a manual method that will let you build in any directory outside the
 am-utils source tree.  It requires that your "make" program understand
 VPATH.  This can be used multiple times to build am-utils concurrently in
 multiple (but different) directories.  In fact, the buildall script
-described above.
+described above does precisely that, using the A.* subdirectories.
 
 (4) If you need to configure am-utils with extra libraries and/or headers,
 for example to add hesiod support, do so as follows:
@@ -74,18 +72,19 @@ for example to add hesiod support, do so as follows:
 hlfsd, lib, etc, all you need to do to get a new version of am-utils is run
 make.
 
-If you modify any of the files in the aux/ or conf/ directories, then you
-must rebuild the configure script, Makefile.in files, aclocal.m4, etc.  The
-best way to do so is to run
+If you modify any of the files in the m4/ or conf/ directories, or any *.in
+or *.am file, then you must rebuild the configure script, Makefile.in files,
+aclocal.m4, etc.  The best way to do so is to run
 
-	./aux/mkconf
+	./bootstrap
 or
 	./buildall -K
 
-To be a developer and be able to run mkconf, you must have autoconf-2.12,
-GNU make-3.75 or later, and automake-1.2 (plus my fixes to it) installed on
-your system.  You may find my version of automake-1.2 where you ftp'ed this
-version of am-utils.  You may also need GNU libtool 1.0.
+To be a developer and be able to run "bootstrap", you must have
+autoconf-2.50, automake-1.5, and libtool 1.4 installed on your system (or
+later versions thereof).  You no longer need to get my special version of
+automake.  Contact me if you'd like to be a maintainer and get access to the
+CVS server.
 
 After you've remade the basic configuration files you must rerun the
 buildall script to rerun configure and then remake the binaries.
@@ -95,9 +94,9 @@ before.  Let me know if you are having any problems with them.  I fully
 expect, at least initially, to have to be the sole developers of the M4
 macros and let others concentrate on C sources.
 
-[E] Report all bugs to amd-dev@majordomo.cs.columbia.edu.  Avoid reporting
-to my personal email address.  It is important to involve the whole list in
-bug fixes etc.
+[E] Report all bugs to am-utils@am-utils.org.  Avoid reporting to my
+personal email address.  It is important to involve the whole list in bug
+fixes etc.
 
 Good luck.
 
diff --git a/contrib/amd/README.attrcache b/contrib/amd/README.attrcache
new file mode 100644
index 0000000..e8522d2
--- /dev/null
+++ b/contrib/amd/README.attrcache
@@ -0,0 +1,129 @@
+		 NFS Attribute Caching OS Problems and Amd
+		      Last updated September 18, 2005
+
+* Summary:
+
+Some OSs don't seem to have a way to turn off the NFS attribute cache, which
+breaks the Amd automounter so badly that it is not recommend using Amd on
+such OS for heavy use, not until this is fixed.
+
+
+* Details:
+
+Amd is a user-level NFSv2 server that manages automounts of all other file
+systems.  The kernel contacts Amd via RPCs, and Amd in turn performs the
+actual mounts, and then responds back to the kernel's RPCs.  Every kernel
+caches attributes of files, in a cache called the Directory Name Lookup
+Cache (DNLC), or a Directory Cache (dcache).
+
+Amd manages its namespace in the user level, but the kernel caches names
+itself.  So the two must coordinate to ensure that both namespaces are in
+sync.  If the kernel uses a cached entry from the DNLC, without consulting
+Amd, users may see corruption of the automounter namespace (symlinks
+pointing to the wrong places, ESTALE errors, and more).  For example,
+suppose Amd timed out an entry and removed the entry from Amd's namespace.
+Amd has to tell the kernel to purge its corresponding DNLC entry too.  The
+way Amd often does that is by incrementing the last modification time
+(mtime) of the parent directory.  This is the most common method for kernels
+to check if their DNLC entries are stale: if the parent directory mtime is
+newer, the kernel will discard all cached entries for that directory, and
+will re-issue lookup methods.  Those lookups will result in
+NFS_GETATTR/NFS_LOOKUP calls sent from the kernel down to Amd, and Amd can
+then properly inform the kernel of the new state of automounted entries.
+
+In order to ensure that Amd is "in charge" of its namespace without
+interference from the kernel, Amd will try to turn off the NFS attribute
+cache.  It does so by using the NFSMNT_NOAC flag, if it exists, or by
+setting various "cache timeout" fields in struct nfs_args to 0 (acregmin,
+acregmax, acdirmin, or acdirmax).
+
+We have released a major new version of am-utils, version 6.1, in June 2005.
+Since then, a lot of people have experimented with Amd, in anticipation of
+migrating from the very old am-utils 6.0 to the new 6.1.  For a couple of
+months since the release of 6.1, we have received reports of problems with
+Amd, especially under heavy use.  Users reported getting ESTALE errors from
+time to time, or seeing automounted entries whose symlinks don't point to
+where it should be.  After much debugging, we traced it to a few places in
+Amd where it wasn't updating the parent directory mtime as it should have;
+in some places where Amd was indeed updating the mtime, it was using a
+resolution of only 1 second, which was not fine enough under heavy load.  We
+fixed this problem and switched to using a microsecond resolution mtime.
+
+After fixing this in Amd, we went on to verify that things work for other
+OSs.  When we got to test certain BSDs, we found out that they always cache
+directory entries, and there is no way to turn it off completely.
+Specifically, if we set the ac{reg,dir}{min,max} fields in struct nfs_args
+all to zero, the kernel seems to cache the entries for a default number of
+seconds (something like 5-30 seconds).  On some OSs, setting these four
+fields to 0 turns off the attribute cache, but not on some BSDs.  We were
+able to verify this using Amd and a script that exercises the interaction of
+the kernel's attrcache and Amd.  (If you're interested, the script can be
+made available.)
+
+We then experimented by setting the ac{reg,dir}{min,max} fields in struct
+nfs_args all to 1, the smallest non-zero value we could.  When we ran the
+Amd exercising script, we found that the value of 1 reduced the race between
+the DNLC and Amd, and the script took a little longer to run before it
+detected an incoherency.  That makes sense: the smaller the DNLC cache
+interval is, the shorter the window of vulnerability is.  (BTW, the man
+pages on some OSs say that the ac{reg,dir}{min,max} fields use a 1 second
+resolution, but experimentation indicated it was in 0.1 second units.)
+
+Clearly, setting the ac{reg,dir}{min,max} fields to 0 is worse than setting
+it to 1 on those OSs that don't have a way to turn off the attribute cache.
+So the current workaround I've implemented in am-utils is to create a
+configuration parameter called "broken_attrcache" which, if turned on, will
+set these nfs_args fields to 1 instead of 0.  I wish I didn't have to create
+such ugly workaround features in Amd, but I've got no choice.
+
+The near term solution is for every OS to support a true 'noac' flag, which
+can be added fairly easily.  This'd make Amd work reliably.
+
+The long term solution is to implement Autofs support for all OSs and to
+support it in Amd.  Currently, Amd supports autofs on Solaris and Linux;
+FreeBSD is next.  Still, we found that even with autofs support, many
+sysadmins still prefer to use the good 'ol non-autofs mode.
+
+
+* Confirmed Status
+
+This is the confirmed status of various OSs' vulnerability to this attribute
+cache bug.  We are slowly checking the status of other OSs.  The status of
+any OS not listed is unknown as of the date at the top of this file.
+
+** Not Vulnerable (support a proper "noac" flag):
+
+Sun Solaris 8 and 9 (10 probably works fine)
+Linux: 2.6.11 kernel (2.4.latest probably works fine)
+FreeBSD 5.4 and 6.0-SNAP001 (older versions probably work fine)
+OpenBSD 3.7 (older versions probably work fine)
+
+** Vulnerable (don't support a proper "noac" flag natively):
+
+NetBSD 2.0.2 (older versions are also probably affected)
+
+Note: NetBSD has promised to support a noac flag hopefully after 2.1.0 is
+released (maybe in 3.0 or 2.2).  In the mean time, you can apply one of
+these two kernel patchs to support a 'noac' flag in NetBSD 2.x or 3.x:
+	ftp://ftp.netbsd.org/pub/NetBSD/misc/christos/2x.nfs.noac.diff
+	ftp://ftp.netbsd.org/pub/NetBSD/misc/christos/3x.nfs.noac.diff
+After applying this patch and rebuilding your kernel, reboot with the new
+kernel.  Then copy the new nfs.h and nfsmount.h from /sys/nfs/ to
+/usr/include/nfs/, and finally rebuild am-utils from scratch.
+
+** Testing
+
+When you build am-utils, a script named scripts/test-attrcache is built,
+which can be used to test the NFS attribute cache behavior of the current
+OS.  You can run this script as root as follows:
+
+# make install
+# cd scripts
+# sh test-attrcache
+
+If you run this script on an OS whose status is known (and not listed
+above), please report it to am-utils@am-utils.org, so we can record it in
+this file.
+
+Sincerely,
+Erez.
diff --git a/contrib/amd/README.ldap b/contrib/amd/README.ldap
new file mode 100644
index 0000000..7151134
--- /dev/null
+++ b/contrib/amd/README.ldap
@@ -0,0 +1,57 @@
+LDAP support for am-utils was originally done by Leif Johansson
+<leifj@it.su.se>.  He no longer maintains it.
+
+The current LDAP support for am-utils is for LDAPv2 only.  Reportedly,
+LDAPv3 mostly works.  Volunteers and patches are welcome.
+
+The IANA has assigned the following Private Enterprise Number to:
+
+	10180  Am-utils Organization   Erez Zadok	ezk@am-utils.org
+
+There are three files in this directory that relate to LDAP:
+
+ldap.schema:
+
+	This is the most current schema.
+
+ldap-id.txt:
+
+	This is an experimental schema for amd mount maps in LDAP.  Since
+	LDAP isn't maintained now, this code may not match with either the
+	current ldap_info.c code or with Amd mount maps in general.
+
+	The schema is written in the form of an internet-draft but it has
+	not been published as such.  We need volunteers who know and use
+	LDAP to clean it up and further its process of submission.
+
+ldap-id.ms:
+
+	This is the NROFF source of the draft.  To generate the text from
+	it, run "nroff -ms ldap-id.ms > ldap-id.txt"
+
+Erez.
+
+------- Forwarded Message
+
+From: "IANA Private Enterprise Number" <iana-pen@icann.org>
+To: "Erez Zadok" <ezk@cs.columbia.edu>
+Subject: RE: Application for Enterprise-number (10180)
+Date: Sun, 15 Jul 2001 14:43:45 -0700
+
+Dear Erez,
+
+The IANA has assigned the following Private Enterprise
+Number to:
+
+10180  Am-utils Organization   Erez Zadok                 ezk@am-utils.org
+
+Please notify the IANA if there is a change in your contact
+or company information.
+
+Thank you,
+
+Bill Huang
+IANA - Private Enterprise Numbers
+
+------- End of Forwarded Message
+
diff --git a/contrib/amd/README.y2k b/contrib/amd/README.y2k
index 300cf38..e75bd12 100644
--- a/contrib/amd/README.y2k
+++ b/contrib/amd/README.y2k
@@ -1,4 +1,3 @@
-# -*- text -*-
 		       AM-UTILS YEAR-2000 COMPLIANCE
 
 Most likely am-utils is y2k compliant.
@@ -18,12 +17,11 @@ code scanner and manually "eyeballed" the code and could not find any more
 problems.  Paul's patch is included in am-utils-6.0.1s7 and newer versions.
 Paul also said that other 2-digit years used in am-utils are "harmless."
 
-
 NOTE: NONE OF THE PERSONS MENTIONED HERE, AUTHOR INCLUDED, ARE WILLING TO
 CERTIFY AM-UTILS AS Y2K COMPLIANT.  USE AT YOUR OWN RISK.
 
 ---
 Erez Zadok.
-Maintainer, am-utils package and AMD-DEV list.
-Email: amd-dev-owner@majordomo.cs.columbia.edu
-WWW:   http://www.cs.columbia.edu/~ezk/am-utils/
+Maintainer, am-utils package and am-utils list.
+Email: am-utils@am-utils.org
+WWW:   http://www.am-utils.org
diff --git a/contrib/amd/TODO b/contrib/amd/TODO
deleted file mode 100644
index 07fb555..0000000
--- a/contrib/amd/TODO
+++ /dev/null
@@ -1,177 +0,0 @@
-# -*- text -*-
-
-Make a tasks file that people can pick jobs off of.
-
-take a look at am_compat.h and fix everything there...
-
-fix all $Id bla bla bla $ on every file.
-add my own copyright 1997 etc.
-
-NOT NEEDED: convert DEBUG symbol to ENABLE_DEBUG
-NOT NEEDED: convert DEBUG_MEM symbol to ENABLE_DEBUG_MEM
-
-Use these two somewhere:
-AC_DEFINE(AM_UTILS_NAME_PACKAGE, "am-utils")
-AC_DEFINE(AM_UTILS_VERSION, "6.0a1)
-
-check all "dnl XXX: in configure.in
-
-check for: INLINE, Const->const, P_void, VOIDP
-
-rename DEBUG_MTAB to DEBUG_MNTTAB
-rename UPDATE_MTAB to MOUNT_TABLE_ON_FILE
-rename HAS_NIS_MAPS to HAVE_MAP_NIS
-rename HAS_TFS to HAVE_FS_TFS
-rename SIG_HNDL_TYP to RETSIGTYPE
-
-remove HOST_EXEC #define from everywhere.  add to am_ops.c a static flag
-initialized_vops, which if not true, should set the host_ops vector field to
-0 or host_umounted.  This way let the feature be turned on if -h option to
-amd is given.
-
-nuke all code that is ifdef'd SUNOS4_COMPAT
-
-rename NEED_MNTOPT_PARSER to HAVE_HASMNTOPT and cleanup the code. also take
-the supplied code in amd/mount_fs.c and include it as the library function
-libamd/hasmntopt.c
-
-TLI code needs to be fixed.
-
-a way to include a site-specific configuration file IFF it exists from
-directory local/<${target}.h>
-
-replace #include WAIT with nothing (HAVE_SYS_WAIT_H?)
-
-replace SYS5_SIGNALS with HAVE_SYS_WAIT_H (which is on only if it sys/wait.h
-exists and is using the newer "int" for type, not "union wait".  The macro
-AC_HEADER_SYS_WAIT turns on HAVE_SYS_WAIT_H iff wait*() functions are
-posix.1 compliant.  Make sure you don't remove SYS5_SIGNALS ifdef's that are
-not related to wait*() syscalls.
-
-add username, hostname, and date at which time amd was compiled.
-
-No more need for MOUNT_HELPER_SOURCE.
-
-any code which is included by NEED_UMOUNT_FS, should be on iff
-MOUNT_TABLE_ON_FILE is on.
-
-replace NFS_FH_FIELD with references fo ".fh" in calls to
-NFS_FH_DREF(src, dst) macro
-
-For *EVERY* M4 Macro with case/esac, check that the $host_os case entries
-are correct.
-
-I'm not using amd's regexp code.  Instead, use generic system code.  If the
-system has posix style regexp functions, then change amd/map.c to use
-correct new prototype.
-
-use HAVE_SVC_GETREQSET instead of RPC_4.
-
-replace all "jsp" in *.[hc] $Id: TODO,v 1.1.1.1 1998/11/05 02:04:19 ezk Exp $ with ezk.
-
-use MNTTAB_FILE_NAME instead of MOUNTED
-
-use MOUNT_TABLE_ON_FILE instead of READ_MTAB_FROM_FILE
-
-no more HAS_EMPTY_AUTOMOUNTS, which was used if a df(1) divide by zero bug
-was invoked.  Instead, change nfs_statfs() code to always return non-zero
-values.  Then nuke HAS_EMPTY_AUTOMOUNTS.
-
-REGEXP: use whatever regular expressionlibrary you have on the system,
-including regexp.h if available, and using regcomp/regexec.  Amd was written
-with BSD regexps in mind, not Sys V, so if I use any of those, I have to
-watch for correct usage.  Otherwise, I can include the older include/re.h
-and amd/re.c.  Replace HAS_REGEXP with HAVE_REGEXEC.
-
-The regex code in amd/mapc.c has changed a lot.  It probably has bugs.  Must
-test and debug it!!!
-
-# string name of filesystem in /etc/mnttab file
-Use MNTTAB_TYPE_FOO instead of MTAB_TYPE_FOO.
-# string name of mount option in /etc/mnttab file
-Use MNTTAB_OPT_FOO instead of MNTOPT_FOO.
-# string (or integer?) name of filesystem type in mount(2) syscall
-Use MOUNT_TYPE_FOO instead of MNTTYPE_FOO or MOUNT_FOO.
-# hex/number of FS mount option in nfs_args passed to mount(2) syscall
-Use MNT2_NFS_OPT_FOO instead NFSMNT_FOO.
-# hex/number of generic FS mount option directly  passed to mount(2) syscall
-Use MNT2_GEN_OPT_FOO instead of MS_FOO or M_FOO.
-
-
-update AMD_COMPAT to 6.0 in include/am_utils.h
-
-convert all mem* functions b* functions (memset to bzero, etc.) or vice
-verse.
-
-put my name/copyright on every src file
-
-change all struct mnttab/mntent to "mntent_t"
-
-cleanup lib/resvport.c (TLI vs. Sockets).  TLI code is #defin'ed
-HAVE_T_OPEN.
-[
-setting MTAB_LOCK_FILE (mtab_svr4.c) should be an amd run-time configuration
-option.
-
-change all UMOUNT_FS macros to umount_fs() fxn calls.
-
-remove getnetbyaddr() from lib/getnetbyaddr.c and then link w/ -lsocket
-
-take care of various (hlfsd et al) scripts in Makefile.am files.
-
-rename HOSTNAMESZ to MAXHOSTNAMELEN
-
-turn on all the NEW_TOPLVL_READDIR code (for "ls" to work in an amd point)
-
-change all NEW_DEFAULTS to ENABLE_DEFAULT_SELECTOTS (which is now on by
-default)
-
-remove refereces to mnt_freq and mnt_passno in mntent_t since it's not in
-use any more.
-
-remove all the (lint?) comments /*ARGSUSED */
-
-change HAS_FOOFS to HAVE_AM_FS_FOO (for example HAS_NFSX -> HAVE_AM_FS_FOO),
-but change HAS_UNION_FS to HAVE_AM_FS_UNION.
-
-some code uses #ifdef M_NEWTYPE to tell if mount(2)'s type field is "char *"
-or int.  Use MTYPE_TYPE declaration instead (not ifdef macro!)
-
-change DEBUG_MTAB to DEBUG_MNTTAB
-
-deal with the changes in values of $os, $arch, and $osver!
-
-replace SYS5_SIGNALS with REINSTATE_SIGNAL_HANDLER
-
-figure out how to auto-conf HAS_HESIOD_RELOAD (amd/info_hesiod.c).  For now
-I've used the macro HAVE_HS_ZONE_TRANSFER.
-
-
-
-
-******************************************************************************
-PERL SCRIPT TO FIX OLD AMD MAPS:
-- fix '=' to ':='
-- fix sos5 -> solaris2, etc.
-
-******************************************************************************
-USE AS IS:
-
-- SVC_IN_ARG_TYPE (change from SVC_IN_ARGS_TYPE, with an 'S')
-- NFS_FH_TYPE
-- MTYPE_TYPE
-- MOUNT_TYPE_* NO!!!
-
-******************************************************************************
-NEW FEATURES:
-
-- autofs
-- cachefs
-- dbm/gdbm/db file maps
-- add amd option -O (override) to override $os, $osver, $arch, $karch, etc.
-
-******************************************************************************
-DONE:
-
-HAS_TFS is gone and all of it's code too.
-major code cleanup, removed if 0 code and if notdef
diff --git a/contrib/amd/amd/am_ops.c b/contrib/amd/amd/am_ops.c
index 49db91e..5a5c336 100644
--- a/contrib/amd/amd/am_ops.c
+++ b/contrib/amd/amd/am_ops.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: am_ops.c,v 1.4 1999/03/13 17:03:26 ezk Exp $
+ * File: am-utils/amd/am_ops.c
  *
  */
 
@@ -53,7 +52,7 @@
  * The order of these entries matters, since lookups in this table are done
  * on a first-match basis.  The entries below are a mixture of native
  * filesystems supported by the OS (HAVE_FS_FOO), and some meta-filesystems
- * supported by amd (HAVE_AM_FS_FOO).  The order is set here in expected
+ * supported by amd (HAVE_AMU_FS_FOO).  The order is set here in expected
  * match-hit such that more popular filesystems are listed first (nfs is the
  * most popular, followed by a symlink F/S)
  */
@@ -62,34 +61,31 @@ static am_ops *vops[] =
 #ifdef HAVE_FS_NFS
   &nfs_ops,			/* network F/S (version 2) */
 #endif /* HAVE_FS_NFS */
-#ifdef HAVE_AM_FS_LINK
+#ifdef HAVE_AMU_FS_LINK
   &amfs_link_ops,		/* symlink F/S */
-#endif /* HAVE_AM_FS_LINK */
+#endif /* HAVE_AMU_FS_LINK */
 
   /*
    * Other amd-supported meta-filesystems.
    */
-#ifdef HAVE_AM_FS_NFSX
+#ifdef HAVE_AMU_FS_NFSX
   &amfs_nfsx_ops,		/* multiple-nfs F/S */
-#endif /* HAVE_AM_FS_NFSX */
-#ifdef HAVE_AM_FS_NFSL
+#endif /* HAVE_AMU_FS_NFSX */
+#ifdef HAVE_AMU_FS_NFSL
   &amfs_nfsl_ops,		/* NFS with local link existence check */
-#endif /* HAVE_AM_FS_NFSL */
-#ifdef HAVE_AM_FS_HOST
+#endif /* HAVE_AMU_FS_NFSL */
+#ifdef HAVE_AMU_FS_HOST
   &amfs_host_ops,		/* multiple exported nfs F/S */
-#endif /* HAVE_AM_FS_HOST */
-#ifdef HAVE_AM_FS_LINKX
+#endif /* HAVE_AMU_FS_HOST */
+#ifdef HAVE_AMU_FS_LINKX
   &amfs_linkx_ops,		/* symlink F/S with link target verify */
-#endif /* HAVE_AM_FS_LINKX */
-#ifdef HAVE_AM_FS_PROGRAM
+#endif /* HAVE_AMU_FS_LINKX */
+#ifdef HAVE_AMU_FS_PROGRAM
   &amfs_program_ops,		/* program F/S */
-#endif /* HAVE_AM_FS_PROGRAM */
-#ifdef HAVE_AM_FS_UNION
+#endif /* HAVE_AMU_FS_PROGRAM */
+#ifdef HAVE_AMU_FS_UNION
   &amfs_union_ops,		/* union F/S */
-#endif /* HAVE_AM_FS_UNION */
-#ifdef HAVE_AM_FS_INHERIT
-  &amfs_inherit_ops,		/* inheritance F/S */
-#endif /* HAVE_AM_FS_INHERIT */
+#endif /* HAVE_AMU_FS_UNION */
 
   /*
    * A few more native filesystems.
@@ -126,138 +122,134 @@ static am_ops *vops[] =
 #endif /* HAVE_FS_UMAPFS */
 
   /*
-   * These 5 should be last, in the order:
+   * These 4 should be last, in the order:
    *	(1) amfs_auto
    *	(2) amfs_direct
    *	(3) amfs_toplvl
-   *	(4) autofs
-   *	(5) amfs_error
+   *	(4) amfs_error
    */
-#ifdef HAVE_AM_FS_AUTO
+#ifdef HAVE_AMU_FS_AUTO
   &amfs_auto_ops,		/* Automounter F/S */
-#endif /* HAVE_AM_FS_AUTO */
-#ifdef HAVE_AM_FS_DIRECT
+#endif /* HAVE_AMU_FS_AUTO */
+#ifdef HAVE_AMU_FS_DIRECT
   &amfs_direct_ops,		/* direct-mount F/S */
-#endif /* HAVE_AM_FS_DIRECT */
-#ifdef HAVE_AM_FS_TOPLVL
+#endif /* HAVE_AMU_FS_DIRECT */
+#ifdef HAVE_AMU_FS_TOPLVL
   &amfs_toplvl_ops,		/* top-level mount F/S */
-#endif /* HAVE_AM_FS_TOPLVL */
-#ifdef HAVE_FS_AUTOFS
-  &autofs_ops,			/* autofs mount F/S */
-#endif /* HAVE_FS_AUTOFS */
-#ifdef HAVE_AM_FS_ERROR
+#endif /* HAVE_AMU_FS_TOPLVL */
+#ifdef HAVE_AMU_FS_ERROR
   &amfs_error_ops,		/* error F/S */
-#endif /* HAVE_AM_FS_ERROR */
+#endif /* HAVE_AMU_FS_ERROR */
   0
 };
 
 
 void
-ops_showamfstypes(char *buf)
+ops_showamfstypes(char *buf, size_t l)
 {
   struct am_ops **ap;
-  int l = 0;
+  int linesize = 0;
 
   buf[0] = '\0';
   for (ap = vops; *ap; ap++) {
-    strcat(buf, (*ap)->fs_type);
+    xstrlcat(buf, (*ap)->fs_type, l);
     if (ap[1])
-      strcat(buf, ", ");
-    l += strlen((*ap)->fs_type) + 2;
-    if (l > 62) {
-      l = 0;
-      strcat(buf, "\n      ");
+      xstrlcat(buf, ", ", l);
+    linesize += strlen((*ap)->fs_type) + 2;
+    if (linesize > 62) {
+      linesize = 0;
+      xstrlcat(buf, "\n      ", l);
     }
   }
 }
 
 
 static void
-ops_show1(char *buf, int *lp, const char *name)
+ops_show1(char *buf, size_t l, int *linesizep, const char *name)
 {
-  strcat(buf, name);
-  strcat(buf, ", ");
-  *lp += strlen(name) + 2;
-  if (*lp > 60) {
-    strcat(buf, "\t\n");
-    *lp = 0;
+  xstrlcat(buf, name, l);
+  xstrlcat(buf, ", ", l);
+  *linesizep += strlen(name) + 2;
+  if (*linesizep > 60) {
+    xstrlcat(buf, "\t\n", l);
+    *linesizep = 0;
   }
 }
 
 
 void
-ops_showfstypes(char *buf)
+ops_showfstypes(char *buf, size_t l)
 {
-  int l = 0;
+  int linesize = 0;
 
   buf[0] = '\0';
 
 #ifdef MNTTAB_TYPE_AUTOFS
-  ops_show1(buf, &l, MNTTAB_TYPE_AUTOFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_AUTOFS);
 #endif /* MNTTAB_TYPE_AUTOFS */
 
 #ifdef MNTTAB_TYPE_CACHEFS
-  ops_show1(buf, &l, MNTTAB_TYPE_CACHEFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_CACHEFS);
 #endif /* MNTTAB_TYPE_CACHEFS */
 
 #ifdef MNTTAB_TYPE_CDFS
-  ops_show1(buf, &l, MNTTAB_TYPE_CDFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_CDFS);
 #endif /* MNTTAB_TYPE_CDFS */
 
 #ifdef MNTTAB_TYPE_CFS
-  ops_show1(buf, &l, MNTTAB_TYPE_CFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_CFS);
 #endif /* MNTTAB_TYPE_CFS */
 
 #ifdef MNTTAB_TYPE_LOFS
-  ops_show1(buf, &l, MNTTAB_TYPE_LOFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_LOFS);
 #endif /* MNTTAB_TYPE_LOFS */
 
 #ifdef MNTTAB_TYPE_EFS
-  ops_show1(buf, &l, MNTTAB_TYPE_EFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_EFS);
 #endif /* MNTTAB_TYPE_EFS */
 
 #ifdef MNTTAB_TYPE_MFS
-  ops_show1(buf, &l, MNTTAB_TYPE_MFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_MFS);
 #endif /* MNTTAB_TYPE_MFS */
 
 #ifdef MNTTAB_TYPE_NFS
-  ops_show1(buf, &l, MNTTAB_TYPE_NFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_NFS);
 #endif /* MNTTAB_TYPE_NFS */
 
 #ifdef MNTTAB_TYPE_NFS3
-  ops_show1(buf, &l, "nfs3");	/* always hard-code as nfs3 */
+  ops_show1(buf, l, &linesize, "nfs3"); /* always hard-code as nfs3 */
 #endif /* MNTTAB_TYPE_NFS3 */
 
 #ifdef MNTTAB_TYPE_NULLFS
-  ops_show1(buf, &l, MNTTAB_TYPE_NULLFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_NULLFS);
 #endif /* MNTTAB_TYPE_NULLFS */
 
 #ifdef MNTTAB_TYPE_PCFS
-  ops_show1(buf, &l, MNTTAB_TYPE_PCFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_PCFS);
 #endif /* MNTTAB_TYPE_PCFS */
 
 #ifdef MNTTAB_TYPE_TFS
-  ops_show1(buf, &l, MNTTAB_TYPE_TFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_TFS);
 #endif /* MNTTAB_TYPE_TFS */
 
 #ifdef MNTTAB_TYPE_TMPFS
-  ops_show1(buf, &l, MNTTAB_TYPE_TMPFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_TMPFS);
 #endif /* MNTTAB_TYPE_TMPFS */
 
 #ifdef MNTTAB_TYPE_UFS
-  ops_show1(buf, &l, MNTTAB_TYPE_UFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_UFS);
 #endif /* MNTTAB_TYPE_UFS */
 
 #ifdef MNTTAB_TYPE_UMAPFS
-  ops_show1(buf, &l, MNTTAB_TYPE_UMAPFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_UMAPFS);
 #endif /* MNTTAB_TYPE_UMAPFS */
 
 #ifdef MNTTAB_TYPE_UNIONFS
-  ops_show1(buf, &l, MNTTAB_TYPE_UNIONFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_UNIONFS);
 #endif /* MNTTAB_TYPE_UNIONFS */
 
 #ifdef MNTTAB_TYPE_XFS
-  ops_show1(buf, &l, MNTTAB_TYPE_XFS);
+  ops_show1(buf, l, &linesize, MNTTAB_TYPE_XFS);
 #endif /* MNTTAB_TYPE_XFS */
 
   /* terminate with a period, newline, and NULL */
@@ -265,7 +257,7 @@ ops_showfstypes(char *buf)
     buf[strlen(buf) - 4] = '\0';
   else
     buf[strlen(buf) - 2] = '\0';
-  strcat(buf, ".\n");
+  xstrlcat(buf, ".\n", l);
 }
 
 
@@ -297,11 +289,11 @@ reverse_option(const char *opt)
 
   /* check if string starts with 'no' and chop it */
   if (NSTREQ(opt, "no", 2)) {
-    strcpy(buf, &opt[2]);
+    xstrlcpy(buf, &opt[2], sizeof(buf));
   } else {
     /* finally return a string prepended with 'no' */
-    strcpy(buf, "no");
-    strcat(buf, opt);
+    xstrlcpy(buf, "no", sizeof(buf));
+    xstrlcat(buf, opt, sizeof(buf));
   }
   return buf;
 }
@@ -320,10 +312,10 @@ merge_opts(const char *opts1, const char *opts2)
   mntent_t mnt2;		/* place holder for opts2 */
   char *newstr;			/* new string to return (malloc'ed) */
   char *tmpstr;			/* temp */
-  char *eq;			/* pointer to '=' within temp */
+  char *eq;			/* pointer to whatever follows '=' within temp */
   char oneopt[80];		/* one option w/o value if any */
   char *revoneopt;		/* reverse of oneopt */
-  int len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */
+  size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */
   char *s1 = strdup(opts1);	/* copy of opts1 to munge */
 
   /* initialization */
@@ -335,31 +327,30 @@ merge_opts(const char *opts1, const char *opts2)
        tmpstr;
        tmpstr = strtok(NULL, ",")) {
     /* copy option to temp buffer */
-    strncpy(oneopt, tmpstr, 80);
-    oneopt[79] = '\0';
+    xstrlcpy(oneopt, tmpstr, 80);
     /* if option has a value such as rsize=1024, chop the value part */
-    if ((eq = strchr(oneopt, '=')))
-      eq[1] = '\0';
+    if ((eq = haseq(oneopt)))
+      *eq = '\0';
     /* find reverse option of oneopt */
     revoneopt = reverse_option(oneopt);
     /* if option orits reverse exist in opts2, ignore it */
-    if (hasmntopt(&mnt2, oneopt) || hasmntopt(&mnt2, revoneopt))
+    if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt))
       continue;
     /* add option to returned string */
-    if (newstr && newstr[0]) {
-      strcat(newstr, ",");
-      strcat(newstr, tmpstr);
+    if (newstr[0]) {
+      xstrlcat(newstr, ",", len);
+      xstrlcat(newstr, tmpstr, len);
     } else {
-      strcpy(newstr, tmpstr);
+      xstrlcpy(newstr, tmpstr, len);
     }
   }
 
   /* finally, append opts2 itself */
-  if (newstr && newstr[0]) {
-    strcat(newstr, ",");
-    strcat(newstr, opts2);
+  if (newstr[0]) {
+    xstrlcat(newstr, ",", len);
+    xstrlcat(newstr, opts2, len);
   } else {
-    strcpy(newstr, opts2);
+    xstrlcpy(newstr, opts2, len);
   }
 
   XFREE(s1);
@@ -368,10 +359,22 @@ merge_opts(const char *opts1, const char *opts2)
 
 
 am_ops *
-ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
+ops_search(char *type)
 {
   am_ops **vp;
   am_ops *rop = 0;
+  for (vp = vops; (rop = *vp); vp++)
+    if (STREQ(rop->fs_type, type))
+      break;
+  return rop;
+}
+
+
+am_ops *
+ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
+{
+  am_ops *rop = 0;
+  char *link_dir;
 
   /*
    * First crack the global opts and the local opts
@@ -385,9 +388,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
     /*
      * Next find the correct filesystem type
      */
-    for (vp = vops; (rop = *vp); vp++)
-      if (STREQ(rop->fs_type, fo->opt_type))
-	break;
+    rop = ops_search(fo->opt_type);
     if (!rop) {
       plog(XLOG_USER, "fs type \"%s\" not recognized", fo->opt_type);
       rop = &amfs_error_ops;
@@ -420,7 +421,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
       /* optimize things for the common case where opts==remopts */
       char *mergedstr;
       mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
-      plog(XLOG_USER, "merge rem/opts \"%s\" add \"%s\" => \"%s\"",
+      plog(XLOG_INFO, "merge rem/opts \"%s\" add \"%s\" => \"%s\"",
 	   fo->opt_opts, fo->opt_addopts, mergedstr);
       XFREE(fo->opt_opts);
       XFREE(fo->opt_remopts);
@@ -429,12 +430,12 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
     } else {
       char *mergedstr, *remmergedstr;
       mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
-      plog(XLOG_USER, "merge opts \"%s\" add \"%s\" => \"%s\"",
+      plog(XLOG_INFO, "merge opts \"%s\" add \"%s\" => \"%s\"",
 	   fo->opt_opts, fo->opt_addopts, mergedstr);
       XFREE(fo->opt_opts);
       fo->opt_opts = mergedstr;
       remmergedstr = merge_opts(fo->opt_remopts, fo->opt_addopts);
-      plog(XLOG_USER, "merge remopts \"%s\" add \"%s\" => \"%s\"",
+      plog(XLOG_INFO, "merge remopts \"%s\" add \"%s\" => \"%s\"",
 	   fo->opt_remopts, fo->opt_addopts, remmergedstr);
       XFREE(fo->opt_remopts);
       fo->opt_remopts = remmergedstr;
@@ -442,17 +443,33 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map
   }
 
   /*
+   * Initialize opt_mount_type to "nfs", if it's not initialized already
+   */
+  if (!fo->opt_mount_type)
+    fo->opt_mount_type = "nfs";
+
+  /* Normalize the sublink and make it absolute */
+  link_dir = fo->opt_sublink;
+  if (link_dir && link_dir[0] && link_dir[0] != '/') {
+    link_dir = str3cat((char *) 0, fo->opt_fs, "/", link_dir);
+    normalize_slash(link_dir);
+    XFREE(fo->opt_sublink);
+    fo->opt_sublink = link_dir;
+  }
+
+  /*
    * Check the filesystem is happy
    */
   if (fo->fs_mtab)
     XFREE(fo->fs_mtab);
 
-  if ((fo->fs_mtab = (*rop->fs_match) (fo)))
+  fo->fs_mtab = rop->fs_match(fo);
+  if (fo->fs_mtab)
     return rop;
 
   /*
    * Return error file system
    */
-  fo->fs_mtab = (*amfs_error_ops.fs_match) (fo);
+  fo->fs_mtab = amfs_error_ops.fs_match(fo);
   return &amfs_error_ops;
 }
diff --git a/contrib/amd/amd/amd.8 b/contrib/amd/amd/amd.8
index faa91f9..ac5a8d5 100644
--- a/contrib/amd/amd/amd.8
+++ b/contrib/amd/amd/amd.8
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-1999 Erez Zadok
+.\" Copyright (c) 1997-2006 Erez Zadok
 .\" Copyright (c) 1989 Jan-Simon Pendry
 .\" Copyright (c) 1989 Imperial College of Science, Technology & Medicine
 .\" Copyright (c) 1989 The Regents of the University of California.
@@ -38,40 +38,34 @@
 .\"
 .\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: amd.8,v 1.3 1999/09/30 21:01:29 ezk Exp $
-.\" $FreeBSD: src/contrib/amd/amd/amd.8,v 1.6.2.9 2001/12/14 15:59:49 ru Exp $
-.\" $DragonFly: src/contrib/amd/amd/amd.8,v 1.2 2003/06/17 04:23:56 dillon Exp $
+.\" $Id: amd.8,v 1.14.2.1 2006/01/02 18:48:23 ezk Exp $
+.\" $FreeBSD: src/contrib/amd/amd/amd.8,v 1.25 2012/11/17 01:48:41 svnexp Exp $
 .\"
-.Dd April 19, 1994
+.Dd January 2, 2006
 .Dt AMD 8
 .Os
 .Sh NAME
 .Nm amd
 .Nd automatically mount file systems
 .Sh SYNOPSIS
-.Nm amd
+.Nm
 .Fl H
-.Nm amd 
+.Nm
 .Op Fl F Ar conf_file
-.Nm amd
+.Nm
 .Op Fl nprvHS
 .Op Fl a Ar mount_point
 .Op Fl c Ar duration
 .Op Fl d Ar domain
-.Bk -words
 .Op Fl k Ar kernel-arch
-.Ek
 .Op Fl l Ar logfile
 .Op Fl o Ar op_sys_ver
 .Op Fl t Ar timeout.retransmit
-.Bk -words
 .Op Fl w Ar interval
-.Ek
 .Op Fl x Ar log-option
 .Op Fl y Ar YP-domain
-.Bk -words
+.Op Fl A Ar arch
 .Op Fl C Ar cluster-name
-.Ek
 .Op Fl D Ar option
 .Op Fl F Ar conf_file
 .Op Fl O Ar op_sys_name
@@ -82,38 +76,46 @@
 .Oc
 .Ar ...
 .Sh DESCRIPTION
-.Nm Amd
-is a daemon that automatically mounts filesystems whenever a file or directory
-within that filesystem is accessed.  Filesystems are automatically unmounted
-when they appear to be quiescent.
+The
+.Nm
+utility
+is a daemon that automatically mounts file systems
+whenever a file or directory
+within that file system is accessed.
+File systems are automatically unmounted when they
+appear to be quiescent.
 .Pp
-.Nm Amd
+The
+.Nm
+utility
 operates by attaching itself as an
 .Tn NFS
 server to each of the specified
 .Ar directories .
 Lookups within the specified directories
 are handled by
-.Nm amd ,
+.Nm ,
 which uses the map defined by
 .Ar mapname
-to determine how to resolve the lookup.  Generally, this will be a host name,
-some filesystem information and some mount options for the given filesystem.
+to determine how to resolve the lookup.
+Generally, this will be a host name, some file system information
+and some mount options for the given file system.
 .Pp
 In the first form depicted above,
-.Nm amd
-will print a short help string.  In the second form, if no options are
+.Nm
+will print a short help string.
+In the second form, if no options are
 specified, or if the
 .Fl F
-is used, 
-.Nm amd 
-will read configuration parameters from the file 
+is used,
+.Nm
+will read configuration parameters from the file
 .Ar conf_file
 which defaults to
 .Pa /etc/amd.conf .
 The last form is described below.
 .Sh OPTIONS
-.Bl -tag -width Ds
+.Bl -tag -width indent
 .It Fl a Ar temporary-directory
 Specify an alternative location for the real mount points.
 The default is
@@ -122,87 +124,112 @@ The default is
 Specify a
 .Ar duration ,
 in seconds, that a looked up name remains
-cached when not in use.  The default is 5 minutes.
+cached when not in use.
+The default is 5 minutes.
 .It Fl d Ar domain
-Specify the local domain name.  If this option is not
+Specify the local domain name.
+If this option is not
 given the domain name is determined from the hostname.
 .It Fl k Ar kernel-arch
-Specifies the kernel architecture.  This is used solely
+Specifies the kernel architecture.
+This is used solely
 to set the ${karch} selector.
 .It Fl l Ar logfile
 Specify a logfile in which to record mount and unmount events.
 If
 .Ar logfile
 is the string
-.Em syslog ,
-the log messages will be sent to the system log daemon by
+.Dq Li syslog ,
+then the log messages will be sent to the system log daemon by
 .Xr syslog 3 .
-The default syslog facility used is LOG_DAEMON.  
-If you wish to change it, append its name to the log file name,
-delimited by a single colon.
-For example, if 
+The default syslog facility used is
+.Dv LOG_DAEMON .
+If you
+wish to change it, append its name to the log file name, delimited by a
+single colon.
+For example, if
 .Ar logfile
 is the string
 .Dq Li syslog:local7
 then
-.Nm amd
-will log messages via 
+.Nm
+will log messages via
 .Xr syslog 3
-using the LOG_LOCAL7 facility (if it exists on the system).
+using the
+.Dv LOG_LOCAL7
+facility (if it exists on the system).
 .It Fl n
 Normalize hostnames.
 The name referred to by ${rhost} is normalized relative to the
-host database before being used.  The effect is to translate
-aliases into ``official'' names.
+host database before being used.
+The effect is to translate
+aliases into
+.Dq official
+names.
 .It Fl o Ar op_sys_ver
 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 
-.Dq 2.5.1 , 
+Useful
+when the built in version is not desired for backward compatibility reasons.
+For example, if the build in version is
+.Dq Li 2.5.1 ,
 you can override it to
-.Dq 5.5.1 , 
+.Dq Li 5.5.1 ,
 and use older maps that were written with the latter in mind.
 .It Fl p
-Print
-.Em PID .
-Outputs the process-id of
-.Nm amd
+Print PID.
+Outputs the process ID of
+.Nm
 to standard output where it can be saved into a file.
 .It Fl r
 Restart existing mounts.
-.Nm Amd
-will scan the mount file table to determine which filesystems
-are currently mounted.  Whenever one of these would have
+The
+.Nm
+utility
+will scan the mount file table to determine which file systems
+are currently mounted.
+Whenever one of these would have
 been auto-mounted,
-.Nm amd
+.Nm
 .Em inherits
 it.
 .It Fl t Ar timeout.retransmit
-Specify the NFS timeout
-.Ar interval ,
+Specify the NFS
+.Ar timeout
+interval,
 in tenths of a second, between
 .Tn NFS/RPC
-retries (for UDP only).  The default
-is 0.8 seconds.  The second value alters the restransmit counter, which
-defaults to 11 retransmissions.  Both of these values are used by the kernel
-to communicate with amd.  Useful defaults are supplied if either or both
+retries (for UDP only).
+The default
+is 0.8 seconds.
+The second value alters the retransmit counter, which
+defaults to 11 retransmissions.
+Both of these values are used by the kernel
+to communicate with amd.
+Useful defaults are supplied if either or both
 values are missing.
 .Pp
-Amd relies on the kernel RPC retransmit mechanism to trigger mount retries.
-The values of these parameters change the overall retry interval.  Too long
+The
+.Xr amd 8
+utility
+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.
 .It Fl v
-Version.  Displays version and configuration information on standard error.
+Version.
+Displays version and configuration information on standard error.
 .It Fl w Ar interval
 Specify an
 .Ar interval ,
-in seconds, between attempts to dismount filesystems that have exceeded their
-cached times.  The default is 2 minutes.
+in seconds, between attempts to dismount
+file systems that have exceeded their cached times.
+The default is 2 minutes.
 .It Fl x Ar options
-Specify run-time logging options.  The options are a comma separated list
-chosen from: fatal, error, user, warn, info, map, stats, all.
+Specify run-time logging options.
+The options are a comma separated
+list chosen from:
+.Li fatal , error , user , warn , info , map , stats , all .
 .It Fl y Ar domain
 Specify an alternative
 .Tn NIS
@@ -213,15 +240,21 @@ The default is the system domain name.
 This option is ignored if
 .Tn NIS
 support is not available.
+.It Fl A Ar arch
+Specifies the OS architecture.
+This is used solely to set the ${arch}
+selector.
 .It Fl C Ar cluster-name
 Specify an alternative HP-UX cluster name to use.
 .It Fl D Ar option
-Select from a variety of debug options.  Prefixing an
+Select from a variety of debug options.
+Prefixing an
 option with the string
-.Em no
-reverses the effect of that option.  Options are cumulative.
+.Dq Li no
+reverses the effect of that option.
+Options are cumulative.
 The most useful option is
-.Ar all .
+.Dq Li all .
 .Pp
 Since
 .Fl D
@@ -232,62 +265,73 @@ option
 and a fuller description is available in the program source.
 .It Fl F Ar conf_file
 Specify an
-.Nm amd
-configuration file to use.  See
+.Nm
+configuration file to use.
+See
+.Xr amd.conf 5
+for description of this file's format.
+This configuration file is used to
+specify any options in lieu of typing many of them on the command line.
+The
 .Xr amd.conf 5
-for description of this file's format.  This configuration file is used to
-specify any options in lieu of typing many of them on the command line.  The
-.Nm amd.conf
-file includes directives for every command line option 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 have been processed, regardless
-of the actual location of this option on the command line.
+file includes directives for every command line option 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.
 .It Fl H
 Print help and usage string.
 .It Fl O Ar op_sys_name
-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 build in name is
-.Dq sunos5 , 
+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 build in name is
+.Dq Li sunos5 ,
 you can override it to
-.Dq sos5
+.Dq Li sos5
 and use older maps which were written with the latter in mind.
 .It Fl S
 Do not lock the running executable pages of
-.Nm amd
-into memory.  To improve
-.Nm amd's
-performance, systems that support the 
+.Nm
+into memory.
+To improve
+.Nm Ns 's
+performance, systems that support the
 .Xr plock 3
 call, could lock the
-.Nm amd
-process into memory.  This way there is less chance the operating system will
-schedule, page out, and swap the
-.Nm amd
-process as needed.  This tends to improve
-.Nm amd's
-performance, at the cost of reserving the memory used by the
-.Nm amd
-process
-(making it unavailable for other processes).
+.Nm
+process into memory.
+This way there is less chance
+the operating system will schedule, page out, and swap the
+.Nm
+process as
+needed.
+This tends to improve
+.Nm Ns 's
+performance, at the cost of reserving the
+memory used by the
+.Nm
+process (making it unavailable for other processes).
 If this behavior is not desired, use the
 .Fl S
 option.
 .It Fl T Ar tag
 Specify a tag to use with
 .Xr amd.conf 5 .
-All Map entries tagged with tag will be processed.   
+All map entries tagged with
+.Ar tag
+will be processed.
 Map entries that are not tagged are always processed.
 Map entries that are tagged with a tag other than
 .Ar tag
 will not be processed.
 .El
 .Sh FILES
-.Bl -tag -width /axx
+.Bl -tag -width ".Pa /etc/amd.conf"
 .It Pa /.amd_mnt
-directory under which filesystems are dynamically mounted
+directory under which file systems are dynamically mounted
 .It Pa /etc/amd.conf
 default configuration file
 .El
@@ -296,23 +340,20 @@ Some care may be required when creating a mount map.
 .Pp
 Symbolic links on an
 .Tn NFS
-filesystem can be incredibly inefficient.
+file system can be incredibly inefficient.
 In most implementations of
 .Tn NFS ,
-their interpolations are not cached by
-the kernel and each time a symbolic link is
-encountered during a
+their interpolations are not cached
+by the kernel and each time a symbolic link is encountered during a
 .Em lookuppn
 translation it costs an
 .Tn RPC
 call to the
 .Tn NFS
 server.
-A large improvement in real-time
+It would appear that a large improvement in real-time
 performance could be gained by adding a cache somewhere.
-Replacing
-.Xr symlink 2
-with a suitable incarnation of the auto-mounter
+Replacing symlinks with a suitable incarnation of the auto-mounter
 results in a large real-time speedup, but also causes a large
 number of process context switches.
 .Pp
@@ -327,24 +368,35 @@ the features.
 .Xr amq 8 ,
 .Xr mount 8 ,
 .Xr umount 8
+.Pp
+.Dq am-utils
+.Xr info 1
+entry.
 .Rs
-.%T Amd \- The 4.4 BSD Automounter
+.%A Erez Zadok
+.%B "Linux NFS and Automounter Administration"
+.%O ISBN 0-7821-2739-8
+.%I Sybex
+.%D 2001
 .Re
 .Pp
-.Pa http://www.cs.columbia.edu/~ezk/am-utils/
+.Pa http://www.am-utils.org/
+.Rs
+.%T Amd \- The 4.4 BSD Automounter
+.Re
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 4.4 .
 .Sh AUTHORS
 .An Jan-Simon Pendry Aq jsp@doc.ic.ac.uk ,
 Department of Computing, Imperial College, London, UK.
 .Pp
-.An Erez Zadok Aq ezk@cs.columbia.edu ,
-Department of Computer Science, Columbia University,
-New York, USA.
+.An Erez Zadok Aq ezk@cs.sunysb.edu ,
+Computer Science Department, Stony Brook
+University, Stony Brook, New York, USA.
 .Pp
 Other authors and contributors to am-utils are listed in the
-.Pa AUTHORS 
+.Pa AUTHORS
 file distributed with am-utils.
-.Sh HISTORY
-The
-.Nm amd
-utility first appeared in
-.Bx 4.4 .
diff --git a/contrib/amd/amd/amd.c b/contrib/amd/amd/amd.c
index b25c041..abb96be 100644
--- a/contrib/amd/amd/amd.c
+++ b/contrib/amd/amd/amd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,12 +36,11 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amd.c,v 1.6 1999/09/30 21:01:29 ezk Exp $
- * $FreeBSD: src/contrib/amd/amd/amd.c,v 1.6.2.1 2000/09/20 02:17:04 jkh Exp $
- * $DragonFly: src/contrib/amd/amd/amd.c,v 1.2 2003/06/17 04:23:56 dillon Exp $
+ * $Id: amd.c,v 1.8.2.6 2004/01/06 03:15:16 ezk Exp $
+ * File: am-utils/amd/amd.c
  *
+ * $FreeBSD: src/contrib/amd/amd/amd.c,v 1.12 2012/11/17 01:48:41 svnexp Exp $
  */
 
 /*
@@ -56,9 +55,10 @@
 
 struct amu_global_options gopt;	/* where global options are stored */
 
-char pid_fsname[16 + MAXHOSTNAMELEN];	/* "kiska.southseas.nz:(pid%d)" */
+char pid_fsname[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */
 char *hostdomain = "unknown.domain";
-char hostd[2 * MAXHOSTNAMELEN + 1]; /* Host+domain */
+#define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1)	/* Host+domain */
+char hostd[SIZEOF_HOSTD];	/* Host+domain */
 char *endian = ARCH_ENDIAN;	/* Big or Little endian */
 char *cpu = HOST_CPU;		/* CPU type */
 char *PrimNetName;		/* name of primary network */
@@ -73,6 +73,10 @@ struct amd_stats amd_stats;	/* Server statistics */
 struct in_addr myipaddr;	/* (An) IP address of this host */
 time_t do_mapc_reload = 0;	/* mapc_reload() call required? */
 
+#ifdef HAVE_FS_AUTOFS
+int amd_use_autofs = 0;
+#endif /* HAVE_FS_AUTOFS */
+
 #ifdef HAVE_SIGACTION
 sigset_t masked_sigs;
 #endif /* HAVE_SIGACTION */
@@ -120,10 +124,8 @@ sighup(int sig)
   signal(sig, sighup);
 #endif /* REINSTALL_SIGNAL_HANDLER */
 
-#ifdef DEBUG
   if (sig != SIGHUP)
     dlog("spurious call to sighup");
-#endif /* DEBUG */
   /*
    * Force a reload by zero'ing the timer
    */
@@ -135,7 +137,26 @@ sighup(int sig)
 static RETSIGTYPE
 parent_exit(int sig)
 {
-  exit(0);
+  /*
+   * This signal handler is called during Amd initialization.  The parent
+   * forks a child to do all the hard automounting work, and waits for a
+   * SIGQUIT signal from the child.  When the parent gets the signal it's
+   * supposed to call this handler and exit(3), thus completing the
+   * daemonizing process.  Alas, on some systems, especially Linux 2.4/2.6
+   * with Glibc, exit(3) doesn't always terminate the parent process.
+   * Worse, the parent process now refuses to accept any more SIGQUIT
+   * signals -- they are blocked.  What's really annoying is that this
+   * doesn't happen all the time, suggesting a race condition somewhere.
+   * (This happens even if I change the logic to use another signal.)  I
+   * traced this to something which exit(3) does in addition to exiting the
+   * process, probably some atexit() stuff or other side-effects related to
+   * signal handling.  Either way, since at this stage the parent process
+   * just needs to terminate, I'm simply calling _exit(2).  Note also that
+   * the OpenGroup doesn't list exit(3) as a recommended "Base Interface"
+   * but they do list _exit(2) as one.  This fix seems to work reliably all
+   * the time. -Erez (2/27/2005)
+   */
+  _exit(0);
 }
 
 
@@ -147,6 +168,7 @@ daemon_mode(void)
 #ifdef HAVE_SIGACTION
   struct sigaction sa, osa;
 
+  memset(&sa, 0, sizeof(sa));
   sa.sa_handler = parent_exit;
   sa.sa_flags = 0;
   sigemptyset(&(sa.sa_mask));
@@ -179,8 +201,8 @@ daemon_mode(void)
   if (gopt.flags & CFM_PRINT_PID) {
     if (STREQ(gopt.pid_file, "/dev/stdout")) {
       printf("%ld\n", (long) am_mypid);
+      /* flush stdout, just in case */
       fflush(stdout);
-      /* do not fclose stdout */
     } else {
       FILE *f;
       mode_t prev_umask = umask(0022); /* set secure temporary umask */
@@ -219,6 +241,7 @@ init_global_options(void)
 #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
   static struct utsname un;
 #endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */
+  int i;
 
   memset(&gopt, 0, sizeof(struct amu_global_options));
 
@@ -228,9 +251,15 @@ init_global_options(void)
   /* automounter temp dir */
   gopt.auto_dir = "/.amd_mnt";
 
+  /* toplevel attribute cache timeout */
+  gopt.auto_attrcache = 0;
+
   /* cluster name */
   gopt.cluster = NULL;
 
+  /* executable map timeout */
+  gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT;
+
   /*
    * kernel architecture: this you must get from uname() if possible.
    */
@@ -262,11 +291,11 @@ init_global_options(void)
   /* local domain */
   gopt.sub_domain = NULL;
 
-  /* NFS retransmit counter */
-  gopt.amfs_auto_retrans = -1;
-
-  /* NFS retry interval */
-  gopt.amfs_auto_timeo = -1;
+  /* reset NFS (and toplvl) retransmit counter and retry interval */
+  for (i=0; i<AMU_TYPE_MAX; ++i) {
+    gopt.amfs_auto_retrans[i] = -1; /* -1 means "never set before" */
+    gopt.amfs_auto_timeo[i] = -1; /* -1 means "never set before" */
+  }
 
   /* cache duration */
   gopt.am_timeo = AM_TTL;
@@ -274,11 +303,13 @@ init_global_options(void)
   /* dismount interval */
   gopt.am_timeo_w = AM_TTL_W;
 
+  /* map reload intervl */
+  gopt.map_reload_interval = ONE_HOUR;
+
   /*
-   * various CFM_* flags.
-   * by default, only the "plock" option is on (if available).
+   * various CFM_* flags that are on by default.
    */
-  gopt.flags = CFM_PROCESS_LOCK;
+  gopt.flags = CFM_DEFAULT_FLAGS;
 
 #ifdef HAVE_MAP_HESIOD
   /* Hesiod rhs zone */
@@ -295,6 +326,9 @@ init_global_options(void)
   /* LDAP cache */
   gopt.ldap_cache_seconds = 0;
   gopt.ldap_cache_maxmem = 131072;
+
+  /* LDAP protocol version */
+  gopt.ldap_proto_version = 2;
 #endif /* HAVE_MAP_LDAP */
 
 #ifdef HAVE_MAP_NIS
@@ -304,17 +338,58 @@ init_global_options(void)
 }
 
 
+/*
+ * Lock process text and data segment in memory (after forking the daemon)
+ */
+static void
+do_memory_locking(void)
+{
+#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
+  int locked_ok = 0;
+#else /* not HAVE_PLOCK and not HAVE_MLOCKALL */
+  plog(XLOG_WARNING, "Process memory locking not supported by the OS");
+#endif /* not HAVE_PLOCK and not HAVE_MLOCKALL */
+#ifdef HAVE_PLOCK
+# ifdef _AIX
+  /*
+   * On AIX you must lower the stack size using ulimit() before calling
+   * plock.  Otherwise plock will reserve a lot of memory space based on
+   * your maximum stack size limit.  Since it is not easily possible to
+   * tell what should the limit be, I print a warning before calling
+   * plock().  See the manual pages for ulimit(1,3,4) on your AIX system.
+   */
+  plog(XLOG_WARNING, "AIX: may need to lower stack size using ulimit(3) before calling plock");
+# endif /* _AIX */
+  if (!locked_ok && plock(PROCLOCK) != 0)
+    plog(XLOG_WARNING, "Couldn't lock process pages in memory using plock(): %m");
+  else
+    locked_ok = 1;
+#endif /* HAVE_PLOCK */
+#ifdef HAVE_MLOCKALL
+  if (!locked_ok && mlockall(MCL_CURRENT|MCL_FUTURE) != 0)
+    plog(XLOG_WARNING, "Couldn't lock process pages in memory using mlockall(): %m");
+  else
+    locked_ok = 1;
+#endif /* HAVE_MLOCKALL */
+#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
+  if (locked_ok)
+    plog(XLOG_INFO, "Locked process pages in memory");
+#endif /* HAVE_PLOCK || HAVE_MLOCKALL */
+
+#if defined(HAVE_MADVISE) && defined(MADV_PROTECT)
+    madvise(0, 0, MADV_PROTECT); /* may be redundant of the above worked out */
+#endif /* defined(HAVE_MADVISE) && defined(MADV_PROTECT) */
+}
+
+
 int
 main(int argc, char *argv[])
 {
-  char *domdot, *verstr;
+  char *domdot, *verstr, *vertmp;
   int ppid = 0;
   int error;
   char *progname = NULL;		/* "amd" */
   char hostname[MAXHOSTNAMELEN + 1] = "localhost"; /* Hostname */
-#ifdef HAVE_SIGACTION
-  struct sigaction sa;
-#endif /* HAVE_SIGACTION */
 
   /*
    * Make sure some built-in assumptions are true before we start
@@ -365,11 +440,6 @@ main(int argc, char *argv[])
     going_down(1);
   }
 
-#ifdef DEBUG
-  /* initialize debugging flags (Register AMQ, Enter daemon mode) */
-  debug_flags = D_AMQ | D_DAEMON;
-#endif /* DEBUG */
-
   /*
    * Initialize global options structure.
    */
@@ -388,73 +458,31 @@ main(int argc, char *argv[])
     *domdot++ = '\0';
     hostdomain = domdot;
   }
-  strcpy(hostd, hostname);
+  xstrlcpy(hostd, hostname, sizeof(hostd));
   am_set_hostname(hostname);
 
   /*
-   * Trap interrupts for shutdowns.
-   */
-#ifdef HAVE_SIGACTION
-  sa.sa_handler = sigterm;
-  sa.sa_flags = 0;
-  sigemptyset(&(sa.sa_mask));
-  sigaddset(&(sa.sa_mask), SIGINT);
-  sigaddset(&(sa.sa_mask), SIGTERM);
-  sigaction(SIGINT, &sa, NULL);
-  sigaction(SIGTERM, &sa, NULL);
-#else /* not HAVE_SIGACTION */
-  (void) signal(SIGINT, sigterm);
-#endif /* not HAVE_SIGACTION */
-
-  /*
-   * Trap Terminate so that we can shutdown gracefully (some chance)
-   */
-#ifdef HAVE_SIGACTION
-  sa.sa_handler = sigterm;
-  sa.sa_flags = 0;
-  sigemptyset(&(sa.sa_mask));
-  sigaddset(&(sa.sa_mask), SIGTERM);
-  sigaction(SIGTERM, &sa, NULL);
-#else /* not HAVE_SIGACTION */
-  (void) signal(SIGTERM, sigterm);
-#endif /* not HAVE_SIGACTION */
-
-  /*
-   * Hangups tell us to reload the cache
+   * Setup signal handlers
    */
-#ifdef HAVE_SIGACTION
-  sa.sa_handler = sighup;
-  sa.sa_flags = 0;
-  sigemptyset(&(sa.sa_mask));
-  sigaddset(&(sa.sa_mask), SIGHUP);
-  sigaction(SIGHUP, &sa, NULL);
-#else /* not HAVE_SIGACTION */
-  (void) signal(SIGHUP, sighup);
-#endif /* not HAVE_SIGACTION */
-
+  /* SIGINT: trap interrupts for shutdowns */
+  setup_sighandler(SIGINT, sigterm);
+  /* SIGTERM: trap terminate so we can shutdown cleanly (some chance) */
+  setup_sighandler(SIGTERM, sigterm);
+  /* SIGHUP: hangups tell us to reload the cache */
+  setup_sighandler(SIGHUP, sighup);
   /*
-   * Trap Death-of-a-child.  These allow us to
-   * pick up the exit status of backgrounded mounts.
-   * See "sched.c".
+   * SIGCHLD: trap Death-of-a-child.  These allow us to pick up the exit
+   * status of backgrounded mounts.  See "sched.c".
    */
+  setup_sighandler(SIGCHLD, sigchld);
 #ifdef HAVE_SIGACTION
-  sa.sa_handler = sigchld;
-  sa.sa_flags = 0;
-  sigemptyset(&(sa.sa_mask));
-  sigaddset(&(sa.sa_mask), SIGCHLD);
-  sigaction(SIGCHLD, &sa, NULL);
-
-  /*
-   * construct global "masked_sigs" used in nfs_start.c
-   */
+  /* construct global "masked_sigs" used in nfs_start.c */
   sigemptyset(&masked_sigs);
+  sigaddset(&masked_sigs, SIGINT);
+  sigaddset(&masked_sigs, SIGTERM);
   sigaddset(&masked_sigs, SIGHUP);
   sigaddset(&masked_sigs, SIGCHLD);
-  sigaddset(&masked_sigs, SIGTERM);
-  sigaddset(&masked_sigs, SIGINT);
-#else /* not HAVE_SIGACTION */
-  (void) signal(SIGCHLD, sigchld);
-#endif /* not HAVE_SIGACTION */
+#endif /* HAVE_SIGACTION */
 
   /*
    * Fix-up any umask problems.  Most systems default
@@ -475,18 +503,21 @@ main(int argc, char *argv[])
   /*
    * Log version information.
    */
-  verstr = strtok(get_version_string(), "\n");
+  vertmp = get_version_string();
+  verstr = strtok(vertmp, "\n");
   plog(XLOG_INFO, "AM-UTILS VERSION INFORMATION:");
   while (verstr) {
-    plog(XLOG_INFO, verstr);
+    plog(XLOG_INFO, "%s", verstr);
     verstr = strtok(NULL, "\n");
   }
+  XFREE(vertmp);
 
   /*
-   * Get our own IP address so that we
-   * can mount the automounter.
+   * Get our own IP address so that we can mount the automounter.  We pass
+   * localhost_address which could be used as the default localhost
+   * name/address in amu_get_myaddress().
    */
-  amu_get_myaddress(&myipaddr);
+  amu_get_myaddress(&myipaddr, gopt.localhost_address);
   plog(XLOG_INFO, "My ip addr is %s", inet_ntoa(myipaddr));
 
   /* avoid hanging on other NFS servers if started elsewhere */
@@ -501,29 +532,6 @@ main(int argc, char *argv[])
     going_down(1);
   }
 
-  /*
-   * Lock process text and data segment in memory.
-   */
-#ifdef HAVE_PLOCK
-  if (gopt.flags & CFM_PROCESS_LOCK) {
-# ifdef _AIX
-    /*
-     * On AIX you must lower the stack size using ulimit() before calling
-     * plock.  Otherwise plock will reserve a lot of memory space based on
-     * your maximum stack size limit.  Since it is not easily possible to
-     * tell what should the limit be, I print a warning before calling
-     * plock().  See the manual pages for ulimit(1,3,4) on your AIX system.
-     */
-    plog(XLOG_WARNING, "AIX: may need to lower stack size using ulimit(3) before calling plock");
-# endif /* _AIX */
-    if (plock(PROCLOCK) != 0) {
-      plog(XLOG_WARNING, "Couldn't lock process text and data segment in memory: %m");
-    } else {
-      plog(XLOG_INFO, "Locked process text and data segment in memory");
-    }
-  }
-#endif /* HAVE_PLOCK */
-
 #ifdef HAVE_MAP_NIS
   /*
    * If the domain was specified then bind it here
@@ -536,14 +544,17 @@ main(int argc, char *argv[])
   }
 #endif /* HAVE_MAP_NIS */
 
-#ifdef DEBUG
-  amuDebug(D_DAEMON)
-#endif /* DEBUG */
+  if (!amuDebug(D_DAEMON))
     ppid = daemon_mode();
 
-  sprintf(pid_fsname, "%s:(pid%ld)", am_get_hostname(), (long) am_mypid);
+  /*
+   * Lock process text and data segment in memory.
+   */
+  if (gopt.flags & CFM_PROCESS_LOCK) {
+    do_memory_locking();
+  }
 
-  do_mapc_reload = clocktime() + ONE_HOUR;
+  do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
 
   /*
    * Register automounter with system.
@@ -551,6 +562,16 @@ main(int argc, char *argv[])
   error = mount_automounter(ppid);
   if (error && ppid)
     kill(ppid, SIGALRM);
+
+#ifdef HAVE_FS_AUTOFS
+  /*
+   * XXX this should be part of going_down(), but I can't move it there
+   * because it would be calling non-library code from the library... ugh
+   */
+  if (amd_use_autofs)
+    destroy_autofs_service();
+#endif /* HAVE_FS_AUTOFS */
+
   going_down(error);
 
   abort();
diff --git a/contrib/amd/amd/amd.h b/contrib/amd/amd/amd.h
index c896022..0e371b7 100644
--- a/contrib/amd/amd/amd.h
+++ b/contrib/amd/amd/amd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amd.h,v 1.4 1999/09/30 21:01:29 ezk Exp $
+ * File: am-utils/amd/amd.h
  *
  */
 
@@ -50,32 +49,160 @@
  * MACROS:
  */
 
+/*
+ * Define a default debug mtab path for systems
+ * that support mtab on file.
+ */
+#ifdef MOUNT_TABLE_ON_FILE
+# define DEBUG_MNTTAB_FILE               "/tmp/mnttab"
+#endif /* MOUNT_TABLE_ON_FILE */
+
 /* options for amd.conf */
-#define CFM_BROWSABLE_DIRS		0x0001
-#define CFM_MOUNT_TYPE_AUTOFS		0x0002
-#define CFM_ENABLE_DEFAULT_SELECTORS	0x0004
-#define CFM_NORMALIZE_HOSTNAMES		0x0008
-#define CFM_PROCESS_LOCK		0x0010
-#define CFM_PRINT_PID			0x0020
-#define CFM_RESTART_EXISTING_MOUNTS	0x0040
-#define CFM_SHOW_STATFS_ENTRIES		0x0080
-#define CFM_FULLY_QUALIFIED_HOSTS	0x0100
-#define CFM_BROWSABLE_DIRS_FULL		0x0200 /* allow '/' in readdir() */
-#define CFM_UNMOUNT_ON_EXIT		0x0400 /* when amd finishing */
+#define CFM_BROWSABLE_DIRS		0x00000001
+#define CFM_MOUNT_TYPE_AUTOFS		0x00000002 /* use kernel autofs support */
+#define CFM_SELECTORS_IN_DEFAULTS	0x00000004
+#define CFM_NORMALIZE_HOSTNAMES		0x00000008
+#define CFM_PROCESS_LOCK		0x00000010
+#define CFM_PRINT_PID			0x00000020
+#define CFM_RESTART_EXISTING_MOUNTS	0x00000040
+#define CFM_SHOW_STATFS_ENTRIES		0x00000080
+#define CFM_FULLY_QUALIFIED_HOSTS	0x00000100
+#define CFM_BROWSABLE_DIRS_FULL		0x00000200 /* allow '/' in readdir() */
+#define CFM_UNMOUNT_ON_EXIT		0x00000400 /* when amd finishing */
+#define CFM_USE_TCPWRAPPERS		0x00000800
+#define CFM_AUTOFS_USE_LOFS		0x00001000
+#define CFM_NFS_INSECURE_PORT		0x00002000
+#define CFM_DOMAIN_STRIP		0x00004000
+#define CFM_NORMALIZE_SLASHES		0x00008000 /* normalize slashes? */
+#define CFM_FORCED_UNMOUNTS		0x00010000 /* forced unmounts? */
+#define CFM_TRUNCATE_LOG		0x00020000 /* truncate log file? */
+#if 0
+/* XXX: reserved to sync up with am-utils-6.2 */
+#define CFM_SUN_MAP_SYNTAX		0x00040000 /* Sun map syntax? */
+#endif
+#define CFM_NFS_ANY_INTERFACE		0x00080000 /* all interfaces are acceptable */
+
+/* defaults global flags: plock, tcpwrappers, and autofs/lofs */
+#define CFM_DEFAULT_FLAGS	(CFM_PROCESS_LOCK|CFM_USE_TCPWRAPPERS|CFM_AUTOFS_USE_LOFS|CFM_DOMAIN_STRIP|CFM_NORMALIZE_SLASHES)
+
+/*
+ * macro definitions for automounter vfs/vnode operations.
+ */
+#define	VLOOK_CREATE	0x1
+#define	VLOOK_DELETE	0x2
+#define VLOOK_LOOKUP	0x3
+
+/*
+ * macro definitions for automounter vfs capabilities
+ */
+#define FS_DIRECTORY	0x0001	/* This looks like a dir, not a link */
+#define	FS_MBACKGROUND	0x0002	/* Should background this mount */
+#define	FS_NOTIMEOUT	0x0004	/* Don't bother with timeouts */
+#define FS_MKMNT	0x0008	/* Need to make the mount point */
+#define FS_UBACKGROUND	0x0010	/* Unmount in background */
+#define	FS_BACKGROUND	(FS_MBACKGROUND|FS_UBACKGROUND)
+#define	FS_DISCARD	0x0020	/* Discard immediately on last reference */
+#define	FS_AMQINFO	0x0040	/* Amq is interested in this fs type */
+#define FS_AUTOFS	0x0080	/* This filesystem can be an autofs f/s */
+#define FS_DIRECT	0x0100	/* Direct mount */
+#define FS_ON_AUTOFS	0x0200	/* This filesystem can be mounted directly
+				   onto an autofs mountpoint */
+
+/*
+ * macros for struct am_node (map of auto-mount points).
+ */
+#define	AMF_NOTIMEOUT	0x0001	/* This node never times out */
+#define	AMF_ROOT	0x0002	/* This is a root node */
+#define AMF_AUTOFS	0x0004	/* This node is part of an autofs filesystem */
+#define AMF_REMOUNT	0x0008	/* This node needs to be remounted */
+#define AMF_SOFTLOOKUP	0x0010	/* This node returns EIO if server is down */
+
+/*
+ * macros for struct mntfs (list of mounted filesystems)
+ */
+#define	MFF_MOUNTED	0x0001	/* Node is mounted */
+#define	MFF_MOUNTING	0x0002	/* Mount is in progress */
+#define	MFF_UNMOUNTING	0x0004	/* Unmount is in progress */
+#define	MFF_RESTART	0x0008	/* Restarted node */
+#define MFF_MKMNT	0x0010	/* Delete this node's am_mount */
+#define	MFF_ERROR	0x0020	/* This node failed to mount */
+#define	MFF_LOGDOWN	0x0040	/* Logged that this mount is down */
+#define	MFF_RSTKEEP	0x0080	/* Don't timeout this filesystem - restarted */
+#define	MFF_WANTTIMO	0x0100	/* Need a timeout call when not busy */
+#define MFF_NFSLINK	0x0200	/* nfsl type, and deemed a link */
+#define MFF_IS_AUTOFS	0x0400	/* this filesystem is of type autofs */
+#define MFF_NFS_SCALEDOWN 0x0800 /* the mount failed, retry with v2/UDP */
+#define MFF_ON_AUTOFS	0x1000	/* autofs has a lofs/link to this f/s */
+#define MFF_WEBNFS	0x2000	/* use public filehandle */
+
+/*
+ * macros for struct fserver.
+ */
+#define	FSF_VALID	0x0001	/* Valid information available */
+#define	FSF_DOWN	0x0002	/* This fileserver is thought to be down */
+#define	FSF_ERROR	0x0004	/* Permanent error has occurred */
+#define	FSF_WANT	0x0008	/* Want a wakeup call */
+#define	FSF_PINGING	0x0010	/* Already doing pings */
+#define	FSF_WEBNFS	0x0020	/* Don't try to contact portmapper */
+#define FSF_PING_UNINIT	0x0040	/* ping values have not been initilized */
+#define FSF_FORCE_UNMOUNT 0x0080 /* force umount of this fserver */
+#define	FSRV_ERROR(fs)	((fs) && (((fs)->fs_flags & FSF_ERROR) == FSF_ERROR))
+#define	FSRV_ISDOWN(fs)	((fs) && (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID)))
+#define	FSRV_ISUP(fs)	(!(fs) || (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID)))
 
 /* some systems (SunOS 4.x) neglect to define the mount null message */
 #ifndef MOUNTPROC_NULL
 # define MOUNTPROC_NULL ((u_long)(0))
 #endif /* not MOUNTPROC_NULL */
 
+/*
+ * Error to return if remote host is not available.
+ * Try, in order, "host down", "host unreachable", "invalid argument".
+ */
+#ifdef EHOSTDOWN
+# define AM_ERRNO_HOST_DOWN	EHOSTDOWN
+#else /* not EHOSTDOWN */
+# ifdef EHOSTUNREACH
+#  define AM_ERRNO_HOST_DOWN	EHOSTUNREACH
+# else /* not EHOSTUNREACH */
+#  define AM_ERRNO_HOST_DOWN	EINVAL
+# endif /* not EHOSTUNREACH */
+#endif /* not EHOSTDOWN */
+
 /* Hash table size */
 #define NKVHASH (1 << 2)        /* Power of two */
 
+/* Max entries to return in one call */
+#define	MAX_READDIR_ENTRIES	16
+
+/*
+ * default amfs_auto retrans - 1/10th seconds
+ */
+#define	AMFS_AUTO_RETRANS(x)	((ALLOWED_MOUNT_TIME*10+5*gopt.amfs_auto_timeo[(x)])/gopt.amfs_auto_timeo[(x)] * 2)
+
+/*
+ * The following values can be tuned...
+ */
+#define	AM_TTL			(300) /* Default cache period (5 min) */
+#define	AM_TTL_W		(120) /* Default unmount interval (2 min) */
+#define	AM_PINGER		30 /* NFS ping interval for live systems */
+#define	AMFS_AUTO_TIMEO		8 /* Default amfs_auto timeout - .8s */
+#define AMFS_EXEC_MAP_TIMEOUT	10 /* default 10sec exec map timeout */
+
 /* interval between forced retries of a mount */
 #define RETRY_INTERVAL	2
 
-#define ereturn(x) { *error_return = x; return 0; }
+#ifndef ROOT_MAP
+# define ROOT_MAP "\"root\""
+#endif /* not ROOT_MAP */
+
+#define ereturn(x) do { *error_return = x; return 0; } while (0)
 
+#define NEVER (time_t) 0
+
+#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
+# define AMD_SERVICE_NAME "amd"	/* for tcpwrappers */
+#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
 
 /*
  * TYPEDEFS:
@@ -83,6 +210,16 @@
 
 typedef struct cf_map cf_map_t;
 typedef struct kv kv;
+typedef struct am_node am_node;
+typedef struct mntfs mntfs;
+typedef struct am_opts am_opts;
+typedef struct am_ops am_ops;
+typedef struct am_stats am_stats;
+typedef struct fserver fserver;
+
+typedef voidp wchan_t;
+typedef voidp opaque_t;
+
 /*
  * Cache map operations
  */
@@ -92,6 +229,28 @@ typedef int mtime_fn(mnt_map *, char *, time_t *);
 typedef int isup_fn(mnt_map *, char *);
 typedef int reload_fn(mnt_map *, char *, add_fn *);
 typedef int search_fn(mnt_map *, char *, char *, char **, time_t *);
+typedef int task_fun(opaque_t);
+typedef void cb_fun(int, int, opaque_t);
+typedef void fwd_fun(voidp, int, struct sockaddr_in *,
+		     struct sockaddr_in *, opaque_t, int);
+typedef int key_fun(char *, opaque_t);
+typedef void callout_fun(opaque_t);
+
+/*
+ * automounter vfs/vnode operations.
+ */
+typedef char *(*vfs_match) (am_opts *);
+typedef int (*vfs_init) (mntfs *);
+typedef int (*vmount_fs) (am_node *, mntfs *);
+typedef int (*vumount_fs) (am_node *, mntfs *);
+typedef am_node *(*vlookup_child) (am_node *, char *, int *, int);
+typedef am_node *(*vmount_child) (am_node *, int *);
+typedef int (*vreaddir) (am_node *, nfscookie, nfsdirlist *, nfsentry *, u_int);
+typedef am_node *(*vreadlink) (am_node *, int *);
+typedef void (*vmounted) (mntfs *);
+typedef void (*vumounted) (mntfs *);
+typedef fserver *(*vffserver) (mntfs *);
+typedef wchan_t (*vget_wchan) (mntfs *);
 
 
 
@@ -103,6 +262,7 @@ typedef int search_fn(mnt_map *, char *, char *, char **, time_t *);
 struct amu_global_options {
   char *arch;			/* name of current architecture */
   char *auto_dir;		/* automounter temp dir */
+  int auto_attrcache;		/* attribute cache timeout for auto dirs */
   char *cluster;		/* cluster name */
   char *karch;			/* kernel architecture */
   char *logfile;		/* amd log file */
@@ -112,16 +272,33 @@ struct amu_global_options {
   char *op_sys_vendor;		/* name of OS vendor ${vendor} */
   char *pid_file;		/* PID file */
   char *sub_domain;		/* local domain */
+  char *localhost_address;	/* localhost address (NULL means use 127.0.0.1) */
+  char *map_defaults;		/* global map /default options */
   char *map_options;		/* global map options */
+  int map_reload_interval;	/* map reload interval */
   char *map_type;		/* global map type */
   char *search_path;		/* search path for maps */
   char *mount_type;		/* mount type for map */
+  char *debug_mtab_file;        /* path for the mtab file during debug mode */
   u_int flags;			/* various CFM_* flags */
-  int amfs_auto_retrans;	/* NFS retransmit counter */
-  int amfs_auto_timeo;		/* NFS retry interval */
+
+#define AMU_TYPE_NONE -1	/* for amfs_auto_{timeo,retrans,toplvl} */
+#define AMU_TYPE_UDP 0		/* for amfs_auto_{timeo,retrans,toplvl} */
+#define AMU_TYPE_TCP 1		/* for amfs_auto_{timeo,retrans,toplvl} */
+  /*
+   * Note: toplvl is only UDP, but we want to separate it from regular
+   * NFS mounts which Amd makes, because the toplvl mount is a localhost
+   * mount for which different timeo/retrans parameters may be desired.
+   */
+#define AMU_TYPE_TOPLVL 2	/* for amfs_auto_{timeo,retrans,toplvl} */
+#define AMU_TYPE_MAX 3		/* for amfs_auto_{timeo,retrans,toplvl} */
+  int amfs_auto_retrans[AMU_TYPE_MAX]; /* NFS retransmit counter */
+  int amfs_auto_timeo[AMU_TYPE_MAX]; /* NFS retry interval */
+
   int am_timeo;			/* cache duration */
   int am_timeo_w;		/* dismount interval */
-  int portmap_program;		/* amd RPC program number */
+  u_long portmap_program;	/* amd RPC program number */
+  u_short preferred_amq_port;	/* preferred amq service RPC port number (0 means "any") */
 #ifdef HAVE_MAP_HESIOD
   char *hesiod_base;		/* Hesiod rhs */
 #endif /* HAVE_MAP_HESIOD */
@@ -130,10 +307,14 @@ struct amu_global_options {
   char *ldap_hostports;		/* LDAP host ports */
   long ldap_cache_seconds; 	/* LDAP internal cache - keep seconds */
   long ldap_cache_maxmem;	/* LDAP internal cache - max memory (bytes) */
+  long ldap_proto_version;	/* LDAP protocol version */
 #endif /* HAVE_MAP_LDAP */
 #ifdef HAVE_MAP_NIS
   char *nis_domain;		/* YP domain name */
 #endif /* HAVE_MAP_NIS */
+  char *nfs_proto;		/* NFS protocol (NULL, udp, tcp) */
+  int nfs_vers;			/* NFS version (0, 2, 3, 4) */
+  u_int exec_map_timeout;	/* timeout (seconds) for executable maps */
 };
 
 /* if you add anything here, update conf.c:reset_cf_map() */
@@ -141,10 +322,12 @@ struct cf_map {
   char *cfm_dir;		/* /home, /u, /src */
   char *cfm_name;		/* amd.home, /etc/amd.home ... */
   char *cfm_type;		/* file, hesiod, ndbm, nis ... */
+  char *cfm_defaults;		/* map /defaults options in amd.conf */
   char *cfm_opts;		/* -cache:=all, etc. */
   char *cfm_search_path;	/* /etc/local:/etc/amdmaps:/misc/yp */
   char *cfm_tag;		/* optional map tag for amd -T */
   u_int cfm_flags;		/* browsable_dirs? mount_type? */
+  struct cf_map *cfm_next;	/* pointer to next in list (if any) */
 };
 
 /*
@@ -173,52 +356,173 @@ struct mnt_map {
   search_fn *search;            /* Function to be used for searching */
   mtime_fn *mtime;              /* Modify time function */
   kv *kvhash[NKVHASH];          /* Cached data */
-  /* options available via amd conf file */
-  char *cf_map_type;            /* file, hesiod, ndbm, nis, etc. */
-  char *cf_search_path;         /* /etc/local:/etc/amdmaps:/misc/yp */
+  cf_map_t *cfm;		/* pointer to per-map amd.conf opts, if any */
   void *map_data;               /* Map data black box */
 };
 
 /*
- * Mounting a file system may take a significant period of time.  The
- * problem is that if this is done in the main process thread then the
- * entire automounter could be blocked, possibly hanging lots of processes
- * on the system.  Instead we use a continuation scheme to allow mounts to
- * be attempted in a sub-process.  When the sub-process exits we pick up the
- * exit status (by convention a UN*X error number) and continue in a
- * notifier.  The notifier gets handed a data structure and can then
- * determine whether the mount was successful or not.  If not, it updates
- * the data structure and tries again until there are no more ways to try
- * the mount, or some other permanent error occurs.  In the mean time no RPC
- * reply is sent, even after the mount is successful.  We rely on the RPC
- * retry mechanism to resend the lookup request which can then be handled.
- */
-struct continuation {
-  char **ivec;			/* Current mount info */
-  am_node *mp;			/* Node we are trying to mount */
-  char *key;			/* Map key */
-  char *info;			/* Info string */
-  char **xivec;			/* Saved strsplit vector */
-  char *auto_opts;		/* Automount options */
-  am_opts fs_opts;		/* Filesystem options */
-  char *def_opts;		/* Default automount options */
-  int retry;			/* Try again? */
-  int tried;			/* Have we tried any yet? */
-  time_t start;			/* Time we started this mount */
-  int callout;			/* Callout identifier */
+ * Options
+ */
+struct am_opts {
+  char *fs_glob;		/* Smashed copy of global options */
+  char *fs_local;		/* Expanded copy of local options */
+  char *fs_mtab;		/* Mount table entry */
+  /* Other options ... */
+  char *opt_dev;
+  char *opt_delay;
+  char *opt_dir;
+  char *opt_fs;
+  char *opt_group;
+  char *opt_mount;
+  char *opt_opts;
+  char *opt_remopts;
+  char *opt_pref;
+  char *opt_cache;
+  char *opt_rfs;
+  char *opt_rhost;
+  char *opt_sublink;
+  char *opt_type;
+  char *opt_mount_type;		/* "nfs" or "autofs" */
+  char *opt_unmount;
+  char *opt_umount;		/* an "alias" for opt_unmount (type:=program) */
+  char *opt_user;
+  char *opt_maptype;		/* map type: file, nis, hesiod, etc. */
+  char *opt_cachedir;		/* cache directory */
+  char *opt_addopts;		/* options to add to opt_opts */
+};
+
+struct am_ops {
+  char		*fs_type;	/* type of filesystems e.g. "nfsx" */
+  vfs_match	fs_match;	/* fxn: match */
+  vfs_init	fs_init;	/* fxn: initialization */
+  vmount_fs	mount_fs;	/* fxn: mount my own vnode */
+  vumount_fs	umount_fs;	/* fxn: unmount my own vnode */
+  vlookup_child	lookup_child;	/* fxn: lookup path-name */
+  vmount_child	mount_child;	/* fxn: mount path-name */
+  vreaddir	readdir;	/* fxn: read directory */
+  vreadlink	readlink;	/* fxn: read link */
+  vmounted	mounted;	/* fxn: after-mount extra actions */
+  vumounted	umounted;	/* fxn: after-umount extra actions */
+  vffserver	ffserver;	/* fxn: find a file server */
+  vget_wchan	get_wchan;	/* fxn: get the waiting channel */
+  int		nfs_fs_flags;	/* filesystem flags FS_* for nfs mounts */
+#ifdef HAVE_FS_AUTOFS
+  int		autofs_fs_flags;/* filesystem flags FS_* for autofs mounts */
+#endif /* HAVE_FS_AUTOFS */
+};
+
+/*
+ * List of mounted filesystems
+ */
+struct mntfs {
+  qelem mf_q;			/* List of mounted filesystems */
+  am_ops *mf_ops;		/* Operations on this mountpoint */
+  am_opts *mf_fo;		/* File opts */
+  char *mf_mount;		/* "/a/kiska/home/kiska" */
+  char *mf_info;		/* Mount info */
+  char *mf_auto;		/* Automount opts */
+  char *mf_mopts;		/* FS mount opts */
+  char *mf_remopts;		/* Remote FS mount opts */
+  char *mf_loopdev;		/* loop device name for /dev/loop mounts */
+  fserver *mf_server;		/* File server */
+  int mf_fsflags;		/* Flags FS_* copied from mf_ops->*_fs_flags */
+  int mf_flags;			/* Flags MFF_* */
+  int mf_error;			/* Error code from background mount */
+  int mf_refc;			/* Number of references to this node */
+  int mf_cid;			/* Callout id */
+  void (*mf_prfree) (opaque_t);	/* Free private space */
+  opaque_t mf_private;		/* Private - per-fs data */
+};
+
+/*
+ * List of fileservers
+ */
+struct fserver {
+  qelem fs_q;			/* List of fileservers */
+  int fs_refc;			/* Number of references to this server */
+  char *fs_host;		/* Normalized hostname of server */
+  struct sockaddr_in *fs_ip;	/* Network address of server */
+  int fs_cid;			/* Callout id */
+  int fs_pinger;		/* Ping (keepalive) interval */
+  int fs_flags;			/* Flags */
+  char *fs_type;		/* File server type */
+  u_long fs_version;		/* NFS version of server (2, 3, etc.)*/
+  char *fs_proto;		/* NFS protocol of server (tcp, udp, etc.) */
+  opaque_t fs_private;		/* Private data */
+  void (*fs_prfree) (opaque_t);	/* Free private data */
+};
+
+/*
+ * Per-mountpoint statistics
+ */
+struct am_stats {
+  time_t s_mtime;		/* Mount time */
+  u_short s_uid;		/* Uid of mounter */
+  int s_getattr;		/* Count of getattrs */
+  int s_lookup;			/* Count of lookups */
+  int s_readdir;		/* Count of readdirs */
+  int s_readlink;		/* Count of readlinks */
+  int s_statfs;			/* Count of statfs */
+};
+
+/*
+ * System statistics
+ */
+struct amd_stats {
+  int d_drops;			/* Dropped requests */
+  int d_stale;			/* Stale NFS handles */
+  int d_mok;			/* Successful mounts */
+  int d_merr;			/* Failed mounts */
+  int d_uerr;			/* Failed unmounts */
 };
+extern struct amd_stats amd_stats;
 
+/*
+ * Map of auto-mount points.
+ */
+struct am_node {
+  int am_mapno;		/* Map number */
+  mntfs *am_mnt;	/* Mounted filesystem */
+  mntfs **am_mfarray;	/* Filesystem sources to try to mount */
+  char *am_name;	/* "kiska": name of this node */
+  char *am_path;	/* "/home/kiska": path of this node's mount point */
+  char *am_link;	/* "/a/kiska/home/kiska/this/that": link to sub-dir */
+  am_node *am_parent;	/* Parent of this node */
+  am_node *am_ysib;	/* Younger sibling of this node */
+  am_node *am_osib;	/* Older sibling of this node */
+  am_node *am_child;	/* First child of this node */
+  nfsattrstat am_attr;	/* File attributes */
+#define am_fattr	am_attr.ns_u.ns_attr_u
+  int am_flags;		/* Boolean flags AMF_* */
+  int am_error;		/* Specific mount error */
+  time_t am_ttl;	/* Time to live */
+  int am_timeo_w;	/* Dismount wait interval */
+  int am_timeo;		/* Cache timeout interval */
+  u_int am_gen;		/* Generation number */
+  char *am_pref;	/* Mount info prefix */
+  am_stats am_stats;	/* Statistics gathering */
+  SVCXPRT *am_transp;	/* Info for quick reply */
+  dev_t am_dev;		/* Device number */
+  dev_t am_rdev;	/* Remote/real device number */
+#ifdef HAVE_FS_AUTOFS
+  autofs_fh_t *am_autofs_fh;
+  time_t am_autofs_ttl;	/* Time to expire autofs nodes */
+#endif /* HAVE_FS_AUTOFS */
+};
 
 /*
  * EXTERNALS:
  */
 
-/* Amq server global functions */
+/*
+ * Amq server global functions
+ */
 extern amq_mount_info_list *amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp);
 extern amq_mount_stats *amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp);
 extern amq_mount_tree_list *amqproc_export_1_svc(voidp argp, struct svc_req *rqstp);
 extern amq_mount_tree_p *amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp);
 extern amq_string *amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp);
+extern amq_string *amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp);
 extern int *amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp);
 extern int *amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp);
 extern int *amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp);
@@ -226,73 +530,224 @@ extern voidp amqproc_null_1_svc(voidp argp, struct svc_req *rqstp);
 extern voidp amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp);
 
 /* other external definitions */
-extern am_nfs_fh *root_fh(char *dir);
-extern am_node * autofs_lookuppn(am_node *mp, char *fname, int *error_return, int op);
+extern am_nfs_fh *get_root_nfs_fh(char *dir);
 extern am_node *find_ap(char *);
-extern am_node *find_ap2(char *, am_node *);
+extern am_node *get_ap_child(am_node *, char *);
 extern bool_t xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead);
 extern fserver *find_nfs_srvr(mntfs *mf);
-extern int auto_fmount(am_node *mp);
-extern int auto_fumount(am_node *mp);
-extern int mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf);
-extern int process_last_regular_map(void);
+extern int mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf);
+extern int process_all_regular_maps(void);
+extern cf_map_t *find_cf_map(const char *name);
 extern int set_conf_kv(const char *section, const char *k, const char *v);
-extern int try_mount(voidp mvp);
+extern int mount_node(opaque_t arg);
+extern int unmount_mp(am_node *mp);
 extern int yyparse (void);
-extern nfsentry *make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable);
-extern void amfs_auto_cont(int rc, int term, voidp closure);
-extern void amfs_auto_mkcacheref(mntfs *mf);
-extern void amfs_auto_retry(int rc, int term, voidp closure);
+
+extern void amfs_mkcacheref(mntfs *mf);
+extern int amfs_mount(am_node *mp, mntfs *mf, char *opts);
 extern void assign_error_mntfs(am_node *mp);
-extern void flush_srvr_nfs_cache(void);
-extern void free_continuation(struct continuation *cp);
-extern void mf_mounted(mntfs *mf);
-extern void quick_reply(am_node *mp, int error);
+extern am_node *next_nonerror_node(am_node *xp);
+extern void flush_srvr_nfs_cache(fserver *fs);
+extern void am_mounted(am_node *);
+extern void mf_mounted(mntfs *mf, bool_t call_free_opts);
+extern void am_unmounted(am_node *);
+extern am_node *get_exported_ap(int index);
+extern am_node *get_first_exported_ap(int *index);
+extern am_node *get_next_exported_ap(int *index);
+extern am_node *path_to_exported_ap(char *path);
+extern am_node *exported_ap_alloc(void);
+extern am_node *find_mf(mntfs *);
+extern am_node *next_map(int *);
+extern am_ops *ops_match(am_opts *, char *, char *, char *, char *, char *);
+extern am_ops *ops_search(char *);
+extern fserver *dup_srvr(fserver *);
+extern void srvrlog(fserver *, char *);
+extern int get_mountd_port(fserver *, u_short *, wchan_t);
+extern void flush_nfs_fhandle_cache(fserver *);
+
+extern mntfs *dup_mntfs(mntfs *);
+extern mntfs *find_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
+extern mntfs *locate_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
+extern mntfs *new_mntfs(void);
+extern mntfs *realloc_mntfs(mntfs *, am_ops *, am_opts *, char *, char *, char *, char *, char *);
+extern void flush_mntfs(void);
+extern void free_mntfs(voidp);
+
+
+extern void amq_program_1(struct svc_req *rqstp, SVCXPRT *transp);
+extern int  background(void);
+extern void deslashify(char *);
+extern void do_task_notify(void);
+extern int  eval_fs_opts(am_opts *, char *, char *, char *, char *, char *);
+extern void forcibly_timeout_mp(am_node *);
+extern void free_map(am_node *);
+extern void free_opts(am_opts *);
+extern void free_srvr(fserver *);
+extern int  fwd_init(void);
+extern int  fwd_packet(int, char *, int, struct sockaddr_in *, struct sockaddr_in *, opaque_t, fwd_fun *);
+extern void fwd_reply(void);
+extern void get_args(int argc, char *argv[]);
+extern wchan_t get_mntfs_wchan(mntfs *mf);
+extern void host_normalize(char **);
+extern void init_map(am_node *, char *);
+extern void ins_que(qelem *, qelem *);
+extern void insert_am(am_node *, am_node *);
+extern int  make_nfs_auth(void);
+extern void make_root_node(void);
+extern void map_flush_srvr(fserver *);
+extern void mapc_add_kv(mnt_map *, char *, char *);
+extern mnt_map *mapc_find(char *, char *, const char *);
+extern void mapc_free(opaque_t);
+extern int  mapc_keyiter(mnt_map *, key_fun, opaque_t);
+extern void mapc_reload(void);
+extern int  mapc_search(mnt_map *, char *, char **);
+extern void mapc_showtypes(char *buf, size_t l);
+extern int  mapc_type_exists(const char *type);
+extern void mk_fattr(nfsfattr *, nfsftype);
+extern int  mount_auto_node(char *, opaque_t);
+extern int  mount_automounter(int);
+extern int  mount_exported(void);
+extern void mp_to_fh(am_node *, am_nfs_fh *);
+extern void new_ttl(am_node *);
+extern void nfs_quick_reply(am_node *mp, int error);
+extern void normalize_slash(char *);
+extern void ops_showamfstypes(char *buf, size_t l);
+extern void ops_showfstypes(char *outbuf, size_t l);
+extern void rem_que(qelem *);
+extern void reschedule_timeout_mp(void);
+extern void restart(void);
+extern void restart_automounter_nodes(void);
+extern int  root_keyiter(key_fun *, opaque_t);
 extern void root_newmap(const char *, const char *, const char *, const cf_map_t *);
+extern void run_task(task_fun *, opaque_t, cb_fun *, opaque_t);
+extern void sched_task(cb_fun *, opaque_t, wchan_t);
+extern int  softclock(void);
+extern int  timeout(u_int, void (*fn)(opaque_t), opaque_t);
+extern void timeout_mp(opaque_t);
+extern void untimeout(int);
+extern void umount_exported(void);
+extern int  valid_key(char *);
+extern void wakeup(wchan_t);
+extern void wakeup_srvr(fserver *);
+extern void wakeup_task(int, int, wchan_t);
+#define SIZEOF_PID_FSNAME	(16 + MAXHOSTNAMELEN)
+extern char pid_fsname[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */
+#define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1)
+extern char hostd[SIZEOF_HOSTD]; /* Host+domain */
+#define SIZEOF_OPTS 256		/* used for char opts[] and preopts[] */
 
-/* amd global variables */
+/*
+ * Global variables.
+ */
 extern FILE *yyin;
-extern SVCXPRT *nfs_program_2_transp;	/* For quick_reply() */
+extern SVCXPRT *current_transp; /* For nfs_quick_reply() */
 extern char *conf_tag;
-extern int NumChild;
+#define SIZEOF_UID_STR	12
+#define SIZEOF_GID_STR	12
+extern char *opt_gid, gid_str[SIZEOF_GID_STR];
+extern char *opt_uid, uid_str[SIZEOF_UID_STR];
+extern int NumChildren;
 extern int fwd_sock;
 extern int select_intr_valid;
+extern int immediate_abort;	/* Should close-down unmounts be retried */
 extern int usage;
 extern int use_conf_file;	/* use amd configuration file */
+extern int task_notify_todo;	/* Task notifier needs running */
 extern jmp_buf select_intr;
 extern qelem mfhead;
-extern struct amu_global_options gopt;	/* where global options are stored */
+extern struct amu_global_options gopt; /* where global options are stored */
+extern time_t do_mapc_reload;	/* Flush & reload mount map cache */
+extern time_t next_softclock;	/* Time to call softclock() */
 
 #ifdef HAVE_SIGACTION
 extern sigset_t masked_sigs;
 #endif /* HAVE_SIGACTION */
 
-#if defined(HAVE_AM_FS_LINK) || defined(HAVE_AM_FS_LINKX)
+#if defined(HAVE_AMU_FS_LINK) || defined(HAVE_AMU_FS_LINKX)
 extern char *amfs_link_match(am_opts *fo);
-extern int amfs_link_fumount(mntfs *mf);
-#endif /* defined(HAVE_AM_FS_LINK) || defined(HAVE_AM_FS_LINKX) */
-
-#ifdef HAVE_AM_FS_NFSL
-extern char *nfs_match(am_opts *fo);
-#endif /* HAVE_AM_FS_NFSL */
-
-#if defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3)
-extern bool_t xdr_mountres3(XDR *xdrs, mountres3 *objp);
-#endif /* defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3) */
+#endif /* defined(HAVE_AMU_FS_LINK) || defined(HAVE_AMU_FS_LINKX) */
 
 #ifdef HAVE_FS_AUTOFS
-extern SVCXPRT *autofsxprt;
-extern u_short autofs_port;
 extern int amd_use_autofs;
 
-extern int autofs_mount(am_node *mp);
-extern int autofs_umount(am_node *mp);
-extern int create_autofs_service(int *soAUTOFSp, u_short *autofs_portp, SVCXPRT **autofs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp));
-extern int svc_create_local_service(void (*dispatch) (), u_long prognum, u_long versnum, char *nettype, char *servname);
-extern void autofs_mounted(mntfs *mf);
-extern void autofs_program_1(struct svc_req *rqstp, SVCXPRT *transp);
+extern int autofs_get_fh(am_node *mp);
+extern void autofs_release_fh(am_node *mp);
+extern void autofs_get_mp(am_node *mp);
+extern void autofs_release_mp(am_node *mp);
+extern void autofs_add_fdset(fd_set *readfds);
+extern int autofs_handle_fdset(fd_set *readfds, int nsel);
+extern void autofs_mounted(am_node *mp);
+extern void autofs_mount_succeeded(am_node *mp);
+extern void autofs_mount_failed(am_node *mp);
+extern int autofs_umount_succeeded(am_node *mp);
+extern int autofs_umount_failed(am_node *mp);
+extern int autofs_mount_fs(am_node *mp, mntfs *mf);
+extern int autofs_umount_fs(am_node *mp, mntfs *mf);
+extern void autofs_get_opts(char *opts, size_t l, autofs_fh_t *fh);
+extern int autofs_compute_mount_flags(mntent_t *);
+extern void autofs_timeout_mp(am_node *);
+extern int create_autofs_service(void);
+extern int destroy_autofs_service(void);
 #endif /* HAVE_FS_AUTOFS */
 
+/**************************************************************************/
+/*** Generic file-system types, implemented as part of the native O/S.	***/
+/**************************************************************************/
+
+/*
+ * Loopback File System
+ * Many systems can't support this, and in any case most of the
+ * functionality is available with Symlink FS.
+ */
+#ifdef HAVE_FS_LOFS
+extern am_ops lofs_ops;
+extern int mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs);
+#endif /* HAVE_FS_LOFS */
+
+/*
+ * CD-ROM File System (CD-ROM)
+ * (HSFS: High Sierra F/S on some machines)
+ * Many systems can't support this, and in any case most of the
+ * functionality is available with program FS.
+ */
+#ifdef HAVE_FS_CDFS
+extern am_ops cdfs_ops;
+#endif /* HAVE_FS_CDFS */
+
+/*
+ * PC File System (MS-DOS)
+ * Many systems can't support this, and in any case most of the
+ * functionality is available with program FS.
+ */
+#ifdef HAVE_FS_PCFS
+extern am_ops pcfs_ops;
+#endif /* HAVE_FS_PCFS */
+
+/*
+ * Caching File System (Solaris)
+ */
+#ifdef HAVE_FS_CACHEFS
+extern am_ops cachefs_ops;
+#endif /* HAVE_FS_CACHEFS */
+
+/*
+ * Network File System
+ * Good, slow, NFS V.2.
+ */
+#ifdef HAVE_FS_NFS
+extern am_ops nfs_ops;		/* NFS */
+extern fserver *find_nfs_srvr (mntfs *);
+extern qelem nfs_srvr_list;
+#endif /* HAVE_FS_NFS */
+
+/*
+ * Un*x File System
+ * Normal local disk file system.
+ */
+#ifdef HAVE_FS_UFS
+extern am_ops ufs_ops;		/* Un*x file system */
+#endif /* HAVE_FS_UFS */
+
 /* Unix file system (irix) */
 #ifdef HAVE_FS_XFS
 extern am_ops xfs_ops;		/* Un*x file system */
@@ -303,4 +758,110 @@ extern am_ops xfs_ops;		/* Un*x file system */
 extern am_ops efs_ops;		/* Un*x file system */
 #endif /* HAVE_FS_EFS */
 
+/**************************************************************************/
+/*** Automounter file-system types, implemented by amd.			***/
+/**************************************************************************/
+
+/*
+ * Root AMD File System
+ */
+extern am_ops amfs_root_ops;	/* Root file system */
+
+/*
+ * Generic amfs helper methods
+ */
+extern am_node *amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op);
+extern am_node *amfs_generic_mount_child(am_node *ap, int *error_return);
+extern int amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count);
+extern int amfs_generic_umount(am_node *mp, mntfs *mf);
+extern void amfs_generic_mounted(mntfs *mf);
+extern char *amfs_generic_match(am_opts *fo);
+extern fserver *amfs_generic_find_srvr(mntfs *);
+
+/*
+ * Automount File System
+ */
+#ifdef HAVE_AMU_FS_AUTO
+extern am_ops amfs_auto_ops;	/* Automount file system (this!) */
+#endif /* HAVE_AMU_FS_AUTO */
+
+/*
+ * Toplvl Automount File System
+ */
+#ifdef HAVE_AMU_FS_TOPLVL
+extern am_ops amfs_toplvl_ops;	/* Toplvl Automount file system */
+extern int amfs_toplvl_mount(am_node *mp, mntfs *mf);
+extern int amfs_toplvl_umount(am_node *mp, mntfs *mf);
+#endif /* HAVE_AMU_FS_TOPLVL */
+
+/*
+ * Direct Automount File System
+ */
+#ifdef HAVE_AMU_FS_DIRECT
+extern am_ops amfs_direct_ops;	/* Direct Automount file system (this too) */
+#endif /* HAVE_AMU_FS_DIRECT */
+
+/*
+ * Error File System
+ */
+#ifdef HAVE_AMU_FS_ERROR
+extern am_ops amfs_error_ops;	/* Error file system */
+extern am_node *amfs_error_lookup_child(am_node *mp, char *fname, int *error_return, int op);
+extern am_node *amfs_error_mount_child(am_node *ap, int *error_return);
+extern int amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count);
+#endif /* HAVE_AMU_FS_ERROR */
+
+/*
+ * NFS mounts with local existence check.
+ */
+#ifdef HAVE_AMU_FS_NFSL
+extern am_ops amfs_nfsl_ops;	/* NFSL */
+#endif /* HAVE_AMU_FS_NFSL */
+
+/*
+ * Multi-nfs mounts.
+ */
+#ifdef HAVE_AMU_FS_NFSX
+extern am_ops amfs_nfsx_ops;	/* NFSX */
+#endif /* HAVE_AMU_FS_NFSX */
+
+/*
+ * NFS host - a whole tree.
+ */
+#ifdef HAVE_AMU_FS_HOST
+extern am_ops amfs_host_ops;	/* NFS host */
+#endif /* HAVE_AMU_FS_HOST */
+
+/*
+ * Program File System
+ * This is useful for things like RVD.
+ */
+#ifdef HAVE_AMU_FS_PROGRAM
+extern am_ops amfs_program_ops;	/* Program File System */
+#endif /* HAVE_AMU_FS_PROGRAM */
+
+/*
+ * Symbolic-link file system.
+ * A "filesystem" which is just a symbol link.
+ */
+#ifdef HAVE_AMU_FS_LINK
+extern am_ops amfs_link_ops;	/* Symlink FS */
+#endif /* HAVE_AMU_FS_LINK */
+
+/*
+ * Symbolic-link file system, which also checks that the target of
+ * the symlink exists.
+ * A "filesystem" which is just a symbol link.
+ */
+#ifdef HAVE_AMU_FS_LINKX
+extern am_ops amfs_linkx_ops;	/* Symlink FS with existence check */
+#endif /* HAVE_AMU_FS_LINKX */
+
+/*
+ * Union file system
+ */
+#ifdef HAVE_AMU_FS_UNION
+extern am_ops amfs_union_ops;	/* Union FS */
+#endif /* HAVE_AMU_FS_UNION */
+
 #endif /* not _AMD_H */
diff --git a/contrib/amd/amd/amfs_auto.c b/contrib/amd/amd/amfs_auto.c
index f04cc50..75a451f 100644
--- a/contrib/amd/amd/amfs_auto.c
+++ b/contrib/amd/amd/amfs_auto.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_auto.c,v 1.5 1999/09/30 21:01:29 ezk Exp $
+ * File: am-utils/amd/amfs_auto.c
  *
  */
 
@@ -55,12 +54,7 @@
 /****************************************************************************
  *** MACROS                                                               ***
  ****************************************************************************/
-#define	IN_PROGRESS(cp) ((cp)->mp->am_mnt->mf_flags & MFF_MOUNTING)
 
-/* DEVELOPERS: turn this on for special debugging of readdir code */
-#undef DEBUG_READDIR
-
-#define DOT_DOT_COOKIE (u_int) 1
 
 /****************************************************************************
  *** STRUCTURES                                                           ***
@@ -70,10 +64,7 @@
 /****************************************************************************
  *** FORWARD DEFINITIONS                                                  ***
  ****************************************************************************/
-static int amfs_auto_bgmount(struct continuation * cp, int mpe);
-static int amfs_auto_mount(am_node *mp);
-static int amfs_auto_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count, int fully_browsable);
-static void amfs_auto_umounted(am_node *mp);
+static int amfs_auto_mount(am_node *mp, mntfs *mf);
 
 
 /****************************************************************************
@@ -82,19 +73,22 @@ static void amfs_auto_umounted(am_node *mp);
 am_ops amfs_auto_ops =
 {
   "auto",
-  amfs_auto_match,
+  amfs_generic_match,
   0,				/* amfs_auto_init */
   amfs_auto_mount,
-  0,
-  amfs_auto_umount,
-  0,
-  amfs_auto_lookuppn,
-  amfs_auto_readdir,
+  amfs_generic_umount,
+  amfs_generic_lookup_child,
+  amfs_generic_mount_child,
+  amfs_generic_readdir,
   0,				/* amfs_auto_readlink */
-  0,				/* amfs_auto_mounted */
-  amfs_auto_umounted,
-  find_amfs_auto_srvr,
-  FS_AMQINFO | FS_DIRECTORY
+  amfs_generic_mounted,
+  0,				/* amfs_auto_umounted */
+  amfs_generic_find_srvr,
+  0,				/* amfs_auto_get_wchan */
+  FS_AMQINFO | FS_DIRECTORY,
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_AUTO_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -102,65 +96,11 @@ am_ops amfs_auto_ops =
  *** FUNCTIONS                                                             ***
  ****************************************************************************/
 /*
- * AMFS_AUTO needs nothing in particular.
- */
-char *
-amfs_auto_match(am_opts *fo)
-{
-  char *p = fo->opt_rfs;
-
-  if (!fo->opt_rfs) {
-    plog(XLOG_USER, "auto: no mount point named (rfs:=)");
-    return 0;
-  }
-  if (!fo->opt_fs) {
-    plog(XLOG_USER, "auto: no map named (fs:=)");
-    return 0;
-  }
-
-  /*
-   * Swap round fs:= and rfs:= options
-   * ... historical (jsp)
-   */
-  fo->opt_rfs = fo->opt_fs;
-  fo->opt_fs = p;
-
-  /*
-   * mtab entry turns out to be the name of the mount map
-   */
-  return strdup(fo->opt_rfs ? fo->opt_rfs : ".");
-}
-
-
-
-
-/*
- * Build a new map cache for this node, or re-use
- * an existing cache for the same map.
- */
-void
-amfs_auto_mkcacheref(mntfs *mf)
-{
-  char *cache;
-
-  if (mf->mf_fo && mf->mf_fo->opt_cache)
-    cache = mf->mf_fo->opt_cache;
-  else
-    cache = "none";
-  mf->mf_private = (voidp) mapc_find(mf->mf_info, cache,
-				     mf->mf_fo->opt_maptype);
-  mf->mf_prfree = mapc_free;
-}
-
-
-/*
  * Mount a sub-mount
  */
 static int
-amfs_auto_mount(am_node *mp)
+amfs_auto_mount(am_node *mp, mntfs *mf)
 {
-  mntfs *mf = mp->am_mnt;
-
   /*
    * Pseudo-directories are used to provide some structure
    * to the automounted directories instead
@@ -191,7 +131,7 @@ amfs_auto_mount(am_node *mp)
   if (mf->mf_fo->opt_pref) {
     /* allow pref:=null to set a real null prefix */
     if (STREQ(mf->mf_fo->opt_pref, "null")) {
-      mp->am_pref = "";
+      mp->am_pref = strdup("");
     } else {
       /*
        * the prefix specified as an option
@@ -210,1396 +150,27 @@ amfs_auto_mount(am_node *mp)
     mp->am_pref = str3cat((char *) 0, ppref, mp->am_name, "/");
   }
 
-  /*
-   * Attach a map cache
-   */
-  amfs_auto_mkcacheref(mf);
-
-  return 0;
-}
-
-
-
-
-/*
- * Unmount an automount sub-node
- */
-int
-amfs_auto_umount(am_node *mp)
-{
-  return 0;
-}
-
-
-/*
- * Unmount an automount node
- */
-static void
-amfs_auto_umounted(am_node *mp)
-{
-  /*
-   * If this is a pseudo-directory then just adjust the link count
-   * in the parent, otherwise call the generic unmount routine
-   */
-  if (mp->am_parent && mp->am_parent->am_parent)
-    --mp->am_parent->am_fattr.na_nlink;
-}
-
-
-/*
- * Discard an old continuation
- */
-void
-free_continuation(struct continuation *cp)
-{
-  if (cp->callout)
-    untimeout(cp->callout);
-  XFREE(cp->key);
-  XFREE(cp->xivec);
-  XFREE(cp->info);
-  XFREE(cp->auto_opts);
-  XFREE(cp->def_opts);
-  free_opts(&cp->fs_opts);
-  XFREE(cp);
-}
-
-
-/*
- * Discard the underlying mount point and replace
- * with a reference to an error filesystem.
- */
-void
-assign_error_mntfs(am_node *mp)
-{
-  if (mp->am_error > 0) {
-    /*
-     * Save the old error code
-     */
-    int error = mp->am_error;
-    if (error <= 0)
-      error = mp->am_mnt->mf_error;
-    /*
-     * Discard the old filesystem
-     */
-    free_mntfs(mp->am_mnt);
-    /*
-     * Allocate a new error reference
-     */
-    mp->am_mnt = new_mntfs();
-    /*
-     * Put back the error code
-     */
-    mp->am_mnt->mf_error = error;
-    mp->am_mnt->mf_flags |= MFF_ERROR;
-    /*
-     * Zero the error in the mount point
-     */
-    mp->am_error = 0;
-  }
-}
-
-
-/*
- * The continuation function.  This is called by
- * the task notifier when a background mount attempt
- * completes.
- */
-void
-amfs_auto_cont(int rc, int term, voidp closure)
-{
-  struct continuation *cp = (struct continuation *) closure;
-  mntfs *mf = cp->mp->am_mnt;
-
-  /*
-   * Definitely not trying to mount at the moment
-   */
-  mf->mf_flags &= ~MFF_MOUNTING;
-
-  /*
-   * While we are mounting - try to avoid race conditions
-   */
-  new_ttl(cp->mp);
-
-  /*
-   * Wakeup anything waiting for this mount
-   */
-  wakeup((voidp) mf);
-
-  /*
-   * Check for termination signal or exit status...
-   */
-  if (rc || term) {
-    am_node *xmp;
-
-    if (term) {
-      /*
-       * Not sure what to do for an error code.
-       */
-      mf->mf_error = EIO;	/* XXX ? */
-      mf->mf_flags |= MFF_ERROR;
-      plog(XLOG_ERROR, "mount for %s got signal %d", cp->mp->am_path, term);
-    } else {
-      /*
-       * Check for exit status...
-       */
-      mf->mf_error = rc;
-      mf->mf_flags |= MFF_ERROR;
-      errno = rc;		/* XXX */
-      if (!STREQ(cp->mp->am_mnt->mf_ops->fs_type, "linkx"))
-	plog(XLOG_ERROR, "%s: mount (amfs_auto_cont): %m", cp->mp->am_path);
-    }
-
-    /*
-     * If we get here then that attempt didn't work, so
-     * move the info vector pointer along by one and
-     * call the background mount routine again
-     */
-    amd_stats.d_merr++;
-    cp->ivec++;
-    xmp = cp->mp;
-    (void) amfs_auto_bgmount(cp, 0);
-    assign_error_mntfs(xmp);
-  } else {
-    /*
-     * The mount worked.
-     */
-    am_mounted(cp->mp);
-    free_continuation(cp);
-  }
-
-  reschedule_timeout_mp();
-}
-
-
-/*
- * Retry a mount
- */
-void
-amfs_auto_retry(int rc, int term, voidp closure)
-{
-  struct continuation *cp = (struct continuation *) closure;
-  int error = 0;
-
-#ifdef DEBUG
-  dlog("Commencing retry for mount of %s", cp->mp->am_path);
-#endif /* DEBUG */
-
-  new_ttl(cp->mp);
-
-  if ((cp->start + ALLOWED_MOUNT_TIME) < clocktime()) {
-    /*
-     * The entire mount has timed out.  Set the error code and skip past all
-     * the info vectors so that amfs_auto_bgmount will not have any more
-     * ways to try the mount, so causing an error.
-     */
-    plog(XLOG_INFO, "mount of \"%s\" has timed out", cp->mp->am_path);
-    error = ETIMEDOUT;
-    while (*cp->ivec)
-      cp->ivec++;
-    /* explicitly forbid further retries after timeout */
-    cp->retry = FALSE;
-  }
-  if (error || !IN_PROGRESS(cp)) {
-    (void) amfs_auto_bgmount(cp, error);
-  }
-  reschedule_timeout_mp();
-}
-
-
-/*
- * Try to mount a file system.  Can be called
- * directly or in a sub-process by run_task.
- */
-int
-try_mount(voidp mvp)
-{
-  int error = 0;
-  am_node *mp = (am_node *) mvp;
-  mntfs *mf = mp->am_mnt;
-
-  /*
-   * If the directory is not yet made and it needs to be made, then make it!
-   * This may be run in a background process in which case the flag setting
-   * won't be noticed later - but it is set anyway just after run_task is
-   * called.  It should probably go away totally...
-   */
-  if (!(mf->mf_flags & MFF_MKMNT) && mf->mf_ops->fs_flags & FS_MKMNT) {
-    error = mkdirs(mf->mf_mount, 0555);
-    if (!error)
-      mf->mf_flags |= MFF_MKMNT;
-  }
-
-  /*
-   * Mount it!
-   */
-  error = mount_node(mp);
-
-#ifdef DEBUG
-  if (error > 0) {
-    errno = error;
-    dlog("amfs_auto call to mount_node failed: %m");
-  }
-#endif /* DEBUG */
-
-  return error;
-}
-
-
-/*
- * Pick a file system to try mounting and
- * do that in the background if necessary
- *
-For each location:
-	if it is new -defaults then
-		extract and process
-		continue;
-	fi
-	if it is a cut then
-		if a location has been tried then
-			break;
-		fi
-		continue;
-	fi
-	parse mount location
-	discard previous mount location if required
-	find matching mounted filesystem
-	if not applicable then
-		this_error = No such file or directory
-		continue
-	fi
-	if the filesystem failed to be mounted then
-		this_error = error from filesystem
-	elif the filesystem is mounting or unmounting then
-		this_error = -1
-	elif the fileserver is down then
-		this_error = -1
-	elif the filesystem is already mounted
-		this_error = 0
-		break
-	fi
-	if no error on this mount then
-		this_error = initialize mount point
-	fi
-	if no error on this mount and mount is delayed then
-		this_error = -1
-	fi
-	if this_error < 0 then
-		retry = true
-	fi
-	if no error on this mount then
-		make mount point if required
-	fi
-	if no error on this mount then
-		if mount in background then
-			run mount in background
-			return -1
-		else
-			this_error = mount in foreground
-		fi
-	fi
-	if an error occurred on this mount then
-		update stats
-		save error in mount point
-	fi
-endfor
- */
-static int
-amfs_auto_bgmount(struct continuation * cp, int mpe)
-{
-  mntfs *mf = cp->mp->am_mnt;	/* Current mntfs */
-  mntfs *mf_retry = 0;		/* First mntfs which needed retrying */
-  int this_error = -1;		/* Per-mount error */
-  int hard_error = -1;
-  int mp_error = mpe;
-
-  /*
-   * Try to mount each location.
-   * At the end:
-   * hard_error == 0 indicates something was mounted.
-   * hard_error > 0 indicates everything failed with a hard error
-   * hard_error < 0 indicates nothing could be mounted now
-   */
-  for (; this_error && *cp->ivec; cp->ivec++) {
-    am_ops *p;
-    am_node *mp = cp->mp;
-    char *link_dir;
-    int dont_retry;
-
-    if (hard_error < 0)
-      hard_error = this_error;
-
-    this_error = -1;
-
-    if (**cp->ivec == '-') {
-      /*
-       * Pick up new defaults
-       */
-      if (cp->auto_opts && *cp->auto_opts)
-	cp->def_opts = str3cat(cp->def_opts, cp->auto_opts, ";", *cp->ivec + 1);
-      else
-	cp->def_opts = strealloc(cp->def_opts, *cp->ivec + 1);
-#ifdef DEBUG
-      dlog("Setting def_opts to \"%s\"", cp->def_opts);
-#endif /* DEBUG */
-      continue;
-    }
-    /*
-     * If a mount has been attempted, and we find
-     * a cut then don't try any more locations.
-     */
-    if (STREQ(*cp->ivec, "/") || STREQ(*cp->ivec, "||")) {
-      if (cp->tried) {
-#ifdef DEBUG
-	dlog("Cut: not trying any more locations for %s",
-	     mp->am_path);
-#endif /* DEBUG */
-	break;
-      }
-      continue;
-    }
-
-    /* match the operators */
-    p = ops_match(&cp->fs_opts, *cp->ivec, cp->def_opts, mp->am_path, cp->key, mp->am_parent->am_mnt->mf_info);
-
-    /*
-     * Find a mounted filesystem for this node.
-     */
-    mp->am_mnt = mf = realloc_mntfs(mf, p, &cp->fs_opts,
-				    cp->fs_opts.opt_fs,
-				    cp->fs_opts.fs_mtab,
-				    cp->auto_opts,
-				    cp->fs_opts.opt_opts,
-				    cp->fs_opts.opt_remopts);
-
-    p = mf->mf_ops;
-#ifdef DEBUG
-    dlog("Got a hit with %s", p->fs_type);
-#endif /* DEBUG */
-
-    /*
-     * Note whether this is a real mount attempt
-     */
-    if (p == &amfs_error_ops) {
-      plog(XLOG_MAP, "Map entry %s for %s failed to match", *cp->ivec, mp->am_path);
-      if (this_error <= 0)
-	this_error = ENOENT;
-      continue;
-    } else {
-      if (cp->fs_opts.fs_mtab) {
-	plog(XLOG_MAP, "Trying mount of %s on %s fstype %s",
-	     cp->fs_opts.fs_mtab, mp->am_path, p->fs_type);
-      }
-      cp->tried = TRUE;
-    }
-
-    this_error = 0;
-    dont_retry = FALSE;
-
-    if (mp->am_link) {
-      XFREE(mp->am_link);
-      mp->am_link = 0;
-    }
-    link_dir = mf->mf_fo->opt_sublink;
-
-    if (link_dir && *link_dir) {
-      if (*link_dir == '/') {
-	mp->am_link = strdup(link_dir);
-      } else {
-	/*
-	 * try getting fs option from continuation, not mountpoint!
-	 * Don't try logging the string from mf, since it may be bad!
-	 */
-	if (cp->fs_opts.opt_fs != mf->mf_fo->opt_fs)
-	  plog(XLOG_ERROR, "use %s instead of 0x%lx",
-	       cp->fs_opts.opt_fs, (unsigned long) mf->mf_fo->opt_fs);
-
-	mp->am_link = str3cat((char *) 0,
-			      cp->fs_opts.opt_fs, "/", link_dir);
-
-	normalize_slash(mp->am_link);
-      }
-    }
-
-    if (mf->mf_error > 0) {
-      this_error = mf->mf_error;
-    } else if (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)) {
-      /*
-       * Still mounting - retry later
-       */
-#ifdef DEBUG
-      dlog("Duplicate pending mount fstype %s", p->fs_type);
-#endif /* DEBUG */
-      this_error = -1;
-    } else if (FSRV_ISDOWN(mf->mf_server)) {
-      /*
-       * Would just mount from the same place
-       * as a hung mount - so give up
-       */
-#ifdef DEBUG
-      dlog("%s is already hung - giving up", mf->mf_mount);
-#endif /* DEBUG */
-      mp_error = EWOULDBLOCK;
-      dont_retry = TRUE;
-      this_error = -1;
-    } else if (mf->mf_flags & MFF_MOUNTED) {
-#ifdef DEBUG
-      dlog("duplicate mount of \"%s\" ...", mf->mf_info);
-#endif /* DEBUG */
-
-      /*
-       * Just call mounted()
-       */
-      am_mounted(mp);
-
-      this_error = 0;
-      break;
-    }
-
-    /*
-     * Will usually need to play around with the mount nodes
-     * file attribute structure.  This must be done here.
-     * Try and get things initialized, even if the fileserver
-     * is not known to be up.  In the common case this will
-     * progress things faster.
-     */
-    if (!this_error) {
-      /*
-       * Fill in attribute fields.
-       */
-      if (mf->mf_ops->fs_flags & FS_DIRECTORY)
-	mk_fattr(mp, NFDIR);
-      else
-	mk_fattr(mp, NFLNK);
-
-      mp->am_fattr.na_fileid = mp->am_gen;
-
-      if (p->fs_init)
-	this_error = (*p->fs_init) (mf);
-    }
-
-    /*
-     * Make sure the fileserver is UP before doing any more work
-     */
-    if (!FSRV_ISUP(mf->mf_server)) {
-#ifdef DEBUG
-      dlog("waiting for server %s to become available", mf->mf_server->fs_host);
-#endif /* DEBUG */
-      this_error = -1;
-    }
-
-    if (!this_error && mf->mf_fo->opt_delay) {
-      /*
-       * If there is a delay timer on the mount
-       * then don't try to mount if the timer
-       * has not expired.
-       */
-      int i = atoi(mf->mf_fo->opt_delay);
-      if (i > 0 && clocktime() < (cp->start + i)) {
-#ifdef DEBUG
-	dlog("Mount of %s delayed by %lds", mf->mf_mount, (long) (i - clocktime() + cp->start));
-#endif /* DEBUG */
-	this_error = -1;
-      }
-    }
-
-    if (this_error < 0 && !dont_retry) {
-      if (!mf_retry)
-	mf_retry = dup_mntfs(mf);
-      cp->retry = TRUE;
-#ifdef DEBUG
-      dlog("will retry ...\n");
-#endif /* DEBUG */
-      break;
-    }
-
-    if (!this_error) {
-      if (p->fs_flags & FS_MBACKGROUND) {
-	mf->mf_flags |= MFF_MOUNTING;	/* XXX */
-#ifdef DEBUG
-	dlog("backgrounding mount of \"%s\"", mf->mf_mount);
-#endif /* DEBUG */
-	if (cp->callout) {
-	  untimeout(cp->callout);
-	  cp->callout = 0;
-	}
-	run_task(try_mount, (voidp) mp, amfs_auto_cont, (voidp) cp);
-	mf->mf_flags |= MFF_MKMNT;	/* XXX */
-	if (mf_retry)
-	  free_mntfs(mf_retry);
-	return -1;
-      } else {
-#ifdef DEBUG
-	dlog("foreground mount of \"%s\" ...", mf->mf_info);
-#endif /* DEBUG */
-	this_error = try_mount((voidp) mp);
-	if (this_error < 0) {
-	  if (!mf_retry)
-	    mf_retry = dup_mntfs(mf);
-	  cp->retry = TRUE;
-	}
-      }
-    }
-
-    if (this_error >= 0) {
-      if (this_error > 0) {
-	amd_stats.d_merr++;
-	if (mf != mf_retry) {
-	  mf->mf_error = this_error;
-	  mf->mf_flags |= MFF_ERROR;
-	}
-      }
-
-      /*
-       * Wakeup anything waiting for this mount
-       */
-      wakeup((voidp) mf);
-    }
-  }
-
-  if (this_error && cp->retry) {
-    free_mntfs(mf);
-    mf = cp->mp->am_mnt = mf_retry;
-    /*
-     * Not retrying again (so far)
-     */
-    cp->retry = FALSE;
-    cp->tried = FALSE;
-    /*
-     * Start at the beginning.
-     * Rewind the location vector and
-     * reset the default options.
-     */
-#ifdef DEBUG
-    dlog("(skipping rewind)\n");
-#endif /* DEBUG */
-    /*
-     * Arrange that amfs_auto_bgmount is called
-     * after anything else happens.
-     */
-#ifdef DEBUG
-    dlog("Arranging to retry mount of %s", cp->mp->am_path);
-#endif /* DEBUG */
-    sched_task(amfs_auto_retry, (voidp) cp, (voidp) mf);
-    if (cp->callout)
-      untimeout(cp->callout);
-    cp->callout = timeout(RETRY_INTERVAL, wakeup, (voidp) mf);
-
-    cp->mp->am_ttl = clocktime() + RETRY_INTERVAL;
-
-    /*
-     * Not done yet - so don't return anything
-     */
-    return -1;
-  }
-
-  if (hard_error < 0 || this_error == 0)
-    hard_error = this_error;
-
-  /*
-   * Discard handle on duff filesystem.
-   * This should never happen since it
-   * should be caught by the case above.
-   */
-  if (mf_retry) {
-    if (hard_error)
-      plog(XLOG_ERROR, "discarding a retry mntfs for %s", mf_retry->mf_mount);
-    free_mntfs(mf_retry);
-  }
-
-  /*
-   * If we get here, then either the mount succeeded or
-   * there is no more mount information available.
-   */
-  if (hard_error < 0 && mp_error)
-    hard_error = cp->mp->am_error = mp_error;
-  if (hard_error > 0) {
-    /*
-     * Set a small(ish) timeout on an error node if
-     * the error was not a time out.
-     */
-    switch (hard_error) {
-    case ETIMEDOUT:
-    case EWOULDBLOCK:
-      cp->mp->am_timeo = 17;
-      break;
-    default:
-      cp->mp->am_timeo = 5;
-      break;
-    }
-    new_ttl(cp->mp);
-  }
-
-  /*
-   * Make sure that the error value in the mntfs has a
-   * reasonable value.
-   */
-  if (mf->mf_error < 0) {
-    mf->mf_error = hard_error;
-    if (hard_error)
-      mf->mf_flags |= MFF_ERROR;
-  }
-
-  /*
-   * In any case we don't need the continuation any more
-   */
-  free_continuation(cp);
-
-  return hard_error;
-}
-
-
-/*
- * Automount interface to RPC lookup routine
- * Find the corresponding entry and return
- * the file handle for it.
- */
-am_node *
-amfs_auto_lookuppn(am_node *mp, char *fname, int *error_return, int op)
-{
-  am_node *ap, *new_mp, *ap_hung;
-  char *info;			/* Mount info - where to get the file system */
-  char **ivec, **xivec;		/* Split version of info */
-  char *auto_opts;		/* Automount options */
-  int error = 0;		/* Error so far */
-  char path_name[MAXPATHLEN];	/* General path name buffer */
-  char *pfname;			/* Path for database lookup */
-  struct continuation *cp;	/* Continuation structure if need to mount */
-  int in_progress = 0;		/* # of (un)mount in progress */
-  char *dflts;
-  mntfs *mf;
-
-#ifdef DEBUG
-  dlog("in amfs_auto_lookuppn");
-#endif /* DEBUG */
-
-  /*
-   * If the server is shutting down
-   * then don't return information
-   * about the mount point.
-   */
-  if (amd_state == Finishing) {
-#ifdef DEBUG
-    if ((mf = mp->am_mnt) == 0 || mf->mf_ops == &amfs_direct_ops) {
-      dlog("%s mount ignored - going down", fname);
-    } else {
-      dlog("%s/%s mount ignored - going down", mp->am_path, fname);
-    }
-#endif /* DEBUG */
-    ereturn(ENOENT);
-  }
-
-  /*
-   * Handle special case of "." and ".."
-   */
-  if (fname[0] == '.') {
-    if (fname[1] == '\0')
-      return mp;		/* "." is the current node */
-    if (fname[1] == '.' && fname[2] == '\0') {
-      if (mp->am_parent) {
-#ifdef DEBUG
-	dlog(".. in %s gives %s", mp->am_path, mp->am_parent->am_path);
-#endif /* DEBUG */
-	return mp->am_parent;	/* ".." is the parent node */
-      }
-      ereturn(ESTALE);
-    }
-  }
-
-  /*
-   * Check for valid key name.
-   * If it is invalid then pretend it doesn't exist.
-   */
-  if (!valid_key(fname)) {
-    plog(XLOG_WARNING, "Key \"%s\" contains a disallowed character", fname);
-    ereturn(ENOENT);
-  }
-
-  /*
-   * Expand key name.
-   * fname is now a private copy.
-   */
-  fname = expand_key(fname);
-
-  for (ap_hung = 0, ap = mp->am_child; ap; ap = ap->am_osib) {
-    /*
-     * Otherwise search children of this node
-     */
-    if (FSTREQ(ap->am_name, fname)) {
-      mf = ap->am_mnt;
-      if (ap->am_error) {
-	error = ap->am_error;
-	continue;
-      }
-      /*
-       * If the error code is undefined then it must be
-       * in progress.
-       */
-      if (mf->mf_error < 0)
-	goto in_progrss;
-
-      /*
-       * Check for a hung node
-       */
-      if (FSRV_ISDOWN(mf->mf_server)) {
-#ifdef DEBUG
-	dlog("server hung");
-#endif /* DEBUG */
-	error = ap->am_error;
-	ap_hung = ap;
-	continue;
-      }
-      /*
-       * If there was a previous error with this node
-       * then return that error code.
-       */
-      if (mf->mf_flags & MFF_ERROR) {
-	error = mf->mf_error;
-	continue;
-      }
-      if (!(mf->mf_flags & MFF_MOUNTED) || (mf->mf_flags & MFF_UNMOUNTING)) {
-      in_progrss:
-	/*
-	 * If the fs is not mounted or it is unmounting then there
-	 * is a background (un)mount in progress.  In this case
-	 * we just drop the RPC request (return nil) and
-	 * wait for a retry, by which time the (un)mount may
-	 * have completed.
-	 */
-#ifdef DEBUG
-	dlog("ignoring mount of %s in %s -- flags (%x) in progress",
-	     fname, mf->mf_mount, mf->mf_flags);
-#endif /* DEBUG */
-	in_progress++;
-	continue;
-      }
-
-      /*
-       * Otherwise we have a hit: return the current mount point.
-       */
-#ifdef DEBUG
-      dlog("matched %s in %s", fname, ap->am_path);
-#endif /* DEBUG */
-      XFREE(fname);
-      return ap;
-    }
-  }
-
-  if (in_progress) {
-#ifdef DEBUG
-    dlog("Waiting while %d mount(s) in progress", in_progress);
-#endif /* DEBUG */
-    XFREE(fname);
-    ereturn(-1);
-  }
-
-  /*
-   * If an error occurred then return it.
-   */
-  if (error) {
-#ifdef DEBUG
-    errno = error;		/* XXX */
-    dlog("Returning error: %m");
-#endif /* DEBUG */
-    XFREE(fname);
-    ereturn(error);
-  }
-
-  /*
-   * If doing a delete then don't create again!
-   */
-  switch (op) {
-  case VLOOK_DELETE:
-    ereturn(ENOENT);
-
-  case VLOOK_CREATE:
-    break;
-
-  default:
-    plog(XLOG_FATAL, "Unknown op to amfs_auto_lookuppn: 0x%x", op);
-    ereturn(EINVAL);
-  }
-
-  /*
-   * If the server is going down then just return,
-   * don't try to mount any more file systems
-   */
-  if ((int) amd_state >= (int) Finishing) {
-#ifdef DEBUG
-    dlog("not found - server going down anyway");
-#endif /* DEBUG */
-    XFREE(fname);
-    ereturn(ENOENT);
-  }
-
-  /*
-   * If we get there then this is a reference to an,
-   * as yet, unknown name so we need to search the mount
-   * map for it.
-   */
-  if (mp->am_pref) {
-    sprintf(path_name, "%s%s", mp->am_pref, fname);
-    pfname = path_name;
-  } else {
-    pfname = fname;
-  }
-
-  mf = mp->am_mnt;
-
-#ifdef DEBUG
-  dlog("will search map info in %s to find %s", mf->mf_info, pfname);
-#endif /* DEBUG */
-  /*
-   * Consult the oracle for some mount information.
-   * info is malloc'ed and belongs to this routine.
-   * It ends up being free'd in free_continuation().
-   *
-   * Note that this may return -1 indicating that information
-   * is not yet available.
-   */
-  error = mapc_search((mnt_map *) mf->mf_private, pfname, &info);
-  if (error) {
-    if (error > 0)
-      plog(XLOG_MAP, "No map entry for %s", pfname);
-    else
-      plog(XLOG_MAP, "Waiting on map entry for %s", pfname);
-    XFREE(fname);
-    ereturn(error);
-  }
-#ifdef DEBUG
-  dlog("mount info is %s", info);
-#endif /* DEBUG */
-
-  /*
-   * Split info into an argument vector.
-   * The vector is malloc'ed and belongs to
-   * this routine.  It is free'd in free_continuation()
-   */
-  xivec = ivec = strsplit(info, ' ', '\"');
-
-  /*
-   * Default error code...
-   */
-  if (ap_hung)
-    error = EWOULDBLOCK;
-  else
-    error = ENOENT;
-
-  /*
-   * Allocate a new map
-   */
-  new_mp = exported_ap_alloc();
-  if (new_mp == 0) {
-    XFREE(xivec);
-    XFREE(info);
-    XFREE(fname);
-    ereturn(ENOSPC);
-  }
-  if (mf->mf_auto)
-    auto_opts = mf->mf_auto;
-  else
-    auto_opts = "";
-
-  auto_opts = strdup(auto_opts);
-
-#ifdef DEBUG
-  dlog("searching for /defaults entry");
-#endif /* DEBUG */
-  if (mapc_search((mnt_map *) mf->mf_private, "/defaults", &dflts) == 0) {
-    char *dfl;
-    char **rvec;
-#ifdef DEBUG
-    dlog("/defaults gave %s", dflts);
-#endif /* DEBUG */
-    if (*dflts == '-')
-      dfl = dflts + 1;
-    else
-      dfl = dflts;
-
-    /*
-     * Chop the defaults up
-     */
-    rvec = strsplit(dfl, ' ', '\"');
-
-    if (gopt.flags & CFM_ENABLE_DEFAULT_SELECTORS) {
-      /*
-       * Pick whichever first entry matched the list of selectors.
-       * Strip the selectors from the string, and assign to dfl the
-       * rest of the string.
-       */
-      if (rvec) {
-	am_opts ap;
-	am_ops *pt;
-	char **sp = rvec;
-	while (*sp) {		/* loop until you find something, if any */
-	  memset((char *) &ap, 0, sizeof(am_opts));
-	  pt = ops_match(&ap, *sp, "", mp->am_path, "/defaults",
-			 mp->am_parent->am_mnt->mf_info);
-	  free_opts(&ap);	/* don't leak */
-	  if (pt == &amfs_error_ops) {
-	    plog(XLOG_MAP, "failed to match defaults for \"%s\"", *sp);
-	  } else {
-	    dfl = strip_selectors(*sp, "/defaults");
-	    plog(XLOG_MAP, "matched default selectors \"%s\"", dfl);
-	    break;
-	  }
-	  ++sp;
-	}
-      }
-    } else {			/* not enable_default_selectors */
-      /*
-       * Extract first value
-       */
-      dfl = rvec[0];
-    }
+#ifdef HAVE_FS_AUTOFS
+  if (mf->mf_flags & MFF_IS_AUTOFS) {
+    char opts[SIZEOF_OPTS];
+    int error;
 
-    /*
-     * If there were any values at all...
-     */
-    if (dfl) {
-      /*
-       * Log error if there were other values
-       */
-      if (!(gopt.flags & CFM_ENABLE_DEFAULT_SELECTORS) && rvec[1]) {
-# ifdef DEBUG
-	dlog("/defaults chopped into %s", dfl);
-# endif /* DEBUG */
-	plog(XLOG_USER, "More than a single value for /defaults in %s", mf->mf_info);
-      }
+    autofs_get_opts(opts, sizeof(opts), mp->am_autofs_fh);
 
-      /*
-       * Prepend to existing defaults if they exist,
-       * otherwise just use these defaults.
-       */
-      if (*auto_opts && *dfl) {
-	char *nopts = (char *) xmalloc(strlen(auto_opts) + strlen(dfl) + 2);
-	sprintf(nopts, "%s;%s", dfl, auto_opts);
-	XFREE(auto_opts);
-	auto_opts = nopts;
-      } else if (*dfl) {
-	auto_opts = strealloc(auto_opts, dfl);
-      }
+    /* now do the mount */
+    error = amfs_mount(mp, mf, opts);
+    if (error) {
+      errno = error;
+      plog(XLOG_FATAL, "amfs_auto_mount: amfs_mount failed: %m");
+      return error;
     }
-    XFREE(dflts);
-    /*
-     * Don't need info vector any more
-     */
-    XFREE(rvec);
   }
+#endif /* HAVE_FS_AUTOFS */
 
   /*
-   * Fill it in
-   */
-  init_map(new_mp, fname);
-
-  /*
-   * Put it in the table
-   */
-  insert_am(new_mp, mp);
-
-  /*
-   * Fill in some other fields,
-   * path and mount point.
-   *
-   * bugfix: do not prepend old am_path if direct map
-   *         <wls@astro.umd.edu> William Sebok
-   */
-  new_mp->am_path = str3cat(new_mp->am_path,
-			    mf->mf_ops == &amfs_direct_ops ? "" : mp->am_path,
-			    *fname == '/' ? "" : "/", fname);
-
-#ifdef DEBUG
-  dlog("setting path to %s", new_mp->am_path);
-#endif /* DEBUG */
-
-  /*
-   * Take private copy of pfname
-   */
-  pfname = strdup(pfname);
-
-  /*
-   * Construct a continuation
-   */
-  cp = ALLOC(struct continuation);
-  cp->callout = 0;
-  cp->mp = new_mp;
-  cp->xivec = xivec;
-  cp->ivec = ivec;
-  cp->info = info;
-  cp->key = pfname;
-  cp->auto_opts = auto_opts;
-  cp->retry = FALSE;
-  cp->tried = FALSE;
-  cp->start = clocktime();
-  cp->def_opts = strdup(auto_opts);
-  memset((voidp) &cp->fs_opts, 0, sizeof(cp->fs_opts));
-
-  /*
-   * Try and mount the file system.  If this succeeds immediately (possible
-   * for a ufs file system) then return the attributes, otherwise just
-   * return an error.
-   */
-  error = amfs_auto_bgmount(cp, error);
-  reschedule_timeout_mp();
-  if (!error) {
-    XFREE(fname);
-    return new_mp;
-  }
-
-  /*
-   * Code for quick reply.  If nfs_program_2_transp is set, then
-   * its the transp that's been passed down from nfs_program_2().
-   * If new_mp->am_transp is not already set, set it by copying in
-   * nfs_program_2_transp.  Once am_transp is set, quick_reply() can
-   * use it to send a reply to the client that requested this mount.
-   */
-  if (nfs_program_2_transp && !new_mp->am_transp) {
-    new_mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT));
-    *(new_mp->am_transp) = *nfs_program_2_transp;
-  }
-  if (error && (new_mp->am_mnt->mf_ops == &amfs_error_ops))
-    new_mp->am_error = error;
-
-  assign_error_mntfs(new_mp);
-
-  XFREE(fname);
-
-  ereturn(error);
-}
-
-
-/*
- * Locate next node in sibling list which is mounted
- * and is not an error node.
- */
-am_node *
-next_nonerror_node(am_node *xp)
-{
-  mntfs *mf;
-
-  /*
-   * Bug report (7/12/89) from Rein Tollevik <rein@ifi.uio.no>
-   * Fixes a race condition when mounting direct automounts.
-   * Also fixes a problem when doing a readdir on a directory
-   * containing hung automounts.
-   */
-  while (xp &&
-	 (!(mf = xp->am_mnt) ||	/* No mounted filesystem */
-	  mf->mf_error != 0 ||	/* There was a mntfs error */
-	  xp->am_error != 0 ||	/* There was a mount error */
-	  !(mf->mf_flags & MFF_MOUNTED) ||	/* The fs is not mounted */
-	  (mf->mf_server->fs_flags & FSF_DOWN))	/* The fs may be down */
-	 )
-    xp = xp->am_osib;
-
-  return xp;
-}
-
-
-/*
- * This readdir function which call a special version of it that allows
- * browsing if browsable_dirs=yes was set on the map.
- */
-int
-amfs_auto_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count)
-{
-  u_int gen = *(u_int *) cookie;
-  am_node *xp;
-  mntent_t mnt;
-
-  dp->dl_eof = FALSE;		/* assume readdir not done */
-
-  /* check if map is browsable */
-  if (mp->am_mnt && mp->am_mnt->mf_mopts) {
-    mnt.mnt_opts = mp->am_mnt->mf_mopts;
-    if (hasmntopt(&mnt, "fullybrowsable"))
-      return amfs_auto_readdir_browsable(mp, cookie, dp, ep, count, TRUE);
-    if (hasmntopt(&mnt, "browsable"))
-      return amfs_auto_readdir_browsable(mp, cookie, dp, ep, count, FALSE);
-  }
-
-  if (gen == 0) {
-    /*
-     * In the default instance (which is used to start a search) we return
-     * "." and "..".
-     *
-     * This assumes that the count is big enough to allow both "." and ".."
-     * to be returned in a single packet.  If it isn't (which would be
-     * fairly unbelievable) then tough.
-     */
-#ifdef DEBUG
-    dlog("amfs_auto_readdir: default search");
-#endif /* DEBUG */
-    /*
-     * Check for enough room.  This is extremely approximate but is more
-     * than enough space.  Really need 2 times:
-     *      4byte fileid
-     *      4byte cookie
-     *      4byte name length
-     *      4byte name
-     * plus the dirlist structure */
-    if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
-      return EINVAL;
-
-    xp = next_nonerror_node(mp->am_child);
-    dp->dl_entries = ep;
-
-    /* construct "." */
-    ep[0].ne_fileid = mp->am_gen;
-    ep[0].ne_name = ".";
-    ep[0].ne_nextentry = &ep[1];
-    *(u_int *) ep[0].ne_cookie = 0;
-
-    /* construct ".." */
-    if (mp->am_parent)
-      ep[1].ne_fileid = mp->am_parent->am_gen;
-    else
-      ep[1].ne_fileid = mp->am_gen;
-    ep[1].ne_name = "..";
-    ep[1].ne_nextentry = 0;
-    *(u_int *) ep[1].ne_cookie = (xp ? xp->am_gen : DOT_DOT_COOKIE);
-
-    if (!xp)
-      dp->dl_eof = TRUE;	/* by default assume readdir done */
-
-    return 0;
-  }
-#ifdef DEBUG
-  dlog("amfs_auto_readdir: real child");
-#endif /* DEBUG */
-
-  if (gen == DOT_DOT_COOKIE) {
-#ifdef DEBUG
-    dlog("amfs_auto_readdir: End of readdir in %s", mp->am_path);
-#endif /* DEBUG */
-    dp->dl_eof = TRUE;
-    dp->dl_entries = 0;
-    return 0;
-  }
-
-  /* non-browsable directories code */
-  xp = mp->am_child;
-  while (xp && xp->am_gen != gen)
-    xp = xp->am_osib;
-
-  if (xp) {
-    int nbytes = count / 2;	/* conservative */
-    int todo = MAX_READDIR_ENTRIES;
-
-    dp->dl_entries = ep;
-    do {
-      am_node *xp_next = next_nonerror_node(xp->am_osib);
-
-      if (xp_next) {
-	*(u_int *) ep->ne_cookie = xp_next->am_gen;
-      } else {
-	*(u_int *) ep->ne_cookie = DOT_DOT_COOKIE;
-	dp->dl_eof = TRUE;
-      }
-
-      ep->ne_fileid = xp->am_gen;
-      ep->ne_name = xp->am_name;
-      nbytes -= sizeof(*ep) + 1;
-      if (xp->am_name)
-	nbytes -= strlen(xp->am_name);
-
-      xp = xp_next;
-
-      if (nbytes > 0 && !dp->dl_eof && todo > 1) {
-	ep->ne_nextentry = ep + 1;
-	ep++;
-	--todo;
-      } else {
-	todo = 0;
-      }
-    } while (todo > 0);
-
-    ep->ne_nextentry = 0;
-
-    return 0;
-  }
-  return ESTALE;
-}
-
-
-/* This one is called only if map is browsable */
-static int
-amfs_auto_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count, int fully_browsable)
-{
-  u_int gen = *(u_int *) cookie;
-  int chain_length, i;
-  static nfsentry *te, *te_next;
-#ifdef DEBUG_READDIR
-  nfsentry *ne;
-  static int j;
-#endif /* DEBUG_READDIR */
-
-  dp->dl_eof = FALSE;		/* assume readdir not done */
-
-#ifdef DEBUG_READDIR
-  plog(XLOG_INFO, "amfs_auto_readdir_browsable gen=%u, count=%d",
-       gen, count);
-#endif /* DEBUG_READDIR */
-
-  if (gen == 0) {
-    /*
-     * In the default instance (which is used to start a search) we return
-     * "." and "..".
-     *
-     * This assumes that the count is big enough to allow both "." and ".."
-     * to be returned in a single packet.  If it isn't (which would be
-     * fairly unbelievable) then tough.
-     */
-#ifdef DEBUG
-    dlog("amfs_auto_readdir_browsable: default search");
-#endif /* DEBUG */
-    /*
-     * Check for enough room.  This is extremely approximate but is more
-     * than enough space.  Really need 2 times:
-     *      4byte fileid
-     *      4byte cookie
-     *      4byte name length
-     *      4byte name
-     * plus the dirlist structure */
-    if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
-      return EINVAL;
-
-    /*
-     * compute # of entries to send in this chain.
-     * heuristics: 128 bytes per entry.
-     * This is too much probably, but it seems to work better because
-     * of the re-entrant nature of nfs_readdir, and esp. on systems
-     * like OpenBSD 2.2.
-     */
-    chain_length = count / 128;
-
-    /* reset static state counters */
-    te = te_next = NULL;
-
-    dp->dl_entries = ep;
-
-    /* construct "." */
-    ep[0].ne_fileid = mp->am_gen;
-    ep[0].ne_name = ".";
-    ep[0].ne_nextentry = &ep[1];
-    *(u_int *) ep[0].ne_cookie = 0;
-
-    /* construct ".." */
-    if (mp->am_parent)
-      ep[1].ne_fileid = mp->am_parent->am_gen;
-    else
-      ep[1].ne_fileid = mp->am_gen;
-    ep[1].ne_name = "..";
-    ep[1].ne_nextentry = 0;
-    *(u_int *) ep[1].ne_cookie = DOT_DOT_COOKIE;
-
-    /*
-     * If map is browsable, call a function make_entry_chain() to construct
-     * a linked list of unmounted keys, and return it.  Then link the chain
-     * to the regular list.  Get the chain only once, but return
-     * chunks of it each time.
-     */
-    te = make_entry_chain(mp, dp->dl_entries, fully_browsable);
-    if (!te)
-      return 0;
-#ifdef DEBUG_READDIR
-    for (j=0,ne=te; ne; ne=ne->ne_nextentry)
-      plog(XLOG_INFO, "gen1 key %4d \"%s\"", j++, ne->ne_name);
-#endif /* DEBUG_READDIR */
-
-    /* return only "chain_length" entries */
-    te_next = te;
-    for (i=1; i<chain_length; ++i) {
-      te_next = te_next->ne_nextentry;
-      if (!te_next)
-	break;
-    }
-    if (te_next) {
-      nfsentry *te_saved = te_next->ne_nextentry;
-      te_next->ne_nextentry = NULL; /* terminate "te" chain */
-      te_next = te_saved;	/* save rest of "te" for next iteration */
-      dp->dl_eof = FALSE;	/* tell readdir there's more */
-    } else {
-      dp->dl_eof = TRUE;	/* tell readdir that's it */
-    }
-    ep[1].ne_nextentry = te;	/* append this chunk of "te" chain */
-#ifdef DEBUG_READDIR
-    for (j=0,ne=te; ne; ne=ne->ne_nextentry)
-      plog(XLOG_INFO, "gen2 key %4d \"%s\"", j++, ne->ne_name);
-    for (j=0,ne=ep; ne; ne=ne->ne_nextentry)
-      plog(XLOG_INFO, "gen2+ key %4d \"%s\" fi=%d ck=%d",
-	   j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie);
-    plog(XLOG_INFO, "EOF is %d", dp->dl_eof);
-#endif /* DEBUG_READDIR */
-    return 0;
-  } /* end of "if (gen == 0)" statement */
-
-#ifdef DEBUG
-  dlog("amfs_auto_readdir_browsable: real child");
-#endif /* DEBUG */
-
-  if (gen == DOT_DOT_COOKIE) {
-#ifdef DEBUG
-    dlog("amfs_auto_readdir_browsable: End of readdir in %s", mp->am_path);
-#endif /* DEBUG */
-    dp->dl_eof = TRUE;
-    dp->dl_entries = 0;
-    return 0;
-  }
-
-  /*
-   * If browsable directories, then continue serving readdir() with another
-   * chunk of entries, starting from where we left off (when gen was equal
-   * to 0).  Once again, assume last chunk served to readdir.
-   */
-  dp->dl_eof = TRUE;
-  dp->dl_entries = ep;
-
-  te = te_next;			/* reset 'te' from last saved te_next */
-  if (!te) {			/* another indicator of end of readdir */
-    dp->dl_entries = 0;
-    return 0;
-  }
-  /*
-   * compute # of entries to send in this chain.
-   * heuristics: 128 bytes per entry.
+   * Attach a map cache
    */
-  chain_length = count / 128;
+  amfs_mkcacheref(mf);
 
-  /* return only "chain_length" entries */
-  for (i=1; i<chain_length; ++i) {
-    te_next = te_next->ne_nextentry;
-    if (!te_next)
-      break;
-  }
-  if (te_next) {
-    nfsentry *te_saved = te_next->ne_nextentry;
-    te_next->ne_nextentry = NULL; /* terminate "te" chain */
-    te_next = te_saved;		/* save rest of "te" for next iteration */
-    dp->dl_eof = FALSE;		/* tell readdir there's more */
-  }
-  ep = te;			/* send next chunk of "te" chain */
-  dp->dl_entries = ep;
-#ifdef DEBUG_READDIR
-  plog(XLOG_INFO, "dl_entries=0x%x, te_next=0x%x, dl_eof=%d",
-       (int) dp->dl_entries, (int) te_next, dp->dl_eof);
-  for (ne=te; ne; ne=ne->ne_nextentry)
-    plog(XLOG_INFO, "gen3 key %4d \"%s\"", j++, ne->ne_name);
-#endif /* DEBUG_READDIR */
   return 0;
 }
-
-
-int
-amfs_auto_fmount(am_node *mp)
-{
-  mntfs *mf = mp->am_mnt;
-  return (*mf->mf_ops->fmount_fs) (mf);
-}
-
-
-int
-amfs_auto_fumount(am_node *mp)
-{
-  mntfs *mf = mp->am_mnt;
-  return (*mf->mf_ops->fumount_fs) (mf);
-}
diff --git a/contrib/amd/amd/amfs_direct.c b/contrib/amd/amd/amfs_direct.c
index 475f388..dbef743 100644
--- a/contrib/amd/amd/amfs_direct.c
+++ b/contrib/amd/amd/amfs_direct.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_direct.c,v 1.2 1999/01/10 21:53:41 ezk Exp $
+ * File: am-utils/amd/amfs_direct.c
  *
  */
 
@@ -63,19 +62,22 @@ static am_node *amfs_direct_readlink(am_node *mp, int *error_return);
 am_ops amfs_direct_ops =
 {
   "direct",
-  amfs_auto_match,
+  amfs_generic_match,
   0,				/* amfs_direct_init */
   amfs_toplvl_mount,
-  0,
   amfs_toplvl_umount,
-  0,
-  amfs_error_lookuppn,
+  amfs_generic_lookup_child,
+  amfs_generic_mount_child,
   amfs_error_readdir,
   amfs_direct_readlink,
-  amfs_toplvl_mounted,
-  0,				/* amfs_auto_umounted */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO
+  amfs_generic_mounted,
+  0,				/* amfs_direct_umounted */
+  amfs_generic_find_srvr,
+  0,				/* amfs_direct_get_wchan */
+  FS_DIRECT | FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO,
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_DIRECT_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -92,8 +94,10 @@ amfs_direct_readlink(am_node *mp, int *error_return)
   xp = next_nonerror_node(mp->am_child);
   if (!xp) {
     if (!mp->am_mnt->mf_private)
-      amfs_auto_mkcacheref(mp->am_mnt);	/* XXX */
-    xp = amfs_auto_lookuppn(mp, mp->am_path + 1, &rc, VLOOK_CREATE);
+      amfs_mkcacheref(mp->am_mnt);	/* XXX */
+    xp = amfs_generic_lookup_child(mp, mp->am_path + 1, &rc, VLOOK_CREATE);
+    if (xp && rc < 0)
+      xp = amfs_generic_mount_child(xp, &rc);
   }
   if (xp) {
     new_ttl(xp);		/* (7/12/89) from Rein Tollevik */
diff --git a/contrib/amd/amd/amfs_error.c b/contrib/amd/amd/amfs_error.c
index 4d4d865..51bdaa6 100644
--- a/contrib/amd/amd/amfs_error.c
+++ b/contrib/amd/amd/amfs_error.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_error.c,v 1.2 1999/01/10 21:53:41 ezk Exp $
+ * File: am-utils/amd/amfs_error.c
  *
  */
 
@@ -56,10 +55,9 @@
 #include <am_defs.h>
 #include <amd.h>
 
-static char * amfs_error_match(am_opts *fo);
-static int amfs_error_fmount(mntfs *mf);
-static int amfs_error_fumount(mntfs *mf);
-static void amfs_error_umounted(am_node *mp);
+static char *amfs_error_match(am_opts *fo);
+static int amfs_error_mount(am_node *am, mntfs *mf);
+static int amfs_error_umount(am_node *am, mntfs *mf);
 
 
 /*
@@ -70,17 +68,20 @@ am_ops amfs_error_ops =
   "error",
   amfs_error_match,
   0,				/* amfs_error_init */
-  amfs_auto_fmount,
-  amfs_error_fmount,
-  amfs_auto_fumount,
-  amfs_error_fumount,
-  amfs_error_lookuppn,
+  amfs_error_mount,
+  amfs_error_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* amfs_error_readlink */
   0,				/* amfs_error_mounted */
-  amfs_error_umounted,
-  find_amfs_auto_srvr,
-  FS_DISCARD
+  0,				/* amfs_error_umounted */
+  amfs_generic_find_srvr,
+  0,				/* amfs_error_get_wchan */
+  FS_DISCARD,			/* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_ERROR_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -96,14 +97,14 @@ amfs_error_match(am_opts *fo)
 
 
 static int
-amfs_error_fmount(mntfs *mf)
+amfs_error_mount(am_node *am, mntfs *mf)
 {
   return ENOENT;
 }
 
 
 static int
-amfs_error_fumount(mntfs *mf)
+amfs_error_umount(am_node *am, mntfs *mf)
 {
   /*
    * Always succeed
@@ -118,7 +119,7 @@ amfs_error_fumount(mntfs *mf)
  * If we do then just give an error.
  */
 am_node *
-amfs_error_lookuppn(am_node *mp, char *fname, int *error_return, int op)
+amfs_error_lookup_child(am_node *mp, char *fname, int *error_return, int op)
 {
   *error_return = ESTALE;
   return 0;
@@ -126,25 +127,25 @@ amfs_error_lookuppn(am_node *mp, char *fname, int *error_return, int op)
 
 
 /*
- * EFS interface to RPC readdir() routine.
+ * EFS interface to RPC lookup() routine.
  * Should never get here in the automounter.
  * If we do then just give an error.
  */
-int
-amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count)
+am_node *
+amfs_error_mount_child(am_node *ap, int *error_return)
 {
-  return ESTALE;
+  *error_return = ESTALE;
+  return 0;
 }
 
 
 /*
- * umounted() callback for EFS.
- *
- * This prevents core-dumps on callbacks to error file-systems from
- * nfsx_fumount.
+ * EFS interface to RPC readdir() routine.
+ * Should never get here in the automounter.
+ * If we do then just give an error.
  */
-static void
-amfs_error_umounted(am_node *mp)
+int
+amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
 {
-  /* nothing to do */
+  return ESTALE;
 }
diff --git a/contrib/amd/amd/amfs_generic.c b/contrib/amd/amd/amfs_generic.c
new file mode 100644
index 0000000..3e7c365
--- /dev/null
+++ b/contrib/amd/amd/amfs_generic.c
@@ -0,0 +1,1262 @@
+/*
+ * Copyright (c) 1997-2006 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.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * 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.
+ *
+ *
+ * File: am-utils/amd/amfs_generic.c
+ *
+ */
+
+/*
+ * generic functions used by amfs filesystems, ripped out of amfs_auto.c.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amd.h>
+
+
+/****************************************************************************
+ *** MACROS                                                               ***
+ ****************************************************************************/
+#define	IN_PROGRESS(cp) ((cp)->mp->am_mnt->mf_flags & MFF_MOUNTING)
+
+
+/****************************************************************************
+ *** STRUCTURES                                                           ***
+ ****************************************************************************/
+/*
+ * Mounting a file system may take a significant period of time.  The
+ * problem is that if this is done in the main process thread then the
+ * entire automounter could be blocked, possibly hanging lots of processes
+ * on the system.  Instead we use a continuation scheme to allow mounts to
+ * be attempted in a sub-process.  When the sub-process exits we pick up the
+ * exit status (by convention a UN*X error number) and continue in a
+ * notifier.  The notifier gets handed a data structure and can then
+ * determine whether the mount was successful or not.  If not, it updates
+ * the data structure and tries again until there are no more ways to try
+ * the mount, or some other permanent error occurs.  In the mean time no RPC
+ * reply is sent, even after the mount is successful.  We rely on the RPC
+ * retry mechanism to resend the lookup request which can then be handled.
+ */
+struct continuation {
+  am_node *mp;			/* Node we are trying to mount */
+  int retry;			/* Try again? */
+  time_t start;			/* Time we started this mount */
+  int callout;			/* Callout identifier */
+  mntfs **mf;			/* Current mntfs */
+};
+
+
+/****************************************************************************
+ *** FORWARD DEFINITIONS                                                  ***
+ ****************************************************************************/
+static am_node *amfs_lookup_node(am_node *mp, char *fname, int *error_return);
+static mntfs *amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec,
+				    char *def_opts, char *pfname);
+static mntfs **amfs_lookup_mntfs(am_node *new_mp, int *error_return);
+static void amfs_cont(int rc, int term, opaque_t arg);
+static void amfs_retry(int rc, int term, opaque_t arg);
+static void free_continuation(struct continuation *cp);
+static int amfs_bgmount(struct continuation *cp);
+static char *amfs_parse_defaults(am_node *mp, mntfs *mf, char *def_opts);
+
+
+/****************************************************************************
+ *** FUNCTIONS                                                             ***
+ ****************************************************************************/
+static am_node *
+amfs_lookup_node(am_node *mp, char *fname, int *error_return)
+{
+  am_node *new_mp;
+  int error = 0;		/* Error so far */
+  int in_progress = 0;		/* # of (un)mount in progress */
+  mntfs *mf;
+  char *expanded_fname = 0;
+
+  dlog("in amfs_lookup_node");
+
+  /*
+   * If the server is shutting down
+   * then don't return information
+   * about the mount point.
+   */
+  if (amd_state == Finishing) {
+    if (mp->am_mnt == 0 || mp->am_mnt->mf_fsflags & FS_DIRECT) {
+      dlog("%s mount ignored - going down", fname);
+    } else {
+      dlog("%s/%s mount ignored - going down", mp->am_path, fname);
+    }
+    ereturn(ENOENT);
+  }
+
+  /*
+   * Handle special case of "." and ".."
+   */
+  if (fname[0] == '.') {
+    if (fname[1] == '\0')
+      return mp;		/* "." is the current node */
+    if (fname[1] == '.' && fname[2] == '\0') {
+      if (mp->am_parent) {
+	dlog(".. in %s gives %s", mp->am_path, mp->am_parent->am_path);
+	return mp->am_parent;	/* ".." is the parent node */
+      }
+      ereturn(ESTALE);
+    }
+  }
+
+  /*
+   * Check for valid key name.
+   * If it is invalid then pretend it doesn't exist.
+   */
+  if (!valid_key(fname)) {
+    plog(XLOG_WARNING, "Key \"%s\" contains a disallowed character", fname);
+    ereturn(ENOENT);
+  }
+
+  /*
+   * Expand key name.
+   * expanded_fname is now a private copy.
+   */
+  expanded_fname = expand_selectors(fname);
+
+  /*
+   * Search children of this node
+   */
+  for (new_mp = mp->am_child; new_mp; new_mp = new_mp->am_osib) {
+    if (FSTREQ(new_mp->am_name, expanded_fname)) {
+      if (new_mp->am_error) {
+	error = new_mp->am_error;
+	continue;
+      }
+
+      /*
+       * If the error code is undefined then it must be
+       * in progress.
+       */
+      mf = new_mp->am_mnt;
+      if (mf->mf_error < 0)
+	goto in_progrss;
+
+      /*
+       * If there was a previous error with this node
+       * then return that error code.
+       */
+      if (mf->mf_flags & MFF_ERROR) {
+	error = mf->mf_error;
+	continue;
+      }
+      if (!(mf->mf_flags & MFF_MOUNTED) || (mf->mf_flags & MFF_UNMOUNTING)) {
+      in_progrss:
+	/*
+	 * If the fs is not mounted or it is unmounting then there
+	 * is a background (un)mount in progress.  In this case
+	 * we just drop the RPC request (return nil) and
+	 * wait for a retry, by which time the (un)mount may
+	 * have completed.
+	 */
+	dlog("ignoring mount of %s in %s -- %smounting in progress, flags %x",
+	     expanded_fname, mf->mf_mount,
+	     (mf->mf_flags & MFF_UNMOUNTING) ? "un" : "", mf->mf_flags);
+	in_progress++;
+	if (mf->mf_flags & MFF_UNMOUNTING) {
+	  dlog("will remount later");
+	  new_mp->am_flags |= AMF_REMOUNT;
+	}
+	continue;
+      }
+
+      /*
+       * Otherwise we have a hit: return the current mount point.
+       */
+      dlog("matched %s in %s", expanded_fname, new_mp->am_path);
+      XFREE(expanded_fname);
+      return new_mp;
+    }
+  }
+
+  if (in_progress) {
+    dlog("Waiting while %d mount(s) in progress", in_progress);
+    XFREE(expanded_fname);
+    ereturn(-1);
+  }
+
+  /*
+   * If an error occurred then return it.
+   */
+  if (error) {
+    dlog("Returning error: %s", strerror(error));
+    XFREE(expanded_fname);
+    ereturn(error);
+  }
+
+  /*
+   * If the server is going down then just return,
+   * don't try to mount any more file systems
+   */
+  if ((int) amd_state >= (int) Finishing) {
+    dlog("not found - server going down anyway");
+    ereturn(ENOENT);
+  }
+
+  /*
+   * Allocate a new map
+   */
+  new_mp = get_ap_child(mp, expanded_fname);
+  XFREE(expanded_fname);
+  if (new_mp == 0)
+    ereturn(ENOSPC);
+
+  *error_return = -1;
+  return new_mp;
+}
+
+
+
+static mntfs *
+amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec,
+		      char *def_opts, char *pfname)
+{
+  am_ops *p;
+  am_opts *fs_opts;
+  mntfs *new_mf;
+  char *mp_dir = 0;
+#ifdef HAVE_FS_AUTOFS
+  int on_autofs = 1;
+#endif /* HAVE_FS_AUTOFS */
+
+  /* match the operators */
+  fs_opts = CALLOC(am_opts);
+  p = ops_match(fs_opts, ivec, def_opts, new_mp->am_path,
+		pfname, mf->mf_info);
+#ifdef HAVE_FS_AUTOFS
+  /* XXX: this should be factored out into an autofs-specific function */
+  if (new_mp->am_flags & AMF_AUTOFS) {
+    /* ignore user-provided fs if we're using autofs */
+    if (fs_opts->opt_sublink) {
+      /*
+       * For sublinks we need to use a hack with autofs:
+       * mount the filesystem on the original opt_fs (which is NOT an
+       * autofs mountpoint) and symlink (or lofs-mount) to it from
+       * the autofs mountpoint.
+       */
+      on_autofs = 0;
+      mp_dir = fs_opts->opt_fs;
+    } else {
+      if (p->autofs_fs_flags & FS_ON_AUTOFS) {
+	mp_dir = new_mp->am_path;
+      } else {
+	mp_dir = fs_opts->opt_fs;
+	on_autofs = 0;
+      }
+    }
+  } else
+#endif /* HAVE_FS_AUTOFS */
+    mp_dir = fs_opts->opt_fs;
+
+  /*
+   * Find or allocate a filesystem for this node.
+   */
+  new_mf = find_mntfs(p, fs_opts,
+		      mp_dir,
+		      fs_opts->fs_mtab,
+		      def_opts,
+		      fs_opts->opt_opts,
+		      fs_opts->opt_remopts);
+
+  /*
+   * See whether this is a real filesystem
+   */
+  p = new_mf->mf_ops;
+  if (p == &amfs_error_ops) {
+    plog(XLOG_MAP, "Map entry %s for %s did not match", ivec, new_mp->am_path);
+    free_mntfs(new_mf);
+    return NULL;
+  }
+
+  dlog("Got a hit with %s", p->fs_type);
+
+#ifdef HAVE_FS_AUTOFS
+  if (new_mp->am_flags & AMF_AUTOFS && on_autofs) {
+    new_mf->mf_flags |= MFF_ON_AUTOFS;
+    new_mf->mf_fsflags = new_mf->mf_ops->autofs_fs_flags;
+  }
+  /*
+   * A new filesystem is an autofs filesystems if:
+   * 1. it claims it can be one (has the FS_AUTOFS flag)
+   * 2. autofs is enabled system-wide
+   * 3. either has an autofs parent,
+   *    or it is explicitly requested to be autofs.
+   */
+  if (new_mf->mf_ops->autofs_fs_flags & FS_AUTOFS &&
+      amd_use_autofs &&
+      ((mf->mf_flags & MFF_IS_AUTOFS) ||
+       (new_mf->mf_fo && new_mf->mf_fo->opt_mount_type &&
+	STREQ(new_mf->mf_fo->opt_mount_type, "autofs"))))
+    new_mf->mf_flags |= MFF_IS_AUTOFS;
+#endif /* HAVE_FS_AUTOFS */
+
+  return new_mf;
+}
+
+
+static mntfs **
+amfs_lookup_mntfs(am_node *new_mp, int *error_return)
+{
+  am_node *mp;
+  char *info;			/* Mount info - where to get the file system */
+  char **ivecs, **cur_ivec;	/* Split version of info */
+  int num_ivecs;
+  char *orig_def_opts;          /* Original Automount options */
+  char *def_opts;	       	/* Automount options */
+  int error = 0;		/* Error so far */
+  char path_name[MAXPATHLEN];	/* General path name buffer */
+  char *pfname;			/* Path for database lookup */
+  mntfs *mf, **mf_array;
+  int count;
+
+  dlog("in amfs_lookup_mntfs");
+
+  mp = new_mp->am_parent;
+
+  /*
+   * If we get here then this is a reference to an,
+   * as yet, unknown name so we need to search the mount
+   * map for it.
+   */
+  if (mp->am_pref) {
+    if (strlen(mp->am_pref) + strlen(new_mp->am_name) >= sizeof(path_name))
+      ereturn(ENAMETOOLONG);
+    xsnprintf(path_name, sizeof(path_name), "%s%s", mp->am_pref, new_mp->am_name);
+    pfname = path_name;
+  } else {
+    pfname = new_mp->am_name;
+  }
+
+  mf = mp->am_mnt;
+
+  dlog("will search map info in %s to find %s", mf->mf_info, pfname);
+  /*
+   * Consult the oracle for some mount information.
+   * info is malloc'ed and belongs to this routine.
+   * It ends up being free'd in free_continuation().
+   *
+   * Note that this may return -1 indicating that information
+   * is not yet available.
+   */
+  error = mapc_search((mnt_map *) mf->mf_private, pfname, &info);
+  if (error) {
+    if (error > 0)
+      plog(XLOG_MAP, "No map entry for %s", pfname);
+    else
+      plog(XLOG_MAP, "Waiting on map entry for %s", pfname);
+    ereturn(error);
+  }
+  dlog("mount info is %s", info);
+
+  /*
+   * Split info into an argument vector.
+   * The vector is malloc'ed and belongs to
+   * this routine.  It is free'd further down.
+   *
+   * Note: the vector pointers point into info, so don't free it!
+   */
+  ivecs = strsplit(info, ' ', '\"');
+
+  if (mf->mf_auto)
+    def_opts = mf->mf_auto;
+  else
+    def_opts = "";
+
+  orig_def_opts = amfs_parse_defaults(mp, mf, strdup(def_opts));
+  def_opts = strdup(orig_def_opts);
+
+  /* first build our defaults */
+  num_ivecs = 0;
+  for (cur_ivec = ivecs; *cur_ivec; cur_ivec++) {
+    if (**cur_ivec == '-') {
+      /*
+       * Pick up new defaults
+       */
+      char *new_def_opts = str3cat(NULL, def_opts, ";", *cur_ivec + 1);
+      XFREE(def_opts);
+      def_opts = new_def_opts;
+      dlog("Setting def_opts to \"%s\"", def_opts);
+      continue;
+    } else
+      num_ivecs++;
+  }
+
+  mf_array = calloc(num_ivecs + 1, sizeof(mntfs *));
+
+  /* construct the array of struct mntfs for this mount point */
+  for (count = 0, cur_ivec = ivecs; *cur_ivec; cur_ivec++) {
+    mntfs *new_mf;
+
+    if (**cur_ivec == '-') {
+      XFREE(def_opts);
+      if ((*cur_ivec)[1] == '\0') {
+	/*
+	 * If we have a single dash '-' than we need to reset the
+	 * default options.
+	 */
+	def_opts = strdup(orig_def_opts);
+	dlog("Resetting the default options, a single dash '-' was found.");
+      } else {
+	/* append options to /default options */
+	def_opts = str3cat((char *) 0, orig_def_opts, ";", *cur_ivec + 1);
+	dlog("Resetting def_opts to \"%s\"", def_opts);
+      }
+      continue;
+    }
+
+    /*
+     * If a mntfs has already been found, and we find
+     * a cut then don't try any more locations.
+     *
+     * XXX: we do not know when the "/" was added as an equivalent for "||".
+     * It's undocumented, it might go away at any time. Caveat emptor.
+     */
+    if (STREQ(*cur_ivec, "/") || STREQ(*cur_ivec, "||")) {
+      if (count > 0) {
+	dlog("Cut: not trying any more locations for %s", mp->am_path);
+	break;
+      }
+      continue;
+    }
+
+    new_mf = amfs_lookup_one_mntfs(new_mp, mf, *cur_ivec, def_opts, pfname);
+    if (new_mf == NULL)
+      continue;
+    mf_array[count++] = new_mf;
+  }
+
+  /* We're done with ivecs */
+  XFREE(ivecs);
+  XFREE(info);
+  XFREE(orig_def_opts);
+  XFREE(def_opts);
+  if (count == 0) {			/* no match */
+    XFREE(mf_array);
+    ereturn(ENOENT);
+  }
+
+  return mf_array;
+}
+
+
+/*
+ * The continuation function.  This is called by
+ * the task notifier when a background mount attempt
+ * completes.
+ */
+static void
+amfs_cont(int rc, int term, opaque_t arg)
+{
+  struct continuation *cp = (struct continuation *) arg;
+  am_node *mp = cp->mp;
+  mntfs *mf = mp->am_mnt;
+
+  dlog("amfs_cont: '%s'", mp->am_path);
+
+  /*
+   * Definitely not trying to mount at the moment
+   */
+  mf->mf_flags &= ~MFF_MOUNTING;
+
+  /*
+   * While we are mounting - try to avoid race conditions
+   */
+  new_ttl(mp);
+
+  /*
+   * Wakeup anything waiting for this mount
+   */
+  wakeup(get_mntfs_wchan(mf));
+
+  /*
+   * Check for termination signal or exit status...
+   */
+  if (rc || term) {
+#ifdef HAVE_FS_AUTOFS
+    if (mf->mf_flags & MFF_IS_AUTOFS &&
+	!(mf->mf_flags & MFF_MOUNTED))
+      autofs_release_fh(mp);
+#endif /* HAVE_FS_AUTOFS */
+
+    if (term) {
+      /*
+       * Not sure what to do for an error code.
+       */
+      mf->mf_error = EIO;	/* XXX ? */
+      mf->mf_flags |= MFF_ERROR;
+      plog(XLOG_ERROR, "mount for %s got signal %d", mp->am_path, term);
+    } else {
+      /*
+       * Check for exit status...
+       */
+#ifdef __linux__
+      /*
+       * HACK ALERT!
+       *
+       * On Linux (and maybe not only) it's possible to run
+       * an amd which "knows" how to mount certain combinations
+       * of nfs_proto/nfs_version which the kernel doesn't grok.
+       * So if we got an EINVAL and we have a server that's not
+       * using NFSv2/UDP, try again with NFSv2/UDP.
+       *
+       * Too bad that there is no way to dynamically determine
+       * what combinations the _client_ supports, as opposed to
+       * what the _server_ supports...
+       */
+      if (rc == EINVAL &&
+	  mf->mf_server &&
+	  (mf->mf_server->fs_version != 2 ||
+	   !STREQ(mf->mf_server->fs_proto, "udp")))
+	mf->mf_flags |= MFF_NFS_SCALEDOWN;
+      else
+#endif /* __linux__ */
+      {
+	mf->mf_error = rc;
+	mf->mf_flags |= MFF_ERROR;
+	errno = rc;		/* XXX */
+	if (!STREQ(mp->am_mnt->mf_ops->fs_type, "linkx"))
+	  plog(XLOG_ERROR, "%s: mount (amfs_cont): %m", mp->am_path);
+      }
+    }
+
+    if (!(mf->mf_flags & MFF_NFS_SCALEDOWN)) {
+      /*
+       * If we get here then that attempt didn't work, so
+       * move the info vector pointer along by one and
+       * call the background mount routine again
+       */
+      amd_stats.d_merr++;
+      cp->mf++;
+    }
+    amfs_bgmount(cp);
+    if (mp->am_error > 0)
+      assign_error_mntfs(mp);
+  } else {
+    /*
+     * The mount worked.
+     */
+    dlog("Mounting %s returned success", cp->mp->am_path);
+    am_mounted(cp->mp);
+    free_continuation(cp);
+  }
+
+  reschedule_timeout_mp();
+}
+
+
+/*
+ * Retry a mount
+ */
+static void
+amfs_retry(int rc, int term, opaque_t arg)
+{
+  struct continuation *cp = (struct continuation *) arg;
+  am_node *mp = cp->mp;
+  int error = 0;
+
+  dlog("Commencing retry for mount of %s", mp->am_path);
+
+  new_ttl(mp);
+
+  if ((cp->start + ALLOWED_MOUNT_TIME) < clocktime(NULL)) {
+    /*
+     * The entire mount has timed out.  Set the error code and skip past all
+     * the mntfs's so that amfs_bgmount will not have any more
+     * ways to try the mount, thus causing an error.
+     */
+    plog(XLOG_INFO, "mount of \"%s\" has timed out", mp->am_path);
+    error = ETIMEDOUT;
+    while (*cp->mf)
+      cp->mf++;
+    /* explicitly forbid further retries after timeout */
+    cp->retry = FALSE;
+  }
+  if (error || !IN_PROGRESS(cp))
+    error = amfs_bgmount(cp);
+
+  reschedule_timeout_mp();
+}
+
+
+/*
+ * Discard an old continuation
+ */
+static void
+free_continuation(struct continuation *cp)
+{
+  mntfs **mfp;
+
+  dlog("free_continuation");
+  if (cp->callout)
+    untimeout(cp->callout);
+  /*
+   * we must free the mntfs's in the list.
+   * so free all of them if there was an error,
+   * or free all but the used one, if the mount succeeded.
+   */
+  for (mfp = cp->mp->am_mfarray; *mfp; mfp++) {
+    free_mntfs(*mfp);
+  }
+  XFREE(cp->mp->am_mfarray);
+  cp->mp->am_mfarray = 0;
+  XFREE(cp);
+}
+
+
+/*
+ * Pick a file system to try mounting and
+ * do that in the background if necessary
+ *
+For each location:
+	discard previous mount location if required
+	fetch next mount location
+	if the filesystem failed to be mounted then
+		this_error = error from filesystem
+		goto failed
+	if the filesystem is mounting or unmounting then
+		goto retry;
+	if the fileserver is down then
+		this_error = EIO
+		continue;
+	if the filesystem is already mounted
+		break
+	fi
+
+	this_error = initialize mount point
+
+	if no error on this mount and mount is delayed then
+		this_error = -1
+	fi
+	if this_error < 0 then
+		retry = true
+	fi
+	if no error on this mount then
+		if mount in background then
+			run mount in background
+			return -1
+		else
+			this_error = mount in foreground
+		fi
+	fi
+	if an error occurred on this mount then
+		update stats
+		save error in mount point
+	fi
+endfor
+ */
+static int
+amfs_bgmount(struct continuation *cp)
+{
+  am_node *mp = cp->mp;
+  mntfs *mf;			/* Current mntfs */
+  int this_error = -1;		/* Per-mount error */
+  int hard_error = -1;		/* Cumulative per-node error */
+
+  if (mp->am_mnt)
+    free_mntfs(mp->am_mnt);
+
+  /*
+   * Try to mount each location.
+   * At the end:
+   * hard_error == 0 indicates something was mounted.
+   * hard_error > 0 indicates everything failed with a hard error
+   * hard_error < 0 indicates nothing could be mounted now
+   */
+  for (mp->am_mnt = *cp->mf; *cp->mf; cp->mf++, mp->am_mnt = *cp->mf) {
+    am_ops *p;
+
+    mf = dup_mntfs(mp->am_mnt);
+    p = mf->mf_ops;
+
+    if (hard_error < 0)
+      hard_error = this_error;
+    this_error = 0;
+
+    if (mf->mf_error > 0) {
+      this_error = mf->mf_error;
+      goto failed;
+    }
+
+    if (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)) {
+      /*
+       * Still mounting - retry later
+       */
+      dlog("mount of \"%s\" already pending", mf->mf_info);
+      goto retry;
+    }
+
+    if (FSRV_ISDOWN(mf->mf_server)) {
+      /*
+       * Would just mount from the same place
+       * as a hung mount - so give up
+       */
+      dlog("%s is already hung - giving up", mf->mf_server->fs_host);
+      this_error = EIO;
+      goto failed;
+    }
+
+    if (mp->am_link) {
+      XFREE(mp->am_link);
+      mp->am_link = NULL;
+    }
+    if (mf->mf_fo && mf->mf_fo->opt_sublink)
+      mp->am_link = strdup(mf->mf_fo->opt_sublink);
+
+    /*
+     * Will usually need to play around with the mount nodes
+     * file attribute structure.  This must be done here.
+     * Try and get things initialized, even if the fileserver
+     * is not known to be up.  In the common case this will
+     * progress things faster.
+     */
+
+    /*
+     * Fill in attribute fields.
+     */
+    if (mf->mf_fsflags & FS_DIRECTORY)
+      mk_fattr(&mp->am_fattr, NFDIR);
+    else
+      mk_fattr(&mp->am_fattr, NFLNK);
+
+    if (mf->mf_flags & MFF_MOUNTED) {
+      dlog("duplicate mount of \"%s\" ...", mf->mf_info);
+      /*
+       * Skip initial processing of the mountpoint if already mounted.
+       * This could happen if we have multiple sublinks into the same f/s,
+       * or if we are restarting an already-mounted filesystem.
+       */
+      goto already_mounted;
+    }
+
+    if (mf->mf_fo && mf->mf_fo->fs_mtab) {
+      plog(XLOG_MAP, "Trying mount of %s on %s fstype %s mount_type %s",
+	   mf->mf_fo->fs_mtab, mf->mf_mount, p->fs_type,
+	   mp->am_flags & AMF_AUTOFS ? "autofs" : "non-autofs");
+    }
+
+    if (p->fs_init && !(mf->mf_flags & MFF_RESTART))
+      this_error = p->fs_init(mf);
+
+    if (this_error > 0)
+      goto failed;
+    if (this_error < 0)
+      goto retry;
+
+    if (mf->mf_fo && mf->mf_fo->opt_delay) {
+      /*
+       * If there is a delay timer on the mount
+       * then don't try to mount if the timer
+       * has not expired.
+       */
+      int i = atoi(mf->mf_fo->opt_delay);
+      time_t now = clocktime(NULL);
+      if (i > 0 && now < (cp->start + i)) {
+	dlog("Mount of %s delayed by %lds", mf->mf_mount, (long) (i - now + cp->start));
+	goto retry;
+      }
+    }
+
+    /*
+     * If the directory is not yet made and it needs to be made, then make it!
+     */
+    if (!(mf->mf_flags & MFF_MKMNT) && mf->mf_fsflags & FS_MKMNT) {
+      plog(XLOG_INFO, "creating mountpoint directory '%s'", mf->mf_mount);
+      this_error = mkdirs(mf->mf_mount, 0555);
+      if (this_error) {
+	plog(XLOG_ERROR, "mkdirs failed: %s", strerror(this_error));
+	goto failed;
+      }
+      mf->mf_flags |= MFF_MKMNT;
+    }
+
+#ifdef HAVE_FS_AUTOFS
+    if (mf->mf_flags & MFF_IS_AUTOFS)
+      if ((this_error = autofs_get_fh(mp)))
+	goto failed;
+#endif /* HAVE_FS_AUTOFS */
+
+  already_mounted:
+    mf->mf_flags |= MFF_MOUNTING;
+    if (mf->mf_fsflags & FS_MBACKGROUND) {
+      dlog("backgrounding mount of \"%s\"", mf->mf_mount);
+      if (cp->callout) {
+	untimeout(cp->callout);
+	cp->callout = 0;
+      }
+
+      /* actually run the task, backgrounding as necessary */
+      run_task(mount_node, (opaque_t) mp, amfs_cont, (opaque_t) cp);
+      return -1;
+    } else {
+      dlog("foreground mount of \"%s\" ...", mf->mf_mount);
+      this_error = mount_node((opaque_t) mp);
+    }
+
+    mf->mf_flags &= ~MFF_MOUNTING;
+    if (this_error > 0)
+      goto failed;
+    if (this_error == 0) {
+      am_mounted(mp);
+      break;					/* Success */
+    }
+
+  retry:
+    if (!cp->retry)
+      continue;
+    dlog("will retry ...\n");
+
+    /*
+     * Arrange that amfs_bgmount is called
+     * after anything else happens.
+     */
+    dlog("Arranging to retry mount of %s", mp->am_path);
+    sched_task(amfs_retry, (opaque_t) cp, get_mntfs_wchan(mf));
+    if (cp->callout)
+      untimeout(cp->callout);
+    cp->callout = timeout(RETRY_INTERVAL, wakeup,
+			  (opaque_t) get_mntfs_wchan(mf));
+
+    mp->am_ttl = clocktime(NULL) + RETRY_INTERVAL;
+
+    /*
+     * Not done yet - so don't return anything
+     */
+    return -1;
+
+  failed:
+    amd_stats.d_merr++;
+    mf->mf_error = this_error;
+    mf->mf_flags |= MFF_ERROR;
+#ifdef HAVE_FS_AUTOFS
+    if (mp->am_autofs_fh)
+      autofs_release_fh(mp);
+#endif /* HAVE_FS_AUTOFS */
+    if (mf->mf_flags & MFF_MKMNT) {
+      rmdirs(mf->mf_mount);
+      mf->mf_flags &= ~MFF_MKMNT;
+    }
+    /*
+     * Wakeup anything waiting for this mount
+     */
+    wakeup(get_mntfs_wchan(mf));
+    free_mntfs(mf);
+    /* continue */
+  }
+
+  /*
+   * If we get here, then either the mount succeeded or
+   * there is no more mount information available.
+   */
+  if (this_error) {
+    mp->am_mnt = mf = new_mntfs();
+
+#ifdef HAVE_FS_AUTOFS
+    if (mp->am_flags & AMF_AUTOFS)
+      autofs_mount_failed(mp);
+    else
+#endif /* HAVE_FS_AUTOFS */
+      nfs_quick_reply(mp, this_error);
+
+    if (hard_error <= 0)
+      hard_error = this_error;
+    if (hard_error < 0)
+      hard_error = ETIMEDOUT;
+
+    /*
+     * Set a small(ish) timeout on an error node if
+     * the error was not a time out.
+     */
+    switch (hard_error) {
+    case ETIMEDOUT:
+    case EWOULDBLOCK:
+    case EIO:
+      mp->am_timeo = 17;
+      break;
+    default:
+      mp->am_timeo = 5;
+      break;
+    }
+    new_ttl(mp);
+  } else {
+    mf = mp->am_mnt;
+    /*
+     * Wakeup anything waiting for this mount
+     */
+    wakeup(get_mntfs_wchan(mf));
+    hard_error = 0;
+  }
+
+  /*
+   * Make sure that the error value in the mntfs has a
+   * reasonable value.
+   */
+  if (mf->mf_error < 0) {
+    mf->mf_error = hard_error;
+    if (hard_error)
+      mf->mf_flags |= MFF_ERROR;
+  }
+
+  /*
+   * In any case we don't need the continuation any more
+   */
+  free_continuation(cp);
+
+  return hard_error;
+}
+
+
+static char *
+amfs_parse_defaults(am_node *mp, mntfs *mf, char *def_opts)
+{
+  char *dflts;
+  char *dfl;
+  char **rvec = NULL;
+  struct mnt_map *mm = (mnt_map *) mf->mf_private;
+
+  dlog("determining /defaults entry value");
+
+  /*
+   * Find out if amd.conf overrode any map-specific /defaults.
+   *
+   * HACK ALERT: there's no easy way to find out what the map mount point is
+   * at this point, so I am forced to initialize the mnt_map->cfm field here
+   * for the first time, upon the very first search for a /defaults entry in
+   * this map.  This initialization is much better done in mapc_create(),
+   * but it's impossible to do that there with the current code structure.
+   */
+  if (mm->cfm == NULL) {	/* then initialize it for first time */
+    mm->cfm = find_cf_map(mf->mf_mount);
+  }
+  if (mm->cfm && mm->cfm->cfm_defaults) {
+    dlog("map %s map_defaults override: %s", mf->mf_mount, mm->cfm->cfm_defaults);
+    dflts = strdup(mm->cfm->cfm_defaults);
+  } else if (mapc_search(mm, "/defaults", &dflts) == 0) {
+    dlog("/defaults gave %s", dflts);
+  } else {
+    return def_opts;		/* if nothing found */
+  }
+
+  /* trim leading '-' in case thee's one */
+  if (*dflts == '-')
+    dfl = dflts + 1;
+  else
+    dfl = dflts;
+
+  /*
+   * Chop the defaults up
+   */
+  rvec = strsplit(dfl, ' ', '\"');
+
+  if (gopt.flags & CFM_SELECTORS_IN_DEFAULTS) {
+    /*
+     * Pick whichever first entry matched the list of selectors.
+     * Strip the selectors from the string, and assign to dfl the
+     * rest of the string.
+     */
+    if (rvec) {
+      am_opts ap;
+      am_ops *pt;
+      char **sp = rvec;
+      while (*sp) {		/* loop until you find something, if any */
+	memset((char *) &ap, 0, sizeof(am_opts));
+	/*
+	 * This next routine cause many spurious "expansion of ... is"
+	 * messages, which are ignored, b/c all we need out of this
+	 * routine is to match selectors.  These spurious messages may
+	 * be wrong, esp. if they try to expand ${key} b/c it will
+	 * get expanded to "/defaults"
+	 */
+	pt = ops_match(&ap, *sp, "", mp->am_path, "/defaults",
+		       mp->am_parent->am_mnt->mf_info);
+	free_opts(&ap);	/* don't leak */
+	if (pt == &amfs_error_ops) {
+	  plog(XLOG_MAP, "did not match defaults for \"%s\"", *sp);
+	} else {
+	  dfl = strip_selectors(*sp, "/defaults");
+	  plog(XLOG_MAP, "matched default selectors \"%s\"", dfl);
+	  break;
+	}
+	++sp;
+      }
+    }
+  } else {			/* not selectors_in_defaults */
+    /*
+     * Extract first value
+     */
+    dfl = rvec[0];
+  }
+
+  /*
+   * If there were any values at all...
+   */
+  if (dfl) {
+    /*
+     * Log error if there were other values
+     */
+    if (!(gopt.flags & CFM_SELECTORS_IN_DEFAULTS) && rvec[1]) {
+      dlog("/defaults chopped into %s", dfl);
+      plog(XLOG_USER, "More than a single value for /defaults in %s", mf->mf_info);
+    }
+
+    /*
+     * Prepend to existing defaults if they exist,
+     * otherwise just use these defaults.
+     */
+    if (*def_opts && *dfl) {
+      size_t l = strlen(def_opts) + strlen(dfl) + 2;
+      char *nopts = (char *) xmalloc(l);
+      xsnprintf(nopts, l, "%s;%s", dfl, def_opts);
+      XFREE(def_opts);
+      def_opts = nopts;
+    } else if (*dfl) {
+      def_opts = strealloc(def_opts, dfl);
+    }
+  }
+
+  XFREE(dflts);
+
+  /* don't need info vector any more */
+  if (rvec)
+    XFREE(rvec);
+
+  return def_opts;
+}
+
+
+am_node *
+amfs_generic_mount_child(am_node *new_mp, int *error_return)
+{
+  int error;
+  struct continuation *cp;	/* Continuation structure if need to mount */
+
+  dlog("in amfs_generic_mount_child");
+
+  *error_return = error = 0;	/* Error so far */
+
+  /* we have an errorfs attached to the am_node, free it */
+  free_mntfs(new_mp->am_mnt);
+  new_mp->am_mnt = 0;
+
+  /*
+   * Construct a continuation
+   */
+  cp = ALLOC(struct continuation);
+  cp->callout = 0;
+  cp->mp = new_mp;
+  cp->retry = TRUE;
+  cp->start = clocktime(NULL);
+  cp->mf = new_mp->am_mfarray;
+
+  /*
+   * Try and mount the file system.  If this succeeds immediately (possible
+   * for a ufs file system) then return the attributes, otherwise just
+   * return an error.
+   */
+  error = amfs_bgmount(cp);
+  reschedule_timeout_mp();
+  if (!error)
+    return new_mp;
+
+  /*
+   * Code for quick reply.  If current_transp is set, then it's the
+   * transp that's been passed down from nfs_program_2() or from
+   * autofs_program_[123]().
+   * If new_mp->am_transp is not already set, set it by copying in
+   * current_transp.  Once am_transp is set, nfs_quick_reply() and
+   * autofs_mount_succeeded() can use it to send a reply to the
+   * client that requested this mount.
+   */
+  if (current_transp && !new_mp->am_transp) {
+    dlog("Saving RPC transport for %s", new_mp->am_path);
+    new_mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT));
+    *(new_mp->am_transp) = *current_transp;
+  }
+  if (error && (new_mp->am_mnt->mf_ops == &amfs_error_ops))
+    new_mp->am_error = error;
+
+  if (new_mp->am_error > 0)
+    assign_error_mntfs(new_mp);
+
+  ereturn(error);
+}
+
+
+/*
+ * Automount interface to RPC lookup routine
+ * Find the corresponding entry and return
+ * the file handle for it.
+ */
+am_node *
+amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op)
+{
+  am_node *new_mp;
+  mntfs **mf_array;
+  int mp_error;
+
+  dlog("in amfs_generic_lookup_child");
+
+  *error_return = 0;
+  new_mp = amfs_lookup_node(mp, fname, error_return);
+
+  /* return if we got an error */
+  if (!new_mp || *error_return > 0)
+    return new_mp;
+
+  /* also return if it's already mounted and known to be up */
+  if (*error_return == 0 && FSRV_ISUP(new_mp->am_mnt->mf_server))
+    return new_mp;
+
+  switch (op) {
+  case VLOOK_DELETE:
+    /*
+     * If doing a delete then don't create again!
+     */
+    ereturn(ENOENT);
+  case VLOOK_LOOKUP:
+    return new_mp;
+  }
+
+  /* save error_return */
+  mp_error = *error_return;
+
+  mf_array = amfs_lookup_mntfs(new_mp, error_return);
+  if (!mf_array) {
+    new_mp->am_error = new_mp->am_mnt->mf_error = *error_return;
+    free_map(new_mp);
+    return NULL;
+  }
+
+  /*
+   * Already mounted but known to be down:
+   * check if we have any alternatives to mount
+   */
+  if (mp_error == 0) {
+    mntfs **mfp;
+    for (mfp = mf_array; *mfp; mfp++)
+      if (*mfp != new_mp->am_mnt)
+	break;
+    if (*mfp != NULL) {
+      /*
+       * we found an alternative, so try mounting again.
+       */
+      *error_return = -1;
+    } else {
+      for (mfp = mf_array; *mfp; mfp++)
+	free_mntfs(*mfp);
+      XFREE(mf_array);
+      if (new_mp->am_flags & AMF_SOFTLOOKUP) {
+	ereturn(EIO);
+      } else {
+	*error_return = 0;
+	return new_mp;
+      }
+    }
+  }
+
+  /* store the array inside the am_node */
+  new_mp->am_mfarray = mf_array;
+
+  /*
+   * Note: while it might seem like a good idea to prioritize
+   * the list of mntfs's we got here, it probably isn't.
+   * It would ignore the ordering of entries specified by the user,
+   * which is counterintuitive and confusing.
+   */
+  return new_mp;
+}
+
+
+void
+amfs_generic_mounted(mntfs *mf)
+{
+  amfs_mkcacheref(mf);
+}
+
+
+/*
+ * Unmount an automount sub-node
+ */
+int
+amfs_generic_umount(am_node *mp, mntfs *mf)
+{
+  int error = 0;
+
+#ifdef HAVE_FS_AUTOFS
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+  if (mf->mf_flags & MFF_IS_AUTOFS)
+    error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags);
+#endif /* HAVE_FS_AUTOFS */
+
+  return error;
+}
+
+
+char *
+amfs_generic_match(am_opts *fo)
+{
+  char *p;
+
+  if (!fo->opt_rfs) {
+    plog(XLOG_USER, "amfs_generic_match: no mount point named (rfs:=)");
+    return 0;
+  }
+  if (!fo->opt_fs) {
+    plog(XLOG_USER, "amfs_generic_match: no map named (fs:=)");
+    return 0;
+  }
+
+  /*
+   * Swap round fs:= and rfs:= options
+   * ... historical (jsp)
+   */
+  p = fo->opt_rfs;
+  fo->opt_rfs = fo->opt_fs;
+  fo->opt_fs = p;
+
+  /*
+   * mtab entry turns out to be the name of the mount map
+   */
+  return strdup(fo->opt_rfs ? fo->opt_rfs : ".");
+}
diff --git a/contrib/amd/amd/amfs_host.c b/contrib/amd/amd/amfs_host.c
index 71b08df..55423c4 100644
--- a/contrib/amd/amd/amfs_host.c
+++ b/contrib/amd/amd/amfs_host.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_host.c,v 1.3 1999/01/13 23:30:57 ezk Exp $
+ * File: am-utils/amd/amfs_host.c
  *
  */
 
@@ -57,10 +56,10 @@
 #include <amd.h>
 
 static char *amfs_host_match(am_opts *fo);
-static int amfs_host_fmount(mntfs *mf);
-static int amfs_host_fumount(mntfs *mf);
 static int amfs_host_init(mntfs *mf);
-static void amfs_host_umounted(am_node *mp);
+static int amfs_host_mount(am_node *am, mntfs *mf);
+static int amfs_host_umount(am_node *am, mntfs *mf);
+static void amfs_host_umounted(mntfs *mf);
 
 /*
  * Ops structure
@@ -70,17 +69,20 @@ am_ops amfs_host_ops =
   "host",
   amfs_host_match,
   amfs_host_init,
-  amfs_auto_fmount,
-  amfs_host_fmount,
-  amfs_auto_fumount,
-  amfs_host_fumount,
-  amfs_error_lookuppn,
+  amfs_host_mount,
+  amfs_host_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* amfs_host_readlink */
   0,				/* amfs_host_mounted */
   amfs_host_umounted,
   find_nfs_srvr,
-  FS_MKMNT | FS_BACKGROUND | FS_AMQINFO
+  0,				/* amfs_host_get_wchan */
+  FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_HOST_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -95,21 +97,21 @@ am_ops amfs_host_ops =
  * allows the entire PC disk to be mounted.
  */
 static void
-make_mntpt(char *mntpt, const exports ex, const mntfs *mf)
+make_mntpt(char *mntpt, size_t l, const exports ex, const char *mf_mount)
 {
   if (ex->ex_dir[0] == '/') {
     if (ex->ex_dir[1] == 0)
-      strcpy(mntpt, (mf)->mf_mount);
+      xstrlcpy(mntpt, mf_mount, l);
     else
-      sprintf(mntpt, "%s%s", mf->mf_mount, ex->ex_dir);
+      xsnprintf(mntpt, l, "%s%s", mf_mount, ex->ex_dir);
   } else if (ex->ex_dir[0] >= 'a' &&
 	     ex->ex_dir[0] <= 'z' &&
 	     ex->ex_dir[1] == ':' &&
 	     ex->ex_dir[2] == '/' &&
 	     ex->ex_dir[3] == 0)
-    sprintf(mntpt, "%s/%c%%", mf->mf_mount, ex->ex_dir[0]);
+    xsnprintf(mntpt, l, "%s/%c%%", mf_mount, ex->ex_dir[0]);
   else
-    sprintf(mntpt, "%s/%s", mf->mf_mount, ex->ex_dir);
+    xsnprintf(mntpt, l, "%s/%s", mf_mount, ex->ex_dir);
 }
 
 
@@ -134,8 +136,7 @@ amfs_host_match(am_opts *fo)
 static int
 amfs_host_init(mntfs *mf)
 {
-  fserver *fs;
-  u_short port;
+  u_short mountd_port;
 
   if (strchr(mf->mf_info, ':') == 0)
     return ENOENT;
@@ -152,41 +153,39 @@ amfs_host_init(mntfs *mf)
    */
   /*
    * First, we find the fileserver for this mntfs and then call
-   * nfs_srvr_port with our mntfs passed as the wait channel.
-   * nfs_srvr_port will check some things and then schedule
+   * get_mountd_port with our mntfs passed as the wait channel.
+   * get_mountd_port will check some things and then schedule
    * it so that when the fileserver is ready, a wakeup is done
-   * on this mntfs.   amfs_auto_cont() is already sleeping on this mntfs
-   * so as soon as that wakeup happens amfs_auto_cont() is called and
+   * on this mntfs.   amfs_cont() is already sleeping on this mntfs
+   * so as soon as that wakeup happens amfs_cont() is called and
    * this mount is retried.
    */
-  if ((fs = mf->mf_server))
+  if (mf->mf_server)
     /*
      * We don't really care if there's an error returned.
      * Since this is just to help speed things along, the
      * error will get handled properly elsewhere.
      */
-    (void) nfs_srvr_port(fs, &port, (voidp) mf);
+    get_mountd_port(mf->mf_server, &mountd_port, get_mntfs_wchan(mf));
 
   return 0;
 }
 
 
 static int
-do_mount(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf)
+do_mount(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
 {
   struct stat stb;
 
-#ifdef DEBUG
-  dlog("amfs_host: mounting fs %s on %s\n", fs_name, dir);
-#endif /* DEBUG */
+  dlog("amfs_host: mounting fs %s on %s\n", fs_name, mntdir);
 
-  (void) mkdirs(dir, 0555);
-  if (stat(dir, &stb) < 0 || (stb.st_mode & S_IFMT) != S_IFDIR) {
-    plog(XLOG_ERROR, "No mount point for %s - skipping", dir);
+  (void) mkdirs(mntdir, 0555);
+  if (stat(mntdir, &stb) < 0 || (stb.st_mode & S_IFMT) != S_IFDIR) {
+    plog(XLOG_ERROR, "No mount point for %s - skipping", mntdir);
     return ENOENT;
   }
 
-  return mount_nfs_fh(fhp, dir, fs_name, opts, mf);
+  return mount_nfs_fh(fhp, mntdir, fs_name, mf);
 }
 
 
@@ -204,10 +203,14 @@ sortfun(const voidp x, const voidp y)
  * Get filehandle
  */
 static int
-fetch_fhandle(CLIENT * client, char *dir, am_nfs_handle_t *fhp, u_long nfs_version)
+fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_version)
 {
   struct timeval tv;
   enum clnt_stat clnt_stat;
+  struct fhstatus res;
+#ifdef HAVE_FS_NFS3
+  struct am_mountres3 res3;
+#endif /* HAVE_FS_NFS3 */
 
   /*
    * Pick a number, any number...
@@ -215,9 +218,7 @@ fetch_fhandle(CLIENT * client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versi
   tv.tv_sec = 20;
   tv.tv_usec = 0;
 
-#ifdef DEBUG
   dlog("Fetching fhandle for %s", dir);
-#endif /* DEBUG */
 
   /*
    * Call the mount daemon on the remote host to
@@ -227,25 +228,28 @@ fetch_fhandle(CLIENT * client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versi
   plog(XLOG_INFO, "fetch_fhandle: NFS version %d", (int) nfs_version);
 #ifdef HAVE_FS_NFS3
   if (nfs_version == NFS_VERSION3) {
-    memset((char *) &fhp->v3, 0, sizeof(fhp->v3));
+    memset((char *) &res3, 0, sizeof(res3));
     clnt_stat = clnt_call(client,
 			  MOUNTPROC_MNT,
 			  (XDRPROC_T_TYPE) xdr_dirpath,
 			  (SVC_IN_ARG_TYPE) &dir,
-			  (XDRPROC_T_TYPE) xdr_mountres3,
-			  (SVC_IN_ARG_TYPE) &fhp->v3,
+			  (XDRPROC_T_TYPE) xdr_am_mountres3,
+			  (SVC_IN_ARG_TYPE) &res3,
 			  tv);
     if (clnt_stat != RPC_SUCCESS) {
       plog(XLOG_ERROR, "mountd rpc failed: %s", clnt_sperrno(clnt_stat));
       return EIO;
     }
     /* Check the status of the filehandle */
-    if ((errno = fhp->v3.fhs_status)) {
-#ifdef DEBUG
+    if ((errno = res3.fhs_status)) {
       dlog("fhandle fetch for mount version 3 failed: %m");
-#endif /* DEBUG */
       return errno;
     }
+    memset((voidp) &fhp->v3, 0, sizeof(am_nfs_fh3));
+    fhp->v3.am_fh3_length = res3.mountres3_u.mountinfo.fhandle.fhandle3_len;
+    memmove(fhp->v3.am_fh3_data,
+	    res3.mountres3_u.mountinfo.fhandle.fhandle3_val,
+	    fhp->v3.am_fh3_length);
   } else {			/* not NFS_VERSION3 mount */
 #endif /* HAVE_FS_NFS3 */
     clnt_stat = clnt_call(client,
@@ -253,21 +257,19 @@ fetch_fhandle(CLIENT * client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versi
 			  (XDRPROC_T_TYPE) xdr_dirpath,
 			  (SVC_IN_ARG_TYPE) &dir,
 			  (XDRPROC_T_TYPE) xdr_fhstatus,
-			  (SVC_IN_ARG_TYPE) &fhp->v2,
+			  (SVC_IN_ARG_TYPE) &res,
 			  tv);
     if (clnt_stat != RPC_SUCCESS) {
-      const char *msg = clnt_sperrno(clnt_stat);
-      plog(XLOG_ERROR, "mountd rpc failed: %s", msg);
+      plog(XLOG_ERROR, "mountd rpc failed: %s", clnt_sperrno(clnt_stat));
       return EIO;
     }
     /* Check status of filehandle */
-    if (fhp->v2.fhs_status) {
-      errno = fhp->v2.fhs_status;
-#ifdef DEBUG
+    if (res.fhs_status) {
+      errno = res.fhs_status;
       dlog("fhandle fetch for mount version 1 failed: %m");
-#endif /* DEBUG */
       return errno;
     }
+    memmove(&fhp->v2, &res.fhs_fh, NFS_FHSIZE);
 #ifdef HAVE_FS_NFS3
   } /* end of "if (nfs_version == NFS_VERSION3)" statement */
 #endif /* HAVE_FS_NFS3 */
@@ -292,11 +294,8 @@ already_mounted(mntlist *mlist, char *dir)
 }
 
 
-/*
- * Mount the export tree from a host
- */
 static int
-amfs_host_fmount(mntfs *mf)
+amfs_host_mount(am_node *am, mntfs *mf)
 {
   struct timeval tv2;
   CLIENT *client;
@@ -318,6 +317,14 @@ amfs_host_fmount(mntfs *mf)
   u_long mnt_version;
 
   /*
+   * WebNFS servers don't necessarily run mountd.
+   */
+  if (mf->mf_flags & MFF_WEBNFS) {
+    plog(XLOG_ERROR, "amfs_host_mount: cannot support WebNFS");
+    return EIO;
+  }
+
+  /*
    * Read the mount list
    */
   mlist = read_mtab(mf->mf_mount, mnttab_file_name);
@@ -335,10 +342,10 @@ amfs_host_fmount(mntfs *mf)
    */
   host = mf->mf_server->fs_host;
   sin = *mf->mf_server->fs_ip;
-  plog(XLOG_INFO, "amfs_host_fmount: NFS version %d", (int) mf->mf_server->fs_version);
+  plog(XLOG_INFO, "amfs_host_mount: NFS version %d", (int) mf->mf_server->fs_version);
 #ifdef HAVE_FS_NFS3
   if (mf->mf_server->fs_version == NFS_VERSION3)
-    mnt_version = MOUNTVERS3;
+    mnt_version = AM_MOUNTVERS3;
   else
 #endif /* HAVE_FS_NFS3 */
     mnt_version = MOUNTVERS;
@@ -375,9 +382,7 @@ amfs_host_fmount(mntfs *mf)
   }
   client->cl_auth = nfs_auth;
 
-#ifdef DEBUG
   dlog("Fetching export list from %s", host);
-#endif /* DEBUG */
 
   /*
    * Fetch the export list
@@ -393,7 +398,7 @@ amfs_host_fmount(mntfs *mf)
 			tv2);
   if (clnt_stat != RPC_SUCCESS) {
     const char *msg = clnt_sperrno(clnt_stat);
-    plog(XLOG_ERROR, "host_fmount rpc failed: %s", msg);
+    plog(XLOG_ERROR, "host_mount rpc failed: %s", msg);
     /* clnt_perror(client, "rpc"); */
     error = EIO;
     goto out;
@@ -403,7 +408,6 @@ amfs_host_fmount(mntfs *mf)
    * Figure out how many exports were returned
    */
   for (n_export = 0, ex = exlist; ex; ex = ex->ex_next) {
-    /* printf("export %s\n", ex->ex_dir); */
     n_export++;
   }
 
@@ -414,8 +418,11 @@ amfs_host_fmount(mntfs *mf)
    */
   ep = (exports *) xmalloc(n_export * sizeof(exports));
   for (j = 0, ex = exlist; ex; ex = ex->ex_next) {
-    make_mntpt(mntpt, ex, mf);
-    if (!already_mounted(mlist, mntpt))
+    make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount);
+    if (already_mounted(mlist, mntpt))
+      /* we have at least one mounted f/s, so don't fail the mount */
+      ok = TRUE;
+    else
       ep[j++] = ex;
   }
   n_export = j;
@@ -441,9 +448,7 @@ amfs_host_fmount(mntfs *mf)
   for (j = k = 0; j < n_export; j++) {
     /* Check and avoid a duplicated export entry */
     if (j > k && ep[k] && STREQ(ep[j]->ex_dir, ep[k]->ex_dir)) {
-#ifdef DEBUG
       dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir);
-#endif /* DEBUG */
       ep[j] = 0;
     } else {
       k = j;
@@ -460,9 +465,9 @@ amfs_host_fmount(mntfs *mf)
    * error code 0 at the end.  If they all fail then return
    * the last error code.
    */
-  strncpy(fs_name, mf->mf_info, sizeof(fs_name));
+  xstrlcpy(fs_name, mf->mf_info, MAXPATHLEN);
   if ((rfs_dir = strchr(fs_name, ':')) == (char *) 0) {
-    plog(XLOG_FATAL, "amfs_host_fmount: mf_info has no colon");
+    plog(XLOG_FATAL, "amfs_host_mount: mf_info has no colon");
     error = EINVAL;
     goto out;
   }
@@ -470,9 +475,15 @@ amfs_host_fmount(mntfs *mf)
   for (j = 0; j < n_export; j++) {
     ex = ep[j];
     if (ex) {
-      strcpy(rfs_dir, ex->ex_dir);
-      make_mntpt(mntpt, ex, mf);
-      if (do_mount(&fp[j], mntpt, fs_name, mf->mf_mopts, mf) == 0)
+      /*
+       * Note: the sizeof space left in rfs_dir is what's left in fs_name
+       * after strchr() above returned a pointer _inside_ fs_name.  The
+       * calculation below also takes into account that rfs_dir was
+       * incremented by the ++ above.
+       */
+      xstrlcpy(rfs_dir, ex->ex_dir, sizeof(fs_name) - (rfs_dir - fs_name));
+      make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount);
+      if (do_mount(&fp[j], mntpt, fs_name, mf) == 0)
 	ok = TRUE;
     }
   }
@@ -521,9 +532,10 @@ directory_prefix(char *pref, char *dir)
  * Unmount a mount tree
  */
 static int
-amfs_host_fumount(mntfs *mf)
+amfs_host_umount(am_node *am, mntfs *mf)
 {
   mntlist *ml, *mprev;
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
   int xerror = 0;
 
   /*
@@ -558,18 +570,24 @@ amfs_host_fumount(mntfs *mf)
     char *dir = ml->mnt->mnt_dir;
     if (directory_prefix(mf->mf_mount, dir)) {
       int error;
-#ifdef DEBUG
       dlog("amfs_host: unmounts %s", dir);
-#endif /* DEBUG */
       /*
        * Unmount "dir"
        */
-      error = UMOUNT_FS(dir, mnttab_file_name);
+      error = UMOUNT_FS(dir, mnttab_file_name, unmount_flags);
       /*
        * Keep track of errors
        */
       if (error) {
-	if (!xerror)
+	/*
+	 * If we have not already set xerror and error is not ENOENT,
+	 * then set xerror equal to error and log it.
+	 * 'xerror' is the return value for this function.
+	 *
+	 * We do not want to pass ENOENT as an error because if the
+	 * directory does not exists our work is done anyway.
+	 */
+	if (!xerror && error != ENOENT)
 	  xerror = error;
 	if (error != EBUSY) {
 	  errno = error;
@@ -590,7 +608,7 @@ amfs_host_fumount(mntfs *mf)
    * Try to remount, except when we are shutting down.
    */
   if (xerror && amd_state != Finishing) {
-    xerror = amfs_host_fmount(mf);
+    xerror = amfs_host_mount(am, mf);
     if (!xerror) {
       /*
        * Don't log this - it's usually too verbose
@@ -610,9 +628,8 @@ amfs_host_fumount(mntfs *mf)
  * mountd protocol is badly broken anyway.
  */
 static void
-amfs_host_umounted(am_node *mp)
+amfs_host_umounted(mntfs *mf)
 {
-  mntfs *mf = mp->am_mnt;
   char *host;
   CLIENT *client;
   enum clnt_stat clnt_stat;
@@ -625,6 +642,14 @@ amfs_host_umounted(am_node *mp)
     return;
 
   /*
+   * WebNFS servers shouldn't ever get here.
+   */
+  if (mf->mf_flags & MFF_WEBNFS) {
+    plog(XLOG_ERROR, "amfs_host_umounted: cannot support WebNFS");
+    return;
+  }
+
+  /*
    * Take a copy of the server hostname, address, and NFS version
    * to mount version conversion.
    */
@@ -633,7 +658,7 @@ amfs_host_umounted(am_node *mp)
   plog(XLOG_INFO, "amfs_host_umounted: NFS version %d", (int) mf->mf_server->fs_version);
 #ifdef HAVE_FS_NFS3
   if (mf->mf_server->fs_version == NFS_VERSION3)
-    mnt_version = MOUNTVERS3;
+    mnt_version = AM_MOUNTVERS3;
   else
 #endif /* HAVE_FS_NFS3 */
     mnt_version = MOUNTVERS;
@@ -660,9 +685,7 @@ amfs_host_umounted(am_node *mp)
   }
   client->cl_auth = nfs_auth;
 
-#ifdef DEBUG
   dlog("Unmounting all from %s", host);
-#endif /* DEBUG */
 
   clnt_stat = clnt_call(client,
 			MOUNTPROC_UMNTALL,
diff --git a/contrib/amd/amd/amfs_inherit.c b/contrib/amd/amd/amfs_inherit.c
deleted file mode 100644
index 891afea..0000000
--- a/contrib/amd/amd/amfs_inherit.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 1997-1999 Erez Zadok
- * Copyright (c) 1989 Jan-Simon Pendry
- * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry at Imperial College, London.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgment:
- *      This product includes software developed by the University of
- *      California, Berkeley and its contributors.
- * 4. 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.
- *
- * 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.
- *
- *      %W% (Berkeley) %G%
- *
- * $Id: amfs_inherit.c,v 1.2 1999/01/10 21:53:41 ezk Exp $
- *
- */
-
-/*
- * Inheritance file system.
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-#include <am_defs.h>
-#include <amd.h>
-
-/*
- * This implements a filesystem restart.
- *
- * This is a *gross* hack - it knows far too
- * much about the way other parts of the
- * system work.  See restart.c too.
- */
-
-static char *amfs_inherit_match(am_opts *fo);
-static int amfs_inherit_fmount(mntfs *mf);
-static int amfs_inherit_fumount(mntfs *mf);
-static int amfs_inherit_init(mntfs *mf);
-static int amfs_inherit_mount(am_node *mp);
-
-
-/*
- * Ops structure
- */
-am_ops amfs_inherit_ops =
-{
-  "inherit",
-  amfs_inherit_match,
-  amfs_inherit_init,
-  amfs_inherit_mount,
-  amfs_inherit_fmount,
-  amfs_auto_fumount,
-  amfs_inherit_fumount,
-  amfs_error_lookuppn,
-  amfs_error_readdir,
-  0,				/* amfs_inherit_readlink */
-  0,				/* amfs_inherit_mounted */
-  0,				/* amfs_inherit_umounted */
-  find_amfs_auto_srvr,
-  FS_DISCARD
-};
-
-
-/*
- * This should never be called.
- */
-static char *
-amfs_inherit_match(am_opts *fo)
-{
-  plog(XLOG_FATAL, "amfs_inherit_match called!");
-  return 0;
-}
-
-
-static int
-amfs_inherit_init(mntfs *mf)
-{
-  mntfs *mf_link = (mntfs *) mf->mf_private;
-
-  if (mf_link == 0) {
-    plog(XLOG_ERROR, "Remount collision on %s?", mf->mf_mount);
-    plog(XLOG_FATAL, "Attempting to init not-a-filesystem");
-    return EINVAL;
-  }
-
-  if (mf_link->mf_ops->fs_init)
-    return (*mf_link->mf_ops->fs_init) (mf_link);
-  return 0;
-}
-
-
-/*
- * Take the linked mount point and
- * propagate.
- */
-static mntfs *
-amfs_inherit_inherit(mntfs *mf)
-{
-  mntfs *mf_link = (mntfs *) mf->mf_private;
-
-  if (mf_link == 0) {
-    plog(XLOG_FATAL, "Attempting to inherit not-a-filesystem");
-    return 0;			/* XXX */
-  }
-  mf_link->mf_fo = mf->mf_fo;
-
-  /*
-   * Discard the old map.
-   * Don't call am_unmounted since this
-   * node was never really mounted in the
-   * first place.
-   */
-  mf->mf_private = 0;
-  free_mntfs(mf);
-
-  /*
-   * Free the dangling reference
-   * to the mount link.
-   */
-  free_mntfs(mf_link);
-
-  /*
-   * Get a hold of the other entry
-   */
-  mf_link->mf_flags &= ~MFF_RESTART;
-
-  /* Say what happened */
-  plog(XLOG_INFO, "restarting %s on %s", mf_link->mf_info, mf_link->mf_mount);
-
-  return mf_link;
-}
-
-
-static int
-amfs_inherit_mount(am_node *mp)
-{
-  mntfs *newmf = amfs_inherit_inherit(mp->am_mnt);
-
-  if (newmf) {
-    mp->am_mnt = newmf;
-    /*
-     * XXX - must do the am_mounted call here
-     */
-    if (newmf->mf_ops->fs_flags & FS_MBACKGROUND)
-      am_mounted(mp);
-
-    new_ttl(mp);
-    return 0;
-  }
-  return EINVAL;
-}
-
-
-static int
-amfs_inherit_fmount(mntfs *mf)
-{
-  am_node *mp = find_mf(mf);
-
-  if (mp)
-    return amfs_inherit_mount(mp);
-  return amfs_inherit_inherit(mf) ? 0 : EINVAL;
-}
-
-
-static int
-amfs_inherit_fumount(mntfs *mf)
-{
-  /*
-   * Always succeed
-   */
-  return 0;
-}
diff --git a/contrib/amd/amd/amfs_link.c b/contrib/amd/amd/amfs_link.c
index fcb142d..e75ab86 100644
--- a/contrib/amd/amd/amfs_link.c
+++ b/contrib/amd/amd/amfs_link.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_link.c,v 1.2 1999/01/10 21:53:42 ezk Exp $
+ * File: am-utils/amd/amfs_link.c
  *
  */
 
@@ -52,6 +51,9 @@
 #include <am_defs.h>
 #include <amd.h>
 
+/* forward declarations */
+static int amfs_link_mount(am_node *mp, mntfs *mf);
+static int amfs_link_umount(am_node *mp, mntfs *mf);
 
 /*
  * Ops structures
@@ -61,17 +63,20 @@ am_ops amfs_link_ops =
   "link",
   amfs_link_match,
   0,				/* amfs_link_init */
-  amfs_auto_fmount,
-  amfs_link_fmount,
-  amfs_auto_fumount,
-  amfs_link_fumount,
-  amfs_error_lookuppn,
+  amfs_link_mount,
+  amfs_link_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* amfs_link_readlink */
   0,				/* amfs_link_mounted */
   0,				/* amfs_link_umounted */
-  find_amfs_auto_srvr,
-  0
+  amfs_generic_find_srvr,
+  0,				/* nfs_fs_flags */
+  0,				/* amfs_link_get_wchan */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_LINK_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -88,54 +93,41 @@ amfs_link_match(am_opts *fo)
   }
 
   /*
-   * Bug report (14/12/89) from Jay Plett <jay@princeton.edu>
-   * If an automount point has the same name as an existing
-   * link type mount Amd hits a race condition and either hangs
-   * or causes a symlink loop.
+   * If the link target points to another mount point, then we could
+   * end up with an unpleasant situation, where the link f/s simply
+   * "assumes" the mntfs of that mount point.
    *
-   * If fs begins with a '/' change the opt_fs & opt_sublink
-   * fields so that the fs option doesn't end up pointing at
-   * an existing symlink.
+   * For example, if the link points to /usr, and /usr is a real ufs
+   * filesystem, then the link f/s will use the inherited ufs mntfs,
+   * and the end result will be that it will become unmountable.
    *
-   * If sublink is nil then set sublink to fs
-   * else set sublink to fs / sublink
+   * To prevent this, we use a hack: we prepend a dot ('.') to opt_fs if
+   * its original value was an absolute path, so that it will never match
+   * any other mntfs.
    *
-   * Finally set fs to ".".
+   * XXX: a less hacky solution should be used...
    */
-  if (*fo->opt_fs == '/') {
-    char *fullpath;
-    char *link = fo->opt_sublink;
-    if (link) {
-      if (*link == '/')
-	fullpath = strdup(link);
-      else
-	fullpath = str3cat((char *) 0, fo->opt_fs, "/", link);
-    } else {
-      fullpath = strdup(fo->opt_fs);
-    }
-
-    if (fo->opt_sublink)
-      XFREE(fo->opt_sublink);
-    fo->opt_sublink = fullpath;
-    fo->opt_fs = str3cat(fo->opt_fs, ".", fullpath, "");
+  if (fo->opt_fs[0] == '/') {
+    char *link_hack = str3cat(NULL, ".", fo->opt_fs, "");
+    if (!fo->opt_sublink)
+      fo->opt_sublink = strdup(fo->opt_fs);
+    XFREE(fo->opt_fs);
+    fo->opt_fs = link_hack;
   }
 
   return strdup(fo->opt_fs);
 }
 
 
-int
-amfs_link_fmount(mntfs *mf)
+static int
+amfs_link_mount(am_node *mp, mntfs *mf)
 {
-  /*
-   * Wow - this is hard to implement! :-)
-   */
   return 0;
 }
 
 
-int
-amfs_link_fumount(mntfs *mf)
+static int
+amfs_link_umount(am_node *mp, mntfs *mf)
 {
   return 0;
 }
diff --git a/contrib/amd/amd/amfs_linkx.c b/contrib/amd/amd/amfs_linkx.c
index 728597f..e306eda 100644
--- a/contrib/amd/amd/amfs_linkx.c
+++ b/contrib/amd/amd/amfs_linkx.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_linkx.c,v 1.2 1999/01/10 21:53:42 ezk Exp $
+ * File: am-utils/amd/amfs_linkx.c
  *
  */
 
@@ -53,7 +52,8 @@
 #include <amd.h>
 
 /* forward declarations */
-static int amfs_linkx_mount(am_node *mp);
+static int amfs_linkx_mount(am_node *mp, mntfs *mf);
+static int amfs_linkx_umount(am_node *mp, mntfs *mf);
 
 /*
  * linkx operations
@@ -64,21 +64,24 @@ struct am_ops amfs_linkx_ops =
   amfs_link_match,
   0,				/* amfs_linkx_init */
   amfs_linkx_mount,
-  0,
-  amfs_auto_fumount,
-  amfs_link_fumount,
-  amfs_error_lookuppn,
+  amfs_linkx_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* amfs_linkx_readlink */
   0,				/* amfs_linkx_mounted */
   0,				/* amfs_linkx_umounted */
-  find_amfs_auto_srvr,
-  FS_MBACKGROUND
+  amfs_generic_find_srvr,
+  0,				/* amfs_linkx_get_wchan */
+  FS_MBACKGROUND,
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_LINKX_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
 static int
-amfs_linkx_mount(am_node *mp)
+amfs_linkx_mount(am_node *mp, mntfs *mf)
 {
   /*
    * Check for existence of target.
@@ -89,7 +92,7 @@ amfs_linkx_mount(am_node *mp)
   if (mp->am_link)
     ln = mp->am_link;
   else				/* should never occur */
-    ln = mp->am_mnt->mf_mount;
+    ln = mf->mf_mount;
 
   /*
    * Use lstat, not stat, since we don't
@@ -101,3 +104,10 @@ amfs_linkx_mount(am_node *mp)
 
   return 0;
 }
+
+
+static int
+amfs_linkx_umount(am_node *mp, mntfs *mf)
+{
+  return 0;
+}
diff --git a/contrib/amd/amd/amfs_nfsl.c b/contrib/amd/amd/amfs_nfsl.c
index 42e0102..bb48f0e 100644
--- a/contrib/amd/amd/amfs_nfsl.c
+++ b/contrib/amd/amd/amfs_nfsl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_nfsl.c,v 1.3 1999/01/10 21:53:42 ezk Exp $
+ * File: am-utils/amd/amfs_nfsl.c
  *
  */
 
@@ -60,9 +59,9 @@
 /* forward declarations */
 static char *amfs_nfsl_match(am_opts *fo);
 static int amfs_nfsl_init(mntfs *mf);
-static int amfs_nfsl_fmount(mntfs *mf);
-static int amfs_nfsl_fumount(mntfs *mf);
-static void amfs_nfsl_umounted(am_node *mp);
+static int amfs_nfsl_mount(am_node *mp, mntfs *mf);
+static int amfs_nfsl_umount(am_node *mp, mntfs *mf);
+static void amfs_nfsl_umounted(mntfs *mf);
 static fserver *amfs_nfsl_ffserver(mntfs *mf);
 
 /*
@@ -70,20 +69,23 @@ static fserver *amfs_nfsl_ffserver(mntfs *mf);
  */
 am_ops amfs_nfsl_ops =
 {
-  "nfsl",			/* name of file system */
-  amfs_nfsl_match,		/* match */
-  amfs_nfsl_init,		/* initialize */
-  amfs_auto_fmount,		/* mount vnode */
-  amfs_nfsl_fmount,		/* mount vfs */
-  amfs_auto_fumount,		/* unmount vnode */
-  amfs_nfsl_fumount,		/* unmount VFS */
-  amfs_error_lookuppn,		/* lookup path-name */
-  amfs_error_readdir,		/* read directory */
-  0,				/* read link */
-  0,				/* after-mount extra actions */
-  amfs_nfsl_umounted,		/* after-umount extra actions */
-  amfs_nfsl_ffserver,		/* find a file server */
-  FS_MKMNT | FS_BACKGROUND | FS_AMQINFO	/* flags */
+  "nfsl",
+  amfs_nfsl_match,
+  amfs_nfsl_init,
+  amfs_nfsl_mount,
+  amfs_nfsl_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
+  amfs_error_readdir,
+  0,				/* amfs_nfsl_readlink */
+  0,				/* amfs_nfsl_mounted */
+  amfs_nfsl_umounted,
+  amfs_nfsl_ffserver,
+  0,				/* amfs_nfsl_get_wchan */
+  FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,	/* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_NFSL_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -94,10 +96,16 @@ am_ops amfs_nfsl_ops =
 static char *
 amfs_nfsl_match(am_opts *fo)
 {
-  char *cp = fo->opt_fs;
+  char *cp;
   char *ho = fo->opt_rhost;
+  char *retval;
   struct stat stb;
 
+  if (fo->opt_sublink)
+    cp = fo->opt_sublink;
+  else
+    cp = fo->opt_fs;
+
   if (!cp || !ho) {
     plog(XLOG_USER, "amfs_nfsl: host $fs and $rhost must be specified");
     return NULL;
@@ -105,20 +113,20 @@ amfs_nfsl_match(am_opts *fo)
 
   /*
    * If this host is not the same as $rhost, or if link does not exist,
-   * perform nfs_match(), same as for type:=nfs.
-   * If link value exists (or same host), then perform amfs_link_match(),
-   * same as for linkx.
+   * call nfs_ops.fs_match().
+   * If link value exists (or same host), call amfs_link_ops.fs_match().
    */
   if (!STRCEQ(ho, am_get_hostname())) {
     plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho);
-    return nfs_match(fo);
+    retval = nfs_ops.fs_match(fo);
   } else if (lstat(cp, &stb) < 0) {
     plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp);
-    return nfs_match(fo);
+    retval = nfs_ops.fs_match(fo);
   } else {
     plog(XLOG_INFO, "amfs_nfsl: \"%s\" exists, using type:=link", cp);
-    return amfs_link_match(fo);
+    retval = amfs_link_ops.fs_match(fo);
   }
+  return retval;
 }
 
 
@@ -129,15 +137,15 @@ amfs_nfsl_match(am_opts *fo)
 static int
 amfs_nfsl_init(mntfs *mf)
 {
-  /*
-   * If a link, do nothing (same as type:=link).
-   * If non-link, do nfs_init (same as type:=nfs).
-   */
+  int ret = 0;
   if (mf->mf_flags & MFF_NFSLINK) {
-    return 0;
+    if (amfs_link_ops.fs_init)
+      ret = amfs_link_ops.fs_init(mf);
   } else {
-    return nfs_init(mf);
+    if (nfs_ops.fs_init)
+      ret = nfs_ops.fs_init(mf);
   }
+  return ret;
 }
 
 
@@ -146,17 +154,17 @@ amfs_nfsl_init(mntfs *mf)
  * Returns: 0 if OK, non-zero (errno) if failed.
  */
 static int
-amfs_nfsl_fmount(mntfs *mf)
+amfs_nfsl_mount(am_node *mp, mntfs *mf)
 {
-  /*
-   * If a link, do run amfs_link_fmount() (same as type:=link)
-   * If non-link, do nfs_fmount (same as type:=nfs).
-   */
+  int ret = 0;
   if (mf->mf_flags & MFF_NFSLINK) {
-    return amfs_link_fmount(mf);
+    if (amfs_link_ops.mount_fs)
+      ret = amfs_link_ops.mount_fs(mp, mf);
   } else {
-    return nfs_fmount(mf);
+    if (nfs_ops.mount_fs)
+      ret = nfs_ops.mount_fs(mp, mf);
   }
+  return ret;
 }
 
 
@@ -165,17 +173,17 @@ amfs_nfsl_fmount(mntfs *mf)
  * Returns: 0 if OK, non-zero (errno) if failed.
  */
 static int
-amfs_nfsl_fumount(mntfs *mf)
+amfs_nfsl_umount(am_node *mp, mntfs *mf)
 {
-  /*
-   * If a link, do run amfs_link_fumount() (same as type:=link)
-   * If non-link, do nfs_fumount (same as type:=nfs).
-   */
+  int ret = 0;
   if (mf->mf_flags & MFF_NFSLINK) {
-    return amfs_link_fumount(mf);
+    if (amfs_link_ops.umount_fs)
+      ret = amfs_link_ops.umount_fs(mp, mf);
   } else {
-    return nfs_fumount(mf);
+    if (nfs_ops.umount_fs)
+      ret = nfs_ops.umount_fs(mp, mf);
   }
+  return ret;
 }
 
 
@@ -186,27 +194,14 @@ amfs_nfsl_fumount(mntfs *mf)
  * See amfs_auto_umounted(), host_umounted(), nfs_umounted().
  */
 static void
-amfs_nfsl_umounted(am_node *mp)
+amfs_nfsl_umounted(mntfs *mf)
 {
-  mntfs *mf = mp->am_mnt;
-
-  /*
-   * If a link, do nothing (same as type:=link)
-   * If non-link, do nfs_fumount (same as type:=nfs).
-   */
   if (mf->mf_flags & MFF_NFSLINK) {
-    return;
+    if (amfs_link_ops.umounted)
+      amfs_link_ops.umounted(mf);
   } else {
-    nfs_umounted(mp);
-    /*
-     * MUST remove mount point directories, because if they remain
-     * behind, the next nfsl access will think they are a link
-     * type file system, and not NFS! (when it performs link target
-     * existence test)
-     */
-    if (mf->mf_flags & MFF_MKMNT)
-      rmdirs(mf->mf_mount);
-    return;
+    if (nfs_ops.umounted)
+      nfs_ops.umounted(mf);
   }
 }
 
@@ -218,20 +213,26 @@ amfs_nfsl_umounted(am_node *mp)
 static fserver *
 amfs_nfsl_ffserver(mntfs *mf)
 {
-  char *cp = mf->mf_fo->opt_fs;
+  char *cp;
   char *ho = mf->mf_fo->opt_rhost;
   struct stat stb;
 
+  if (mf->mf_fo->opt_sublink)
+    cp = mf->mf_fo->opt_sublink;
+  else
+    cp = mf->mf_fo->opt_fs;
+
   /*
    * If this host is not the same as $rhost, or if link does not exist,
-   * perform find_nfs_srvr(), same as for type:=nfs.
-   * If link value exists (or same host), then perform
-   * find_amfs_auto_srvr(), same as for linkx.
+   * call amfs_link_ops.ffserver().
+   * If link value exists (or same host), then call ops_nfs.ffserver().
    */
   if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) {
-    return find_nfs_srvr(mf);
+    return nfs_ops.ffserver(mf);
   } else {
     mf->mf_flags |= MFF_NFSLINK;
-    return find_amfs_auto_srvr(mf);
+    /* remove the FS_MKMNT flag, we don't want amd touching the mountpoint */
+    mf->mf_fsflags &= ~FS_MKMNT;
+    return amfs_link_ops.ffserver(mf);
   }
 }
diff --git a/contrib/amd/amd/amfs_nfsx.c b/contrib/amd/amd/amfs_nfsx.c
index a253e50..91be8af 100644
--- a/contrib/amd/amd/amfs_nfsx.c
+++ b/contrib/amd/amd/amfs_nfsx.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_nfsx.c,v 1.2 1999/01/10 21:53:42 ezk Exp $
+ * File: am-utils/amd/amfs_nfsx.c
  *
  */
 
@@ -67,13 +66,13 @@ struct amfs_nfsx {
   int nx_c;			/* Number of elements in nx_v */
   amfs_nfsx_mnt *nx_v;		/* Underlying mounts */
   amfs_nfsx_mnt *nx_try;
+  am_node *nx_mp;
 };
 
 /* forward definitions */
 static char *amfs_nfsx_match(am_opts *fo);
-static int amfs_nfsx_fmount (mntfs *);
-static int amfs_nfsx_fmount(mntfs *mf);
-static int amfs_nfsx_fumount(mntfs *mf);
+static int amfs_nfsx_mount(am_node *am, mntfs *mf);
+static int amfs_nfsx_umount(am_node *am, mntfs *mf);
 static int amfs_nfsx_init(mntfs *mf);
 
 /*
@@ -84,17 +83,20 @@ am_ops amfs_nfsx_ops =
   "nfsx",
   amfs_nfsx_match,
   amfs_nfsx_init,
-  amfs_auto_fmount,
-  amfs_nfsx_fmount,
-  amfs_auto_fumount,
-  amfs_nfsx_fumount,
-  amfs_error_lookuppn,
+  amfs_nfsx_mount,
+  amfs_nfsx_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* amfs_nfsx_readlink */
   0,				/* amfs_nfsx_mounted */
   0,				/* amfs_nfsx_umounted */
   find_nfs_srvr,		/* XXX */
-	/* FS_UBACKGROUND| */ FS_AMQINFO
+  0,				/* amfs_nfsx_get_wchan */
+  /* FS_UBACKGROUND| */ FS_AMQINFO,	/* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_NFSX_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -118,7 +120,7 @@ amfs_nfsx_match(am_opts *fo)
   /* set default sublink */
   if (fo->opt_sublink == 0) {
     ptr = strchr(fo->opt_rfs, ',');
-    if (ptr && ptr != (fo->opt_rfs + 1))
+    if (ptr && ptr > (fo->opt_rfs + 1))
       fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1);
   }
 
@@ -148,17 +150,15 @@ amfs_nfsx_match(am_opts *fo)
    * Determine magic cookie to put in mtab
    */
   xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs);
-#ifdef DEBUG
-  dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
+  dlog("NFSX: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
        fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
-#endif /* DEBUG */
 
   return xmtab;
 }
 
 
 static void
-amfs_nfsx_prfree(voidp vp)
+amfs_nfsx_prfree(opaque_t vp)
 {
   struct amfs_nfsx *nx = (struct amfs_nfsx *) vp;
   int i;
@@ -201,7 +201,7 @@ amfs_nfsx_init(mntfs *mf)
       error = EINVAL;
       goto errexit;
     }
-    pref = host +1;
+    pref = host + 1;
     host = info;
 
     /*
@@ -212,14 +212,16 @@ amfs_nfsx_init(mntfs *mf)
     /*
      * Count array size
      */
-    for (i = 0; ivec[i]; i++) ;
+    for (i = 0; ivec[i]; i++)
+      /* nothing */;
 
     nx = ALLOC(struct amfs_nfsx);
-    mf->mf_private = (voidp) nx;
+    mf->mf_private = (opaque_t) nx;
     mf->mf_prfree = amfs_nfsx_prfree;
 
     nx->nx_c = i - 1;		/* i-1 because we don't want the prefix */
     nx->nx_v = (amfs_nfsx_mnt *) xmalloc(nx->nx_c * sizeof(amfs_nfsx_mnt));
+    nx->nx_mp = 0;
     {
       char *mp = 0;
       char *xinfo = 0;
@@ -243,11 +245,11 @@ amfs_nfsx_init(mntfs *mf)
 	normalize_slash(xinfo);
 	if (pref[1] != '\0')
 	  deslashify(xinfo);
-#ifdef DEBUG
 	dlog("amfs_nfsx: init mount for %s on %s", xinfo, mp);
-#endif /* DEBUG */
 	nx->nx_v[i].n_error = -1;
 	nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts);
+	/* propagate the on_autofs flag */
+	nx->nx_v[i].n_mnt->mf_flags |= mf->mf_flags & MFF_ON_AUTOFS;
       }
       if (rfs)
 	XFREE(rfs);
@@ -274,7 +276,9 @@ amfs_nfsx_init(mntfs *mf)
   for (i = 0; i < nx->nx_c; i++) {
     amfs_nfsx_mnt *n = &nx->nx_v[i];
     mntfs *m = n->n_mnt;
-    int error = (*m->mf_ops->fs_init) (m);
+    int error = 0;
+    if (m->mf_ops->fs_init && !(mf->mf_flags & MFF_RESTART))
+      error = m->mf_ops->fs_init(m);
     /*
      * if you just "return error" here, you will have made a failure
      * in any submounts to fail the whole group.  There was old unused code
@@ -287,7 +291,7 @@ amfs_nfsx_init(mntfs *mf)
       glob_error = -1;
       if (!asked_for_wakeup) {
 	asked_for_wakeup = 1;
-	sched_task(wakeup_task, (voidp) mf, (voidp) m);
+	sched_task(wakeup_task, (opaque_t) mf, get_mntfs_wchan(m));
       }
     }
   }
@@ -297,10 +301,11 @@ amfs_nfsx_init(mntfs *mf)
 
 
 static void
-amfs_nfsx_cont(int rc, int term, voidp closure)
+amfs_nfsx_cont(int rc, int term, opaque_t arg)
 {
-  mntfs *mf = (mntfs *) closure;
+  mntfs *mf = (mntfs *) arg;
   struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
+  am_node *mp = nx->nx_mp;
   amfs_nfsx_mnt *n = nx->nx_try;
 
   n->n_mnt->mf_flags &= ~(MFF_ERROR | MFF_MOUNTING);
@@ -309,7 +314,7 @@ amfs_nfsx_cont(int rc, int term, voidp closure)
   /*
    * Wakeup anything waiting for this mount
    */
-  wakeup((voidp) n->n_mnt);
+  wakeup(get_mntfs_wchan(n->n_mnt));
 
   if (rc || term) {
     if (term) {
@@ -334,52 +339,41 @@ amfs_nfsx_cont(int rc, int term, voidp closure)
     /*
      * The mount worked.
      */
-    mf_mounted(n->n_mnt);
+    mf_mounted(n->n_mnt, FALSE); /* FALSE => don't free the n_mnt->am_opts */
     n->n_error = 0;
   }
 
   /*
    * Do the remaining bits
    */
-  if (amfs_nfsx_fmount(mf) >= 0) {
-    wakeup((voidp) mf);
-    mf->mf_flags &= ~MFF_MOUNTING;
-    mf_mounted(mf);
-  }
+  if (amfs_nfsx_mount(mp, mf) >= 0)
+    wakeup(get_mntfs_wchan(mf));
 }
 
 
 static int
-try_amfs_nfsx_mount(voidp mv)
+try_amfs_nfsx_mount(opaque_t mv)
 {
   mntfs *mf = (mntfs *) mv;
+  struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
+  am_node *mp = nx->nx_mp;
   int error;
 
-  mf->mf_flags |= MFF_MOUNTING;
-  error = (*mf->mf_ops->fmount_fs) (mf);
-  mf->mf_flags &= ~MFF_MOUNTING;
+  error = mf->mf_ops->mount_fs(mp, mf);
 
   return error;
 }
 
 
 static int
-amfs_nfsx_remount(mntfs *mf, int fg)
+amfs_nfsx_remount(am_node *am, mntfs *mf, int fg)
 {
   struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
   amfs_nfsx_mnt *n;
   int glob_error = -1;
 
-  for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
-    mntfs *m = n->n_mnt;
-    if (n->n_error < 0) {
-      if (!(m->mf_flags & MFF_MKMNT) && m->mf_ops->fs_flags & FS_MKMNT) {
-	int error = mkdirs(m->mf_mount, 0555);
-	if (!error)
-	  m->mf_flags |= MFF_MKMNT;
-      }
-    }
-  }
+  /* Save the am_node pointer for later use */
+  nx->nx_mp = am;
 
   /*
    * Iterate through the mntfs's and mount each filesystem
@@ -387,40 +381,38 @@ amfs_nfsx_remount(mntfs *mf, int fg)
    */
   for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
     mntfs *m = n->n_mnt;
+
+    if (m->mf_flags & MFF_MOUNTING)
+      break;
+
+    if (m->mf_flags & MFF_MOUNTED) {
+      mf_mounted(m, FALSE);	/* FALSE => don't free the m->am_opts */
+      n->n_error = glob_error = 0;
+      continue;
+    }
+
     if (n->n_error < 0) {
-      /*
-       * Check fmount entry pt. exists
-       * and then mount...
-       */
-      if (!m->mf_ops->fmount_fs) {
-	n->n_error = EINVAL;
-      } else {
-#ifdef DEBUG
-	dlog("calling underlying fmount on %s", m->mf_mount);
-#endif /* DEBUG */
-	if (!fg && foreground && (m->mf_ops->fs_flags & FS_MBACKGROUND)) {
-	  m->mf_flags |= MFF_MOUNTING;	/* XXX */
-#ifdef DEBUG
-	  dlog("backgrounding mount of \"%s\"", m->mf_info);
-#endif /* DEBUG */
-	  nx->nx_try = n;
-	  run_task(try_amfs_nfsx_mount, (voidp) m, amfs_nfsx_cont, (voidp) mf);
-	  n->n_error = -1;
-	  return -1;
-	} else {
-#ifdef DEBUG
-	  dlog("foreground mount of \"%s\" ...", mf->mf_info);
-#endif /* DEBUG */
-	  n->n_error = (*m->mf_ops->fmount_fs) (m);
-	}
+      /* Create the mountpoint, if and as required */
+      if (!(m->mf_flags & MFF_MKMNT) && m->mf_fsflags & FS_MKMNT) {
+	if (!mkdirs(m->mf_mount, 0555))
+	  m->mf_flags |= MFF_MKMNT;
       }
 
-#ifdef DEBUG
-      if (n->n_error > 0) {
-	errno = n->n_error;	/* XXX */
-	dlog("underlying fmount of %s failed: %m", m->mf_mount);
+      dlog("calling underlying mount on %s", m->mf_mount);
+      if (!fg && foreground && (m->mf_fsflags & FS_MBACKGROUND)) {
+	m->mf_flags |= MFF_MOUNTING;
+	dlog("backgrounding mount of \"%s\"", m->mf_info);
+	nx->nx_try = n;
+	run_task(try_amfs_nfsx_mount, (opaque_t) m, amfs_nfsx_cont, (opaque_t) mf);
+	n->n_error = -1;
+	return -1;
+      } else {
+	dlog("foreground mount of \"%s\" ...", mf->mf_info);
+	n->n_error = m->mf_ops->mount_fs(am, m);
       }
-#endif /* DEBUG */
+
+      if (n->n_error > 0)
+	dlog("underlying fmount of %s failed: %s", m->mf_mount, strerror(n->n_error));
 
       if (n->n_error == 0) {
 	glob_error = 0;
@@ -435,9 +427,9 @@ amfs_nfsx_remount(mntfs *mf, int fg)
 
 
 static int
-amfs_nfsx_fmount(mntfs *mf)
+amfs_nfsx_mount(am_node *am, mntfs *mf)
 {
-  return amfs_nfsx_remount(mf, FALSE);
+  return amfs_nfsx_remount(am, mf, FALSE);
 }
 
 
@@ -447,7 +439,7 @@ amfs_nfsx_fmount(mntfs *mf)
  * and so may hang under extremely rare conditions.
  */
 static int
-amfs_nfsx_fumount(mntfs *mf)
+amfs_nfsx_umount(am_node *am, mntfs *mf)
 {
   struct amfs_nfsx *nx = (struct amfs_nfsx *) mf->mf_private;
   amfs_nfsx_mnt *n;
@@ -469,10 +461,8 @@ amfs_nfsx_fumount(mntfs *mf)
      * which had been successfully unmounted.
      */
     if (n->n_error == 0) {
-#ifdef DEBUG
       dlog("calling underlying fumount on %s", m->mf_mount);
-#endif /* DEBUG */
-      n->n_error = (*m->mf_ops->fumount_fs) (m);
+      n->n_error = m->mf_ops->umount_fs(am, m);
       if (n->n_error) {
 	glob_error = n->n_error;
 	n->n_error = 0;
@@ -490,7 +480,7 @@ amfs_nfsx_fumount(mntfs *mf)
    * whole lot...
    */
   if (glob_error) {
-    glob_error = amfs_nfsx_remount(mf, TRUE);
+    glob_error = amfs_nfsx_remount(am, mf, TRUE);
     if (glob_error) {
       errno = glob_error;	/* XXX */
       plog(XLOG_USER, "amfs_nfsx: remount of %s failed: %m", mf->mf_mount);
@@ -502,22 +492,12 @@ amfs_nfsx_fumount(mntfs *mf)
      */
     for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
       mntfs *m = n->n_mnt;
-      am_node am;
-
-      /*
-       * XXX: all the umounted handler needs is a
-       * mntfs pointer, so pass an am_node with the right
-       * pointer in it.
-       */
-      memset((voidp) &am, 0, sizeof(am));
-      am.am_mnt = m;
-#ifdef DEBUG
       dlog("calling underlying umounted on %s", m->mf_mount);
-#endif /* DEBUG */
-      (*m->mf_ops->umounted) (&am);
+      if (m->mf_ops->umounted)
+	m->mf_ops->umounted(m);
 
       if (n->n_error < 0) {
-	if (m->mf_ops->fs_flags & FS_MKMNT) {
+	if (m->mf_fsflags & FS_MKMNT) {
 	  (void) rmdirs(m->mf_mount);
 	  m->mf_flags &= ~MFF_MKMNT;
 	}
diff --git a/contrib/amd/amd/amfs_program.c b/contrib/amd/amd/amfs_program.c
index fd03231..843e805 100644
--- a/contrib/amd/amd/amfs_program.c
+++ b/contrib/amd/amd/amfs_program.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_program.c,v 1.5 1999/09/30 21:01:30 ezk Exp $
+ * File: am-utils/amd/amfs_program.c
  *
  */
 
@@ -54,8 +53,8 @@
 
 /* forward definitions */
 static char *amfs_program_match(am_opts *fo);
-static int amfs_program_fmount(mntfs *mf);
-static int amfs_program_fumount(mntfs *mf);
+static int amfs_program_mount(am_node *am, mntfs *mf);
+static int amfs_program_umount(am_node *am, mntfs *mf);
 static int amfs_program_init(mntfs *mf);
 
 /*
@@ -66,17 +65,20 @@ am_ops amfs_program_ops =
   "program",
   amfs_program_match,
   amfs_program_init,
-  amfs_auto_fmount,
-  amfs_program_fmount,
-  amfs_auto_fumount,
-  amfs_program_fumount,
-  amfs_error_lookuppn,
+  amfs_program_mount,
+  amfs_program_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* amfs_program_readlink */
   0,				/* amfs_program_mounted */
   0,				/* amfs_program_umounted */
-  find_amfs_auto_srvr,
-  FS_BACKGROUND | FS_AMQINFO
+  amfs_generic_find_srvr,
+  0,				/* amfs_program_get_wchan */
+  FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,	/* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_PROGRAM_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -88,10 +90,19 @@ amfs_program_match(am_opts *fo)
 {
   char *prog;
 
-  if (!fo->opt_mount || !fo->opt_unmount) {
-    plog(XLOG_ERROR, "program: both mount and unmount must be specified");
+  if (fo->opt_unmount && fo->opt_umount) {
+    plog(XLOG_ERROR, "program: cannot specify both unmount and umount options");
     return 0;
   }
+  if (!fo->opt_mount) {
+    plog(XLOG_ERROR, "program: must specify mount command");
+    return 0;
+  }
+  if (!fo->opt_unmount && !fo->opt_umount) {
+    fo->opt_unmount = str3cat(NULL, UNMOUNT_PROGRAM, " umount ", fo->opt_fs);
+    plog(XLOG_INFO, "program: un/umount not specified; using default \"%s\"",
+	 fo->opt_unmount);
+  }
   prog = strchr(fo->opt_mount, ' ');
 
   return strdup(prog ? prog + 1 : fo->opt_mount);
@@ -101,13 +112,16 @@ amfs_program_match(am_opts *fo)
 static int
 amfs_program_init(mntfs *mf)
 {
-  /*
-   * Save unmount command
-   */
-  if (mf->mf_refc == 1) {
-    mf->mf_private = (voidp) strdup(mf->mf_fo->opt_unmount);
-    mf->mf_prfree = (void (*)(voidp)) free;
-  }
+  /* check if already saved value */
+  if (mf->mf_private != NULL)
+    return 0;
+
+  /* save unmount (or umount) command */
+  if (mf->mf_fo->opt_unmount != NULL)
+    mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_unmount);
+  else
+    mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_umount);
+  mf->mf_prfree = (void (*)(opaque_t)) free;
 
   return 0;
 }
@@ -142,8 +156,7 @@ amfs_program_exec(char *info)
   /*
    * Try the exec
    */
-#ifdef DEBUG
-  amuDebug(D_FULL) {
+  if (amuDebug(D_FULL)) {
     char **cp = xivec;
     plog(XLOG_DEBUG, "executing (un)mount command...");
     while (*cp) {
@@ -151,7 +164,6 @@ amfs_program_exec(char *info)
       cp++;
     }
   }
-#endif /* DEBUG */
 
   if (xivec[0] == 0 || xivec[1] == 0) {
     errno = EINVAL;
@@ -180,14 +192,14 @@ amfs_program_exec(char *info)
 
 
 static int
-amfs_program_fmount(mntfs *mf)
+amfs_program_mount(am_node *am, mntfs *mf)
 {
   return amfs_program_exec(mf->mf_fo->opt_mount);
 }
 
 
 static int
-amfs_program_fumount(mntfs *mf)
+amfs_program_umount(am_node *am, mntfs *mf)
 {
   return amfs_program_exec((char *) mf->mf_private);
 }
diff --git a/contrib/amd/amd/amfs_root.c b/contrib/amd/amd/amfs_root.c
index 91f770dec..243267e 100644
--- a/contrib/amd/amd/amfs_root.c
+++ b/contrib/amd/amd/amfs_root.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_root.c,v 1.2 1999/01/10 21:53:43 ezk Exp $
+ * File: am-utils/amd/amfs_root.c
  *
  */
 
@@ -55,7 +54,7 @@
 /****************************************************************************
  *** FORWARD DEFINITIONS                                                  ***
  ****************************************************************************/
-static int amfs_root_mount(am_node *mp);
+static int amfs_root_mount(am_node *mp, mntfs *mf);
 
 /****************************************************************************
  *** OPS STRUCTURES                                                       ***
@@ -66,16 +65,19 @@ am_ops amfs_root_ops =
   0,				/* amfs_root_match */
   0,				/* amfs_root_init */
   amfs_root_mount,
-  0,
-  amfs_auto_umount,
-  0,
-  amfs_auto_lookuppn,
-  amfs_auto_readdir,
+  amfs_generic_umount,
+  amfs_generic_lookup_child,
+  amfs_generic_mount_child,
+  amfs_generic_readdir,
   0,				/* amfs_root_readlink */
   0,				/* amfs_root_mounted */
   0,				/* amfs_root_umounted */
-  find_amfs_auto_srvr,
-  FS_NOTIMEOUT | FS_AMQINFO | FS_DIRECTORY
+  amfs_generic_find_srvr,
+  0,				/* amfs_root_get_wchan */
+  FS_NOTIMEOUT | FS_AMQINFO | FS_DIRECTORY,	/* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_ROOT_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -87,12 +89,10 @@ am_ops amfs_root_ops =
  * Mount the root...
  */
 static int
-amfs_root_mount(am_node *mp)
+amfs_root_mount(am_node *mp, mntfs *mf)
 {
-  mntfs *mf = mp->am_mnt;
-
   mf->mf_mount = strealloc(mf->mf_mount, pid_fsname);
-  mf->mf_private = (voidp) mapc_find(mf->mf_info, "", NULL);
+  mf->mf_private = (opaque_t) mapc_find(mf->mf_info, "", NULL);
   mf->mf_prfree = mapc_free;
 
   return 0;
diff --git a/contrib/amd/amd/amfs_toplvl.c b/contrib/amd/amd/amfs_toplvl.c
index 5d07f62..1b968f1 100644
--- a/contrib/amd/amd/amfs_toplvl.c
+++ b/contrib/amd/amd/amfs_toplvl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_toplvl.c,v 1.5 1999/02/04 07:24:14 ezk Exp $
+ * File: am-utils/amd/amfs_toplvl.c
  *
  */
 
@@ -55,7 +54,7 @@
 /****************************************************************************
  *** FORWARD DEFINITIONS                                                  ***
  ****************************************************************************/
-
+static int amfs_toplvl_init(mntfs *mf);
 
 /****************************************************************************
  *** OPS STRUCTURES                                                       ***
@@ -63,19 +62,23 @@
 am_ops amfs_toplvl_ops =
 {
   "toplvl",
-  amfs_auto_match,
-  0,				/* amfs_auto_init */
+  amfs_generic_match,
+  amfs_toplvl_init,		/* amfs_toplvl_init */
   amfs_toplvl_mount,
-  0,
   amfs_toplvl_umount,
-  0,
-  amfs_auto_lookuppn,
-  amfs_auto_readdir,		/* browsable version of readdir() */
+  amfs_generic_lookup_child,
+  amfs_generic_mount_child,
+  amfs_generic_readdir,
   0,				/* amfs_toplvl_readlink */
-  amfs_toplvl_mounted,
+  amfs_generic_mounted,
   0,				/* amfs_toplvl_umounted */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY
+  amfs_generic_find_srvr,
+  0,				/* amfs_toplvl_get_wchan */
+  FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND |
+	  FS_AMQINFO | FS_DIRECTORY, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_TOPLVL_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -83,166 +86,79 @@ am_ops amfs_toplvl_ops =
  *** FUNCTIONS                                                             ***
  ****************************************************************************/
 
-/*
- * Mount an automounter directory.
- * The automounter is connected into the system
- * as a user-level NFS server.  mount_amfs_toplvl constructs
- * the necessary NFS parameters to be given to the
- * kernel so that it will talk back to us.
- *
- * NOTE: automounter mounts in themselves are using NFS Version 2.
- */
-static int
-mount_amfs_toplvl(char *dir, char *opts)
+static void
+set_auto_attrcache_timeout(char *preopts, char *opts, size_t l)
 {
-  char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
-  int retry, error, genflags;
-  mntent_t mnt;
-  nfs_args_t nfs_args;
-  am_nfs_fh *fhp;
-  am_nfs_handle_t anh;
-  MTYPE_TYPE type = MOUNT_TYPE_NFS;
-#ifndef HAVE_TRANSPORT_TYPE_TLI
-  u_short port;
-  struct sockaddr_in sin;
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
-
-  memset((voidp) &mnt, 0, sizeof(mnt));
-  mnt.mnt_dir = dir;
-  mnt.mnt_fsname = pid_fsname;
-  mnt.mnt_opts = opts;
-
-  /*
-   * Make sure that amd's top-level NFS mounts are hidden by default
-   * from df.
-   * If they don't appear to support the either the "ignore" mnttab
-   * option entry, or the "auto" one, set the mount type to "nfs".
-   */
-  mnt.mnt_type = HIDE_MOUNT_TYPE;
-
-  retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
-  if (retry <= 0)
-    retry = 2;			/* XXX */
-
-  /*
-   * SET MOUNT ARGS
-   */
-  /*
-   * get fhandle of remote path for automount point
-   */
-  fhp = root_fh(dir);
-  if (!fhp) {
-    plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
-    return EINVAL;
-  }
 
-#ifndef HAVE_TRANSPORT_TYPE_TLI
+#ifdef MNTTAB_OPT_NOAC
   /*
-   * Create sockaddr to point to the local machine.  127.0.0.1
-   * is not used since that will not work in HP-UX clusters and
-   * this is no more expensive.
+   * Don't cache attributes - they are changing under the kernel's feet.
+   * For example, IRIX5.2 will dispense with nfs lookup calls and hand stale
+   * filehandles to getattr unless we disable attribute caching on the
+   * automount points.
    */
-  memset((voidp) &sin, 0, sizeof(sin));
-  sin.sin_family = AF_INET;
-  sin.sin_addr = myipaddr;
-  port = hasmntval(&mnt, MNTTAB_OPT_PORT);
-  if (port) {
-    sin.sin_port = htons(port);
-  } else {
-    plog(XLOG_ERROR, "no port number specified for %s", dir);
-    return EINVAL;
+  if (gopt.auto_attrcache == 0) {
+    xsnprintf(preopts, l, ",%s", MNTTAB_OPT_NOAC);
+    xstrlcat(opts, preopts, l);
   }
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+#endif /* MNTTAB_OPT_NOAC */
 
   /*
-   * Make a ``hostname'' string for the kernel
-   */
-  sprintf(fs_hostname, "pid%ld@%s:%s",
-	  (long) (foreground ? am_mypid : getppid()),
-	  am_get_hostname(),
-	  dir);
-  /*
-   * Most kernels have a name length restriction (64 bytes)...
+   * XXX: note that setting these to 0 in the past resulted in an error on
+   * some systems, which is why it's better to use "noac" if possible.  For
+   * now, we're setting everything possible, but if this will cause trouble,
+   * then we'll have to condition the remainder of this on OPT_NOAC.
    */
-  if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
-    strcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..");
-#ifdef HOSTNAMESZ
-  /*
-   * ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
-   * If you need to get the definition for HOSTNAMESZ found, you may
-   * add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
-   */
-  if (strlen(fs_hostname) >= HOSTNAMESZ)
-    strcpy(fs_hostname + HOSTNAMESZ - 3, "..");
-#endif /* HOSTNAMESZ */
+#ifdef MNTTAB_OPT_ACTIMEO
+  xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTIMEO, gopt.auto_attrcache);
+  xstrlcat(opts, preopts, l);
+#else /* MNTTAB_OPT_ACTIMEO */
+# ifdef MNTTAB_OPT_ACDIRMIN
+  xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMIN, gopt.auto_attrcache);
+  xstrlcat(opts, preopts, l);
+# endif /* MNTTAB_OPT_ACDIRMIN */
+# ifdef MNTTAB_OPT_ACDIRMAX
+  xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTDIRMAX, gopt.auto_attrcache);
+  xstrlcat(opts, preopts, l);
+# endif /* MNTTAB_OPT_ACDIRMAX */
+# ifdef MNTTAB_OPT_ACREGMIN
+  xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMIN, gopt.auto_attrcache);
+  xstrlcat(opts, preopts, l);
+# endif /* MNTTAB_OPT_ACREGMIN */
+# ifdef MNTTAB_OPT_ACREGMAX
+  xsnprintf(preopts, l, ",%s=%d", MNTTAB_OPT_ACTREGMAX, gopt.auto_attrcache);
+  xstrlcat(opts, preopts, l);
+# endif /* MNTTAB_OPT_ACREGMAX */
+#endif /* MNTTAB_OPT_ACTIMEO */
+}
 
-  /*
-   * Finally we can compute the mount genflags set above,
-   * and add any automounter specific flags.
-   */
-  genflags = compute_mount_flags(&mnt);
-  genflags |= compute_automounter_mount_flags(&mnt);
 
-  /* setup the many fields and flags within nfs_args */
-  memmove(&anh.v2.fhs_fh, fhp, sizeof(*fhp));
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-  compute_nfs_args(&nfs_args,
-		   &mnt,
-		   genflags,
-		   nfsncp,
-		   NULL,	/* remote host IP addr is set below */
-		   NFS_VERSION,	/* version 2 */
-		   "udp",
-		   &anh,
-		   fs_hostname,
-		   pid_fsname);
-  /*
-   * IMPORTANT: set the correct IP address AFTERWARDS.  It cannot
-   * be done using the normal mechanism of compute_nfs_args(), because
-   * that one will allocate a new address and use NFS_SA_DREF() to copy
-   * parts to it, while assuming that the ip_addr passed is always
-   * a "struct sockaddr_in".  That assumption is incorrect on TLI systems,
-   * because they define a special macro HOST_SELF which is DIFFERENT
-   * than localhost (127.0.0.1)!
-   */
-  nfs_args.addr = &nfsxprt->xp_ltaddr;
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
-  compute_nfs_args(&nfs_args,
-		   &mnt,
-		   genflags,
-		   &sin,
-		   NFS_VERSION,	/* version 2 */
-		   "udp",
-		   &anh,
-		   fs_hostname,
-		   pid_fsname);
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
-
-  /*************************************************************************
-   * NOTE: while compute_nfs_args() works ok for regular NFS mounts	   *
-   * the toplvl one is not, and so some options must be corrected by hand  *
-   * more carefully, *after* compute_nfs_args() runs.			   *
-   *************************************************************************/
-  compute_automounter_nfs_args(&nfs_args, &mnt);
+/*
+ * Initialize a top-level mount.  In our case, if the user asked for
+ * forced_unmounts, and the OS supports it, then we try forced/lazy unmounts
+ * on any previous toplvl mounts.  This is useful if a previous Amd died and
+ * left behind toplvl mount points (this Amd will clean them up).
+ *
+ * WARNING: Don't use forced/lazy unmounts if you have another valid Amd
+ * running, because this code WILL force those valid toplvl mount points to
+ * be detached as well!
+ */
+static int
+amfs_toplvl_init(mntfs *mf)
+{
+  int error = 0;
 
-  /* This is it!  Here we try to mount amd on its mount points */
-#ifdef DEBUG
-  amuDebug(D_TRACE) {
-    print_nfs_args(&nfs_args, 0);
-    plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
+#if defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)
+  if (gopt.flags & CFM_FORCED_UNMOUNTS) {
+    plog(XLOG_INFO, "amfs_toplvl_init: trying forced/lazy unmount of %s",
+	 mf->mf_mount);
+    error = umount2_fs(mf->mf_mount, AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH);
+    if (error)
+      plog(XLOG_INFO, "amfs_toplvl_init: forced/lazy unmount failed: %m");
+    else
+      dlog("amfs_toplvl_init: forced/lazy unmount succeeded");
   }
-#endif /* DEBUG */
-  error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type,
-		   0, NULL, mnttab_file_name);
-
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-  free_knetconfig(nfs_args.knconf);
-  /*
-   * local automounter mounts do not allocate a special address, so
-   * no need to XFREE(nfs_args.addr) under TLI.
-   */
-#endif /* HAVE_TRANSPORT_TYPE_TLI */
-
+#endif /* MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH */
   return error;
 }
 
@@ -251,13 +167,11 @@ mount_amfs_toplvl(char *dir, char *opts)
  * Mount the top-level
  */
 int
-amfs_toplvl_mount(am_node *mp)
+amfs_toplvl_mount(am_node *mp, mntfs *mf)
 {
-  mntfs *mf = mp->am_mnt;
   struct stat stb;
-  char opts[256], preopts[256];
+  char opts[SIZEOF_OPTS], preopts[SIZEOF_OPTS], toplvl_opts[40];
   int error;
-  char *mnttype;
 
   /*
    * Mounting the automounter.
@@ -271,16 +185,6 @@ amfs_toplvl_mount(am_node *mp)
     plog(XLOG_WARNING, "%s is not a directory", mp->am_path);
     return ENOTDIR;
   }
-  if (mf->mf_ops == &amfs_toplvl_ops)
-    mnttype = "indirect";
-  else if (mf->mf_ops == &amfs_direct_ops)
-    mnttype = "direct";
-#ifdef HAVE_AM_FS_UNION
-  else if (mf->mf_ops == &amfs_union_ops)
-    mnttype = "union";
-#endif /* HAVE_AM_FS_UNION */
-  else
-    mnttype = "auto";
 
   /*
    * Construct some mount options:
@@ -288,49 +192,71 @@ amfs_toplvl_mount(am_node *mp)
    * Tack on magic map=<mapname> option in mtab to emulate
    * SunOS automounter behavior.
    */
-  preopts[0] = '\0';
+
+#ifdef HAVE_FS_AUTOFS
+  if (mf->mf_flags & MFF_IS_AUTOFS) {
+    autofs_get_opts(opts, sizeof(opts), mp->am_autofs_fh);
+  } else
+#endif /* HAVE_FS_AUTOFS */
+  {
+    preopts[0] = '\0';
 #ifdef MNTTAB_OPT_INTR
-  strcat(preopts, MNTTAB_OPT_INTR);
-  strcat(preopts, ",");
+    xstrlcat(preopts, MNTTAB_OPT_INTR, sizeof(preopts));
+    xstrlcat(preopts, ",", sizeof(preopts));
 #endif /* MNTTAB_OPT_INTR */
 #ifdef MNTTAB_OPT_IGNORE
-  strcat(preopts, MNTTAB_OPT_IGNORE);
-  strcat(preopts, ",");
+    xstrlcat(preopts, MNTTAB_OPT_IGNORE, sizeof(preopts));
+    xstrlcat(preopts, ",", sizeof(preopts));
 #endif /* MNTTAB_OPT_IGNORE */
-  sprintf(opts, "%s%s,%s=%d,%s=%d,%s=%d,%s,map=%s",
-	  preopts,
-	  MNTTAB_OPT_RW,
-	  MNTTAB_OPT_PORT, nfs_port,
-	  MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo,
-	  MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans,
-	  mnttype, mf->mf_info);
+    /* write most of the initial options + preopts */
+    xsnprintf(opts, sizeof(opts), "%s%s,%s=%d,%s,map=%s",
+	      preopts,
+	      MNTTAB_OPT_RW,
+	      MNTTAB_OPT_PORT, nfs_port,
+	      mf->mf_ops->fs_type, mf->mf_info);
+
+    /* process toplvl timeo/retrans options, if any */
+    if (gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] > 0) {
+      xsnprintf(toplvl_opts, sizeof(toplvl_opts), ",%s=%d",
+		MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL]);
+      xstrlcat(opts, toplvl_opts, sizeof(opts));
+    }
+    if (gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] > 0) {
+      xsnprintf(toplvl_opts, sizeof(toplvl_opts), ",%s=%d",
+		MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL]);
+      xstrlcat(opts, toplvl_opts, sizeof(opts));
+    }
+
+#ifdef MNTTAB_OPT_NOAC
+    if (gopt.auto_attrcache == 0) {
+      xstrlcat(opts, ",", sizeof(opts));
+      xstrlcat(opts, MNTTAB_OPT_NOAC, sizeof(opts));
+    } else
+#endif /* MNTTAB_OPT_NOAC */
+      set_auto_attrcache_timeout(preopts, opts, sizeof(preopts));
+  }
 
   /* now do the mount */
-  error = mount_amfs_toplvl(mf->mf_mount, opts);
+  error = amfs_mount(mp, mf, opts);
   if (error) {
     errno = error;
-    plog(XLOG_FATAL, "mount_amfs_toplvl: %m");
+    plog(XLOG_FATAL, "amfs_toplvl_mount: amfs_mount failed: %m");
     return error;
   }
   return 0;
 }
 
 
-void
-amfs_toplvl_mounted(mntfs *mf)
-{
-  amfs_auto_mkcacheref(mf);
-}
-
-
 /*
  * Unmount a top-level automount node
  */
 int
-amfs_toplvl_umount(am_node *mp)
+amfs_toplvl_umount(am_node *mp, mntfs *mf)
 {
-  int error;
   struct stat stb;
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+  int error;
+  int count = 0;		/* how many times did we try to unmount? */
 
 again:
   /*
@@ -345,15 +271,48 @@ again:
    * actually fixed the problem - so simulate an ls -ld here.
    */
   if (lstat(mp->am_path, &stb) < 0) {
-#ifdef DEBUG
+    error = errno;
     dlog("lstat(%s): %m", mp->am_path);
-#endif /* DEBUG */
+    goto out;
   }
-  error = UMOUNT_FS(mp->am_path, mnttab_file_name);
+  if ((stb.st_mode & S_IFMT) != S_IFDIR) {
+    plog(XLOG_ERROR, "amfs_toplvl_umount: %s is not a directory, aborting.", mp->am_path);
+    error = ENOTDIR;
+    goto out;
+  }
+
+  error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags);
   if (error == EBUSY) {
+#ifdef HAVE_FS_AUTOFS
+    /*
+     * autofs mounts are "in place", so it is possible
+     * that we can't just unmount our mount points and go away.
+     * If that's the case, just give up.
+     */
+    if (mf->mf_flags & MFF_IS_AUTOFS)
+      return error;
+#endif /* HAVE_FS_AUTOFS */
     plog(XLOG_WARNING, "amfs_toplvl_unmount retrying %s in 1s", mp->am_path);
-    sleep(1);			/* XXX */
+    count++;
+    sleep(1);
+    /*
+     * If user wants forced/lazy unmount semantics, then set those flags,
+     * but only after we've tried normal lstat/umount a few times --
+     * otherwise forced unmounts may hang this very same Amd (by preventing
+     * it from achieving a clean unmount).
+     */
+    if (gopt.flags & CFM_FORCED_UNMOUNTS) {
+      if (count == 5) {		/* after 5 seconds, try MNT_FORCE */
+	dlog("enabling forced unmounts for toplvl node %s", mp->am_path);
+	unmount_flags |= AMU_UMOUNT_FORCE;
+      }
+      if (count == 10) {	/* after 10 seconds, try MNT_DETACH */
+	dlog("enabling detached unmounts for toplvl node %s", mp->am_path);
+	unmount_flags |= AMU_UMOUNT_DETACH;
+      }
+    }
     goto again;
   }
+out:
   return error;
 }
diff --git a/contrib/amd/amd/amfs_union.c b/contrib/amd/amd/amfs_union.c
index 6e079a4..6adb5b0 100644
--- a/contrib/amd/amd/amfs_union.c
+++ b/contrib/amd/amd/amfs_union.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amfs_union.c,v 1.2 1999/01/10 21:53:43 ezk Exp $
+ * File: am-utils/amd/amfs_union.c
  *
  */
 
@@ -55,6 +54,7 @@
 /****************************************************************************
  *** FORWARD DEFINITIONS                                                  ***
  ****************************************************************************/
+static int create_amfs_union_node(char *dir, opaque_t arg);
 static void amfs_union_mounted(mntfs *mf);
 
 
@@ -64,19 +64,22 @@ static void amfs_union_mounted(mntfs *mf);
 am_ops amfs_union_ops =
 {
   "union",
-  amfs_auto_match,
-  0,				/* amfs_auto_init */
+  amfs_generic_match,
+  0,				/* amfs_union_init */
   amfs_toplvl_mount,
-  0,
   amfs_toplvl_umount,
-  0,
-  amfs_auto_lookuppn,
-  amfs_auto_readdir,
-  0,				/* amfs_toplvl_readlink */
+  amfs_generic_lookup_child,
+  amfs_generic_mount_child,
+  amfs_generic_readdir,
+  0,				/* amfs_union_readlink */
   amfs_union_mounted,
-  0,				/* amfs_toplvl_umounted */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY
+  0,				/* amfs_union_umounted */
+  amfs_generic_find_srvr,
+  0,				/* amfs_union_get_wchan */
+  FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY,
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_UNION_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -85,14 +88,17 @@ am_ops amfs_union_ops =
  * XXX: this function may not be used anywhere...
  */
 static int
-create_amfs_union_node(char *dir, voidp arg)
+create_amfs_union_node(char *dir, opaque_t arg)
 {
   if (!STREQ(dir, "/defaults")) {
     int error = 0;
-    (void) amfs_toplvl_ops.lookuppn(arg, dir, &error, VLOOK_CREATE);
+    am_node *am;
+    am = amfs_generic_lookup_child(arg, dir, &error, VLOOK_CREATE);
+    if (am && error < 0)
+      am = amfs_generic_mount_child(am, &error);
     if (error > 0) {
       errno = error;		/* XXX */
-      plog(XLOG_ERROR, "Could not mount %s: %m", dir);
+      plog(XLOG_ERROR, "unionfs: could not mount %s: %m", dir);
     }
     return error;
   }
@@ -103,20 +109,22 @@ create_amfs_union_node(char *dir, voidp arg)
 static void
 amfs_union_mounted(mntfs *mf)
 {
-  int i;
+  int index;
+  am_node *mp;
 
-  amfs_auto_mkcacheref(mf);
+  amfs_mkcacheref(mf);
 
   /*
    * Having made the union mount point,
    * populate all the entries...
    */
-  for (i = 0; i <= last_used_map; i++) {
-    am_node *mp = exported_ap[i];
-    if (mp && mp->am_mnt == mf) {
+  for (mp = get_first_exported_ap(&index);
+       mp;
+       mp = get_next_exported_ap(&index)) {
+    if (mp->am_mnt == mf) {
       /* return value from create_amfs_union_node is ignored by mapc_keyiter */
       (void) mapc_keyiter((mnt_map *) mp->am_mnt->mf_private,
-			  (void (*)(char *, voidp)) create_amfs_union_node,
+			  create_amfs_union_node,
 			  mp);
       break;
     }
diff --git a/contrib/amd/amd/amq_subr.c b/contrib/amd/amd/amq_subr.c
index f69c37b..79ecafc 100644
--- a/contrib/amd/amd/amq_subr.c
+++ b/contrib/amd/amd/amq_subr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amq_subr.c,v 1.5 1999/08/24 21:31:06 ezk Exp $
- * $FreeBSD: src/contrib/amd/amd/amq_subr.c,v 1.5 1999/09/15 05:45:13 obrien Exp $
- * $DragonFly: src/contrib/amd/amd/amq_subr.c,v 1.2 2003/06/17 04:23:56 dillon Exp $
+ * File: am-utils/amd/amq_subr.c
  *
  */
 /*
@@ -76,7 +73,7 @@ amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp)
   static am_node *mp;
 
   mp = find_ap(*(char **) argp);
-  return (amq_mount_tree_p *) &mp;
+  return (amq_mount_tree_p *) ((void *)&mp);
 }
 
 
@@ -102,7 +99,7 @@ amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp)
 amq_mount_stats *
 amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp)
 {
-  return (amq_mount_stats *) &amd_stats;
+  return (amq_mount_stats *) ((void *)&amd_stats);
 }
 
 
@@ -113,8 +110,10 @@ amq_mount_tree_list *
 amqproc_export_1_svc(voidp argp, struct svc_req *rqstp)
 {
   static amq_mount_tree_list aml;
+  static am_node *mp;
 
-  aml.amq_mount_tree_list_val = (amq_mount_tree_p *) &exported_ap[0];
+  mp = get_exported_ap(0);
+  aml.amq_mount_tree_list_val = (amq_mount_tree_p *) ((void *) &mp);
   aml.amq_mount_tree_list_len = 1;	/* XXX */
 
   return &aml;
@@ -132,16 +131,14 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
   switch (opt->as_opt) {
 
   case AMOPT_DEBUG:
-#ifdef DEBUG
     if (debug_option(opt->as_str))
-#endif /* DEBUG */
       rc = EINVAL;
     break;
 
   case AMOPT_LOGFILE:
     if (gopt.logfile && opt->as_str
 	&& STREQ(gopt.logfile, opt->as_str)) {
-      if (switch_to_logfile(opt->as_str, orig_umask))
+      if (switch_to_logfile(opt->as_str, orig_umask, 0))
 	rc = EINVAL;
     } else {
       rc = EACCES;
@@ -157,8 +154,8 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
     if (amd_state == Run) {
       plog(XLOG_INFO, "amq says flush cache");
       do_mapc_reload = 0;
-      flush_nfs_fhandle_cache((fserver *) 0);
-      flush_srvr_nfs_cache();
+      flush_nfs_fhandle_cache((fserver *) NULL);
+      flush_srvr_nfs_cache((fserver *) NULL);
     }
     break;
   }
@@ -170,92 +167,8 @@ amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp)
 amq_mount_info_list *
 amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp)
 {
-  return (amq_mount_info_list *) &mfhead;	/* XXX */
-}
-
-#ifdef ENABLE_AMQ_MOUNT
-/*
- * This is code that is vulnerable to IP spoofing attacks.  Unless you
- * absolutely need it, I suggest you do not enable it
- * (using configure --enable-amq-mount)
- */
-static int
-ok_security(struct svc_req *rqstp)
-{
-  struct sockaddr_in *sin = (struct sockaddr_in *) NULL;
-
-  if ((sin = amu_svc_getcaller(rqstp->rq_xprt)) == NULL) {
-    plog(XLOG_ERROR, "amu_svc_getcaller returned NULL");
-    return(0);			/* assume security is therefore not OK */
-  }
-
-  if (ntohs(sin->sin_port) >= IPPORT_RESERVED ||
-      !(sin->sin_addr.s_addr == htonl(0x7f000001) ||
-	sin->sin_addr.s_addr == myipaddr.s_addr)) {
-    char dq[20];
-    plog(XLOG_INFO, "AMQ request from %s.%d DENIED",
-	 inet_dquad(dq, sin->sin_addr.s_addr),
-	 ntohs(sin->sin_port));
-    return (0);
-  }
-
-  return (1);
-}
-
-
-int *
-amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp)
-{
-  static int rc = EINVAL;
-  char s[AMQ_STRLEN];
-  char *cp;
-  char dq[20];
-  struct sockaddr_in *sin;
-
-  if ((sin = amu_svc_getcaller(rqstp->rq_xprt)) == NULL) {
-    plog(XLOG_ERROR, "amu_svc_getcaller returned NULL");
-    return &rc;
-  }
-
-  strncpy(s, *(amq_string *) argp, AMQ_STRLEN-1);
-  s[AMQ_STRLEN-1] = '\0';	/* null terminate, to be sure */
-  plog(XLOG_ERROR,
-       "amq requested mount of %s from %s.%d",
-       s, inet_dquad(dq, sin->sin_addr.s_addr),
-       ntohs(sin->sin_port));
-
-  /*
-   * Minimalist security check.
-   */
-  if (!ok_security(rqstp)) {
-    rc = EACCES;
-    return &rc;
-  }
-  /*
-   * Find end of key
-   */
-  for (cp = (char *) s; *cp && (!isascii(*cp) || !isspace(*cp)); cp++) ;
-
-  if (!*cp) {
-    plog(XLOG_INFO, "amqproc_mount: Invalid arguments");
-    rc = EINVAL;
-    return &rc;
-  }
-  *cp++ = '\0';
-
-  /*
-   * Find start of value
-   */
-  while (*cp && isascii(*cp) && isspace(*cp))
-    cp++;
-
-  root_newmap(s, cp, (char *) 0, NULL);
-  rc = mount_auto_node(s, (voidp) root_node);
-  if (rc < 0)
-    return 0;
-  return &rc;
+  return (amq_mount_info_list *) ((void *)&mfhead);	/* XXX */
 }
-#endif /* ENABLE_AMQ_MOUNT */
 
 
 amq_string *
@@ -280,6 +193,64 @@ amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp)
 
 
 /*
+ * Process PAWD string of remote pawd tool.
+ *
+ * We repeat the resolution of the string until the resolved string resolves
+ * to itself.  This ensures that we follow path resolutions through all
+ * possible Amd mount points until we reach some sort of convergence.  To
+ * prevent possible infinite loops, we break out of this loop if the strings
+ * do not converge after MAX_PAWD_TRIES times.
+ */
+amq_string *
+amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp)
+{
+  static amq_string res;
+#define MAX_PAWD_TRIES 10
+  int index, len, maxagain = MAX_PAWD_TRIES;
+  am_node *mp;
+  char *mountpoint;
+  char *dir = *(char **) argp;
+  static char tmp_buf[MAXPATHLEN];
+  char prev_buf[MAXPATHLEN];
+
+  tmp_buf[0] = prev_buf[0] = '\0'; /* default is empty string: no match */
+  do {
+    for (mp = get_first_exported_ap(&index);
+	 mp;
+	 mp = get_next_exported_ap(&index)) {
+      if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl"))
+	continue;
+      if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto"))
+	continue;
+      mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
+      len = strlen(mountpoint);
+      if (len == 0)
+	continue;
+      if (!NSTREQ(mountpoint, dir, len))
+	continue;
+      if (dir[len] != '\0' && dir[len] != '/')
+	continue;
+      xstrlcpy(tmp_buf, mp->am_path, sizeof(tmp_buf));
+      xstrlcat(tmp_buf, &dir[len], sizeof(tmp_buf));
+      break;
+    } /* end of "for" loop */
+    /* once tmp_buf and prev_buf are equal, break out of "do" loop */
+    if (STREQ(tmp_buf, prev_buf))
+      break;
+    else
+      xstrlcpy(prev_buf, tmp_buf, sizeof(prev_buf));
+  } while (--maxagain);
+  /* check if we couldn't resolve the string after MAX_PAWD_TRIES times */
+  if (maxagain <= 0)
+    plog(XLOG_WARNING, "path \"%s\" did not resolve after %d tries",
+	 tmp_buf, MAX_PAWD_TRIES);
+
+  res = tmp_buf;
+  return &res;
+}
+
+
+/*
  * XDR routines.
  */
 
@@ -287,7 +258,7 @@ amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp)
 bool_t
 xdr_amq_setopt(XDR *xdrs, amq_setopt *objp)
 {
-  if (!xdr_enum(xdrs, (enum_t *) & objp->as_opt)) {
+  if (!xdr_enum(xdrs, (enum_t *) ((voidp) &objp->as_opt))) {
     return (FALSE);
   }
   if (!xdr_string(xdrs, &objp->as_str, AMQ_STRLEN)) {
@@ -352,10 +323,16 @@ xdr_amq_mount_subtree(XDR *xdrs, amq_mount_tree *objp)
   if (!xdr_amq_mount_tree_node(xdrs, objp)) {
     return (FALSE);
   }
-  if (!xdr_pointer(xdrs, (char **) &mp->am_osib, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
+  if (!xdr_pointer(xdrs,
+		   (char **) ((voidp) &mp->am_osib),
+		   sizeof(amq_mount_tree),
+		   (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
     return (FALSE);
   }
-  if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
+  if (!xdr_pointer(xdrs,
+		   (char **) ((voidp) &mp->am_child),
+		   sizeof(amq_mount_tree),
+		   (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
     return (FALSE);
   }
   return (TRUE);
@@ -366,15 +343,21 @@ bool_t
 xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
 {
   am_node *mp = (am_node *) objp;
-  am_node *mnil = 0;
+  am_node *mnil = NULL;
 
   if (!xdr_amq_mount_tree_node(xdrs, objp)) {
     return (FALSE);
   }
-  if (!xdr_pointer(xdrs, (char **) &mnil, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
+  if (!xdr_pointer(xdrs,
+		   (char **) ((voidp) &mnil),
+		   sizeof(amq_mount_tree),
+		   (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
     return (FALSE);
   }
-  if (!xdr_pointer(xdrs, (char **) &mp->am_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
+  if (!xdr_pointer(xdrs,
+		   (char **) ((voidp) &mp->am_child),
+		   sizeof(amq_mount_tree),
+		   (XDRPROC_T_TYPE) xdr_amq_mount_subtree)) {
     return (FALSE);
   }
   return (TRUE);
@@ -418,7 +401,7 @@ bool_t
 xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp)
 {
   if (!xdr_array(xdrs,
-		 (char **) &objp->amq_mount_tree_list_val,
+		 (char **) ((voidp) &objp->amq_mount_tree_list_val),
 		 (u_int *) &objp->amq_mount_tree_list_len,
 		 ~0,
 		 sizeof(amq_mount_tree_p),
@@ -440,7 +423,7 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
   u_int len = 0;
 
   for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
-    if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
+    if (!(mf->mf_fsflags & FS_AMQINFO))
       continue;
     len++;
   }
@@ -451,7 +434,7 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
    */
   for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
     int up;
-    if (!(mf->mf_ops->fs_flags & FS_AMQINFO))
+    if (!(mf->mf_fsflags & FS_AMQINFO))
       continue;
 
     if (!xdr_amq_string(xdrs, &mf->mf_ops->fs_type)) {
@@ -472,20 +455,12 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
     if (!xdr_int(xdrs, &mf->mf_refc)) {
       return (FALSE);
     }
-    if (mf->mf_server->fs_flags & FSF_ERROR)
+    if (FSRV_ERROR(mf->mf_server) || FSRV_ISDOWN(mf->mf_server))
       up = 0;
+    else if (FSRV_ISUP(mf->mf_server))
+      up = 1;
     else
-      switch (mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) {
-      case FSF_DOWN | FSF_VALID:
-	up = 0;
-	break;
-      case FSF_VALID:
-	up = 1;
-	break;
-      default:
-	up = -1;
-	break;
-      }
+      up = -1;
     if (!xdr_int(xdrs, &up)) {
       return (FALSE);
     }
diff --git a/contrib/amd/amd/amq_svc.c b/contrib/amd/amd/amq_svc.c
index c22f219..6fadb16 100644
--- a/contrib/amd/amd/amq_svc.c
+++ b/contrib/amd/amd/amq_svc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amq_svc.c,v 1.3 1999/08/24 21:31:06 ezk Exp $
+ * File: am-utils/amd/amq_svc.c
  *
  */
 
@@ -51,6 +50,65 @@
 /* typedefs */
 typedef char *(*amqsvcproc_t)(voidp, struct svc_req *);
 
+#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
+# ifdef NEED_LIBWRAP_SEVERITY_VARIABLES
+/*
+ * Some systems that define libwrap already define these two variables
+ * in libwrap, while others don't: so I need to know precisely iff
+ * to define these two severity variables.
+ */
+int allow_severity=0, deny_severity=0;
+# endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */
+
+/*
+ * check if remote amq is authorized to access this amd.
+ * Returns: 1=allowed, 0=denied.
+ */
+static int
+amqsvc_is_client_allowed(const struct sockaddr_in *addr, char *remote)
+{
+  struct hostent *h;
+  char *name = NULL, **ad;
+  int ret = 0;			/* default is 0==denied */
+
+  /* Check IP address */
+  if (hosts_ctl(AMD_SERVICE_NAME, "", remote, "")) {
+    ret = 1;
+    goto out;
+  }
+  /* Get address */
+  if (!(h = gethostbyaddr((const char *)&(addr->sin_addr),
+                          sizeof(addr->sin_addr),
+                          AF_INET)))
+    goto out;
+  if (!(name = strdup(h->h_name)))
+    goto out;
+  /* Paranoia check */
+  if (!(h = gethostbyname(name)))
+    goto out;
+  for (ad = h->h_addr_list; *ad; ad++)
+    if (!memcmp(*ad, &(addr->sin_addr), h->h_length))
+      break;
+  if (!*ad)
+    goto out;
+  if (hosts_ctl(AMD_SERVICE_NAME, "", h->h_name, "")) {
+    return 1;
+    goto out;
+  }
+  /* Check aliases */
+  for (ad = h->h_aliases; *ad; ad++)
+    if (hosts_ctl(AMD_SERVICE_NAME, "", *ad, "")) {
+      return 1;
+      goto out;
+    }
+
+ out:
+  if (name)
+    XFREE(name);
+  return ret;
+}
+#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
+
 
 void
 amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
@@ -59,14 +117,26 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
     amq_string amqproc_mnttree_1_arg;
     amq_string amqproc_umnt_1_arg;
     amq_setopt amqproc_setopt_1_arg;
-#ifdef ENABLE_AMQ_MOUNT
-    amq_string amqproc_mount_1_arg;
-#endif /* ENABLE_AMQ_MOUNT */
   } argument;
   char *result;
   xdrproc_t xdr_argument, xdr_result;
   amqsvcproc_t local;
 
+#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
+  if (gopt.flags & CFM_USE_TCPWRAPPERS) {
+    struct sockaddr_in *remote_addr = svc_getcaller(rqstp->rq_xprt);
+    char *remote_hostname = inet_ntoa(remote_addr->sin_addr);
+
+    if (!amqsvc_is_client_allowed(remote_addr, remote_hostname)) {
+      plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname);
+      svcerr_auth(transp, AUTH_FAILED);
+      return;
+    } else {
+      dlog("Amd allowed remote amq service to %s", remote_hostname);
+    }
+  }
+#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
+
   switch (rqstp->rq_proc) {
 
   case AMQPROC_NULL:
@@ -111,14 +181,6 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
     local = (amqsvcproc_t) amqproc_getmntfs_1_svc;
     break;
 
-#ifdef ENABLE_AMQ_MOUNT
-  case AMQPROC_MOUNT:
-    xdr_argument = (xdrproc_t) xdr_amq_string;
-    xdr_result = (xdrproc_t) xdr_int;
-    local = (amqsvcproc_t) amqproc_mount_1_svc;
-    break;
-#endif /* ENABLE_AMQ_MOUNT */
-
   case AMQPROC_GETVERS:
     xdr_argument = (xdrproc_t) xdr_void;
     xdr_result = (xdrproc_t) xdr_amq_string;
@@ -131,6 +193,12 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
     local = (amqsvcproc_t) amqproc_getpid_1_svc;
     break;
 
+  case AMQPROC_PAWD:
+    xdr_argument = (xdrproc_t) xdr_amq_string;
+    xdr_result = (xdrproc_t) xdr_amq_string;
+    local = (amqsvcproc_t) amqproc_pawd_1_svc;
+    break;
+
   default:
     svcerr_noproc(transp);
     return;
diff --git a/contrib/amd/amd/autil.c b/contrib/amd/amd/autil.c
index 006c755..a5ecd6d 100644
--- a/contrib/amd/amd/autil.c
+++ b/contrib/amd/amd/autil.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: autil.c,v 1.3 1999/01/10 21:53:44 ezk Exp $
+ * File: am-utils/amd/autil.c
  *
  */
 
@@ -52,100 +51,49 @@
 #include <am_defs.h>
 #include <amd.h>
 
-int NumChild = 0;		/* number of children of primary amd */
+int NumChildren = 0;		/* number of children of primary amd */
 static char invalid_keys[] = "\"'!;@ \t\n";
 
+/****************************************************************************
+ *** MACROS                                                               ***
+ ****************************************************************************/
+
 #ifdef HAVE_TRANSPORT_TYPE_TLI
 # define PARENT_USLEEP_TIME	100000 /* 0.1 seconds */
 #endif /* HAVE_TRANSPORT_TYPE_TLI */
 
 
+/****************************************************************************
+ *** FORWARD DEFINITIONS                                                  ***
+ ****************************************************************************/
+static void domain_strip(char *otherdom, char *localdom);
+static int dofork(void);
+
+
+/****************************************************************************
+ *** FUNCTIONS                                                             ***
+ ****************************************************************************/
+
+/*
+ * Copy s into p, reallocating p if necessary
+ */
 char *
 strealloc(char *p, char *s)
 {
-  int len = strlen(s) + 1;
+  size_t len = strlen(s) + 1;
 
   p = (char *) xrealloc((voidp) p, len);
 
-  strcpy(p, s);
+  xstrlcpy(p, s, len);
 #ifdef DEBUG_MEM
+# if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY)
   malloc_verify();
+# endif /* not defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) */
 #endif /* DEBUG_MEM */
   return p;
 }
 
 
-char **
-strsplit(char *s, int ch, int qc)
-{
-  char **ivec;
-  int ic = 0;
-  int done = 0;
-
-  ivec = (char **) xmalloc((ic + 1) * sizeof(char *));
-
-  while (!done) {
-    char *v;
-
-    /*
-     * skip to split char
-     */
-    while (*s && (ch == ' ' ? (isascii(*s) && isspace((int)*s)) : *s == ch))
-      *s++ = '\0';
-
-    /*
-     * End of string?
-     */
-    if (!*s)
-      break;
-
-    /*
-     * remember start of string
-     */
-    v = s;
-
-    /*
-     * skip to split char
-     */
-    while (*s && !(ch == ' ' ? (isascii(*s) && isspace((int)*s)) : *s == ch)) {
-      if (*s++ == qc) {
-	/*
-	 * Skip past string.
-	 */
-	s++;
-	while (*s && *s != qc)
-	  s++;
-	if (*s == qc)
-	  s++;
-      }
-    }
-
-    if (!*s)
-      done = 1;
-    *s++ = '\0';
-
-    /*
-     * save string in new ivec slot
-     */
-    ivec[ic++] = v;
-    ivec = (char **) xrealloc((voidp) ivec, (ic + 1) * sizeof(char *));
-#ifdef DEBUG
-    amuDebug(D_STR)
-      plog(XLOG_DEBUG, "strsplit saved \"%s\"", v);
-#endif /* DEBUG */
-  }
-
-#ifdef DEBUG
-  amuDebug(D_STR)
-    plog(XLOG_DEBUG, "strsplit saved a total of %d strings", ic);
-#endif /* DEBUG */
-
-  ivec[ic] = 0;
-
-  return ivec;
-}
-
-
 /*
  * Strip off the trailing part of a domain
  * to produce a short-form domain relative
@@ -170,7 +118,8 @@ domain_strip(char *otherdom, char *localdom)
 
 
 /*
- * Normalize a host name
+ * Normalize a host name: replace cnames with real names, and decide if to
+ * strip domain name or not.
  */
 void
 host_normalize(char **chp)
@@ -182,20 +131,18 @@ host_normalize(char **chp)
    */
   if (gopt.flags & CFM_NORMALIZE_HOSTNAMES) {
     struct hostent *hp;
-    clock_valid = 0;
     hp = gethostbyname(*chp);
     if (hp && hp->h_addrtype == AF_INET) {
-#ifdef DEBUG
       dlog("Hostname %s normalized to %s", *chp, hp->h_name);
-#endif /* DEBUG */
       *chp = strealloc(*chp, (char *) hp->h_name);
     }
   }
-  domain_strip(*chp, hostd);
+  if (gopt.flags & CFM_DOMAIN_STRIP) {
+    domain_strip(*chp, hostd);
+  }
 }
 
 
-
 /*
  * Keys are not allowed to contain " ' ! or ; to avoid
  * problems with macro expansions.
@@ -219,19 +166,27 @@ forcibly_timeout_mp(am_node *mp)
    */
   if (mf && ((mp->am_flags & AMF_ROOT) ||
 	     (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)))) {
-    if (!(mf->mf_flags & MFF_UNMOUNTING))
+    if (mf->mf_flags & MFF_UNMOUNTING)
+      plog(XLOG_WARNING, "node %s is currently being unmounted, ignoring timeout request", mp->am_path);
+    else
       plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path);
   } else {
     plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
     mp->am_flags &= ~AMF_NOTIMEOUT;
-    mp->am_ttl = clocktime();
+    mp->am_ttl = clocktime(NULL);
+    /*
+     * Force mtime update of parent dir, to prevent DNLC/dcache from caching
+     * the old entry, which could result in ESTALE errors, bad symlinks, and
+     * more.
+     */
+    clocktime(&mp->am_parent->am_fattr.na_mtime);
     reschedule_timeout_mp();
   }
 }
 
 
 void
-mf_mounted(mntfs *mf)
+mf_mounted(mntfs *mf, bool_t call_free_opts)
 {
   int quoted;
   int wasmounted = mf->mf_flags & MFF_MOUNTED;
@@ -248,10 +203,33 @@ mf_mounted(mntfs *mf)
     /*
      * Do mounted callback
      */
-    if (mf->mf_ops->mounted) {
-      (*mf->mf_ops->mounted) (mf);
+    if (mf->mf_ops->mounted)
+      mf->mf_ops->mounted(mf);
+
+    /*
+     * Be careful when calling free_ops and XFREE here.  Some pseudo file
+     * systems like nfsx call this function (mf_mounted), even though it
+     * would be called by the lower-level amd file system functions.  nfsx
+     * needs to call this function because of the other actions it takes.
+     * So we pass a boolean from the caller (yes, not so clean workaround)
+     * to determine if we should free or not.  If we're not freeing (often
+     * because we're called from a callback function), then just to be sure,
+     * we'll zero out the am_opts structure and set the pointer to NULL.
+     * The parent mntfs node owns this memory and is going to free it with a
+     * call to mf_mounted(mntfs,TRUE) (see comment in the am_mounted code).
+     */
+    if (call_free_opts) {
+      free_opts(mf->mf_fo);	/* this free is needed to prevent leaks */
+      XFREE(mf->mf_fo);		/* (also this one) */
+    } else {
+      memset(mf->mf_fo, 0, sizeof(am_opts));
+      mf->mf_fo = NULL;
     }
-    mf->mf_fo = 0;
+  }
+
+  if (mf->mf_flags & MFF_RESTART) {
+    mf->mf_flags &= ~MFF_RESTART;
+    dlog("Restarted filesystem %s, flags 0x%x", mf->mf_mount, mf->mf_flags);
   }
 
   /*
@@ -270,32 +248,61 @@ mf_mounted(mntfs *mf)
 void
 am_mounted(am_node *mp)
 {
+  int notimeout = 0;		/* assume normal timeouts initially */
   mntfs *mf = mp->am_mnt;
 
-  mf_mounted(mf);
+  /*
+   * This is the parent mntfs which does the mf->mf_fo (am_opts type), and
+   * we're passing TRUE here to tell mf_mounted to actually free the
+   * am_opts.  See a related comment in mf_mounted().
+   */
+  mf_mounted(mf, TRUE);
+
+#ifdef HAVE_FS_AUTOFS
+  if (mf->mf_flags & MFF_IS_AUTOFS)
+    autofs_mounted(mp);
+#endif /* HAVE_FS_AUTOFS */
 
   /*
    * Patch up path for direct mounts
    */
-  if (mp->am_parent && mp->am_parent->am_mnt->mf_ops == &amfs_direct_ops)
+  if (mp->am_parent && mp->am_parent->am_mnt->mf_fsflags & FS_DIRECT)
     mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
 
   /*
-   * Check whether this mount should be cached permanently
+   * Check whether this mount should be cached permanently or not,
+   * and handle user-requested timeouts.
    */
-  if (mf->mf_ops->fs_flags & FS_NOTIMEOUT) {
-    mp->am_flags |= AMF_NOTIMEOUT;
-  } else if (mf->mf_mount[1] == '\0' && mf->mf_mount[0] == '/') {
+  /* first check if file system was set to never timeout */
+  if (mf->mf_fsflags & FS_NOTIMEOUT)
+    notimeout = 1;
+  /* next, alter that decision by map flags */
+  if (mf->mf_mopts) {
+    mntent_t mnt;
+    mnt.mnt_opts = mf->mf_mopts;
+
+    /* umount option: user wants to unmount this entry */
+    if (amu_hasmntopt(&mnt, "unmount") || amu_hasmntopt(&mnt, "umount"))
+      notimeout = 0;
+    /* noumount option: user does NOT want to unmount this entry */
+    if (amu_hasmntopt(&mnt, "nounmount") || amu_hasmntopt(&mnt, "noumount"))
+      notimeout = 1;
+    /* utimeout=N option: user wants to unmount this option AND set timeout */
+    if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
+      mp->am_timeo = gopt.am_timeo; /* otherwise use default timeout */
+    else
+      notimeout = 0;
+    /* special case: don't try to unmount "/" (it can never succeed) */
+    if (mf->mf_mount[0] == '/' && mf->mf_mount[1] == '\0')
+      notimeout = 1;
+  }
+  /* finally set actual flags */
+  if (notimeout) {
     mp->am_flags |= AMF_NOTIMEOUT;
+    plog(XLOG_INFO, "%s set to never timeout", mp->am_path);
   } else {
-    mntent_t mnt;
-    if (mf->mf_mopts) {
-      mnt.mnt_opts = mf->mf_mopts;
-      if (hasmntopt(&mnt, "nounmount"))
-	mp->am_flags |= AMF_NOTIMEOUT;
-      if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
-	mp->am_timeo = gopt.am_timeo;
-    }
+    mp->am_flags &= ~AMF_NOTIMEOUT;
+    plog(XLOG_INFO, "%s set to timeout in %d seconds", mp->am_path, mp->am_timeo);
   }
 
   /*
@@ -303,25 +310,38 @@ am_mounted(am_node *mp)
    * compute the length of the returned string.
    */
   if (mp->am_fattr.na_type == NFLNK)
-    mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
+    mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mf->mf_mount);
 
   /*
-   * Record mount time
+   * Record mount time, and update am_stats at the same time.
    */
-  mp->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime = clocktime();
+  mp->am_stats.s_mtime = clocktime(&mp->am_fattr.na_mtime);
   new_ttl(mp);
 
   /*
-   * Update mtime of parent node
+   * Update mtime of parent node (copying "struct nfstime" in '=' below)
    */
   if (mp->am_parent && mp->am_parent->am_mnt)
-    mp->am_parent->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime;
+    mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime;
 
   /*
-   * Now, if we can, do a reply to our NFS client here
+   * This is ugly, but essentially unavoidable
+   * Sublinks must be treated separately as type==link
+   * when the base type is different.
+   */
+  if (mp->am_link && mf->mf_ops != &amfs_link_ops)
+    amfs_link_ops.mount_fs(mp, mf);
+
+  /*
+   * Now, if we can, do a reply to our client here
    * to speed things up.
    */
-  quick_reply(mp, 0);
+#ifdef HAVE_FS_AUTOFS
+  if (mp->am_flags & AMF_AUTOFS)
+    autofs_mount_succeeded(mp);
+  else
+#endif /* HAVE_FS_AUTOFS */
+    nfs_quick_reply(mp, 0);
 
   /*
    * Update stats
@@ -330,21 +350,303 @@ am_mounted(am_node *mp)
 }
 
 
+/*
+ * Replace mount point with a reference to an error filesystem.
+ * The mount point (struct mntfs) is NOT discarded,
+ * the caller must do it if it wants to _before_ calling this function.
+ */
+void
+assign_error_mntfs(am_node *mp)
+{
+  int error;
+  dlog("assign_error_mntfs");
+  /*
+   * Save the old error code
+   */
+  error = mp->am_error;
+  if (error <= 0)
+    error = mp->am_mnt->mf_error;
+  /*
+   * Allocate a new error reference
+   */
+  mp->am_mnt = new_mntfs();
+  /*
+   * Put back the error code
+   */
+  mp->am_mnt->mf_error = error;
+  mp->am_mnt->mf_flags |= MFF_ERROR;
+  /*
+   * Zero the error in the mount point
+   */
+  mp->am_error = 0;
+}
+
+
+/*
+ * Build a new map cache for this node, or re-use
+ * an existing cache for the same map.
+ */
+void
+amfs_mkcacheref(mntfs *mf)
+{
+  char *cache;
+
+  if (mf->mf_fo && mf->mf_fo->opt_cache)
+    cache = mf->mf_fo->opt_cache;
+  else
+    cache = "none";
+  mf->mf_private = (opaque_t) mapc_find(mf->mf_info,
+					cache,
+					(mf->mf_fo ? mf->mf_fo->opt_maptype : NULL));
+  mf->mf_prfree = mapc_free;
+}
+
+
+/*
+ * Locate next node in sibling list which is mounted
+ * and is not an error node.
+ */
+am_node *
+next_nonerror_node(am_node *xp)
+{
+  mntfs *mf;
+
+  /*
+   * Bug report (7/12/89) from Rein Tollevik <rein@ifi.uio.no>
+   * Fixes a race condition when mounting direct automounts.
+   * Also fixes a problem when doing a readdir on a directory
+   * containing hung automounts.
+   */
+  while (xp &&
+	 (!(mf = xp->am_mnt) ||	/* No mounted filesystem */
+	  mf->mf_error != 0 ||	/* There was a mntfs error */
+	  xp->am_error != 0 ||	/* There was a mount error */
+	  !(mf->mf_flags & MFF_MOUNTED) ||	/* The fs is not mounted */
+	  (mf->mf_server->fs_flags & FSF_DOWN))	/* The fs may be down */
+	 )
+    xp = xp->am_osib;
+
+  return xp;
+}
+
+
+/*
+ * Mount an automounter directory.
+ * The automounter is connected into the system
+ * as a user-level NFS server.  amfs_mount constructs
+ * the necessary NFS parameters to be given to the
+ * kernel so that it will talk back to us.
+ *
+ * NOTE: automounter mounts in themselves are using NFS Version 2 (UDP).
+ *
+ * NEW: on certain systems, mounting can be done using the
+ * kernel-level automount (autofs) support. In that case,
+ * we don't need NFS at all here.
+ */
 int
-mount_node(am_node *mp)
+amfs_mount(am_node *mp, mntfs *mf, char *opts)
 {
-  mntfs *mf = mp->am_mnt;
-  int error = 0;
+  char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
+  int retry, error = 0, genflags;
+  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
+  char *dir = mf->mf_mount;
+  mntent_t mnt;
+  MTYPE_TYPE type;
+  int forced_unmount = 0;	/* are we using forced unmounts? */
+
+  memset((voidp) &mnt, 0, sizeof(mnt));
+  mnt.mnt_dir = dir;
+  mnt.mnt_fsname = pid_fsname;
+  mnt.mnt_opts = opts;
+
+#ifdef HAVE_FS_AUTOFS
+  if (mf->mf_flags & MFF_IS_AUTOFS) {
+    type = MOUNT_TYPE_AUTOFS;
+    /*
+     * Make sure that amd's top-level autofs mounts are hidden by default
+     * from df.
+     * XXX: It works ok on Linux, might not work on other systems.
+     */
+    mnt.mnt_type = "autofs";
+  } else
+#endif /* HAVE_FS_AUTOFS */
+  {
+    type = MOUNT_TYPE_NFS;
+    /*
+     * Make sure that amd's top-level NFS mounts are hidden by default
+     * from df.
+     * If they don't appear to support the either the "ignore" mnttab
+     * option entry, or the "auto" one, set the mount type to "nfs".
+     */
+    mnt.mnt_type = HIDE_MOUNT_TYPE;
+  }
+
+  retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
+  if (retry <= 0)
+    retry = 2;			/* XXX: default to 2 retries */
+
+  /*
+   * SET MOUNT ARGS
+   */
+
+  /*
+   * Make a ``hostname'' string for the kernel
+   */
+  xsnprintf(fs_hostname, sizeof(fs_hostname), "pid%ld@%s:%s",
+	    get_server_pid(), am_get_hostname(), dir);
+  /*
+   * Most kernels have a name length restriction (64 bytes)...
+   */
+  if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
+    xstrlcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..",
+	     sizeof(fs_hostname) - MAXHOSTNAMELEN + 3);
+#ifdef HOSTNAMESZ
+  /*
+   * ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
+   * If you need to get the definition for HOSTNAMESZ found, you may
+   * add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
+   */
+  if (strlen(fs_hostname) >= HOSTNAMESZ)
+    xstrlcpy(fs_hostname + HOSTNAMESZ - 3, "..",
+	     sizeof(fs_hostname) - HOSTNAMESZ + 3);
+#endif /* HOSTNAMESZ */
+
+  /*
+   * Finally we can compute the mount genflags set above,
+   * and add any automounter specific flags.
+   */
+  genflags = compute_mount_flags(&mnt);
+#ifdef HAVE_FS_AUTOFS
+  if (on_autofs)
+    genflags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
+  genflags |= compute_automounter_mount_flags(&mnt);
+
+again:
+  if (!(mf->mf_flags & MFF_IS_AUTOFS)) {
+    nfs_args_t nfs_args;
+    am_nfs_fh *fhp;
+    am_nfs_handle_t anh;
+#ifndef HAVE_TRANSPORT_TYPE_TLI
+    u_short port;
+    struct sockaddr_in sin;
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+
+    /*
+     * get fhandle of remote path for automount point
+     */
+    fhp = get_root_nfs_fh(dir);
+    if (!fhp) {
+      plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
+      return EINVAL;
+    }
+
+#ifndef HAVE_TRANSPORT_TYPE_TLI
+    /*
+     * Create sockaddr to point to the local machine.
+     */
+    memset((voidp) &sin, 0, sizeof(sin));
+    /* as per POSIX, sin_len need not be set (used internally by kernel) */
+    sin.sin_family = AF_INET;
+    sin.sin_addr = myipaddr;
+    port = hasmntval(&mnt, MNTTAB_OPT_PORT);
+    if (port) {
+      sin.sin_port = htons(port);
+    } else {
+      plog(XLOG_ERROR, "no port number specified for %s", dir);
+      return EINVAL;
+    }
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+
+    /* setup the many fields and flags within nfs_args */
+    memmove(&anh.v2, fhp, sizeof(*fhp));
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+    compute_nfs_args(&nfs_args,
+		     &mnt,
+		     genflags,
+		     nfsncp,
+		     NULL,	/* remote host IP addr is set below */
+		     NFS_VERSION,	/* version 2 */
+		     "udp",
+		     &anh,
+		     fs_hostname,
+		     pid_fsname);
+    /*
+     * IMPORTANT: set the correct IP address AFTERWARDS.  It cannot
+     * be done using the normal mechanism of compute_nfs_args(), because
+     * that one will allocate a new address and use NFS_SA_DREF() to copy
+     * parts to it, while assuming that the ip_addr passed is always
+     * a "struct sockaddr_in".  That assumption is incorrect on TLI systems,
+     * because they define a special macro HOST_SELF which is DIFFERENT
+     * than localhost (127.0.0.1)!
+     */
+    nfs_args.addr = &nfsxprt->xp_ltaddr;
+#else /* not HAVE_TRANSPORT_TYPE_TLI */
+    compute_nfs_args(&nfs_args,
+		     &mnt,
+		     genflags,
+		     NULL,
+		     &sin,
+		     NFS_VERSION,	/* version 2 */
+		     "udp",
+		     &anh,
+		     fs_hostname,
+		     pid_fsname);
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+
+    /*************************************************************************
+     * NOTE: while compute_nfs_args() works ok for regular NFS mounts	     *
+     * the toplvl one is not quite regular, and so some options must be      *
+     * corrected by hand more carefully, *after* compute_nfs_args() runs.    *
+     *************************************************************************/
+    compute_automounter_nfs_args(&nfs_args, &mnt);
+
+    if (amuDebug(D_TRACE)) {
+      print_nfs_args(&nfs_args, 0);
+      plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
+    }
 
-  mf->mf_flags |= MFF_MOUNTING;
-  error = (*mf->mf_ops->mount_fs) (mp);
+    /* This is it!  Here we try to mount amd on its mount points */
+    error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args,
+		     retry, type, 0, NULL, mnttab_file_name, on_autofs);
 
-  mf = mp->am_mnt;
-  if (error >= 0)
-    mf->mf_flags &= ~MFF_MOUNTING;
-  if (!error && !(mf->mf_ops->fs_flags & FS_MBACKGROUND)) {
-    /* ...but see ifs_mount */
-    am_mounted(mp);
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+    free_knetconfig(nfs_args.knconf);
+    /*
+     * local automounter mounts do not allocate a special address, so
+     * no need to XFREE(nfs_args.addr) under TLI.
+     */
+#endif /* HAVE_TRANSPORT_TYPE_TLI */
+
+#ifdef HAVE_FS_AUTOFS
+  } else {
+    /* This is it!  Here we try to mount amd on its mount points */
+    error = mount_fs(&mnt, genflags, (caddr_t) mp->am_autofs_fh,
+		     retry, type, 0, NULL, mnttab_file_name, on_autofs);
+#endif /* HAVE_FS_AUTOFS */
+  }
+  if (error == 0 || forced_unmount)
+     return error;
+
+  /*
+   * If user wants forced/lazy unmount semantics, then try it iff the
+   * current mount failed with EIO or ESTALE.
+   */
+  if (gopt.flags & CFM_FORCED_UNMOUNTS) {
+    switch (errno) {
+    case ESTALE:
+    case EIO:
+      forced_unmount = errno;
+      plog(XLOG_WARNING, "Mount %s failed (%m); force unmount.", mp->am_path);
+      if ((error = UMOUNT_FS(mp->am_path, mnttab_file_name,
+			     AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH)) < 0) {
+	plog(XLOG_WARNING, "Forced umount %s failed: %m.", mp->am_path);
+	errno = forced_unmount;
+      } else
+	goto again;
+    default:
+      break;
+    }
   }
 
   return error;
@@ -363,15 +665,79 @@ am_unmounted(am_node *mp)
    * Do unmounted callback
    */
   if (mf->mf_ops->umounted)
-    (*mf->mf_ops->umounted) (mp);
+    mf->mf_ops->umounted(mf);
+
+  /*
+   * This is ugly, but essentially unavoidable.
+   * Sublinks must be treated separately as type==link
+   * when the base type is different.
+   */
+  if (mp->am_link && mf->mf_ops != &amfs_link_ops)
+    amfs_link_ops.umount_fs(mp, mf);
+
+#ifdef HAVE_FS_AUTOFS
+  if (mf->mf_flags & MFF_IS_AUTOFS)
+    autofs_release_fh(mp);
+  if (mp->am_flags & AMF_AUTOFS)
+    autofs_umount_succeeded(mp);
+#endif /* HAVE_FS_AUTOFS */
+
+  /*
+   * Clean up any directories that were made
+   *
+   * If we remove the mount point of a pending mount, any queued access
+   * to it will fail. So don't do it in that case.
+   * Also don't do it if the refcount is > 1.
+   */
+  if (mf->mf_flags & MFF_MKMNT &&
+      mf->mf_refc == 1 &&
+      !(mp->am_flags & AMF_REMOUNT)) {
+    plog(XLOG_INFO, "removing mountpoint directory '%s'", mf->mf_mount);
+    rmdirs(mf->mf_mount);
+    mf->mf_flags &= ~MFF_MKMNT;
+  }
+
+  /*
+   * If this is a pseudo-directory then adjust the link count
+   * in the parent
+   */
+  if (mp->am_parent && mp->am_fattr.na_type == NFDIR)
+    --mp->am_parent->am_fattr.na_nlink;
 
   /*
    * Update mtime of parent node
    */
   if (mp->am_parent && mp->am_parent->am_mnt)
-    mp->am_parent->am_fattr.na_mtime.nt_seconds = clocktime();
-
-  free_map(mp);
+    clocktime(&mp->am_parent->am_fattr.na_mtime);
+
+  if (mp->am_parent && (mp->am_flags & AMF_REMOUNT)) {
+    char *fname = strdup(mp->am_name);
+    am_node *mp_parent = mp->am_parent;
+    mntfs *mf_parent = mp_parent->am_mnt;
+    int error = 0;
+
+    free_map(mp);
+    plog(XLOG_INFO, "am_unmounted: remounting %s", fname);
+    mp = mf_parent->mf_ops->lookup_child(mp_parent, fname, &error, VLOOK_CREATE);
+    if (mp && error < 0)
+      mp = mf_parent->mf_ops->mount_child(mp, &error);
+    if (error > 0) {
+      errno = error;
+      plog(XLOG_ERROR, "am_unmounted: could not remount %s: %m", fname);
+    }
+    XFREE(fname);
+  } else
+    /*
+     * We have a race here.
+     * If this node has a pending mount and amd is going down (unmounting
+     * everything in the process), then we could potentially free it here
+     * while a struct continuation still has a reference to it. So when
+     * amfs_cont is called, it blows up.
+     * We avoid the race by refusing to free any nodes that have
+     * pending mounts (defined as having a non-NULL am_mfarray).
+     */
+    if (!mp->am_mfarray)
+      free_map(mp);
 }
 
 
@@ -396,7 +762,7 @@ top:
     am_set_mypid();
     foreground = 0;
   } else {			/* parent process, has one more child */
-    NumChild++;
+    NumChildren++;
   }
 
   return pid;
@@ -409,10 +775,9 @@ background(void)
   int pid = dofork();
 
   if (pid == 0) {
-#ifdef DEBUG
     dlog("backgrounded");
-#endif /* DEBUG */
     foreground = 0;
-  }
+  } else
+    dlog("forked process %d", pid);
   return pid;
 }
diff --git a/contrib/amd/amd/clock.c b/contrib/amd/amd/clock.c
index 72d4719..0caa7df 100644
--- a/contrib/amd/amd/clock.c
+++ b/contrib/amd/amd/clock.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: clock.c,v 1.3 1999/01/13 23:30:58 ezk Exp $
+ * File: am-utils/amd/clock.c
  *
  */
 
@@ -59,14 +58,13 @@
 #include <am_defs.h>
 #include <amd.h>
 
-int timeout(u_int secs, void (*fn) (voidp), voidp closure);
 void reschedule_timeouts(time_t now, time_t then);
 
 typedef struct callout callout;
 struct callout {
   callout *c_next;		/* List of callouts */
-  void (*c_fn) (voidp);		/* Function to call */
-  voidp c_closure;		/* Closure to pass to call */
+  callout_fun *c_fn;		/* Function to call */
+  opaque_t c_arg;		/* Argument to pass to call */
   time_t c_time;		/* Time of call */
   int c_id;			/* Unique identifier */
 };
@@ -87,7 +85,7 @@ time_t next_softclock;		/* Time of next call to softclock() */
 /*
  * Global assumption: valid id's are non-zero.
  */
-#define	CID_ALLOC(struct )	(++callout_id)
+#define	CID_ALLOC()		(++callout_id)
 #define	CID_UNDEF		(0)
 
 
@@ -121,22 +119,22 @@ free_callout(callout *cp)
 /*
  * Schedule a callout.
  *
- * (*fn)(closure) will be called at clocktime() + secs
+ * (*fn)(fn_arg) will be called at clocktime(NULL) + secs
  */
 int
-timeout(u_int secs, void (*fn) (voidp), voidp closure)
+timeout(u_int secs, callout_fun *fn, opaque_t fn_arg)
 {
   callout *cp, *cp2;
-  time_t t = clocktime() + secs;
+  time_t t = clocktime(NULL) + secs;
 
   /*
    * Allocate and fill in a new callout structure
    */
   callout *cpnew = alloc_callout();
-  cpnew->c_closure = closure;
+  cpnew->c_arg = fn_arg;
   cpnew->c_fn = fn;
   cpnew->c_time = t;
-  cpnew->c_id = CID_ALLOC(struct );
+  cpnew->c_id = CID_ALLOC();
 
   if (t < next_softclock)
     next_softclock = t;
@@ -189,10 +187,8 @@ reschedule_timeouts(time_t now, time_t then)
   for (cp = callouts.c_next; cp; cp = cp->c_next) {
     if (cp->c_time >= now && cp->c_time <= then) {
       plog(XLOG_WARNING, "job %d rescheduled to run immediately", cp->c_id);
-#ifdef DEBUG
       dlog("rescheduling job %d back %ld seconds",
 	   cp->c_id, (long) (cp->c_time - now));
-#endif /* DEBUG */
       next_softclock = cp->c_time = now;
     }
   }
@@ -212,14 +208,14 @@ softclock(void)
     if (task_notify_todo)
       do_task_notify();
 
-    now = clocktime();
+    now = clocktime(NULL);
 
     /*
      * While there are more callouts waiting...
      */
     while ((cp = callouts.c_next) && cp->c_time <= now) {
       /*
-       * Extract first from list, save fn & closure and
+       * Extract first from list, save fn & fn_arg and
        * unlink callout from list and free.
        * Finally call function.
        *
@@ -228,12 +224,12 @@ softclock(void)
        * function will call timeout()
        * and try to allocate a callout
        */
-      void (*fn) (voidp) = cp->c_fn;
-      voidp closure = cp->c_closure;
+      callout_fun *fn = cp->c_fn;
+      opaque_t fn_arg = cp->c_arg;
 
       callouts.c_next = cp->c_next;
       free_callout(cp);
-      (*fn) (closure);
+      (*fn) (fn_arg);
     }
 
   } while (task_notify_todo);
diff --git a/contrib/amd/amd/conf.c b/contrib/amd/amd/conf.c
index a45e130..2fc587b 100644
--- a/contrib/amd/amd/conf.c
+++ b/contrib/amd/amd/conf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: conf.c,v 1.5 1999/09/30 21:01:30 ezk Exp $
+ * File: am-utils/amd/conf.c
  *
  */
 
@@ -76,12 +75,18 @@ struct _func_map {
  * FORWARD DECLARATIONS:
  */
 static int gopt_arch(const char *val);
+static int gopt_auto_attrcache(const char *val);
 static int gopt_auto_dir(const char *val);
+static int gopt_autofs_use_lofs(const char *val);
 static int gopt_browsable_dirs(const char *val);
 static int gopt_cache_duration(const char *val);
 static int gopt_cluster(const char *val);
+static int gopt_debug_mtab_file(const char *val);
 static int gopt_debug_options(const char *val);
 static int gopt_dismount_interval(const char *val);
+static int gopt_domain_strip(const char *val);
+static int gopt_exec_map_timeout(const char *val);
+static int gopt_forced_unmounts(const char *val);
 static int gopt_full_os(const char *val);
 static int gopt_fully_qualified_hosts(const char *val);
 static int gopt_hesiod_base(const char *val);
@@ -90,18 +95,34 @@ static int gopt_ldap_base(const char *val);
 static int gopt_ldap_cache_maxmem(const char *val);
 static int gopt_ldap_cache_seconds(const char *val);
 static int gopt_ldap_hostports(const char *val);
+static int gopt_ldap_proto_version(const char *val);
 static int gopt_local_domain(const char *val);
+static int gopt_localhost_address(const char *val);
 static int gopt_log_file(const char *val);
 static int gopt_log_options(const char *val);
+static int gopt_map_defaults(const char *val);
 static int gopt_map_options(const char *val);
+static int gopt_map_reload_interval(const char *val);
 static int gopt_map_type(const char *val);
 static int gopt_mount_type(const char *val);
 static int gopt_pid_file(const char *val);
 static int gopt_portmap_program(const char *val);
+static int gopt_preferred_amq_port(const char *val);
+static int gopt_nfs_allow_any_interface(const char *val);
+static int gopt_nfs_allow_insecure_port(const char *val);
+static int gopt_nfs_proto(const char *val);
 static int gopt_nfs_retransmit_counter(const char *val);
+static int gopt_nfs_retransmit_counter_udp(const char *val);
+static int gopt_nfs_retransmit_counter_tcp(const char *val);
+static int gopt_nfs_retransmit_counter_toplvl(const char *val);
 static int gopt_nfs_retry_interval(const char *val);
+static int gopt_nfs_retry_interval_udp(const char *val);
+static int gopt_nfs_retry_interval_tcp(const char *val);
+static int gopt_nfs_retry_interval_toplvl(const char *val);
+static int gopt_nfs_vers(const char *val);
 static int gopt_nis_domain(const char *val);
 static int gopt_normalize_hostnames(const char *val);
+static int gopt_normalize_slashes(const char *val);
 static int gopt_os(const char *val);
 static int gopt_osver(const char *val);
 static int gopt_plock(const char *val);
@@ -109,35 +130,45 @@ static int gopt_print_pid(const char *val);
 static int gopt_print_version(const char *val);
 static int gopt_restart_mounts(const char *val);
 static int gopt_search_path(const char *val);
-static int gopt_selectors_on_default(const char *val);
+static int gopt_selectors_in_defaults(const char *val);
 static int gopt_show_statfs_entries(const char *val);
+static int gopt_truncate_log(const char *val);
 static int gopt_unmount_on_exit(const char *val);
+static int gopt_use_tcpwrappers(const char *val);
 static int gopt_vendor(const char *val);
 static int process_global_option(const char *key, const char *val);
-static int process_regular_map(cf_map_t *cfm);
+static int process_one_regular_map(const cf_map_t *cfm);
 static int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm);
 static int ropt_browsable_dirs(const char *val, cf_map_t *cfm);
 static int ropt_map_name(const char *val, cf_map_t *cfm);
+static int ropt_map_defaults(const char *val, cf_map_t *cfm);
 static int ropt_map_options(const char *val, cf_map_t *cfm);
 static int ropt_map_type(const char *val, cf_map_t *cfm);
 static int ropt_mount_type(const char *val, cf_map_t *cfm);
 static int ropt_search_path(const char *val, cf_map_t *cfm);
 static int ropt_tag(const char *val, cf_map_t *cfm);
-static void reset_cf_map(cf_map_t *cfm);
+static void init_cf_map(cf_map_t *cfm);
 
 
 /*
  * STATIC VARIABLES:
  */
-static cf_map_t cur_map;
+static cf_map_t *head_map, *cur_map;
+
 static struct _func_map glob_functable[] = {
   {"arch",			gopt_arch},
+  {"auto_attrcache",		gopt_auto_attrcache},
   {"auto_dir",			gopt_auto_dir},
+  {"autofs_use_lofs",		gopt_autofs_use_lofs},
   {"browsable_dirs",		gopt_browsable_dirs},
   {"cache_duration",		gopt_cache_duration},
   {"cluster",			gopt_cluster},
+  {"debug_mtab_file",           gopt_debug_mtab_file},
   {"debug_options",		gopt_debug_options},
   {"dismount_interval",		gopt_dismount_interval},
+  {"domain_strip",		gopt_domain_strip},
+  {"exec_map_timeout",		gopt_exec_map_timeout},
+  {"forced_unmounts",		gopt_forced_unmounts},
   {"fully_qualified_hosts",	gopt_fully_qualified_hosts},
   {"full_os",			gopt_full_os},
   {"hesiod_base",		gopt_hesiod_base},
@@ -146,18 +177,34 @@ static struct _func_map glob_functable[] = {
   {"ldap_cache_maxmem",		gopt_ldap_cache_maxmem},
   {"ldap_cache_seconds",	gopt_ldap_cache_seconds},
   {"ldap_hostports",		gopt_ldap_hostports},
+  {"ldap_proto_version",	gopt_ldap_proto_version},
   {"local_domain",		gopt_local_domain},
+  {"localhost_address",		gopt_localhost_address},
   {"log_file",			gopt_log_file},
   {"log_options",		gopt_log_options},
+  {"map_defaults",		gopt_map_defaults},
   {"map_options",		gopt_map_options},
+  {"map_reload_interval",	gopt_map_reload_interval},
   {"map_type",			gopt_map_type},
   {"mount_type",		gopt_mount_type},
   {"pid_file",			gopt_pid_file},
   {"portmap_program",		gopt_portmap_program},
+  {"preferred_amq_port",	gopt_preferred_amq_port},
+  {"nfs_allow_any_interface",	gopt_nfs_allow_any_interface},
+  {"nfs_allow_insecure_port",	gopt_nfs_allow_insecure_port},
+  {"nfs_proto",			gopt_nfs_proto},
   {"nfs_retransmit_counter",	gopt_nfs_retransmit_counter},
+  {"nfs_retransmit_counter_udp",	gopt_nfs_retransmit_counter_udp},
+  {"nfs_retransmit_counter_tcp",	gopt_nfs_retransmit_counter_tcp},
+  {"nfs_retransmit_counter_toplvl",	gopt_nfs_retransmit_counter_toplvl},
   {"nfs_retry_interval",	gopt_nfs_retry_interval},
+  {"nfs_retry_interval_udp",	gopt_nfs_retry_interval_udp},
+  {"nfs_retry_interval_tcp",	gopt_nfs_retry_interval_tcp},
+  {"nfs_retry_interval_toplvl",	gopt_nfs_retry_interval_toplvl},
+  {"nfs_vers",			gopt_nfs_vers},
   {"nis_domain",		gopt_nis_domain},
   {"normalize_hostnames",	gopt_normalize_hostnames},
+  {"normalize_slashes",		gopt_normalize_slashes},
   {"os",			gopt_os},
   {"osver",			gopt_osver},
   {"plock",			gopt_plock},
@@ -165,63 +212,46 @@ static struct _func_map glob_functable[] = {
   {"print_version",		gopt_print_version},
   {"restart_mounts",		gopt_restart_mounts},
   {"search_path",		gopt_search_path},
-  {"selectors_on_default",	gopt_selectors_on_default},
+  {"selectors_on_default",	gopt_selectors_in_defaults},
+  {"selectors_in_defaults",	gopt_selectors_in_defaults},
   {"show_statfs_entries",	gopt_show_statfs_entries},
+  {"truncate_log",		gopt_truncate_log},
   {"unmount_on_exit",		gopt_unmount_on_exit},
+  {"use_tcpwrappers",		gopt_use_tcpwrappers},
   {"vendor",			gopt_vendor},
   {NULL, NULL}
 };
 
 
 /*
- * Reset a map.
+ * Initialize a map from [global] defaults.
  */
 static void
-reset_cf_map(cf_map_t *cfm)
+init_cf_map(cf_map_t *cfm)
 {
   if (!cfm)
     return;
 
-  if (cfm->cfm_dir) {
-    XFREE(cfm->cfm_dir);
-    cfm->cfm_dir = NULL;
-  }
-
-  if (cfm->cfm_name) {
-    XFREE(cfm->cfm_name);
-    cfm->cfm_name = NULL;
-  }
-
-  if (cfm->cfm_tag) {
-    XFREE(cfm->cfm_tag);
-    cfm->cfm_tag = NULL;
-  }
-
   /*
-   * reset/initialize a regular map's flags and other variables from the
+   * Initialize a regular map's flags and other variables from the
    * global ones, so that they are applied to all maps.  Of course, each map
    * can then override the flags individually.
    *
    * NOTES:
    * (1): Will only work for maps that appear after [global].
-   * (2): Also be careful not to free() a global option.
-   * (3): I'm doing direct char* pointer comparison, and not strcmp().  This
-   *      is correct!
+   * (2): I'm assigning pointers directly from the global map.
    */
 
   /* initialize map_type from [global] */
-  if (cfm->cfm_type && cfm->cfm_type != gopt.map_type)
-    XFREE(cfm->cfm_type);
   cfm->cfm_type = gopt.map_type;
 
+  /* initialize map_defaults from [global] */
+  cfm->cfm_defaults = gopt.map_defaults;
+
   /* initialize map_opts from [global] */
-  if (cfm->cfm_opts && cfm->cfm_opts != gopt.map_options)
-    XFREE(cfm->cfm_opts);
   cfm->cfm_opts = gopt.map_options;
 
   /* initialize search_path from [global] */
-  if (cfm->cfm_search_path && cfm->cfm_search_path != gopt.search_path)
-    XFREE(cfm->cfm_search_path);
   cfm->cfm_search_path = gopt.search_path;
 
   /*
@@ -230,12 +260,12 @@ reset_cf_map(cf_map_t *cfm)
   cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS |
 				 CFM_BROWSABLE_DIRS_FULL |
 				 CFM_MOUNT_TYPE_AUTOFS |
-				 CFM_ENABLE_DEFAULT_SELECTORS);
+				 CFM_SELECTORS_IN_DEFAULTS);
 }
 
 
 /*
- * Process configuration file options.
+ * Process configuration file options (called from YACC parser).
  * Return 0 if OK, 1 otherwise.
  */
 int
@@ -244,50 +274,67 @@ set_conf_kv(const char *section, const char *key, const char *val)
   int ret;
 
 #ifdef DEBUG_CONF
-  fprintf(stderr,"set_conf_kv: section=%s, key=%s, val=%s\n",
+  fprintf(stderr, "set_conf_kv: section=%s, key=%s, val=%s\n",
 	  section, key, val);
 #endif /* DEBUG_CONF */
 
   /*
-   * If global section, process them one at a time.
+   * If global section, process kv pairs one at a time.
    */
   if (STREQ(section, "global")) {
     /*
      * Check if a regular map was configured before "global",
-     * and process it as needed.
+     * and warn about it.
      */
-    if (cur_map.cfm_dir) {
-      fprintf(stderr,"processing regular map \"%s\" before global one.\n",
-	      section);
-      ret = process_regular_map(&cur_map); /* will reset map */
-      if (ret != 0)
-	return ret;
+    if (cur_map && cur_map->cfm_dir) {
+      static short printed_this_error;
+      if (!printed_this_error) {
+	fprintf(stderr, "found regular map \"%s\" before global one.\n",
+		cur_map->cfm_dir);
+	printed_this_error = 1;
+      }
     }
 
     /* process the global option first */
     ret = process_global_option(key, val);
 
-    /* reset default options for regular maps from just updated globals */
-    if (ret == 0)
-      reset_cf_map(&cur_map);
-
     /* return status from the processing of the global option */
     return ret;
   }
 
   /*
-   * otherwise save options and process a single map all at once.
+   * Otherwise we found a non-global option: store it after some testing.
    */
 
-  /* check if we found a new map, so process one already collected */
-  if (cur_map.cfm_dir && !STREQ(cur_map.cfm_dir, section)) {
-    ret = process_regular_map(&cur_map); /* will reset map */
-    if (ret != 0)
-      return ret;
+  /* initialize (static) global list head and current map pointer */
+  if (!head_map && !cur_map) {
+    cur_map = CALLOC(cf_map_t);
+    if (!cur_map) {
+      perror("calloc");
+      exit(1);
+    }
+    /* initialize first head map from global defaults */
+    init_cf_map(cur_map);
+    head_map = cur_map;
+  }
+
+  /* check if we found a new map, then allocate and initialize it */
+  if (cur_map->cfm_dir && !STREQ(cur_map->cfm_dir, section)) {
+    /* allocate new map struct */
+    cf_map_t *tmp_map = CALLOC(cf_map_t);
+    if (!tmp_map) {
+      perror("calloc");
+      exit(1);
+    }
+    /* initialize it from global defaults */
+    init_cf_map(tmp_map);
+    /* append it to end of linked list */
+    cur_map->cfm_next = tmp_map;
+    cur_map = tmp_map;
   }
 
   /* now process a single entry of a regular map */
-  return process_regular_option(section, key, val, &cur_map);
+  return process_regular_option(section, key, val, cur_map);
 }
 
 
@@ -325,6 +372,18 @@ gopt_arch(const char *val)
 
 
 static int
+gopt_auto_attrcache(const char *val)
+{
+  gopt.auto_attrcache = atoi(val);
+  if (gopt.auto_attrcache < 0) {
+    fprintf(stderr, "conf: bad attrcache value: \"%s\"\n", val);
+    return 1;
+  }
+  return 0;
+}
+
+
+static int
 gopt_auto_dir(const char *val)
 {
   gopt.auto_dir = strdup((char *)val);
@@ -333,6 +392,22 @@ gopt_auto_dir(const char *val)
 
 
 static int
+gopt_autofs_use_lofs(const char *val)
+{
+  if (STREQ(val, "yes")) {
+    gopt.flags |= CFM_AUTOFS_USE_LOFS;
+    return 0;
+  } else if (STREQ(val, "no")) {
+    gopt.flags &= ~CFM_AUTOFS_USE_LOFS;
+    return 0;
+  }
+
+  fprintf(stderr, "conf: unknown value to autofs_use_lofs \"%s\"\n", val);
+  return 1;			/* unknown value */
+}
+
+
+static int
 gopt_browsable_dirs(const char *val)
 {
   if (STREQ(val, "full")) {
@@ -370,10 +445,18 @@ gopt_cluster(const char *val)
 
 
 static int
+gopt_debug_mtab_file(const char *val)
+{
+  gopt.debug_mtab_file = strdup((char*)val);
+  return 0;
+}
+
+
+static int
 gopt_debug_options(const char *val)
 {
 #ifdef DEBUG
-  usage += debug_option(strdup((char *)val));
+  usage += debug_option((char *)val);
   return 0;
 #else /* not DEBUG */
   fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
@@ -394,6 +477,74 @@ gopt_dismount_interval(const char *val)
 
 
 static int
+gopt_domain_strip(const char *val)
+{
+  if (STREQ(val, "yes")) {
+    gopt.flags |= CFM_DOMAIN_STRIP;
+    return 0;
+  } else if (STREQ(val, "no")) {
+    gopt.flags &= ~CFM_DOMAIN_STRIP;
+    return 0;
+  }
+
+  fprintf(stderr, "conf: unknown value to domain_strip \"%s\"\n", val);
+  return 1;                     /* unknown value */
+}
+
+
+static int
+gopt_exec_map_timeout(const char *val)
+{
+  gopt.exec_map_timeout = atoi(val);
+  if (gopt.exec_map_timeout <= 0)
+    gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT; /* default exec map timeout */
+  return 0;
+}
+
+
+static int
+gopt_forced_unmounts(const char *val)
+{
+  if (STREQ(val, "yes")) {
+#if !defined(MNT2_GEN_OPT_DETACH) && !defined(MNT2_GEN_OPT_FORCE)
+    fprintf(stderr, "conf: forced_unmounts unsupported on this system.\n");
+    return 1;
+#else /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
+# ifdef __linux__
+    /*
+     * HACK ALERT: Linux has had MNT_FORCE since 2.2, but it hasn't gotten
+     * stable until 2.4.  And it had MNT_DETACH since 2.4, but it hasn't
+     * gotten stable since 2.6.  So alert users if they're trying to use a
+     * feature that may not work well on their older kernel.
+     */
+    {
+      struct utsname un;
+      if (uname(&un) >= 0) {
+#  ifdef MNT2_GEN_OPT_FORCE
+	if (strcmp(un.release, "2.4.0") < 0)
+	  fprintf(stderr, "warning: forced-unmounts (MNT_FORCE) may not work well before 2.4.0\n");
+#  endif /* MNT2_GEN_OPT_FORCE */
+#  ifdef MNT2_GEN_OPT_DETACH
+	if (strcmp(un.release, "2.6.0") < 0)
+	  fprintf(stderr, "warning: lazy-unmounts (MNT_DETACH) may not work well before 2.6.0\n");
+#  endif /* MNT2_GEN_OPT_DETACH */
+      }
+    }
+# endif /* __linux__ */
+    gopt.flags |= CFM_FORCED_UNMOUNTS;
+    return 0;
+#endif /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
+  } else if (STREQ(val, "no")) {
+    gopt.flags &= ~CFM_FORCED_UNMOUNTS;
+    return 0;
+  }
+
+  fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
+  return 1;			/* unknown value */
+}
+
+
+static int
 gopt_full_os(const char *val)
 {
   gopt.op_sys_full = strdup((char *)val);
@@ -455,6 +606,14 @@ gopt_local_domain(const char *val)
 
 
 static int
+gopt_localhost_address(const char *val)
+{
+  gopt.localhost_address = strdup((char *)val);
+  return 0;
+}
+
+
+static int
 gopt_ldap_base(const char *val)
 {
 #ifdef HAVE_MAP_LDAP
@@ -480,7 +639,7 @@ gopt_ldap_cache_seconds(const char *val)
   }
   return 0;
 #else /* not HAVE_MAP_LDAP */
-  fprintf(stderr, "conf: ldap_cache option ignored.  No LDAP support available.\n");
+  fprintf(stderr, "conf: ldap_cache_seconds option ignored.  No LDAP support available.\n");
   return 1;
 #endif /* not HAVE_MAP_LDAP */
 }
@@ -499,7 +658,7 @@ gopt_ldap_cache_maxmem(const char *val)
   }
   return 0;
 #else /* not HAVE_MAP_LDAP */
-  fprintf(stderr, "conf: ldap_cache option ignored.  No LDAP support available.\n");
+  fprintf(stderr, "conf: ldap_cache_maxmem option ignored.  No LDAP support available.\n");
   return 1;
 #endif /* not HAVE_MAP_LDAP */
 }
@@ -520,6 +679,44 @@ gopt_ldap_hostports(const char *val)
 
 
 static int
+gopt_ldap_proto_version(const char *val)
+{
+#ifdef HAVE_MAP_LDAP
+  char *end;
+
+  gopt.ldap_proto_version = strtol((char *)val, &end, 10);
+  if (end == val) {
+    fprintf(stderr, "conf: bad ldap_proto_version option: %s\n",val);
+    return 1;
+  }
+
+  if (gopt.ldap_proto_version < 0 || gopt.ldap_proto_version > LDAP_VERSION_MAX) {
+    fprintf(stderr, "conf: bad ldap_proto_version option value: %s\n",val);
+    return 1;
+  }
+  switch (gopt.ldap_proto_version) {
+    /* XXX: what about LDAP_VERSION1? */
+  case LDAP_VERSION2:
+#ifdef LDAP_VERSION3
+  case LDAP_VERSION3:
+#endif /* LDAP_VERSION3 */
+#ifdef LDAP_VERSION4
+  case LDAP_VERSION4:
+#endif /* LDAP_VERSION4 */
+    break;
+  default:
+    fprintf(stderr, "conf: unsupported ldap_proto_version option value: %s\n",val);
+    return 1;
+  }
+  return 0;
+#else /* not HAVE_MAP_LDAP */
+  fprintf(stderr, "conf: ldap_proto_version option ignored.  No LDAP support available.\n");
+  return 1;
+#endif /* not HAVE_MAP_LDAP */
+}
+
+
+static int
 gopt_log_file(const char *val)
 {
   gopt.logfile = strdup((char *)val);
@@ -530,7 +727,15 @@ gopt_log_file(const char *val)
 static int
 gopt_log_options(const char *val)
 {
-  usage += switch_option(strdup((char *)val));
+  usage += switch_option((char *)val);
+  return 0;
+}
+
+
+static int
+gopt_map_defaults(const char *val)
+{
+  gopt.map_defaults = strdup((char *)val);
   return 0;
 }
 
@@ -544,6 +749,16 @@ gopt_map_options(const char *val)
 
 
 static int
+gopt_map_reload_interval(const char *val)
+{
+  gopt.map_reload_interval = atoi(val);
+  if (gopt.map_reload_interval <= 0)
+    gopt.map_reload_interval = ONE_HOUR;
+  return 0;
+}
+
+
+static int
 gopt_map_type(const char *val)
 {
   /* check if map type exist */
@@ -581,7 +796,7 @@ gopt_mount_type(const char *val)
 static int
 gopt_portmap_program(const char *val)
 {
-  gopt.portmap_program = atoi(val);
+  gopt.portmap_program = atol(val);
   /*
    * allow alternate program numbers to be no more than 10 offset from
    * official amd program number (300019).
@@ -590,7 +805,7 @@ gopt_portmap_program(const char *val)
       gopt.portmap_program > AMQ_PROGRAM + 10) {
     gopt.portmap_program = AMQ_PROGRAM;
     set_amd_program_number(gopt.portmap_program);
-    fprintf(stderr, "conf: illegal amd program numver \"%s\"\n", val);
+    fprintf(stderr, "conf: illegal amd program number \"%s\"\n", val);
     return 1;
   }
 
@@ -600,9 +815,93 @@ gopt_portmap_program(const char *val)
 
 
 static int
+gopt_preferred_amq_port(const char *val)
+{
+  gopt.preferred_amq_port = atoi(val);
+
+  /*
+   * No need to check value: preferred_amq_port is an unsigned short and 0
+   * is a valid number, meaning "any port".
+   */
+  return 0;			/* all is OK */
+}
+
+
+static int
+gopt_nfs_allow_any_interface(const char *val)
+{
+  if (STREQ(val, "yes")) {
+    gopt.flags |= CFM_NFS_ANY_INTERFACE;
+    return 0;
+  } else if (STREQ(val, "no")) {
+    gopt.flags &= ~CFM_NFS_ANY_INTERFACE;
+    return 0;
+  }
+
+  fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val);
+  return 1;			/* unknown value */
+}
+
+
+static int
+gopt_nfs_allow_insecure_port(const char *val)
+{
+  if (STREQ(val, "yes")) {
+    gopt.flags |= CFM_NFS_INSECURE_PORT;
+    return 0;
+  } else if (STREQ(val, "no")) {
+    gopt.flags &= ~CFM_NFS_INSECURE_PORT;
+    return 0;
+  }
+
+  fprintf(stderr, "conf: unknown value to nfs_allow_insecure_port \"%s\"\n", val);
+  return 1;			/* unknown value */
+}
+
+
+static int
+gopt_nfs_proto(const char *val)
+{
+  if (STREQ(val, "udp") || STREQ(val, "tcp")) {
+    gopt.nfs_proto = strdup((char *)val);
+    return 0;
+  }
+  fprintf(stderr, "conf: illegal nfs_proto \"%s\"\n", val);
+  return 1;
+}
+
+
+static int
 gopt_nfs_retransmit_counter(const char *val)
 {
-  gopt.amfs_auto_retrans = atoi(val);
+  int i;
+
+  for (i=0; i<AMU_TYPE_MAX; ++i)
+    gopt.amfs_auto_retrans[i] = atoi(val);
+  return 0;
+}
+
+
+static int
+gopt_nfs_retransmit_counter_udp(const char *val)
+{
+  gopt.amfs_auto_retrans[AMU_TYPE_UDP] = atoi(val);
+  return 0;
+}
+
+
+static int
+gopt_nfs_retransmit_counter_tcp(const char *val)
+{
+  gopt.amfs_auto_retrans[AMU_TYPE_TCP] = atoi(val);
+  return 0;
+}
+
+
+static int
+gopt_nfs_retransmit_counter_toplvl(const char *val)
+{
+  gopt.amfs_auto_retrans[AMU_TYPE_TOPLVL] = atoi(val);
   return 0;
 }
 
@@ -610,12 +909,53 @@ gopt_nfs_retransmit_counter(const char *val)
 static int
 gopt_nfs_retry_interval(const char *val)
 {
-  gopt.amfs_auto_timeo = atoi(val);
+  int i;
+
+  for (i=0; i<AMU_TYPE_MAX; ++i)
+    gopt.amfs_auto_timeo[i] = atoi(val);
+  return 0;
+}
+
+
+static int
+gopt_nfs_retry_interval_udp(const char *val)
+{
+  gopt.amfs_auto_timeo[AMU_TYPE_UDP] = atoi(val);
+  return 0;
+}
+
+
+static int
+gopt_nfs_retry_interval_tcp(const char *val)
+{
+  gopt.amfs_auto_timeo[AMU_TYPE_TCP] = atoi(val);
+  return 0;
+}
+
+
+static int
+gopt_nfs_retry_interval_toplvl(const char *val)
+{
+  gopt.amfs_auto_timeo[AMU_TYPE_TOPLVL] = atoi(val);
   return 0;
 }
 
 
 static int
+gopt_nfs_vers(const char *val)
+{
+  int i = atoi(val);
+
+  if (i == 2 || i == 3) {
+    gopt.nfs_vers = i;
+    return 0;
+  }
+  fprintf(stderr, "conf: illegal nfs_vers \"%s\"\n", val);
+  return 1;
+}
+
+
+static int
 gopt_nis_domain(const char *val)
 {
 #ifdef HAVE_MAP_NIS
@@ -645,6 +985,22 @@ gopt_normalize_hostnames(const char *val)
 
 
 static int
+gopt_normalize_slashes(const char *val)
+{
+  if (STREQ(val, "yes")) {
+    gopt.flags |= CFM_NORMALIZE_SLASHES;
+    return 0;
+  } else if (STREQ(val, "no")) {
+    gopt.flags &= ~CFM_NORMALIZE_SLASHES;
+    return 0;
+  }
+
+  fprintf(stderr, "conf: unknown value to normalize_slashes \"%s\"\n", val);
+  return 1;			/* unknown value */
+}
+
+
+static int
 gopt_os(const char *val)
 {
   gopt.op_sys = strdup((char *)val);
@@ -696,7 +1052,9 @@ static int
 gopt_print_version(const char *val)
 {
   if (STREQ(val, "yes")) {
-    fputs(get_version_string(), stderr);
+    char *vers = get_version_string();
+    fputs(vers, stderr);
+    XFREE(vers);
     return 0;
   } else if (STREQ(val, "no")) {
     return 0;
@@ -732,13 +1090,13 @@ gopt_search_path(const char *val)
 
 
 static int
-gopt_selectors_on_default(const char *val)
+gopt_selectors_in_defaults(const char *val)
 {
   if (STREQ(val, "yes")) {
-    gopt.flags |= CFM_ENABLE_DEFAULT_SELECTORS;
+    gopt.flags |= CFM_SELECTORS_IN_DEFAULTS;
     return 0;
   } else if (STREQ(val, "no")) {
-    gopt.flags &= ~CFM_ENABLE_DEFAULT_SELECTORS;
+    gopt.flags &= ~CFM_SELECTORS_IN_DEFAULTS;
     return 0;
   }
 
@@ -764,6 +1122,22 @@ gopt_show_statfs_entries(const char *val)
 
 
 static int
+gopt_truncate_log(const char *val)
+{
+  if (STREQ(val, "yes")) {
+    gopt.flags |= CFM_TRUNCATE_LOG;
+    return 0;
+  } else if (STREQ(val, "no")) {
+    gopt.flags &= ~CFM_TRUNCATE_LOG;
+    return 0;
+  }
+
+  fprintf(stderr, "conf: unknown value to truncate_log \"%s\"\n", val);
+  return 1;			/* unknown value */
+}
+
+
+static int
 gopt_unmount_on_exit(const char *val)
 {
   if (STREQ(val, "yes")) {
@@ -780,6 +1154,27 @@ gopt_unmount_on_exit(const char *val)
 
 
 static int
+gopt_use_tcpwrappers(const char *val)
+{
+#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
+  if (STREQ(val, "yes")) {
+    gopt.flags |= CFM_USE_TCPWRAPPERS;
+    return 0;
+  } else if (STREQ(val, "no")) {
+    gopt.flags &= ~CFM_USE_TCPWRAPPERS;
+    return 0;
+  }
+#else /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
+    fprintf(stderr, "conf: no tcpd/libwrap support available\n");
+    return 1;
+#endif /* not defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
+
+  fprintf(stderr, "conf: unknown value to use_tcpwrappers \"%s\"\n", val);
+  return 1;			/* unknown value */
+}
+
+
+static int
 gopt_vendor(const char *val)
 {
   gopt.op_sys_vendor = strdup((char *)val);
@@ -813,6 +1208,9 @@ process_regular_option(const char *section, const char *key, const char *val, cf
   if (STREQ(key, "map_name"))
     return ropt_map_name(val, cfm);
 
+  if (STREQ(key, "map_defaults"))
+    return ropt_map_defaults(val, cfm);
+
   if (STREQ(key, "map_options"))
     return ropt_map_options(val, cfm);
 
@@ -862,6 +1260,14 @@ ropt_map_name(const char *val, cf_map_t *cfm)
 
 
 static int
+ropt_map_defaults(const char *val, cf_map_t *cfm)
+{
+  cfm->cfm_defaults = strdup((char *)val);
+  return 0;
+}
+
+
+static int
 ropt_map_options(const char *val, cf_map_t *cfm)
 {
   cfm->cfm_opts = strdup((char *)val);
@@ -924,9 +1330,8 @@ ropt_tag(const char *val, cf_map_t *cfm)
  * Process one collected map.
  */
 static int
-process_regular_map(cf_map_t *cfm)
+process_one_regular_map(const cf_map_t *cfm)
 {
-
   if (!cfm->cfm_name) {
     fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir);
     return 1;
@@ -950,22 +1355,52 @@ process_regular_map(cf_map_t *cfm)
     fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir);
   }
 
-  reset_cf_map(cfm);
   return 0;
 }
 
 
 /*
- * Process last map in conf file (if any)
+ * Process all regular maps in conf file (if any)
  */
 int
-process_last_regular_map(void)
+process_all_regular_maps(void)
 {
+  cf_map_t *tmp_map = head_map;
+
   /*
    * If the amd.conf file only has a [global] section (pretty useless
-   * IMHO), do not try to process a map that does not exist.
+   * IMHO), there's nothing to process
    */
-  if (!cur_map.cfm_dir)
+  if (!tmp_map)
     return 0;
-  return process_regular_map(&cur_map);
+
+  while (tmp_map) {
+    if (process_one_regular_map(tmp_map) != 0)
+      return 1;
+    tmp_map = tmp_map->cfm_next;
+  }
+  return 0;
+}
+
+
+/*
+ * Find a cf_map_t for a given map name.
+ * Return NULL if not found.
+ */
+cf_map_t *
+find_cf_map(const char *name)
+{
+
+  cf_map_t *tmp_map = head_map;
+
+  if (!tmp_map || !name)
+    return NULL;
+
+  while (tmp_map) {
+    if (STREQ(tmp_map->cfm_dir,name)) {
+      return tmp_map;
+    }
+    tmp_map = tmp_map->cfm_next;
+  }
+  return NULL;
 }
diff --git a/contrib/amd/amd/conf_parse.y b/contrib/amd/amd/conf_parse.y
index d02c565..b397b05 100644
--- a/contrib/amd/amd/conf_parse.y
+++ b/contrib/amd/amd/conf_parse.y
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	%W% (Berkeley) %G%
  *
- * $Id: conf_parse.y,v 1.3 1999/04/16 14:20:59 ezk Exp $
+ * File: am-utils/amd/conf_parse.y
  *
  */
 
@@ -49,22 +48,6 @@
 #include <am_defs.h>
 #include <amd.h>
 
-/* AIX requires this to be the first thing in the file. */
-#ifndef __GNUC__
-# if HAVE_ALLOCA_H
-#  include <alloca.h>
-# else /* not HAVE_ALLOCA_H */
-#  ifdef _AIX
-#pragma alloca
-#  else /* not _AIX */
-#   ifndef alloca
-  /* predefined by HP cc +Olibcalls */
-voidp alloca();
-#   endif /* not alloca */
-#  endif /* not _AIX */
-# endif /* not HAVE_ALLOCA_H */
-#endif /* not __GNUC__ */
-
 extern char *yytext;
 extern int ayylineno;
 extern int yylex(void);
@@ -80,10 +63,10 @@ static char *header_section = NULL; /* start with no header section */
 #if PARSE_DEBUG
 # define dprintf(f,s) fprintf(stderr, (f), ayylineno, (s))
 # define amu_return(v)
-#else
+#else /* not PARSE_DEBUG */
 # define dprintf(f,s)
 # define amu_return(v) return((v))
-#endif /* PARSE_DEBUG */
+#endif /* not PARSE_DEBUG */
 
 %}
 
diff --git a/contrib/amd/amd/conf_tok.l b/contrib/amd/amd/conf_tok.l
index a157f5f..b572e4d 100644
--- a/contrib/amd/amd/conf_tok.l
+++ b/contrib/amd/amd/conf_tok.l
@@ -1,6 +1,6 @@
 %{
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -37,9 +37,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	%W% (Berkeley) %G%
  *
- * $Id: conf_tok.l,v 1.2 1999/01/10 21:53:45 ezk Exp $
+ * File: am-utils/amd/conf_tok.l
  *
  */
 
@@ -77,9 +76,10 @@
 # ifndef ECHO
 #  define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
 # endif /* not ECHO */
-int ayylineno = 0;
 #endif /* FLEX_SCANNER */
 
+int ayylineno = 0;
+
 int yylex(void);
 /*
  * some systems such as DU-4.x have a different GNU flex in /usr/bin
@@ -95,17 +95,23 @@ int yywrap(void);
 #if TOK_DEBUG
 # define dprintf(f,s) fprintf(stderr, (f), ayylineno, (s))
 # define amu_return(v)
-#else
+#else /* not TOK_DEBUG */
 # define dprintf(f,s)
 # define amu_return(v) return((v))
-#endif /* TOK_DEBUG */
+#endif /* not TOK_DEBUG */
 
-/* no need to use yyunput() or yywrap() */
-#define YY_NO_UNPUT
+/* no need to use yywrap() */
 #define YY_SKIP_YYWRAP
 
 %}
 
+/* This option causes Solaris lex to fail.  Use flex.  See BUGS file */
+/* no need to use yyunput() */
+%option nounput
+
+/* allocate more output slots so lex scanners don't run out of mem */
+%o 1024
+
 DIGIT		[0-9]
 ALPHA		[A-Za-z]
 ALPHANUM	[A-Za-z0-9]
diff --git a/contrib/amd/amd/get_args.c b/contrib/amd/amd/get_args.c
index d63e87c..dda7618 100644
--- a/contrib/amd/amd/get_args.c
+++ b/contrib/amd/amd/get_args.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: get_args.c,v 1.4 1999/09/30 21:01:31 ezk Exp $
- * $FreeBSD: src/contrib/amd/amd/get_args.c,v 1.5 1999/11/05 11:58:05 obrien Exp $
- * $DragonFly: src/contrib/amd/amd/get_args.c,v 1.2 2003/06/17 04:23:56 dillon Exp $
+ * File: am-utils/amd/get_args.c
  *
  */
 
@@ -57,17 +54,12 @@
 /* include auto-generated version file */
 #include <build_version.h>
 
-char *conf_file = "/etc/amd.conf"; /* default amd configuration file */
+char *amu_conf_file = "/etc/amd.conf"; /* default amd configuration file */
 char *conf_tag = NULL;		/* default conf file tags to use */
 int usage = 0;
 int use_conf_file = 0;		/* default don't use amd.conf file */
 char *mnttab_file_name = NULL;	/* symbol must be available always */
-#if 0
-#ifdef DEBUG
-int debug_flags = D_AMQ		/* Register AMQ */
-		| D_DAEMON;	/* Enter daemon mode */
-#endif /* DEBUG */
-#endif
+
 
 /*
  * Return the version string (dynamic buffer)
@@ -75,48 +67,61 @@ int debug_flags = D_AMQ		/* Register AMQ */
 char *
 get_version_string(void)
 {
-  static char *vers = NULL;
+  char *vers = NULL;
   char tmpbuf[1024];
   char *wire_buf;
   int wire_buf_len = 0;
+  size_t len;		  /* max allocated length (to avoid buf overflow) */
 
-  /* first get dynamic string listing all known networks */
+  /*
+   * First get dynamic string listing all known networks.
+   * This could be a long list, if host has lots of interfaces.
+   */
   wire_buf = print_wires();
   if (wire_buf)
     wire_buf_len = strlen(wire_buf);
 
-  vers = xmalloc(2048 + wire_buf_len);
-  sprintf(vers, "%s\n%s\n%s\n%s\n",
-	  "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.");
-  sprintf(tmpbuf, "%s version %s (build %d).\n",
-	  PACKAGE, VERSION, AMU_BUILD_VERSION);
-  strcat(vers, tmpbuf);
-  sprintf(tmpbuf, "Built by %s@%s on date %s.\n",
-	  USER_NAME, HOST_NAME, CONFIG_DATE);
-  strcat(vers, tmpbuf);
-  sprintf(tmpbuf, "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
-	  cpu, endian, gopt.arch, gopt.karch);
-  strcat(vers, tmpbuf);
-  sprintf(tmpbuf, "full_os=%s, os=%s, osver=%s, vendor=%s.\n",
-	  gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor);
-  strcat(vers, tmpbuf);
-
-  strcat(vers, "Map support for: ");
-  mapc_showtypes(tmpbuf);
-  strcat(vers, tmpbuf);
-  strcat(vers, ".\nAMFS: ");
-  ops_showamfstypes(tmpbuf);
-  strcat(vers, tmpbuf);
-  strcat(vers, ".\nFS: ");
-  ops_showfstypes(tmpbuf);
-  strcat(vers, tmpbuf);
+  len = 2048 + wire_buf_len;
+  vers = xmalloc(len);
+  xsnprintf(vers, len, "%s\n%s\n%s\n%s\n",
+	    "Copyright (c) 1997-2006 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.");
+  xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n",
+	    PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION);
+  strlcat(vers, tmpbuf, len);
+  xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT);
+  strlcat(vers, tmpbuf, len);
+  xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
+	    USER_NAME, HOST_NAME, CONFIG_DATE);
+  strlcat(vers, tmpbuf, len);
+  xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s.\n",
+	    BUILD_USER, BUILD_HOST);
+  strlcat(vers, tmpbuf, len);
+  xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n",
+	    cpu, endian, gopt.arch, gopt.karch);
+  strlcat(vers, tmpbuf, len);
+  xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n",
+	    gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME);
+  strlcat(vers, tmpbuf, len);
+  xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n",
+	    hostdomain, am_get_hostname(), hostd);
+  strlcat(vers, tmpbuf, len);
+
+  strlcat(vers, "Map support for: ", len);
+  mapc_showtypes(tmpbuf, sizeof(tmpbuf));
+  strlcat(vers, tmpbuf, len);
+  strlcat(vers, ".\nAMFS: ", len);
+  ops_showamfstypes(tmpbuf, sizeof(tmpbuf));
+  strlcat(vers, tmpbuf, len);
+  strlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
+  ops_showfstypes(tmpbuf, sizeof(tmpbuf));
+  strlcat(vers, tmpbuf, len);
 
   /* append list of networks if available */
   if (wire_buf) {
-    strcat(vers, wire_buf);
+    strlcat(vers, wire_buf, len);
     XFREE(wire_buf);
   }
 
@@ -124,17 +129,60 @@ get_version_string(void)
 }
 
 
+static void
+show_usage(void)
+{
+  fprintf(stderr,
+	  "Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
+\t[-k kernel_arch] [-l logfile%s\n\
+\t[-t timeout.retrans] [-w wait_timeout] [-A arch] [-C cluster_name]\n\
+\t[-o op_sys_ver] [-O op_sys_name]\n\
+\t[-F conf_file] [-T conf_tag]", am_get_progname(),
+#ifdef HAVE_SYSLOG
+# ifdef LOG_DAEMON
+	  "|\"syslog[:facility]\"]"
+# else /* not LOG_DAEMON */
+	  "|\"syslog\"]"
+# endif /* not LOG_DAEMON */
+#else /* not HAVE_SYSLOG */
+	  "]"
+#endif /* not HAVE_SYSLOG */
+	  );
+
+#ifdef HAVE_MAP_NIS
+  fputs(" [-y nis-domain]\n", stderr);
+#else /* not HAVE_MAP_NIS */
+  fputc('\n', stderr);
+#endif /* HAVE_MAP_NIS */
+
+  show_opts('x', xlog_opt);
+#ifdef DEBUG
+  show_opts('D', dbg_opt);
+#endif /* DEBUG */
+  fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
+}
+
+
 void
 get_args(int argc, char *argv[])
 {
-  int opt_ch;
+  int opt_ch, i;
   FILE *fp = stdin;
+  char getopt_arguments[] = "+nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:HA:";
+  char *getopt_args;
+  int print_version = 0;	/* 1 means we should print version info */
+
+#ifdef HAVE_GNU_GETOPT
+  getopt_args = getopt_arguments;
+#else /* ! HAVE_GNU_GETOPT */
+  getopt_args = &getopt_arguments[1];
+#endif /* HAVE_GNU_GETOPT */
 
   /* if no arguments were passed, try to use /etc/amd.conf file */
   if (argc <= 1)
     use_conf_file = 1;
 
-  while ((opt_ch = getopt(argc, argv, "nprvSa:c:d:k:l:o:t:w:x:y:C:D:F:T:O:H")) != -1)
+  while ((opt_ch = getopt(argc, argv, getopt_args)) != -1)
     switch (opt_ch) {
 
     case 'a':
@@ -181,24 +229,30 @@ get_args(int argc, char *argv[])
       break;
 
     case 't':
-      /* timeo.retrans */
+      /* timeo.retrans (also affects toplvl mounts) */
       {
 	char *dot = strchr(optarg, '.');
+	int i;
 	if (dot)
 	  *dot = '\0';
 	if (*optarg) {
-	  gopt.amfs_auto_timeo = atoi(optarg);
+	  for (i=0; i<AMU_TYPE_MAX; ++i)
+	    gopt.amfs_auto_timeo[i] = atoi(optarg);
 	}
 	if (dot) {
-	  gopt.amfs_auto_retrans = atoi(dot + 1);
+	  for (i=0; i<AMU_TYPE_MAX; ++i)
+	    gopt.amfs_auto_retrans[i] = atoi(dot + 1);
 	  *dot = '.';
 	}
       }
       break;
 
     case 'v':
-      fputs(get_version_string(), stderr);
-      exit(0);
+      /*
+       * defer to print version info after every variable had been
+       * initialized.
+       */
+      print_version++;
       break;
 
     case 'w':
@@ -219,6 +273,10 @@ get_args(int argc, char *argv[])
 #endif /* not HAVE_MAP_NIS */
       break;
 
+    case 'A':
+      gopt.arch = optarg;
+      break;
+
     case 'C':
       gopt.cluster = optarg;
       break;
@@ -233,12 +291,13 @@ get_args(int argc, char *argv[])
       break;
 
     case 'F':
-      conf_file = optarg;
+      amu_conf_file = optarg;
       use_conf_file = 1;
       break;
 
     case 'H':
-      goto show_usage;
+      show_usage();
+      exit(1);
       break;
 
     case 'O':
@@ -263,18 +322,19 @@ get_args(int argc, char *argv[])
    * specified, then use that amd.conf file.  If the file cannot be opened,
    * abort amd.  If it can be found, open it, parse it, and then close it.
    */
-  if (use_conf_file && conf_file) {
-    fp = fopen(conf_file, "r");
+  if (use_conf_file && amu_conf_file) {
+    fp = fopen(amu_conf_file, "r");
     if (!fp) {
       char buf[128];
-      sprintf(buf, "Amd configuration file (%s)", conf_file);
+      xsnprintf(buf, sizeof(buf), "Amd configuration file (%s)",
+		amu_conf_file);
       perror(buf);
       exit(1);
     }
     yyin = fp;
     yyparse();
     fclose(fp);
-    if (process_last_regular_map() != 0)
+    if (process_all_regular_maps() != 0)
       exit(1);
   }
 
@@ -287,8 +347,8 @@ get_args(int argc, char *argv[])
 #endif /* DEBUG */
 
   /* log information regarding amd.conf file */
-  if (use_conf_file && conf_file)
-    plog(XLOG_INFO, "using configuration file %s", conf_file);
+  if (use_conf_file && amu_conf_file)
+    plog(XLOG_INFO, "using configuration file %s", amu_conf_file);
 
 #ifdef HAVE_MAP_LDAP
   /* ensure that if ldap_base is specified, that also ldap_hostports is */
@@ -298,8 +358,10 @@ get_args(int argc, char *argv[])
   }
 #endif /* HAVE_MAP_LDAP */
 
-  if (usage)
-    goto show_usage;
+  if (usage) {
+    show_usage();
+    exit(1);
+  }
 
   while (optind <= argc - 2) {
     char *dir = argv[optind++];
@@ -321,73 +383,55 @@ get_args(int argc, char *argv[])
       hostdomain = gopt.sub_domain;
     if (*hostdomain == '.')
       hostdomain++;
-    strcat(hostd, ".");
-    strcat(hostd, hostdomain);
+    xstrlcat(hostd, ".", sizeof(hostd));
+    xstrlcat(hostd, hostdomain, sizeof(hostd));
 
 #ifdef MOUNT_TABLE_ON_FILE
-# ifdef DEBUG
-    if (debug_flags & D_MTAB)
-      mnttab_file_name = DEBUG_MNTTAB;
+    if (amuDebug(D_MTAB))
+      if (gopt.debug_mtab_file)
+        mnttab_file_name = gopt.debug_mtab_file; /* user supplied debug mtab path */
+      else
+	mnttab_file_name = DEBUG_MNTTAB_FILE; /* default debug mtab path */
     else
-# endif /* DEBUG */
       mnttab_file_name = MNTTAB_FILE_NAME;
 #else /* not MOUNT_TABLE_ON_FILE */
-# ifdef DEBUG
-    if (debug_flags & D_MTAB)
+    if (amuDebug(D_MTAB))
       dlog("-D mtab option ignored");
-# endif /* DEBUG */
+# ifdef MNTTAB_FILE_NAME
+    mnttab_file_name = MNTTAB_FILE_NAME;
+# endif /* MNTTAB_FILE_NAME */
 #endif /* not MOUNT_TABLE_ON_FILE */
 
-    if (switch_to_logfile(gopt.logfile, orig_umask) != 0)
-      plog(XLOG_USER, "Cannot switch logfile");
-
     /*
      * If the kernel architecture was not specified
      * then use the machine architecture.
      */
-    if (gopt.karch == 0)
+    if (gopt.karch == NULL)
       gopt.karch = gopt.arch;
 
-    if (gopt.cluster == 0)
+    if (gopt.cluster == NULL)
       gopt.cluster = hostdomain;
 
-    if (gopt.amfs_auto_timeo <= 0)
-      gopt.amfs_auto_timeo = AMFS_AUTO_TIMEO;
-    if (gopt.amfs_auto_retrans <= 0)
-      gopt.amfs_auto_retrans = AMFS_AUTO_RETRANS;
-    if (gopt.amfs_auto_retrans <= 0)
-      gopt.amfs_auto_retrans = 3;	/* XXX */
-    return;
+    /* sanity checking, normalize values just in case (toplvl too) */
+    for (i=0; i<AMU_TYPE_MAX; ++i) {
+      if (gopt.amfs_auto_timeo[i] == 0)
+	gopt.amfs_auto_timeo[i] = AMFS_AUTO_TIMEO;
+      if (gopt.amfs_auto_retrans[i] == 0)
+	gopt.amfs_auto_retrans[i] = AMFS_AUTO_RETRANS(i);
+      if (gopt.amfs_auto_retrans[i] == 0)
+	gopt.amfs_auto_retrans[i] = 3;	/* under very unusual circumstances, could be zero */
+    }
   }
 
-show_usage:
-  fprintf(stderr,
-	  "Usage: %s [-nprvHS] [-a mount_point] [-c cache_time] [-d domain]\n\
-\t[-k kernel_arch] [-l logfile%s\n\
-\t[-t timeout.retrans] [-w wait_timeout] [-C cluster_name]\n\
-\t[-o op_sys_ver] [-O op_sys_name]\n\
-\t[-F conf_file] [-T conf_tag]", am_get_progname(),
-#ifdef HAVE_SYSLOG
-# ifdef LOG_DAEMON
-	  "|\"syslog[:facility]\"]"
-# else /* not LOG_DAEMON */
-	  "|\"syslog\"]"
-# endif /* not LOG_DAEMON */
-#else /* not HAVE_SYSLOG */
-	  "]"
-#endif /* not HAVE_SYSLOG */
-	  );
+  /* finally print version string and exit, if asked for */
+  if (print_version) {
+    fputs(get_version_string(), stderr);
+    exit(0);
+  }
 
-#ifdef HAVE_MAP_NIS
-  fputs(" [-y nis-domain]\n", stderr);
-#else /* not HAVE_MAP_NIS */
-  fputc('\n', stderr);
-#endif /* HAVE_MAP_NIS */
+  if (switch_to_logfile(gopt.logfile, orig_umask,
+			(gopt.flags & CFM_TRUNCATE_LOG)) != 0)
+    plog(XLOG_USER, "Cannot switch logfile");
 
-  show_opts('x', xlog_opt);
-#ifdef DEBUG
-  show_opts('D', dbg_opt);
-#endif /* DEBUG */
-  fprintf(stderr, "\t[directory mapname [-map_options]] ...\n");
-  exit(1);
+  return;
 }
diff --git a/contrib/amd/amd/info_exec.c b/contrib/amd/amd/info_exec.c
new file mode 100644
index 0000000..8ccab9a
--- /dev/null
+++ b/contrib/amd/amd/info_exec.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 1997-2006 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.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * 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.
+ *
+ *
+ * File: am-utils/amd/info_exec.c
+ *
+ */
+
+/*
+ * Get info from executable map
+ *
+ * Original from Erik Kline, 2004.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amd.h>
+
+#define	MAX_LINE_LEN		1500
+
+/* forward declarations */
+int exec_init(mnt_map *m, char *map, time_t *tp);
+int exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
+
+
+/*
+ * a timed fgets()
+ */
+static char *
+fgets_timed(char *s, int size, int rdfd, int secs)
+{
+  fd_set fds;
+  struct timeval timeo;
+  time_t start, now;
+  int rval=0, i=0;
+
+  if (!s || size < 0 || rdfd < 0)
+    return 0;
+
+  s[0] = 0;
+  if (size == 0)
+    return s;
+
+  start = clocktime(NULL);
+  while (s[i] != '\n'  &&  i < size-1) {
+    s[i+1] = 0; /* places the requisite trailing '\0' */
+
+    /* ready for reading */
+    rval = read(rdfd, (void *)(s+i), 1);
+    if (rval == 1) {
+      if (s[i] == 0) {
+        rval = 0;
+        break;
+      }
+      i++;
+      continue;
+    } else if (rval == 0) {
+      break;
+    } else if (rval < 0  &&  errno != EAGAIN  &&  errno != EINTR) {
+      plog(XLOG_WARNING, "fgets_timed read error: %m");
+      break;
+    }
+
+    timeo.tv_usec = 0;
+    now = clocktime(NULL) - start;
+    if (secs <= 0)
+      timeo.tv_sec = 0;
+    else if (now < secs)
+      timeo.tv_sec = secs - now;
+    else {
+      /* timed out (now>=secs) */
+      plog(XLOG_WARNING, "executable map read timed out (> %d secs)", secs);
+      rval = -1;
+      break;
+    }
+
+    FD_ZERO(&fds);
+    FD_SET(rdfd, &fds);
+
+    rval = select(rdfd+1, &fds, 0, 0, &timeo);
+    if (rval < 0) {
+      /* error selecting */
+      plog(XLOG_WARNING, "fgets_timed select error: %m");
+      if (errno == EINTR)
+        continue;
+      rval = -1;
+      break;
+    } else if (rval == 0) {
+      /* timed out */
+      plog(XLOG_WARNING, "executable map read timed out (> %d secs)", secs);
+      rval = -1;
+      break;
+    }
+  }
+
+  if (rval > 0)
+    return s;
+
+  close(rdfd);
+  return (rval == 0 ? s : 0);
+}
+
+
+static int
+read_line(char *buf, int size, int fd)
+{
+  int done = 0;
+
+  while (fgets_timed(buf, size, fd, gopt.exec_map_timeout)) {
+    int len = strlen(buf);
+    done += len;
+    if (len > 1  &&  buf[len - 2] == '\\' &&
+        buf[len - 1] == '\n') {
+      buf += len - 2;
+      size -= len - 2;
+      *buf = '\n';
+      buf[1] = '\0';
+    } else {
+      return done;
+    }
+  }
+
+  return done;
+}
+
+
+/*
+ * Try to locate a value in a query answer
+ */
+static int
+exec_parse_qanswer(int fd, char *map, char *key, char **pval, time_t *tp)
+{
+  char qanswer[MAX_LINE_LEN], *dc = 0;
+  int chuck = 0;
+  int line_no = 0;
+
+  while (read_line(qanswer, sizeof(qanswer), fd)) {
+    char *cp;
+    char *hash;
+    int len = strlen(qanswer);
+    line_no++;
+
+    /*
+     * Make sure we got the whole line
+     */
+    if (qanswer[len - 1] != '\n') {
+      plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map);
+      chuck = 1;
+    } else {
+      qanswer[len - 1] = '\0';
+    }
+
+    /*
+     * Strip comments
+     */
+    hash = strchr(qanswer, '#');
+    if (hash)
+      *hash = '\0';
+
+    /*
+     * Find beginning of value (query answer)
+     */
+    for (cp = qanswer; *cp && !isascii((int)*cp) && !isspace((int)*cp); cp++)
+      ;;
+
+    /* Ignore blank lines */
+    if (!*cp)
+      goto again;
+
+    /*
+     * Return a copy of the data
+     */
+    dc = strdup(cp);
+    *pval = dc;
+    dlog("%s returns %s", key, dc);
+
+    close(fd);
+    return 0;
+
+  again:
+    /*
+     * If the last read didn't get a whole line then
+     * throw away the remainder before continuing...
+     */
+    if (chuck) {
+      while (fgets_timed(qanswer, sizeof(qanswer), fd, gopt.exec_map_timeout) &&
+	     !strchr(qanswer, '\n')) ;
+      chuck = 0;
+    }
+  }
+
+  return ENOENT;
+}
+
+
+static int
+set_nonblock(int fd)
+{
+  int val;
+
+  if (fd < 0)
+     return 0;
+
+  if ((val = fcntl(fd, F_GETFL, 0)) < 0) {
+    plog(XLOG_WARNING, "set_nonblock fcntl F_GETFL error: %m");
+    return 0;
+  }
+
+  val |= O_NONBLOCK;
+  if (fcntl(fd, F_SETFL, val) < 0) {
+    plog(XLOG_WARNING, "set_nonblock fcntl F_SETFL error: %m");
+    return 0;
+  }
+
+  return 1;
+}
+
+
+static int
+exec_map_open(char *emap, char *key)
+{
+  pid_t p1, p2;
+  int pdes[2], nullfd, i;
+  char *argv[3];
+
+  if (!emap)
+    return 0;
+
+  argv[0] = emap;
+  argv[1] = key;
+  argv[2] = NULL;
+
+  if ((nullfd = open("/dev/null", O_WRONLY|O_NOCTTY)) < 0)
+    return -1;
+
+  if (pipe(pdes) < 0) {
+    close(nullfd);
+    return -1;
+  }
+
+  switch ((p1 = vfork())) {
+  case -1:
+    /* parent: fork error */
+    close(nullfd);
+    close(pdes[0]);
+    close(pdes[1]);
+    return -1;
+  case 0:
+    /* child #1 */
+    p2 = vfork();
+    switch (p2) {
+    case -1:
+      /* child #1: fork error */
+      exit(errno);
+    case 0:
+      /* child #2: init will reap our status */
+      if (pdes[1] != STDOUT_FILENO) {
+	dup2(pdes[1], STDOUT_FILENO);
+	close(pdes[1]);
+      }
+
+      if (nullfd != STDERR_FILENO) {
+	dup2(nullfd, STDERR_FILENO);
+	close(nullfd);
+      }
+
+      for (i=0; i<FD_SETSIZE; i++)
+	if (i != STDOUT_FILENO  &&  i != STDERR_FILENO)
+	  close(i);
+
+      /* make the write descriptor non-blocking */
+      if (!set_nonblock(STDOUT_FILENO)) {
+	close(STDOUT_FILENO);
+	exit(-1);
+      }
+
+      execve(emap, argv, NULL);
+      exit(errno);		/* in case execve failed */
+    }
+
+    /* child #1 */
+    exit(0);
+  }
+
+  /* parent */
+  close(nullfd);
+  close(pdes[1]);
+
+  /* anti-zombie insurance */
+  while (waitpid(p1,0,0) < 0)
+    if (errno != EINTR)
+      exit(errno);
+
+  /* make the read descriptor non-blocking */
+  if (!set_nonblock(pdes[0])) {
+    close(pdes[0]);
+    return -1;
+  }
+
+  return pdes[0];
+}
+
+
+/*
+ * Check for various permissions on executable map without trying to
+ * fork a new executable-map process.
+ *
+ * return: >0 (errno) if failed
+ *          0 if ok
+ */
+static int
+exec_check_perm(char *map)
+{
+  struct stat sb;
+
+  /* sanity and permission checks */
+  if (!map) {
+    dlog("exec_check_permission got a NULL map");
+    return EINVAL;
+  }
+  if (stat(map, &sb)) {
+    plog(XLOG_ERROR, "map \"%s\" stat failure: %m", map);
+    return errno;
+  }
+  if (!S_ISREG(sb.st_mode)) {
+    plog(XLOG_ERROR, "map \"%s\" should be regular file", map);
+    return EINVAL;
+  }
+  if (sb.st_uid != 0) {
+    plog(XLOG_ERROR, "map \"%s\" owned by uid %u (must be 0)", map, (u_int) sb.st_uid);
+    return EACCES;
+  }
+  if (!(sb.st_mode & S_IXUSR)) {
+    plog(XLOG_ERROR, "map \"%s\" should be executable", map);
+    return EACCES;
+  }
+  if (sb.st_mode & (S_ISUID|S_ISGID)) {
+    plog(XLOG_ERROR, "map \"%s\" should not be setuid/setgid", map);
+    return EACCES;
+  }
+  if (sb.st_mode & S_IWOTH) {
+    plog(XLOG_ERROR, "map \"%s\" should not be world writeable", map);
+    return EACCES;
+  }
+
+  return 0;			/* all is well */
+}
+
+
+int
+exec_init(mnt_map *m, char *map, time_t *tp)
+{
+  /*
+   * Basically just test that the executable map can be found
+   * and has proper permissions.
+   */
+  return exec_check_perm(map);
+}
+
+
+int
+exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
+{
+  int mapfd, ret;
+
+  if ((ret = exec_check_perm(map)) != 0) {
+    return ret;
+  }
+
+  if (!key)
+    return 0;
+
+  if (logfp)
+    fflush(logfp);
+  dlog("exec_search \"%s\", key: \"%s\"", map, key);
+  mapfd = exec_map_open(map, key);
+
+  if (mapfd >= 0) {
+    if (tp)
+      *tp = clocktime(NULL);
+
+    return exec_parse_qanswer(mapfd, map, key, pval, tp);
+  }
+
+  return errno;
+}
diff --git a/contrib/amd/amd/info_file.c b/contrib/amd/amd/info_file.c
index e235752..3777a2a 100644
--- a/contrib/amd/amd/info_file.c
+++ b/contrib/amd/amd/info_file.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: info_file.c,v 1.2 1999/01/10 21:53:45 ezk Exp $
+ * File: am-utils/amd/info_file.c
  *
  */
 
@@ -55,14 +54,13 @@
 #define	MAX_LINE_LEN	1500
 
 /* forward declarations */
-int file_init(mnt_map *m, char *map, time_t *tp);
+int file_init_or_mtime(mnt_map *m, char *map, time_t *tp);
 int file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *));
 int file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
-int file_mtime(mnt_map *m, char *map, time_t *tp);
 
 
 static int
-read_line(char *buf, int size, FILE * fp)
+read_line(char *buf, int size, FILE *fp)
 {
   int done = 0;
 
@@ -87,7 +85,7 @@ read_line(char *buf, int size, FILE * fp)
 	return done;
       }
     }
-  } while (size > 0 && !feof(fp));
+  } while (size > 0 && !feof(fp) && !ferror(fp));
 
   return done;
 }
@@ -97,7 +95,12 @@ read_line(char *buf, int size, FILE * fp)
  * Try to locate a key in a file
  */
 static int
-search_or_reload_file(FILE * fp, char *map, char *key, char **val, mnt_map *m, void (*fn) (mnt_map *m, char *, char *))
+file_search_or_reload(FILE *fp,
+		      char *map,
+		      char *key,
+		      char **val,
+		      mnt_map *m,
+		      void (*fn) (mnt_map *m, char *, char *))
 {
   char key_val[MAX_LINE_LEN];
   int chuck = 0;
@@ -161,9 +164,7 @@ search_or_reload_file(FILE * fp, char *map, char *key, char **val, mnt_map *m, v
 	  (*fn) (m, strdup(kp), dc);
 	} else {
 	  *val = dc;
-#ifdef DEBUG
 	  dlog("%s returns %s", key, dc);
-#endif /* DEBUG */
 	}
 	if (!fn)
 	  return 0;
@@ -196,7 +197,7 @@ file_open(char *map, time_t *tp)
   if (mapf && tp) {
     struct stat stb;
     if (fstat(fileno(mapf), &stb) < 0)
-      *tp = clocktime();
+      *tp = clocktime(NULL);
     else
       *tp = stb.st_mtime;
   }
@@ -205,7 +206,7 @@ file_open(char *map, time_t *tp)
 
 
 int
-file_init(mnt_map *m, char *map, time_t *tp)
+file_init_or_mtime(mnt_map *m, char *map, time_t *tp)
 {
   FILE *mapf = file_open(map, tp);
 
@@ -223,7 +224,7 @@ file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
   FILE *mapf = file_open(map, (time_t *) 0);
 
   if (mapf) {
-    int error = search_or_reload_file(mapf, map, 0, 0, m, fn);
+    int error = file_search_or_reload(mapf, map, 0, 0, m, fn);
     (void) fclose(mapf);
     return error;
   }
@@ -243,23 +244,10 @@ file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
       *tp = t;
       error = -1;
     } else {
-      error = search_or_reload_file(mapf, map, key, pval, 0, 0);
+      error = file_search_or_reload(mapf, map, key, pval, 0, 0);
     }
     (void) fclose(mapf);
     return error;
   }
   return errno;
 }
-
-
-int
-file_mtime(mnt_map *m, char *map, time_t *tp)
-{
-  FILE *mapf = file_open(map, tp);
-
-  if (mapf) {
-    (void) fclose(mapf);
-    return 0;
-  }
-  return errno;
-}
diff --git a/contrib/amd/amd/info_hesiod.c b/contrib/amd/amd/info_hesiod.c
index 62007d6..e345c99 100644
--- a/contrib/amd/amd/info_hesiod.c
+++ b/contrib/amd/amd/info_hesiod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: info_hesiod.c,v 1.5 1999/02/04 07:24:15 ezk Exp $
+ * File: am-utils/amd/info_hesiod.c
  *
  */
 
@@ -75,13 +74,11 @@ int hesiod_isup(mnt_map *m, char *map);
 int
 amu_hesiod_init(mnt_map *m, char *map, time_t *tp)
 {
-#ifdef DEBUG
   dlog("amu_hesiod_init(%s)", map);
-#endif /* DEBUG */
   *tp = 0;
 
 #ifdef HAVE_HESIOD_INIT
-  if(!hesiod_context && hesiod_init(&hesiod_context) != 0)
+  if (!hesiod_context && hesiod_init(&hesiod_context) != 0)
     return ENOENT;
 #endif /* HAVE_HESIOD_INIT */
 
@@ -102,22 +99,21 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
   int error;
 #endif /* not HAVE_HESIOD_INIT */
 
-#ifdef DEBUG
   dlog("hesiod_search(m=%lx, map=%s, key=%s, pval=%lx tp=%lx)",
        (unsigned long) m, map, key, (unsigned long) pval, (unsigned long) tp);
-#endif /* DEBUG */
 
-  sprintf(hes_key, "%s.%s", key, map + HES_PREFLEN);
+  if (key[0] == '.')
+    return ENOENT;
+
+  xsnprintf(hes_key, sizeof(hes_key), "%s.%s", key, map + HES_PREFLEN);
 
   /*
    * Call the resolver
    */
-#ifdef DEBUG
   dlog("Hesiod base is: %s\n", gopt.hesiod_base);
   dlog("hesiod_search: hes_resolve(%s, %s)", hes_key, gopt.hesiod_base);
-  if (debug_flags & D_INFO)
+  if (amuDebug(D_INFO))
     _res.options |= RES_DEBUG;
-#endif /* DEBUG */
 
 #ifdef HAVE_HESIOD_INIT
   /* new style hesiod */
@@ -144,9 +140,7 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
   /*
    * Otherwise reflect the hesiod error into a Un*x error
    */
-# ifdef DEBUG
   dlog("hesiod_search: Error: %d", hes_error());
-# endif /* DEBUG */
   switch (hes_error()) {
   case HES_ER_NOTFOUND:
     error = ENOENT;
@@ -161,9 +155,7 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
     error = EINVAL;
     break;
   }
-# ifdef DEBUG
   dlog("hesiod_search: Returning: %d", error);
-# endif /* DEBUG */
   return error;
 #endif /* not HAVE_HESIOD_INIT */
 }
@@ -183,9 +175,7 @@ hesiod_isup(mnt_map *m, char *map)
   static int last_status = 1;	/* assume up by default */
 
   error = hesiod_search(m, map, "/defaults", &val, &mtime);
-#ifdef DEBUG
   dlog("hesiod_isup(%s): %s", map, strerror(error));
-#endif /* DEBUG */
   if (error != 0 && error != ENOENT) {
     plog(XLOG_ERROR,
 	 "hesiod_isup: error getting `/defaults' entry in map %s: %m", map);
diff --git a/contrib/amd/amd/info_ldap.c b/contrib/amd/amd/info_ldap.c
index a2bd9ba..36ce1c8 100644
--- a/contrib/amd/amd/info_ldap.c
+++ b/contrib/amd/amd/info_ldap.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: info_ldap.c,v 1.6 1999/09/30 21:01:31 ezk Exp $
+ * File: am-utils/amd/info_ldap.c
  *
  */
 
@@ -48,6 +47,20 @@
  * LDAP Home Page: http://www.umich.edu/~rsug/ldap/
  */
 
+/*
+ * WARNING: as of Linux Fedora Core 5 (which comes with openldap-2.3.9), the
+ * ldap.h headers deprecate several functions used in this file, such as
+ * ldap_unbind.  You get compile errors about missing extern definitions.
+ * Those externs are still in <ldap.h>, but surrounded by an ifdef
+ * LDAP_DEPRECATED.  I am turning on that ifdef here, under the assumption
+ * that the functions may be deprecated, but they still work for this
+ * (older?) version of the LDAP API.  It gets am-utils to compile, but it is
+ * not clear if it will work perfectly.
+ */
+#ifndef LDAP_DEPRECATED
+# define LDAP_DEPRECATED 1
+#endif /* not LDAP_DEPRECATED */
+
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif /* HAVE_CONFIG_H */
@@ -81,14 +94,14 @@
  */
 typedef struct ald_ent ALD;
 typedef struct cr_ent CR;
-typedef struct he_ent HE;
+typedef struct he_ent HE_ENT;
 
 /*
  * STRUCTURES:
  */
 struct ald_ent {
   LDAP *ldap;
-  HE *hostent;
+  HE_ENT *hostent;
   CR *credentials;
   time_t timestamp;
 };
@@ -109,7 +122,7 @@ struct he_ent {
  * FORWARD DECLARATIONS:
  */
 static int amu_ldap_rebind(ALD *a);
-static int get_ldap_timestamp(LDAP *ld, char *map, time_t *ts);
+static int get_ldap_timestamp(ALD *a, char *map, time_t *ts);
 
 
 /*
@@ -117,7 +130,7 @@ static int get_ldap_timestamp(LDAP *ld, char *map, time_t *ts);
  */
 
 static void
-he_free(HE *h)
+he_free(HE_ENT *h)
 {
   XFREE(h->host);
   if (h->next != NULL)
@@ -126,25 +139,26 @@ he_free(HE *h)
 }
 
 
-static HE *
-string2he(char *s)
+static HE_ENT *
+string2he(char *s_orig)
 {
   char *c, *p;
-  HE *new, *old = NULL;
+  char *s;
+  HE_ENT *new, *old = NULL;
 
-  if (s == NULL)
-    return (NULL);
+  if (NULL == s_orig || NULL == (s = strdup(s_orig)))
+    return NULL;
   for (p = s; p; p = strchr(p, ',')) {
     if (old != NULL) {
-      new = (HE *) xmalloc(sizeof(HE));
+      new = ALLOC(HE_ENT);
       old->next = new;
       old = new;
     } else {
-      old = (HE *) xmalloc(sizeof(HE));
+      old = ALLOC(HE_ENT);
       old->next = NULL;
     }
     c = strchr(p, ':');
-    if (c) {			/* Host and port */
+    if (c) {            /* Host and port */
       *c++ = '\0';
       old->host = strdup(p);
       old->port = atoi(c);
@@ -152,6 +166,7 @@ string2he(char *s)
       old->host = strdup(p);
 
   }
+  XFREE(s);
   return (old);
 }
 
@@ -165,13 +180,54 @@ cr_free(CR *c)
 }
 
 
+/*
+ * Special ldap_unbind function to handle SIGPIPE.
+ * We first ignore SIGPIPE, in case a remote LDAP server was
+ * restarted, then we reinstall the handler.
+ */
+static int
+amu_ldap_unbind(LDAP *ld)
+{
+  int e;
+#ifdef HAVE_SIGACTION
+  struct sigaction sa;
+#else /* not HAVE_SIGACTION */
+  void (*handler)(int);
+#endif /* not HAVE_SIGACTION */
+
+  dlog("amu_ldap_unbind()\n");
+
+#ifdef HAVE_SIGACTION
+  sa.sa_handler = SIG_IGN;
+  sa.sa_flags = 0;
+  sigemptyset(&(sa.sa_mask));
+  sigaddset(&(sa.sa_mask), SIGPIPE);
+  sigaction(SIGPIPE, &sa, &sa);	/* set IGNORE, and get old action */
+#else /* not HAVE_SIGACTION */
+  handler = signal(SIGPIPE, SIG_IGN);
+#endif /* not HAVE_SIGACTION */
+
+  e = ldap_unbind(ld);
+
+#ifdef HAVE_SIGACTION
+  sigemptyset(&(sa.sa_mask));
+  sigaddset(&(sa.sa_mask), SIGPIPE);
+  sigaction(SIGPIPE, &sa, NULL);
+#else /* not HAVE_SIGACTION */
+  (void) signal(SIGPIPE, handler);
+#endif /* not HAVE_SIGACTION */
+
+  return e;
+}
+
+
 static void
 ald_free(ALD *a)
 {
   he_free(a->hostent);
   cr_free(a->credentials);
   if (a->ldap != NULL)
-    ldap_unbind(a->ldap);
+    amu_ldap_unbind(a->ldap);
   XFREE(a);
 }
 
@@ -182,27 +238,29 @@ amu_ldap_init(mnt_map *m, char *map, time_t *ts)
   ALD *aldh;
   CR *creds;
 
+  dlog("-> amu_ldap_init: map <%s>\n", map);
+
   /*
    * XXX: by checking that map_type must be defined, aren't we
    * excluding the possibility of automatic searches through all
    * map types?
    */
   if (!gopt.map_type || !STREQ(gopt.map_type, AMD_LDAP_TYPE)) {
-    return (ENOENT);
-  }
-#ifdef DEBUG
-  else {
+    dlog("amu_ldap_init called with map_type <%s>\n",
+	 (gopt.map_type ? gopt.map_type : "null"));
+  } else {
     dlog("Map %s is ldap\n", map);
   }
-#endif /* DEBUG */
-
-  aldh = (ALD *) xmalloc(sizeof(ALD));
-  creds = (CR *) xmalloc(sizeof(CR));
 
+  aldh = ALLOC(ALD);
+  creds = ALLOC(CR);
+  aldh->ldap = NULL;
   aldh->hostent = string2he(gopt.ldap_hostports);
   if (aldh->hostent == NULL) {
     plog(XLOG_USER, "Unable to parse hostport %s for ldap map %s",
-	 gopt.ldap_hostports, map);
+	 gopt.ldap_hostports ? gopt.ldap_hostports : "(null)", map);
+    XFREE(creds);
+    XFREE(aldh);
     return (ENOENT);
   }
   creds->who = "";
@@ -210,22 +268,17 @@ amu_ldap_init(mnt_map *m, char *map, time_t *ts)
   creds->method = LDAP_AUTH_SIMPLE;
   aldh->credentials = creds;
   aldh->timestamp = 0;
-#ifdef DEBUG
+  aldh->ldap = NULL;
   dlog("Trying for %s:%d\n", aldh->hostent->host, aldh->hostent->port);
-#endif /* DEBUG */
   if (amu_ldap_rebind(aldh)) {
     ald_free(aldh);
     return (ENOENT);
   }
   m->map_data = (void *) aldh;
-#ifdef DEBUG
   dlog("Bound to %s:%d\n", aldh->hostent->host, aldh->hostent->port);
-#endif /* DEBUG */
-  if (get_ldap_timestamp(aldh->ldap, map, ts))
+  if (get_ldap_timestamp(aldh, map, ts))
     return (ENOENT);
-#ifdef DEBUG
-  dlog("Got timestamp for map %s: %ld\n", map, *ts);
-#endif /* DEBUG */
+  dlog("Got timestamp for map %s: %ld\n", map, (u_long) *ts);
 
   return (0);
 }
@@ -235,20 +288,24 @@ static int
 amu_ldap_rebind(ALD *a)
 {
   LDAP *ld;
-  HE *h;
+  HE_ENT *h;
   CR *c = a->credentials;
-  time_t now = clocktime();
+  time_t now = clocktime(NULL);
   int try;
 
+  dlog("-> amu_ldap_rebind\n");
+
   if (a->ldap != NULL) {
     if ((a->timestamp - now) > AMD_LDAP_TTL) {
-#ifdef DEBUG
-      dlog("Reestablishing ldap connection\n");
-#endif /* DEBUG */
-      ldap_unbind(a->ldap);
+      dlog("Re-establishing ldap connection\n");
+      amu_ldap_unbind(a->ldap);
       a->timestamp = now;
-    } else
+      a->ldap = NULL;
+    } else {
+      /* Assume all is OK.  If it wasn't we'll be back! */
+      dlog("amu_ldap_rebind: timestamp OK\n");
       return (0);
+    }
   }
 
   for (try=0; try<10; try++) {	/* XXX: try up to 10 times (makes sense?) */
@@ -257,17 +314,34 @@ amu_ldap_rebind(ALD *a)
 	plog(XLOG_WARNING, "Unable to ldap_open to %s:%d\n", h->host, h->port);
 	break;
       }
+#if LDAP_VERSION_MAX > LDAP_VERSION2
+      /* handle LDAPv3 and heigher, if available and amd.conf-igured */
+      if (gopt.ldap_proto_version > LDAP_VERSION2) {
+        if (!ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &gopt.ldap_proto_version)) {
+          dlog("amu_ldap_rebind: LDAP protocol version set to %ld\n",
+	       gopt.ldap_proto_version);
+        } else {
+          plog(XLOG_WARNING, "Unable to set ldap protocol version to %ld\n",
+	       gopt.ldap_proto_version);
+	  break;
+        }
+      }
+#endif /* LDAP_VERSION_MAX > LDAP_VERSION2 */
       if (ldap_bind_s(ld, c->who, c->pw, c->method) != LDAP_SUCCESS) {
 	plog(XLOG_WARNING, "Unable to ldap_bind to %s:%d as %s\n",
 	     h->host, h->port, c->who);
 	break;
       }
       if (gopt.ldap_cache_seconds > 0) {
+#if defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE)
 	ldap_enable_cache(ld, gopt.ldap_cache_seconds, gopt.ldap_cache_maxmem);
-	a->ldap = ld;
-	a->timestamp = now;
-	return (0);
+#else /* not defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE) */
+	plog(XLOG_WARNING, "ldap_enable_cache(%ld) is not available on this system!\n", gopt.ldap_cache_seconds);
+#endif /* not defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE) */
       }
+      a->ldap = ld;
+      a->timestamp = now;
+      return (0);
     }
     plog(XLOG_WARNING, "Exhausted list of ldap servers, looping.\n");
   }
@@ -278,24 +352,24 @@ amu_ldap_rebind(ALD *a)
 
 
 static int
-get_ldap_timestamp(LDAP * ld, char *map, time_t *ts)
+get_ldap_timestamp(ALD *a, char *map, time_t *ts)
 {
   struct timeval tv;
   char **vals, *end;
   char filter[MAXPATHLEN];
   int i, err = 0, nentries = 0;
-  LDAPMessage *res, *entry;
+  LDAPMessage *res = NULL, *entry;
+
+  dlog("-> get_ldap_timestamp: map <%s>\n", map);
 
   tv.tv_sec = 3;
   tv.tv_usec = 0;
-  sprintf(filter, AMD_LDAP_TSFILTER, map);
-#ifdef DEBUG
+  xsnprintf(filter, sizeof(filter), AMD_LDAP_TSFILTER, map);
   dlog("Getting timestamp for map %s\n", map);
   dlog("Filter is: %s\n", filter);
   dlog("Base is: %s\n", gopt.ldap_base);
-#endif /* DEBUG */
   for (i = 0; i < AMD_LDAP_RETRIES; i++) {
-    err = ldap_search_st(ld,
+    err = ldap_search_st(a->ldap,
 			 gopt.ldap_base,
 			 LDAP_SCOPE_SUBTREE,
 			 filter,
@@ -305,19 +379,32 @@ get_ldap_timestamp(LDAP * ld, char *map, time_t *ts)
 			 &res);
     if (err == LDAP_SUCCESS)
       break;
-#ifdef DEBUG
-    dlog("Timestamp search timed out, trying again...\n");
-#endif /* DEBUG */
+    if (res) {
+      ldap_msgfree(res);
+      res = NULL;
+    }
+    plog(XLOG_USER, "Timestamp LDAP search attempt %d failed: %s\n",
+	 i + 1, ldap_err2string(err));
+    if (err != LDAP_TIMEOUT) {
+      dlog("get_ldap_timestamp: unbinding...\n");
+      amu_ldap_unbind(a->ldap);
+      a->ldap = NULL;
+      if (amu_ldap_rebind(a))
+        return (ENOENT);
+    }
+    dlog("Timestamp search failed, trying again...\n");
   }
 
   if (err != LDAP_SUCCESS) {
     *ts = 0;
     plog(XLOG_USER, "LDAP timestamp search failed: %s\n",
-	 ldap_err2string(ld->ld_errno));
+	 ldap_err2string(err));
+    if (res)
+      ldap_msgfree(res);
     return (ENOENT);
   }
 
-  nentries = ldap_count_entries(ld, res);
+  nentries = ldap_count_entries(a->ldap, res);
   if (nentries == 0) {
     plog(XLOG_USER, "No timestamp entry for map %s\n", map);
     *ts = 0;
@@ -325,19 +412,16 @@ get_ldap_timestamp(LDAP * ld, char *map, time_t *ts)
     return (ENOENT);
   }
 
-  entry = ldap_first_entry(ld, res);
-  vals = ldap_get_values(ld, entry, AMD_LDAP_TSATTR);
+  entry = ldap_first_entry(a->ldap, res);
+  vals = ldap_get_values(a->ldap, entry, AMD_LDAP_TSATTR);
   if (ldap_count_values(vals) == 0) {
     plog(XLOG_USER, "Missing timestamp value for map %s\n", map);
     *ts = 0;
     ldap_value_free(vals);
     ldap_msgfree(res);
-    ldap_msgfree(entry);
     return (ENOENT);
   }
-#ifdef DEBUG
   dlog("TS value is:%s:\n", vals[0]);
-#endif /* DEBUG */
 
   if (vals[0]) {
     *ts = (time_t) strtol(vals[0], &end, 10);
@@ -348,7 +432,7 @@ get_ldap_timestamp(LDAP * ld, char *map, time_t *ts)
     }
     if (!*ts > 0) {
       plog(XLOG_USER, "Nonpositive timestamp %ld for map %s\n",
-	   *ts, map);
+	   (u_long) *ts, map);
       err = ENOENT;
     }
   } else {
@@ -359,10 +443,7 @@ get_ldap_timestamp(LDAP * ld, char *map, time_t *ts)
 
   ldap_value_free(vals);
   ldap_msgfree(res);
-  ldap_msgfree(entry);
-#ifdef DEBUG
-  dlog("The timestamp for %s is %ld (err=%d)\n", map, *ts, err);
-#endif /* DEBUG */
+  dlog("The timestamp for %s is %ld (err=%d)\n", map, (u_long) *ts, err);
   return (err);
 }
 
@@ -370,12 +451,15 @@ get_ldap_timestamp(LDAP * ld, char *map, time_t *ts)
 int
 amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
 {
-  char **vals, filter[MAXPATHLEN];
+  char **vals, filter[MAXPATHLEN], filter2[2 * MAXPATHLEN];
+  char *f1, *f2;
   struct timeval tv;
   int i, err = 0, nvals = 0, nentries = 0;
-  LDAPMessage *entry, *res;
+  LDAPMessage *entry, *res = NULL;
   ALD *a = (ALD *) (m->map_data);
 
+  dlog("-> amu_ldap_search: map <%s>, key <%s>\n", map, key);
+
   tv.tv_sec = 2;
   tv.tv_usec = 0;
   if (a == NULL) {
@@ -385,43 +469,63 @@ amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
   if (amu_ldap_rebind(a))	/* Check that's the handle is still valid */
     return (ENOENT);
 
-  sprintf(filter, AMD_LDAP_FILTER, map, key);
-#ifdef DEBUG
-  dlog("Search with filter: %s\n", filter);
-#endif /* DEBUG */
+  xsnprintf(filter, sizeof(filter), AMD_LDAP_FILTER, map, key);
+  /* "*" is special to ldap_search(); run through the filter escaping it. */
+  f1 = filter; f2 = filter2;
+  while (*f1) {
+    if (*f1 == '*') {
+      *f2++ = '\\'; *f2++ = '2'; *f2++ = 'a';
+      f1++;
+    } else {
+      *f2++ = *f1++;
+    }
+  }
+  *f2 = '\0';
+  dlog("Search with filter: <%s>\n", filter2);
   for (i = 0; i < AMD_LDAP_RETRIES; i++) {
     err = ldap_search_st(a->ldap,
 			 gopt.ldap_base,
 			 LDAP_SCOPE_SUBTREE,
-			 filter,
+			 filter2,
 			 0,
 			 0,
 			 &tv,
 			 &res);
     if (err == LDAP_SUCCESS)
       break;
+    if (res) {
+      ldap_msgfree(res);
+      res = NULL;
+    }
+    plog(XLOG_USER, "LDAP search attempt %d failed: %s\n",
+        i + 1, ldap_err2string(err));
+    if (err != LDAP_TIMEOUT) {
+      dlog("amu_ldap_search: unbinding...\n");
+      amu_ldap_unbind(a->ldap);
+      a->ldap = NULL;
+      if (amu_ldap_rebind(a))
+        return (ENOENT);
+    }
   }
 
   switch (err) {
   case LDAP_SUCCESS:
     break;
   case LDAP_NO_SUCH_OBJECT:
-#ifdef DEBUG
     dlog("No object\n");
-#endif /* DEBUG */
-    ldap_msgfree(res);
+    if (res)
+      ldap_msgfree(res);
     return (ENOENT);
   default:
     plog(XLOG_USER, "LDAP search failed: %s\n",
-	 ldap_err2string(a->ldap->ld_errno));
-    ldap_msgfree(res);
+	 ldap_err2string(err));
+    if (res)
+      ldap_msgfree(res);
     return (EIO);
   }
 
   nentries = ldap_count_entries(a->ldap, res);
-#ifdef DEBUG
   dlog("Search found %d entries\n", nentries);
-#endif /* DEBUG */
   if (nentries == 0) {
     ldap_msgfree(res);
     return (ENOENT);
@@ -433,12 +537,9 @@ amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
     plog(XLOG_USER, "Missing value for %s in map %s\n", key, map);
     ldap_value_free(vals);
     ldap_msgfree(res);
-    ldap_msgfree(entry);
     return (EIO);
   }
-#ifdef DEBUG
   dlog("Map %s, %s => %s\n", map, key, vals[0]);
-#endif /* DEBUG */
   if (vals[0]) {
     *pval = strdup(vals[0]);
     err = 0;
@@ -447,7 +548,6 @@ amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
     err = ENOENT;
   }
   ldap_msgfree(res);
-  ldap_msgfree(entry);
   ldap_value_free(vals);
 
   return (err);
@@ -460,15 +560,13 @@ amu_ldap_mtime(mnt_map *m, char *map, time_t *ts)
   ALD *aldh = (ALD *) (m->map_data);
 
   if (aldh == NULL) {
-#ifdef DEBUG
     dlog("LDAP panic: unable to find map data\n");
-#endif /* DEBUG */
     return (ENOENT);
   }
   if (amu_ldap_rebind(aldh)) {
     return (ENOENT);
   }
-  if (get_ldap_timestamp(aldh->ldap, map, ts)) {
+  if (get_ldap_timestamp(aldh, map, ts)) {
     return (ENOENT);
   }
   return (0);
diff --git a/contrib/amd/amd/info_ndbm.c b/contrib/amd/amd/info_ndbm.c
index 91cb8e0..8a52ba9 100644
--- a/contrib/amd/amd/info_ndbm.c
+++ b/contrib/amd/amd/info_ndbm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: info_ndbm.c,v 1.2 1999/01/10 21:53:46 ezk Exp $
+ * File: am-utils/amd/info_ndbm.c
  *
  */
 
@@ -86,8 +85,8 @@ ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
 #ifdef DBM_SUFFIX
     char dbfilename[256];
 
-    strcpy(dbfilename, map);
-    strcat(dbfilename, DBM_SUFFIX);
+    xstrlcpy(dbfilename, map, sizeof(dbfilename));
+    xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename));
     error = stat(dbfilename, &stb);
 #else /* not DBM_SUFFIX */
     error = fstat(dbm_pagfno(db), &stb);
@@ -117,14 +116,14 @@ ndbm_init(mnt_map *m, char *map, time_t *tp)
 #ifdef DBM_SUFFIX
     char dbfilename[256];
 
-    strcpy(dbfilename, map);
-    strcat(dbfilename, DBM_SUFFIX);
+    xstrlcpy(dbfilename, map, sizeof(dbfilename));
+    xstrlcat(dbfilename, DBM_SUFFIX, sizeof(dbfilename));
     error = stat(dbfilename, &stb);
 #else /* not DBM_SUFFIX */
     error = fstat(dbm_pagfno(db), &stb);
 #endif /* not DBM_SUFFIX */
     if (error < 0)
-      *tp = clocktime();
+      *tp = clocktime(NULL);
     else
       *tp = stb.st_mtime;
     dbm_close(db);
diff --git a/contrib/amd/amd/info_nis.c b/contrib/amd/amd/info_nis.c
index 17699d4..bcb87d5 100644
--- a/contrib/amd/amd/info_nis.c
+++ b/contrib/amd/amd/info_nis.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: info_nis.c,v 1.5 1999/08/22 05:12:51 ezk Exp $
+ * File: am-utils/amd/info_nis.c
  *
  */
 
@@ -107,9 +106,7 @@ determine_nis_domain(void)
   }
   if (!*default_domain) {
     nis_not_running = 1;
-#ifdef DEBUG
     plog(XLOG_WARNING, "NIS domain name is not set.  NIS ignored.");
-#endif /* DEBUG */
     return ENOENT;
   }
   gopt.nis_domain = strdup(default_domain);
@@ -144,12 +141,8 @@ callback(int status, char *key, int kl, char *val, int vl, char *data)
       /* check what went wrong */
       int e = ypprot_err(status);
 
-#ifdef DEBUG
       plog(XLOG_ERROR, "yp enumeration of %s: %s, status=%d, e=%d",
 	   ncdp->ncd_map, yperr_string(e), status, e);
-#else /* not DEBUG */
-      plog(XLOG_ERROR, "yp enumeration of %s: %s", ncdp->ncd_map, yperr_string(e));
-#endif /* not DEBUG */
     }
     return TRUE;
   }
@@ -321,7 +314,7 @@ nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
     return ENOENT;
 
   default:
-    plog(XLOG_ERROR, "%s: %s", map, yperr_string(res));
+    plog(XLOG_ERROR, "nis_search: %s: %s", map, yperr_string(res));
     return EIO;
   }
 }
@@ -350,9 +343,7 @@ nis_init(mnt_map *m, char *map, time_t *tp)
     /* NIS server found */
     has_yp_order = 1;
     *tp = (time_t) order;
-#ifdef DEBUG
     dlog("NIS master for %s@%s has order %lu", map, gopt.nis_domain, (unsigned long) order);
-#endif /* DEBUG */
     break;
   case YPERR_YPERR:
     /* NIS+ server found ! */
@@ -361,9 +352,7 @@ nis_init(mnt_map *m, char *map, time_t *tp)
     if (yp_master(gopt.nis_domain, map, &master)) {
       return ENOENT;
     } else {
-#ifdef DEBUG
       dlog("NIS master for %s@%s is a NIS+ server", map, gopt.nis_domain);
-#endif /* DEBUG */
       /* Use fake timestamps */
       *tp = time(NULL);
     }
@@ -442,11 +431,9 @@ am_yp_all(char *indomain, char *inmap, struct ypall_callback *incallback)
 		&outvallen);
     XFREE(outkey_old);
   } while (!i);
-#ifdef DEBUG
   if (i) {
     dlog("yp_next() returned error: %s\n", yperr_string(i));
   }
-#endif /* DEBUG */
   if (i == YPERR_NOMORE)
     return 0;
   return i;
diff --git a/contrib/amd/amd/info_nisplus.c b/contrib/amd/amd/info_nisplus.c
index ea7a3d7..d392b48 100644
--- a/contrib/amd/amd/info_nisplus.c
+++ b/contrib/amd/amd/info_nisplus.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: info_nisplus.c,v 1.2 1999/01/10 21:53:46 ezk Exp $
+ * File: am-utils/amd/info_nisplus.c
  *
  */
 
@@ -74,9 +73,7 @@ nisplus_callback(const nis_name key, const nis_object *value, voidp opaquedata)
   char *vp = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
   struct nis_callback_data *data = (struct nis_callback_data *) opaquedata;
 
-#ifdef DEBUG
   dlog("NISplus callback for <%s,%s>", kp, vp);
-#endif /* DEBUG */
 
   (*data->ncd_fn) (data->ncd_m, kp, vp);
 
@@ -95,6 +92,7 @@ nisplus_reload(mnt_map *m, char *map, void (*fn) ())
   nis_result *result;
   char *org;		/* if map does not have ".org_dir" then append it */
   nis_name map_name;
+  size_t l;
 
   org = strstr(map, NISPLUS_ORGDIR);
   if (org == NULL)
@@ -103,21 +101,20 @@ nisplus_reload(mnt_map *m, char *map, void (*fn) ())
     org = "";
 
   /* make some room for the NIS map_name */
-  map_name = xmalloc(strlen(map) + sizeof(NISPLUS_ORGDIR));
+  l = strlen(map) + sizeof(NISPLUS_ORGDIR);
+  map_name = xmalloc(l);
   if (map_name == NULL) {
     plog(XLOG_ERROR, "Unable to create map_name %s: %s",
 	 map, strerror(ENOMEM));
     return ENOMEM;
   }
-  sprintf(map_name, "%s%s", map, org);
+  xsnprintf(map_name, l, "%s%s", map, org);
 
   data.ncd_m = m;
   data.ncd_map = map_name;
   data.ncd_fn = fn;
 
-#ifdef DEBUG
   dlog("NISplus reload for %s", map);
-#endif /* DEBUG */
 
   result = nis_list(map_name,
 		    EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
@@ -145,10 +142,8 @@ nisplus_search_callback(const nis_name key, const nis_object *value, voidp opaqu
 {
   struct nisplus_search_callback_data *data = (struct nisplus_search_callback_data *) opaquedata;
 
-#ifdef DEBUG
   dlog("NISplus search callback for <%s>", ENTRY_VAL(value, 0));
   dlog("NISplus search callback value <%s>", ENTRY_VAL(value, 1));
-#endif /* DEBUG */
 
   data->value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
   return TRUE;
@@ -166,6 +161,7 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
   struct nisplus_search_callback_data data;
   nis_name index;
   char *org;		/* if map does not have ".org_dir" then append it */
+  size_t l;
 
   org = strstr(map, NISPLUS_ORGDIR);
   if (org == NULL)
@@ -174,14 +170,14 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
     org = "";
 
   /* make some room for the NIS index */
-  index = xmalloc(sizeof('[')	/* for opening selection criteria */
-		  +sizeof(NISPLUS_KEY)
-		  + strlen(key)
-		  + sizeof(']')	/* for closing selection criteria */
-		  +sizeof(',')	/* + 1 for , separator */
-		  +strlen(map)
-		  + sizeof(NISPLUS_ORGDIR)
-		  );
+  l = sizeof('[')		/* for opening selection criteria */
+    + sizeof(NISPLUS_KEY)
+    + strlen(key)
+    + sizeof(']')		/* for closing selection criteria */
+    + sizeof(',')		/* + 1 for , separator */
+    + strlen(map)
+    + sizeof(NISPLUS_ORGDIR);
+  index = xmalloc(l);
   if (index == NULL) {
     plog(XLOG_ERROR,
 	 "Unable to create index %s: %s",
@@ -189,14 +185,12 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
 	 strerror(ENOMEM));
     return ENOMEM;
   }
-  sprintf(index, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
+  xsnprintf(index, l, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
 
   data.key = key;
   data.value = NULL;
 
-#ifdef DEBUG
   dlog("NISplus search for %s", index);
-#endif /* DEBUG */
 
   result = nis_list(index,
 		    EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
@@ -207,7 +201,7 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
   XFREE(index);
 
   if (result == NULL) {
-    plog(XLOG_ERROR, "%s: %s", map, strerror(ENOMEM));
+    plog(XLOG_ERROR, "nisplus_search: %s: %s", map, strerror(ENOMEM));
     return ENOMEM;
   }
 
@@ -220,11 +214,9 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
 
     if (data.value == NULL) {
       nis_object *value = result->objects.objects_val;
-#ifdef DEBUG
       dlog("NISplus search found <nothing>");
       dlog("NISplus search for %s: %s(%d)",
 	   map, nis_sperrno(result->status), result->status);
-#endif /* DEBUG */
 
       if (value != NULL)
 	data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
@@ -233,28 +225,22 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
 
     if (*val) {
       error = 0;
-#ifdef DEBUG
       dlog("NISplus search found %s", *val);
-#endif /* DEBUG */
     } else {
       error = ENOENT;
-#ifdef DEBUG
       dlog("NISplus search found nothing");
-#endif /* DEBUG */
     }
 
     *tp = 0;
     break;
 
   case NIS_NOSUCHNAME:
-#ifdef DEBUG
     dlog("NISplus search returned %d", result->status);
-#endif /* DEBUG */
     error = ENOENT;
     break;
 
   default:
-    plog(XLOG_ERROR, "%s: %s", map, nis_sperrno(result->status));
+    plog(XLOG_ERROR, "nisplus_search: %s: %s", map, nis_sperrno(result->status));
     error = EIO;
     break;
   }
@@ -271,6 +257,7 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
   char *org;		/* if map does not have ".org_dir" then append it */
   nis_name map_name;
   int error = 0;
+  size_t l;
 
   org = strstr(map, NISPLUS_ORGDIR);
   if (org == NULL)
@@ -279,7 +266,8 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
     org = "";
 
   /* make some room for the NIS map_name */
-  map_name = xmalloc(strlen(map) + sizeof(NISPLUS_ORGDIR));
+  l = strlen(map) + sizeof(NISPLUS_ORGDIR);
+  map_name = xmalloc(l);
   if (map_name == NULL) {
     plog(XLOG_ERROR,
 	 "Unable to create map_name %s: %s",
@@ -287,7 +275,7 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
 	 strerror(ENOMEM));
     return ENOMEM;
   }
-  sprintf(map_name, "%s%s", map, org);
+  xsnprintf(map_name, l, "%s%s", map, org);
 
   result = nis_lookup(map_name, (EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH));
 
@@ -300,10 +288,8 @@ nisplus_init(mnt_map *m, char *map, time_t *tp)
   }
 
   if (result->status != NIS_SUCCESS) {
-#ifdef DEBUG
     dlog("NISplus init <%s>: %s (%d)",
 	 map, nis_sperrno(result->status), result->status);
-#endif /* DEBUG */
 
     error = ENOENT;
   }
diff --git a/contrib/amd/amd/info_passwd.c b/contrib/amd/amd/info_passwd.c
index d367f38..c8bf388 100644
--- a/contrib/amd/amd/info_passwd.c
+++ b/contrib/amd/amd/info_passwd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: info_passwd.c,v 1.2 1999/01/10 21:53:46 ezk Exp $
+ * File: am-utils/amd/info_passwd.c
  *
  */
 
@@ -151,11 +150,11 @@ passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
     do {
       q = strrchr(p, '/');
       if (q) {
-	strcat(rhost, q + 1);
-	strcat(rhost, ".");
+	xstrlcat(rhost, q + 1, sizeof(rhost));
+	xstrlcat(rhost, ".", sizeof(rhost));
 	*q = '\0';
       } else {
-	strcat(rhost, p);
+	xstrlcat(rhost, p, sizeof(rhost));
       }
     } while (q);
 
@@ -176,11 +175,9 @@ passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
       p++;
     else
       p = "type:=nfs;rfs:=/${var0}/${var1};rhost:=${var1};sublink:=${var2};fs:=${autodir}${var3}";
-    sprintf(val, "var0:=%s;var1:=%s;var2:=%s;var3:=%s;%s",
-	    dir+1, rhost, user, pw->pw_dir, p);
-#ifdef DEBUG
+    xsnprintf(val, sizeof(val), "var0:=%s;var1:=%s;var2:=%s;var3:=%s;%s",
+	      dir+1, rhost, user, pw->pw_dir, p);
     dlog("passwd_search: map=%s key=%s -> %s", map, key, val);
-#endif /* DEBUG */
     if (q)
       *q = '.';
     *pval = strdup(val);
diff --git a/contrib/amd/amd/info_union.c b/contrib/amd/amd/info_union.c
index d81602b..8f0631c 100644
--- a/contrib/amd/amd/info_union.c
+++ b/contrib/amd/amd/info_union.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: info_union.c,v 1.2 1999/01/10 21:53:47 ezk Exp $
+ * File: am-utils/amd/info_union.c
  *
  */
 
@@ -81,10 +80,12 @@ union_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
   char *mapd = strdup(map + UNION_PREFLEN);
   char **v = strsplit(mapd, ':', '\"');
   char **p;
+  size_t l;
 
   for (p = v; p[1]; p++) ;
-  *pval = xmalloc(strlen(*p) + 5);
-  sprintf(*pval, "fs:=%s", *p);
+  l = strlen(*p) + 5;
+  *pval = xmalloc(l);
+  xsnprintf(*pval, l, "fs:=%s", *p);
   XFREE(mapd);
   XFREE(v);
   return 0;
@@ -104,7 +105,7 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
   (*fn) (m, strdup("/defaults"), strdup("type:=link;opts:=nounmount;sublink:=${key}"));
 
   for (dir = v; *dir; dir++) {
-    int dlen;
+    size_t l;
     struct dirent *dp;
 
     DIR *dirp = opendir(*dir);
@@ -112,11 +113,9 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
       plog(XLOG_USER, "Cannot read directory %s: %m", *dir);
       continue;
     }
-    dlen = strlen(*dir);
+    l = strlen(*dir) + 5;
 
-#ifdef DEBUG
     dlog("Reading directory %s...", *dir);
-#endif /* DEBUG */
     while ((dp = readdir(dirp))) {
       char *val, *dpname = &dp->d_name[0];
       if (dpname[0] == '.' &&
@@ -124,11 +123,9 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
 	   (dpname[1] == '.' && dpname[2] == '\0')))
 	continue;
 
-#ifdef DEBUG
       dlog("... gives %s", dp->d_name);
-#endif /* DEBUG */
-      val = xmalloc(dlen + 5);
-      sprintf(val, "fs:=%s", *dir);
+      val = xmalloc(l);
+      xsnprintf(val, l + 5, "fs:=%s", *dir);
       (*fn) (m, strdup(dp->d_name), val);
     }
     closedir(dirp);
@@ -138,9 +135,10 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
    * Add wildcard entry
    */
   {
-    char *val = xmalloc(strlen(dir[-1]) + 5);
+    size_t l = strlen(*(dir-1)) + 5;
+    char *val = xmalloc(l);
 
-    sprintf(val, "fs:=%s", dir[-1]);
+    xsnprintf(val, l, "fs:=%s", *(dir-1));
     (*fn) (m, strdup("*"), val);
   }
   XFREE(mapd);
diff --git a/contrib/amd/amd/map.c b/contrib/amd/amd/map.c
index 4bfb058..8696dfd 100644
--- a/contrib/amd/amd/map.c
+++ b/contrib/amd/amd/map.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: map.c,v 1.5 1999/08/22 05:12:51 ezk Exp $
+ * File: am-utils/amd/map.c
  *
  */
 
@@ -50,7 +49,6 @@
 
 #define	smallest_t(t1, t2) (t1 != NEVER ? (t2 != NEVER ? (t1 < t2 ? t1 : t2) : t1) : t2)
 #define IGNORE_FLAGS (MFF_MOUNTING|MFF_UNMOUNTING|MFF_RESTART)
-#define NEVER (time_t) 0
 #define new_gen() (am_gen++)
 
 /*
@@ -65,15 +63,16 @@
  * there is no way that 2^32 generation numbers could ever
  * be allocated by a single run of amd - there is simply
  * not enough cpu time available.
+ * Famous last words... -Ion
  */
 static u_int am_gen = 2;	/* Initial generation number */
 static int timeout_mp_id;	/* Id from last call to timeout */
 
-am_node *root_node;		/* The root of the mount tree */
-am_node **exported_ap = (am_node **) 0;
-int exported_ap_size = 0;
-int first_free_map = 0;		/* First available free slot */
-int last_used_map = -1;		/* Last unavailable used slot */
+static am_node *root_node;	/* The root of the mount tree */
+static am_node **exported_ap = (am_node **) 0;
+static int exported_ap_size = 0;
+static int first_free_map = 0;	/* First available free slot */
+static int last_used_map = -1;	/* Last unavailable used slot */
 
 
 /*
@@ -102,9 +101,65 @@ static nfsfattr gen_fattr =
 };
 
 /* forward declarations */
-static int unmount_node(am_node *mp);
+static int unmount_node(opaque_t arg);
 static void exported_ap_free(am_node *mp);
 static void remove_am(am_node *mp);
+static am_node *get_root_ap(char *dir);
+
+
+/*
+ * Iterator functions for exported_ap[]
+ */
+am_node *
+get_first_exported_ap(int *index)
+{
+  *index = -1;
+  return get_next_exported_ap(index);
+}
+
+
+am_node *
+get_next_exported_ap(int *index)
+{
+  (*index)++;
+  while (*index < exported_ap_size) {
+    if (exported_ap[*index] != NULL)
+      return exported_ap[*index];
+    (*index)++;
+  }
+  return NULL;
+}
+
+
+/*
+ * Get exported_ap by index
+ */
+am_node *
+get_exported_ap(int index)
+{
+  if (index < 0 || index >= exported_ap_size)
+    return 0;
+  return exported_ap[index];
+}
+
+
+/*
+ * Get exported_ap by path
+ */
+am_node *
+path_to_exported_ap(char *path)
+{
+  int index;
+  am_node *mp;
+
+  mp = get_first_exported_ap(&index);
+  while (mp != NULL) {
+    if (STREQ(mp->am_path, path))
+      break;
+    mp = get_next_exported_ap(&index);
+  }
+  return mp;
+}
 
 
 /*
@@ -130,6 +185,46 @@ exported_ap_realloc_map(int nsize)
 }
 
 
+
+am_node *
+get_ap_child(am_node *mp, char *fname)
+{
+  am_node *new_mp;
+  mntfs *mf = mp->am_mnt;
+
+  /*
+   * Allocate a new map
+   */
+  new_mp = exported_ap_alloc();
+  if (new_mp) {
+    /*
+     * Fill it in
+     */
+    init_map(new_mp, fname);
+
+    /*
+     * Put it in the table
+     */
+    insert_am(new_mp, mp);
+
+    /*
+     * Fill in some other fields,
+     * path and mount point.
+     *
+     * bugfix: do not prepend old am_path if direct map
+     *         <wls@astro.umd.edu> William Sebok
+     */
+    new_mp->am_path = str3cat(new_mp->am_path,
+			      (mf->mf_fsflags & FS_DIRECT)
+				     ? ""
+				     : mp->am_path,
+			      *fname == '/' ? "" : "/", fname);
+    dlog("setting path to %s", new_mp->am_path);
+  }
+
+  return new_mp;
+}
+
 /*
  * Allocate a new mount slot and create
  * a new node.
@@ -153,7 +248,7 @@ exported_ap_alloc(void)
    */
   mpp = exported_ap + first_free_map;
   mp = *mpp = ALLOC(struct am_node);
-  memset((char *) mp, 0, sizeof(*mp));
+  memset((char *) mp, 0, sizeof(struct am_node));
 
   mp->am_mapno = first_free_map++;
 
@@ -198,8 +293,9 @@ exported_ap_free(am_node *mp)
     first_free_map = mp->am_mapno;
 
   /*
-   * Free the mount node
+   * Free the mount node, and zero out it's internal struct data.
    */
+  memset((char *) mp, 0, sizeof(am_node));
   XFREE(mp);
 }
 
@@ -228,6 +324,10 @@ insert_am(am_node *mp, am_node *p_mp)
   if (mp->am_osib)
     mp->am_osib->am_ysib = mp;
   p_mp->am_child = mp;
+#ifdef HAVE_FS_AUTOFS
+  if (p_mp->am_mnt->mf_flags & MFF_IS_AUTOFS)
+    mp->am_flags |= AMF_AUTOFS;
+#endif /* HAVE_FS_AUTOFS */
 }
 
 
@@ -267,27 +367,26 @@ void
 new_ttl(am_node *mp)
 {
   mp->am_timeo_w = 0;
-  mp->am_ttl = clocktime();
-  mp->am_fattr.na_atime.nt_seconds = mp->am_ttl;
+  mp->am_ttl = clocktime(&mp->am_fattr.na_atime);
   mp->am_ttl += mp->am_timeo;	/* sun's -tl option */
 }
 
 
 void
-mk_fattr(am_node *mp, nfsftype vntype)
+mk_fattr(nfsfattr *fattr, nfsftype vntype)
 {
   switch (vntype) {
   case NFDIR:
-    mp->am_fattr.na_type = NFDIR;
-    mp->am_fattr.na_mode = NFSMODE_DIR | 0555;
-    mp->am_fattr.na_nlink = 2;
-    mp->am_fattr.na_size = 512;
+    fattr->na_type = NFDIR;
+    fattr->na_mode = NFSMODE_DIR | 0555;
+    fattr->na_nlink = 2;
+    fattr->na_size = 512;
     break;
   case NFLNK:
-    mp->am_fattr.na_type = NFLNK;
-    mp->am_fattr.na_mode = NFSMODE_LNK | 0777;
-    mp->am_fattr.na_nlink = 1;
-    mp->am_fattr.na_size = 0;
+    fattr->na_type = NFLNK;
+    fattr->na_mode = NFSMODE_LNK | 0777;
+    fattr->na_nlink = 1;
+    fattr->na_size = 0;
     break;
   default:
     plog(XLOG_FATAL, "Unknown fattr type %d - ignored", vntype);
@@ -310,21 +409,27 @@ init_map(am_node *mp, char *dir)
    * other fields don't need to be set to zero.
    */
   mp->am_mnt = new_mntfs();
+  mp->am_mfarray = 0;
   mp->am_name = strdup(dir);
   mp->am_path = strdup(dir);
   mp->am_gen = new_gen();
+#ifdef HAVE_FS_AUTOFS
+  mp->am_autofs_fh = 0;
+#endif /* HAVE_FS_AUTOFS */
 
   mp->am_timeo = gopt.am_timeo;
   mp->am_attr.ns_status = NFS_OK;
   mp->am_fattr = gen_fattr;
   mp->am_fattr.na_fsid = 42;
-  mp->am_fattr.na_fileid = 0;
-  mp->am_fattr.na_atime.nt_seconds = clocktime();
-  mp->am_fattr.na_atime.nt_useconds = 0;
+  mp->am_fattr.na_fileid = mp->am_gen;
+  clocktime(&mp->am_fattr.na_atime);
+  /* next line copies a "struct nfstime" among several fields */
   mp->am_fattr.na_mtime = mp->am_fattr.na_ctime = mp->am_fattr.na_atime;
 
   new_ttl(mp);
   mp->am_stats.s_mtime = mp->am_fattr.na_atime.nt_seconds;
+  mp->am_dev = -1;
+  mp->am_rdev = -1;
 }
 
 
@@ -335,7 +440,6 @@ init_map(am_node *mp, char *dir)
 void
 free_map(am_node *mp)
 {
-
   remove_am(mp);
 
   if (mp->am_link)
@@ -352,188 +456,24 @@ free_map(am_node *mp)
   if (mp->am_mnt)
     free_mntfs(mp->am_mnt);
 
-  exported_ap_free(mp);
-}
-
-
-/*
- * Convert from file handle to automount node.
- */
-am_node *
-fh_to_mp3(am_nfs_fh *fhp, int *rp, int c_or_d)
-{
-  struct am_fh *fp = (struct am_fh *) fhp;
-  am_node *ap = 0;
-
-  /*
-   * Check process id matches
-   * If it doesn't then it is probably
-   * from an old kernel cached filehandle
-   * which is now out of date.
-   */
-  if (fp->fhh_pid != am_mypid)
-    goto drop;
-
-  /*
-   * Make sure the index is valid before
-   * exported_ap is referenced.
-   */
-  if (fp->fhh_id < 0 || fp->fhh_id >= exported_ap_size)
-    goto drop;
-
-  /*
-   * Get hold of the supposed mount node
-   */
-  ap = exported_ap[fp->fhh_id];
-
-  /*
-   * If it exists then maybe...
-   */
-  if (ap) {
-    /*
-     * Check the generation number in the node
-     * matches the one from the kernel.  If not
-     * then the old node has been timed out and
-     * a new one allocated.
-     */
-    if (ap->am_gen != fp->fhh_gen) {
-      ap = 0;
-      goto drop;
-    }
-    /*
-     * If the node is hung then locate a new node
-     * for it.  This implements the replicated filesystem
-     * retries.
-     */
-    if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) {
-      int error;
-      am_node *orig_ap = ap;
-
-#ifdef DEBUG
-      dlog("fh_to_mp3: %s (%s) is hung:- call lookup",
-	   orig_ap->am_path, orig_ap->am_mnt->mf_info);
-#endif /* DEBUG */
-
-      /*
-       * Update modify time of parent node.
-       * With any luck the kernel will re-stat
-       * the child node and get new information.
-       */
-      orig_ap->am_fattr.na_mtime.nt_seconds = clocktime();
-
-      /*
-       * Call the parent's lookup routine for an object
-       * with the same name.  This may return -1 in error
-       * if a mount is in progress.  In any case, if no
-       * mount node is returned the error code is propagated
-       * to the caller.
-       */
-      if (c_or_d == VLOOK_CREATE) {
-	ap = (*orig_ap->am_parent->am_mnt->mf_ops->lookuppn)
-	  (orig_ap->am_parent, orig_ap->am_name, &error, c_or_d);
-      } else {
-	ap = 0;
-	error = ESTALE;
-      }
-      if (ap == 0) {
-	if (error < 0 && amd_state == Finishing)
-	  error = ENOENT;
-	*rp = error;
-	return 0;
-      }
-
-      /*
-       * Update last access to original node.  This
-       * avoids timing it out and so sending ESTALE
-       * back to the kernel.
-       * XXX - Not sure we need this anymore (jsp, 90/10/6).
-       */
-      new_ttl(orig_ap);
-
-    }
-
-    /*
-     * Disallow references to objects being unmounted, unless
-     * they are automount points.
-     */
-    if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) &&
-	!(ap->am_flags & AMF_ROOT)) {
-      if (amd_state == Finishing)
-	*rp = ENOENT;
-      else
-	*rp = -1;
-      return 0;
-    }
-    new_ttl(ap);
-  }
-
-drop:
-  if (!ap || !ap->am_mnt) {
-    /*
-     * If we are shutting down then it is likely
-     * that this node has disappeared because of
-     * a fast timeout.  To avoid things thrashing
-     * just pretend it doesn't exist at all.  If
-     * ESTALE is returned, some NFS clients just
-     * keep retrying (stupid or what - if it's
-     * stale now, what's it going to be in 5 minutes?)
-     */
-    if (amd_state == Finishing)
-      *rp = ENOENT;
-    else
-      *rp = ESTALE;
-    amd_stats.d_stale++;
+  if (mp->am_mfarray) {
+    mntfs **temp_mf;
+    for (temp_mf = mp->am_mfarray; *temp_mf; temp_mf++)
+      free_mntfs(*temp_mf);
+    XFREE(mp->am_mfarray);
   }
 
-  return ap;
-}
-
-
-am_node *
-fh_to_mp(am_nfs_fh *fhp)
-{
-  int dummy;
-
-  return fh_to_mp2(fhp, &dummy);
-}
-
-
-/*
- * Convert from automount node to file handle.
- */
-void
-mp_to_fh(am_node *mp, am_nfs_fh *fhp)
-{
-  struct am_fh *fp = (struct am_fh *) fhp;
-
-  memset((char *) fhp, 0, sizeof(am_nfs_fh));
-
-  /*
-   * Take the process id
-   */
-  fp->fhh_pid = am_mypid;
-
-  /*
-   * ... the map number
-   */
-  fp->fhh_id = mp->am_mapno;
+#ifdef HAVE_FS_AUTOFS
+  if (mp->am_autofs_fh)
+    autofs_release_fh(mp);
+#endif /* HAVE_FS_AUTOFS */
 
-  /*
-   * ... and the generation number
-   */
-  fp->fhh_gen = mp->am_gen;
-
-  /*
-   * ... to make a "unique" triple that will never
-   * be reallocated except across reboots (which doesn't matter)
-   * or if we are unlucky enough to be given the same
-   * pid as a previous amd (very unlikely).
-   */
+  exported_ap_free(mp);
 }
 
 
-am_node *
-find_ap2(char *dir, am_node *mp)
+static am_node *
+find_ap_recursive(char *dir, am_node *mp)
 {
   if (mp) {
     am_node *mp2;
@@ -544,10 +484,10 @@ find_ap2(char *dir, am_node *mp)
 	STREQ(mp->am_mnt->mf_mount, dir))
       return mp;
 
-    mp2 = find_ap2(dir, mp->am_osib);
+    mp2 = find_ap_recursive(dir, mp->am_osib);
     if (mp2)
       return mp2;
-    return find_ap2(dir, mp->am_child);
+    return find_ap_recursive(dir, mp->am_child);
   }
 
   return 0;
@@ -566,7 +506,7 @@ find_ap(char *dir)
   for (i = last_used_map; i >= 0; --i) {
     am_node *mp = exported_ap[i];
     if (mp && (mp->am_flags & AMF_ROOT)) {
-      mp = find_ap2(dir, exported_ap[i]);
+      mp = find_ap_recursive(dir, exported_ap[i]);
       if (mp) {
 	return mp;
       }
@@ -602,22 +542,12 @@ find_mf(mntfs *mf)
  * the filehandles of the initial automount points.
  */
 am_nfs_fh *
-root_fh(char *dir)
+get_root_nfs_fh(char *dir)
 {
   static am_nfs_fh nfh;
-  am_node *mp = root_ap(dir, TRUE);
+  am_node *mp = get_root_ap(dir);
   if (mp) {
     mp_to_fh(mp, &nfh);
-    /*
-     * Patch up PID to match main server...
-     */
-    if (!foreground) {
-      long pid = getppid();
-      ((struct am_fh *) &nfh)->fhh_pid = pid;
-#ifdef DEBUG
-      dlog("root_fh substitutes pid %ld", (long) pid);
-#endif /* DEBUG */
-    }
     return &nfh;
   }
 
@@ -630,8 +560,8 @@ root_fh(char *dir)
 }
 
 
-am_node *
-root_ap(char *dir, int path)
+static am_node *
+get_root_ap(char *dir)
 {
   am_node *mp = find_ap(dir);
 
@@ -656,7 +586,7 @@ map_flush_srvr(fserver *fs)
     am_node *mp = exported_ap[i];
     if (mp && mp->am_mnt && mp->am_mnt->mf_server == fs) {
       plog(XLOG_INFO, "Flushed %s; dependent on %s", mp->am_path, fs->fs_host);
-      mp->am_ttl = clocktime();
+      mp->am_ttl = clocktime(NULL);
       done = 1;
     }
   }
@@ -672,11 +602,23 @@ map_flush_srvr(fserver *fs)
  * automount node to be automounted.
  */
 int
-mount_auto_node(char *dir, voidp arg)
+mount_auto_node(char *dir, opaque_t arg)
 {
   int error = 0;
+  am_node *mp = (am_node *) arg;
+  am_node *new_mp;
+
+  new_mp = mp->am_mnt->mf_ops->lookup_child(mp, dir, &error, VLOOK_CREATE);
+  if (new_mp && error < 0) {
+    /*
+     * We can't allow the fileid of the root node to change.
+     * Should be ok to force it to 1, always.
+     */
+    new_mp->am_gen = new_mp->am_fattr.na_fileid = 1;
+
+    new_mp = mp->am_mnt->mf_ops->mount_child(new_mp, &error);
+  }
 
-  (void) amfs_auto_ops.lookuppn((am_node *) arg, dir, &error, VLOOK_CREATE);
   if (error > 0) {
     errno = error;		/* XXX */
     plog(XLOG_ERROR, "Could not mount %s: %m", dir);
@@ -695,7 +637,7 @@ mount_exported(void)
   /*
    * Iterate over all the nodes to be started
    */
-  return root_keyiter((void (*)P((char *, voidp))) mount_auto_node, root_node);
+  return root_keyiter(mount_auto_node, root_node);
 }
 
 
@@ -734,7 +676,7 @@ make_root_node(void)
   /*
    * Mount the root
    */
-  root_mnt->mf_error = (*root_mnt->mf_ops->mount_fs) (root_node);
+  root_mnt->mf_error = root_mnt->mf_ops->mount_fs(root_node, root_mnt);
 }
 
 
@@ -749,143 +691,136 @@ umount_exported(void)
 
   for (i = last_used_map; i >= 0; --i) {
     am_node *mp = exported_ap[i];
+    mntfs *mf;
 
-    if (mp) {
-      mntfs *mf = mp->am_mnt;
-      if (mf->mf_flags & MFF_UNMOUNTING) {
-	/*
-	 * If this node is being unmounted then just ignore it.  However,
-	 * this could prevent amd from finishing if the unmount gets blocked
-	 * since the am_node will never be free'd.  am_unmounted needs
-	 * telling about this possibility. - XXX
-	 */
-	continue;
-      }
+    if (!mp)
+      continue;
 
-      if (mf && !(mf->mf_ops->fs_flags & FS_DIRECTORY)) {
-	/*
-	 * When shutting down this had better
-	 * look like a directory, otherwise it
-	 * can't be unmounted!
-	 */
-	mk_fattr(mp, NFDIR);
-      }
+    mf = mp->am_mnt;
+    if (mf->mf_flags & MFF_UNMOUNTING) {
+      /*
+       * If this node is being unmounted then just ignore it.  However,
+       * this could prevent amd from finishing if the unmount gets blocked
+       * since the am_node will never be free'd.  am_unmounted needs
+       * telling about this possibility. - XXX
+       */
+      continue;
+    }
 
-      if ((--immediate_abort < 0 &&
-	   !(mp->am_flags & AMF_ROOT) && mp->am_parent) ||
-	  (mf->mf_flags & MFF_RESTART)) {
+    if (!(mf->mf_fsflags & FS_DIRECTORY))
+      /*
+       * When shutting down this had better
+       * look like a directory, otherwise it
+       * can't be unmounted!
+       */
+      mk_fattr(&mp->am_fattr, NFDIR);
 
-	/*
-	 * Just throw this node away without bothering to unmount it.  If
-	 * the server is not known to be up then don't discard the mounted
-	 * on directory or Amd might hang...
-	 */
-	if (mf->mf_server &&
-	    (mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) != FSF_VALID)
-	  mf->mf_flags &= ~MFF_MKMNT;
-	if (gopt.flags & CFM_UNMOUNT_ON_EXIT) {
-	  plog(XLOG_INFO, "on-exit attempt to unmount %s", mf->mf_mount);
-	  unmount_node(mp);
-	}
-	am_unmounted(mp);
+    if ((--immediate_abort < 0 &&
+	 !(mp->am_flags & AMF_ROOT) && mp->am_parent) ||
+	(mf->mf_flags & MFF_RESTART)) {
 
-      } else {
+      /*
+       * Just throw this node away without bothering to unmount it.  If
+       * the server is not known to be up then don't discard the mounted
+       * on directory or Amd might hang...
+       */
+      if (mf->mf_server &&
+	  (mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) != FSF_VALID)
+	mf->mf_flags &= ~MFF_MKMNT;
+      if (gopt.flags & CFM_UNMOUNT_ON_EXIT || mp->am_flags & AMF_AUTOFS) {
+	plog(XLOG_INFO, "on-exit attempt to unmount %s", mf->mf_mount);
 	/*
-	 * Any other node gets forcibly timed out.
+	 * use unmount_mp, not unmount_node, so that unmounts be
+	 * backgrounded as needed.
 	 */
-	mp->am_flags &= ~AMF_NOTIMEOUT;
-	mp->am_mnt->mf_flags &= ~MFF_RSTKEEP;
-	mp->am_ttl = 0;
-	mp->am_timeo = 1;
-	mp->am_timeo_w = 0;
+	unmount_mp((opaque_t) mp);
+      } else {
+	am_unmounted(mp);
       }
+      exported_ap[i] = 0;
+    } else {
+      /*
+       * Any other node gets forcibly timed out.
+       */
+      mp->am_flags &= ~AMF_NOTIMEOUT;
+      mp->am_mnt->mf_flags &= ~MFF_RSTKEEP;
+      mp->am_ttl = 0;
+      mp->am_timeo = 1;
+      mp->am_timeo_w = 0;
     }
   }
 }
 
 
+/*
+ * Try to mount a file system.  Can be called directly or in a sub-process by run_task.
+ *
+ * Warning: this function might be running in a child process context.
+ * Don't expect any changes made here to survive in the parent amd process.
+ */
+int
+mount_node(opaque_t arg)
+{
+  am_node *mp = (am_node *) arg;
+  mntfs *mf = mp->am_mnt;
+  int error = 0;
+
+#ifdef HAVE_FS_AUTOFS
+  if (mp->am_flags & AMF_AUTOFS)
+    error = autofs_mount_fs(mp, mf);
+  else
+#endif /* HAVE_FS_AUTOFS */
+    if (!(mf->mf_flags & MFF_MOUNTED))
+      error = mf->mf_ops->mount_fs(mp, mf);
+
+  if (error > 0)
+    dlog("mount_node: call to mf_ops->mount_fs(%s) failed: %s",
+	 mp->am_path, strerror(error));
+  return error;
+}
+
+
 static int
-unmount_node(am_node *mp)
+unmount_node(opaque_t arg)
 {
+  am_node *mp = (am_node *) arg;
   mntfs *mf = mp->am_mnt;
-  int error;
+  int error = 0;
 
-  if ((mf->mf_flags & MFF_ERROR) || mf->mf_refc > 1) {
+  if (mf->mf_flags & MFF_ERROR) {
     /*
      * Just unlink
      */
-#ifdef DEBUG
-    if (mf->mf_flags & MFF_ERROR)
-      dlog("No-op unmount of error node %s", mf->mf_info);
-#endif /* DEBUG */
-    error = 0;
+    dlog("No-op unmount of error node %s", mf->mf_info);
   } else {
-#ifdef DEBUG
-    dlog("Unmounting %s (%s)", mf->mf_mount, mf->mf_info);
-#endif /* DEBUG */
-    error = (*mf->mf_ops->umount_fs) (mp);
+    dlog("Unmounting <%s> <%s> (%s) flags %x",
+	 mp->am_path, mf->mf_mount, mf->mf_info, mf->mf_flags);
+#ifdef HAVE_FS_AUTOFS
+    if (mp->am_flags & AMF_AUTOFS)
+      error = autofs_umount_fs(mp, mf);
+    else
+#endif /* HAVE_FS_AUTOFS */
+      if (mf->mf_refc == 1)
+	error = mf->mf_ops->umount_fs(mp, mf);
   }
 
+  /* do this again, it might have changed */
+  mf = mp->am_mnt;
   if (error) {
     errno = error;		/* XXX */
-#ifdef DEBUG
     dlog("%s: unmount: %m", mf->mf_mount);
-#endif /* DEBUG */
   }
 
   return error;
 }
 
 
-static int
-unmount_node_wrap(voidp vp)
-{
-  return unmount_node((am_node *) vp);
-
-  /*
-   * Below is the comment left from the old code
-   * that was dependent on the macro FLUSH_KERNEL_NAME_CACHE
-   */
-  /*
-   * This code should just say:
-   * return unmount_node((am_node *) vp);
-   *
-   * However...
-   * The kernel keeps a cached copy of filehandles,
-   * and doesn't ever uncache them (apparently).  So
-   * when Amd times out a node the kernel will have a
-   * stale filehandle.  When the kernel next uses the
-   * filehandle it gets ESTALE.
-   *
-   * The workaround:
-   * Arrange that when a node is removed an unlink or
-   * rmdir is done on that path so that the kernel
-   * cache is done.  Yes - yuck.
-   *
-   * This can all be removed (and the background
-   * unmount flag in amfs_link_ops) if/when the kernel does
-   * something smarter.
-   *
-   * If the unlink or rmdir failed then just log a warning,
-   * don't fail the unmount.  This can occur if the kernel
-   * client code decides that the object is still referenced
-   * and should be renamed rather than discarded.
-   *
-   * There is still a race condition here...
-   * if another process is trying to access the same
-   * filesystem at the time we get here, then
-   * it will block, since the MF_UNMOUNTING flag will
-   * be set.  That may, or may not, cause the entire
-   * system to deadlock.  Hmmm...
-   */
-}
-
-
 static void
-free_map_if_success(int rc, int term, voidp closure)
+free_map_if_success(int rc, int term, opaque_t arg)
 {
-  am_node *mp = (am_node *) closure;
+  am_node *mp = (am_node *) arg;
   mntfs *mf = mp->am_mnt;
+  wchan_t wchan = get_mntfs_wchan(mf);
 
   /*
    * Not unmounting any more
@@ -911,75 +846,95 @@ free_map_if_success(int rc, int term, voidp closure)
       am_unmounted(mp);
     }
 #endif /* DEBUG */
+#ifdef HAVE_FS_AUTOFS
+    if (mp->am_flags & AMF_AUTOFS)
+      autofs_umount_failed(mp);
+#endif /* HAVE_FS_AUTOFS */
     amd_stats.d_uerr++;
   } else if (rc) {
-    if (mf->mf_ops == &amfs_program_ops || rc == EBUSY) {
+    if (mf->mf_ops == &amfs_program_ops || rc == EBUSY)
       plog(XLOG_STATS, "\"%s\" on %s still active", mp->am_path, mf->mf_mount);
-    } else {
-      errno = rc;		/* XXX */
-      plog(XLOG_ERROR, "%s: unmount: %m", mp->am_path);
-    }
+    else
+      plog(XLOG_ERROR, "%s: unmount: %s", mp->am_path, strerror(rc));
+#ifdef HAVE_FS_AUTOFS
+    if (mf->mf_flags & MFF_IS_AUTOFS)
+      autofs_get_mp(mp);
+    if (mp->am_flags & AMF_AUTOFS)
+      autofs_umount_failed(mp);
+#endif /* HAVE_FS_AUTOFS */
     amd_stats.d_uerr++;
   } else {
     am_unmounted(mp);
   }
 
   /*
-   * Wakeup anything waiting for this mount
+   * Wakeup anything waiting for this unmount
    */
-  wakeup((voidp) mf);
+  wakeup(wchan);
 }
 
 
-static int
+int
 unmount_mp(am_node *mp)
 {
   int was_backgrounded = 0;
   mntfs *mf = mp->am_mnt;
 
 #ifdef notdef
-  plog(XLOG_INFO, "\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount);
+  plog(XLOG_INFO, "\"%s\" on %s timed out (flags 0x%x)",
+       mp->am_path, mp->am_mnt->mf_mount, (int) mf->mf_flags);
 #endif /* notdef */
 
-  if ((mf->mf_ops->fs_flags & FS_UBACKGROUND) &&
-      (mf->mf_flags & MFF_MOUNTED)) {
-    if (mf->mf_refc == 1 && !FSRV_ISUP(mf->mf_server)) {
-      /*
-       * Don't try to unmount from a server that is known to be down
-       */
-      if (!(mf->mf_flags & MFF_LOGDOWN)) {
-	/* Only log this once, otherwise gets a bit boring */
-	plog(XLOG_STATS, "file server %s is down - timeout of \"%s\" ignored", mf->mf_server->fs_host, mp->am_path);
-	mf->mf_flags |= MFF_LOGDOWN;
-      }
-    } else {
-      /* Clear logdown flag - since the server must be up */
-      mf->mf_flags &= ~MFF_LOGDOWN;
-#ifdef DEBUG
-      dlog("\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount);
-      /* dlog("Will background the unmount attempt"); */
-#endif /* DEBUG */
-      /*
-       * Note that we are unmounting this node
-       */
-      mf->mf_flags |= MFF_UNMOUNTING;
-      run_task(unmount_node_wrap, (voidp) mp,
-	       free_map_if_success, (voidp) mp);
-      was_backgrounded = 1;
-#ifdef DEBUG
-      dlog("unmount attempt backgrounded");
-#endif /* DEBUG */
+#ifndef MNT2_NFS_OPT_SYMTTL
+    /*
+     * This code is needed to defeat Solaris 2.4's (and newer) symlink
+     * values cache.  It forces the last-modified time of the symlink to be
+     * current.  It is not needed if the O/S has an nfs flag to turn off the
+     * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
+     *
+     * Additionally, Linux currently ignores the nt_useconds field,
+     * so we must update the nt_seconds field every time if clocktime(NULL)
+     * didn't return a new number of seconds.
+     */
+  if (mp->am_parent) {
+    time_t last = mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime.nt_seconds;
+    clocktime(&mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime);
+    /* defensive programming... can't we assert the above condition? */
+    if (last == (time_t) mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime.nt_seconds)
+      mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime.nt_seconds++;
+  }
+#endif /* not MNT2_NFS_OPT_SYMTTL */
+
+  if (mf->mf_refc == 1 && !FSRV_ISUP(mf->mf_server)) {
+    /*
+     * Don't try to unmount from a server that is known to be down
+     */
+    if (!(mf->mf_flags & MFF_LOGDOWN)) {
+      /* Only log this once, otherwise gets a bit boring */
+      plog(XLOG_STATS, "file server %s is down - timeout of \"%s\" ignored", mf->mf_server->fs_host, mp->am_path);
+      mf->mf_flags |= MFF_LOGDOWN;
     }
+    return 0;
+  }
+
+  dlog("\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount);
+  mf->mf_flags |= MFF_UNMOUNTING;
+
+#ifdef HAVE_FS_AUTOFS
+  if (mf->mf_flags & MFF_IS_AUTOFS)
+    autofs_release_mp(mp);
+#endif /* HAVE_FS_AUTOFS */
+
+  if ((mf->mf_fsflags & FS_UBACKGROUND) &&
+      (mf->mf_flags & MFF_MOUNTED)) {
+    dlog("Trying unmount in background");
+    run_task(unmount_node, (opaque_t) mp,
+	     free_map_if_success, (opaque_t) mp);
+    was_backgrounded = 1;
   } else {
-#ifdef DEBUG
-    dlog("\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount);
     dlog("Trying unmount in foreground");
-#endif /* DEBUG */
-    mf->mf_flags |= MFF_UNMOUNTING;
-    free_map_if_success(unmount_node(mp), 0, (voidp) mp);
-#ifdef DEBUG
+    free_map_if_success(unmount_node((opaque_t) mp), 0, (opaque_t) mp);
     dlog("unmount attempt done");
-#endif /* DEBUG */
   }
 
   return was_backgrounded;
@@ -987,25 +942,23 @@ unmount_mp(am_node *mp)
 
 
 void
-timeout_mp(voidp v)
+timeout_mp(opaque_t v)				/* argument not used?! */
 {
   int i;
   time_t t = NEVER;
-  time_t now = clocktime();
-  int backoff = NumChild / 4;
+  time_t now = clocktime(NULL);
+  int backoff = NumChildren / 4;
 
-#ifdef DEBUG
   dlog("Timing out automount points...");
-#endif /* DEBUG */
 
   for (i = last_used_map; i >= 0; --i) {
     am_node *mp = exported_ap[i];
     mntfs *mf;
 
     /*
-     * Just continue if nothing mounted, or can't be timed out.
+     * Just continue if nothing mounted
      */
-    if (!mp || (mp->am_flags & AMF_NOTIMEOUT))
+    if (!mp)
       continue;
 
     /*
@@ -1015,6 +968,17 @@ timeout_mp(voidp v)
     if (!mf)
       continue;
 
+#ifdef HAVE_FS_AUTOFS
+    if (mf->mf_flags & MFF_IS_AUTOFS && mp->am_autofs_ttl != NEVER) {
+      if (now >= mp->am_autofs_ttl)
+	autofs_timeout_mp(mp);
+      t = smallest_t(t, mp->am_autofs_ttl);
+    }
+#endif /* HAVE_FS_AUTOFS */
+
+    if (mp->am_flags & AMF_NOTIMEOUT)
+      continue;
+
     /*
      * Don't delete last reference to a restarted filesystem.
      */
@@ -1071,9 +1035,7 @@ timeout_mp(voidp v)
   }
 
   if (t == NEVER) {
-#ifdef DEBUG
     dlog("No further timeouts");
-#endif /* DEBUG */
     t = now + ONE_HOUR;
   }
 
@@ -1092,9 +1054,7 @@ timeout_mp(voidp v)
    */
   if ((int) amd_state >= (int) Finishing)
     t = now + 1;
-#ifdef DEBUG
   dlog("Next mount timeout in %lds", (long) (t - now));
-#endif /* DEBUG */
 
   timeout_mp_id = timeout(t - now, timeout_mp, 0);
 }
diff --git a/contrib/amd/amd/mapc.c b/contrib/amd/amd/mapc.c
index e27928b..d7efdbc 100644
--- a/contrib/amd/amd/mapc.c
+++ b/contrib/amd/amd/mapc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: mapc.c,v 1.5 1999/09/30 21:01:31 ezk Exp $
+ * File: am-utils/amd/mapc.c
  *
  */
 
@@ -85,8 +84,6 @@
 #define	MREC_PART	1
 #define	MREC_NONE	0
 
-#define MAX_CHAIN	2048
-
 static struct opt_tab mapc_opt[] =
 {
   {"all", MAPC_ALL},
@@ -201,12 +198,17 @@ extern int ndbm_search(mnt_map *, char *, char *, char **, time_t *);
 extern int ndbm_mtime(mnt_map *, char *, time_t *);
 #endif /* HAVE_MAP_NDBM */
 
+/* EXECUTABLE MAPS */
+#ifdef HAVE_MAP_EXEC
+extern int exec_init(mnt_map *, char *, time_t *);
+extern int exec_search(mnt_map *, char *, char *, char **, time_t *);
+#endif /* HAVE_MAP_EXEC */
+
 /* FILE MAPS */
 #ifdef HAVE_MAP_FILE
-extern int file_init(mnt_map *, char *, time_t *);
+extern int file_init_or_mtime(mnt_map *, char *, time_t *);
 extern int file_reload(mnt_map *, char *, add_fn *);
 extern int file_search(mnt_map *, char *, char *, char **, time_t *);
-extern int file_mtime(mnt_map *, char *, time_t *);
 #endif /* HAVE_MAP_FILE */
 
 
@@ -230,7 +232,7 @@ static map_type maptypes[] =
     NULL,			/* isup function */
     passwd_search,
     error_mtime,
-    MAPC_ALL
+    MAPC_INC
   },
 #endif /* HAVE_MAP_PASSWD */
 #ifdef HAVE_MAP_HESIOD
@@ -241,7 +243,7 @@ static map_type maptypes[] =
     hesiod_isup,		/* is Hesiod up or not? */
     hesiod_search,
     error_mtime,
-    MAPC_ALL
+    MAPC_INC
   },
 #endif /* HAVE_MAP_HESIOD */
 #ifdef HAVE_MAP_LDAP
@@ -252,7 +254,7 @@ static map_type maptypes[] =
     NULL,			/* isup function */
     amu_ldap_search,
     amu_ldap_mtime,
-    MAPC_ALL
+    MAPC_INC
   },
 #endif /* HAVE_MAP_LDAP */
 #ifdef HAVE_MAP_UNION
@@ -296,20 +298,31 @@ static map_type maptypes[] =
     NULL,			/* isup function */
     ndbm_search,
     ndbm_mtime,
-    MAPC_ALL
+    MAPC_INC
   },
 #endif /* HAVE_MAP_NDBM */
 #ifdef HAVE_MAP_FILE
   {
     "file",
-    file_init,
+    file_init_or_mtime,
     file_reload,
     NULL,			/* isup function */
     file_search,
-    file_mtime,
+    file_init_or_mtime,
     MAPC_ALL
   },
 #endif /* HAVE_MAP_FILE */
+#ifdef HAVE_MAP_EXEC
+  {
+    "exec",
+    exec_init,
+    error_reload,
+    NULL,			/* isup function */
+    exec_search,
+    error_mtime,
+    MAPC_INC
+  },
+#endif /* HAVE_MAP_EXEC */
   {
     "error",
     error_init,
@@ -337,16 +350,27 @@ kvhash_of(char *key)
 
 
 void
-mapc_showtypes(char *buf)
+mapc_showtypes(char *buf, size_t l)
 {
-  map_type *mt;
-  char *sep = "";
+  map_type *mt=NULL, *lastmt;
+  int linesize = 0, i;
 
+  i = sizeof(maptypes) / sizeof(maptypes[0]);
+  lastmt = maptypes + i;
   buf[0] = '\0';
-  for (mt = maptypes; mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]); mt++) {
-    strcat(buf, sep);
-    strcat(buf, mt->name);
-    sep = ", ";
+  for (mt = maptypes; mt < lastmt; mt++) {
+    xstrlcat(buf, mt->name, l);
+    if (mt == (lastmt-1))
+      break;	      /* if last one, don't do xstrlcat's that follows */
+    linesize += strlen(mt->name);
+    if (--i > 0) {
+      xstrlcat(buf, ", ", l);
+      linesize += 2;
+    }
+    if (linesize > 54) {
+      linesize = 0;
+      xstrlcat(buf, "\n\t\t ", l);
+    }
   }
 }
 
@@ -386,9 +410,7 @@ mapc_add_kv(mnt_map *m, char *key, char *val)
   regex_t re;
 #endif /* HAVE_REGEXEC */
 
-#ifdef DEBUG
   dlog("add_kv: %s -> %s", key, val);
-#endif /* DEBUG */
 
 #ifdef HAVE_REGEXEC
   if (MAPC_ISRE(m)) {
@@ -398,7 +420,7 @@ mapc_add_kv(mnt_map *m, char *key, char *val)
     /*
      * Make sure the string is bound to the start and end
      */
-    sprintf(pattern, "^%s$", key);
+    xsnprintf(pattern, sizeof(pattern), "^%s$", key);
     retval = regcomp(&re, pattern, REG_ICASE);
     if (retval != 0) {
       char errstr[256];
@@ -492,32 +514,30 @@ mapc_find_wildcard(mnt_map *m)
  * Do a map reload.
  * Attempt to reload without losing current data by switching the hashes
  * round.
+ * If reloading was needed and succeeded, return 1; else return 0.
  */
-static void
+static int
 mapc_reload_map(mnt_map *m)
 {
-  int error;
+  int error, ret = 0;
   kv *maphash[NKVHASH], *tmphash[NKVHASH];
+  time_t t;
+
+  error = (*m->mtime) (m, m->map_name, &t);
+  if (error) {
+    t = m->modify;
+  }
 
   /*
    * skip reloading maps that have not been modified, unless
    * amq -f was used (do_mapc_reload is 0)
    */
   if (m->reloads != 0 && do_mapc_reload != 0) {
-    time_t t;
-    error = (*m->mtime) (m, m->map_name, &t);
-    if (!error) {
-      if (t <= m->modify) {
+    if (t <= m->modify) {
       plog(XLOG_INFO, "reload of map %s is not needed (in sync)", m->map_name);
-#ifdef DEBUG
       dlog("map %s last load time is %d, last modify time is %d",
 	   m->map_name, (int) m->modify, (int) t);
-#endif /* DEBUG */
-      return;
-      } else {
-	/* reload of the map is needed, update map reload time */
-	m->modify = t;
-      }
+      return ret;
     }
   }
 
@@ -525,9 +545,7 @@ mapc_reload_map(mnt_map *m)
   memcpy((voidp) maphash, (voidp) m->kvhash, sizeof(m->kvhash));
   memset((voidp) m->kvhash, 0, sizeof(m->kvhash));
 
-#ifdef DEBUG
   dlog("calling map reload on %s", m->map_name);
-#endif /* DEBUG */
   error = (*m->reload) (m, m->map_name, mapc_add_kv);
   if (error) {
     if (m->reloads == 0)
@@ -547,15 +565,16 @@ mapc_reload_map(mnt_map *m)
     memcpy((voidp) m->kvhash, (voidp) maphash, sizeof(m->kvhash));
     mapc_clear(m);
     memcpy((voidp) m->kvhash, (voidp) tmphash, sizeof(m->kvhash));
+    m->modify = t;
+    ret = 1;
   }
   m->wildcard = 0;
 
-#ifdef DEBUG
   dlog("calling mapc_search for wildcard");
-#endif /* DEBUG */
   error = mapc_search(m, wildcard, &m->wildcard);
   if (error)
     m->wildcard = 0;
+  return ret;
 }
 
 
@@ -567,7 +586,7 @@ mapc_create(char *map, char *opt, const char *type)
 {
   mnt_map *m = ALLOC(struct mnt_map);
   map_type *mt;
-  time_t modify;
+  time_t modify = 0;
   int alloc = 0;
 
   cmdoption(opt, mapc_opt, &alloc);
@@ -584,7 +603,7 @@ mapc_create(char *map, char *opt, const char *type)
 	 mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]);
 	 mt++) {
       if (STREQ(type, mt->name)) {
-	plog(XLOG_INFO, "initializing amd conf map %s of type %s", map, type);
+	plog(XLOG_INFO, "initializing amd.conf map %s of type %s", map, type);
 	if ((*mt->init) (m, map, &modify) == 0) {
 	  break;
 	} else {
@@ -603,9 +622,7 @@ mapc_create(char *map, char *opt, const char *type)
     for (mt = maptypes;
 	 mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]);
 	 mt++) {
-#ifdef DEBUG
       dlog("trying to initialize map %s of type %s ...", map, mt->name);
-#endif /* DEBUG */
       if ((*mt->init) (m, map, &modify) == 0) {
 	break;
       }
@@ -652,9 +669,7 @@ mapc_create(char *map, char *opt, const char *type)
 #endif /* HAVE_REGEXEC */
   }
 
-#ifdef DEBUG
   dlog("Map for %s coming from maptype %s", map, mt->name);
-#endif /* DEBUG */
 
   m->alloc = alloc;
   m->reload = mt->reload;
@@ -667,6 +682,8 @@ mapc_create(char *map, char *opt, const char *type)
   m->refc = 1;
   m->wildcard = 0;
   m->reloads = 0;
+  /* Unfortunately with current code structure, this cannot be initialized here */
+  m->cfm = NULL;
 
   /*
    * synchronize cache with reality
@@ -732,7 +749,7 @@ mapc_find(char *map, char *opt, const char *maptype)
    * add it to the list of maps
    */
   ITER(m, mnt_map, &map_list_head)
-  if (STREQ(m->map_name, map))
+    if (STREQ(m->map_name, map))
       return mapc_dup(m);
   m = mapc_create(map, opt, maptype);
   ins_que(&m->hdr, &map_list_head);
@@ -745,9 +762,9 @@ mapc_find(char *map, char *opt, const char *maptype)
  * Free a map.
  */
 void
-mapc_free(voidp v)
+mapc_free(opaque_t arg)
 {
-  mnt_map *m = v;
+  mnt_map *m = (mnt_map *) arg;
 
   /*
    * Decrement the reference count.
@@ -780,6 +797,7 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
     plog(XLOG_ERROR, "Null map request for %s", key);
     return ENOENT;
   }
+
   if (m->flags & MAPC_SYNC) {
     /*
      * Get modify time...
@@ -787,7 +805,6 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
     time_t t;
     error = (*m->mtime) (m, m->map_name, &t);
     if (error || t > m->modify) {
-      m->modify = t;
       plog(XLOG_INFO, "Map %s is out of date", m->map_name);
       mapc_sync(m);
     }
@@ -883,12 +900,15 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
        * For example:
        * "src/gnu/gcc" -> "src / gnu / *" -> "src / *"
        */
-      strcpy(wildname, key);
+      xstrlcpy(wildname, key, sizeof(wildname));
       while (error && (subp = strrchr(wildname, '/'))) {
-	strcpy(subp, "/*");
-#ifdef DEBUG
+	/*
+	 * sizeof space left in subp is sizeof wildname minus what's left
+	 * after the strchr above returned a pointer inside wildname into
+	 * subp.
+	 */
+	xstrlcpy(subp, "/*", sizeof(wildname) - (subp - wildname));
 	dlog("mapc recurses on %s", wildname);
-#endif /* DEBUG */
 	error = mapc_meta_search(m, wildname, pval, MREC_PART);
 	if (error)
 	  *subp = 0;
@@ -917,25 +937,42 @@ mapc_search(mnt_map *m, char *key, char **pval)
 static void
 mapc_sync(mnt_map *m)
 {
-  if (m->alloc != MAPC_ROOT) {
+  int need_mtime_update = 0;
 
-    /* do not clear map if map service is down */
-    if (m->isup) {
-      if (!((*m->isup)(m, m->map_name))) {
-	plog(XLOG_ERROR, "mapc_sync: map %s is down: not clearing map", m->map_name);
-	return;
-      }
+  if (m->alloc == MAPC_ROOT)
+    return;			/* nothing to do */
+
+  /* do not clear map if map service is down */
+  if (m->isup) {
+    if (!((*m->isup)(m, m->map_name))) {
+      plog(XLOG_ERROR, "mapc_sync: map %s is down: not clearing map", m->map_name);
+      return;
     }
+  }
+
+  if (m->alloc >= MAPC_ALL) {
+    /* mapc_reload_map() always works */
+    need_mtime_update = mapc_reload_map(m);
+  } else {
+    mapc_clear(m);
+    /*
+     * Attempt to find the wildcard entry
+     */
+    mapc_find_wildcard(m);
+    need_mtime_update = 1;	/* because mapc_clear always works */
+  }
 
-    if (m->alloc >= MAPC_ALL) {
-      /* mapc_reload_map() always works */
-      mapc_reload_map(m);
+  /*
+   * To be safe, update the mtime of the mnt_map's own node, so that the
+   * kernel will flush all of its cached entries.
+   */
+  if (need_mtime_update && m->cfm) {
+    am_node *mp = find_ap(m->cfm->cfm_dir);
+    if (mp) {
+      clocktime(&mp->am_fattr.na_mtime);
     } else {
-      mapc_clear(m);
-      /*
-       * Attempt to find the wildcard entry
-       */
-      mapc_find_wildcard(m);
+      plog(XLOG_ERROR, "cannot find map %s to update its mtime",
+	   m->cfm->cfm_dir);
     }
   }
 }
@@ -972,7 +1009,7 @@ mapc_reload(void)
 static int
 root_init(mnt_map *m, char *map, time_t *tp)
 {
-  *tp = clocktime();
+  *tp = clocktime(NULL);
   return STREQ(map, ROOT_MAP) ? 0 : ENOENT;
 }
 
@@ -1007,37 +1044,39 @@ root_newmap(const char *dir, const char *opts, const char *map, const cf_map_t *
 
   if (cfm) {
     if (map) {
-      sprintf(str, "cache:=mapdefault;type:=%s;fs:=\"%s\"",
-	      cfm->cfm_flags & CFM_MOUNT_TYPE_AUTOFS ? "autofs" : "toplvl",
-	      get_full_path(map, cfm->cfm_search_path, cfm->cfm_type));
+      xsnprintf(str, sizeof(str),
+		"cache:=mapdefault;type:=toplvl;mount_type:=%s;fs:=\"%s\"",
+		cfm->cfm_flags & CFM_MOUNT_TYPE_AUTOFS ? "autofs" : "nfs",
+		get_full_path(map, cfm->cfm_search_path, cfm->cfm_type));
       if (opts && opts[0] != '\0') {
-	strcat(str, ";");
-	strcat(str, opts);
+	xstrlcat(str, ";", sizeof(str));
+	xstrlcat(str, opts, sizeof(str));
       }
       if (cfm->cfm_flags & CFM_BROWSABLE_DIRS_FULL)
-	strcat(str, ";opts:=rw,fullybrowsable");
+	xstrlcat(str, ";opts:=rw,fullybrowsable", sizeof(str));
       if (cfm->cfm_flags & CFM_BROWSABLE_DIRS)
-	strcat(str, ";opts:=rw,browsable");
+	xstrlcat(str, ";opts:=rw,browsable", sizeof(str));
       if (cfm->cfm_type) {
-	strcat(str, ";maptype:=");
-	strcat(str, cfm->cfm_type);
+	xstrlcat(str, ";maptype:=", sizeof(str));
+	xstrlcat(str, cfm->cfm_type, sizeof(str));
       }
     } else {
-      strcpy(str, opts);
+      xstrlcpy(str, opts, sizeof(str));
     }
   } else {
     if (map)
-      sprintf(str, "cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s",
-	      map, opts ? opts : "");
+      xsnprintf(str, sizeof(str),
+		"cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s",
+		map, opts ? opts : "");
     else
-      strcpy(str, opts);
+      xstrlcpy(str, opts, sizeof(str));
   }
   mapc_repl_kv(root_map, strdup((char *)dir), strdup(str));
 }
 
 
 int
-mapc_keyiter(mnt_map *m, void (*fn) (char *, voidp), voidp arg)
+mapc_keyiter(mnt_map *m, key_fun *fn, opaque_t arg)
 {
   int i;
   int c = 0;
@@ -1057,10 +1096,10 @@ mapc_keyiter(mnt_map *m, void (*fn) (char *, voidp), voidp arg)
 
 /*
  * Iterate on the root map and call (*fn)() on the key of all the nodes.
- * Finally throw away the root map.
+ * Returns the number of entries in the root map.
  */
 int
-root_keyiter(void (*fn)(char *, voidp), voidp arg)
+root_keyiter(key_fun *fn, opaque_t arg)
 {
   if (root_map) {
     int c = mapc_keyiter(root_map, fn, arg);
@@ -1072,126 +1111,6 @@ root_keyiter(void (*fn)(char *, voidp), voidp arg)
 
 
 /*
- * Was: NEW_TOPLVL_READDIR
- * Search a chain for an entry with some name.
- * -Erez Zadok <ezk@cs.columbia.edu>
- */
-static int
-key_already_in_chain(char *keyname, const nfsentry *chain)
-{
-  const nfsentry *tmpchain = chain;
-
-  while (tmpchain) {
-    if (keyname && tmpchain->ne_name && STREQ(keyname, tmpchain->ne_name))
-        return 1;
-    tmpchain = tmpchain->ne_nextentry;
-  }
-
-  return 0;
-}
-
-
-/*
- * Create a chain of entries which are not linked.
- * -Erez Zadok <ezk@cs.columbia.edu>
- */
-nfsentry *
-make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable)
-{
-  static u_int last_cookie = (u_int) 2;	/* monotonically increasing */
-  static nfsentry chain[MAX_CHAIN];
-  static int max_entries = MAX_CHAIN;
-  char *key;
-  int num_entries = 0, preflen = 0, i;
-  nfsentry *retval = (nfsentry *) NULL;
-  mntfs *mf;
-  mnt_map *mmp;
-
-  if (!mp) {
-    plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)");
-    return retval;
-  }
-  mf = mp->am_mnt;
-  if (!mf) {
-    plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt is (NULL)");
-    return retval;
-  }
-  mmp = (mnt_map *) mf->mf_private;
-  if (!mmp) {
-    plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt->mf_private is (NULL)");
-    return retval;
-  }
-
-  /* iterate over keys */
-  for (i = 0; i < NKVHASH; i++) {
-    kv *k;
-    for (k = mmp->kvhash[i]; k ; k = k->next) {
-
-      /*
-       * Skip unwanted entries which are either not real entries or
-       * very difficult to interpret (wildcards...)  This test needs
-       * lots of improvement.  Any takers?
-       */
-      key = k->key;
-      if (!key)
-	continue;
-
-      /* Skip '*' */
-      if (!fully_browsable && strchr(key, '*'))
-	continue;
-
-      /*
-       * If the map has a prefix-string then check if the key starts with
-       * this * string, and if it does, skip over this prefix.
-       */
-      if (preflen) {
-	if (!NSTREQ(key, mp->am_pref, preflen))
-	  continue;
-	key += preflen;
-      }
-
-      /* no more '/' are allowed, unless browsable_dirs=full was used */
-      if (!fully_browsable && strchr(key, '/'))
-	continue;
-
-      /* no duplicates allowed */
-      if (key_already_in_chain(key, current_chain))
-	continue;
-
-      /* fill in a cell and link the entry */
-      if (num_entries >= max_entries) {
-	/* out of space */
-	plog(XLOG_DEBUG, "make_entry_chain: no more space in chain");
-	if (num_entries > 0) {
-	  chain[num_entries - 1].ne_nextentry = 0;
-	  retval = &chain[0];
-	}
-	return retval;
-      }
-
-      /* we have space.  put entry in next cell */
-      ++last_cookie;
-      chain[num_entries].ne_fileid = (u_int) last_cookie;
-      *(u_int *) chain[num_entries].ne_cookie = (u_int) last_cookie;
-      chain[num_entries].ne_name = key;
-      if (num_entries < max_entries - 1) {	/* link to next one */
-	chain[num_entries].ne_nextentry = &chain[num_entries + 1];
-      }
-      ++num_entries;
-    } /* end of "while (k)" */
-  } /* end of "for (i ... NKVHASH ..." */
-
-  /* terminate chain */
-  if (num_entries > 0) {
-    chain[num_entries - 1].ne_nextentry = 0;
-    retval = &chain[0];
-  }
-
-  return retval;
-}
-
-
-/*
  * Error map
  */
 static int
@@ -1255,15 +1174,15 @@ get_full_path(const char *map, const char *path, const char *type)
     return map;
 
   /* now break path into components, and search in each */
-  strcpy(component, path);
+  xstrlcpy(component, path, sizeof(component));
 
   str = strtok(component, ":");
   do {
-    strcpy(full_path, str);
+    xstrlcpy(full_path, str, sizeof(full_path));
     len = strlen(full_path);
     if (full_path[len - 1] != '/') /* add trailing "/" if needed */
-      strcat(full_path, "/");
-    strcat(full_path, map);
+      xstrlcat(full_path, "/", sizeof(full_path));
+    xstrlcat(full_path, map, sizeof(full_path));
     if (access(full_path, R_OK) == 0)
       return full_path;
     str = strtok(NULL, ":");
diff --git a/contrib/amd/amd/mntfs.c b/contrib/amd/amd/mntfs.c
index 7e67959..6021838 100644
--- a/contrib/amd/amd/mntfs.c
+++ b/contrib/amd/amd/mntfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: mntfs.c,v 1.2 1999/01/10 21:53:47 ezk Exp $
+ * File: am-utils/amd/mntfs.c
  *
  */
 
@@ -71,12 +70,14 @@ static void
 init_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
 {
   mf->mf_ops = ops;
+  mf->mf_fsflags = ops->nfs_fs_flags;
   mf->mf_fo = mo;
   mf->mf_mount = strdup(mp);
   mf->mf_info = strdup(info);
   mf->mf_auto = strdup(auto_opts);
   mf->mf_mopts = strdup(mopts);
   mf->mf_remopts = strdup(remopts);
+  mf->mf_loopdev = NULL;
   mf->mf_refc = 1;
   mf->mf_flags = 0;
   mf->mf_error = -1;
@@ -104,17 +105,25 @@ alloc_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, cha
 }
 
 
+/* find a matching mntfs in our list */
 mntfs *
-find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
+locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
 {
   mntfs *mf;
 
-#ifdef DEBUG
-  dlog("Locating mntfs reference to %s", mp);
-#endif /* DEBUG */
+  dlog("Locating mntfs reference to (%s,%s)", mp, info);
 
   ITER(mf, mntfs, &mfhead) {
-    if (STREQ(mf->mf_mount, mp)) {
+    /*
+     * For backwards compatibility purposes, we treat already-mounted
+     * filesystems differently and only require a match of their mount point,
+     * not of their server info. After all, there is little we can do if
+     * the user asks us to mount two different things onto the same mount: one
+     * will always cover the other one.
+     */
+    if (STREQ(mf->mf_mount, mp) &&
+	((mf->mf_flags & MFF_MOUNTED && !(mf->mf_fsflags & FS_DIRECT))
+	 || (STREQ(mf->mf_info, info) && mf->mf_ops == ops))) {
       /*
        * Handle cases where error ops are involved
        */
@@ -125,35 +134,32 @@ find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char
 	 */
 	if (mf->mf_ops != &amfs_error_ops)
 	  continue;
-	else
-	  return dup_mntfs(mf);
-      } else {			/* ops != &amfs_error_ops */
-	/*
-	 * If the existing ops are amfs_error_ops
-	 * then continue...
-	 */
-	if (mf->mf_ops == &amfs_error_ops)
-	  continue;
+	return dup_mntfs(mf);
       }
 
-      if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) {
+      dlog("mf->mf_flags = %#x", mf->mf_flags);
+      mf->mf_fo = mo;
+      if ((mf->mf_flags & MFF_RESTART) && amd_state < Finishing) {
 	/*
 	 * Restart a previously mounted filesystem.
 	 */
-	mntfs *mf2 = alloc_mntfs(&amfs_inherit_ops, mo, mp, info, auto_opts, mopts, remopts);
-#ifdef DEBUG
 	dlog("Restarting filesystem %s", mf->mf_mount);
-#endif /* DEBUG */
 
 	/*
-	 * Remember who we are restarting
+	 * If we are restarting an amd internal filesystem,
+	 * we need to initialize it a bit.
+	 *
+	 * We know it's internal because it is marked as toplvl.
 	 */
-	mf2->mf_private = (voidp) dup_mntfs(mf);
-	mf2->mf_prfree = free_mntfs;
-	return mf2;
+	if (mf->mf_ops == &amfs_toplvl_ops) {
+	  mf->mf_ops = ops;
+	  mf->mf_info = strealloc(mf->mf_info, info);
+	  ops->mounted(mf);	/* XXX: not right, but will do for now */
+	}
+
+	return mf;
       }
 
-      mf->mf_fo = mo;
       if (!(mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))) {
 	fserver *fs;
 	mf->mf_flags &= ~MFF_ERROR;
@@ -164,7 +170,7 @@ find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char
 	mf->mf_info = strealloc(mf->mf_info, info);
 
 	if (mf->mf_private && mf->mf_prfree) {
-	  (*mf->mf_prfree) (mf->mf_private);
+	  mf->mf_prfree(mf->mf_private);
 	  mf->mf_private = 0;
 	}
 
@@ -174,8 +180,20 @@ find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char
 	mf->mf_server = fs;
       }
       return dup_mntfs(mf);
-    }
-  }
+    } /* end of "if (STREQ(mf-> ..." */
+  } /* end of ITER */
+
+  return 0;
+}
+
+
+/* find a matching mntfs in our list, create a new one if none is found */
+mntfs *
+find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
+{
+  mntfs *mf = locate_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
+  if (mf)
+    return mf;
 
   return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
 }
@@ -189,7 +207,7 @@ new_mntfs(void)
 
 
 static void
-uninit_mntfs(mntfs *mf, int rmd)
+uninit_mntfs(mntfs *mf)
 {
   if (mf->mf_auto)
     XFREE(mf->mf_auto);
@@ -202,12 +220,6 @@ uninit_mntfs(mntfs *mf, int rmd)
   if (mf->mf_private && mf->mf_prfree)
     (*mf->mf_prfree) (mf->mf_private);
 
-  /*
-   * Clean up any directories that were made
-   */
-  if (rmd && (mf->mf_flags & MFF_MKMNT))
-    rmdirs(mf->mf_mount);
-  /* free mf_mount _AFTER_ removing the directories */
   if (mf->mf_mount)
     XFREE(mf->mf_mount);
 
@@ -237,7 +249,7 @@ discard_mntfs(voidp v)
   /*
    * Free memory
    */
-  uninit_mntfs(mf, TRUE);
+  uninit_mntfs(mf);
   XFREE(mf);
 
   --mntfs_allocated;
@@ -260,9 +272,30 @@ flush_mntfs(void)
 
 
 void
-free_mntfs(voidp v)
+free_mntfs(opaque_t arg)
 {
-  mntfs *mf = v;
+  mntfs *mf = (mntfs *) arg;
+
+  dlog("free_mntfs <%s> type %s mf_refc %d flags %x",
+       mf->mf_mount, mf->mf_ops->fs_type, mf->mf_refc, mf->mf_flags);
+
+  /*
+   * We shouldn't ever be called to free something that has
+   * a non-positive refcount.  Something is badly wrong if
+   * we have been!  Ignore the request for now...
+   */
+  if (mf->mf_refc <= 0) {
+    plog(XLOG_ERROR, "IGNORING free_mntfs for <%s>: refc %d, flags %x (bug?)",
+         mf->mf_mount, mf->mf_refc, mf->mf_flags);
+    return;
+  }
+
+  /* don't discard last reference of a restarted/kept mntfs */
+  if (mf->mf_refc == 1 && mf->mf_flags & MFF_RSTKEEP) {
+    plog(XLOG_ERROR, "IGNORING free_mntfs for <%s>: refc %d, flags %x (restarted)",
+         mf->mf_mount, mf->mf_refc, mf->mf_flags);
+    return;
+  }
 
   if (--mf->mf_refc == 0) {
     if (mf->mf_flags & MFF_MOUNTED) {
@@ -281,15 +314,12 @@ free_mntfs(voidp v)
 	   mf->mf_ops->fs_type, mf->mf_mount);
     }
 
-    if (mf->mf_ops->fs_flags & FS_DISCARD) {
-#ifdef DEBUG
+    if (mf->mf_fsflags & FS_DISCARD) {
       dlog("Immediately discarding mntfs for %s", mf->mf_mount);
-#endif /* DEBUG */
       discard_mntfs(mf);
 
     } else {
 
-#ifdef DEBUG
       if (mf->mf_flags & MFF_RESTART) {
 	dlog("Discarding remount hook for %s", mf->mf_mount);
       } else {
@@ -298,7 +328,6 @@ free_mntfs(voidp v)
       }
       if (mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))
 	dlog("mntfs reference for %s still active", mf->mf_mount);
-#endif /* DEBUG */
       mf->mf_cid = timeout(ALLOWED_MOUNT_TIME, discard_mntfs, (voidp) mf);
     }
   }
@@ -310,7 +339,9 @@ realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *a
 {
   mntfs *mf2;
 
-  if (mf->mf_refc == 1 && mf->mf_ops == &amfs_inherit_ops && STREQ(mf->mf_mount, mp)) {
+  if (mf->mf_refc == 1 &&
+      mf->mf_flags & MFF_RESTART &&
+      STREQ(mf->mf_mount, mp)) {
     /*
      * If we are inheriting then just return
      * the same node...
diff --git a/contrib/amd/amd/nfs_prot_svc.c b/contrib/amd/amd/nfs_prot_svc.c
index 7c0048b..0dd6992 100644
--- a/contrib/amd/amd/nfs_prot_svc.c
+++ b/contrib/amd/amd/nfs_prot_svc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: nfs_prot_svc.c,v 1.4 1999/08/22 21:12:30 ezk Exp $
+ * File: am-utils/amd/nfs_prot_svc.c
  *
  */
 
@@ -50,26 +49,26 @@
 
 /* external definitions */
 extern voidp nfsproc_null_2_svc(voidp, struct svc_req *);
-extern nfsattrstat * nfsproc_getattr_2_svc(am_nfs_fh *, struct svc_req *);
-extern nfsattrstat * nfsproc_setattr_2_svc(nfssattrargs *, struct svc_req *);
+extern nfsattrstat *nfsproc_getattr_2_svc(am_nfs_fh *, struct svc_req *);
+extern nfsattrstat *nfsproc_setattr_2_svc(nfssattrargs *, struct svc_req *);
 extern voidp nfsproc_root_2_svc(voidp, struct svc_req *);
-extern nfsdiropres * nfsproc_lookup_2_svc(nfsdiropargs *, struct svc_req *);
-extern nfsreadlinkres * nfsproc_readlink_2_svc(am_nfs_fh *, struct svc_req *);
-extern nfsreadres * nfsproc_read_2_svc(nfsreadargs *, struct svc_req *);
+extern nfsdiropres *nfsproc_lookup_2_svc(nfsdiropargs *, struct svc_req *);
+extern nfsreadlinkres *nfsproc_readlink_2_svc(am_nfs_fh *, struct svc_req *);
+extern nfsreadres *nfsproc_read_2_svc(nfsreadargs *, struct svc_req *);
 extern voidp nfsproc_writecache_2_svc(voidp, struct svc_req *);
-extern nfsattrstat * nfsproc_write_2_svc(nfswriteargs *, struct svc_req *);
-extern nfsdiropres * nfsproc_create_2_svc(nfscreateargs *, struct svc_req *);
-extern nfsstat * nfsproc_remove_2_svc(nfsdiropargs *, struct svc_req *);
-extern nfsstat * nfsproc_rename_2_svc(nfsrenameargs *, struct svc_req *);
-extern nfsstat * nfsproc_link_2_svc(nfslinkargs *, struct svc_req *);
-extern nfsstat * nfsproc_symlink_2_svc(nfssymlinkargs *, struct svc_req *);
-extern nfsdiropres * nfsproc_mkdir_2_svc(nfscreateargs *, struct svc_req *);
-extern nfsstat * nfsproc_rmdir_2_svc(nfsdiropargs *, struct svc_req *);
-extern nfsreaddirres * nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *);
-extern nfsstatfsres * nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
+extern nfsattrstat *nfsproc_write_2_svc(nfswriteargs *, struct svc_req *);
+extern nfsdiropres *nfsproc_create_2_svc(nfscreateargs *, struct svc_req *);
+extern nfsstat *nfsproc_remove_2_svc(nfsdiropargs *, struct svc_req *);
+extern nfsstat *nfsproc_rename_2_svc(nfsrenameargs *, struct svc_req *);
+extern nfsstat *nfsproc_link_2_svc(nfslinkargs *, struct svc_req *);
+extern nfsstat *nfsproc_symlink_2_svc(nfssymlinkargs *, struct svc_req *);
+extern nfsdiropres *nfsproc_mkdir_2_svc(nfscreateargs *, struct svc_req *);
+extern nfsstat *nfsproc_rmdir_2_svc(nfsdiropargs *, struct svc_req *);
+extern nfsreaddirres *nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *);
+extern nfsstatfsres *nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
 
 /* global variables */
-SVCXPRT *nfs_program_2_transp;
+SVCXPRT *current_transp;
 
 /* typedefs */
 typedef char *(*nfssvcproc_t)(voidp, struct svc_req *);
@@ -98,29 +97,60 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
   char *result;
   xdrproc_t xdr_argument, xdr_result;
   nfssvcproc_t local;
+
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+  /*
+   * On TLI systems we don't use an INET network type, but a "ticlts" (see
+   * /etc/netconfig and conf/transp_tli.c:create_nfs_service).  This means
+   * that packets could only come from the loopback interface, and we don't
+   * need to check them and filter possibly spoofed packets.  Therefore we
+   * only need to check if the UID caller is correct.
+   */
+# ifdef HAVE___RPC_GET_LOCAL_UID
+  uid_t u;
+  /* extern definition for an internal libnsl function */
+  extern int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid);
+  if (__rpc_get_local_uid(transp, &u) >= 0  &&  u != 0) {
+    plog(XLOG_WARNING, "ignoring request from UID %ld, must be 0", (long) u);
+    return;
+  }
+# else /* not HAVE___RPC_GET_LOCAL_UID */
+  dlog("cannot verify local uid for rpc request");
+# endif /* HAVE___RPC_GET_LOCAL_UID */
+#else /* not HAVE_TRANPORT_TYPE_TLI */
   struct sockaddr_in *sinp;
   char dq[20], dq2[28];
-
   sinp = amu_svc_getcaller(rqstp->rq_xprt);
-#ifdef MNT2_NFS_OPT_RESVPORT
+# ifdef MNT2_NFS_OPT_RESVPORT
   /* Verify that the request comes from a reserved port */
-  if (ntohs(sinp->sin_port) >= IPPORT_RESERVED) {
+  if (sinp &&
+      ntohs(sinp->sin_port) >= IPPORT_RESERVED &&
+      !(gopt.flags & CFM_NFS_INSECURE_PORT)) {
     plog(XLOG_WARNING, "ignoring request from %s:%u, port not reserved",
-	 inet_dquad(dq, sinp->sin_addr.s_addr),
+	 inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
 	 ntohs(sinp->sin_port));
     return;
   }
-#endif /* MNT2_NFS_OPT_RESVPORT */
+# endif /* MNT2_NFS_OPT_RESVPORT */
   /* if the address does not match, ignore the request */
-  if (sinp->sin_addr.s_addr && sinp->sin_addr.s_addr != myipaddr.s_addr) {
-    plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s",
-	 inet_dquad(dq, sinp->sin_addr.s_addr),
-	 ntohs(sinp->sin_port),
-	 inet_dquad(dq2, myipaddr.s_addr));
-    return;
+  if (sinp && (sinp->sin_addr.s_addr != myipaddr.s_addr)) {
+    if (gopt.flags & CFM_NFS_ANY_INTERFACE) {
+      if (!is_interface_local(sinp->sin_addr.s_addr)) {
+	plog(XLOG_WARNING, "ignoring request from %s:%u, not a local interface",
+	     inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
+	     ntohs(sinp->sin_port));
+      }
+    } else {
+      plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s",
+	   inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
+	   ntohs(sinp->sin_port),
+	   inet_dquad(dq2, sizeof(dq2), myipaddr.s_addr));
+      return;
+    }
   }
+#endif /* not HAVE_TRANPORT_TYPE_TLI */
 
-  nfs_program_2_transp = NULL;
+  current_transp = NULL;
 
   switch (rqstp->rq_proc) {
 
@@ -157,7 +187,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
      * be stored in the am_node structure and later used for
      * quick_reply().
      */
-    nfs_program_2_transp = transp;
+    current_transp = transp;
     break;
 
   case NFSPROC_READLINK:
@@ -255,7 +285,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
   }
   result = (*local) (&argument, rqstp);
 
-  nfs_program_2_transp = NULL;
+  current_transp = NULL;
 
   if (result != NULL && !svc_sendreply(transp,
 				       (XDRPROC_T_TYPE) xdr_result,
diff --git a/contrib/amd/amd/nfs_start.c b/contrib/amd/amd/nfs_start.c
index 48d6f06..f6aba94 100644
--- a/contrib/amd/amd/nfs_start.c
+++ b/contrib/amd/amd/nfs_start.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: nfs_start.c,v 1.4 1999/02/04 07:24:16 ezk Exp $
+ * File: am-utils/amd/nfs_start.c
  *
  */
 
@@ -52,14 +51,8 @@
 # define SELECT_MAXWAIT 16
 #endif /* not SELECT_MAXWAIT */
 
-SVCXPRT *nfsxprt;
-u_short nfs_port;
-
-#ifdef HAVE_FS_AUTOFS
-SVCXPRT *autofsxprt = NULL;
-u_short autofs_port = 0;
-int amd_use_autofs = 0;
-#endif /* HAVE_FS_AUTOFS */
+SVCXPRT *nfsxprt = NULL;
+u_short nfs_port = 0;
 
 #ifndef HAVE_SIGACTION
 # define MASKED_SIGS	(sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
@@ -89,7 +82,7 @@ checkup(void)
 #ifdef HAVE_GETPAGESIZE
     dlog("%#lx bytes of memory allocated; total is %#lx (%ld pages)",
 	 (long) (next_mem - max_mem), (unsigned long) next_mem,
-	 ((long) next_mem + getpagesize() - 1) / getpagesize());
+	 ((long) next_mem + getpagesize() - 1) / (long) getpagesize());
 #else /* not HAVE_GETPAGESIZE */
     dlog("%#lx bytes of memory allocated; total is %#lx",
 	 (long) (next_mem - max_mem), (unsigned long) next_mem);
@@ -98,7 +91,9 @@ checkup(void)
 
   }
 }
-#endif /* DEBUG */
+#else  /* not DEBUG */
+#define checkup()
+#endif /* not DEBUG */
 
 
 static int
@@ -127,10 +122,6 @@ do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp)
   } else {
     select_intr_valid = 1;
     /*
-     * Invalidate the current clock value
-     */
-    clock_valid = 0;
-    /*
      * Allow interrupts.  If a signal
      * occurs, then it will cause a longjmp
      * up above.
@@ -157,9 +148,9 @@ do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp)
   /*
    * Perhaps reload the cache?
    */
-  if (do_mapc_reload < clocktime()) {
+  if (do_mapc_reload < clocktime(NULL)) {
     mapc_reload();
-    do_mapc_reload = clocktime() + ONE_HOUR;
+    do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
   }
   return nsel;
 }
@@ -174,26 +165,17 @@ rpc_pending_now(void)
 {
   struct timeval tvv;
   int nsel;
-#ifdef FD_SET
   fd_set readfds;
 
   FD_ZERO(&readfds);
   FD_SET(fwd_sock, &readfds);
-#else /* not FD_SET */
-  int readfds = (1 << fwd_sock);
-#endif /* not FD_SET */
 
   tvv.tv_sec = tvv.tv_usec = 0;
   nsel = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &tvv);
   if (nsel < 1)
     return (0);
-#ifdef FD_SET
   if (FD_ISSET(fwd_sock, &readfds))
     return (1);
-#else /* not FD_SET */
-  if (readfds & (1 << fwd_sock))
-    return (1);
-#endif /* not FD_SET */
 
   return (0);
 }
@@ -209,7 +191,7 @@ run_rpc(void)
   int smask = sigblock(MASKED_SIGS);
 #endif /* not HAVE_SIGACTION */
 
-  next_softclock = clocktime();
+  next_softclock = clocktime(NULL);
 
   amd_state = Run;
 
@@ -222,31 +204,27 @@ run_rpc(void)
     struct timeval tvv;
     int nsel;
     time_t now;
-#ifdef HAVE_SVC_GETREQSET
     fd_set readfds;
 
+#ifdef HAVE_SVC_GETREQSET
     memmove(&readfds, &svc_fdset, sizeof(svc_fdset));
-    FD_SET(fwd_sock, &readfds);
 #else /* not HAVE_SVC_GETREQSET */
-# ifdef FD_SET
-    fd_set readfds;
     FD_ZERO(&readfds);
+# ifdef HAVE_FD_SET_FDS_BITS
     readfds.fds_bits[0] = svc_fds;
-    FD_SET(fwd_sock, &readfds);
-# else /* not FD_SET */
-    int readfds = svc_fds | (1 << fwd_sock);
-# endif /* not FD_SET */
+# else /* not HAVE_FD_SET_FDS_BITS */
+    readfds = svc_fds;
+# endif  /* not HAVE_FD_SET_FDS_BITS */
 #endif /* not HAVE_SVC_GETREQSET */
+    FD_SET(fwd_sock, &readfds);
 
-#ifdef DEBUG
     checkup();
-#endif /* DEBUG */
 
     /*
      * If the full timeout code is not called,
      * then recompute the time delta manually.
      */
-    now = clocktime();
+    now = clocktime(NULL);
 
     if (next_softclock <= now) {
       if (amd_state == Finishing)
@@ -257,32 +235,33 @@ run_rpc(void)
     }
     tvv.tv_usec = 0;
 
-    if (amd_state == Finishing && last_used_map < 0) {
+    if (amd_state == Finishing && get_exported_ap(0) == NULL) {
       flush_mntfs();
       amd_state = Quit;
       break;
     }
+
+#ifdef HAVE_FS_AUTOFS
+    autofs_add_fdset(&readfds);
+#endif /* HAVE_FS_AUTOFS */
+
     if (tvv.tv_sec <= 0)
       tvv.tv_sec = SELECT_MAXWAIT;
-#ifdef DEBUG
     if (tvv.tv_sec) {
       dlog("Select waits for %ds", (int) tvv.tv_sec);
     } else {
       dlog("Select waits for Godot");
     }
-#endif /* DEBUG */
 
     nsel = do_select(smask, FD_SETSIZE, &readfds, &tvv);
 
     switch (nsel) {
     case -1:
       if (errno == EINTR) {
-#ifdef DEBUG
 	dlog("select interrupted");
-#endif /* DEBUG */
 	continue;
       }
-      perror("select");
+      plog(XLOG_ERROR, "select: %m");
       break;
 
     case 0:
@@ -290,22 +269,22 @@ run_rpc(void)
 
     default:
       /*
-       * Read all pending NFS responses at once to avoid having responses.
+       * Read all pending NFS responses at once to avoid having responses
        * queue up as a consequence of retransmissions.
        */
-#ifdef FD_SET
       if (FD_ISSET(fwd_sock, &readfds)) {
 	FD_CLR(fwd_sock, &readfds);
-#else /* not FD_SET */
-      if (readfds & (1 << fwd_sock)) {
-	readfds &= ~(1 << fwd_sock);
-#endif /* not FD_SET */
 	--nsel;
 	do {
 	  fwd_reply();
 	} while (rpc_pending_now() > 0);
       }
 
+#ifdef HAVE_FS_AUTOFS
+      if (nsel)
+	nsel = autofs_handle_fdset(&readfds, nsel);
+#endif /* HAVE_FS_AUTOFS */
+
       if (nsel) {
 	/*
 	 * Anything left must be a normal
@@ -314,11 +293,11 @@ run_rpc(void)
 #ifdef HAVE_SVC_GETREQSET
 	svc_getreqset(&readfds);
 #else /* not HAVE_SVC_GETREQSET */
-# ifdef FD_SET
+# ifdef HAVE_FD_SET_FDS_BITS
 	svc_getreq(readfds.fds_bits[0]);
-# else /* not FD_SET */
+# else /* not HAVE_FD_SET_FDS_BITS */
 	svc_getreq(readfds);
-# endif /* not FD_SET */
+# endif /* not HAVE_FD_SET_FDS_BITS */
 #endif /* not HAVE_SVC_GETREQSET */
       }
       break;
@@ -350,43 +329,16 @@ mount_automounter(int ppid)
   int nmount, ret;
   int soNFS;
   int udp_soAMQ, tcp_soAMQ;
-#ifdef HAVE_TRANSPORT_TYPE_TLI
   struct netconfig *udp_amqncp, *tcp_amqncp;
-#endif /* HAVE_TRANSPORT_TYPE_TLI */
-#ifdef HAVE_FS_AUTOFS
-  int soAUTOFS;
-#endif /* HAVE_FS_AUTOFS */
 
   /*
-   * Create the nfs service for amd
+   * This must be done first, because it attempts to bind
+   * to various UDP ports and we don't want anything else
+   * potentially taking over those ports before we get a chance
+   * to reserve them.
    */
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-  ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
-  if (ret != 0)
-    return ret;
-  ret = create_amq_service(&udp_soAMQ, &udp_amqp, &udp_amqncp, &tcp_soAMQ, &tcp_amqp, &tcp_amqncp);
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
-  ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
-  if (ret != 0)
-    return ret;
-  ret = create_amq_service(&udp_soAMQ, &udp_amqp, &tcp_soAMQ, &tcp_amqp);
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
-  if (ret != 0)
-    return ret;
-
-#ifdef HAVE_FS_AUTOFS
-  if (amd_use_autofs) {
-    /*
-     * Create the autofs service for amd, but only if autofs maps
-     * were defined (so amd doesn't clash with automountd.)
-     */
-    plog(XLOG_INFO, "creating autofs service listener");
-    ret = create_autofs_service(&soAUTOFS, &autofs_port, &autofsxprt, autofs_program_1);
-    /* if autofs service fails it is OK if using a test amd */
-    if (ret != 0 && gopt.portmap_program == AMQ_PROGRAM)
-      return ret;
-  }
-#endif /* HAVE_FS_AUTOFS */
+  if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
+    restart_automounter_nodes();
 
   /*
    * Start RPC forwarding
@@ -408,6 +360,46 @@ mount_automounter(int ppid)
     restart();
 
   /*
+   * Create the nfs service for amd
+   * If nfs_port is already initialized, it means we
+   * already created the service during restart_automounter_nodes().
+   */
+  if (nfs_port == 0) {
+    ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
+    if (ret != 0)
+      return ret;
+  }
+  xsnprintf(pid_fsname, sizeof(pid_fsname), "%s:(pid%ld,port%u)",
+	    am_get_hostname(), (long) am_mypid, nfs_port);
+
+  /* security: if user sets -D amq, don't even create listening socket */
+  if (!amuDebug(D_AMQ)) {
+    ret = create_amq_service(&udp_soAMQ,
+			     &udp_amqp,
+			     &udp_amqncp,
+			     &tcp_soAMQ,
+			     &tcp_amqp,
+			     &tcp_amqncp,
+			     gopt.preferred_amq_port);
+    if (ret != 0)
+      return ret;
+  }
+
+#ifdef HAVE_FS_AUTOFS
+  if (amd_use_autofs) {
+    /*
+     * Create the autofs service for amd.
+     */
+    ret = create_autofs_service();
+    /* if autofs service fails it is OK if using a test amd */
+    if (ret != 0) {
+      plog(XLOG_WARNING, "autofs service registration failed, turning off autofs support");
+      amd_use_autofs = 0;
+    }
+  }
+#endif /* HAVE_FS_AUTOFS */
+
+  /*
    * Mount the top-level auto-mountpoints
    */
   nmount = mount_exported();
@@ -424,41 +416,26 @@ mount_automounter(int ppid)
     return 0;
   }
 
-#ifdef DEBUG
-  amuDebug(D_AMQ) {
-#endif /* DEBUG */
+  if (!amuDebug(D_AMQ)) {
     /*
      * Complete registration of amq (first TCP service then UDP)
      */
     unregister_amq();
 
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-    ret = svc_reg(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
-		  amq_program_1, tcp_amqncp);
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
-    ret = svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
-		       amq_program_1, IPPROTO_TCP);
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+    ret = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
+			   amq_program_1, IPPROTO_TCP, tcp_amqncp);
     if (ret != 1) {
       plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM=%d, AMQ_VERSION, tcp)", get_amd_program_number());
       return 3;
     }
 
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-    ret = svc_reg(udp_amqp, get_amd_program_number(), AMQ_VERSION,
-		  amq_program_1, udp_amqncp);
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
-    ret = svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
-		       amq_program_1, IPPROTO_UDP);
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+    ret = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
+			   amq_program_1, IPPROTO_UDP, udp_amqncp);
     if (ret != 1) {
       plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM=%d, AMQ_VERSION, udp)", get_amd_program_number());
       return 4;
     }
-
-#ifdef DEBUG
   }
-#endif /* DEBUG */
 
   /*
    * Start timeout_mp rolling
diff --git a/contrib/amd/amd/nfs_subr.c b/contrib/amd/amd/nfs_subr.c
index d06d008..80d3ca8 100644
--- a/contrib/amd/amd/nfs_subr.c
+++ b/contrib/amd/amd/nfs_subr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: nfs_subr.c,v 1.3 1999/01/13 23:31:00 ezk Exp $
+ * File: am-utils/amd/nfs_subr.c
  *
  */
 
@@ -57,19 +56,45 @@
 # define nfs_error(e) ((nfsstat)(e))
 #endif /* nfs_error */
 
+/*
+ * File Handle structure
+ *
+ * This is interpreted by indexing the exported array
+ * by fhh_id (for old-style filehandles), or by retrieving
+ * the node name from fhh_path (for new-style filehandles).
+ *
+ * The whole structure is mapped onto a standard fhandle_t
+ * when transmitted.
+ */
+struct am_fh {
+  u_int fhh_gen;				/* generation number */
+  union {
+    struct {
+      int fhh_type;				/* old or new am_fh */
+      pid_t fhh_pid;				/* process id */
+      int fhh_id;				/* map id */
+    } s;
+    char fhh_path[NFS_FHSIZE-sizeof(u_int)];	/* path to am_node */
+  } u;
+};
+
+
 /* forward declarations */
+/* converting am-filehandles to mount-points */
+static am_node *fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop);
+static am_node *fh_to_mp(am_nfs_fh *fhp);
 static void count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int *out_bavail);
 
 
 static char *
-do_readlink(am_node *mp, int *error_return, nfsattrstat **attrpp)
+do_readlink(am_node *mp, int *error_return)
 {
   char *ln;
 
   /*
-   * If there is a readlink method, then use
-   * that, otherwise if a link exists use
-   * that, otherwise use the mount point.
+   * If there is a readlink method then use it,
+   * otherwise if a link exists use that,
+   * otherwise use the mount point.
    */
   if (mp->am_mnt->mf_ops->readlink) {
     int retry = 0;
@@ -86,8 +111,6 @@ do_readlink(am_node *mp, int *error_return, nfsattrstat **attrpp)
   } else {
     ln = mp->am_mnt->mf_mount;
   }
-  if (attrpp)
-    *attrpp = &mp->am_attr;
 
   return ln;
 }
@@ -108,47 +131,38 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
   static nfsattrstat res;
   am_node *mp;
   int retry;
+  time_t now = clocktime(NULL);
 
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_TRACE))
     plog(XLOG_DEBUG, "getattr:");
-#endif /* DEBUG */
 
-  mp = fh_to_mp2(argp, &retry);
+  mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
   if (mp == 0) {
-
-#ifdef DEBUG
-    amuDebug(D_TRACE)
+    if (amuDebug(D_TRACE))
       plog(XLOG_DEBUG, "\tretry=%d", retry);
-#endif /* DEBUG */
 
-    if (retry < 0)
+    if (retry < 0) {
+      amd_stats.d_drops++;
       return 0;
+    }
     res.ns_status = nfs_error(retry);
-  } else {
-    nfsattrstat *attrp = &mp->am_attr;
-
-#ifdef DEBUG
-    amuDebug(D_TRACE)
-      plog(XLOG_DEBUG, "\tstat(%s), size = %d", mp->am_path,
-	   (int) attrp->ns_u.ns_attr_u.na_size);
-#endif /* DEBUG */
-
-    mp->am_stats.s_getattr++;
-    return attrp;
+    return &res;
   }
 
-#ifndef MNT2_NFS_OPT_SYMTTL
-  /*
-   * This code is needed to defeat Solaris 2.4's (and newer) symlink values
-   * cache.  It forces the last-modified time of the symlink to be current.
-   * It is not needed if the O/S has an nfs flag to turn off the
-   * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
-   */
-  if (++res.ns_u.ns_attr_u.na_mtime.nt_useconds == 0)
-    ++res.ns_u.ns_attr_u.na_mtime.nt_seconds;
-#endif /* not MNT2_NFS_OPT_SYMTTL */
+  res = mp->am_attr;
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "\tstat(%s), size = %d, mtime=%ld.%ld",
+	 mp->am_path,
+	 (int) res.ns_u.ns_attr_u.na_size,
+	 (long) res.ns_u.ns_attr_u.na_mtime.nt_seconds,
+	 (long) res.ns_u.ns_attr_u.na_mtime.nt_useconds);
 
+  /* Delay unmount of what was looked up */
+  if (mp->am_timeo_w < 4 * gopt.am_timeo_w)
+    mp->am_timeo_w += gopt.am_timeo_w;
+  mp->am_ttl = now + mp->am_timeo_w;
+
+  mp->am_stats.s_getattr++;
   return &res;
 }
 
@@ -182,30 +196,35 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
   static nfsdiropres res;
   am_node *mp;
   int retry;
+  uid_t uid;
+  gid_t gid;
 
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_TRACE))
     plog(XLOG_DEBUG, "lookup:");
-#endif /* DEBUG */
 
-  mp = fh_to_mp2(&argp->da_fhandle, &retry);
+  /* finally, find the effective uid/gid from RPC request */
+  if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0)
+    plog(XLOG_ERROR, "cannot get uid/gid from RPC credentials");
+  xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) uid);
+  xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) gid);
+
+  mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_CREATE);
   if (mp == 0) {
-    if (retry < 0)
+    if (retry < 0) {
+      amd_stats.d_drops++;
       return 0;
+    }
     res.dr_status = nfs_error(retry);
   } else {
     int error;
     am_node *ap;
-#ifdef DEBUG
-    amuDebug(D_TRACE)
-      plog(XLOG_DEBUG, "\tlookuppn(%s, %s)", mp->am_path, argp->da_name);
-#endif /* DEBUG */
-    ap = (*mp->am_mnt->mf_ops->lookuppn) (mp, argp->da_name, &error, VLOOK_CREATE);
+    if (amuDebug(D_TRACE))
+      plog(XLOG_DEBUG, "\tlookup(%s, %s)", mp->am_path, argp->da_name);
+    ap = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &error, VLOOK_CREATE);
+    if (ap && error < 0)
+      ap = mp->am_mnt->mf_ops->mount_child(ap, &error);
     if (ap == 0) {
       if (error < 0) {
-#ifdef DEBUG
-	dlog("Not sending RPC reply");
-#endif /* DEBUG */
 	amd_stats.d_drops++;
 	return 0;
       }
@@ -231,7 +250,7 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
 
 
 void
-quick_reply(am_node *mp, int error)
+nfs_quick_reply(am_node *mp, int error)
 {
   SVCXPRT *transp = mp->am_transp;
   nfsdiropres res;
@@ -265,11 +284,8 @@ quick_reply(am_node *mp, int error)
     /*
      * Free up transp.  It's only used for one reply.
      */
-    XFREE(transp);
-    mp->am_transp = NULL;
-#ifdef DEBUG
+    XFREE(mp->am_transp);
     dlog("Quick reply sent for %s", mp->am_mnt->mf_mount);
-#endif /* DEBUG */
   }
 }
 
@@ -281,27 +297,24 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
   am_node *mp;
   int retry;
 
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_TRACE))
     plog(XLOG_DEBUG, "readlink:");
-#endif /* DEBUG */
 
-  mp = fh_to_mp2(argp, &retry);
+  mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
   if (mp == 0) {
   readlink_retry:
-    if (retry < 0)
+    if (retry < 0) {
+      amd_stats.d_drops++;
       return 0;
+    }
     res.rlr_status = nfs_error(retry);
   } else {
-    char *ln = do_readlink(mp, &retry, (nfsattrstat **) 0);
+    char *ln = do_readlink(mp, &retry);
     if (ln == 0)
       goto readlink_retry;
     res.rlr_status = NFS_OK;
-#ifdef DEBUG
-    amuDebug(D_TRACE)
-      if (ln)
-	plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
-#endif /* DEBUG */
+    if (amuDebug(D_TRACE) && ln)
+      plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
     res.rlr_u.rlr_data_u = ln;
     mp->am_stats.s_readlink++;
   }
@@ -367,8 +380,10 @@ unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp)
 
   am_node *mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_DELETE);
   if (mp == 0) {
-    if (retry < 0)
+    if (retry < 0) {
+      amd_stats.d_drops++;
       return 0;
+    }
     res = nfs_error(retry);
     goto out;
   }
@@ -378,12 +393,10 @@ unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp)
     goto out;
   }
 
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_TRACE))
     plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->da_name);
-#endif /* DEBUG */
 
-  mp = (*mp->am_mnt->mf_ops->lookuppn) (mp, argp->da_name, &retry, VLOOK_DELETE);
+  mp = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &retry, VLOOK_DELETE);
   if (mp == 0) {
     /*
      * Ignore retries...
@@ -493,21 +506,19 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
   am_node *mp;
   int retry;
 
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_TRACE))
     plog(XLOG_DEBUG, "readdir:");
-#endif /* DEBUG */
 
-  mp = fh_to_mp2(&argp->rda_fhandle, &retry);
+  mp = fh_to_mp3(&argp->rda_fhandle, &retry, VLOOK_CREATE);
   if (mp == 0) {
-    if (retry < 0)
+    if (retry < 0) {
+      amd_stats.d_drops++;
       return 0;
+    }
     res.rdr_status = nfs_error(retry);
   } else {
-#ifdef DEBUG
-    amuDebug(D_TRACE)
+    if (amuDebug(D_TRACE))
       plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
-#endif /* DEBUG */
     res.rdr_status = nfs_error((*mp->am_mnt->mf_ops->readdir)
 			   (mp, argp->rda_cookie,
 			    &res.rdr_u.rdr_reply_u, e_res, argp->rda_count));
@@ -526,22 +537,20 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
   int retry;
   mntent_t mnt;
 
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_TRACE))
     plog(XLOG_DEBUG, "statfs:");
-#endif /* DEBUG */
 
-  mp = fh_to_mp2(argp, &retry);
+  mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
   if (mp == 0) {
-    if (retry < 0)
+    if (retry < 0) {
+      amd_stats.d_drops++;
       return 0;
+    }
     res.sfr_status = nfs_error(retry);
   } else {
     nfsstatfsokres *fp;
-#ifdef DEBUG
-    amuDebug(D_TRACE)
+    if (amuDebug(D_TRACE))
       plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path);
-#endif /* DEBUG */
 
     /*
      * just return faked up file system information
@@ -555,7 +564,7 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
     if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) &&
 	mp->am_mnt && mp->am_mnt->mf_mopts) {
       mnt.mnt_opts = mp->am_mnt->mf_mopts;
-      if (hasmntopt(&mnt, "browsable")) {
+      if (amu_hasmntopt(&mnt, "browsable")) {
 	count_map_entries(mp,
 			  &fp->sfrok_blocks,
 			  &fp->sfrok_bfree,
@@ -615,3 +624,205 @@ out:
   *out_bfree = bfree;
   *out_bavail = bavail;
 }
+
+
+/*
+ * Convert from file handle to automount node.
+ */
+static am_node *
+fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop)
+{
+  struct am_fh *fp = (struct am_fh *) fhp;
+  am_node *ap = 0;
+
+  if (fp->u.s.fhh_type != 0) {
+    /* New filehandle type */
+    int len = sizeof(*fhp) - sizeof(fp->fhh_gen);
+    char *path = xmalloc(len+1);
+    /*
+     * Because fhp is treated as a filehandle we use memcpy
+     * instead of xstrlcpy.
+     */
+    memcpy(path, (char *) fp->u.fhh_path, len);
+    path[len] = '\0';
+    /* dlog("fh_to_mp3: new filehandle: %s", path); */
+
+    ap = path_to_exported_ap(path);
+    XFREE(path);
+  } else {
+    /* dlog("fh_to_mp3: old filehandle: %d", fp->u.s.fhh_id); */
+    /*
+     * Check process id matches
+     * If it doesn't then it is probably
+     * from an old kernel-cached filehandle
+     * which is now out of date.
+     */
+    if (fp->u.s.fhh_pid != get_server_pid()) {
+      dlog("fh_to_mp3: wrong pid %ld != my pid %ld",
+	   (long) fp->u.s.fhh_pid, get_server_pid());
+      goto drop;
+    }
+
+    /*
+     * Get hold of the supposed mount node
+     */
+    ap = get_exported_ap(fp->u.s.fhh_id);
+  }
+
+  /*
+   * Check the generation number in the node
+   * matches the one from the kernel.  If not
+   * then the old node has been timed out and
+   * a new one allocated.
+   */
+  if (ap != NULL && ap->am_gen != fp->fhh_gen)
+    ap = 0;
+
+  /*
+   * If it doesn't exists then drop the request
+   */
+  if (!ap)
+    goto drop;
+
+#if 0
+  /*
+   * If the node is hung then locate a new node
+   * for it.  This implements the replicated filesystem
+   * retries.
+   */
+  if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) {
+    int error;
+    am_node *orig_ap = ap;
+
+    dlog("fh_to_mp3: %s (%s) is hung: lookup alternative file server",
+	 orig_ap->am_path, orig_ap->am_mnt->mf_info);
+
+    /*
+     * Update modify time of parent node.
+     * With any luck the kernel will re-stat
+     * the child node and get new information.
+     */
+    clocktime(&orig_ap->am_fattr.na_mtime);
+
+    /*
+     * Call the parent's lookup routine for an object
+     * with the same name.  This may return -1 in error
+     * if a mount is in progress.  In any case, if no
+     * mount node is returned the error code is propagated
+     * to the caller.
+     */
+    if (vop == VLOOK_CREATE) {
+      ap = orig_ap->am_parent->am_mnt->mf_ops->lookup_child(orig_ap->am_parent, orig_ap->am_name, &error, vop);
+      if (ap && error < 0)
+	ap = orig_ap->am_parent->am_mnt->mf_ops->mount_child(ap, &error);
+    } else {
+      ap = 0;
+      error = ESTALE;
+    }
+    if (ap == 0) {
+      if (error < 0 && amd_state == Finishing)
+	error = ENOENT;
+      *rp = error;
+      return 0;
+    }
+
+    /*
+     * Update last access to original node.  This
+     * avoids timing it out and so sending ESTALE
+     * back to the kernel.
+     * XXX - Not sure we need this anymore (jsp, 90/10/6).
+     */
+    new_ttl(orig_ap);
+
+  }
+#endif
+
+  /*
+   * Disallow references to objects being unmounted, unless
+   * they are automount points.
+   */
+  if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) &&
+      !(ap->am_flags & AMF_ROOT)) {
+    if (amd_state == Finishing)
+      *rp = ENOENT;
+    else
+      *rp = -1;
+    return 0;
+  }
+  new_ttl(ap);
+
+drop:
+  if (!ap || !ap->am_mnt) {
+    /*
+     * If we are shutting down then it is likely
+     * that this node has disappeared because of
+     * a fast timeout.  To avoid things thrashing
+     * just pretend it doesn't exist at all.  If
+     * ESTALE is returned, some NFS clients just
+     * keep retrying (stupid or what - if it's
+     * stale now, what's it going to be in 5 minutes?)
+     */
+    if (amd_state == Finishing)
+      *rp = ENOENT;
+    else
+      *rp = ESTALE;
+    amd_stats.d_stale++;
+  }
+
+  return ap;
+}
+
+
+static am_node *
+fh_to_mp(am_nfs_fh *fhp)
+{
+  int dummy;
+
+  return fh_to_mp3(fhp, &dummy, VLOOK_CREATE);
+}
+
+
+/*
+ * Convert from automount node to file handle.
+ */
+void
+mp_to_fh(am_node *mp, am_nfs_fh *fhp)
+{
+  u_int pathlen;
+  struct am_fh *fp = (struct am_fh *) fhp;
+
+  memset((char *) fhp, 0, sizeof(am_nfs_fh));
+
+  /* Store the generation number */
+  fp->fhh_gen = mp->am_gen;
+
+  pathlen = strlen(mp->am_path);
+  if (pathlen <= sizeof(*fhp) - sizeof(fp->fhh_gen)) {
+    /* dlog("mp_to_fh: new filehandle: %s", mp->am_path); */
+
+    /*
+     * Because fhp is treated as a filehandle we use memcpy instead of
+     * xstrlcpy.
+     */
+    memcpy(fp->u.fhh_path, mp->am_path, pathlen); /* making a filehandle */
+  } else {
+    /*
+     * Take the process id
+     */
+    fp->u.s.fhh_pid = get_server_pid();
+
+    /*
+     * ... the map number
+     */
+    fp->u.s.fhh_id = mp->am_mapno;
+
+    /*
+     * ... and the generation number (previously stored)
+     * to make a "unique" triple that will never
+     * be reallocated except across reboots (which doesn't matter)
+     * or if we are unlucky enough to be given the same
+     * pid as a previous amd (very unlikely).
+     */
+    /* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */
+  }
+}
diff --git a/contrib/amd/amd/ops_TEMPLATE.c b/contrib/amd/amd/ops_TEMPLATE.c
index 34fd308..3f74219 100644
--- a/contrib/amd/amd/ops_TEMPLATE.c
+++ b/contrib/amd/amd/ops_TEMPLATE.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_TEMPLATE.c,v 1.2 1999/01/10 21:53:48 ezk Exp $
+ * File: am-utils/amd/ops_TEMPLATE.c
  *
  */
 
@@ -60,18 +59,16 @@
 #include <amd.h>
 
 /* forward declarations */
-static char * foofs_match(am_opts *fo);
+static char *foofs_match(am_opts *fo);
 static int foofs_init(mntfs *mf);
-static int foofs_mount(am_node *mp);
-static int foofs_fmount(mntfs *mf);
-static int foofs_umount(am_node *mp);
-static int foofs_fumount(mntfs *mf);
-static am_node * foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op);
-static int foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count);
-static am_node * foofs_readlink(am_node *mp, int *error_return);
-static void foofs_mounted(mntfs *mf);
-static void foofs_umounted(am_node *mp);
-fserver * foofs_ffserver(mntfs *mf);
+static int foofs_mount(am_node *mp, mntfs *mf);
+static int foofs_umount(am_node *mp, mntfs *mf);
+static am_node *foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op);
+static int foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count);
+static am_node *foofs_readlink(am_node *mp, int *error_return);
+static void foofs_mounted(am_node *am, mntfs *mf);
+static void foofs_umounted(am_node *mp, mntfs *mf);
+static fserver *foofs_ffserver(mntfs *mf);
 
 
 /*
@@ -84,16 +81,19 @@ am_ops foofs_ops =
   foofs_match,			/* match */
   foofs_init,			/* initialize */
   foofs_mount,			/* mount vnode */
-  foofs_fmount,			/* mount vfs */
   foofs_umount,			/* unmount vnode */
-  foofs_fumount,		/* unmount VFS */
-  foofs_lookuppn,		/* lookup path-name */
+  foofs_lookup_child,		/* lookup path-name */
+  foofs_mount_child,		/* mount path-name */
   foofs_readdir,		/* read directory */
   foofs_readlink,		/* read link */
   foofs_mounted,		/* after-mount extra actions */
   foofs_umounted,		/* after-umount extra actions */
   foofs_ffserver,		/* find a file server */
-  FS_MKMNT | FS_BACKGROUND | FS_AMQINFO	/* flags */
+  foofs_get_wchan,		/* return the waiting channel */
+  FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,	/* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_TEMPLATE_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -220,7 +220,7 @@ foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op)
  * If OK, fills in ep with chain of directory entries.
  */
 static int
-foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count)
+foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
 {
   int error = 0;
 
@@ -284,10 +284,22 @@ foofs_umounted(am_node *mp)
  * Find a file server.
  * Returns: fserver of found server, or NULL if not found.
  */
-fserver *
+static fserver *
 foofs_ffserver(mntfs *mf)
 {
   plog(XLOG_INFO, "entering foofs_ffserver...");
 
   return NULL;
 }
+
+
+/*
+ * Normally just return mf. Only inherit needs to do special tricks.
+ */
+static wchan_t *
+foofs_get_wchan(mntfs *mf)
+{
+  plog(XLOG_INFO, "entering foofs_get_wchan...");
+
+  return mf;
+}
diff --git a/contrib/amd/amd/ops_autofs.c b/contrib/amd/amd/ops_autofs.c
deleted file mode 100644
index da77af1..0000000
--- a/contrib/amd/amd/ops_autofs.c
+++ /dev/null
@@ -1,1281 +0,0 @@
-/*
- * 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.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry at Imperial College, London.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgment:
- *      This product includes software developed by the University of
- *      California, Berkeley and its contributors.
- * 4. 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.
- *
- * 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.
- *
- *      %W% (Berkeley) %G%
- *
- * $Id: ops_autofs.c,v 1.4 1999/01/13 23:31:00 ezk Exp $
- *
- */
-
-/*
- * Automounter filesystem
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-#include <am_defs.h>
-#include <amd.h>
-
-/*
- * KLUDGE: wrap whole file in HAVE_FS_AUTOFS, because
- * not all systems with an automounter file system are supported
- * by am-utils yet...
- */
-
-#ifdef HAVE_FS_AUTOFS
-
-/*
- * MACROS:
- */
-#ifndef AUTOFS_NULL
-# define AUTOFS_NULL	((u_long)0)
-#endif /* not AUTOFS_NULL */
-
-/*
- * VARIABLES:
- */
-
-/* forward declarations */
-static int mount_autofs(char *dir, char *opts);
-static int autofs_mount_1_svc(struct mntrequest *mr, struct mntres *result, struct authunix_parms *cred);
-static int autofs_unmount_1_svc(struct umntrequest *ur, struct umntres *result, struct authunix_parms *cred);
-
-/* external declarations */
-extern bool_t xdr_mntrequest(XDR *, mntrequest *);
-extern bool_t xdr_mntres(XDR *, mntres *);
-extern bool_t xdr_umntrequest(XDR *, umntrequest *);
-extern bool_t xdr_umntres(XDR *, umntres *);
-
-/*
- * STRUCTURES:
- */
-
-/* Sun's kernel-based automounter-supporting file system */
-am_ops autofs_ops =
-{
-  "autofs",
-  amfs_auto_match,
-  0,				/* amfs_auto_init */
-  autofs_mount,
-  0,
-  autofs_umount,
-  0,
-  amfs_auto_lookuppn,
-  amfs_auto_readdir,		/* browsable version of readdir() */
-  0,				/* autofs_readlink */
-  autofs_mounted,
-  0,				/* autofs_umounted */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND | FS_AMQINFO | FS_DIRECTORY
-};
-
-
-/****************************************************************************
- *** FUNCTIONS                                                            ***
- ****************************************************************************/
-
-/*
- * Mount the top-level using autofs
- */
-int
-autofs_mount(am_node *mp)
-{
-  mntfs *mf = mp->am_mnt;
-  struct stat stb;
-  char opts[256], preopts[256];
-  int error;
-  char *mnttype;
-
-  /*
-   * Mounting the automounter.
-   * Make sure the mount directory exists, construct
-   * the mount options and call the mount_autofs routine.
-   */
-
-  if (stat(mp->am_path, &stb) < 0) {
-    return errno;
-  } else if ((stb.st_mode & S_IFMT) != S_IFDIR) {
-    plog(XLOG_WARNING, "%s is not a directory", mp->am_path);
-    return ENOTDIR;
-  }
-  if (mf->mf_ops == &autofs_ops)
-    mnttype = "indirect";
-  else if (mf->mf_ops == &amfs_direct_ops)
-    mnttype = "direct";
-#ifdef HAVE_AM_FS_UNION
-  else if (mf->mf_ops == &amfs_union_ops)
-    mnttype = "union";
-#endif /* HAVE_AM_FS_UNION */
-  else
-    mnttype = "auto";
-
-  /*
-   * Construct some mount options:
-   *
-   * Tack on magic map=<mapname> option in mtab to emulate
-   * SunOS automounter behavior.
-   */
-  preopts[0] = '\0';
-#ifdef MNTTAB_OPT_INTR
-  strcat(preopts, MNTTAB_OPT_INTR);
-  strcat(preopts, ",");
-#endif /* MNTTAB_OPT_INTR */
-#ifdef MNTTAB_OPT_IGNORE
-  strcat(preopts, MNTTAB_OPT_IGNORE);
-  strcat(preopts, ",");
-#endif /* MNTTAB_OPT_IGNORE */
-  sprintf(opts, "%s%s,%s=%d,%s=%d,%s=%d,%s,map=%s",
-	  preopts,
-	  MNTTAB_OPT_RW,
-	  MNTTAB_OPT_PORT, nfs_port,
-	  MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo,
-	  MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans,
-	  mnttype, mf->mf_info);
-
-  /* now do the mount */
-  error = mount_autofs(mf->mf_mount, opts);
-  if (error) {
-    errno = error;
-    plog(XLOG_FATAL, "mount_autofs: %m");
-    return error;
-  }
-  return 0;
-}
-
-
-void
-autofs_mounted(mntfs *mf)
-{
-  amfs_auto_mkcacheref(mf);
-}
-
-
-/*
- * Unmount a top-level automount node
- */
-int
-autofs_umount(am_node *mp)
-{
-  int error;
-  struct stat stb;
-
-  /*
-   * The lstat is needed if this mount is type=direct.  When that happens,
-   * the kernel cache gets confused between the underlying type (dir) and
-   * the mounted type (link) and so needs to be re-synced before the
-   * unmount.  This is all because the unmount system call follows links and
-   * so can't actually unmount a link (stupid!).  It was noted that doing an
-   * ls -ld of the mount point to see why things were not working actually
-   * fixed the problem - so simulate an ls -ld here.
-   */
-  if (lstat(mp->am_path, &stb) < 0) {
-#ifdef DEBUG
-    dlog("lstat(%s): %m", mp->am_path);
-#endif /* DEBUG */
-  }
-  error = UMOUNT_FS(mp->am_path, mnttab_file_name);
-  if (error == EBUSY && mp->am_flags & AMF_AUTOFS) {
-    plog(XLOG_WARNING, "autofs_unmount of %s busy (autofs). exit", mp->am_path);
-    error = 0;			/* fake unmount was ok */
-  }
-  return error;
-}
-
-
-/*
- * Mount an automounter directory.
- * The automounter is connected into the system
- * as a user-level NFS server.  mount_autofs constructs
- * the necessary NFS parameters to be given to the
- * kernel so that it will talk back to us.
- */
-static int
-mount_autofs(char *dir, char *opts)
-{
-  char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
-  char *map_opt, buf[MAXHOSTNAMELEN];
-  int retry, error, flags;
-  struct utsname utsname;
-  mntent_t mnt;
-  autofs_args_t autofs_args;
-  MTYPE_TYPE type = MOUNT_TYPE_AUTOFS;
-
-  memset((voidp) &autofs_args, 0, sizeof(autofs_args)); /* Paranoid */
-
-  memset((voidp) &mnt, 0, sizeof(mnt));
-  mnt.mnt_dir = dir;
-  mnt.mnt_fsname = pid_fsname;
-  mnt.mnt_opts = opts;
-  mnt.mnt_type = type;
-
-  retry = hasmntval(&mnt, "retry");
-  if (retry <= 0)
-    retry = 2;			/* XXX */
-
-  /*
-   * SET MOUNT ARGS
-   */
-  if (uname(&utsname) < 0) {
-    strcpy(buf, "localhost.autofs");
-  } else {
-    strcpy(buf, utsname.nodename);
-    strcat(buf, ".autofs");
-  }
-#ifdef HAVE_FIELD_AUTOFS_ARGS_T_ADDR
-  autofs_args.addr.buf = buf;
-  autofs_args.addr.len = strlen(autofs_args.addr.buf);
-  autofs_args.addr.maxlen = autofs_args.addr.len;
-#endif /* HAVE_FIELD_AUTOFS_ARGS_T_ADDR */
-
-  autofs_args.path = dir;
-  autofs_args.opts = opts;
-
-  map_opt = hasmntopt(&mnt, "map");
-  if (map_opt) {
-    map_opt += sizeof("map="); /* skip the "map=" */
-    if (map_opt == NULL) {
-      plog(XLOG_WARNING, "map= has a null map name. reset to amd.unknown");
-      map_opt = "amd.unknown";
-    }
-  }
-  autofs_args.map = map_opt;
-
-  /* XXX: these I set arbitrarily... */
-  autofs_args.mount_to = 300;
-  autofs_args.rpc_to = 60;
-  autofs_args.direct = 0;
-
-  /*
-   * Make a ``hostname'' string for the kernel
-   */
-  sprintf(fs_hostname, "pid%ld@%s:%s",
-	  (long) (foreground ? am_mypid : getppid()),
-	  am_get_hostname(), dir);
-
-  /*
-   * Most kernels have a name length restriction.
-   */
-  if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
-    strcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..");
-
-  /*
-   * Finally we can compute the mount flags set above.
-   */
-  flags = compute_mount_flags(&mnt);
-
-  /*
-   * This is it!  Here we try to mount amd on its mount points.
-   */
-  error = mount_fs(&mnt, flags, (caddr_t) &autofs_args, retry, type, 0, NULL, mnttab_file_name);
-  return error;
-}
-
-
-/****************************************************************************/
-/* autofs program dispatcher */
-void
-autofs_program_1(struct svc_req *rqstp, SVCXPRT *transp)
-{
-  int ret;
-  union {
-    mntrequest autofs_mount_1_arg;
-    umntrequest autofs_umount_1_arg;
-  } argument;
-  union {
-    mntres mount_res;
-    umntres umount_res;
-  } result;
-
-  bool_t (*xdr_argument)(), (*xdr_result)();
-  int (*local)();
-
-  switch (rqstp->rq_proc) {
-
-  case AUTOFS_NULL:
-    svc_sendreply(transp,
-		  (XDRPROC_T_TYPE) xdr_void,
-		  (SVC_IN_ARG_TYPE) NULL);
-    return;
-
-  case AUTOFS_MOUNT:
-    xdr_argument = xdr_mntrequest;
-    xdr_result = xdr_mntres;
-    local = (int (*)()) autofs_mount_1_svc;
-    break;
-
-  case AUTOFS_UNMOUNT:
-    xdr_argument = xdr_umntrequest;
-    xdr_result = xdr_umntres;
-    local = (int (*)()) autofs_unmount_1_svc;
-    break;
-
-  default:
-    svcerr_noproc(transp);
-    return;
-  }
-
-  memset((char *) &argument, 0, sizeof(argument));
-  if (!svc_getargs(transp,
-		   (XDRPROC_T_TYPE) xdr_argument,
-		   (SVC_IN_ARG_TYPE) &argument)) {
-    plog(XLOG_ERROR,
-	 "AUTOFS xdr decode failed for %d %d %d",
-	 (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
-    svcerr_decode(transp);
-    return;
-  }
-
-  ret = (*local) (&argument, &result, rqstp);
-  if (!svc_sendreply(transp,
-		     (XDRPROC_T_TYPE) xdr_result,
-		     (SVC_IN_ARG_TYPE) &result)) {
-    svcerr_systemerr(transp);
-  }
-
-  if (!svc_freeargs(transp,
-		    (XDRPROC_T_TYPE) xdr_argument,
-		    (SVC_IN_ARG_TYPE) &argument)) {
-    plog(XLOG_FATAL, "unable to free rpc arguments in autofs_program_1");
-    going_down(1);
-  }
-}
-
-
-static int
-autofs_mount_1_svc(struct mntrequest *mr, struct mntres *result, struct authunix_parms *cred)
-{
-  int err = 0;
-  am_node *anp, *anp2;
-
-  plog(XLOG_INFO, "XXX: autofs_mount_1_svc: %s:%s:%s:%s",
-       mr->map, mr->name, mr->opts, mr->path);
-
-  /* look for map (eg. "/home") */
-  anp = find_ap(mr->path);
-  if (!anp) {
-    plog(XLOG_ERROR, "map %s not found", mr->path);
-    err = ENOENT;
-    goto out;
-  }
-  /* turn on autofs in map flags */
-  if (!(anp->am_flags & AMF_AUTOFS)) {
-    plog(XLOG_INFO, "turning on AMF_AUTOFS for node %s", mr->path);
-    anp->am_flags |= AMF_AUTOFS;
-  }
-
-  /*
-   * Look for (and create if needed) the new node.
-   *
-   * If an error occurred, return it.  If a -1 was returned, that indicates
-   * that a mount is in progress, so sleep a while (while the backgrounded
-   * mount is happening), and then signal the autofs to retry the mount.
-   *
-   * There's something I don't understand.  I was thinking that this code
-   * here is the one which will succeed eventually and will send an RPC
-   * reply to the kernel, but apparently that happens somewhere else, not
-   * here.  It works though, just that I don't know how.  Arg. -Erez.
-   * */
-  err = 0;
-  anp2 = autofs_lookuppn(anp, mr->name, &err, VLOOK_CREATE);
-  if (!anp2) {
-    if (err == -1) {		/* then tell autofs to retry */
-      sleep(1);
-      err = EAGAIN;
-    }
-    goto out;
-  }
-
-out:
-  result->status = err;
-  return err;
-}
-
-
-static int
-autofs_unmount_1_svc(struct umntrequest *ur, struct umntres *result, struct authunix_parms *cred)
-{
-  int err = 0;
-
-#ifdef HAVE_FIELD_UMNTREQUEST_RDEVID
-  plog(XLOG_INFO, "XXX: autofs_unmount_1_svc: %d:%lu:%lu:0x%lx",
-       ur->isdirect, (unsigned long) ur->devid, (unsigned long) ur->rdevid,
-       (unsigned long) ur->next);
-#else /* HAVE_FIELD_UMNTREQUEST_RDEVID */
-  plog(XLOG_INFO, "XXX: autofs_unmount_1_svc: %d:%lu:0x%lx",
-       ur->isdirect, (unsigned long) ur->devid,
-       (unsigned long) ur->next);
-#endif /* HAVE_FIELD_UMNTREQUEST_RDEVID */
-
-  err = EINVAL;			/* XXX: not implemented yet */
-  goto out;
-
-out:
-  result->status = err;
-  return err;
-}
-
-
-/*
- * Pick a file system to try mounting and
- * do that in the background if necessary
- *
- For each location:
- if it is new -defaults then
- extract and process
- continue;
- fi
- if it is a cut then
- if a location has been tried then
- break;
- fi
- continue;
- fi
- parse mount location
- discard previous mount location if required
- find matching mounted filesystem
- if not applicable then
- this_error = No such file or directory
- continue
- fi
- if the filesystem failed to be mounted then
- this_error = error from filesystem
- elif the filesystem is mounting or unmounting then
- this_error = -1
- elif the fileserver is down then
- this_error = -1
- elif the filesystem is already mounted
- this_error = 0
- break
- fi
- if no error on this mount then
- this_error = initialize mount point
- fi
- if no error on this mount and mount is delayed then
- this_error = -1
- fi
- if this_error < 0 then
- retry = true
- fi
- if no error on this mount then
- make mount point if required
- fi
- if no error on this mount then
- if mount in background then
- run mount in background
- return -1
- else
- this_error = mount in foreground
- fi
- fi
- if an error occurred on this mount then
- update stats
- save error in mount point
- fi
- endfor
- */
-static int
-autofs_bgmount(struct continuation * cp, int mpe)
-{
-  mntfs *mf = cp->mp->am_mnt;	/* Current mntfs */
-  mntfs *mf_retry = 0;		/* First mntfs which needed retrying */
-  int this_error = -1;		/* Per-mount error */
-  int hard_error = -1;
-  int mp_error = mpe;
-
-  /*
-   * Try to mount each location.
-   * At the end:
-   * hard_error == 0 indicates something was mounted.
-   * hard_error > 0 indicates everything failed with a hard error
-   * hard_error < 0 indicates nothing could be mounted now
-   */
-  for (; this_error && *cp->ivec; cp->ivec++) {
-    am_ops *p;
-    am_node *mp = cp->mp;
-    char *link_dir;
-    int dont_retry;
-
-    if (hard_error < 0)
-      hard_error = this_error;
-
-    this_error = -1;
-
-    if (**cp->ivec == '-') {
-      /*
-       * Pick up new defaults
-       */
-      if (cp->auto_opts && *cp->auto_opts)
-	cp->def_opts = str3cat(cp->def_opts, cp->auto_opts, ";", *cp->ivec + 1);
-      else
-	cp->def_opts = strealloc(cp->def_opts, *cp->ivec + 1);
-#ifdef DEBUG
-      dlog("Setting def_opts to \"%s\"", cp->def_opts);
-#endif /* DEBUG */
-      continue;
-    }
-    /*
-     * If a mount has been attempted, and we find
-     * a cut then don't try any more locations.
-     */
-    if (STREQ(*cp->ivec, "/") || STREQ(*cp->ivec, "||")) {
-      if (cp->tried) {
-#ifdef DEBUG
-	dlog("Cut: not trying any more locations for %s",
-	     mp->am_path);
-#endif /* DEBUG */
-	break;
-      }
-      continue;
-    }
-
-    /* match the operators */
-    p = ops_match(&cp->fs_opts, *cp->ivec, cp->def_opts, mp->am_path, cp->key, mp->am_parent->am_mnt->mf_info);
-
-    /*
-     * Find a mounted filesystem for this node.
-     */
-    mp->am_mnt = mf = realloc_mntfs(mf, p, &cp->fs_opts,
-				    cp->fs_opts.opt_fs,
-				    cp->fs_opts.fs_mtab,
-				    cp->auto_opts,
-				    cp->fs_opts.opt_opts,
-				    cp->fs_opts.opt_remopts);
-
-    p = mf->mf_ops;
-#ifdef DEBUG
-    dlog("Got a hit with %s", p->fs_type);
-#endif /* DEBUG */
-
-    /*
-     * Note whether this is a real mount attempt
-     */
-    if (p == &amfs_error_ops) {
-      plog(XLOG_MAP, "Map entry %s for %s failed to match", *cp->ivec, mp->am_path);
-      if (this_error <= 0)
-	this_error = ENOENT;
-      continue;
-    } else {
-      if (cp->fs_opts.fs_mtab) {
-	plog(XLOG_MAP, "Trying mount of %s on \"%s\" fstype %s",
-	     cp->fs_opts.fs_mtab, mp->am_path, p->fs_type);
-      }
-      cp->tried = TRUE;
-    }
-
-    this_error = 0;
-    dont_retry = FALSE;
-
-    if (mp->am_link) {
-      XFREE(mp->am_link);
-      mp->am_link = 0;
-    }
-    link_dir = mf->mf_fo->opt_sublink;
-
-    if (link_dir && *link_dir) {
-      if (*link_dir == '/') {
-	mp->am_link = strdup(link_dir);
-      } else {
-	/*
-	 * try getting fs option from continuation, not mountpoint!
-	 * Don't try logging the string from mf, since it may be bad!
-	 */
-	if (cp->fs_opts.opt_fs != mf->mf_fo->opt_fs)
-	  plog(XLOG_ERROR, "use %s instead of 0x%lx",
-	       cp->fs_opts.opt_fs, (unsigned long) mf->mf_fo->opt_fs);
-
-	mp->am_link = str3cat((char *) 0,
-			      cp->fs_opts.opt_fs, "/", link_dir);
-
-	normalize_slash(mp->am_link);
-      }
-    }
-
-    if (mf->mf_error > 0) {
-      this_error = mf->mf_error;
-    } else if (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)) {
-      /*
-       * Still mounting - retry later
-       */
-#ifdef DEBUG
-      dlog("Duplicate pending mount fstype %s", p->fs_type);
-#endif /* DEBUG */
-      this_error = -1;
-    } else if (FSRV_ISDOWN(mf->mf_server)) {
-      /*
-       * Would just mount from the same place
-       * as a hung mount - so give up
-       */
-#ifdef DEBUG
-      dlog("%s is already hung - giving up", mf->mf_mount);
-#endif /* DEBUG */
-      mp_error = EWOULDBLOCK;
-      dont_retry = TRUE;
-      this_error = -1;
-    } else if (mf->mf_flags & MFF_MOUNTED) {
-#ifdef DEBUG
-      dlog("duplicate mount of \"%s\" ...", mf->mf_info);
-#endif /* DEBUG */
-
-      /*
-       * Just call mounted()
-       */
-      am_mounted(mp);
-
-      this_error = 0;
-      break;
-    }
-
-    /*
-     * Will usually need to play around with the mount nodes
-     * file attribute structure.  This must be done here.
-     * Try and get things initialized, even if the fileserver
-     * is not known to be up.  In the common case this will
-     * progress things faster.
-     */
-    if (!this_error) {
-      /*
-       * Fill in attribute fields.
-       */
-      if (mf->mf_ops->fs_flags & FS_DIRECTORY)
-	mk_fattr(mp, NFDIR);
-      else
-	mk_fattr(mp, NFLNK);
-
-      mp->am_fattr.na_fileid = mp->am_gen;
-
-      if (p->fs_init)
-	this_error = (*p->fs_init) (mf);
-    }
-
-    /*
-     * Make sure the fileserver is UP before doing any more work
-     */
-    if (!FSRV_ISUP(mf->mf_server)) {
-#ifdef DEBUG
-      dlog("waiting for server %s to become available", mf->mf_server->fs_host);
-#endif /* DEBUG */
-      this_error = -1;
-    }
-
-    if (!this_error && mf->mf_fo->opt_delay) {
-      /*
-       * If there is a delay timer on the mount
-       * then don't try to mount if the timer
-       * has not expired.
-       */
-      int i = atoi(mf->mf_fo->opt_delay);
-      if (i > 0 && clocktime() < (cp->start + i)) {
-#ifdef DEBUG
-	dlog("Mount of %s delayed by %lds", mf->mf_mount, i - clocktime() + cp->start);
-#endif /* DEBUG */
-	this_error = -1;
-      }
-    }
-
-    if (this_error < 0 && !dont_retry) {
-      if (!mf_retry)
-	mf_retry = dup_mntfs(mf);
-      cp->retry = TRUE;
-    }
-
-    if (!this_error) {
-      if (p->fs_flags & FS_MBACKGROUND) {
-	mf->mf_flags |= MFF_MOUNTING;	/* XXX */
-#ifdef DEBUG
-	dlog("backgrounding mount of \"%s\"", mf->mf_mount);
-#endif /* DEBUG */
-	if (cp->callout) {
-	  untimeout(cp->callout);
-	  cp->callout = 0;
-	}
-	run_task(try_mount, (voidp) mp, amfs_auto_cont, (voidp) cp);
-	mf->mf_flags |= MFF_MKMNT;	/* XXX */
-	if (mf_retry)
-	  free_mntfs(mf_retry);
-	return -1;
-      } else {
-#ifdef DEBUG
-	dlog("foreground mount of \"%s\" ...", mf->mf_info);
-#endif /* DEBUG */
-	this_error = try_mount((voidp) mp);
-	if (this_error < 0) {
-	  if (!mf_retry)
-	    mf_retry = dup_mntfs(mf);
-	  cp->retry = TRUE;
-	}
-      }
-    }
-
-    if (this_error >= 0) {
-      if (this_error > 0) {
-	amd_stats.d_merr++;
-	if (mf != mf_retry) {
-	  mf->mf_error = this_error;
-	  mf->mf_flags |= MFF_ERROR;
-	}
-      }
-
-      /*
-       * Wakeup anything waiting for this mount
-       */
-      wakeup((voidp) mf);
-    }
-  }
-
-  if (this_error && cp->retry) {
-    free_mntfs(mf);
-    mf = cp->mp->am_mnt = mf_retry;
-    /*
-     * Not retrying again (so far)
-     */
-    cp->retry = FALSE;
-    cp->tried = FALSE;
-    /*
-     * Start at the beginning.
-     * Rewind the location vector and
-     * reset the default options.
-     */
-    cp->ivec = cp->xivec;
-    cp->def_opts = strealloc(cp->def_opts, cp->auto_opts);
-    /*
-     * Arrange that autofs_bgmount is called
-     * after anything else happens.
-     */
-#ifdef DEBUG
-    dlog("Arranging to retry mount of %s", cp->mp->am_path);
-#endif /* DEBUG */
-    sched_task(amfs_auto_retry, (voidp) cp, (voidp) mf);
-    if (cp->callout)
-      untimeout(cp->callout);
-    cp->callout = timeout(RETRY_INTERVAL, wakeup, (voidp) mf);
-
-    cp->mp->am_ttl = clocktime() + RETRY_INTERVAL;
-
-    /*
-     * Not done yet - so don't return anything
-     */
-    return -1;
-  }
-
-  if (hard_error < 0 || this_error == 0)
-    hard_error = this_error;
-
-  /*
-   * Discard handle on duff filesystem.
-   * This should never happen since it
-   * should be caught by the case above.
-   */
-  if (mf_retry) {
-    if (hard_error)
-      plog(XLOG_ERROR, "discarding a retry mntfs for %s", mf_retry->mf_mount);
-    free_mntfs(mf_retry);
-  }
-
-  /*
-   * If we get here, then either the mount succeeded or
-   * there is no more mount information available.
-   */
-  if (hard_error < 0 && mp_error)
-    hard_error = cp->mp->am_error = mp_error;
-  if (hard_error > 0) {
-    /*
-     * Set a small(ish) timeout on an error node if
-     * the error was not a time out.
-     */
-    switch (hard_error) {
-    case ETIMEDOUT:
-    case EWOULDBLOCK:
-      cp->mp->am_timeo = 17;
-      break;
-    default:
-      cp->mp->am_timeo = 5;
-      break;
-    }
-    new_ttl(cp->mp);
-  }
-
-  /*
-   * Make sure that the error value in the mntfs has a
-   * reasonable value.
-   */
-  if (mf->mf_error < 0) {
-    mf->mf_error = hard_error;
-    if (hard_error)
-      mf->mf_flags |= MFF_ERROR;
-  }
-
-  /*
-   * In any case we don't need the continuation any more
-   */
-  free_continuation(cp);
-
-  return hard_error;
-}
-
-
-/*
- * Automount interface to RPC lookup routine
- * Find the corresponding entry and return
- * the file handle for it.
- */
-am_node *
-autofs_lookuppn(am_node *mp, char *fname, int *error_return, int op)
-{
-  am_node *ap, *new_mp, *ap_hung;
-  char *info;			/* Mount info - where to get the file system */
-  char **ivec, **xivec;		/* Split version of info */
-  char *auto_opts;		/* Automount options */
-  int error = 0;		/* Error so far */
-  char path_name[MAXPATHLEN];	/* General path name buffer */
-  char apath[MAXPATHLEN];	/* autofs path (added space) */
-  char *pfname;			/* Path for database lookup */
-  struct continuation *cp;	/* Continuation structure if need to mount */
-  int in_progress = 0;		/* # of (un)mount in progress */
-  char *dflts;
-  mntfs *mf;
-
-#ifdef DEBUG
-  dlog("in autofs_lookuppn");
-#endif /* DEBUG */
-
-  /*
-   * If the server is shutting down
-   * then don't return information
-   * about the mount point.
-   */
-  if (amd_state == Finishing) {
-#ifdef DEBUG
-    if ((mf = mp->am_mnt) == 0 || mf->mf_ops == &amfs_direct_ops) {
-      dlog("%s mount ignored - going down", fname);
-    } else {
-      dlog("%s/%s mount ignored - going down", mp->am_path, fname);
-    }
-#endif /* DEBUG */
-    ereturn(ENOENT);
-  }
-
-  /*
-   * Handle special case of "." and ".."
-   */
-  if (fname[0] == '.') {
-    if (fname[1] == '\0')
-      return mp;		/* "." is the current node */
-    if (fname[1] == '.' && fname[2] == '\0') {
-      if (mp->am_parent) {
-#ifdef DEBUG
-	dlog(".. in %s gives %s", mp->am_path, mp->am_parent->am_path);
-#endif /* DEBUG */
-	return mp->am_parent;	/* ".." is the parent node */
-      }
-      ereturn(ESTALE);
-    }
-  }
-
-  /*
-   * Check for valid key name.
-   * If it is invalid then pretend it doesn't exist.
-   */
-  if (!valid_key(fname)) {
-    plog(XLOG_WARNING, "Key \"%s\" contains a disallowed character", fname);
-    ereturn(ENOENT);
-  }
-
-  /*
-   * Expand key name.
-   * fname is now a private copy.
-   */
-  fname = expand_key(fname);
-
-  for (ap_hung = 0, ap = mp->am_child; ap; ap = ap->am_osib) {
-    /*
-     * Otherwise search children of this node
-     */
-    if (FSTREQ(ap->am_name, fname)) {
-      mf = ap->am_mnt;
-      if (ap->am_error) {
-	error = ap->am_error;
-	continue;
-      }
-      /*
-       * If the error code is undefined then it must be
-       * in progress.
-       */
-      if (mf->mf_error < 0)
-	goto in_progrss;
-
-      /*
-       * Check for a hung node
-       */
-      if (FSRV_ISDOWN(mf->mf_server)) {
-#ifdef DEBUG
-	dlog("server hung");
-#endif /* DEBUG */
-	error = ap->am_error;
-	ap_hung = ap;
-	continue;
-      }
-      /*
-       * If there was a previous error with this node
-       * then return that error code.
-       */
-      if (mf->mf_flags & MFF_ERROR) {
-	error = mf->mf_error;
-	continue;
-      }
-      if (!(mf->mf_flags & MFF_MOUNTED) || (mf->mf_flags & MFF_UNMOUNTING)) {
-      in_progrss:
-	/*
-	 * If the fs is not mounted or it is unmounting then there
-	 * is a background (un)mount in progress.  In this case
-	 * we just drop the RPC request (return nil) and
-	 * wait for a retry, by which time the (un)mount may
-	 * have completed.
-	 */
-#ifdef DEBUG
-	dlog("ignoring mount of %s in %s -- flags (%x) in progress",
-	     fname, mf->mf_mount, mf->mf_flags);
-#endif /* DEBUG */
-	in_progress++;
-	continue;
-      }
-
-      /*
-       * Otherwise we have a hit: return the current mount point.
-       */
-#ifdef DEBUG
-      dlog("matched %s in %s", fname, ap->am_path);
-#endif /* DEBUG */
-      XFREE(fname);
-      return ap;
-    }
-  }
-
-  if (in_progress) {
-#ifdef DEBUG
-    dlog("Waiting while %d mount(s) in progress", in_progress);
-#endif /* DEBUG */
-    XFREE(fname);
-    ereturn(-1);
-  }
-
-  /*
-   * If an error occurred then return it.
-   */
-  if (error) {
-#ifdef DEBUG
-    errno = error;		/* XXX */
-    dlog("Returning error: %m");
-#endif /* DEBUG */
-    XFREE(fname);
-    ereturn(error);
-  }
-
-  /*
-   * If doing a delete then don't create again!
-   */
-  switch (op) {
-  case VLOOK_DELETE:
-    ereturn(ENOENT);
-
-  case VLOOK_CREATE:
-    break;
-
-  default:
-    plog(XLOG_FATAL, "Unknown op to autofs_lookuppn: 0x%x", op);
-    ereturn(EINVAL);
-  }
-
-  /*
-   * If the server is going down then just return,
-   * don't try to mount any more file systems
-   */
-  if ((int) amd_state >= (int) Finishing) {
-#ifdef DEBUG
-    dlog("not found - server going down anyway");
-#endif /* DEBUG */
-    XFREE(fname);
-    ereturn(ENOENT);
-  }
-
-  /*
-   * If we get there then this is a reference to an,
-   * as yet, unknown name so we need to search the mount
-   * map for it.
-   */
-  if (mp->am_pref) {
-    sprintf(path_name, "%s%s", mp->am_pref, fname);
-    pfname = path_name;
-  } else {
-    pfname = fname;
-  }
-
-  mf = mp->am_mnt;
-
-#ifdef DEBUG
-  dlog("will search map info in %s to find %s", mf->mf_info, pfname);
-#endif /* DEBUG */
-  /*
-   * Consult the oracle for some mount information.
-   * info is malloc'ed and belongs to this routine.
-   * It ends up being free'd in free_continuation().
-   *
-   * Note that this may return -1 indicating that information
-   * is not yet available.
-   */
-  error = mapc_search((mnt_map *) mf->mf_private, pfname, &info);
-  if (error) {
-    if (error > 0)
-      plog(XLOG_MAP, "No map entry for %s", pfname);
-    else
-      plog(XLOG_MAP, "Waiting on map entry for %s", pfname);
-    XFREE(fname);
-    ereturn(error);
-  }
-#ifdef DEBUG
-  dlog("mount info is %s", info);
-#endif /* DEBUG */
-
-  /*
-   * Split info into an argument vector.
-   * The vector is malloc'ed and belongs to
-   * this routine.  It is free'd in free_continuation()
-   */
-  xivec = ivec = strsplit(info, ' ', '\"');
-
-  /*
-   * Default error code...
-   */
-  if (ap_hung)
-    error = EWOULDBLOCK;
-  else
-    error = ENOENT;
-
-  /*
-   * Allocate a new map
-   */
-  new_mp = exported_ap_alloc();
-  if (new_mp == 0) {
-    XFREE(xivec);
-    XFREE(info);
-    XFREE(fname);
-    ereturn(ENOSPC);
-  }
-  if (mf->mf_auto)
-    auto_opts = mf->mf_auto;
-  else
-    auto_opts = "";
-
-  auto_opts = strdup(auto_opts);
-
-#ifdef DEBUG
-  dlog("searching for /defaults entry");
-#endif /* DEBUG */
-  if (mapc_search((mnt_map *) mf->mf_private, "/defaults", &dflts) == 0) {
-    char *dfl;
-    char **rvec;
-#ifdef DEBUG
-    dlog("/defaults gave %s", dflts);
-#endif /* DEBUG */
-    if (*dflts == '-')
-      dfl = dflts + 1;
-    else
-      dfl = dflts;
-
-    /*
-     * Chop the defaults up
-     */
-    rvec = strsplit(dfl, ' ', '\"');
-
-    if (gopt.flags & CFM_ENABLE_DEFAULT_SELECTORS) {
-      /*
-       * Pick whichever first entry matched the list of selectors.
-       * Strip the selectors from the string, and assign to dfl the
-       * rest of the string.
-       */
-      if (rvec) {
-	am_opts ap;
-	am_ops *pt;
-	char **sp = rvec;
-	while (*sp) {		/* loop until you find something, if any */
-	  memset((char *) &ap, 0, sizeof(am_opts));
-	  pt = ops_match(&ap, *sp, "", mp->am_path, "/defaults",
-			 mp->am_parent->am_mnt->mf_info);
-	  free_opts(&ap);	/* don't leak */
-	  if (pt == &amfs_error_ops) {
-	    plog(XLOG_MAP, "failed to match defaults for \"%s\"", *sp);
-	  } else {
-	    dfl = strip_selectors(*sp, "/defaults");
-	    plog(XLOG_MAP, "matched default selectors \"%s\"", dfl);
-	    break;
-	  }
-	  ++sp;
-	}
-      }
-    } else {			/* not enable_default_selectors */
-      /*
-       * Extract first value
-       */
-      dfl = rvec[0];
-    }
-
-    /*
-     * If there were any values at all...
-     */
-    if (dfl) {
-      /*
-       * Log error if there were other values
-       */
-      if (!(gopt.flags & CFM_ENABLE_DEFAULT_SELECTORS) && rvec[1]) {
-# ifdef DEBUG
-	dlog("/defaults chopped into %s", dfl);
-# endif /* DEBUG */
-	plog(XLOG_USER, "More than a single value for /defaults in %s", mf->mf_info);
-      }
-
-      /*
-       * Prepend to existing defaults if they exist,
-       * otherwise just use these defaults.
-       */
-      if (*auto_opts && *dfl) {
-	char *nopts = (char *) xmalloc(strlen(auto_opts) + strlen(dfl) + 2);
-	sprintf(nopts, "%s;%s", dfl, auto_opts);
-	XFREE(auto_opts);
-	auto_opts = nopts;
-      } else if (*dfl) {
-	auto_opts = strealloc(auto_opts, dfl);
-      }
-    }
-    XFREE(dflts);
-    /*
-     * Don't need info vector any more
-     */
-    XFREE(rvec);
-  }
-
-  /*
-   * Fill it in
-   */
-  init_map(new_mp, fname);
-
-  /*
-   * Turn on autofs flag if needed.
-   */
-  if (mp->am_flags & AMF_AUTOFS) {
-    new_mp->am_flags |= AMF_AUTOFS;
-  }
-
-  /*
-   * Put it in the table
-   */
-  insert_am(new_mp, mp);
-
-  /*
-   * Fill in some other fields,
-   * path and mount point.
-   *
-   * bugfix: do not prepend old am_path if direct map
-   *         <wls@astro.umd.edu> William Sebok
-   */
-
-  strcpy(apath, fname);
-  strcat(apath, " ");
-  new_mp->am_path = str3cat(new_mp->am_path,
-			    mf->mf_ops == &amfs_direct_ops ? "" : mp->am_path,
-			    *fname == '/' ? "" : "/",
-			    apath);
-
-#ifdef DEBUG
-  dlog("setting path to \"%s\"", new_mp->am_path);
-#endif /* DEBUG */
-
-  /*
-   * Take private copy of pfname
-   */
-  pfname = strdup(pfname);
-
-  /*
-   * Construct a continuation
-   */
-  cp = ALLOC(struct continuation);
-  cp->callout = 0;
-  cp->mp = new_mp;
-  cp->xivec = xivec;
-  cp->ivec = ivec;
-  cp->info = info;
-  cp->key = pfname;
-  cp->auto_opts = auto_opts;
-  cp->retry = FALSE;
-  cp->tried = FALSE;
-  cp->start = clocktime();
-  cp->def_opts = strdup(auto_opts);
-  memset((voidp) &cp->fs_opts, 0, sizeof(cp->fs_opts));
-
-  /*
-   * Try and mount the file system.  If this succeeds immediately (possible
-   * for a ufs file system) then return the attributes, otherwise just
-   * return an error.
-   */
-  error = autofs_bgmount(cp, error);
-  reschedule_timeout_mp();
-  if (!error) {
-    XFREE(fname);
-    return new_mp;
-  }
-
-  /*
-   * Code for quick reply.  If nfs_program_2_transp is set, then
-   * its the transp that's been passed down from nfs_program_2().
-   * If new_mp->am_transp is not already set, set it by copying in
-   * nfs_program_2_transp.  Once am_transp is set, quick_reply() can
-   * use it to send a reply to the client that requested this mount.
-   */
-  if (nfs_program_2_transp && !new_mp->am_transp) {
-    new_mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT));
-    *(new_mp->am_transp) = *nfs_program_2_transp;
-  }
-  if (error && (new_mp->am_mnt->mf_ops == &amfs_error_ops))
-    new_mp->am_error = error;
-
-  assign_error_mntfs(new_mp);
-
-  XFREE(fname);
-
-  ereturn(error);
-}
-#endif /* HAVE_FS_AUTOFS */
diff --git a/contrib/amd/amd/ops_cachefs.c b/contrib/amd/amd/ops_cachefs.c
index adb7583..d3e303b 100644
--- a/contrib/amd/amd/ops_cachefs.c
+++ b/contrib/amd/amd/ops_cachefs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_cachefs.c,v 1.2 1999/01/10 21:53:49 ezk Exp $
+ * File: am-utils/amd/ops_cachefs.c
  *
  */
 
@@ -55,8 +54,8 @@
 /* forward declarations */
 static char *cachefs_match(am_opts *fo);
 static int cachefs_init(mntfs *mf);
-static int cachefs_fmount(mntfs *mf);
-static int cachefs_fumount(mntfs *mf);
+static int cachefs_mount(am_node *am, mntfs *mf);
+static int cachefs_umount(am_node *am, mntfs *mf);
 
 
 /*
@@ -67,17 +66,20 @@ am_ops cachefs_ops =
   "cachefs",
   cachefs_match,
   cachefs_init,
-  amfs_auto_fmount,
-  cachefs_fmount,
-  amfs_auto_fumount,
-  cachefs_fumount,
-  amfs_error_lookuppn,
+  cachefs_mount,
+  cachefs_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* cachefs_readlink */
-  0,				/* post-mount actions */
-  0,				/* post-umount actions */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
+  0,				/* cachefs_mounted */
+  0,				/* cachefs_umounted */
+  amfs_generic_find_srvr,
+  0,				/* cachefs_get_wchan */
+  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_CACHEFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -94,9 +96,7 @@ cachefs_match(am_opts *fo)
     return NULL;
   }
 
-#ifdef DEBUG
   dlog("CACHEFS: using cache directory \"%s\"", fo->opt_cachedir);
-#endif /* DEBUG */
 
   /* determine magic cookie to put in mtab */
   return strdup(fo->opt_cachedir);
@@ -113,7 +113,7 @@ cachefs_init(mntfs *mf)
   /*
    * Save cache directory name
    */
-  if (mf->mf_refc == 1) {
+  if (!mf->mf_private) {
     mf->mf_private = (voidp) strdup(mf->mf_fo->opt_cachedir);
     mf->mf_prfree = (void (*)(voidp)) free;
   }
@@ -128,7 +128,8 @@ cachefs_init(mntfs *mf)
  * cachedir is the cache directory ($cachedir)
  */
 static int
-mount_cachefs(char *mntpt, char *backdir, char *cachedir, char *opts)
+mount_cachefs(char *mntdir, char *backdir, char *cachedir,
+	      char *opts, int on_autofs)
 {
   cachefs_args_t ca;
   mntent_t mnt;
@@ -142,12 +143,16 @@ mount_cachefs(char *mntpt, char *backdir, char *cachedir, char *opts)
    * Fill in the mount structure
    */
   memset((voidp) &mnt, 0, sizeof(mnt));
-  mnt.mnt_dir = mntpt;
+  mnt.mnt_dir = mntdir;
   mnt.mnt_fsname = backdir;
   mnt.mnt_type = MNTTAB_TYPE_CACHEFS;
   mnt.mnt_opts = opts;
 
   flags = compute_mount_flags(&mnt);
+#ifdef HAVE_FS_AUTOFS
+  if (on_autofs)
+    flags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
 
   /* Fill in cachefs mount arguments */
 
@@ -170,8 +175,13 @@ mount_cachefs(char *mntpt, char *backdir, char *cachedir, char *opts)
 
   /* CFS fscdir name */
   memset(ca.cfs_cacheid, 0, sizeof(ca.cfs_cacheid));
-  /* append cacheid and mountpoint */
-  sprintf(ca.cfs_cacheid, "%s:%s", ca.cfs_fsid, mntpt);
+  /*
+   * Append cacheid and mountpoint.
+   * sizeof(cfs_cacheid) should be C_MAX_MOUNT_FSCDIRNAME as per
+   * <sys/fs/cachefs_fs.h> (checked on Solaris 8).
+   */
+  xsnprintf(ca.cfs_cacheid, sizeof(ca.cfs_cacheid),
+	    "%s:%s", ca.cfs_fsid, mntdir);
   /* convert '/' to '_' (Solaris does that...) */
   cp = ca.cfs_cacheid;
   while ((cp = strpbrk(cp, "/")) != NULL)
@@ -192,19 +202,21 @@ mount_cachefs(char *mntpt, char *backdir, char *cachedir, char *opts)
   /*
    * Call generic mount routine
    */
-  return mount_fs(&mnt, flags, (caddr_t) &ca, 0, type, 0, NULL, mnttab_file_name);
+  return mount_fs(&mnt, flags, (caddr_t) &ca, 0, type, 0, NULL, mnttab_file_name, on_autofs);
 }
 
 
 static int
-cachefs_fmount(mntfs *mf)
+cachefs_mount(am_node *am, mntfs *mf)
 {
+  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
   int error;
 
   error = mount_cachefs(mf->mf_mount,
 			mf->mf_fo->opt_rfs,
 			mf->mf_fo->opt_cachedir,
-			mf->mf_mopts);
+			mf->mf_mopts,
+			on_autofs);
   if (error) {
     errno = error;
     /* according to Solaris, if errno==ESRCH, "options to not match" */
@@ -220,11 +232,12 @@ cachefs_fmount(mntfs *mf)
 
 
 static int
-cachefs_fumount(mntfs *mf)
+cachefs_umount(am_node *am, mntfs *mf)
 {
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
   int error;
 
-  error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
+  error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 
   /*
    * In the case of cachefs, we must fsck the cache directory.  Otherwise,
@@ -239,7 +252,7 @@ cachefs_fumount(mntfs *mf)
 
     cachedir = (char *) mf->mf_private;
     plog(XLOG_INFO, "running fsck on cache directory \"%s\"", cachedir);
-    sprintf(cmd, "fsck -F cachefs %s", cachedir);
+    xsnprintf(cmd, sizeof(cmd), "fsck -F cachefs %s", cachedir);
     system(cmd);
   }
 
diff --git a/contrib/amd/amd/ops_cdfs.c b/contrib/amd/amd/ops_cdfs.c
index 0f104d6..40355ac 100644
--- a/contrib/amd/amd/ops_cdfs.c
+++ b/contrib/amd/amd/ops_cdfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_cdfs.c,v 1.3 1999/03/30 17:22:46 ezk Exp $
+ * File: am-utils/amd/ops_cdfs.c
  *
  */
 
@@ -54,8 +53,8 @@
 
 /* forward declarations */
 static char *cdfs_match(am_opts *fo);
-static int cdfs_fmount(mntfs *mf);
-static int cdfs_fumount(mntfs *mf);
+static int cdfs_mount(am_node *am, mntfs *mf);
+static int cdfs_umount(am_node *am, mntfs *mf);
 
 /*
  * Ops structure
@@ -65,17 +64,20 @@ am_ops cdfs_ops =
   "cdfs",
   cdfs_match,
   0,				/* cdfs_init */
-  amfs_auto_fmount,
-  cdfs_fmount,
-  amfs_auto_fumount,
-  cdfs_fumount,
-  amfs_error_lookuppn,
+  cdfs_mount,
+  cdfs_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* cdfs_readlink */
   0,				/* cdfs_mounted */
   0,				/* cdfs_umounted */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
+  amfs_generic_find_srvr,
+  0,				/* cdfs_get_wchan */
+  FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO,	/* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_CDFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -89,10 +91,8 @@ cdfs_match(am_opts *fo)
     plog(XLOG_USER, "cdfs: no source device specified");
     return 0;
   }
-#ifdef DEBUG
   dlog("CDFS: mounting device \"%s\" on \"%s\"",
        fo->opt_dev, fo->opt_fs);
-#endif /* DEBUG */
 
   /*
    * Determine magic cookie to put in mtab
@@ -102,11 +102,11 @@ cdfs_match(am_opts *fo)
 
 
 static int
-mount_cdfs(char *dir, char *fs_name, char *opts)
+mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
 {
   cdfs_args_t cdfs_args;
   mntent_t mnt;
-  int genflags, cdfs_flags;
+  int genflags, cdfs_flags, retval;
 
   /*
    * Figure out the name of the file system type.
@@ -120,13 +120,13 @@ mount_cdfs(char *dir, char *fs_name, char *opts)
    * Fill in the mount structure
    */
   memset((voidp) &mnt, 0, sizeof(mnt));
-  mnt.mnt_dir = dir;
+  mnt.mnt_dir = mntdir;
   mnt.mnt_fsname = fs_name;
   mnt.mnt_type = MNTTAB_TYPE_CDFS;
   mnt.mnt_opts = opts;
 
 #if defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM)
-  if (hasmntopt(&mnt, MNTTAB_OPT_DEFPERM))
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_DEFPERM))
 # ifdef MNT2_CDFS_OPT_DEFPERM
     cdfs_flags |= MNT2_CDFS_OPT_DEFPERM;
 # else /* not MNT2_CDFS_OPT_DEFPERM */
@@ -135,74 +135,81 @@ mount_cdfs(char *dir, char *fs_name, char *opts)
 #endif /* defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM) */
 
 #if defined(MNT2_CDFS_OPT_NODEFPERM) && defined(MNTTAB_OPT_NODEFPERM)
-  if (hasmntopt(&mnt, MNTTAB_OPT_NODEFPERM))
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NODEFPERM))
     cdfs_flags |= MNT2_CDFS_OPT_NODEFPERM;
 #endif /* MNTTAB_OPT_NODEFPERM */
 
 #if defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION)
-  if (hasmntopt(&mnt, MNTTAB_OPT_NOVERSION))
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOVERSION))
     cdfs_flags |= MNT2_CDFS_OPT_NOVERSION;
 #endif /* defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION) */
 
 #if defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP)
-  if (hasmntopt(&mnt, MNTTAB_OPT_RRIP))
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRIP))
     cdfs_flags |= MNT2_CDFS_OPT_RRIP;
 #endif /* defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) */
 #if defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP)
-  if (hasmntopt(&mnt, MNTTAB_OPT_NORRIP))
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NORRIP))
     cdfs_flags |= MNT2_CDFS_OPT_NORRIP;
 #endif /* defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP) */
 
 #if defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS)
-  if (hasmntopt(&mnt, MNTTAB_OPT_GENS))
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_GENS))
     cdfs_flags |= MNT2_CDFS_OPT_GENS;
 #endif /* defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS) */
 #if defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT)
-  if (hasmntopt(&mnt, MNTTAB_OPT_EXTATT))
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_EXTATT))
     cdfs_flags |= MNT2_CDFS_OPT_EXTATT;
 #endif /* defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) */
 
   genflags = compute_mount_flags(&mnt);
+#ifdef HAVE_FS_AUTOFS
+  if (on_autofs)
+    genflags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
 
-#ifdef HAVE_FIELD_CDFS_ARGS_T_FLAGS
+#ifdef HAVE_CDFS_ARGS_T_FLAGS
   cdfs_args.flags = cdfs_flags;
-#endif /* HAVE_FIELD_CDFS_ARGS_T_FLAGS */
+#endif /* HAVE_CDFS_ARGS_T_FLAGS */
 
-#ifdef HAVE_FIELD_CDFS_ARGS_T_ISO_FLAGS
+#ifdef HAVE_CDFS_ARGS_T_ISO_FLAGS
   cdfs_args.iso_flags = genflags | cdfs_flags;
-#endif /* HAVE_FIELD_CDFS_ARGS_T_ISO_FLAGS */
+#endif /* HAVE_CDFS_ARGS_T_ISO_FLAGS */
 
-#ifdef HAVE_FIELD_CDFS_ARGS_T_ISO_PGTHRESH
+#ifdef HAVE_CDFS_ARGS_T_ISO_PGTHRESH
   cdfs_args.iso_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH);
-#endif /* HAVE_FIELD_CDFS_ARGS_T_ISO_PGTHRESH */
+#endif /* HAVE_CDFS_ARGS_T_ISO_PGTHRESH */
 
-#ifdef HAVE_FIELD_CDFS_ARGS_T_FSPEC
-  cdfs_args.fspec = fs_name;
-#endif /* HAVE_FIELD_CDFS_ARGS_T_FSPEC */
-
-#ifdef HAVE_FIELD_CDFS_ARGS_T_NORRIP
+#ifdef HAVE_CDFS_ARGS_T_NORRIP
   /* XXX: need to provide norrip mount opt */
   cdfs_args.norrip = 0;		/* use Rock-Ridge Protocol extensions */
-#endif /* HAVE_FIELD_CDFS_ARGS_T_NORRIP */
+#endif /* HAVE_CDFS_ARGS_T_NORRIP */
 
-#ifdef HAVE_FIELD_CDFS_ARGS_T_SSECTOR
+#ifdef HAVE_CDFS_ARGS_T_SSECTOR
   /* XXX: need to provide ssector mount option */
   cdfs_args.ssector = 0;	/* use 1st session on disk */
-#endif /* HAVE_FIELD_CDFS_ARGS_T_SSECTOR */
+#endif /* HAVE_CDFS_ARGS_T_SSECTOR */
+
+#ifdef HAVE_CDFS_ARGS_T_FSPEC
+  cdfs_args.fspec = fs_name;
+#endif /* HAVE_CDFS_ARGS_T_FSPEC */
 
   /*
    * Call generic mount routine
    */
-  return mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name);
+  retval = mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
+
+  return retval;
 }
 
 
 static int
-cdfs_fmount(mntfs *mf)
+cdfs_mount(am_node *am, mntfs *mf)
 {
+  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
   int error;
 
-  error = mount_cdfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
+  error = mount_cdfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
   if (error) {
     errno = error;
     plog(XLOG_ERROR, "mount_cdfs: %m");
@@ -213,7 +220,9 @@ cdfs_fmount(mntfs *mf)
 
 
 static int
-cdfs_fumount(mntfs *mf)
+cdfs_umount(am_node *am, mntfs *mf)
 {
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
diff --git a/contrib/amd/amd/ops_efs.c b/contrib/amd/amd/ops_efs.c
index 5c8b27e..047fe1e 100644
--- a/contrib/amd/amd/ops_efs.c
+++ b/contrib/amd/amd/ops_efs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_efs.c,v 1.2 1999/01/10 21:53:49 ezk Exp $
+ * File: am-utils/amd/ops_efs.c
  *
  */
 
@@ -54,8 +53,8 @@
 
 /* forward declarations */
 static char *efs_match(am_opts *fo);
-static int efs_fmount(mntfs *mf);
-static int efs_fumount(mntfs *mf);
+static int efs_mount(am_node *am, mntfs *mf);
+static int efs_umount(am_node *am, mntfs *mf);
 
 /*
  * Ops structure
@@ -65,17 +64,20 @@ am_ops efs_ops =
   "efs",
   efs_match,
   0,				/* efs_init */
-  amfs_auto_fmount,
-  efs_fmount,
-  amfs_auto_fumount,
-  efs_fumount,
-  amfs_error_lookuppn,
+  efs_mount,
+  efs_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* efs_readlink */
   0,				/* efs_mounted */
   0,				/* efs_umounted */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
+  amfs_generic_find_srvr,
+  0,				/* efs_get_wchan */
+  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_EFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -91,9 +93,7 @@ efs_match(am_opts *fo)
     return 0;
   }
 
-#ifdef DEBUG
   dlog("EFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
-#endif /* DEBUG */
 
   /*
    * Determine magic cookie to put in mtab
@@ -103,7 +103,7 @@ efs_match(am_opts *fo)
 
 
 static int
-mount_efs(char *dir, char *fs_name, char *opts)
+mount_efs(char *mntdir, char *fs_name, char *opts, int on_autofs)
 {
   efs_args_t efs_args;
   mntent_t mnt;
@@ -120,33 +120,38 @@ mount_efs(char *dir, char *fs_name, char *opts)
    * Fill in the mount structure
    */
   memset((voidp) &mnt, 0, sizeof(mnt));
-  mnt.mnt_dir = dir;
+  mnt.mnt_dir = mntdir;
   mnt.mnt_fsname = fs_name;
   mnt.mnt_type = MNTTAB_TYPE_EFS;
   mnt.mnt_opts = opts;
 
   flags = compute_mount_flags(&mnt);
+#ifdef HAVE_FS_AUTOFS
+  if (on_autofs)
+    flags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
 
-#ifdef HAVE_FIELD_EFS_ARGS_T_FLAGS
+#ifdef HAVE_EFS_ARGS_T_FLAGS
   efs_args.flags = 0;		/* XXX: fix this to correct flags */
-#endif /* HAVE_FIELD_EFS_ARGS_T_FLAGS */
-#ifdef HAVE_FIELD_EFS_ARGS_T_FSPEC
+#endif /* HAVE_EFS_ARGS_T_FLAGS */
+#ifdef HAVE_EFS_ARGS_T_FSPEC
   efs_args.fspec = fs_name;
-#endif /* HAVE_FIELD_EFS_ARGS_T_FSPEC */
+#endif /* HAVE_EFS_ARGS_T_FSPEC */
 
   /*
    * Call generic mount routine
    */
-  return mount_fs(&mnt, flags, (caddr_t) &efs_args, 0, type, 0, NULL, mnttab_file_name);
+  return mount_fs(&mnt, flags, (caddr_t) &efs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
 }
 
 
 static int
-efs_fmount(mntfs *mf)
+efs_mount(am_node *am, mntfs *mf)
 {
+  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
   int error;
 
-  error = mount_efs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
+  error = mount_efs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
   if (error) {
     errno = error;
     plog(XLOG_ERROR, "mount_efs: %m");
@@ -158,7 +163,10 @@ efs_fmount(mntfs *mf)
 
 
 static int
-efs_fumount(mntfs *mf)
+efs_umount(am_node *am, mntfs *mf)
 {
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
+
diff --git a/contrib/amd/amd/ops_lofs.c b/contrib/amd/amd/ops_lofs.c
index a7cccba..26fdc9f 100644
--- a/contrib/amd/amd/ops_lofs.c
+++ b/contrib/amd/amd/ops_lofs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_lofs.c,v 1.2 1999/01/10 21:53:49 ezk Exp $
+ * File: am-utils/amd/ops_lofs.c
  *
  */
 
@@ -53,11 +52,9 @@
 #include <amd.h>
 
 /* forward definitions */
-static char * lofs_match(am_opts *fo);
-static int lofs_fmount(mntfs *mf);
-static int lofs_fumount(mntfs *mf);
-static int mount_lofs(char *dir, char *fs_name, char *opts);
-
+static char *lofs_match(am_opts *fo);
+static int lofs_mount(am_node *am, mntfs *mf);
+static int lofs_umount(am_node *am, mntfs *mf);
 
 /*
  * Ops structure
@@ -67,17 +64,20 @@ am_ops lofs_ops =
   "lofs",
   lofs_match,
   0,				/* lofs_init */
-  amfs_auto_fmount,
-  lofs_fmount,
-  amfs_auto_fumount,
-  lofs_fumount,
-  amfs_error_lookuppn,
+  lofs_mount,
+  lofs_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* lofs_readlink */
   0,				/* lofs_mounted */
   0,				/* lofs_umounted */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
+  amfs_generic_find_srvr,
+  0,				/* lofs_get_wchan */
+  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_LOFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -91,10 +91,8 @@ lofs_match(am_opts *fo)
     plog(XLOG_USER, "lofs: no source filesystem specified");
     return 0;
   }
-#ifdef DEBUG
   dlog("LOFS: mounting fs \"%s\" on \"%s\"",
        fo->opt_rfs, fo->opt_fs);
-#endif /* DEBUG */
 
   /*
    * Determine magic cookie to put in mtab
@@ -103,8 +101,8 @@ lofs_match(am_opts *fo)
 }
 
 
-static int
-mount_lofs(char *dir, char *fs_name, char *opts)
+int
+mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs)
 {
   mntent_t mnt;
   int flags;
@@ -118,26 +116,31 @@ mount_lofs(char *dir, char *fs_name, char *opts)
    * Fill in the mount structure
    */
   memset((voidp) &mnt, 0, sizeof(mnt));
-  mnt.mnt_dir = dir;
+  mnt.mnt_dir = mntdir;
   mnt.mnt_fsname = fs_name;
   mnt.mnt_type = MNTTAB_TYPE_LOFS;
   mnt.mnt_opts = opts;
 
   flags = compute_mount_flags(&mnt);
+#ifdef HAVE_FS_AUTOFS
+  if (on_autofs)
+    flags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
 
   /*
    * Call generic mount routine
    */
-  return mount_fs(&mnt, flags, NULL, 0, type, 0, NULL, mnttab_file_name);
+  return mount_fs(&mnt, flags, NULL, 0, type, 0, NULL, mnttab_file_name, on_autofs);
 }
 
 
 static int
-lofs_fmount(mntfs *mf)
+lofs_mount(am_node *am, mntfs *mf)
 {
+  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
   int error;
 
-  error = mount_lofs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
+  error = mount_lofs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
   if (error) {
     errno = error;
     plog(XLOG_ERROR, "mount_lofs: %m");
@@ -148,7 +151,9 @@ lofs_fmount(mntfs *mf)
 
 
 static int
-lofs_fumount(mntfs *mf)
+lofs_umount(am_node *am, mntfs *mf)
 {
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
diff --git a/contrib/amd/amd/ops_mfs.c b/contrib/amd/amd/ops_mfs.c
index 87178b0..ccaa49c 100644
--- a/contrib/amd/amd/ops_mfs.c
+++ b/contrib/amd/amd/ops_mfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_mfs.c,v 1.2 1999/01/10 21:53:50 ezk Exp $
+ * File: am-utils/amd/ops_mfs.c
  *
  */
 
diff --git a/contrib/amd/amd/ops_nfs.c b/contrib/amd/amd/ops_nfs.c
index 01cdcee..a6a8585 100644
--- a/contrib/amd/amd/ops_nfs.c
+++ b/contrib/amd/amd/ops_nfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_nfs.c,v 1.5 1999/03/13 17:03:28 ezk Exp $
+ * File: am-utils/amd/ops_nfs.c
  *
  */
 
@@ -64,7 +63,7 @@
  */
 #define	FH_TTL			(5 * 60) /* five minutes */
 #define	FH_TTL_ERROR		(30) /* 30 seconds */
-#define	FHID_ALLOC(struct)	(++fh_id)
+#define	FHID_ALLOC()		(++fh_id)
 
 /*
  * The NFS layer maintains a cache of file handles.
@@ -92,19 +91,26 @@
 typedef struct fh_cache fh_cache;
 struct fh_cache {
   qelem			fh_q;		/* List header */
-  voidp			fh_wchan;	/* Wait channel */
+  wchan_t		fh_wchan;	/* Wait channel */
   int			fh_error;	/* Valid data? */
   int			fh_id;		/* Unique id */
   int			fh_cid;		/* Callout id */
   u_long		fh_nfs_version;	/* highest NFS version on host */
   am_nfs_handle_t	fh_nfs_handle;	/* Handle on filesystem */
+  int			fh_status;	/* Status of last rpc */
   struct sockaddr_in	fh_sin;		/* Address of mountd */
   fserver		*fh_fs;		/* Server holding filesystem */
   char			*fh_path;	/* Filesystem on host */
 };
 
 /* forward definitions */
-static int call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan);
+static int nfs_init(mntfs *mf);
+static char *nfs_match(am_opts *fo);
+static int nfs_mount(am_node *am, mntfs *mf);
+static int nfs_umount(am_node *am, mntfs *mf);
+static void nfs_umounted(mntfs *mf);
+static int call_mountd(fh_cache *fp, u_long proc, fwd_fun f, wchan_t wchan);
+static int webnfs_lookup(fh_cache *fp, fwd_fun f, wchan_t wchan);
 static int fh_id = 0;
 
 /* globals */
@@ -119,25 +125,28 @@ am_ops nfs_ops =
   "nfs",
   nfs_match,
   nfs_init,
-  amfs_auto_fmount,
-  nfs_fmount,
-  amfs_auto_fumount,
-  nfs_fumount,
-  amfs_error_lookuppn,
+  nfs_mount,
+  nfs_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* nfs_readlink */
   0,				/* nfs_mounted */
   nfs_umounted,
   find_nfs_srvr,
-  FS_MKMNT | FS_BACKGROUND | FS_AMQINFO
+  0,				/* nfs_get_wchan */
+  FS_MKMNT | FS_BACKGROUND | FS_AMQINFO,	/* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_NFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
 static fh_cache *
-find_nfs_fhandle_cache(voidp idv, int done)
+find_nfs_fhandle_cache(opaque_t arg, int done)
 {
   fh_cache *fp, *fp2 = 0;
-  int id = (long) idv;		/* for 64-bit archs */
+  int id = (long) arg;		/* for 64-bit archs */
 
   ITER(fp, fh_cache, &fh_head) {
     if (fp->fh_id == id) {
@@ -146,13 +155,11 @@ find_nfs_fhandle_cache(voidp idv, int done)
     }
   }
 
-#ifdef DEBUG
   if (fp2) {
     dlog("fh cache gives fp %#lx, fs %s", (unsigned long) fp2, fp2->fh_path);
   } else {
     dlog("fh cache search failed");
   }
-#endif /* DEBUG */
 
   if (fp2 && !done) {
     fp2->fh_error = ETIMEDOUT;
@@ -164,14 +171,18 @@ find_nfs_fhandle_cache(voidp idv, int done)
 
 
 /*
- * Called when a filehandle appears
+ * Called when a filehandle appears via the mount protocol
  */
 static void
-got_nfs_fh(voidp pkt, int len, struct sockaddr_in * sa, struct sockaddr_in * ia, voidp idv, int done)
+got_nfs_fh_mount(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done)
 {
   fh_cache *fp;
+  struct fhstatus res;
+#ifdef HAVE_FS_NFS3
+  struct am_mountres3 res3;
+#endif /* HAVE_FS_NFS3 */
 
-  fp = find_nfs_fhandle_cache(idv, done);
+  fp = find_nfs_fhandle_cache(arg, done);
   if (!fp)
     return;
 
@@ -180,28 +191,109 @@ got_nfs_fh(voidp pkt, int len, struct sockaddr_in * sa, struct sockaddr_in * ia,
    * NFS protocol version.
    */
 #ifdef HAVE_FS_NFS3
-  if (fp->fh_nfs_version == NFS_VERSION3)
-    fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_nfs_handle.v3,
-				    (XDRPROC_T_TYPE) xdr_mountres3);
-  else
+  if (fp->fh_nfs_version == NFS_VERSION3) {
+    memset(&res3, 0, sizeof(res3));
+    fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res3,
+				    (XDRPROC_T_TYPE) xdr_am_mountres3);
+    fp->fh_status = unx_error(res3.fhs_status);
+    memset(&fp->fh_nfs_handle.v3, 0, sizeof(am_nfs_fh3));
+    fp->fh_nfs_handle.v3.am_fh3_length = res3.mountres3_u.mountinfo.fhandle.fhandle3_len;
+    memmove(fp->fh_nfs_handle.v3.am_fh3_data,
+	    res3.mountres3_u.mountinfo.fhandle.fhandle3_val,
+	    fp->fh_nfs_handle.v3.am_fh3_length);
+  } else {
 #endif /* HAVE_FS_NFS3 */
-    fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_nfs_handle.v2,
+    memset(&res, 0, sizeof(res));
+    fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res,
 				    (XDRPROC_T_TYPE) xdr_fhstatus);
+    fp->fh_status = unx_error(res.fhs_status);
+    memmove(&fp->fh_nfs_handle.v2, &res.fhs_fh, NFS_FHSIZE);
+#ifdef HAVE_FS_NFS3
+  }
+#endif /* HAVE_FS_NFS3 */
 
   if (!fp->fh_error) {
-#ifdef DEBUG
     dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
-#endif /* DEBUG */
+  } else {
+    plog(XLOG_USER, "filehandle denied for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
+    /*
+     * Force the error to be EACCES. It's debatable whether it should be
+     * ENOENT instead, but the server really doesn't give us any clues, and
+     * EACCES is more in line with the "filehandle denied" message.
+     */
+    fp->fh_error = EACCES;
+  }
+
+  /*
+   * Wakeup anything sleeping on this filehandle
+   */
+  if (fp->fh_wchan) {
+    dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan);
+    wakeup(fp->fh_wchan);
+  }
+}
+
 
+/*
+ * Called when a filehandle appears via WebNFS
+ */
+static void
+got_nfs_fh_webnfs(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, opaque_t arg, int done)
+{
+  fh_cache *fp;
+  nfsdiropres res;
+#ifdef HAVE_FS_NFS3
+  am_LOOKUP3res res3;
+#endif /* HAVE_FS_NFS3 */
+
+  fp = find_nfs_fhandle_cache(arg, done);
+  if (!fp)
+    return;
+
+  /*
+   * retrieve the correct RPC reply for the file handle, based on the
+   * NFS protocol version.
+   */
+#ifdef HAVE_FS_NFS3
+  if (fp->fh_nfs_version == NFS_VERSION3) {
+    memset(&res3, 0, sizeof(res3));
+    fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res3,
+				    (XDRPROC_T_TYPE) xdr_am_LOOKUP3res);
+    fp->fh_status = unx_error(res3.status);
+    memset(&fp->fh_nfs_handle.v3, 0, sizeof(am_nfs_fh3));
+    fp->fh_nfs_handle.v3.am_fh3_length = res3.res_u.ok.object.am_fh3_length;
+    memmove(fp->fh_nfs_handle.v3.am_fh3_data,
+	    res3.res_u.ok.object.am_fh3_data,
+	    fp->fh_nfs_handle.v3.am_fh3_length);
+  } else {
+#endif /* HAVE_FS_NFS3 */
+    memset(&res, 0, sizeof(res));
+    fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &res,
+				    (XDRPROC_T_TYPE) xdr_diropres);
+    fp->fh_status = unx_error(res.dr_status);
+    memmove(&fp->fh_nfs_handle.v2, &res.dr_u.dr_drok_u.drok_fhandle, NFS_FHSIZE);
+#ifdef HAVE_FS_NFS3
+  }
+#endif /* HAVE_FS_NFS3 */
+
+  if (!fp->fh_error) {
+    dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
+  } else {
+    plog(XLOG_USER, "filehandle denied for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
     /*
-     * Wakeup anything sleeping on this filehandle
+     * Force the error to be EACCES. It's debatable whether it should be
+     * ENOENT instead, but the server really doesn't give us any clues, and
+     * EACCES is more in line with the "filehandle denied" message.
      */
-    if (fp->fh_wchan) {
-#ifdef DEBUG
-      dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan);
-#endif /* DEBUG */
-      wakeup(fp->fh_wchan);
-    }
+    fp->fh_error = EACCES;
+  }
+
+  /*
+   * Wakeup anything sleeping on this filehandle
+   */
+  if (fp->fh_wchan) {
+    dlog("Calling wakeup on %#lx", (unsigned long) fp->fh_wchan);
+    wakeup(fp->fh_wchan);
   }
 }
 
@@ -212,8 +304,12 @@ flush_nfs_fhandle_cache(fserver *fs)
   fh_cache *fp;
 
   ITER(fp, fh_cache, &fh_head) {
-    if (fp->fh_fs == fs || fs == 0) {
-      fp->fh_sin.sin_port = (u_short) 0;
+    if (fp->fh_fs == fs || fs == NULL) {
+      /*
+       * Only invalidate port info for non-WebNFS servers
+       */
+      if (!(fp->fh_fs->fs_flags & FSF_WEBNFS))
+	fp->fh_sin.sin_port = (u_short) 0;
       fp->fh_error = -1;
     }
   }
@@ -221,15 +317,13 @@ flush_nfs_fhandle_cache(fserver *fs)
 
 
 static void
-discard_fh(voidp v)
+discard_fh(opaque_t arg)
 {
-  fh_cache *fp = v;
+  fh_cache *fp = (fh_cache *) arg;
 
   rem_que(&fp->fh_q);
   if (fp->fh_fs) {
-#ifdef DEBUG
     dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
-#endif /* DEBUG */
     free_srvr(fp->fh_fs);
   }
   if (fp->fh_path)
@@ -242,88 +336,92 @@ discard_fh(voidp v)
  * Determine the file handle for a node
  */
 static int
-prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, voidp wchan)
+prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *mf)
 {
   fh_cache *fp, *fp_save = 0;
   int error;
   int reuse_id = FALSE;
 
-#ifdef DEBUG
   dlog("Searching cache for %s:%s", fs->fs_host, path);
-#endif /* DEBUG */
 
   /*
    * First search the cache
    */
   ITER(fp, fh_cache, &fh_head) {
-    if (fs == fp->fh_fs && STREQ(path, fp->fh_path)) {
-      switch (fp->fh_error) {
-      case 0:
-	plog(XLOG_INFO, "prime_nfs_fhandle_cache: NFS version %d", (int) fp->fh_nfs_version);
-#ifdef HAVE_FS_NFS3
-	if (fp->fh_nfs_version == NFS_VERSION3)
-	  error = fp->fh_error = unx_error(fp->fh_nfs_handle.v3.fhs_status);
-	else
-#endif /* HAVE_FS_NFS3 */
-	  error = fp->fh_error = unx_error(fp->fh_nfs_handle.v2.fhs_status);
-	if (error == 0) {
-	  if (fhbuf) {
+    if (fs != fp->fh_fs  ||  !STREQ(path, fp->fh_path))
+      continue;			/* skip to next ITER item */
+    /* else we got a match */
+    switch (fp->fh_error) {
+    case 0:
+      plog(XLOG_INFO, "prime_nfs_fhandle_cache: NFS version %d", (int) fp->fh_nfs_version);
+
+      error = fp->fh_error = fp->fh_status;
+
+      if (error == 0) {
+	if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
+	  fp_save = fp;
+	  /* XXX: why reuse the ID? */
+	  reuse_id = TRUE;
+	  break;
+	}
+
+	if (fhbuf) {
 #ifdef HAVE_FS_NFS3
-	    if (fp->fh_nfs_version == NFS_VERSION3)
-	      memmove((voidp) &(fhbuf->v3), (voidp) &(fp->fh_nfs_handle.v3),
-		      sizeof(fp->fh_nfs_handle.v3));
-	    else
+	  if (fp->fh_nfs_version == NFS_VERSION3) {
+	    memmove((voidp) &(fhbuf->v3), (voidp) &(fp->fh_nfs_handle.v3),
+		    sizeof(fp->fh_nfs_handle.v3));
+	  } else
 #endif /* HAVE_FS_NFS3 */
+	    {
 	      memmove((voidp) &(fhbuf->v2), (voidp) &(fp->fh_nfs_handle.v2),
 		      sizeof(fp->fh_nfs_handle.v2));
-	  }
-	  if (fp->fh_cid)
-	    untimeout(fp->fh_cid);
-	  fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
-	} else if (error == EACCES) {
-	  /*
-	   * Now decode the file handle return code.
-	   */
-	  plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"",
-	       fs->fs_host, path);
-	} else {
-	  errno = error;	/* XXX */
-	  plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m",
-	       fs->fs_host, path);
+	    }
 	}
-
+	if (fp->fh_cid)
+	  untimeout(fp->fh_cid);
+	fp->fh_cid = timeout(FH_TTL, discard_fh, (opaque_t) fp);
+      } else if (error == EACCES) {
 	/*
-	 * The error was returned from the remote mount daemon.
-	 * Policy: this error will be cached for now...
+	 * Now decode the file handle return code.
 	 */
-	return error;
+	plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"",
+	     fs->fs_host, path);
+      } else {
+	errno = error;	/* XXX */
+	plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m",
+	     fs->fs_host, path);
+      }
 
-      case -1:
-	/*
-	 * Still thinking about it, but we can re-use.
-	 */
-	fp_save = fp;
-	reuse_id = TRUE;
-	break;
+      /*
+       * The error was returned from the remote mount daemon.
+       * Policy: this error will be cached for now...
+       */
+      return error;
 
-      default:
-	/*
-	 * Return the error.
-	 * Policy: make sure we recompute if required again
-	 * in case this was caused by a network failure.
-	 * This can thrash mountd's though...  If you find
-	 * your mountd going slowly then:
-	 * 1.  Add a fork() loop to main.
-	 * 2.  Remove the call to innetgr() and don't use
-	 *     netgroups, especially if you don't use YP.
-	 */
-	error = fp->fh_error;
-	fp->fh_error = -1;
-	return error;
-      }
+    case -1:
+      /*
+       * Still thinking about it, but we can re-use.
+       */
+      fp_save = fp;
+      reuse_id = TRUE;
       break;
-    }
-  }
+
+    default:
+      /*
+       * Return the error.
+       * Policy: make sure we recompute if required again
+       * in case this was caused by a network failure.
+       * This can thrash mountd's though...  If you find
+       * your mountd going slowly then:
+       * 1.  Add a fork() loop to main.
+       * 2.  Remove the call to innetgr() and don't use
+       *     netgroups, especially if you don't use YP.
+       */
+      error = fp->fh_error;
+      fp->fh_error = -1;
+      return error;
+    }	/* end of switch statement */
+  } /* end of ITER loop */
 
   /*
    * Not in cache
@@ -342,13 +440,13 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, voidp w
     ins_que(&fp->fh_q, &fh_head);
   }
   if (!reuse_id)
-    fp->fh_id = FHID_ALLOC(struct );
-  fp->fh_wchan = wchan;
+    fp->fh_id = FHID_ALLOC();
+  fp->fh_wchan = get_mntfs_wchan(mf);
   fp->fh_error = -1;
-  fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
+  fp->fh_cid = timeout(FH_TTL, discard_fh, (opaque_t) fp);
 
   /*
-   * if fs->fs_ip is null, remote server is probably down.
+   * If fs->fs_ip is null, remote server is probably down.
    */
   if (!fs->fs_ip) {
     /* Mark the fileserver down and invalid again */
@@ -359,18 +457,25 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, voidp w
   }
 
   /*
-   * If the address has changed then don't try to re-use the
-   * port information
+   * Either fp has been freshly allocated or the address has changed.
+   * Initialize address and nfs version.  Don't try to re-use the port
+   * information unless using WebNFS where the port is fixed either by
+   * the spec or the "port" mount option.
    */
   if (fp->fh_sin.sin_addr.s_addr != fs->fs_ip->sin_addr.s_addr) {
     fp->fh_sin = *fs->fs_ip;
-    fp->fh_sin.sin_port = 0;
+    if (!(mf->mf_flags & MFF_WEBNFS))
+	fp->fh_sin.sin_port = 0;
     fp->fh_nfs_version = fs->fs_version;
   }
+
   fp->fh_fs = dup_srvr(fs);
   fp->fh_path = strdup(path);
 
-  error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh, wchan);
+  if (mf->mf_flags & MFF_WEBNFS)
+    error = webnfs_lookup(fp, got_nfs_fh_webnfs, get_mntfs_wchan(mf));
+  else
+    error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh_mount, get_mntfs_wchan(mf));
   if (error) {
     /*
      * Local error - cache for a short period
@@ -378,7 +483,7 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, voidp w
      */
     untimeout(fp->fh_cid);
     fp->fh_cid = timeout(error < 0 ? 2 * ALLOWED_MOUNT_TIME : FH_TTL_ERROR,
-			 discard_fh, (voidp) fp);
+			 discard_fh, (opaque_t) fp);
     fp->fh_error = error;
   } else {
     error = fp->fh_error;
@@ -397,14 +502,14 @@ make_nfs_auth(void)
 
 #ifdef HAVE_TRANSPORT_TYPE_TLI
   if (gopt.flags & CFM_FULLY_QUALIFIED_HOSTS) {
-    plog(XLOG_INFO, "Using NFS auth for fqhn \"%s\"", hostd);
+    plog(XLOG_INFO, "Using NFS auth for FQHN \"%s\"", hostd);
     nfs_auth = authsys_create(hostd, 0, 0, 1, &group_wheel);
   } else {
     nfs_auth = authsys_create_default();
   }
 #else /* not HAVE_TRANSPORT_TYPE_TLI */
   if (gopt.flags & CFM_FULLY_QUALIFIED_HOSTS) {
-    plog(XLOG_INFO, "Using NFS auth for fqhn \"%s\"", hostd);
+    plog(XLOG_INFO, "Using NFS auth for FQHN \"%s\"", hostd);
     nfs_auth = authunix_create(hostd, 0, 0, 1, &group_wheel);
   } else {
     nfs_auth = authunix_create_default();
@@ -419,11 +524,11 @@ make_nfs_auth(void)
 
 
 static int
-call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan)
+call_mountd(fh_cache *fp, u_long proc, fwd_fun fun, wchan_t wchan)
 {
   struct rpc_msg mnt_msg;
   int len;
-  char iobuf[8192];
+  char iobuf[UDPMSGSIZE];
   int error;
   u_long mnt_version;
 
@@ -434,17 +539,17 @@ call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan)
   }
 
   if (fp->fh_sin.sin_port == 0) {
-    u_short port;
-    error = nfs_srvr_port(fp->fh_fs, &port, wchan);
+    u_short mountd_port;
+    error = get_mountd_port(fp->fh_fs, &mountd_port, wchan);
     if (error)
       return error;
-    fp->fh_sin.sin_port = port;
+    fp->fh_sin.sin_port = mountd_port;
   }
 
   /* find the right version of the mount protocol */
 #ifdef HAVE_FS_NFS3
   if (fp->fh_nfs_version == NFS_VERSION3)
-    mnt_version = MOUNTVERS3;
+    mnt_version = AM_MOUNTVERS3;
   else
 #endif /* HAVE_FS_NFS3 */
     mnt_version = MOUNTVERS;
@@ -462,40 +567,128 @@ call_mountd(fh_cache *fp, u_long proc, fwd_fun f, voidp wchan)
 
   if (len > 0) {
     error = fwd_packet(MK_RPC_XID(RPC_XID_MOUNTD, fp->fh_id),
-		       (voidp) iobuf,
+		       iobuf,
 		       len,
 		       &fp->fh_sin,
 		       &fp->fh_sin,
-		       (voidp) ((long) fp->fh_id), /* for 64-bit archs */
-		       f);
+		       (opaque_t) ((long) fp->fh_id), /* cast to long needed for 64-bit archs */
+		       fun);
   } else {
     error = -len;
   }
 
-/*
- * It may be the case that we're sending to the wrong MOUNTD port.  This
- * occurs if mountd is restarted on the server after the port has been
- * looked up and stored in the filehandle cache somewhere.  The correct
- * solution, if we're going to cache port numbers is to catch the ICMP
- * port unreachable reply from the server and cause the portmap request
- * to be redone.  The quick solution here is to invalidate the MOUNTD
- * port.
- */
+  /*
+   * It may be the case that we're sending to the wrong MOUNTD port.  This
+   * occurs if mountd is restarted on the server after the port has been
+   * looked up and stored in the filehandle cache somewhere.  The correct
+   * solution, if we're going to cache port numbers is to catch the ICMP
+   * port unreachable reply from the server and cause the portmap request
+   * to be redone.  The quick solution here is to invalidate the MOUNTD
+   * port.
+   */
   fp->fh_sin.sin_port = 0;
 
   return error;
 }
 
 
+static int
+webnfs_lookup(fh_cache *fp, fwd_fun fun, wchan_t wchan)
+{
+  struct rpc_msg wnfs_msg;
+  int len;
+  char iobuf[UDPMSGSIZE];
+  int error;
+  u_long proc;
+  XDRPROC_T_TYPE xdr_fn;
+  voidp argp;
+  nfsdiropargs args;
+#ifdef HAVE_FS_NFS3
+  am_LOOKUP3args args3;
+#endif
+  char *wnfs_path;
+  size_t l;
+
+  if (!nfs_auth) {
+    error = make_nfs_auth();
+    if (error)
+      return error;
+  }
+
+  if (fp->fh_sin.sin_port == 0) {
+    /* FIXME: wrong, don't discard sin_port in the first place for WebNFS. */
+    plog(XLOG_WARNING, "webnfs_lookup: port == 0 for nfs on %s, fixed",
+	 fp->fh_fs->fs_host);
+    fp->fh_sin.sin_port = htons(NFS_PORT);
+  }
+
+  /*
+   * Use native path like the rest of amd (cf. RFC 2054, 6.1).
+   */
+  l = strlen(fp->fh_path) + 2;
+  wnfs_path = (char *) xmalloc(l);
+  wnfs_path[0] = 0x80;
+  xstrlcpy(wnfs_path + 1, fp->fh_path, l - 1);
+
+  /* find the right program and lookup procedure */
+#ifdef HAVE_FS_NFS3
+  if (fp->fh_nfs_version == NFS_VERSION3) {
+    proc = AM_NFSPROC3_LOOKUP;
+    xdr_fn = (XDRPROC_T_TYPE) xdr_am_LOOKUP3args;
+    argp = &args3;
+    /* WebNFS public file handle */
+    args3.what.dir.am_fh3_length = 0;
+    args3.what.name = wnfs_path;
+  } else {
+#endif /* HAVE_FS_NFS3 */
+    proc = NFSPROC_LOOKUP;
+    xdr_fn = (XDRPROC_T_TYPE) xdr_diropargs;
+    argp = &args;
+    /* WebNFS public file handle */
+    memset(&args.da_fhandle, 0, NFS_FHSIZE);
+    args.da_name = wnfs_path;
+#ifdef HAVE_FS_NFS3
+  }
+#endif /* HAVE_FS_NFS3 */
+
+  plog(XLOG_INFO, "webnfs_lookup: NFS version %d", (int) fp->fh_nfs_version);
+
+  rpc_msg_init(&wnfs_msg, NFS_PROGRAM, fp->fh_nfs_version, proc);
+  len = make_rpc_packet(iobuf,
+			sizeof(iobuf),
+			proc,
+			&wnfs_msg,
+			argp,
+			(XDRPROC_T_TYPE) xdr_fn,
+			nfs_auth);
+
+  if (len > 0) {
+    error = fwd_packet(MK_RPC_XID(RPC_XID_WEBNFS, fp->fh_id),
+		       iobuf,
+		       len,
+		       &fp->fh_sin,
+		       &fp->fh_sin,
+		       (opaque_t) ((long) fp->fh_id), /* cast to long needed for 64-bit archs */
+		       fun);
+  } else {
+    error = -len;
+  }
+
+  XFREE(wnfs_path);
+  return error;
+}
+
+
 /*
  * NFS needs the local filesystem, remote filesystem
  * remote hostname.
  * Local filesystem defaults to remote and vice-versa.
  */
-char *
+static char *
 nfs_match(am_opts *fo)
 {
   char *xmtab;
+  size_t l;
 
   if (fo->opt_fs && !fo->opt_rfs)
     fo->opt_rfs = fo->opt_fs;
@@ -511,12 +704,11 @@ nfs_match(am_opts *fo)
   /*
    * Determine magic cookie to put in mtab
    */
-  xmtab = (char *) xmalloc(strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2);
-  sprintf(xmtab, "%s:%s", fo->opt_rhost, fo->opt_rfs);
-#ifdef DEBUG
+  l = strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2;
+  xmtab = (char *) xmalloc(l);
+  xsnprintf(xmtab, l, "%s:%s", fo->opt_rhost, fo->opt_rfs);
   dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
        fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
-#endif /* DEBUG */
 
   return xmtab;
 }
@@ -525,24 +717,36 @@ nfs_match(am_opts *fo)
 /*
  * Initialize am structure for nfs
  */
-int
+static int
 nfs_init(mntfs *mf)
 {
   int error;
   am_nfs_handle_t fhs;
   char *colon;
 
-  if (mf->mf_private)
-    return 0;
+  if (mf->mf_private) {
+    if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
+      fserver *fs;
+
+      /* tell remote mountd that we're done with this filehandle */
+      mf->mf_ops->umounted(mf);
+
+      mf->mf_prfree(mf->mf_private);
+      fs = mf->mf_ops->ffserver(mf);
+      free_srvr(mf->mf_server);
+      mf->mf_server = fs;
+    } else
+      return 0;
+  }
 
   colon = strchr(mf->mf_info, ':');
   if (colon == 0)
     return ENOENT;
 
-  error = prime_nfs_fhandle_cache(colon + 1, mf->mf_server, &fhs, (voidp) mf);
+  error = prime_nfs_fhandle_cache(colon + 1, mf->mf_server, &fhs, mf);
   if (!error) {
-    mf->mf_private = (voidp) ALLOC(am_nfs_handle_t);
-    mf->mf_prfree = (void (*)(voidp)) free;
+    mf->mf_private = (opaque_t) ALLOC(am_nfs_handle_t);
+    mf->mf_prfree = (void (*)(opaque_t)) free;
     memmove(mf->mf_private, (voidp) &fhs, sizeof(fhs));
   }
   return error;
@@ -550,18 +754,20 @@ nfs_init(mntfs *mf)
 
 
 int
-mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf)
+mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf)
 {
   MTYPE_TYPE type;
   char *colon;
-  char *xopts;
+  char *xopts=NULL, transp_timeo_opts[40], transp_retrans_opts[40];
   char host[MAXHOSTNAMELEN + MAXPATHLEN + 2];
   fserver *fs = mf->mf_server;
   u_long nfs_version = fs->fs_version;
   char *nfs_proto = fs->fs_proto; /* "tcp" or "udp" */
+  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
   int error;
   int genflags;
   int retry;
+  int proto = AMU_TYPE_NONE;
   mntent_t mnt;
   nfs_args_t nfs_args;
 
@@ -575,26 +781,48 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *
 #ifdef MOUNT_TABLE_ON_FILE
   *colon = '\0';
 #endif /* MOUNT_TABLE_ON_FILE */
-  strncpy(host, fs_name, sizeof(host));
+  xstrlcpy(host, fs_name, sizeof(host));
 #ifdef MOUNT_TABLE_ON_FILE
   *colon = ':';
 #endif /* MOUNT_TABLE_ON_FILE */
 #ifdef MAXHOSTNAMELEN
   /* most kernels have a name length restriction */
   if (strlen(host) >= MAXHOSTNAMELEN)
-    strcpy(host + MAXHOSTNAMELEN - 3, "..");
+    xstrlcpy(host + MAXHOSTNAMELEN - 3, "..",
+	     sizeof(host) - MAXHOSTNAMELEN + 3);
 #endif /* MAXHOSTNAMELEN */
 
+  /*
+   * Create option=VAL for udp/tcp specific timeouts and retrans values, but
+   * only if these options were specified.
+   */
+
+  transp_timeo_opts[0] = transp_retrans_opts[0] = '\0';	/* initialize */
+  if (STREQ(nfs_proto, "udp"))
+    proto = AMU_TYPE_UDP;
+  else if (STREQ(nfs_proto, "tcp"))
+    proto = AMU_TYPE_TCP;
+  if (proto != AMU_TYPE_NONE) {
+    if (gopt.amfs_auto_timeo[proto] > 0)
+      xsnprintf(transp_timeo_opts, sizeof(transp_timeo_opts), "%s=%d,",
+		MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo[proto]);
+    if (gopt.amfs_auto_retrans[proto] > 0)
+      xsnprintf(transp_retrans_opts, sizeof(transp_retrans_opts), "%s=%d,",
+		MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans[proto]);
+  }
+
   if (mf->mf_remopts && *mf->mf_remopts &&
       !islocalnet(fs->fs_ip->sin_addr.s_addr)) {
     plog(XLOG_INFO, "Using remopts=\"%s\"", mf->mf_remopts);
-    xopts = strdup(mf->mf_remopts);
+    /* use transp_opts first, so map-specific opts will override */
+    xopts = str3cat(xopts, transp_timeo_opts, transp_retrans_opts, mf->mf_remopts);
   } else {
-    xopts = strdup(opts);
+    /* use transp_opts first, so map-specific opts will override */
+    xopts = str3cat(xopts, transp_timeo_opts, transp_retrans_opts, mf->mf_mopts);
   }
 
   memset((voidp) &mnt, 0, sizeof(mnt));
-  mnt.mnt_dir = dir;
+  mnt.mnt_dir = mntdir;
   mnt.mnt_fsname = fs_name;
   mnt.mnt_opts = xopts;
 
@@ -626,18 +854,19 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *
   }
 #endif /* HAVE_FS_NFS3 */
   plog(XLOG_INFO, "mount_nfs_fh: NFS version %d", (int) nfs_version);
-#if defined(HAVE_FS_NFS3) || defined(HAVE_TRANSPORT_TYPE_TLI)
   plog(XLOG_INFO, "mount_nfs_fh: using NFS transport %s", nfs_proto);
-#endif /* defined(HAVE_FS_NFS3) || defined(HAVE_TRANSPORT_TYPE_TLI) */
 
   retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
   if (retry <= 0)
     retry = 1;			/* XXX */
 
   genflags = compute_mount_flags(&mnt);
+#ifdef HAVE_FS_AUTOFS
+  if (on_autofs)
+    genflags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
 
   /* setup the many fields and flags within nfs_args */
-#ifdef HAVE_TRANSPORT_TYPE_TLI
   compute_nfs_args(&nfs_args,
 		   &mnt,
 		   genflags,
@@ -648,27 +877,14 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *
 		   fhp,
 		   host,
 		   fs_name);
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
-  compute_nfs_args(&nfs_args,
-		   &mnt,
-		   genflags,
-		   fs->fs_ip,
-		   nfs_version,
-		   nfs_proto,
-		   fhp,
-		   host,
-		   fs_name);
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
 
   /* finally call the mounting function */
-#ifdef DEBUG
-  amuDebug(D_TRACE) {
+  if (amuDebug(D_TRACE)) {
     print_nfs_args(&nfs_args, nfs_version);
-    plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
+    plog(XLOG_DEBUG, "Generic mount flags 0x%x used for NFS mount", genflags);
   }
-#endif /* DEBUG */
   error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type,
-		   nfs_version, nfs_proto, mnttab_file_name);
+		    nfs_version, nfs_proto, mnttab_file_name, on_autofs);
   XFREE(xopts);
 
 #ifdef HAVE_TRANSPORT_TYPE_TLI
@@ -682,39 +898,62 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *
 
 
 static int
-mount_nfs(char *dir, char *fs_name, char *opts, mntfs *mf)
+nfs_mount(am_node *am, mntfs *mf)
 {
+  int error = 0;
+  mntent_t mnt;
+
   if (!mf->mf_private) {
-    plog(XLOG_ERROR, "Missing filehandle for %s", fs_name);
+    plog(XLOG_ERROR, "Missing filehandle for %s", mf->mf_info);
     return EINVAL;
   }
 
-  return mount_nfs_fh((am_nfs_handle_t *) mf->mf_private, dir, fs_name, opts, mf);
-}
+  mnt.mnt_opts = mf->mf_mopts;
+  if (amu_hasmntopt(&mnt, "softlookup") ||
+      (amu_hasmntopt(&mnt, "soft") && !amu_hasmntopt(&mnt, "nosoftlookup")))
+    am->am_flags |= AMF_SOFTLOOKUP;
 
+  error = mount_nfs_fh((am_nfs_handle_t *) mf->mf_private,
+		       mf->mf_mount,
+		       mf->mf_info,
+		       mf);
 
-int
-nfs_fmount(mntfs *mf)
-{
-  int error = 0;
-
-  error = mount_nfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, mf);
-
-#ifdef DEBUG
   if (error) {
     errno = error;
     dlog("mount_nfs: %m");
   }
-#endif /* DEBUG */
 
   return error;
 }
 
 
-int
-nfs_fumount(mntfs *mf)
+static int
+nfs_umount(am_node *am, mntfs *mf)
 {
-  int error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
+  int unmount_flags, new_unmount_flags, error;
+
+  unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+  error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
+
+#if defined(HAVE_UMOUNT2) && (defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH))
+  /*
+   * If the attempt to unmount failed with EBUSY, and this fserver was
+   * marked for forced unmounts, then use forced/lazy unmounts.
+   */
+  if (error == EBUSY &&
+      gopt.flags & CFM_FORCED_UNMOUNTS &&
+      mf->mf_server->fs_flags & FSF_FORCE_UNMOUNT) {
+    plog(XLOG_INFO, "EZK: nfs_umount: trying forced/lazy unmounts");
+    /*
+     * XXX: turning off the FSF_FORCE_UNMOUNT may not be perfectly
+     * incorrect.  Multiple nodes may need to be timed out and restarted for
+     * a single hung fserver.
+     */
+    mf->mf_server->fs_flags &= ~FSF_FORCE_UNMOUNT;
+    new_unmount_flags = unmount_flags | AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH;
+    error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, new_unmount_flags);
+  }
+#endif /* HAVE_UMOUNT2 && (MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH) */
 
   /*
    * Here is some code to unmount 'restarted' file systems.
@@ -743,12 +982,14 @@ nfs_fumount(mntfs *mf)
 
       if (NSTREQ(mf->mf_mount, new_mf->mf_mount, len) &&
 	  new_mf->mf_mount[len] == '/') {
-	UMOUNT_FS(new_mf->mf_mount, mnttab_file_name);
+	new_unmount_flags =
+	  (new_mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+	UMOUNT_FS(new_mf->mf_mount, mnttab_file_name, new_unmount_flags);
 	didsome = 1;
       }
     }
     if (didsome)
-      error = UMOUNT_FS(mf->mf_mount, mnttab_file_name);
+      error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
   }
   if (error)
     return error;
@@ -757,38 +998,35 @@ nfs_fumount(mntfs *mf)
 }
 
 
-void
-nfs_umounted(am_node *mp)
+static void
+nfs_umounted(mntfs *mf)
 {
-  /*
-   * Don't bother to inform remote mountd that we are finished.  Until a
-   * full track of filehandles is maintained the mountd unmount callback
-   * cannot be done correctly anyway...
-   */
-  mntfs *mf = mp->am_mnt;
   fserver *fs;
   char *colon, *path;
 
   if (mf->mf_error || mf->mf_refc > 1)
     return;
 
-  fs = mf->mf_server;
+  /*
+   * No need to inform mountd when WebNFS is in use.
+   */
+  if (mf->mf_flags & MFF_WEBNFS)
+    return;
 
   /*
    * Call the mount daemon on the server to announce that we are not using
    * the fs any more.
    *
-   * This is *wrong*.  The mountd should be called when the fhandle is
+   * XXX: This is *wrong*.  The mountd should be called when the fhandle is
    * flushed from the cache, and a reference held to the cached entry while
    * the fs is mounted...
    */
+  fs = mf->mf_server;
   colon = path = strchr(mf->mf_info, ':');
   if (fs && colon) {
     fh_cache f;
 
-#ifdef DEBUG
     dlog("calling mountd for %s", mf->mf_info);
-#endif /* DEBUG */
     *path++ = '\0';
     f.fh_path = path;
     f.fh_sin = *fs->fs_ip;
@@ -797,8 +1035,8 @@ nfs_umounted(am_node *mp)
     f.fh_fs = fs;
     f.fh_id = 0;
     f.fh_error = 0;
-    prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) 0, (voidp) mf);
-    call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun) 0, (voidp) 0);
+    prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) 0, mf);
+    call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun *) 0, (wchan_t) 0);
     *colon = ':';
   }
 }
diff --git a/contrib/amd/amd/ops_nfs3.c b/contrib/amd/amd/ops_nfs3.c
index 0a9a198..db3c7f9 100644
--- a/contrib/amd/amd/ops_nfs3.c
+++ b/contrib/amd/amd/ops_nfs3.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_nfs3.c,v 1.2 1999/01/10 21:53:50 ezk Exp $
+ * File: am-utils/amd/ops_nfs3.c
  *
  */
 
diff --git a/contrib/amd/amd/ops_nullfs.c b/contrib/amd/amd/ops_nullfs.c
index bd2e5ba..cf621ec 100644
--- a/contrib/amd/amd/ops_nullfs.c
+++ b/contrib/amd/amd/ops_nullfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_nullfs.c,v 1.2 1999/01/10 21:53:50 ezk Exp $
+ * File: am-utils/amd/ops_nullfs.c
  *
  */
 
diff --git a/contrib/amd/amd/ops_pcfs.c b/contrib/amd/amd/ops_pcfs.c
index bca33ae..527dc92 100644
--- a/contrib/amd/amd/ops_pcfs.c
+++ b/contrib/amd/amd/ops_pcfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_pcfs.c,v 1.2 1999/01/10 21:53:50 ezk Exp $
+ * File: am-utils/amd/ops_pcfs.c
  *
  */
 
@@ -54,8 +53,8 @@
 
 /* forward definitions */
 static char *pcfs_match(am_opts *fo);
-static int pcfs_fmount(mntfs *mf);
-static int pcfs_fumount(mntfs *mf);
+static int pcfs_mount(am_node *am, mntfs *mf);
+static int pcfs_umount(am_node *am, mntfs *mf);
 
 /*
  * Ops structure
@@ -65,17 +64,20 @@ am_ops pcfs_ops =
   "pcfs",
   pcfs_match,
   0,				/* pcfs_init */
-  amfs_auto_fmount,
-  pcfs_fmount,
-  amfs_auto_fumount,
-  pcfs_fumount,
-  amfs_error_lookuppn,
+  pcfs_mount,
+  pcfs_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* pcfs_readlink */
   0,				/* pcfs_mounted */
   0,				/* pcfs_umounted */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
+  amfs_generic_find_srvr,
+  0,				/* pcfs_get_wchan */
+  FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO,	/* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_PCFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -90,9 +92,7 @@ pcfs_match(am_opts *fo)
     plog(XLOG_USER, "pcfs: no source device specified");
     return 0;
   }
-#ifdef DEBUG
   dlog("PCFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
-#endif /* DEBUG */
 
   /*
    * Determine magic cookie to put in mtab
@@ -102,11 +102,17 @@ pcfs_match(am_opts *fo)
 
 
 static int
-mount_pcfs(char *dir, char *fs_name, char *opts)
+mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
 {
   pcfs_args_t pcfs_args;
   mntent_t mnt;
   int flags;
+#if defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK)
+  int mask;
+#endif /* defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK) */
+#if defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID)
+  char *str;
+#endif /* defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID) */
 
   /*
    * Figure out the name of the file system type.
@@ -119,49 +125,88 @@ mount_pcfs(char *dir, char *fs_name, char *opts)
    * Fill in the mount structure
    */
   memset((voidp) &mnt, 0, sizeof(mnt));
-  mnt.mnt_dir = dir;
+  mnt.mnt_dir = mntdir;
   mnt.mnt_fsname = fs_name;
   mnt.mnt_type = MNTTAB_TYPE_PCFS;
   mnt.mnt_opts = opts;
 
   flags = compute_mount_flags(&mnt);
-
-#ifdef HAVE_FIELD_PCFS_ARGS_T_FSPEC
+#ifdef HAVE_FS_AUTOFS
+  if (on_autofs)
+    flags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "mount_pcfs: flags=0x%x", (u_int) flags);
+
+#ifdef HAVE_PCFS_ARGS_T_FSPEC
   pcfs_args.fspec = fs_name;
-#endif /* HAVE_FIELD_PCFS_ARGS_T_FSPEC */
+#endif /* HAVE_PCFS_ARGS_T_FSPEC */
 
-#ifdef HAVE_FIELD_PCFS_ARGS_T_MASK
+#ifdef HAVE_PCFS_ARGS_T_MASK
   pcfs_args.mask = 0777;	/* this may be the msdos file modes */
-#endif /* HAVE_FIELD_PCFS_ARGS_T_MASK */
-
-#ifdef HAVE_FIELD_PCFS_ARGS_T_UID
-  pcfs_args.uid = 0;		/* root */
-#endif /* HAVE_FIELD_PCFS_ARGS_T_UID */
-
-#ifdef HAVE_FIELD_PCFS_ARGS_T_GID
-  pcfs_args.gid = 0;		/* wheel */
-#endif /* HAVE_FIELD_PCFS_ARGS_T_GID */
+  if ((mask = hasmntval(&mnt, MNTTAB_OPT_MASK)) > 0)
+    pcfs_args.mask = mask;
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "mount_pcfs: mask=%o (octal)", (u_int) pcfs_args.mask);
+#endif /* HAVE_PCFS_ARGS_T_MASK */
+
+#ifdef HAVE_PCFS_ARGS_T_DIRMASK
+  pcfs_args.dirmask = 0777;    /* this may be the msdos dir modes */
+  if ((mask = hasmntval(&mnt, MNTTAB_OPT_DIRMASK)) > 0)
+    pcfs_args.dirmask = mask;
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "mount_pcfs: dirmask=%o (octal)", (u_int) pcfs_args.dirmask);
+#endif /* HAVE_PCFS_ARGS_T_DIRMASK */
+
+#ifdef HAVE_PCFS_ARGS_T_UID
+  pcfs_args.uid = 0;		/* default to root */
+  if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) {
+    struct passwd *pw;
+    if ((pw = getpwnam(str)) != NULL)
+      pcfs_args.uid = pw->pw_uid;
+    else		 /* maybe used passed a UID number, not user name */
+      pcfs_args.uid = atoi(str); /* atoi returns '0' if it failed */
+    XFREE(str);
+  }
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "mount_pcfs: uid=%d", (int) pcfs_args.uid);
+#endif /* HAVE_PCFS_ARGS_T_UID */
+
+#ifdef HAVE_PCFS_ARGS_T_GID
+  pcfs_args.gid = 0;		/* default to wheel/root group */
+  if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) {
+    struct group *gr;
+    if ((gr = getgrnam(str)) != NULL)
+      pcfs_args.gid = gr->gr_gid;
+    else		/* maybe used passed a GID number, not group name */
+      pcfs_args.gid = atoi(str); /* atoi returns '0' if it failed */
+    XFREE(str);
+  }
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "mount_pcfs: gid=%d", (int) pcfs_args.gid);
+#endif /* HAVE_PCFS_ARGS_T_GID */
 
-#ifdef HAVE_FIELD_PCFS_ARGS_T_SECONDSWEST
+#ifdef HAVE_PCFS_ARGS_T_SECONDSWEST
   pcfs_args.secondswest = 0;	/* XXX: fill in correct values */
-#endif /* HAVE_FIELD_PCFS_ARGS_T_SECONDSWEST */
-#ifdef HAVE_FIELD_PCFS_ARGS_T_DSTTIME
+#endif /* HAVE_PCFS_ARGS_T_SECONDSWEST */
+#ifdef HAVE_PCFS_ARGS_T_DSTTIME
   pcfs_args.dsttime = 0;	/* XXX: fill in correct values */
-#endif /* HAVE_FIELD_PCFS_ARGS_T_DSTTIME */
+#endif /* HAVE_PCFS_ARGS_T_DSTTIME */
 
   /*
    * Call generic mount routine
    */
-  return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name);
+  return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
 }
 
 
 static int
-pcfs_fmount(mntfs *mf)
+pcfs_mount(am_node *am, mntfs *mf)
 {
+  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
   int error;
 
-  error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
+  error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
   if (error) {
     errno = error;
     plog(XLOG_ERROR, "mount_pcfs: %m");
@@ -173,7 +218,9 @@ pcfs_fmount(mntfs *mf)
 
 
 static int
-pcfs_fumount(mntfs *mf)
+pcfs_umount(am_node *am, mntfs *mf)
 {
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
diff --git a/contrib/amd/amd/ops_tfs.c b/contrib/amd/amd/ops_tfs.c
index f370eb9..142c320 100644
--- a/contrib/amd/amd/ops_tfs.c
+++ b/contrib/amd/amd/ops_tfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_tfs.c,v 1.2 1999/01/10 21:53:51 ezk Exp $
+ * File: am-utils/amd/ops_tfs.c
  *
  */
 
diff --git a/contrib/amd/amd/ops_tmpfs.c b/contrib/amd/amd/ops_tmpfs.c
index 99f47dc..eddd755 100644
--- a/contrib/amd/amd/ops_tmpfs.c
+++ b/contrib/amd/amd/ops_tmpfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_tmpfs.c,v 1.2 1999/01/10 21:53:51 ezk Exp $
+ * File: am-utils/amd/ops_tmpfs.c
  *
  */
 
diff --git a/contrib/amd/amd/ops_ufs.c b/contrib/amd/amd/ops_ufs.c
index 0b2ff2d..fd82a5c 100644
--- a/contrib/amd/amd/ops_ufs.c
+++ b/contrib/amd/amd/ops_ufs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_ufs.c,v 1.2 1999/01/10 21:53:51 ezk Exp $
+ * File: am-utils/amd/ops_ufs.c
  *
  */
 
@@ -54,8 +53,8 @@
 
 /* forward declarations */
 static char *ufs_match(am_opts *fo);
-static int ufs_fmount(mntfs *mf);
-static int ufs_fumount(mntfs *mf);
+static int ufs_mount(am_node *am, mntfs *mf);
+static int ufs_umount(am_node *am, mntfs *mf);
 
 /*
  * Ops structure
@@ -65,17 +64,20 @@ am_ops ufs_ops =
   "ufs",
   ufs_match,
   0,				/* ufs_init */
-  amfs_auto_fmount,
-  ufs_fmount,
-  amfs_auto_fumount,
-  ufs_fumount,
-  amfs_error_lookuppn,
+  ufs_mount,
+  ufs_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* ufs_readlink */
   0,				/* ufs_mounted */
   0,				/* ufs_umounted */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
+  amfs_generic_find_srvr,
+  0,				/* ufs_get_wchan */
+  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_UFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -91,9 +93,7 @@ ufs_match(am_opts *fo)
     return 0;
   }
 
-#ifdef DEBUG
   dlog("UFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
-#endif /* DEBUG */
 
   /*
    * Determine magic cookie to put in mtab
@@ -103,7 +103,7 @@ ufs_match(am_opts *fo)
 
 
 static int
-mount_ufs(char *dir, char *fs_name, char *opts)
+mount_ufs(char *mntdir, char *fs_name, char *opts, int on_autofs)
 {
   ufs_args_t ufs_args;
   mntent_t mnt;
@@ -120,42 +120,47 @@ mount_ufs(char *dir, char *fs_name, char *opts)
    * Fill in the mount structure
    */
   memset((voidp) &mnt, 0, sizeof(mnt));
-  mnt.mnt_dir = dir;
+  mnt.mnt_dir = mntdir;
   mnt.mnt_fsname = fs_name;
   mnt.mnt_type = MNTTAB_TYPE_UFS;
   mnt.mnt_opts = opts;
 
   genflags = compute_mount_flags(&mnt);
+#ifdef HAVE_FS_AUTOFS
+  if (on_autofs)
+    genflags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
 
-#ifdef HAVE_FIELD_UFS_ARGS_T_FLAGS
+#ifdef HAVE_UFS_ARGS_T_FLAGS
   ufs_args.flags = genflags;	/* XXX: is this correct? */
-#endif /* HAVE_FIELD_UFS_ARGS_T_FLAGS */
+#endif /* HAVE_UFS_ARGS_T_FLAGS */
 
-#ifdef HAVE_FIELD_UFS_ARGS_T_UFS_FLAGS
+#ifdef HAVE_UFS_ARGS_T_UFS_FLAGS
   ufs_args.ufs_flags = genflags;
-#endif /* HAVE_FIELD_UFS_ARGS_T_UFS_FLAGS */
+#endif /* HAVE_UFS_ARGS_T_UFS_FLAGS */
 
-#ifdef HAVE_FIELD_UFS_ARGS_T_FSPEC
+#ifdef HAVE_UFS_ARGS_T_FSPEC
   ufs_args.fspec = fs_name;
-#endif /* HAVE_FIELD_UFS_ARGS_T_FSPEC */
+#endif /* HAVE_UFS_ARGS_T_FSPEC */
 
-#ifdef HAVE_FIELD_UFS_ARGS_T_UFS_PGTHRESH
+#ifdef HAVE_UFS_ARGS_T_UFS_PGTHRESH
   ufs_args.ufs_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH);
-#endif /* HAVE_FIELD_UFS_ARGS_T_UFS_PGTHRESH */
+#endif /* HAVE_UFS_ARGS_T_UFS_PGTHRESH */
 
   /*
    * Call generic mount routine
    */
-  return mount_fs(&mnt, genflags, (caddr_t) &ufs_args, 0, type, 0, NULL, mnttab_file_name);
+  return mount_fs(&mnt, genflags, (caddr_t) &ufs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
 }
 
 
 static int
-ufs_fmount(mntfs *mf)
+ufs_mount(am_node *am, mntfs *mf)
 {
+  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
   int error;
 
-  error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
+  error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
   if (error) {
     errno = error;
     plog(XLOG_ERROR, "mount_ufs: %m");
@@ -167,7 +172,9 @@ ufs_fmount(mntfs *mf)
 
 
 static int
-ufs_fumount(mntfs *mf)
+ufs_umount(am_node *am, mntfs *mf)
 {
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
diff --git a/contrib/amd/amd/ops_umapfs.c b/contrib/amd/amd/ops_umapfs.c
index 9862933..5ba735e 100644
--- a/contrib/amd/amd/ops_umapfs.c
+++ b/contrib/amd/amd/ops_umapfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_umapfs.c,v 1.2 1999/01/10 21:53:51 ezk Exp $
+ * File: am-utils/amd/ops_umapfs.c
  *
  */
 
diff --git a/contrib/amd/amd/ops_unionfs.c b/contrib/amd/amd/ops_unionfs.c
index 2e914a9..73f8d66 100644
--- a/contrib/amd/amd/ops_unionfs.c
+++ b/contrib/amd/amd/ops_unionfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_unionfs.c,v 1.2 1999/01/10 21:53:51 ezk Exp $
+ * File: am-utils/amd/ops_unionfs.c
  *
  */
 
diff --git a/contrib/amd/amd/ops_xfs.c b/contrib/amd/amd/ops_xfs.c
index 86ebfa0..e0e740b 100644
--- a/contrib/amd/amd/ops_xfs.c
+++ b/contrib/amd/amd/ops_xfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: ops_xfs.c,v 1.2 1999/01/10 21:53:52 ezk Exp $
+ * File: am-utils/amd/ops_xfs.c
  *
  */
 
@@ -53,9 +52,9 @@
 #include <amd.h>
 
 /* forward declarations */
-static char * xfs_match(am_opts *fo);
-static int xfs_fmount(mntfs *mf);
-static int xfs_fumount(mntfs *mf);
+static char *xfs_match(am_opts *fo);
+static int xfs_mount(am_node *am, mntfs *mf);
+static int xfs_umount(am_node *am, mntfs *mf);
 
 /*
  * Ops structure
@@ -65,17 +64,20 @@ am_ops xfs_ops =
   "xfs",
   xfs_match,
   0,				/* xfs_init */
-  amfs_auto_fmount,
-  xfs_fmount,
-  amfs_auto_fumount,
-  xfs_fumount,
-  amfs_error_lookuppn,
+  xfs_mount,
+  xfs_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
   amfs_error_readdir,
   0,				/* xfs_readlink */
   0,				/* xfs_mounted */
   0,				/* xfs_umounted */
-  find_amfs_auto_srvr,
-  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
+  amfs_generic_find_srvr,
+  0,				/* xfs_get_wchan */
+  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#ifdef HAVE_FS_AUTOFS
+  AUTOFS_XFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
 };
 
 
@@ -91,9 +93,7 @@ xfs_match(am_opts *fo)
     return 0;
   }
 
-#ifdef DEBUG
   dlog("XFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
-#endif /* DEBUG */
 
   /*
    * Determine magic cookie to put in mtab
@@ -103,7 +103,7 @@ xfs_match(am_opts *fo)
 
 
 static int
-mount_xfs(char *dir, char *fs_name, char *opts)
+mount_xfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
 {
   xfs_args_t xfs_args;
   mntent_t mnt;
@@ -120,33 +120,38 @@ mount_xfs(char *dir, char *fs_name, char *opts)
    * Fill in the mount structure
    */
   memset((voidp) &mnt, 0, sizeof(mnt));
-  mnt.mnt_dir = dir;
+  mnt.mnt_dir = mntdir;
   mnt.mnt_fsname = fs_name;
   mnt.mnt_type = MNTTAB_TYPE_XFS;
   mnt.mnt_opts = opts;
 
   flags = compute_mount_flags(&mnt);
+#ifdef HAVE_FS_AUTOFS
+  if (on_autofs)
+    flags |= autofs_compute_mount_flags(&mnt);
+#endif /* HAVE_FS_AUTOFS */
 
-#ifdef HAVE_FIELD_XFS_ARGS_T_FLAGS
+#ifdef HAVE_XFS_ARGS_T_FLAGS
   xfs_args.flags = 0;		/* XXX: fix this to correct flags */
-#endif /* HAVE_FIELD_XFS_ARGS_T_FLAGS */
-#ifdef HAVE_FIELD_XFS_ARGS_T_FSPEC
+#endif /* HAVE_XFS_ARGS_T_FLAGS */
+#ifdef HAVE_XFS_ARGS_T_FSPEC
   xfs_args.fspec = fs_name;
-#endif /* HAVE_FIELD_XFS_ARGS_T_FSPEC */
+#endif /* HAVE_XFS_ARGS_T_FSPEC */
 
   /*
    * Call generic mount routine
    */
-  return mount_fs(&mnt, flags, (caddr_t) &xfs_args, 0, type, 0, NULL, mnttab_file_name);
+  return mount_fs(&mnt, flags, (caddr_t) &xfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
 }
 
 
 static int
-xfs_fmount(mntfs *mf)
+xfs_mount(am_node *am, mntfs *mf)
 {
+  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
   int error;
 
-  error = mount_xfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
+  error = mount_xfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
   if (error) {
     errno = error;
     plog(XLOG_ERROR, "mount_xfs: %m");
@@ -158,7 +163,9 @@ xfs_fmount(mntfs *mf)
 
 
 static int
-xfs_fumount(mntfs *mf)
+xfs_umount(am_node *am, mntfs *mf)
 {
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
diff --git a/contrib/amd/amd/opts.c b/contrib/amd/amd/opts.c
index d564e69..a3d3534 100644
--- a/contrib/amd/amd/opts.c
+++ b/contrib/amd/amd/opts.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: opts.c,v 1.6 1999/09/30 21:01:32 ezk Exp $
+ * File: am-utils/amd/opts.c
  *
  */
 
@@ -94,16 +93,17 @@ struct functable {
  * FORWARD DEFINITION:
  */
 static int f_in_network(char *);
+static int f_xhost(char *);
 static int f_netgrp(char *);
 static int f_netgrpd(char *);
 static int f_exists(char *);
 static int f_false(char *);
 static int f_true(char *);
+static inline char *expand_options(char *key);
 
 /*
  * STATICS:
  */
-static struct am_opts fs_static; /* copy of the options to play with */
 static char NullStr[] = "<NULL>";
 static char nullstr[] = "";
 static char *opt_dkey = NullStr;
@@ -113,16 +113,25 @@ static char *opt_key = nullstr;
 static char *opt_keyd = nullstr;
 static char *opt_map = nullstr;
 static char *opt_path = nullstr;
+char uid_str[SIZEOF_UID_STR], gid_str[SIZEOF_GID_STR];
+char *opt_uid = uid_str;
+char *opt_gid = gid_str;
 static char *vars[8];
+static char *literal_dollar = "$"; /* ${dollar}: a literal '$' in maps */
+
+/*
+ * GLOBALS
+ */
+static struct am_opts fs_static;      /* copy of the options to play with */
 
 
 /*
- * Options in something corresponding to frequency of use so that
+ * Options in some order corresponding to frequency of use so that
  * first-match algorithm is sped up.
  */
 static struct opt opt_fields[] = {
   /* Name and length.
-	Option str.		Selector str.	boolean fxn.	flags */
+	Option str.		Selector str.	boolean fxn.	case sensitive */
   { S("opts"),
        &fs_static.opt_opts,	0,		0, 		FALSE	},
   { S("host"),
@@ -149,8 +158,6 @@ static struct opt opt_fields[] = {
 	&fs_static.opt_dev,	0,		0,		FALSE	},
   { S("pref"),
 	&fs_static.opt_pref,	0,		0,		FALSE	},
-  { S("autopref"),
-	&fs_static.opt_autopref,0,		0,		FALSE	},
   { S("path"),
 	0,			&opt_path,	0,		FALSE	},
   { S("autodir"),
@@ -185,6 +192,8 @@ static struct opt opt_fields[] = {
 	&fs_static.opt_mount,	0,		0,		FALSE	},
   { S("unmount"),
 	&fs_static.opt_unmount,	0,		0,		FALSE	},
+  { S("umount"),
+	&fs_static.opt_umount,	0,		0,		FALSE	},
   { S("cache"),
 	&fs_static.opt_cache,	0,		0,		FALSE	},
   { S("user"),
@@ -200,7 +209,15 @@ static struct opt opt_fields[] = {
   { S("cachedir"),
 	&fs_static.opt_cachedir, 0,		0,		FALSE	},
   { S("addopts"),
-       &fs_static.opt_addopts,	0,		0, 		FALSE	},
+	&fs_static.opt_addopts,	0,		0, 		FALSE	},
+  { S("uid"),
+	0,			&opt_uid,	0,		FALSE	},
+  { S("gid"),
+	0,			&opt_gid,	0, 		FALSE	},
+  { S("mount_type"),
+	&fs_static.opt_mount_type, 0,		0,		FALSE	},
+  { S("dollar"),
+	&literal_dollar,	0,		0,		FALSE	},
   { S("var0"),
 	&vars[0],		0,		0,		FALSE	},
   { S("var1"),
@@ -222,6 +239,7 @@ static struct opt opt_fields[] = {
 
 static struct functable functable[] = {
   { "in_network",	f_in_network },
+  { "xhost",		f_xhost },
   { "netgrp",		f_netgrp },
   { "netgrpd",		f_netgrpd },
   { "exists",		f_exists },
@@ -252,6 +270,7 @@ static opt_apply expansions[] =
   {&fs_static.opt_remopts, "${opts}"},
   {&fs_static.opt_mount, 0},
   {&fs_static.opt_unmount, 0},
+  {&fs_static.opt_umount, 0},
   {&fs_static.opt_cachedir, 0},
   {&fs_static.opt_addopts, 0},
   {0, 0},
@@ -273,6 +292,7 @@ static opt_apply to_free[] =
   {&fs_static.opt_remopts, 0},
   {&fs_static.opt_mount, 0},
   {&fs_static.opt_unmount, 0},
+  {&fs_static.opt_umount, 0},
   {&fs_static.opt_cachedir, 0},
   {&fs_static.opt_addopts, 0},
   {&vars[0], 0},
@@ -289,6 +309,7 @@ static opt_apply to_free[] =
 
 /*
  * expand backslash escape sequences
+ * (escaped slash is handled separately in normalize_slash)
  */
 static char
 backslash(char **p)
@@ -303,7 +324,7 @@ backslash(char **p)
   if (**p == '\\') {
     (*p)++;
     switch (**p) {
-    case 'a':
+    case 'g':
       c = '\007';		/* Bell */
       break;
     case 'b':
@@ -444,33 +465,99 @@ functable_lookup(char *key)
 }
 
 
+/*
+ * Fill in the global structure fs_static by
+ * cracking the string opts.  opts may be
+ * scribbled on at will.  Does NOT evaluate options.
+ * Returns 0 on error, 1 if no syntax errors were discovered.
+ */
 static int
-eval_opts(char *opts, char *mapkey)
+split_opts(char *opts, char *mapkey)
 {
+  char *o = opts;
+  char *f;
+
   /*
-   * Fill in the global structure fs_static by
-   * cracking the string opts.  opts may be
-   * scribbled on at will.
+   * For each user-specified option
    */
-  char *o = opts;
+  for (f = opt(&o); *f; f = opt(&o)) {
+    struct opt *op;
+    char *eq = strchr(f, '=');
+    char *opt = NULL;
+
+    if (!eq)
+      continue;
+
+    if (*(eq-1) == '!' ||
+	eq[1] == '=' ||
+	eq[1] == '!') {	/* != or == or =! */
+      continue;			/* we don't care about selectors */
+    }
+
+    if (*(eq-1) == ':') {	/* := */
+      *(eq-1) = '\0';
+    } else {
+      /* old style assignment */
+      eq[0] = '\0';
+    }
+    opt = eq + 1;
+
+    /*
+     * For each recognized option
+     */
+    for (op = opt_fields; op->name; op++) {
+      /*
+       * Check whether they match
+       */
+      if (FSTREQ(op->name, f)) {
+	if (op->sel_p) {
+	  plog(XLOG_USER, "key %s: Can't assign to a selector (%s)",
+	       mapkey, op->name);
+	  return 0;
+	}
+	*op->optp = opt;	/* actual assignment into fs_static */
+	break;			/* break out of for loop */
+      }	/* end of "if (FSTREQ(op->name, f))" statement  */
+    } /* end of "for (op = opt_fields..." statement  */
+
+    if (!op->name)
+      plog(XLOG_USER, "key %s: Unrecognized key/option \"%s\"", mapkey, f);
+  }
+
+  return 1;
+}
+
+
+/*
+ * Just evaluate selectors, which were split by split_opts.
+ * Returns 0 on error or no match, 1 if matched.
+ */
+static int
+eval_selectors(char *opts, char *mapkey)
+{
+  char *o, *old_o;
   char *f;
+  int ret = 0;
+
+  o = old_o = strdup(opts);
 
   /*
    * For each user-specified option
    */
-  while (*(f = opt(&o))) {
+  for (f = opt(&o); *f; f = opt(&o)) {
     struct opt *op;
-    enum vs_opt vs_opt = VarAss;
+    enum vs_opt vs_opt;
     char *eq = strchr(f, '=');
     char *fx;
     IntFuncPtr func;
     char *opt = NULL;
+    char *arg;
 
-    if (!eq || eq[1] == '\0' || eq == f) {
+    if (!eq) {
       /*
        * No value, is it a function call?
        */
-      char *arg = strchr(f, '(');
+      arg = strchr(f, '(');
 
       if (!arg || arg[1] == '\0' || arg == f) {
 	/*
@@ -489,43 +576,54 @@ eval_opts(char *opts, char *mapkey)
       }
       *fx = '\0';
 
+      if (f[0] == '!') {
+	vs_opt = SelNE;
+	f++;
+      } else {
+	vs_opt = SelEQ;
+      }
       /*
        * look up f in functable and pass it arg.
        * func must return 0 on failure, and 1 on success.
        */
       if ((func = functable_lookup(f))) {
-	if (!(*func) (arg)) {
-	  return (0);
-	}
-	continue;
-      } else if (NSTREQ(f, "!", 1) && (func = functable_lookup(&f[1]))) {
-	/* then this is a negated prefixed function such as "!exists" */
-	plog(XLOG_INFO, "executing negated function %s", &f[1]);
-	if ((*func) (arg)) {
-	  return (0);
-	}
+	int funok;
+
+	/* this allocates memory, don't forget to free */
+	arg = expand_options(arg);
+	funok = func(arg);
+	XFREE(arg);
+
+	if (vs_opt == SelNE)
+	  funok = !funok;
+	if (!funok)
+	  goto out;
+
 	continue;
       } else {
 	plog(XLOG_USER, "key %s: unknown function \"%s\"", mapkey, f);
-	return (0);
+	goto out;
+      }
+    } else {
+      if (eq[1] == '\0' || eq == f) {
+	/* misformed selector */
+	plog(XLOG_USER, "key %s: Bad selector \"%s\"", mapkey, f);
+	continue;
       }
-
     }
 
     /*
      * Check what type of operation is happening
      * !=, =!  is SelNE
      * == is SelEQ
-     * := is VarAss
+     * =, := is VarAss
      */
-    if (eq[-1] == '!') {	/* != */
+    if (*(eq-1) == '!') {	/* != */
       vs_opt = SelNE;
-      eq[-1] = '\0';
-      opt = eq + 1;
-    } else if (eq[-1] == ':') {	/* := */
-      vs_opt = VarAss;
-      eq[-1] = '\0';
+      *(eq-1) = '\0';
       opt = eq + 1;
+    } else if (*(eq-1) == ':') {	/* := */
+      continue;
     } else if (eq[1] == '=') {	/* == */
       vs_opt = SelEQ;
       eq[0] = '\0';
@@ -534,6 +632,9 @@ eval_opts(char *opts, char *mapkey)
       vs_opt = SelNE;
       eq[0] = '\0';
       opt = eq + 2;
+    } else {
+      /* old style assignment */
+      continue;
     }
 
     /*
@@ -544,48 +645,47 @@ eval_opts(char *opts, char *mapkey)
        * Check whether they match
        */
       if (FSTREQ(op->name, f)) {
-        int selok;
-	switch (vs_opt) {
-	case SelEQ:
-	case SelNE:
-          if ((selok = (op->sel_p != NULL))) {
-            if (op->case_insensitive) {
-              selok = (STRCEQ(*op->sel_p, opt) == (vs_opt == SelNE));
-            } else {
-              selok = (STREQ(*op->sel_p, opt) == (vs_opt == SelNE));
-            }
-          }
-          if (selok) {
+	opt = expand_options(opt);
+
+	if (op->sel_p != NULL) {
+	  int selok;
+	  if (op->case_insensitive) {
+	    selok = STRCEQ(*op->sel_p, opt);
+	  } else {
+	    selok = STREQ(*op->sel_p, opt);
+	  }
+	  if (vs_opt == SelNE)
+	    selok = !selok;
+	  if (!selok) {
 	    plog(XLOG_MAP, "key %s: map selector %s (=%s) did not %smatch %s",
 		 mapkey,
 		 op->name,
 		 *op->sel_p,
 		 vs_opt == SelNE ? "mis" : "",
 		 opt);
-	    return 0;
+	    XFREE(opt);
+	    goto out;
 	  }
-	  /* check if to apply a function */
-	  if (op->fxn_p &&
-	      ((*op->fxn_p)(opt) == (vs_opt == SelNE))) {
+	  XFREE(opt);
+	}
+	/* check if to apply a function */
+	if (op->fxn_p) {
+	  int funok;
+
+	  funok = op->fxn_p(opt);
+	  if (vs_opt == SelNE)
+	    funok = !funok;
+	  if (!funok) {
 	    plog(XLOG_MAP, "key %s: map function %s did not %smatch %s",
 		 mapkey,
 		 op->name,
 		 vs_opt == SelNE ? "mis" : "",
 		 opt);
-	    return 0;
-	  }
-	  break;
-
-	case VarAss:
-	  if (op->sel_p) {
-	    plog(XLOG_USER, "key %s: Can't assign to a selector (%s)",
-		 mapkey, op->name);
-	    return 0;
+	    XFREE(opt);
+	    goto out;
 	  }
-	  *op->optp = opt;
-	  break;
-
-	} /* end of "switch (vs_opt)" statement */
+	  XFREE(opt);
+	}
 	break;			/* break out of for loop */
       }
     }
@@ -594,7 +694,12 @@ eval_opts(char *opts, char *mapkey)
       plog(XLOG_USER, "key %s: Unrecognized key/option \"%s\"", mapkey, f);
   }
 
-  return 1;
+  /* all is ok */
+  ret = 1;
+
+ out:
+  free(old_o);
+  return ret;
 }
 
 
@@ -682,9 +787,9 @@ strip_selectors(char *opts, char *mapkey)
      * == is SelEQ
      * := is VarAss
      */
-    if (eq[-1] == '!') {	/* != */
+    if (*(eq-1) == '!') {	/* != */
       vs_opt = SelNE;
-    } else if (eq[-1] == ':') {	/* := */
+    } else if (*(eq-1) == ':') {	/* := */
       vs_opt = VarAss;
     } else if (eq[1] == '=') {	/* == */
       vs_opt = SelEQ;
@@ -702,9 +807,7 @@ strip_selectors(char *opts, char *mapkey)
 
     case VarAss:
       /* found the first assignment, return the string starting with it */
-#ifdef DEBUG
       dlog("found first assignment past selectors \"%s\"", o);
-#endif /* DEBUG */
       return oo;
     }
   }
@@ -725,27 +828,86 @@ f_in_network(char *arg)
   int status;
 
   if (!arg)
-    return FALSE;
+    return 0;
 
   status = is_network_member(arg);
-#ifdef DEBUG
-    plog(XLOG_USER, "%s is %son a local network",
-	 arg, (status ? "" : "not "));
-#endif /* DEBUG */
+  dlog("%s is %son a local network", arg, (status ? "" : "not "));
   return status;
 }
 
 
+/*
+ * Test if arg is any of this host's names or aliases (CNAMES).
+ * Note: this function compares against the fully expanded host name (hostd).
+ * XXX: maybe we also need to compare against the stripped host name?
+ */
+static int
+f_xhost(char *arg)
+{
+  struct hostent *hp;
+  char **cp;
+
+  if (!arg)
+    return 0;
+
+  /* simple test: does it match main host name? */
+  if (STREQ(arg, opt_hostd))
+    return 1;
+
+  /* now find all of the names of "arg" and compare against opt_hostd */
+  hp = gethostbyname(arg);
+  if (hp == NULL) {
+#ifdef HAVE_HSTRERROR
+    plog(XLOG_ERROR, "gethostbyname xhost(%s): %s", arg, hstrerror(h_errno));
+#else /* not HAVE_HSTRERROR */
+    plog(XLOG_ERROR, "gethostbyname xhost(%s): h_errno %d", arg, h_errno);
+#endif /* not HAVE_HSTRERROR */
+    return 0;
+  }
+  /* check primary name */
+  if (hp->h_name) {
+    dlog("xhost: compare %s==%s", hp->h_name, opt_hostd);
+    if (STREQ(hp->h_name, opt_hostd)) {
+      plog(XLOG_INFO, "xhost(%s): matched h_name %s", arg, hp->h_name);
+      return 1;
+    }
+  }
+  /* check all aliases, if any */
+  if (hp->h_aliases == NULL) {
+    dlog("gethostbyname(%s) has no aliases", arg);
+    return 0;
+  }
+  cp = hp->h_aliases;
+  while (*cp) {
+    dlog("xhost: compare alias %s==%s", *cp, opt_hostd);
+    if (STREQ(*cp, opt_hostd)) {
+      plog(XLOG_INFO, "xhost(%s): matched alias %s", arg, *cp);
+      return 1;
+    }
+    cp++;
+  }
+  /* nothing matched */
+  return 0;
+}
+
+
 /* test if this host (short hostname form) is in netgroup (arg) */
 static int
 f_netgrp(char *arg)
 {
   int status;
+  char *ptr, *nhost;
 
-  status = innetgr(arg, opt_host, NULL, NULL);
-#ifdef DEBUG
-  plog(XLOG_USER, "netgrp = %s status = %d host = %s", arg, status, opt_host);
-#endif /* DEBUG */
+  if ((ptr = strchr(arg, ',')) != NULL) {
+    *ptr = '\0';
+    nhost = ptr + 1;
+  } else {
+    nhost = opt_host;
+  }
+  status = innetgr(arg, nhost, NULL, NULL);
+  dlog("netgrp = %s status = %d host = %s", arg, status, nhost);
+  if (ptr)
+    *ptr = ',';
   return status;
 }
 
@@ -755,11 +917,18 @@ static int
 f_netgrpd(char *arg)
 {
   int status;
+  char *ptr, *nhost;
 
-  status = innetgr(arg, opt_hostd, NULL, NULL);
-#ifdef DEBUG
-  plog(XLOG_USER, "netgrp = %s status = %d hostd = %s", arg, status, opt_hostd);
-#endif /* DEBUG */
+  if ((ptr = strchr(arg, ',')) != NULL) {
+    *ptr = '\0';
+    nhost = ptr + 1;
+  } else {
+    nhost = opt_hostd;
+  }
+  status = innetgr(arg, nhost, NULL, NULL);
+  dlog("netgrp = %s status = %d hostd = %s", arg, status, nhost);
+  if (ptr)
+    *ptr = ',';
   return status;
 }
 
@@ -801,7 +970,6 @@ free_op(opt_apply *p, int b)
 {
   if (*p->opt) {
     XFREE(*p->opt);
-    *p->opt = 0;
   }
 }
 
@@ -812,9 +980,12 @@ free_op(opt_apply *p, int b)
 void
 normalize_slash(char *p)
 {
-  char *f = strchr(p, '/');
-  char *f0 = f;
+  char *f, *f0;
+
+  if (!(gopt.flags & CFM_NORMALIZE_SLASHES))
+    return;
 
+  f0 = f = strchr(p, '/');
   if (f) {
     char *t = f;
     do {
@@ -836,6 +1007,9 @@ normalize_slash(char *p)
       /* assert(*f != '/'); */
       /* keep copying up to next / */
       while (*f && *f != '/') {
+	/* support escaped slashes '\/' */
+	if (f[0] == '\\' && f[1] == '/')
+	  f++;			/* skip backslash */
 	*t++ = *f++;
       }
 
@@ -850,22 +1024,20 @@ normalize_slash(char *p)
 /*
  * Macro-expand an option.  Note that this does not
  * handle recursive expansions.  They will go badly wrong.
- * If sel is true then old expand selectors, otherwise
+ * If sel_p is true then old expand selectors, otherwise
  * don't expand selectors.
  */
-static void
-expand_op(opt_apply *p, int sel_p)
+static char *
+expand_op(char *opt, int sel_p)
 {
-  static char expand_error[] = "No space to expand \"%s\"";
+#define EXPAND_ERROR "No space to expand \"%s\""
   char expbuf[MAXPATHLEN + 1];
   char nbuf[NLEN + 1];
   char *ep = expbuf;
-  char *cp = *p->opt;
+  char *cp = opt;
   char *dp;
   struct opt *op;
-#ifdef DEBUG
-  char *cp_orig = *p->opt;
-#endif /* DEBUG */
+  char *cp_orig = opt;
 
   while ((dp = strchr(cp, '$'))) {
     char ch;
@@ -875,12 +1047,18 @@ expand_op(opt_apply *p, int sel_p)
     {
       int len = dp - cp;
 
-      if (BUFSPACE(ep, len)) {
-	strncpy(ep, cp, len);
-	ep += len;
-      } else {
-	plog(XLOG_ERROR, expand_error, *p->opt);
-	goto out;
+      if (len > 0) {
+	if (BUFSPACE(ep, len)) {
+	  /*
+	   * We use strncpy (not xstrlcpy) because 'ep' relies on its
+	   * semantics.  BUFSPACE guarantees that ep can hold len.
+	   */
+	  strncpy(ep, cp, len);
+	  ep += len;
+	} else {
+	  plog(XLOG_ERROR, EXPAND_ERROR, opt);
+	  goto out;
+	}
       }
     }
 
@@ -890,7 +1068,7 @@ expand_op(opt_apply *p, int sel_p)
       if (BUFSPACE(ep, 1)) {
 	*ep++ = '$';
       } else {
-	plog(XLOG_ERROR, expand_error, *p->opt);
+	plog(XLOG_ERROR, EXPAND_ERROR, opt);
 	goto out;
       }
     } else if (ch == '{') {
@@ -911,7 +1089,7 @@ expand_op(opt_apply *p, int sel_p)
 	/*
 	 * Just give up
 	 */
-	plog(XLOG_USER, "No closing '}' in \"%s\"", *p->opt);
+	plog(XLOG_USER, "No closing '}' in \"%s\"", opt);
 	goto out;
       }
       len = br_p - cp;
@@ -926,7 +1104,7 @@ expand_op(opt_apply *p, int sel_p)
 	todo = E_File;
 	cp++;
 	--len;
-      } else if (br_p[-1] == '/') {
+      } else if (*(br_p-1) == '/') {
 	/*
 	 * Take all but the last component
 	 */
@@ -939,7 +1117,7 @@ expand_op(opt_apply *p, int sel_p)
 	todo = E_Domain;
 	cp++;
 	--len;
-      } else if (br_p[-1] == '.') {
+      } else if (*(br_p-1) == '.') {
 	/*
 	 * Take host name
 	 */
@@ -963,6 +1141,11 @@ expand_op(opt_apply *p, int sel_p)
       /*
        * Put the string into another buffer so
        * we can do comparisons.
+       *
+       * We use strncpy here (not xstrlcpy) because the dest is meant
+       * to be truncated and we don't want to log it as an error.  The
+       * use of the BUFSPACE macro above guarantees the safe use of
+       * strncpy with nbuf.
        */
       strncpy(nbuf, cp, len);
       nbuf[len] = '\0';
@@ -990,12 +1173,12 @@ expand_op(opt_apply *p, int sel_p)
 	    /*
 	     * Copy the string across unexpanded
 	     */
-	    sprintf(xbuf, "${%s%s%s}",
-		    todo == E_File ? "/" :
-		    todo == E_Domain ? "." : "",
-		    nbuf,
-		    todo == E_Dir ? "/" :
-		    todo == E_Host ? "." : "");
+	    xsnprintf(xbuf, sizeof(xbuf), "${%s%s%s}",
+		      todo == E_File ? "/" :
+		      todo == E_Domain ? "." : "",
+		      nbuf,
+		      todo == E_Dir ? "/" :
+		      todo == E_Host ? "." : "");
 	    val = xbuf;
 	    /*
 	     * Make sure expansion doesn't
@@ -1054,11 +1237,11 @@ expand_op(opt_apply *p, int sel_p)
 	      break;
 	    }
 
-	    if (BUFSPACE(ep, vlen)) {
-	      strcpy(ep, vptr);
+	    if (BUFSPACE(ep, vlen+1)) {
+	      xstrlcpy(ep, vptr, vlen+1);
 	      ep += vlen;
 	    } else {
-	      plog(XLOG_ERROR, expand_error, *p->opt);
+	      plog(XLOG_ERROR, EXPAND_ERROR, opt);
 	      goto out;
 	    }
 	  }
@@ -1083,17 +1266,15 @@ expand_op(opt_apply *p, int sel_p)
 	if (env) {
 	  int vlen = strlen(env);
 
-	  if (BUFSPACE(ep, vlen)) {
-	    strcpy(ep, env);
+	  if (BUFSPACE(ep, vlen+1)) {
+	    xstrlcpy(ep, env, vlen+1);
 	    ep += vlen;
 	  } else {
-	    plog(XLOG_ERROR, expand_error, *p->opt);
+	    plog(XLOG_ERROR, EXPAND_ERROR, opt);
 	    goto out;
 	  }
-#ifdef DEBUG
-	  amuDebug(D_STR)
+	  if (amuDebug(D_STR))
 	    plog(XLOG_DEBUG, "Environment gave \"%s\" -> \"%s\"", nbuf, env);
-#endif /* DEBUG */
 	} else {
 	  plog(XLOG_USER, "Unknown sequence \"${%s}\"", nbuf);
 	}
@@ -1102,7 +1283,7 @@ expand_op(opt_apply *p, int sel_p)
       /*
        * Error, error
        */
-      plog(XLOG_USER, "Unknown $ sequence in \"%s\"", *p->opt);
+      plog(XLOG_USER, "Unknown $ sequence in \"%s\"", opt);
     }
   }
 
@@ -1110,33 +1291,33 @@ out:
   /*
    * Handle common case - no expansion
    */
-  if (cp == *p->opt) {
-    *p->opt = strdup(cp);
+  if (cp == opt) {
+    opt = strdup(cp);
   } else {
     /*
      * Finish off the expansion
      */
-    if (BUFSPACE(ep, strlen(cp))) {
-      strcpy(ep, cp);
-      /* ep += strlen(ep); */
+    int vlen = strlen(cp);
+    if (BUFSPACE(ep, vlen+1)) {
+      xstrlcpy(ep, cp, vlen+1);
+      /* ep += vlen; */
     } else {
-      plog(XLOG_ERROR, expand_error, *p->opt);
+      plog(XLOG_ERROR, EXPAND_ERROR, opt);
     }
 
     /*
      * Save the expansion
      */
-    *p->opt = strdup(expbuf);
+    opt = strdup(expbuf);
   }
 
-  normalize_slash(*p->opt);
+  normalize_slash(opt);
 
-#ifdef DEBUG
-  amuDebug(D_STR) {
+  if (amuDebug(D_STR)) {
     plog(XLOG_DEBUG, "Expansion of \"%s\"...", cp_orig);
-    plog(XLOG_DEBUG, "... is \"%s\"", *p->opt);
+    plog(XLOG_DEBUG, "......... is \"%s\"", opt);
   }
-#endif /* DEBUG */
+  return opt;
 }
 
 
@@ -1147,15 +1328,15 @@ static void
 expand_opts(opt_apply *p, int sel_p)
 {
   if (*p->opt) {
-    expand_op(p, sel_p);
+    *p->opt = expand_op(*p->opt, sel_p);
   } else if (p->val) {
     /*
      * Do double expansion, remembering
      * to free the string from the first
      * expansion...
      */
-    char *s = *p->opt = expand_key(p->val);
-    expand_op(p, sel_p);
+    char *s = expand_op(p->val, TRUE);
+    *p->opt = expand_op(s, sel_p);
     XFREE(s);
   }
 }
@@ -1193,18 +1374,22 @@ free_opts(am_opts *fo)
 
 
 /*
- * Expand lookup key
+ * Expand selectors (variables that cannot be assigned to or overridden)
  */
 char *
-expand_key(char *key)
+expand_selectors(char *key)
 {
-  opt_apply oa;
+  return expand_op(key, TRUE);
+}
 
-  oa.opt = &key;
-  oa.val = 0;
-  expand_opts(&oa, TRUE);
 
-  return key;
+/*
+ * Expand options (i.e. non-selectors, see above for definition)
+ */
+static inline char *
+expand_options(char *key)
+{
+  return expand_op(key, FALSE);
 }
 
 
@@ -1212,10 +1397,14 @@ expand_key(char *key)
  * Remove trailing /'s from a string
  * unless the string is a single / (Steven Glassman)
  * or unless it is two slashes // (Kevin D. Bond)
+ * or unless amd.conf says not to touch slashes.
  */
 void
 deslashify(char *s)
 {
+  if (!(gopt.flags & CFM_NORMALIZE_SLASHES))
+    return;
+
   if (s && *s) {
     char *sl = s + strlen(s);
 
@@ -1263,24 +1452,27 @@ eval_fs_opts(am_opts *fo, char *opts, char *g_opts, char *path, char *key, char
   /*
    * Expand global options
    */
-  fs_static.fs_glob = expand_key(g_opts);
+  fs_static.fs_glob = expand_selectors(g_opts);
 
   /*
    * Expand local options
    */
-  fs_static.fs_local = expand_key(opts);
-
-  /*
-   * Expand default (global) options
-   */
-  if (!eval_opts(fs_static.fs_glob, key))
-    ok = FALSE;
+  fs_static.fs_local = expand_selectors(opts);
 
-  /*
-   * Expand local options
-   */
-  if (ok && !eval_opts(fs_static.fs_local, key))
-    ok = FALSE;
+  /* break global options into fs_static fields */
+  if ((ok = split_opts(fs_static.fs_glob, key))) {
+    dlog("global split_opts ok");
+    /*
+     * evaluate local selectors
+     */
+    if ((ok = eval_selectors(fs_static.fs_local, key))) {
+      dlog("local eval_selectors ok");
+      /* if the local selectors matched, then do the local overrides */
+      ok = split_opts(fs_static.fs_local, key);
+      if (ok)
+	dlog("local split_opts ok");
+    }
+  }
 
   /*
    * Normalize remote host name.
diff --git a/contrib/amd/amd/readdir.c b/contrib/amd/amd/readdir.c
new file mode 100644
index 0000000..d025c91
--- /dev/null
+++ b/contrib/amd/amd/readdir.c
@@ -0,0 +1,498 @@
+/*
+ * Copyright (c) 1997-2006 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.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * 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.
+ *
+ *
+ * File: am-utils/amd/readdir.c
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amd.h>
+
+
+/****************************************************************************
+ *** MACROS                                                               ***
+ ****************************************************************************/
+#define DOT_DOT_COOKIE	(u_int) 1
+#define MAX_CHAIN	2048
+
+
+/****************************************************************************
+ *** FORWARD DEFINITIONS                                                  ***
+ ****************************************************************************/
+static int key_already_in_chain(char *keyname, const nfsentry *chain);
+static nfsentry *make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable);
+static int amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable);
+
+
+/****************************************************************************
+ *** FUNCTIONS                                                             ***
+ ****************************************************************************/
+/*
+ * Was: NEW_TOPLVL_READDIR
+ * Search a chain for an entry with some name.
+ * -Erez Zadok <ezk@cs.columbia.edu>
+ */
+static int
+key_already_in_chain(char *keyname, const nfsentry *chain)
+{
+  const nfsentry *tmpchain = chain;
+
+  while (tmpchain) {
+    if (keyname && tmpchain->ne_name && STREQ(keyname, tmpchain->ne_name))
+        return 1;
+    tmpchain = tmpchain->ne_nextentry;
+  }
+
+  return 0;
+}
+
+
+/*
+ * Create a chain of entries which are not linked.
+ * -Erez Zadok <ezk@cs.columbia.edu>
+ */
+static nfsentry *
+make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable)
+{
+  static u_int last_cookie = (u_int) 2;	/* monotonically increasing */
+  static nfsentry chain[MAX_CHAIN];
+  static int max_entries = MAX_CHAIN;
+  char *key;
+  int num_entries = 0, i;
+  u_int preflen = 0;
+  nfsentry *retval = (nfsentry *) NULL;
+  mntfs *mf;
+  mnt_map *mmp;
+
+  if (!mp) {
+    plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)");
+    return retval;
+  }
+  mf = mp->am_mnt;
+  if (!mf) {
+    plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt is (NULL)");
+    return retval;
+  }
+  mmp = (mnt_map *) mf->mf_private;
+  if (!mmp) {
+    plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt->mf_private is (NULL)");
+    return retval;
+  }
+
+  if (mp->am_pref)
+    preflen = strlen(mp->am_pref);
+
+  /* iterate over keys */
+  for (i = 0; i < NKVHASH; i++) {
+    kv *k;
+    for (k = mmp->kvhash[i]; k ; k = k->next) {
+
+      /*
+       * Skip unwanted entries which are either not real entries or
+       * very difficult to interpret (wildcards...)  This test needs
+       * lots of improvement.  Any takers?
+       */
+      key = k->key;
+      if (!key)
+	continue;
+
+      /* Skip '/defaults' */
+      if (STREQ(key, "/defaults"))
+	continue;
+
+      /* Skip '*' */
+      if (!fully_browsable && strchr(key, '*'))
+	continue;
+
+      /*
+       * If the map has a prefix-string then check if the key starts with
+       * this string, and if it does, skip over this prefix.  If it has a
+       * prefix and it doesn't match the start of the key, skip it.
+       */
+      if (preflen) {
+	if (preflen > strlen(key))
+	  continue;
+	if (!NSTREQ(key, mp->am_pref, preflen))
+	  continue;
+	key += preflen;
+      }
+
+      /* no more '/' are allowed, unless browsable_dirs=full was used */
+      if (!fully_browsable && strchr(key, '/'))
+	continue;
+
+      /* no duplicates allowed */
+      if (key_already_in_chain(key, current_chain))
+	continue;
+
+      /* fill in a cell and link the entry */
+      if (num_entries >= max_entries) {
+	/* out of space */
+	plog(XLOG_DEBUG, "make_entry_chain: no more space in chain");
+	if (num_entries > 0) {
+	  chain[num_entries - 1].ne_nextentry = 0;
+	  retval = &chain[0];
+	}
+	return retval;
+      }
+
+      /* we have space.  put entry in next cell */
+      ++last_cookie;
+      chain[num_entries].ne_fileid = (u_int) last_cookie;
+      *(u_int *) chain[num_entries].ne_cookie = (u_int) last_cookie;
+      chain[num_entries].ne_name = key;
+      if (num_entries < max_entries - 1) {	/* link to next one */
+	chain[num_entries].ne_nextentry = &chain[num_entries + 1];
+      }
+      ++num_entries;
+    } /* end of "while (k)" */
+  } /* end of "for (i ... NKVHASH ..." */
+
+  /* terminate chain */
+  if (num_entries > 0) {
+    chain[num_entries - 1].ne_nextentry = 0;
+    retval = &chain[0];
+  }
+
+  return retval;
+}
+
+
+
+/* This one is called only if map is browsable */
+static int
+amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable)
+{
+  u_int gen = *(u_int *) cookie;
+  int chain_length, i;
+  static nfsentry *te, *te_next;
+  static int j;
+
+  dp->dl_eof = FALSE;		/* assume readdir not done */
+
+  if (amuDebug(D_READDIR))
+    plog(XLOG_DEBUG, "amfs_readdir_browsable gen=%u, count=%d",
+	 gen, count);
+
+  if (gen == 0) {
+    /*
+     * In the default instance (which is used to start a search) we return
+     * "." and "..".
+     *
+     * This assumes that the count is big enough to allow both "." and ".."
+     * to be returned in a single packet.  If it isn't (which would be
+     * fairly unbelievable) then tough.
+     */
+    dlog("amfs_readdir_browsable: default search");
+    /*
+     * Check for enough room.  This is extremely approximate but is more
+     * than enough space.  Really need 2 times:
+     *      4byte fileid
+     *      4byte cookie
+     *      4byte name length
+     *      4byte name
+     * plus the dirlist structure */
+    if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
+      return EINVAL;
+
+    /*
+     * compute # of entries to send in this chain.
+     * heuristics: 128 bytes per entry.
+     * This is too much probably, but it seems to work better because
+     * of the re-entrant nature of nfs_readdir, and esp. on systems
+     * like OpenBSD 2.2.
+     */
+    chain_length = count / 128;
+
+    /* reset static state counters */
+    te = te_next = NULL;
+
+    dp->dl_entries = ep;
+
+    /* construct "." */
+    ep[0].ne_fileid = mp->am_gen;
+    ep[0].ne_name = ".";
+    ep[0].ne_nextentry = &ep[1];
+    *(u_int *) ep[0].ne_cookie = 0;
+
+    /* construct ".." */
+    if (mp->am_parent)
+      ep[1].ne_fileid = mp->am_parent->am_gen;
+    else
+      ep[1].ne_fileid = mp->am_gen;
+
+    ep[1].ne_name = "..";
+    ep[1].ne_nextentry = 0;
+    *(u_int *) ep[1].ne_cookie = DOT_DOT_COOKIE;
+
+    /*
+     * If map is browsable, call a function make_entry_chain() to construct
+     * a linked list of unmounted keys, and return it.  Then link the chain
+     * to the regular list.  Get the chain only once, but return
+     * chunks of it each time.
+     */
+    te = make_entry_chain(mp, dp->dl_entries, fully_browsable);
+    if (!te)
+      return 0;
+    if (amuDebug(D_READDIR)) {
+      nfsentry *ne;
+      for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
+	plog(XLOG_DEBUG, "gen1 key %4d \"%s\"", j++, ne->ne_name);
+    }
+
+    /* return only "chain_length" entries */
+    te_next = te;
+    for (i=1; i<chain_length; ++i) {
+      te_next = te_next->ne_nextentry;
+      if (!te_next)
+	break;
+    }
+    if (te_next) {
+      nfsentry *te_saved = te_next->ne_nextentry;
+      te_next->ne_nextentry = NULL; /* terminate "te" chain */
+      te_next = te_saved;	/* save rest of "te" for next iteration */
+      dp->dl_eof = FALSE;	/* tell readdir there's more */
+    } else {
+      dp->dl_eof = TRUE;	/* tell readdir that's it */
+    }
+    ep[1].ne_nextentry = te;	/* append this chunk of "te" chain */
+    if (amuDebug(D_READDIR)) {
+      nfsentry *ne;
+      for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
+	plog(XLOG_DEBUG, "gen2 key %4d \"%s\"", j++, ne->ne_name);
+      for (j = 0, ne = ep; ne; ne = ne->ne_nextentry)
+	plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%d ck=%d",
+	     j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie);
+      plog(XLOG_DEBUG, "EOF is %d", dp->dl_eof);
+    }
+    return 0;
+  } /* end of "if (gen == 0)" statement */
+
+  dlog("amfs_readdir_browsable: real child");
+
+  if (gen == DOT_DOT_COOKIE) {
+    dlog("amfs_readdir_browsable: End of readdir in %s", mp->am_path);
+    dp->dl_eof = TRUE;
+    dp->dl_entries = 0;
+    return 0;
+  }
+
+  /*
+   * If browsable directories, then continue serving readdir() with another
+   * chunk of entries, starting from where we left off (when gen was equal
+   * to 0).  Once again, assume last chunk served to readdir.
+   */
+  dp->dl_eof = TRUE;
+  dp->dl_entries = ep;
+
+  te = te_next;			/* reset 'te' from last saved te_next */
+  if (!te) {			/* another indicator of end of readdir */
+    dp->dl_entries = 0;
+    return 0;
+  }
+  /*
+   * compute # of entries to send in this chain.
+   * heuristics: 128 bytes per entry.
+   */
+  chain_length = count / 128;
+
+  /* return only "chain_length" entries */
+  for (i = 1; i < chain_length; ++i) {
+    te_next = te_next->ne_nextentry;
+    if (!te_next)
+      break;
+  }
+  if (te_next) {
+    nfsentry *te_saved = te_next->ne_nextentry;
+    te_next->ne_nextentry = NULL; /* terminate "te" chain */
+    te_next = te_saved;		/* save rest of "te" for next iteration */
+    dp->dl_eof = FALSE;		/* tell readdir there's more */
+  }
+  ep = te;			/* send next chunk of "te" chain */
+  dp->dl_entries = ep;
+  if (amuDebug(D_READDIR)) {
+    nfsentry *ne;
+    plog(XLOG_DEBUG, "dl_entries=%p, te_next=%p, dl_eof=%d",
+	 dp->dl_entries, te_next, dp->dl_eof);
+    for (ne = te; ne; ne = ne->ne_nextentry)
+      plog(XLOG_DEBUG, "gen3 key %4d \"%s\"", j++, ne->ne_name);
+  }
+  return 0;
+}
+
+
+/*
+ * This readdir function which call a special version of it that allows
+ * browsing if browsable_dirs=yes was set on the map.
+ */
+int
+amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
+{
+  u_int gen = *(u_int *) cookie;
+  am_node *xp;
+  mntent_t mnt;
+
+  dp->dl_eof = FALSE;		/* assume readdir not done */
+
+  /* check if map is browsable */
+  if (mp->am_mnt && mp->am_mnt->mf_mopts) {
+    mnt.mnt_opts = mp->am_mnt->mf_mopts;
+    if (amu_hasmntopt(&mnt, "fullybrowsable"))
+      return amfs_readdir_browsable(mp, cookie, dp, ep, count, TRUE);
+    if (amu_hasmntopt(&mnt, "browsable"))
+      return amfs_readdir_browsable(mp, cookie, dp, ep, count, FALSE);
+  }
+
+  /* when gen is 0, we start reading from the beginning of the directory */
+  if (gen == 0) {
+    /*
+     * In the default instance (which is used to start a search) we return
+     * "." and "..".
+     *
+     * This assumes that the count is big enough to allow both "." and ".."
+     * to be returned in a single packet.  If it isn't (which would be
+     * fairly unbelievable) then tough.
+     */
+    dlog("amfs_generic_readdir: default search");
+    /*
+     * Check for enough room.  This is extremely approximate but is more
+     * than enough space.  Really need 2 times:
+     *      4byte fileid
+     *      4byte cookie
+     *      4byte name length
+     *      4byte name
+     * plus the dirlist structure */
+    if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
+      return EINVAL;
+
+    xp = next_nonerror_node(mp->am_child);
+    dp->dl_entries = ep;
+
+    /* construct "." */
+    ep[0].ne_fileid = mp->am_gen;
+    ep[0].ne_name = ".";
+    ep[0].ne_nextentry = &ep[1];
+    *(u_int *) ep[0].ne_cookie = 0;
+
+    /* construct ".." */
+    if (mp->am_parent)
+      ep[1].ne_fileid = mp->am_parent->am_gen;
+    else
+      ep[1].ne_fileid = mp->am_gen;
+    ep[1].ne_name = "..";
+    ep[1].ne_nextentry = 0;
+    *(u_int *) ep[1].ne_cookie = (xp ? xp->am_gen : DOT_DOT_COOKIE);
+
+    if (!xp)
+      dp->dl_eof = TRUE;	/* by default assume readdir done */
+
+    if (amuDebug(D_READDIR)) {
+      nfsentry *ne;
+      int j;
+      for (j = 0, ne = ep; ne; ne = ne->ne_nextentry)
+	plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%d ck=%d",
+	     j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie);
+    }
+    return 0;
+  }
+  dlog("amfs_generic_readdir: real child");
+
+  if (gen == DOT_DOT_COOKIE) {
+    dlog("amfs_generic_readdir: End of readdir in %s", mp->am_path);
+    dp->dl_eof = TRUE;
+    dp->dl_entries = 0;
+    if (amuDebug(D_READDIR))
+      plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n");
+    return 0;
+  }
+
+  /* non-browsable directories code */
+  xp = mp->am_child;
+  while (xp && xp->am_gen != gen)
+    xp = xp->am_osib;
+
+  if (xp) {
+    int nbytes = count / 2;	/* conservative */
+    int todo = MAX_READDIR_ENTRIES;
+
+    dp->dl_entries = ep;
+    do {
+      am_node *xp_next = next_nonerror_node(xp->am_osib);
+
+      if (xp_next) {
+	*(u_int *) ep->ne_cookie = xp_next->am_gen;
+      } else {
+	*(u_int *) ep->ne_cookie = DOT_DOT_COOKIE;
+	dp->dl_eof = TRUE;
+      }
+
+      ep->ne_fileid = xp->am_gen;
+      ep->ne_name = xp->am_name;
+      nbytes -= sizeof(*ep) + 1;
+      if (xp->am_name)
+	nbytes -= strlen(xp->am_name);
+
+      xp = xp_next;
+
+      if (nbytes > 0 && !dp->dl_eof && todo > 1) {
+	ep->ne_nextentry = ep + 1;
+	ep++;
+	--todo;
+      } else {
+	todo = 0;
+      }
+    } while (todo > 0);
+
+    ep->ne_nextentry = 0;
+
+    if (amuDebug(D_READDIR)) {
+      nfsentry *ne;
+      int j;
+      for (j=0,ne=ep; ne; ne=ne->ne_nextentry)
+	plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%d ck=%d",
+	     j++, ne->ne_name, ne->ne_fileid, *(u_int *)ne->ne_cookie);
+    }
+    return 0;
+  }
+  return ESTALE;
+}
diff --git a/contrib/amd/amd/restart.c b/contrib/amd/amd/restart.c
index bd8e4aa..4f71e38 100644
--- a/contrib/amd/amd/restart.c
+++ b/contrib/amd/amd/restart.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: restart.c,v 1.2 1999/01/10 21:53:52 ezk Exp $
+ * File: am-utils/amd/restart.c
  *
  */
 
@@ -49,14 +48,81 @@
 #include <amd.h>
 
 
+static void
+restart_fake_mntfs(mntent_t *me, am_ops *fs_ops)
+{
+  mntfs *mf;
+  am_opts mo;
+  char *cp;
+
+  /*
+   * Partially fake up an opts structure
+   */
+  memset(&mo, 0, sizeof(mo));
+  mo.opt_rhost = 0;
+  mo.opt_rfs = 0;
+  cp = strchr(me->mnt_fsname, ':');
+  if (cp) {
+    *cp = '\0';
+    mo.opt_rhost = strdup(me->mnt_fsname);
+    mo.opt_rfs = strdup(cp + 1);
+    *cp = ':';
+  } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
+    /*
+     * Hacky workaround for mnttab NFS entries that only list the server
+     */
+    plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
+    mo.opt_rhost = strdup(me->mnt_fsname);
+    mo.opt_rfs = strdup("/");
+    me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
+  }
+  mo.opt_fs = me->mnt_dir;
+  mo.opt_opts = me->mnt_opts;
+
+  /*
+   * Make a new mounted filesystem
+   */
+  mf = find_mntfs(fs_ops, &mo, me->mnt_dir,
+		  me->mnt_fsname, "", me->mnt_opts, "");
+  if (mf->mf_refc == 1) {
+    mf->mf_flags |= MFF_RESTART | MFF_MOUNTED;
+    mf->mf_error = 0;		     /* Already mounted correctly */
+    mf->mf_fo = 0;
+    /*
+     * Only timeout non-NFS entries
+     */
+    if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS))
+      mf->mf_flags |= MFF_RSTKEEP;
+    if (fs_ops->fs_init) {
+      /*
+       * Don't care whether this worked since
+       * it is checked again when the fs is
+       * inherited.
+       */
+      (void) (*fs_ops->fs_init) (mf);
+    }
+    plog(XLOG_INFO, "%s restarted fstype %s on %s, flags 0x%x",
+	 me->mnt_fsname, fs_ops->fs_type, me->mnt_dir, mf->mf_flags);
+  } else {
+    /* Something strange happened - two mounts at the same place! */
+    free_mntfs(mf);
+  }
+  /*
+   * Clean up mo
+   */
+  if (mo.opt_rhost)
+    XFREE(mo.opt_rhost);
+  if (mo.opt_rfs)
+    XFREE(mo.opt_rfs);
+}
+
+
 /*
  * Handle an amd restart.
  *
  * Scan through the mount list finding all "interesting" mount points.
  * Next hack up partial data structures and add the mounted file
- * system to the list of known filesystems.  This will leave a
- * dangling reference to that filesystems, so when the filesystem is
- * finally inherited, an extra "free" must be done on it.
+ * system to the list of known filesystems.
  *
  * This module relies on internal details of other components.  If
  * you change something else make *sure* restart() still works.
@@ -64,26 +130,19 @@
 void
 restart(void)
 {
-  /*
-   * Read the existing mount table
-   */
   mntlist *ml, *mlp;
 
   /*
-   * For each entry, find nfs, ufs or auto mounts
-   * and create a partial am_node to represent it.
+   * Read the existing mount table.  For each entry, find nfs, ufs or auto
+   * mounts and create a partial am_node to represent it.
    */
   for (mlp = ml = read_mtab("restart", mnttab_file_name);
        mlp;
        mlp = mlp->mnext) {
     mntent_t *me = mlp->mnt;
     am_ops *fs_ops = 0;
-    if (STREQ(me->mnt_type, MNTTAB_TYPE_UFS)) {
-      /*
-       * UFS entry
-       */
-      fs_ops = &ufs_ops;
-    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
+
+    if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
       /*
        * NFS entry, or possibly an Amd entry...
        * The mnt_fsname for daemon mount points is
@@ -92,117 +151,138 @@ restart(void)
        *        host:daemon(pidXXX)
        */
       char *colon = strchr(me->mnt_fsname, ':');
+      if (colon && strstr(colon, "(pid"))
+	continue;
+    }
 
-      if (colon && strstr(colon, "(pid")) {
-	plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
-	fs_ops = &amfs_link_ops;
-      } else {
-	fs_ops = &nfs_ops;
-      }
-#ifdef MNTTAB_TYPE_NFS3
-    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS3)) {
-      fs_ops = &nfs_ops;
-#endif /* MNTTAB_TYPE_NFS3 */
-#ifdef MNTTAB_TYPE_LOFS
-    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_LOFS)) {
-      fs_ops = &lofs_ops;
-#endif /* MNTTAB_TYPE_LOFS */
-#ifdef MNTTAB_TYPE_CDFS
-    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_CDFS)) {
-      fs_ops = &cdfs_ops;
-#endif /* MNTTAB_TYPE_CDFS */
-#ifdef MNTTAB_TYPE_PCFS
-    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_PCFS)) {
-      fs_ops = &pcfs_ops;
-#endif /* MNTTAB_TYPE_PCFS */
-#ifdef MNTTAB_TYPE_MFS
-    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_MFS)) {
-      /*
-       * MFS entry.  Fake with a symlink.
-       */
-      fs_ops = &amfs_link_ops;
-#endif /* MNTTAB_TYPE_MFS */
-    } else {
-      /*
-       * Catch everything else with symlinks to
-       * avoid recursive mounts.  This is debatable...
-       */
+    /* Search for the correct filesystem ops */
+    fs_ops = ops_search(me->mnt_type);
+
+    /*
+     * Catch everything else with symlinks to
+     * avoid recursive mounts.  This is debatable...
+     */
+    if (!fs_ops)
       fs_ops = &amfs_link_ops;
+
+    restart_fake_mntfs(me, fs_ops);
+  }
+
+  /*
+   * Free the mount list
+   */
+  free_mntlist(ml);
+}
+
+
+/*
+ * Handle an amd restart for amd's own mount points.
+ *
+ * Scan through the mount list finding all daemon mount points
+ * (determined by the presence of a pid inside the mount info).
+ * Next hack up partial data structures and add the mounted file
+ * system to the list of known filesystems.
+ *
+ * This module relies on internal details of other components.  If
+ * you change something else make *sure* restart() still works.
+ */
+void
+restart_automounter_nodes(void)
+{
+  mntlist *ml, *mlp;
+  /* reasonably sized list of restarted nfs ports */
+  u_short old_ports[256];
+
+  memset((voidp) &old_ports, 0, sizeof(u_short) * 256);
+
+  /*
+   * Read the existing mount table.  For each entry, find nfs, ufs or auto
+   * mounts and create a partial am_node to represent it.
+   */
+  for (mlp = ml = read_mtab("restart", mnttab_file_name);
+       mlp;
+       mlp = mlp->mnext) {
+    mntent_t *me = mlp->mnt;
+    am_ops *fs_ops = 0;
+    char *colon;
+    long pid;
+    u_short port;
+    int err;
+
+    if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS))
+      continue;			/* to next mlp */
+    /*
+     * NFS entry, or possibly an Amd entry...
+     * The mnt_fsname for daemon mount points is
+     *	   host:(pidXXX)
+     * or (seen on Solaris)
+     *     host:daemon(pidXXX)
+     */
+    colon = strchr(me->mnt_fsname, ':');
+    if (!colon || !strstr(colon, "(pid"))
+      continue;
+    /* if got here, then we matched an existing Amd mount point */
+    err = 1;
+
+    plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
+
+    /* Is the old automounter still alive? */
+    if (sscanf(colon, "%*[^(](pid%ld%*[,)]", &pid) != 1) {
+      plog(XLOG_WARNING, "Can't parse pid in %s", me->mnt_fsname);
+      goto give_up;
+    }
+    if (kill(pid, 0) != -1 || errno != ESRCH) {
+      plog(XLOG_WARNING, "Automounter (pid: %ld) still alive", pid);
+      goto give_up;
     }
 
     /*
-     * If we found something to do
+     * Do we have a map for this mount point?  Who cares, we'll restart
+     * anyway -- getting ESTALE is way better than hanging.
      */
-    if (fs_ops) {
-      mntfs *mf;
-      am_opts mo;
-      char *cp;
-      cp = strchr(me->mnt_fsname, ':');
 
-      /*
-       * Partially fake up an opts structure
-       */
-      mo.opt_rhost = 0;
-      mo.opt_rfs = 0;
-      if (cp) {
-	*cp = '\0';
-	mo.opt_rhost = strdup(me->mnt_fsname);
-	mo.opt_rfs = strdup(cp + 1);
-	*cp = ':';
-      } else if (fs_ops->ffserver == find_nfs_srvr) {
-	/*
-	 * Prototype 4.4 BSD used to end up here -
-	 * might as well keep the workaround for now
-	 */
-	plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
-	mo.opt_rhost = strdup(me->mnt_fsname);
-	mo.opt_rfs = strdup("/");
-	me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
+    /* Can we restart it? Only if it tells us what port it was using... */
+    if (sscanf(colon, "%*[^,],port%hu)", &port) != 1) {
+      plog(XLOG_WARNING, "No port specified for %s", me->mnt_fsname);
+      goto give_up;
+    }
+
+    /* Maybe we already own that port... */
+    if (port != nfs_port) {
+      int i;
+      for (i = 0; i < 256; i++) {
+	if (old_ports[i] == port ||
+	    old_ports[i] == 0)
+	  break;
+      }
+      if (i == 256) {
+	plog(XLOG_WARNING, "Too many open ports (256)");
+	goto give_up;
       }
-      mo.opt_fs = me->mnt_dir;
-      mo.opt_opts = me->mnt_opts;
 
-      /*
-       * Make a new mounted filesystem
-       */
-      mf = find_mntfs(fs_ops, &mo, me->mnt_dir,
-		      me->mnt_fsname, "", me->mnt_opts, "");
-      if (mf->mf_refc == 1) {
-	mf->mf_flags |= MFF_RESTART | MFF_MOUNTED;
-	mf->mf_error = 0;	/* Already mounted correctly */
-	mf->mf_fo = 0;
-	/*
-	 * If the restarted type is a link then
-	 * don't time out.
-	 */
-	if (fs_ops == &amfs_link_ops || fs_ops == &ufs_ops)
-	  mf->mf_flags |= MFF_RSTKEEP;
-	if (fs_ops->fs_init) {
-	  /*
-	   * Don't care whether this worked since
-	   * it is checked again when the fs is
-	   * inherited.
-	   */
-	  (void) (*fs_ops->fs_init) (mf);
+      if (old_ports[i] == 0) {
+	int soNFS;
+	SVCXPRT *nfsxprt;
+	if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_program_2) != 0) {
+	  plog(XLOG_WARNING, "Can't bind to port %u", port);
+	  goto give_up;
 	}
-	plog(XLOG_INFO, "%s restarted fstype %s on %s",
-	     me->mnt_fsname, fs_ops->fs_type, me->mnt_dir);
-      } else {
-	/* Something strange happened - two mounts at the same place! */
-	free_mntfs(mf);
+	old_ports[i] = nfs_port = port;
       }
-      /*
-       * Clean up mo
-       */
-      if (mo.opt_rhost)
-	XFREE(mo.opt_rhost);
-      if (mo.opt_rfs)
-	XFREE(mo.opt_rfs);
     }
-  }
+    err = 0;
 
-  /*
-   * Free the mount list
-   */
+  give_up:
+    if (err) {
+      plog(XLOG_WARNING, "Can't restart %s, leaving it alone", me->mnt_dir);
+      fs_ops = &amfs_link_ops;
+    } else {
+      fs_ops = &amfs_toplvl_ops;
+    }
+
+    restart_fake_mntfs(me, fs_ops);
+  } /* end of "for (mlp" */
+
+  /* free the mount list */
   free_mntlist(ml);
 }
diff --git a/contrib/amd/amd/rpc_fwd.c b/contrib/amd/amd/rpc_fwd.c
index 5a74f3b..b3c8be4 100644
--- a/contrib/amd/amd/rpc_fwd.c
+++ b/contrib/amd/amd/rpc_fwd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: rpc_fwd.c,v 1.2 1999/01/10 21:53:52 ezk Exp $
+ * File: am-utils/amd/rpc_fwd.c
  *
  */
 
@@ -58,7 +57,7 @@
  * is no need to convert to and from network byte ordering.
  */
 
-#define	XID_ALLOC(struct )	(xid++)
+#define	XID_ALLOC()		(xid++)
 #define	MAX_PACKET_SIZE	8192	/* Maximum UDP packet size */
 
 /*
@@ -75,7 +74,7 @@ struct rpc_forward {
   time_t rf_ttl;		/* Time to live */
   u_int rf_xid;			/* Packet id */
   u_int rf_oldid;		/* Original packet id */
-  fwd_fun rf_fwd;		/* Forwarding function */
+  fwd_fun *rf_fwd;		/* Forwarding function */
   voidp rf_ptr;
   struct sockaddr_in rf_sin;
 };
@@ -94,7 +93,7 @@ static u_int xid;
 static rpc_forward *
 fwd_alloc(void)
 {
-  time_t now = clocktime();
+  time_t now = clocktime(NULL);
   rpc_forward *p = 0, *p2;
 
   /*
@@ -117,9 +116,7 @@ fwd_alloc(void)
      * Call forwarding function to say that
      * this message was junked.
      */
-#ifdef DEBUG
     dlog("Re-using packet forwarding slot - id %#x", p->rf_xid);
-#endif /* DEBUG */
     if (p->rf_fwd)
       (*p->rf_fwd) (0, 0, 0, &p->rf_sin, p->rf_ptr, FALSE);
     rem_que(&p->rf_q);
@@ -187,7 +184,7 @@ fwd_init(void)
    * Some things we talk to require a priv port - so make one here
    */
   if (bind_resv_port(fwd_sock, (u_short *) 0) < 0)
-    plog(XLOG_ERROR, "can't bind privileged port");
+    plog(XLOG_ERROR, "can't bind privileged port (rpc_fwd)");
 
   if (fcntl(fwd_sock, F_SETFL, FNDELAY) < 0
 #ifdef FIONBIO
@@ -228,7 +225,7 @@ fwd_locate(u_int id)
  * different address.
  */
 int
-fwd_packet(int type_id, voidp pkt, int len, struct sockaddr_in *fwdto, struct sockaddr_in *replyto, voidp i, fwd_fun cb)
+fwd_packet(int type_id, char *pkt, int len, struct sockaddr_in *fwdto, struct sockaddr_in *replyto, opaque_t cb_arg, fwd_fun cb)
 {
   rpc_forward *p;
   u_int *pkt_int;
@@ -247,36 +244,33 @@ fwd_packet(int type_id, voidp pkt, int len, struct sockaddr_in *fwdto, struct so
    * Otherwise make sure the type_id is
    * fully qualified by allocating an id here.
    */
-#ifdef DEBUG
   switch (type_id & RPC_XID_MASK) {
   case RPC_XID_PORTMAP:
-    dlog("Sending PORTMAP request");
+    dlog("Sending PORTMAP request %#x", type_id);
     break;
   case RPC_XID_MOUNTD:
     dlog("Sending MOUNTD request %#x", type_id);
     break;
   case RPC_XID_NFSPING:
-    dlog("Sending NFS ping");
+    dlog("Sending NFS ping %#x", type_id);
+    break;
+  case RPC_XID_WEBNFS:
+    dlog("Sending WebNFS lookup %#x", type_id);
     break;
   default:
-    dlog("UNKNOWN RPC XID");
+    dlog("UNKNOWN RPC XID %#x", type_id);
     break;
   }
-#endif /* DEBUG */
 
   if (type_id & ~RPC_XID_MASK) {
     p = fwd_locate(type_id);
     if (p) {
-#ifdef DEBUG
       dlog("Discarding earlier rpc fwd handle");
-#endif /* DEBUG */
       fwd_free(p);
     }
   } else {
-#ifdef DEBUG
     dlog("Allocating a new xid...");
-#endif /* DEBUG */
-    type_id = MK_RPC_XID(type_id, XID_ALLOC(struct ));
+    type_id = MK_RPC_XID(type_id, XID_ALLOC());
   }
 
   p = fwd_alloc();
@@ -290,12 +284,13 @@ fwd_packet(int type_id, voidp pkt, int len, struct sockaddr_in *fwdto, struct so
   /*
    * Get the original packet id
    */
-  p->rf_oldid = *pkt_int;
+  p->rf_oldid = ntohl(*pkt_int);
 
   /*
    * Replace with newly allocated id
    */
-  p->rf_xid = *pkt_int = type_id;
+  p->rf_xid = type_id;
+  *pkt_int = htonl(type_id);
 
   /*
    * The sendto may fail if, for example, the route
@@ -307,9 +302,9 @@ fwd_packet(int type_id, voidp pkt, int len, struct sockaddr_in *fwdto, struct so
   {
     char dq[20];
     if (p && fwdto)
-      dlog("Sending packet id %#x to %s.%d",
+      dlog("Sending packet id %#x to %s:%d",
 	   p->rf_xid,
-	   inet_dquad(dq, fwdto->sin_addr.s_addr),
+	   inet_dquad(dq, sizeof(dq), fwdto->sin_addr.s_addr),
 	   ntohs(fwdto->sin_port));
   }
 #endif /* DEBUG */
@@ -349,7 +344,7 @@ out:
     p->rf_sin = *replyto;
   else
     memset((voidp) &p->rf_sin, 0, sizeof(p->rf_sin));
-  p->rf_ptr = i;
+  p->rf_ptr = cb_arg;
 
   return error;
 }
@@ -364,6 +359,7 @@ fwd_reply(void)
   int len;
   u_int pkt[MAX_PACKET_SIZE / sizeof(u_int) + 1];
   u_int *pkt_int;
+  u_int pkt_xid;
   int rc;
   rpc_forward *p;
   struct sockaddr_in src_addr;
@@ -396,6 +392,12 @@ again:
     rc = ud.udata.len;
   else {
     plog(XLOG_ERROR,"fwd_reply failed: t_errno=%d, errno=%d, flags=%d",t_errno,errno, flags);
+    /*
+     * Clear error indication, otherwise the error condition persists and
+     * amd gets into an infinite loop.
+     */
+    if (t_errno == TLOOK)
+      t_rcvuderr(fwd_sock, NULL);
   }
 #else /* not HAVE_TRANSPORT_TYPE_TLI */
   rc = recvfrom(fwd_sock,
@@ -428,29 +430,29 @@ again:
    * Find packet reference
    */
   pkt_int = (u_int *) pkt;
+  pkt_xid = ntohl(*pkt_int);
 
-#ifdef DEBUG
-  switch (*pkt_int & RPC_XID_MASK) {
+  switch (pkt_xid & RPC_XID_MASK) {
   case RPC_XID_PORTMAP:
-    dlog("Receiving PORTMAP reply");
+    dlog("Receiving PORTMAP reply %#x", pkt_xid);
     break;
   case RPC_XID_MOUNTD:
-    dlog("Receiving MOUNTD reply %#x", *pkt_int);
+    dlog("Receiving MOUNTD reply %#x", pkt_xid);
     break;
   case RPC_XID_NFSPING:
-    dlog("Receiving NFS ping %#x", *pkt_int);
+    dlog("Receiving NFS ping %#x", pkt_xid);
+    break;
+  case RPC_XID_WEBNFS:
+    dlog("Receiving WebNFS lookup %#x", pkt_xid);
     break;
   default:
-    dlog("UNKNOWN RPC XID");
+    dlog("UNKNOWN RPC XID %#x", pkt_xid);
     break;
   }
-#endif /* DEBUG */
 
-  p = fwd_locate(*pkt_int);
+  p = fwd_locate(pkt_xid);
   if (!p) {
-#ifdef DEBUG
-    dlog("Can't forward reply id %#x", *pkt_int);
-#endif /* DEBUG */
+    dlog("Can't forward reply id %#x", pkt_xid);
     goto out;
   }
 
@@ -459,7 +461,7 @@ again:
      * Put the original message id back
      * into the packet.
      */
-    *pkt_int = p->rf_oldid;
+    *pkt_int = htonl(p->rf_oldid);
 
     /*
      * Call forwarding function
diff --git a/contrib/amd/amd/sched.c b/contrib/amd/amd/sched.c
index e5cf679..8efe57a 100644
--- a/contrib/amd/amd/sched.c
+++ b/contrib/amd/amd/sched.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: sched.c,v 1.3 1999/01/13 23:31:01 ezk Exp $
+ * File: am-utils/amd/sched.c
  *
  */
 
@@ -56,12 +55,12 @@
 typedef struct pjob pjob;
 
 struct pjob {
-  qelem hdr;			/* Linked list */
-  int pid;			/* Process ID of job */
-  cb_fun cb_fun;		/* Callback function */
-  voidp cb_closure;		/* Closure for callback */
+  qelem hdr;		/* Linked list */
+  int pid;		/* Process ID of job */
+  cb_fun *cb_fun;	/* Callback function */
+  opaque_t cb_arg;	/* Argument for callback */
   int w;		/* everyone these days uses int, not a "union wait" */
-  voidp wchan;			/* Wait channel */
+  wchan_t wchan;	/* Wait channel */
 };
 
 /* globals */
@@ -94,12 +93,12 @@ rem_que(qelem *elem)
 
 
 static pjob *
-sched_job(cb_fun cf, voidp ca)
+sched_job(cb_fun *cf, opaque_t ca)
 {
   pjob *p = ALLOC(struct pjob);
 
   p->cb_fun = cf;
-  p->cb_closure = ca;
+  p->cb_arg = ca;
 
   /*
    * Now place on wait queue
@@ -115,7 +114,7 @@ sched_job(cb_fun cf, voidp ca)
  * cf: Continuation function (ca is its arguments)
  */
 void
-run_task(task_fun tf, voidp ta, cb_fun cf, voidp ca)
+run_task(task_fun *tf, opaque_t ta, cb_fun *cf, opaque_t ca)
 {
   pjob *p = sched_job(cf, ca);
 #ifdef HAVE_SIGACTION
@@ -124,7 +123,7 @@ run_task(task_fun tf, voidp ta, cb_fun cf, voidp ca)
   int mask;
 #endif /* not HAVE_SIGACTION */
 
-  p->wchan = (voidp) p;
+  p->wchan = (wchan_t) p;
 
 #ifdef HAVE_SIGACTION
   sigemptyset(&new);		/* initialize signal set we wish to block */
@@ -143,7 +142,7 @@ run_task(task_fun tf, voidp ta, cb_fun cf, voidp ca)
     return;
   }
 
-  /* child code runs here, parent have returned to caller */
+  /* child code runs here, parent has returned to caller */
 
   exit((*tf) (ta));
   /* firewall... */
@@ -155,19 +154,17 @@ run_task(task_fun tf, voidp ta, cb_fun cf, voidp ca)
  * Schedule a task to be run when woken up
  */
 void
-sched_task(cb_fun cf, voidp ca, voidp wchan)
+sched_task(cb_fun *cf, opaque_t ca, wchan_t wchan)
 {
   /*
    * Allocate a new task
    */
   pjob *p = sched_job(cf, ca);
 
-#ifdef DEBUG
-  dlog("SLEEP on %#lx", (unsigned long) wchan);
-#endif /* DEBUG */
+  dlog("SLEEP on %p", wchan);
   p->wchan = wchan;
   p->pid = 0;
-  memset((voidp) &p->w, 0, sizeof(p->w));
+  p->w = 0;			/* was memset (when ->w was union) */
 }
 
 
@@ -181,7 +178,7 @@ wakeupjob(pjob *p)
 
 
 void
-wakeup(voidp wchan)
+wakeup(wchan_t wchan)
 {
   pjob *p, *p2;
 
@@ -189,7 +186,7 @@ wakeup(voidp wchan)
     return;
 
   /*
-   * Can't user ITER() here because
+   * Can't use ITER() here because
    * wakeupjob() juggles the list.
    */
   for (p = AM_FIRST(pjob, &proc_wait_list);
@@ -203,9 +200,20 @@ wakeup(voidp wchan)
 
 
 void
-wakeup_task(int rc, int term, voidp cl)
+wakeup_task(int rc, int term, wchan_t wchan)
 {
-  wakeup(cl);
+  wakeup(wchan);
+}
+
+
+wchan_t
+get_mntfs_wchan(mntfs *mf)
+{
+  if (mf &&
+      mf->mf_ops &&
+      mf->mf_ops->get_wchan)
+    return mf->mf_ops->get_wchan(mf);
+  return mf;
 }
 
 
@@ -219,7 +227,7 @@ do_task_notify(void)
   /*
    * Keep taking the first item off the list and processing it.
    *
-   * Done this way because the the callback can, quite reasonably,
+   * Done this way because the callback can, quite reasonably,
    * queue a new task, so no local reference into the list can be
    * held here.
    */
@@ -236,9 +244,9 @@ do_task_notify(void)
      */
     if (p->cb_fun) {
       /* these two trigraphs will ensure compatibility with strict POSIX.1 */
-      (*p->cb_fun) (WIFEXITED(p->w)   ? WEXITSTATUS(p->w) : 0,
-		    WIFSIGNALED(p->w) ? WTERMSIG(p->w)	  : 0,
-		    p->cb_closure);
+      p->cb_fun(WIFEXITED(p->w)   ? WEXITSTATUS(p->w) : 0,
+		WIFSIGNALED(p->w) ? WTERMSIG(p->w)    : 0,
+		p->cb_arg);
     }
     XFREE(p);
   }
@@ -261,11 +269,9 @@ sigchld(int sig)
     if (WIFSIGNALED(w))
       plog(XLOG_ERROR, "Process %d exited with signal %d",
 	   pid, WTERMSIG(w));
-#ifdef DEBUG
     else
       dlog("Process %d exited with status %d",
 	   pid, WEXITSTATUS(w));
-#endif /* DEBUG */
 
     for (p = AM_FIRST(pjob, &proc_wait_list);
 	 p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
@@ -277,18 +283,16 @@ sigchld(int sig)
       }
     } /* end of for loop */
 
-#ifdef DEBUG
-    if (!p)
+    if (p == HEAD(pjob, &proc_wait_list))
       dlog("can't locate task block for pid %d", pid);
-#endif /* DEBUG */
 
     /*
      * Must count down children inside the while loop, otherwise we won't
-     * count them all, and NumChild (and later backoff) will be set
+     * count them all, and NumChildren (and later backoff) will be set
      * incorrectly. SH/RUNIT 940519.
      */
-    if (--NumChild < 0)
-      NumChild = 0;
+    if (--NumChildren < 0)
+      NumChildren = 0;
   } /* end of "while wait..." loop */
 
 #ifdef REINSTALL_SIGNAL_HANDLER
diff --git a/contrib/amd/amd/srvr_amfs_auto.c b/contrib/amd/amd/srvr_amfs_auto.c
index a8ddd17..4742cf6 100644
--- a/contrib/amd/amd/srvr_amfs_auto.c
+++ b/contrib/amd/amd/srvr_amfs_auto.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: srvr_amfs_auto.c,v 1.2 1999/01/10 21:53:53 ezk Exp $
+ * File: am-utils/amd/srvr_amfs_auto.c
  *
  */
 
@@ -53,9 +52,9 @@
 #include <amd.h>
 
 /* globals */
-qelem amfs_auto_srvr_list = {&amfs_auto_srvr_list, &amfs_auto_srvr_list};
 
 /* statics */
+static qelem amfs_auto_srvr_list = {&amfs_auto_srvr_list, &amfs_auto_srvr_list};
 static fserver *localhost;
 
 
@@ -63,7 +62,7 @@ static fserver *localhost;
  * Find an nfs server for the local host
  */
 fserver *
-find_amfs_auto_srvr(mntfs *mf)
+amfs_generic_find_srvr(mntfs *mf)
 {
   fserver *fs = localhost;
 
@@ -73,8 +72,8 @@ find_amfs_auto_srvr(mntfs *mf)
     fs->fs_host = strdup("localhost");
     fs->fs_ip = 0;
     fs->fs_cid = 0;
-    fs->fs_pinger = 0;
-    fs->fs_flags = FSF_VALID;
+    fs->fs_pinger = AM_PINGER;
+    fs->fs_flags = FSF_VALID | FSF_PING_UNINIT;
     fs->fs_type = "local";
     fs->fs_private = 0;
     fs->fs_prfree = 0;
@@ -119,9 +118,7 @@ timeout_srvr(voidp v)
    * we are free to remove this node
    */
   if (fs->fs_refc == 0) {
-#ifdef DEBUG
     dlog("Deleting file server %s", fs->fs_host);
-#endif /* DEBUG */
     if (fs->fs_flags & FSF_WANT)
       wakeup_srvr(fs);
 
@@ -167,11 +164,9 @@ free_srvr(fserver *fs)
      * removed in AM_TTL seconds if no
      * other mntfs is referencing it.
      */
-    int ttl = (fs->fs_flags & (FSF_DOWN | FSF_ERROR)) ? 19 : AM_TTL;
+    int ttl = (FSRV_ERROR(fs) || FSRV_ISDOWN(fs)) ? 19 : AM_TTL;
 
-#ifdef DEBUG
     dlog("Last hard reference to file server %s - will timeout in %ds", fs->fs_host, ttl);
-#endif /* DEBUG */
     if (fs->fs_cid) {
       untimeout(fs->fs_cid);
       /*
@@ -208,7 +203,8 @@ dup_srvr(fserver *fs)
 /*
  * Log state change
  */
-void srvrlog(fserver *fs, char *state)
+void
+srvrlog(fserver *fs, char *state)
 {
-  plog(XLOG_INFO, "file server %s type %s %s", fs->fs_host, fs->fs_type, state);
+  plog(XLOG_INFO, "file server %s, type %s, state %s", fs->fs_host, fs->fs_type, state);
 }
diff --git a/contrib/amd/amd/srvr_nfs.c b/contrib/amd/amd/srvr_nfs.c
index 93b4c8e..0c74a65 100644
--- a/contrib/amd/amd/srvr_nfs.c
+++ b/contrib/amd/amd/srvr_nfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: srvr_nfs.c,v 1.5 1999/09/08 23:36:39 ezk Exp $
- * $FreeBSD: src/contrib/amd/amd/srvr_nfs.c,v 1.4 1999/09/15 05:45:13 obrien Exp $
- * $DragonFly: src/contrib/amd/amd/srvr_nfs.c,v 1.2 2003/06/17 04:23:56 dillon Exp $
+ * File: am-utils/amd/srvr_nfs.c
  *
  */
 
@@ -74,8 +71,6 @@
  */
 #endif /* (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME */
 
-#define	NPXID_ALLOC(struct )	(++np_xid)
-
 /* structures and typedefs */
 typedef struct nfs_private {
   u_short np_mountd;		/* Mount daemon port number */
@@ -90,12 +85,27 @@ typedef struct nfs_private {
 qelem nfs_srvr_list = {&nfs_srvr_list, &nfs_srvr_list};
 
 /* statics */
-static int np_xid;		/* For NFS pings */
-static int ping_len;
-static char ping_buf[sizeof(struct rpc_msg) + 32];
+static int global_xid;		/* For NFS pings */
+#define	XID_ALLOC()		(++global_xid)
+
+#ifdef HAVE_FS_NFS3
+# define NUM_NFS_VERS 2
+#else  /* not HAVE_FS_NFS3 */
+# define NUM_NFS_VERS 1
+#endif /* not HAVE_FS_NFS3 */
+static int ping_len[NUM_NFS_VERS];
+static char ping_buf[NUM_NFS_VERS][sizeof(struct rpc_msg) + 32];
 
 #if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
-/* protocols we know about, in order of preference */
+/*
+ * Protocols we know about, in order of preference.
+ *
+ * Note that Solaris 8 and newer NetBSD systems are switching to UDP first,
+ * so this order may have to be adjusted for Amd in the future once more
+ * vendors make that change. -Erez 11/24/2000
+ *
+ * Or we might simply make this is a platform-specific order. -Ion 09/13/2003
+ */
 static char *protocols[] = { "tcp", "udp", NULL };
 #endif /* defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
 
@@ -103,20 +113,21 @@ static char *protocols[] = { "tcp", "udp", NULL };
 static void nfs_keepalive(voidp);
 
 
-
 /*
- * Flush any cached data
+ * Flush cached data for an fserver (or for all, if fs==NULL)
  */
 void
-flush_srvr_nfs_cache(void)
+flush_srvr_nfs_cache(fserver *fs)
 {
-  fserver *fs = 0;
+  fserver *fs2 = NULL;
 
-  ITER(fs, fserver, &nfs_srvr_list) {
-    nfs_private *np = (nfs_private *) fs->fs_private;
-    if (np) {
-      np->np_mountd_inval = TRUE;
-      np->np_error = -1;
+  ITER(fs2, fserver, &nfs_srvr_list) {
+    if (fs == NULL || fs == fs2) {
+      nfs_private *np = (nfs_private *) fs2->fs_private;
+      if (np) {
+	np->np_mountd_inval = TRUE;
+	np->np_error = -1;
+      }
     }
   }
 }
@@ -126,7 +137,7 @@ flush_srvr_nfs_cache(void)
  * Startup the NFS ping for a particular version.
  */
 static void
-start_ping(u_long nfs_version)
+create_ping_payload(u_long nfs_version)
 {
   XDR ping_xdr;
   struct rpc_msg ping_msg;
@@ -136,16 +147,16 @@ start_ping(u_long nfs_version)
    */
   if (nfs_version == 0) {
     nfs_version = NFS_VERSION;
-    plog(XLOG_WARNING, "start_ping: nfs_version = 0 fixed");
-  }
-  plog(XLOG_INFO, "start_ping: nfs_version: %d", (int) nfs_version);
+    plog(XLOG_WARNING, "create_ping_payload: nfs_version = 0, changed to 2");
+  } else
+    plog(XLOG_INFO, "create_ping_payload: nfs_version: %d", (int) nfs_version);
 
   rpc_msg_init(&ping_msg, NFS_PROGRAM, nfs_version, NFSPROC_NULL);
 
   /*
    * Create an XDR endpoint
    */
-  xdrmem_create(&ping_xdr, ping_buf, sizeof(ping_buf), XDR_ENCODE);
+  xdrmem_create(&ping_xdr, ping_buf[nfs_version - NFS_VERSION], sizeof(ping_buf[0]), XDR_ENCODE);
 
   /*
    * Create the NFS ping message
@@ -157,7 +168,7 @@ start_ping(u_long nfs_version)
   /*
    * Find out how long it is
    */
-  ping_len = xdr_getpos(&ping_xdr);
+  ping_len[nfs_version - NFS_VERSION] = xdr_getpos(&ping_xdr);
 
   /*
    * Destroy the XDR endpoint - we don't need it anymore
@@ -170,7 +181,7 @@ start_ping(u_long nfs_version)
  * Called when a portmap reply arrives
  */
 static void
-got_portmap(voidp pkt, int len, struct sockaddr_in * sa, struct sockaddr_in * ia, voidp idv, int done)
+got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, voidp idv, int done)
 {
   fserver *fs2 = (fserver *) idv;
   fserver *fs = 0;
@@ -179,7 +190,7 @@ got_portmap(voidp pkt, int len, struct sockaddr_in * sa, struct sockaddr_in * ia
    * Find which fileserver we are talking about
    */
   ITER(fs, fserver, &nfs_srvr_list)
-  if (fs == fs2)
+    if (fs == fs2)
       break;
 
   if (fs == fs2) {
@@ -188,9 +199,7 @@ got_portmap(voidp pkt, int len, struct sockaddr_in * sa, struct sockaddr_in * ia
     nfs_private *np = (nfs_private *) fs->fs_private;
 
     if (!error && port) {
-#ifdef DEBUG
       dlog("got port (%d) for mountd on %s", (int) port, fs->fs_host);
-#endif /* DEBUG */
       /*
        * Grab the port number.  Portmap sends back
        * an u_long in native ordering, so it
@@ -201,10 +210,8 @@ got_portmap(voidp pkt, int len, struct sockaddr_in * sa, struct sockaddr_in * ia
       np->np_mountd_inval = FALSE;
       np->np_error = 0;
     } else {
-#ifdef DEBUG
       dlog("Error fetching port for mountd on %s", fs->fs_host);
       dlog("\t error=%d, port=%d", error, (int) port);
-#endif /* DEBUG */
       /*
        * Almost certainly no mountd running on remote host
        */
@@ -214,13 +221,9 @@ got_portmap(voidp pkt, int len, struct sockaddr_in * sa, struct sockaddr_in * ia
     if (fs->fs_flags & FSF_WANT)
       wakeup_srvr(fs);
   } else if (done) {
-#ifdef DEBUG
     dlog("Got portmap for old port request");
-#endif /* DEBUG */
   } else {
-#ifdef DEBUG
     dlog("portmap request timed out");
-#endif /* DEBUG */
   }
 }
 
@@ -229,7 +232,7 @@ got_portmap(voidp pkt, int len, struct sockaddr_in * sa, struct sockaddr_in * ia
  * Obtain portmap information
  */
 static int
-call_portmap(fserver *fs, AUTH * auth, u_long prog, u_long vers, u_long prot)
+call_portmap(fserver *fs, AUTH *auth, u_long prog, u_long vers, u_long prot)
 {
   struct rpc_msg pmap_msg;
   int len;
@@ -254,7 +257,7 @@ call_portmap(fserver *fs, AUTH * auth, u_long prog, u_long vers, u_long prot)
     memset((voidp) &sin, 0, sizeof(sin));
     sin = *fs->fs_ip;
     sin.sin_port = htons(PMAPPORT);
-    error = fwd_packet(RPC_XID_PORTMAP, (voidp) iobuf, len,
+    error = fwd_packet(RPC_XID_PORTMAP, iobuf, len,
 		       &sin, &sin, (voidp) fs, got_portmap);
   } else {
     error = -len;
@@ -270,6 +273,12 @@ recompute_portmap(fserver *fs)
   int error;
   u_long mnt_version;
 
+  /*
+   * No portmap calls for pure WebNFS servers.
+   */
+  if (fs->fs_flags & FSF_WEBNFS)
+    return;
+
   if (nfs_auth)
     error = 0;
   else
@@ -284,10 +293,11 @@ recompute_portmap(fserver *fs)
   if (fs->fs_version == 0)
     plog(XLOG_WARNING, "recompute_portmap: nfs_version = 0 fixed");
 
-  plog(XLOG_INFO, "recompute_portmap: NFS version %d", (int) fs->fs_version);
+  plog(XLOG_INFO, "recompute_portmap: NFS version %d on %s",
+       (int) fs->fs_version, fs->fs_host);
 #ifdef HAVE_FS_NFS3
   if (fs->fs_version == NFS_VERSION3)
-    mnt_version = MOUNTVERS3;
+    mnt_version = AM_MOUNTVERS3;
   else
 #endif /* HAVE_FS_NFS3 */
     mnt_version = MOUNTVERS;
@@ -297,19 +307,61 @@ recompute_portmap(fserver *fs)
 }
 
 
+int
+get_mountd_port(fserver *fs, u_short *port, wchan_t wchan)
+{
+  int error = -1;
+  if (FSRV_ISDOWN(fs))
+    return EWOULDBLOCK;
+
+  if (FSRV_ISUP(fs)) {
+    nfs_private *np = (nfs_private *) fs->fs_private;
+    if (np->np_error == 0) {
+      *port = np->np_mountd;
+      error = 0;
+    } else {
+      error = np->np_error;
+    }
+    /*
+     * Now go get the port mapping again in case it changed.
+     * Note that it is used even if (np_mountd_inval)
+     * is True.  The flag is used simply as an
+     * indication that the mountd may be invalid, not
+     * that it is known to be invalid.
+     */
+    if (np->np_mountd_inval)
+      recompute_portmap(fs);
+    else
+      np->np_mountd_inval = TRUE;
+  }
+  if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
+    /*
+     * If a wait channel is supplied, and no
+     * error has yet occurred, then arrange
+     * that a wakeup is done on the wait channel,
+     * whenever a wakeup is done on this fs node.
+     * Wakeup's are done on the fs node whenever
+     * it changes state - thus causing control to
+     * come back here and new, better things to happen.
+     */
+    fs->fs_flags |= FSF_WANT;
+    sched_task(wakeup_task, wchan, (wchan_t) fs);
+  }
+  return error;
+}
+
+
 /*
  * This is called when we get a reply to an RPC ping.
  * The value of id was taken from the nfs_private
  * structure when the ping was transmitted.
  */
 static void
-nfs_pinged(voidp pkt, int len, struct sockaddr_in * sp, struct sockaddr_in * tsp, voidp idv, int done)
+nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp, voidp idv, int done)
 {
-  int xid = (long) idv;		/* for 64-bit archs */
+  int xid = (long) idv;		/* cast needed for 64-bit archs */
   fserver *fs;
-#ifdef DEBUG
   int found_map = 0;
-#endif /* DEBUG */
 
   if (!done)
     return;
@@ -332,19 +384,15 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in * sp, struct sockaddr_in * tsp
 	} else {
 	  if (np->np_ping > 1)
 	    srvrlog(fs, "ok");
-#ifdef DEBUG
 	  else
 	    srvrlog(fs, "starts up");
-#endif /* DEBUG */
 	  fs->fs_flags |= FSF_VALID;
 	}
 
 	map_flush_srvr(fs);
       } else {
 	if (fs->fs_flags & FSF_VALID) {
-#ifdef DEBUG
 	  dlog("file server %s type nfs is still up", fs->fs_host);
-#endif /* DEBUG */
 	} else {
 	  if (np->np_ping > 1)
 	    srvrlog(fs, "ok");
@@ -361,13 +409,13 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in * sp, struct sockaddr_in * tsp
       /*
        * Update ttl for this server
        */
-      np->np_ttl = clocktime() +
+      np->np_ttl = clocktime(NULL) +
 	(MAX_ALLOWED_PINGS - 1) * FAST_NFS_PING + fs->fs_pinger - 1;
 
       /*
        * New RPC xid...
        */
-      np->np_xid = NPXID_ALLOC(struct );
+      np->np_xid = XID_ALLOC();
 
       /*
        * Failed pings is zero...
@@ -380,17 +428,53 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in * sp, struct sockaddr_in * tsp
       if (np->np_mountd_inval)
 	recompute_portmap(fs);
 
-#ifdef DEBUG
       found_map++;
-#endif /* DEBUG */
       break;
     }
   }
 
-#ifdef DEBUG
   if (found_map == 0)
     dlog("Spurious ping packet");
-#endif /* DEBUG */
+}
+
+
+static void
+check_fs_addr_change(fserver *fs)
+{
+  struct hostent *hp = NULL;
+  struct in_addr ia;
+  char *old_ipaddr, *new_ipaddr;
+
+  hp = gethostbyname(fs->fs_host);
+  if (!hp ||
+      hp->h_addrtype != AF_INET ||
+      !STREQ((char *) hp->h_name, fs->fs_host) ||
+      memcmp((voidp) &fs->fs_ip->sin_addr,
+	     (voidp) hp->h_addr,
+	     sizeof(fs->fs_ip->sin_addr)) == 0)
+    return;
+  /* if got here: downed server changed IP address */
+  old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr));
+  memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr));
+  new_ipaddr = inet_ntoa(ia);	/* ntoa uses static buf */
+  plog(XLOG_WARNING, "EZK: down fileserver %s changed ip: %s -> %s",
+       fs->fs_host, old_ipaddr, new_ipaddr);
+  XFREE(old_ipaddr);
+  /* copy new IP addr */
+  memmove((voidp) &fs->fs_ip->sin_addr,
+	  (voidp) hp->h_addr,
+	  sizeof(fs->fs_ip->sin_addr));
+  /* XXX: do we need to un/set these flags? */
+  fs->fs_flags &= ~FSF_DOWN;
+  fs->fs_flags |= FSF_VALID | FSF_WANT;
+  map_flush_srvr(fs);		/* XXX: a race with flush_srvr_nfs_cache? */
+  flush_srvr_nfs_cache(fs);
+  fs->fs_flags |= FSF_FORCE_UNMOUNT;
+
+#if 0
+  flush_nfs_fhandle_cache(fs);	/* done in caller: nfs_keepalive_timeout */
+  /* XXX: need to purge nfs_private so that somehow it will get re-initialized? */
+#endif
 }
 
 
@@ -398,7 +482,7 @@ nfs_pinged(voidp pkt, int len, struct sockaddr_in * sp, struct sockaddr_in * tsp
  * Called when no ping-reply received
  */
 static void
-nfs_timed_out(voidp v)
+nfs_keepalive_timeout(voidp v)
 {
   fserver *fs = v;
   nfs_private *np = (nfs_private *) fs->fs_private;
@@ -407,21 +491,21 @@ nfs_timed_out(voidp v)
    * Another ping has failed
    */
   np->np_ping++;
+  if (np->np_ping > 1)
+    srvrlog(fs, "not responding");
 
   /*
    * Not known to be up any longer
    */
-  if (FSRV_ISUP(fs)) {
+  if (FSRV_ISUP(fs))
     fs->fs_flags &= ~FSF_VALID;
-    if (np->np_ping > 1)
-      srvrlog(fs, "not responding");
-  }
 
   /*
    * If ttl has expired then guess that it is dead
    */
-  if (np->np_ttl < clocktime()) {
+  if (np->np_ttl < clocktime(NULL)) {
     int oflags = fs->fs_flags;
+    dlog("ttl has expired");
     if ((fs->fs_flags & FSF_DOWN) == 0) {
       /*
        * Server was up, but is now down.
@@ -435,26 +519,33 @@ nfs_timed_out(voidp v)
        */
       flush_nfs_fhandle_cache(fs);
       np->np_error = -1;
+      check_fs_addr_change(fs); /* check if IP addr of fserver changed */
     } else {
       /*
        * Known to be down
        */
-#ifdef DEBUG
       if ((fs->fs_flags & FSF_VALID) == 0)
 	srvrlog(fs, "starts down");
-#endif /* DEBUG */
       fs->fs_flags |= FSF_VALID;
     }
     if (oflags != fs->fs_flags && (fs->fs_flags & FSF_WANT))
       wakeup_srvr(fs);
+    /*
+     * Reset failed ping count
+     */
+    np->np_ping = 0;
   } else {
-#ifdef DEBUG
     if (np->np_ping > 1)
       dlog("%d pings to %s failed - at most %d allowed", np->np_ping, fs->fs_host, MAX_ALLOWED_PINGS);
-#endif /* DEBUG */
   }
 
   /*
+   * New RPC xid, so any late responses to the previous ping
+   * get ignored...
+   */
+  np->np_xid = XID_ALLOC();
+
+  /*
    * Run keepalive again
    */
   nfs_keepalive(fs);
@@ -476,19 +567,19 @@ nfs_keepalive(voidp v)
    * Send an NFS ping to this node
    */
 
-  if (ping_len == 0)
-    start_ping(fs->fs_version);
+  if (ping_len[fs->fs_version - NFS_VERSION] == 0)
+    create_ping_payload(fs->fs_version);
 
   /*
    * Queue the packet...
    */
   error = fwd_packet(MK_RPC_XID(RPC_XID_NFSPING, np->np_xid),
-		     (voidp) ping_buf,
-		     ping_len,
+		     ping_buf[fs->fs_version - NFS_VERSION],
+		     ping_len[fs->fs_version - NFS_VERSION],
 		     fs->fs_ip,
 		     (struct sockaddr_in *) 0,
-		     (voidp) ((long) np->np_xid), /* for 64-bit archs */
-		     nfs_pinged);
+		     (voidp) ((long) np->np_xid), /* cast needed for 64-bit archs */
+		     nfs_keepalive_callback);
 
   /*
    * See if a hard error occurred
@@ -501,7 +592,7 @@ nfs_keepalive(voidp v)
     np->np_ping = MAX_ALLOWED_PINGS;	/* immediately down */
     np->np_ttl = (time_t) 0;
     /*
-     * This causes an immediate call to nfs_timed_out
+     * This causes an immediate call to nfs_keepalive_timeout
      * whenever the server was thought to be up.
      * See +++ below.
      */
@@ -509,15 +600,13 @@ nfs_keepalive(voidp v)
     break;
 
   case 0:
-#ifdef DEBUG
     dlog("Sent NFS ping to %s", fs->fs_host);
-#endif /* DEBUG */
     break;
   }
 
   /*
    * Back off the ping interval if we are not getting replies and
-   * the remote system is know to be down.
+   * the remote system is known to be down.
    */
   switch (fs->fs_flags & (FSF_DOWN | FSF_VALID)) {
   case FSF_VALID:		/* Up */
@@ -534,77 +623,46 @@ nfs_keepalive(voidp v)
     break;
   }
 
-#ifdef DEBUG
   dlog("NFS timeout in %d seconds", fstimeo);
-#endif /* DEBUG */
 
-  fs->fs_cid = timeout(fstimeo, nfs_timed_out, (voidp) fs);
+  fs->fs_cid = timeout(fstimeo, nfs_keepalive_timeout, (voidp) fs);
 }
 
 
-int
-nfs_srvr_port(fserver *fs, u_short * port, voidp wchan)
+static void
+start_nfs_pings(fserver *fs, int pingval)
 {
-  int error = -1;
-  if ((fs->fs_flags & FSF_VALID) == FSF_VALID) {
-    if ((fs->fs_flags & FSF_DOWN) == 0) {
-      nfs_private *np = (nfs_private *) fs->fs_private;
-      if (np->np_error == 0) {
-	*port = np->np_mountd;
-	error = 0;
-      } else {
-	error = np->np_error;
-      }
-      /*
-       * Now go get the port mapping again in case it changed.
-       * Note that it is used even if (np_mountd_inval)
-       * is True.  The flag is used simply as an
-       * indication that the mountd may be invalid, not
-       * that it is known to be invalid.
-       */
-      if (np->np_mountd_inval)
-	recompute_portmap(fs);
-      else
-	np->np_mountd_inval = TRUE;
-    } else {
-      error = EWOULDBLOCK;
-    }
-  }
-  if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
-    /*
-     * If a wait channel is supplied, and no
-     * error has yet occurred, then arrange
-     * that a wakeup is done on the wait channel,
-     * whenever a wakeup is done on this fs node.
-     * Wakeup's are done on the fs node whenever
-     * it changes state - thus causing control to
-     * come back here and new, better things to happen.
-     */
-    fs->fs_flags |= FSF_WANT;
-    sched_task(wakeup_task, wchan, (voidp) fs);
+  if (pingval == 0)	    /* could be because ping mnt option not found */
+    pingval = AM_PINGER;
+  /* if pings haven't been initalized, then init them for first time */
+  if (fs->fs_flags & FSF_PING_UNINIT) {
+    fs->fs_flags &= ~FSF_PING_UNINIT;
+    plog(XLOG_INFO, "initializing %s's pinger to %d sec", fs->fs_host, pingval);
+    goto do_pings;
   }
-  return error;
-}
 
+  if ((fs->fs_flags & FSF_PINGING)  &&  fs->fs_pinger == pingval) {
+    dlog("already running pings to %s", fs->fs_host);
+    return;
+  }
 
-static void
-start_nfs_pings(fserver *fs, int pingval)
-{
-  if (!(fs->fs_flags & FSF_PINGING)) {
-    fs->fs_flags |= FSF_PINGING;
-    if (fs->fs_cid)
-      untimeout(fs->fs_cid);
-    if (pingval < 0) {
-      srvrlog(fs, "wired up");
-      fs->fs_flags |= FSF_VALID;
-      fs->fs_flags &= ~FSF_DOWN;
-    } else {
-      nfs_keepalive(fs);
-    }
+  /* if got here, then we need to update the ping value */
+  plog(XLOG_INFO, "changing %s's ping value from %d%s to %d%s",
+       fs->fs_host,
+       fs->fs_pinger, (fs->fs_pinger < 0 ? " (off)" : ""),
+       pingval, (pingval < 0 ? " (off)" : ""));
+ do_pings:
+  fs->fs_pinger = pingval;
+
+  if (fs->fs_cid)
+    untimeout(fs->fs_cid);
+  if (pingval < 0) {
+    srvrlog(fs, "wired up (pings disabled)");
+    fs->fs_flags |= FSF_VALID;
+    fs->fs_flags &= ~FSF_DOWN;
   } else {
-#ifdef DEBUG
-    dlog("Already running pings to %s", fs->fs_host);
-#endif /* DEBUG */
+    fs->fs_flags |= FSF_PINGING;
+    nfs_keepalive(fs);
   }
 }
 
@@ -616,17 +674,18 @@ fserver *
 find_nfs_srvr(mntfs *mf)
 {
   char *host = mf->mf_fo->opt_rhost;
-  char *nfs_proto = NULL;
   fserver *fs;
   int pingval;
   mntent_t mnt;
   nfs_private *np;
-  struct hostent *hp = 0;
-  struct sockaddr_in *ip;
+  struct hostent *hp = NULL;
+  struct sockaddr_in *ip = NULL;
   u_long nfs_version = 0;	/* default is no version specified */
-#ifdef MNTTAB_OPT_PROTO
-  char *rfsname = mf->mf_fo->opt_rfs;
-#endif /* MNTTAB_OPT_PROTO */
+  u_long best_nfs_version = 0;
+  char *nfs_proto = NULL;	/* no IP protocol either */
+  int nfs_port = 0;
+  int nfs_port_opt = 0;
+  int fserver_is_down = 0;
 
   /*
    * Get ping interval from mount options.
@@ -636,44 +695,62 @@ find_nfs_srvr(mntfs *mf)
   mnt.mnt_opts = mf->mf_mopts;
   pingval = hasmntval(&mnt, "ping");
 
-  /*
-   * Get the NFS version from the mount options. This is used
-   * to decide the highest NFS version to try.
-   */
+  if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
+    /*
+     * the server granted us a filehandle, but we were unable to mount it.
+     * therefore, scale down to NFSv2/UDP and try again.
+     */
+    nfs_version = NFS_VERSION;
+    nfs_proto = "udp";
+    plog(XLOG_WARNING, "find_nfs_srvr: NFS mount failed, trying again with NFSv2/UDP");
+    mf->mf_flags &= ~MFF_NFS_SCALEDOWN;
+  } else {
+    /*
+     * Get the NFS version from the mount options. This is used
+     * to decide the highest NFS version to try.
+     */
 #ifdef MNTTAB_OPT_VERS
-  nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS);
+    nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS);
 #endif /* MNTTAB_OPT_VERS */
 
 #ifdef MNTTAB_OPT_PROTO
-  {
-    char *proto_opt = hasmntopt(&mnt, MNTTAB_OPT_PROTO);
-    if (proto_opt) {
-      char **p;
-
-      proto_opt += sizeof(MNTTAB_OPT_PROTO) - 1; /* skip the "proto" */
-
-      for (p = protocols; *p; p ++)
-	if (proto_opt[0] == '=' &&
-	    NSTREQ(&proto_opt[1], *p, strlen(*p))) {
-	  nfs_proto = *p;
-	  break;
-	}
-      if (*p == NULL)
-	plog(XLOG_WARNING, "ignoring unknown protocol option for %s:%s",
-	     host, rfsname);
+    {
+      char *proto_opt = hasmnteq(&mnt, MNTTAB_OPT_PROTO);
+      if (proto_opt) {
+	char **p;
+	for (p = protocols; *p; p++)
+	  if (NSTREQ(proto_opt, *p, strlen(*p))) {
+	    nfs_proto = *p;
+	    break;
+	  }
+	if (*p == NULL)
+	  plog(XLOG_WARNING, "ignoring unknown protocol option for %s:%s",
+	       host, mf->mf_fo->opt_rfs);
+      }
     }
-  }
 #endif /* MNTTAB_OPT_PROTO */
 
 #ifdef HAVE_NFS_NFSV2_H
-  /* allow overriding if nfsv2 option is specified in mount options */
-  if (hasmntopt(&mnt, "nfsv2")) {
-    nfs_version = (u_long) 2;	/* nullify any ``vers=X'' statements */
-    nfs_proto = "udp";		/* nullify any ``proto=tcp'' statements */
-    plog(XLOG_WARNING, "found compatiblity option \"nfsv2\": set options vers=2, proto=udp for host %s", host);
-  }
+    /* allow overriding if nfsv2 option is specified in mount options */
+    if (amu_hasmntopt(&mnt, "nfsv2")) {
+      nfs_version = NFS_VERSION;/* nullify any ``vers=X'' statements */
+      nfs_proto = "udp";	/* nullify any ``proto=tcp'' statements */
+      plog(XLOG_WARNING, "found compatibility option \"nfsv2\": set options vers=2,proto=udp for host %s", host);
+    }
 #endif /* HAVE_NFS_NFSV2_H */
 
+    /* check if we've globally overridden the NFS version/protocol */
+    if (gopt.nfs_vers) {
+      nfs_version = gopt.nfs_vers;
+      plog(XLOG_INFO, "find_nfs_srvr: force NFS version to %d",
+	   (int) nfs_version);
+    }
+    if (gopt.nfs_proto) {
+      nfs_proto = gopt.nfs_proto;
+      plog(XLOG_INFO, "find_nfs_srvr: force NFS protocol transport to %s", nfs_proto);
+    }
+  }
+
   /*
    * lookup host address and canonical name
    */
@@ -694,72 +771,148 @@ find_nfs_srvr(mntfs *mf)
     case AF_INET:
       ip = ALLOC(struct sockaddr_in);
       memset((voidp) ip, 0, sizeof(*ip));
+      /* as per POSIX, sin_len need not be set (used internally by kernel) */
       ip->sin_family = AF_INET;
       memmove((voidp) &ip->sin_addr, (voidp) hp->h_addr, sizeof(ip->sin_addr));
-
-      ip->sin_port = htons(NFS_PORT);
       break;
 
     default:
-      ip = 0;
-      break;
+      plog(XLOG_USER, "No IP address for host %s", host);
+      goto no_dns;
     }
   } else {
     plog(XLOG_USER, "Unknown host: %s", host);
-    ip = 0;
+    goto no_dns;
   }
 
   /*
-   * Get the NFS Version, and verify server is up. Probably no
-   * longer need to start server down below.
+   * This may not be the best way to do things, but it really doesn't make
+   * sense to query a file server which is marked as 'down' for any
+   * version/proto combination.
    */
-  if (ip) {
+  ITER(fs, fserver, &nfs_srvr_list) {
+    if (FSRV_ISDOWN(fs) &&
+	STREQ(host, fs->fs_host)) {
+      plog(XLOG_WARNING, "fileserver %s is already hung - not running NFS proto/version discovery", host);
+      fs->fs_refc++;
+      if (ip)
+	XFREE(ip);
+      return fs;
+    }
+  }
+
+  /*
+   * Get the NFS Version, and verify server is up.
+   * If the client only supports NFSv2, hardcode it but still try to
+   * contact the remote portmapper to see if the service is running.
+   */
+#ifndef HAVE_FS_NFS3
+  nfs_version = NFS_VERSION;
+  nfs_proto = "udp";
+  plog(XLOG_INFO, "The client supports only NFS(2,udp)");
+#endif /* not HAVE_FS_NFS3 */
+
+
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_PUBLIC)) {
+    /*
+     * Use WebNFS to obtain file handles.
+     */
+    mf->mf_flags |= MFF_WEBNFS;
+    plog(XLOG_INFO, "%s option used, NOT contacting the portmapper on %s",
+	 MNTTAB_OPT_PUBLIC, host);
+    /*
+     * Prefer NFSv3/tcp if the client supports it (cf. RFC 2054, 7).
+     */
+    if (!nfs_version) {
 #ifdef HAVE_FS_NFS3
+      nfs_version = NFS_VERSION3;
+#else /* not HAVE_FS_NFS3 */
+      nfs_version = NFS_VERSION;
+#endif /* not HAVE_FS_NFS3 */
+      plog(XLOG_INFO, "No NFS version specified, will use NFSv%d",
+	   (int) nfs_version);
+    }
+    if (!nfs_proto) {
+#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
+      nfs_proto = "tcp";
+#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
+      nfs_proto = "udp";
+#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
+      plog(XLOG_INFO, "No NFS protocol transport specified, will use %s",
+	   nfs_proto);
+    }
+  } else {
     /*
      * Find the best combination of NFS version and protocol.
      * When given a choice, use the highest available version,
      * and use TCP over UDP if available.
      */
-    if (nfs_proto)
-      nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto);
-    else {
-      int best_nfs_version = 0;
-      int proto_nfs_version;
-      char **p;
-
-      for (p = protocols; *p; p++) {
-	proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p);
-
-	if (proto_nfs_version > best_nfs_version) {
-	  best_nfs_version = proto_nfs_version;
-	  nfs_proto = *p;
+    if (check_pmap_up(host, ip)) {
+      if (nfs_proto) {
+	best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto);
+	nfs_port = ip->sin_port;
+      }
+#ifdef MNTTAB_OPT_PROTO
+      else {
+	u_int proto_nfs_version;
+	char **p;
+
+	for (p = protocols; *p; p++) {
+	  proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p);
+
+	  if (proto_nfs_version > best_nfs_version) {
+	    best_nfs_version = proto_nfs_version;
+	    nfs_proto = *p;
+	    nfs_port = ip->sin_port;
+	  }
 	}
       }
-      nfs_version = best_nfs_version;
+#endif /* MNTTAB_OPT_PROTO */
+    } else {
+      plog(XLOG_INFO, "portmapper service not running on %s", host);
     }
 
-    if (!nfs_version) {
+    /* use the portmapper results only nfs_version is not set yet */
+    if (!best_nfs_version) {
       /*
        * If the NFS server is down or does not support the portmapper call
        * (such as certain Novell NFS servers) we mark it as version 2 and we
-       * let the nfs code deal with the case that is down.  If when the
-       * server comes back up, it can support NFS V.3 and/or TCP, it will
+       * let the nfs code deal with the case when it is down.  If/when the
+       * server comes back up and it can support NFSv3 and/or TCP, it will
        * use those.
        */
-      nfs_version = NFS_VERSION;
-      nfs_proto = "udp";
+      if (nfs_version == 0) {
+	nfs_version = NFS_VERSION;
+	nfs_proto = "udp";
+      }
+      plog(XLOG_INFO, "NFS service not running on %s", host);
+      fserver_is_down = 1;
+    } else {
+      if (nfs_version == 0)
+	nfs_version = best_nfs_version;
+      plog(XLOG_INFO, "Using NFS version %d, protocol %s on host %s",
+	   (int) nfs_version, nfs_proto, host);
     }
-#else /* not HAVE_FS_NFS3 */
-    nfs_version = NFS_VERSION;
-#endif /* not HAVE_FS_NFS3 */
   }
 
-  if (!nfs_proto)
-    nfs_proto = "udp";
+  /*
+   * Determine the NFS port.
+   *
+   * A valid "port" mount option overrides anything else.
+   * If the port has been determined from the portmapper, use that.
+   * Default to NFS_PORT otherwise (cf. RFC 2054, 3).
+   */
+  nfs_port_opt = hasmntval(&mnt, MNTTAB_OPT_PORT);
+  if (nfs_port_opt > 0)
+    nfs_port = htons(nfs_port_opt);
+  if (!nfs_port)
+    nfs_port = htons(NFS_PORT);
 
-  plog(XLOG_INFO, "Using NFS version %d, protocol %s on host %s",
-       (int) nfs_version, nfs_proto, host);
+  dlog("find_nfs_srvr: using port %d for nfs on %s",
+       (int) ntohs(nfs_port), host);
+  ip->sin_port = nfs_port;
 
+no_dns:
   /*
    * Try to find an existing fs server structure for this host.
    * Note that differing versions or protocols have their own structures.
@@ -771,16 +924,46 @@ find_nfs_srvr(mntfs *mf)
  	nfs_version == fs->fs_version &&
 	STREQ(nfs_proto, fs->fs_proto)) {
       /*
-       * following if statement from Mike Mitchell
-       * <mcm@unx.sas.com>
-       * Initialize the ping data if we aren't pinging
-       * now.  The np_ttl and np_ping fields are
-       * especially important.
+       * fill in the IP address -- this is only needed
+       * if there is a chance an IP address will change
+       * between mounts.
+       * Mike Mitchell, mcm@unx.sas.com, 09/08/93
+       */
+      if (hp && fs->fs_ip &&
+	  memcmp((voidp) &fs->fs_ip->sin_addr,
+		 (voidp) hp->h_addr,
+		 sizeof(fs->fs_ip->sin_addr)) != 0) {
+	struct in_addr ia;
+	char *old_ipaddr, *new_ipaddr;
+	old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr));
+	memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr));
+	new_ipaddr = inet_ntoa(ia);	/* ntoa uses static buf */
+	plog(XLOG_WARNING, "fileserver %s changed ip: %s -> %s",
+	     fs->fs_host, old_ipaddr, new_ipaddr);
+	XFREE(old_ipaddr);
+	flush_nfs_fhandle_cache(fs);
+	memmove((voidp) &fs->fs_ip->sin_addr, (voidp) hp->h_addr, sizeof(fs->fs_ip->sin_addr));
+      }
+
+      /*
+       * If the new file systems doesn't use WebNFS, the nfs pings may
+       * try to contact the portmapper.
+       */
+      if (!(mf->mf_flags & MFF_WEBNFS))
+	fs->fs_flags &= ~FSF_WEBNFS;
+
+      /* check if pingval needs to be updated/set/reset */
+      start_nfs_pings(fs, pingval);
+
+      /*
+       * Following if statement from Mike Mitchell <mcm@unx.sas.com>
+       * Initialize the ping data if we aren't pinging now.  The np_ttl and
+       * np_ping fields are especially important.
        */
       if (!(fs->fs_flags & FSF_PINGING)) {
 	np = (nfs_private *) fs->fs_private;
 	np->np_mountd_inval = TRUE;
-	np->np_xid = NPXID_ALLOC(struct );
+	np->np_xid = XID_ALLOC();
 	np->np_error = -1;
 	np->np_ping = 0;
 	/*
@@ -788,18 +971,12 @@ find_nfs_srvr(mntfs *mf)
 	 * after MAX_ALLOWED_PINGS of the fast variety
 	 * have failed.
 	 */
-	np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime() - 1;
+	np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime(NULL) - 1;
+	start_nfs_pings(fs, pingval);
+	if (fserver_is_down)
+	  fs->fs_flags |= FSF_VALID | FSF_DOWN;
       }
-      /*
-       * fill in the IP address -- this is only needed
-       * if there is a chance an IP address will change
-       * between mounts.
-       * Mike Mitchell, mcm@unx.sas.com, 09/08/93
-       */
-      if (hp && fs->fs_ip)
-	memmove((voidp) &fs->fs_ip->sin_addr, (voidp) hp->h_addr, sizeof(fs->fs_ip->sin_addr));
 
-      start_nfs_pings(fs, pingval);
       fs->fs_refc++;
       if (ip)
 	XFREE(ip);
@@ -828,29 +1005,32 @@ find_nfs_srvr(mntfs *mf)
     mf->mf_flags |= MFF_ERROR;
     mf->mf_error = ENOENT;
   }
+  if (mf->mf_flags & MFF_WEBNFS)
+    fs->fs_flags |= FSF_WEBNFS;
   fs->fs_version = nfs_version;
   fs->fs_proto = nfs_proto;
   fs->fs_type = MNTTAB_TYPE_NFS;
   fs->fs_pinger = AM_PINGER;
+  fs->fs_flags |= FSF_PING_UNINIT; /* pinger hasn't been initialized */
   np = ALLOC(struct nfs_private);
   memset((voidp) np, 0, sizeof(*np));
   np->np_mountd_inval = TRUE;
-  np->np_xid = NPXID_ALLOC(struct );
+  np->np_xid = XID_ALLOC();
   np->np_error = -1;
 
   /*
    * Initially the server will be deemed dead after
    * MAX_ALLOWED_PINGS of the fast variety have failed.
    */
-  np->np_ttl = clocktime() + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1;
+  np->np_ttl = clocktime(NULL) + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1;
   fs->fs_private = (voidp) np;
   fs->fs_prfree = (void (*)(voidp)) free;
 
-  if (!(fs->fs_flags & FSF_ERROR)) {
-    /*
-     * Start of keepalive timer
-     */
+  if (!FSRV_ERROR(fs)) {
+    /* start of keepalive timer, first updating pingval */
     start_nfs_pings(fs, pingval);
+    if (fserver_is_down)
+      fs->fs_flags |= FSF_VALID | FSF_DOWN;
   }
 
   /*
diff --git a/contrib/amd/amq/amq.8 b/contrib/amd/amq/amq.8
index 7947944..4b8485c 100644
--- a/contrib/amd/amq/amq.8
+++ b/contrib/amd/amq/amq.8
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-1999 Erez Zadok
+.\" Copyright (c) 1997-2006 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.
@@ -38,178 +38,243 @@
 .\"
 .\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: amq.8,v 1.2 1999/01/10 21:53:58 ezk Exp $
-.\" $FreeBSD: src/contrib/amd/amq/amq.8,v 1.5.2.3 2001/08/16 10:53:40 ru Exp $
-.\" $DragonFly: src/contrib/amd/amq/amq.8,v 1.2 2003/06/17 04:23:57 dillon Exp $
+.\" $Id: amq.8,v 1.15.2.1 2006/01/02 18:48:24 ezk Exp $
+.\" $FreeBSD: src/contrib/amd/amq/amq.8,v 1.17 2012/11/17 01:48:41 svnexp Exp $
 .\"
-.Dd March 16, 1991
+.Dd January 2, 2006
 .Dt AMQ 8
 .Os
 .Sh NAME
 .Nm amq
 .Nd automounter query tool
 .Sh SYNOPSIS
-.Nm amq
-.Op Fl fmpsuvTU
+.Nm
+.Op Fl fmpsvwHTU
 .Op Fl h Ar hostname
 .Op Fl l Ar log_file
 .Op Fl x Ar log_options
 .Op Fl D Ar debug_options
-.Op Fl M Ar mountmap_entry
 .Op Fl P Ar program_number
-.Op Ar directory
-.Ar ...
+.Op Oo Fl u Oc Ar directory ...
 .Sh DESCRIPTION
-.Nm Amq
+The
+.Nm
+utility
 provides a simple way of determining the current state of the
 .Xr amd 8
 program.
 Communication is by
 .Tn RPC .
 Three modes of operation are supported by the current protocol.
-By default a list of mount points and auto-mounted filesystems
-is output.
-An alternative host can be specified using the
+By default
+a list of mount points and auto-mounted file systems is output.
+An
+alternative host can be specified using the
 .Fl h
 option.
 .Pp
-If directory names are given, as output by default,
-then per-filesystem information is displayed.
+If
+.Ar directory
+names are given, as output by default, then per file system
+information is displayed.
 .Sh OPTIONS
-.Bl -tag -width Ds
+.Bl -tag -width indent
 .It Fl f
-Request automounter to flush the internal caches.
+Ask the automounter to flush the internal caches and reload all the maps.
 .It Fl h Ar hostname
-Query alternate host
-.Ar hostname .
-By default the local host is used.  In an
+Specify an alternate host to query.
+By default the local host is used.
+In
+an
 .Tn HP-UX
-cluster, the root server is queried by default, since
-that is the system on which the automounter is normally run.
+cluster, the root server is queried by default, since that is the system on
+which the automounter is normally run.
 .It Fl l Ar log_file
-Tell amd to use
+Tell
+.Xr amd 8
+to use
 .Ar log_file
-as the log file name. 
-For security reasons, this must be the same log file which
-.Nm amd
-used when started.  This option is therefore only useful to 
+as the log file name.
+For security reasons, this must be the same log file
+which
+.Xr amd 8
+used when started.
+This option is therefore only useful to
 refresh
-.Nm amd Ns \'s
-open file handle on the log file, so that it can be rotated and compressed via
-daily cron jobs.
+.Nm amd Ns 's
+open file handle on the log file, so that it can be rotated
+and compressed via daily cron jobs.
 .It Fl m
-Request the automounter to provide a list of mounted filesystems,
-including the number of references to each filesystem and any error
-which occurred while mounting.
+Ask the automounter to provide a list of mounted file systems, including the
+number of references to each file system and any error which occurred while
+mounting.
 .It Fl p
 Return the process ID of the remote or locally running
-.Nm amd .  
-Useful when you need to send a signal to the local
-.Nm amd
-process, and would rather not have to search through the process table.  This
-option is used in the
+.Xr amd 8 .
+Useful when you
+need to send a signal to the local
+.Xr amd 8
+process, and would rather not have to
+search through the process table.
+This option is used in the
 .Pa ctl-amd
 script.
 .It Fl s
-Request the automounter to provide system-wide mount statistics.
+Ask the automounter to provide system-wide mount statistics.
 .It Fl u
-Request the automounter to unmount the named filesystems
-instead of providing information about them.  Unmounts are requested,
-not forced.  They merely cause the mounted filesystem to timeout,
-which will be picked up by
-.Nm amd Ns \'s
+Ask the automounter to unmount the file systems named in
+.Ar directory
+instead of providing
+information about them.
+Unmounts are requested, not forced.
+They merely
+cause the mounted file system to timeout, which will be picked up by
+.Nm amd Ns 's
 main scheduler thus causing the normal timeout action to be taken.
 .It Fl v
-Request the automounter to provide version information.  This is a subset
-of the information provided by
-.Nm amd Ns \'s Fl v
+Ask the automounter for its version information.
+This is a subset of the
+information output by
+.Xr amd 8 Ns 's
+.Fl v
 option.
+.It Fl w
+Translate a full pathname as returned by
+.Xr getcwd 3
+into a short
+.Xr amd 8
+pathname that goes through its mount points.
+This option requires that
+.Xr amd 8
+is running.
 .It Fl x Ar log_options
-Ask the automounter to use the logging options specified in 
+Ask the automounter to use the logging options specified in
 .Ar log_options
 from now on.
-.It Fl D Ar log_options
-Ask the automounter to use the debugging options specified in 
+.It Fl D Ar debug_options
+Ask the automounter to use the debugging options specified in
 .Ar debug_options
 from now on.
-.It Fl M
-Pass a mount map entry to 
-.Nm amd
-and wait for it to be evaluated, possibly causing a mount.
-This option is highly insecure.  
-By default,
-.Nm amd
-and 
-.Nm amq
-do not support it.
-It is necessary to configure
-.Nm am-utils
-with 
-.Ar --enable-amq-mount
-to enable this option.
+.It Fl H
+Display short usage message.
 .It Fl P Ar program_number
-Contact an alternate running 
-.Nm amd 
-that had registered itself on a different RPC
-.Ar program_number 
-and apply all other operations to that instance of the automounter.  
-This is useful when running multiple copies of 
-.Nm amd , 
-and need to manage each one separately.  
-If not specified, 
-.Nm amq
-will use the default program number for 
-.Nm amd ,
+Contact an alternate running
+.Xr amd 8
+that had registered itself on a different
+.Tn RPC
+.Ar program_number
+and apply all other operations to that instance of the automounter.
+This is
+useful when you run multiple copies of
+.Xr amd 8 ,
+and need to manage each
+one separately.
+If not specified,
+.Nm
+will use the default program number for
+.Xr amd 8 ,
 300019.
 For security reasons, the only alternate program numbers
-.Nm amd
+.Xr amd 8
 can use range from 300019 to 300029, inclusive.
 .It Fl T
 Contact
-.Nm amd
-using the TCP transport only.  
-Normally 
-.Nm amq
-will try TCP, and if that fails, will try UDP.
+.Xr amd 8
+using the TCP transport only.
+Normally
+.Nm
+will try TCP, and if that failed, will try UDP.
 .It Fl U
-Contact 
-.Nm amd
-using UDP (connectionless) transport only. 
+Contact
+.Xr amd 8
+using UDP (connectionless) transport only.
 Normally
-.Nm amq
-will try TCP, and if that fails, will try UDP.
+.Nm
+will try TCP, and if that failed, will try UDP.
 .El
 .Sh FILES
-.Bl -tag -width amq.x -compact
+.Bl -tag -width ".Pa amq.x" -compact
 .It Pa amq.x
 .Tn RPC
 protocol description.
 .El
 .Sh CAVEATS
-.Nm Amq
+The
+.Nm
+utility
 uses a Sun registered
 .Tn RPC
 program number (300019 decimal) which may not
 be in the
-.Pa /etc/rpc
+.Xr rpc 5
 database.
+.Pp
+If the TCP wrappers library is available, and the
+.Va use_tcpwrappers
+global
+.Xr amd.conf 5
+option is set to
+.Dq Li yes ,
+then
+.Xr amd 8
+will verify that the host running
+.Nm
+is authorized to connect.
+The
+.Dq Li amd
+service name must be used in the
+.Pa /etc/hosts.allow
+and
+.Pa /etc/hosts.deny
+files.
+For example, to allow only localhost to connect to
+.Xr amd 8 ,
+add this line to
+.Pa /etc/hosts.allow :
+.Pp
+.Dl "amd: localhost"
+.Pp
+and this line to
+.Pa /etc/hosts.deny :
+.Pp
+.Dl "amd: ALL"
 .Sh SEE ALSO
 .Xr amd.conf 5 ,
+.Xr hosts_access 5 ,
 .Xr amd 8
+.Pp
+.Dq am-utils
+.Xr info 1
+entry.
+.Rs
+.%A Erez Zadok
+.%B "Linux NFS and Automounter Administration"
+.%O ISBN 0-7821-2739-8
+.%I Sybex
+.%D 2001
+.Re
+.Pp
+.Pa http://www.am-utils.org/
+.Rs
+.%T Amd \- The 4.4 BSD Automounter
+.Re
+.Sh HISTORY
+The
+.Nm
+utility
+first appeared in
+.Bx 4.4 .
 .Sh AUTHORS
 .An Jan-Simon Pendry Aq jsp@doc.ic.ac.uk ,
 Department of Computing, Imperial College, London, UK.
 .Pp
-.An Erez Zadok Aq ezk@cs.columbia.edu ,
-Department of Computer Science, Columbia University, New York, USA.
+.An Erez Zadok Aq ezk@cs.sunysb.edu ,
+Computer Science Department, Stony Brook
+University, Stony Brook, New York, USA.
 .Pp
-.An Other authors and contributors to 
+Other authors and contributors to
 .Nm am-utils
 are listed in the
-.Nm AUTHORS 
+.Pa AUTHORS
 file distributed with
 .Nm am-utils .
-.Sh HISTORY
-.Nm Amq
-first appeared in
-.Bx 4.4 .
diff --git a/contrib/amd/amq/amq.c b/contrib/amd/amq/amq.c
index 4d90a93..2379b62 100644
--- a/contrib/amd/amq/amq.c
+++ b/contrib/amd/amq/amq.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amq.c,v 1.6 1999/09/08 23:36:40 ezk Exp $
- * $FreeBSD: src/contrib/amd/amq/amq.c,v 1.5 1999/09/15 05:45:14 obrien Exp $
- * $DragonFly: src/contrib/amd/amq/amq.c,v 1.3 2004/01/23 19:49:35 joerg Exp $
+ * File: am-utils/amq/amq.c
  *
  */
 
@@ -48,19 +45,6 @@
  * Automounter query tool
  */
 
-#ifndef lint
-char copyright[] = "\
-@(#)Copyright (c) 1997-1999 Erez Zadok\n\
-@(#)Copyright (c) 1990 Jan-Simon Pendry\n\
-@(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\
-@(#)Copyright (c) 1990 The Regents of the University of California.\n\
-@(#)All rights reserved.\n";
-#if __GNUC__ < 2
-static char rcsid[] = "$Id: amq.c,v 1.6 1999/09/08 23:36:40 ezk Exp $";
-static char sccsid[] = "%W% (Berkeley) %G%";
-#endif /* __GNUC__ < 2 */
-#endif /* not lint */
-
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif /* HAVE_CONFIG_H */
@@ -76,9 +60,9 @@ static int stats_flag;
 static int getvers_flag;
 static int amd_program_number = AMQ_PROGRAM;
 static int use_tcp_flag, use_udp_flag;
+static int getpwd_flag;
 static char *debug_opts;
 static char *amq_logfile;
-static char *mount_map;
 static char *xlog_optstr;
 static char localhost[] = "localhost";
 static char *def_server = localhost;
@@ -87,14 +71,6 @@ static char *def_server = localhost;
 extern int optind;
 extern char *optarg;
 
-/* forward declarations */
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-static CLIENT *get_secure_amd_client(char *host, struct timeval *tv, int *sock);
-static int amq_bind_resv_port(int td, u_short *pp);
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
-static int privsock(int ty);
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
-
 /* structures */
 enum show_opt {
   Full, Stats, Calc, Short, ShowDone
@@ -125,8 +101,8 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
 
   case Full:
     {
-      struct tm *tp = localtime((time_t *) &mt->mt_mounttime);
-      printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
+      struct tm *tp = localtime((time_t *) ((voidp) &mt->mt_mounttime));
+      printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%04d %02d:%02d:%02d\n",
 	     *dwid, *dwid,
 	     *mt->mt_directory ? mt->mt_directory : "/",	/* XXX */
 	     *twid, *twid,
@@ -142,16 +118,16 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
 	     mt->mt_readlink,
 	     mt->mt_statfs,
 
-	     tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
 	     tp->tm_mon + 1, tp->tm_mday,
+	     tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year,
 	     tp->tm_hour, tp->tm_min, tp->tm_sec);
     }
   break;
 
   case Stats:
     {
-      struct tm *tp = localtime((time_t *) &mt->mt_mounttime);
-      printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
+      struct tm *tp = localtime((time_t *) ((voidp) &mt->mt_mounttime));
+      printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%04d\n",
 	     *dwid, *dwid,
 	     *mt->mt_directory ? mt->mt_directory : "/",	/* XXX */
 
@@ -162,8 +138,8 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
 	     mt->mt_readlink,
 	     mt->mt_statfs,
 
-	     tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
 	     tp->tm_mon + 1, tp->tm_mday,
+	     tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year,
 	     tp->tm_hour, tp->tm_min, tp->tm_sec);
     }
   break;
@@ -186,6 +162,31 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
   }
 }
 
+
+/*
+ * Display a pwd data
+ */
+static void
+show_pwd(amq_mount_tree *mt, char *path, size_t l, int *flag)
+{
+  int len;
+
+  while (mt) {
+    len = strlen(mt->mt_mountpoint);
+    if (NSTREQ(path, mt->mt_mountpoint, len) &&
+	!STREQ(mt->mt_directory, mt->mt_mountpoint)) {
+      char buf[MAXPATHLEN+1];	/* must be same size as 'path' */
+      xstrlcpy(buf, mt->mt_directory, sizeof(buf));
+      xstrlcat(buf, &path[len], sizeof(buf));
+      xstrlcpy(path, buf, l);
+      *flag = 1;
+    }
+    show_pwd(mt->mt_next, path, l, flag);
+    mt = mt->mt_child;
+  }
+}
+
+
 /*
  * Display a mount tree.
  */
@@ -199,10 +200,11 @@ show_mt(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *pwid)
   }
 }
 
+
 static void
 show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twid)
 {
-  int i;
+  u_int i;
 
   switch (e) {
 
@@ -235,14 +237,7 @@ show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twi
 	       mi->mi_up > 0 ? "up" :
 	       mi->mi_up < 0 ? "starting" : "down");
 	if (mi->mi_error > 0) {
-	  if (mi->mi_error < sys_nerr)
-#ifdef HAVE_STRERROR
-	    printf(" (%s)", strerror(mi->mi_error));
-#else /* not HAVE_STRERROR */
-	    printf(" (%s)", sys_errlist[mi->mi_error]);
-#endif /* not HAVE_STRERROR */
-	  else
-	    printf(" (Error %d)", mi->mi_error);
+	  printf(" (%s)", strerror(mi->mi_error));
 	} else if (mi->mi_error < 0) {
 	  fputs(" (in progress)", stdout);
 	}
@@ -302,16 +297,11 @@ main(int argc, char *argv[])
   int errs = 0;
   char *server;
   struct sockaddr_in server_addr;
-  int s;	/* to pass the Amd security check, we must use a priv port */
   CLIENT *clnt = NULL;
   struct hostent *hp;
   int nodefault = 0;
   struct timeval tv;
   char *progname = NULL;
-#ifndef HAVE_TRANSPORT_TYPE_TLI
-  enum clnt_stat cs;
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
-
 
   /*
    * Compute program name
@@ -330,12 +320,12 @@ main(int argc, char *argv[])
   /*
    * Parse arguments
    */
-#ifdef ENABLE_AMQ_MOUNT
-  while ((opt_ch = getopt(argc, argv, "fh:l:msuvx:D:M:pP:TU")) != -1)
-#else /* not ENABLE_AMQ_MOUNT */
-  while ((opt_ch = getopt(argc, argv, "fh:l:msuvx:D:pP:TU")) != -1)
-#endif /* not ENABLE_AMQ_MOUNT */
+  while ((opt_ch = getopt(argc, argv, "Hfh:l:msuvx:D:pP:TUw")) != -1)
     switch (opt_ch) {
+    case 'H':
+      goto show_usage;
+      break;
+
     case 'f':
       flush_flag = 1;
       nodefault = 1;
@@ -385,13 +375,6 @@ main(int argc, char *argv[])
       nodefault = 1;
       break;
 
-#ifdef ENABLE_AMQ_MOUNT
-    case 'M':
-      mount_map = optarg;
-      nodefault = 1;
-      break;
-#endif /* ENABLE_AMQ_MOUNT */
-
     case 'P':
       amd_program_number = atoi(optarg);
       break;
@@ -404,6 +387,10 @@ main(int argc, char *argv[])
       use_udp_flag = 1;
       break;
 
+    case 'w':
+      getpwd_flag = 1;
+      break;
+
     default:
       errs = 1;
       break;
@@ -416,21 +403,15 @@ main(int argc, char *argv[])
   if (errs) {
   show_usage:
     fprintf(stderr, "\
-Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\
-\t[-l logfile|\"syslog\"] [-x log_flags] [-D dbg_opts]%s\n\
-\t[-P prognum] [-T] [-U]\n",
-	    am_get_progname(),
-#ifdef ENABLE_AMQ_MOUNT
-	    " [-M mapent]"
-#else /* not ENABLE_AMQ_MOUNT */
-	    ""
-#endif /* not ENABLE_AMQ_MOUNT */
+Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
+\t[-x log_options] [-D debug_options]\n\
+\t[-P program_number] [[-u] directory ...]\n",
+	    am_get_progname()
     );
     exit(1);
   }
 
 
-
   /* set use_udp and use_tcp flags both to on if none are defined */
   if (!use_tcp_flag && !use_udp_flag)
     use_tcp_flag = use_udp_flag = 1;
@@ -453,7 +434,8 @@ Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\
 	    am_get_progname(), server);
     exit(1);
   }
-  memset(&server_addr, 0, sizeof server_addr);
+  memset(&server_addr, 0, sizeof(server_addr));
+  /* as per POSIX, sin_len need not be set (used internally by kernel) */
   server_addr.sin_family = AF_INET;
   if (hp) {
     memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr,
@@ -469,9 +451,7 @@ Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\
   tv.tv_sec = 5;		/* 5 seconds for timeout or per retry */
   tv.tv_usec = 0;
 
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-  clnt = get_secure_amd_client(server, &tv, &s);
-  if (!clnt && use_tcp_flag)	/* try tcp first */
+  if (use_tcp_flag)	/* try tcp first */
     clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "tcp");
   if (!clnt && use_udp_flag) {	/* try udp next */
     clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "udp");
@@ -479,29 +459,6 @@ Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\
     if (clnt)
       clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tv);
   }
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
-
-  /* first check if remote portmapper is up */
-  cs = pmap_ping(&server_addr);
-  if (cs == RPC_TIMEDOUT) {
-    fprintf(stderr, "%s: failed to contact portmapper on host \"%s\". %s\n",
-	    am_get_progname(), server, clnt_sperrno(cs));
-    exit(1);
-  }
-
-  /* portmapper exists: get remote amd info from it */
-  if (!clnt && use_tcp_flag) {	/* try tcp first */
-    s = RPC_ANYSOCK;
-    clnt = clnttcp_create(&server_addr, amd_program_number,
-			  AMQ_VERSION, &s, 0, 0);
-  }
-  if (!clnt && use_udp_flag) {	/* try udp next */
-    /* XXX: do we need to close(s) ? */
-    s = privsock(SOCK_DGRAM);
-    clnt = clntudp_create(&server_addr, amd_program_number,
-			  AMQ_VERSION, tv, &s);
-  }
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
   if (!clnt) {
     fprintf(stderr, "%s: ", am_get_progname());
     clnt_pcreateerror(server);
@@ -577,6 +534,35 @@ Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\
   }
 
   /*
+   * getpwd info
+   */
+  if (getpwd_flag) {
+    char path[MAXPATHLEN+1];
+    char *wd = getcwd(path, MAXPATHLEN+1);
+    amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
+    amq_mount_tree_p mt;
+    u_int i;
+    int flag;
+
+    if (!wd) {
+      perror("getcwd");
+      exit(1);
+    }
+    for (i = 0; mlp && i < mlp->amq_mount_tree_list_len; i++) {
+      mt = mlp->amq_mount_tree_list_val[i];
+      while (1) {
+	flag = 0;
+	show_pwd(mt, path, sizeof(path), &flag);
+	if (!flag) {
+	  printf("%s\n", path);
+	  break;
+	}
+      }
+    }
+    exit(0);
+  }
+
+  /*
    * Mount info
    */
   if (minfo_flag) {
@@ -597,24 +583,6 @@ Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\
   }
 
   /*
-   * Mount map
-   */
-  if (mount_map) {
-    int *rc;
-    do {
-      rc = amqproc_mount_1(&mount_map, clnt);
-    } while (rc && *rc < 0);
-    if (!rc || *rc > 0) {
-      if (rc)
-	errno = *rc;
-      else
-	errno = ETIMEDOUT;
-      fprintf(stderr, "%s: could not start new ", am_get_progname());
-      perror("automount point");
-    }
-  }
-
-  /*
    * Get Version
    */
   if (getvers_flag) {
@@ -698,8 +666,9 @@ Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\
     if (mlp) {
       enum show_opt e = Calc;
       int mwid = 0, dwid = 0, pwid = 0;
+
       while (e != ShowDone) {
-	int i;
+	u_int i;
 	for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
 	  show_mt(mlp->amq_mount_tree_list_val[i],
 		  e, &mwid, &dwid, &pwid);
@@ -721,241 +690,3 @@ Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\
   exit(errs);
   return errs; /* should never reach here */
 }
-
-
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-
-/*
- * How to bind to reserved ports.
- * TLI handle (socket) and port version.
- */
-/* defined here so that it does not have to resolve it with libamu.a */
-static int
-amq_bind_resv_port(int td, u_short *pp)
-{
-  int rc = -1, port;
-  struct t_bind *treq, *tret;
-  struct sockaddr_in *sin;
-
-  treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
-  if (!treq) {
-    plog(XLOG_ERROR, "t_alloc 1");
-    return -1;
-  }
-  tret = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
-  if (!tret) {
-    t_free((char *) treq, T_BIND);
-    plog(XLOG_ERROR, "t_alloc 2");
-    return -1;
-  }
-  memset((char *) treq->addr.buf, 0, treq->addr.len);
-  sin = (struct sockaddr_in *) treq->addr.buf;
-  sin->sin_family = AF_INET;
-  treq->qlen = 0;
-  treq->addr.len = treq->addr.maxlen;
-  errno = EADDRINUSE;
-  port = IPPORT_RESERVED;
-
-  do {
-    --port;
-    sin->sin_port = htons(port);
-    rc = t_bind(td, treq, tret);
-    if (rc < 0) {
-    } else {
-      if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0)
-	break;
-      else
-	t_unbind(td);
-    }
-  } while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2);
-
-  if (pp) {
-    if (rc == 0)
-      *pp = port;
-    else
-      plog(XLOG_ERROR, "could not t_bind to any reserved port");
-  }
-  t_free((char *) tret, T_BIND);
-  t_free((char *) treq, T_BIND);
-  return rc;
-}
-
-
-/*
- * Create a secure rpc client attached to the amd daemon.
- */
-static CLIENT *
-get_secure_amd_client(char *host, struct timeval *tv, int *sock)
-{
-  CLIENT *client;
-  struct netbuf nb;
-  struct netconfig *nc, *pm_nc;
-  struct sockaddr_in sin;
-
-
-  nb.maxlen = sizeof(sin);
-  nb.buf = (char *) &sin;
-
-  /*
-   * Ensure that remote portmapper is alive
-   * (must use connectionless netconfig).
-   */
-  if ((pm_nc = getnetconfigent(NC_UDP)) != NULL) {
-    enum clnt_stat cs;
-
-    cs = rpcb_rmtcall(pm_nc,
-		      host,
-		      amd_program_number,
-		      AMQ_VERSION,
-		      AMQPROC_NULL,
-		      (XDRPROC_T_TYPE) xdr_void,
-		      NULL,
-		      (XDRPROC_T_TYPE) xdr_void,
-		      NULL,
-		      *tv,
-		      NULL);
-    if (cs == RPC_TIMEDOUT) {
-      fprintf(stderr, "%s: failed to contact portmapper on host \"%s\". %s\n",
-	      am_get_progname(), host, clnt_sperrno(cs));
-      exit(1);
-    }
-  }
-
-  /*
-   * First transport type to try: TCP
-   */
-  if (use_tcp_flag) {
-    /* Find amd address on TCP */
-    nc = getnetconfigent(NC_TCP);
-    if (!nc) {
-      fprintf(stderr, "getnetconfig for tcp failed: %s\n", nc_sperror());
-      goto tryudp;
-    }
-
-    if (!rpcb_getaddr(amd_program_number, AMQ_VERSION, nc, &nb, host)) {
-      /*
-       * don't print error messages here, since amd might legitimately
-       * serve udp only
-       */
-      goto tryudp;
-    }
-    /* Create privileged TCP socket */
-    *sock = t_open(nc->nc_device, O_RDWR, 0);
-
-    if (*sock < 0) {
-      fprintf(stderr, "t_open %s: %m\n", nc->nc_device);
-      goto tryudp;
-    }
-    if (amq_bind_resv_port(*sock, (u_short *) 0) < 0)
-      goto tryudp;
-
-    client = clnt_vc_create(*sock, &nb, amd_program_number, AMQ_VERSION, 0, 0);
-    if (!client) {
-      fprintf(stderr, "clnt_vc_create failed");
-      t_close(*sock);
-      goto tryudp;
-    }
-    /* tcp succeeded */
-    return client;
-  }
-
-tryudp:
-  /*
-   * TCP failed so try UDP
-   */
-  if (use_udp_flag) {
-    /* find amd address on UDP */
-    nc = getnetconfigent(NC_UDP);
-    if (!nc) {
-      fprintf(stderr, "getnetconfig for udp failed: %s\n", nc_sperror());
-      return NULL;
-    }
-    if (!rpcb_getaddr(amd_program_number, AMQ_VERSION, nc, &nb, host)) {
-      fprintf(stderr, "%s\n",
-	      clnt_spcreateerror("couldn't get amd address on udp"));
-      return NULL;
-    }
-    /* create privileged UDP socket */
-    *sock = t_open(nc->nc_device, O_RDWR, 0);
-
-    if (*sock < 0) {
-      fprintf(stderr, "t_open %s: %m\n", nc->nc_device);
-      return NULL;		/* neither tcp not udp succeeded */
-    }
-    if (amq_bind_resv_port(*sock, (u_short *) 0) < 0)
-      return NULL;
-
-    client = clnt_dg_create(*sock, &nb, amd_program_number, AMQ_VERSION, 0, 0);
-    if (!client) {
-      fprintf(stderr, "clnt_dg_create failed\n");
-      t_close(*sock);
-      return NULL;		/* neither tcp not udp succeeded */
-    }
-    if (clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) tv) == FALSE) {
-      fprintf(stderr, "clnt_control CLSET_RETRY_TIMEOUT for udp failed\n");
-      clnt_destroy(client);
-      return NULL;		/* neither tcp not udp succeeded */
-    }
-    /* udp succeeded */
-    return client;
-  }
-
-  /* should never get here */
-  return NULL;
-}
-
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
-
-/*
- * inetresport creates a datagram socket and attempts to bind it to a
- * secure port.
- * returns: The bound socket, or -1 to indicate an error.
- */
-static int
-inetresport(int ty)
-{
-  int alport;
-  struct sockaddr_in addr;
-  int fd;
-
-  /* Use internet address family */
-  addr.sin_family = AF_INET;
-  addr.sin_addr.s_addr = INADDR_ANY;
-  if ((fd = socket(AF_INET, ty, 0)) < 0)
-    return -1;
-
-  for (alport = IPPORT_RESERVED - 1; alport > IPPORT_RESERVED / 2 + 1; alport--) {
-    addr.sin_port = htons((u_short) alport);
-    if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) >= 0)
-      return fd;
-    if (errno != EADDRINUSE) {
-      close(fd);
-      return -1;
-    }
-  }
-  close(fd);
-  errno = EAGAIN;
-  return -1;
-}
-
-
-/*
- * Privsock() calls inetresport() to attempt to bind a socket to a secure
- * port.  If inetresport() fails, privsock returns a magic socket number which
- * indicates to RPC that it should make its own socket.
- * returns: A privileged socket # or RPC_ANYSOCK.
- */
-static int
-privsock(int ty)
-{
-  int sock = inetresport(ty);
-
-  if (sock < 0) {
-    errno = 0;
-    /* Couldn't get a secure port, let RPC make an insecure one */
-    sock = RPC_ANYSOCK;
-  }
-  return sock;
-}
-
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
diff --git a/contrib/amd/amq/amq.h b/contrib/amd/amq/amq.h
index cebe624..2f36b81 100644
--- a/contrib/amd/amq/amq.h
+++ b/contrib/amd/amq/amq.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amq.h,v 1.2 1999/01/10 21:53:59 ezk Exp $
+ * File: am-utils/amq/amq.h
  *
  */
 
@@ -59,5 +58,6 @@ extern amq_mount_info_list *amqproc_getmntfs_1(voidp argp, CLIENT *rqstp);
 extern int *amqproc_mount_1(voidp argp, CLIENT *rqstp);
 extern amq_string *amqproc_getvers_1(voidp argp, CLIENT *rqstp);
 extern int *amqproc_getpid_1(voidp argp, CLIENT *rqstp);
+extern amq_string *amqproc_pawd_1(amq_string *argp, CLIENT *rqstp);
 
 #endif /* not _AMQ_H */
diff --git a/contrib/amd/amq/amq_clnt.c b/contrib/amd/amq/amq_clnt.c
index 1251c87..ddfeb67 100644
--- a/contrib/amd/amq/amq_clnt.c
+++ b/contrib/amd/amq/amq_clnt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amq_clnt.c,v 1.2 1999/01/10 21:53:59 ezk Exp $
+ * File: am-utils/amq/amq_clnt.c
  *
  */
 
@@ -76,7 +75,7 @@ amqproc_mnttree_1(amq_string *argp, CLIENT *clnt)
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_MNTTREE,
 		(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
-		(XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (SVC_IN_ARG_TYPE) & res,
+		(XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (SVC_IN_ARG_TYPE) &res,
 		TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
@@ -109,7 +108,7 @@ amqproc_stats_1(voidp argp, CLIENT *clnt)
   if (clnt_call(clnt, AMQPROC_STATS,
 		(XDRPROC_T_TYPE) xdr_void, argp,
 		(XDRPROC_T_TYPE) xdr_amq_mount_stats,
-		(SVC_IN_ARG_TYPE) & res,
+		(SVC_IN_ARG_TYPE) &res,
 		TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
@@ -126,7 +125,7 @@ amqproc_export_1(voidp argp, CLIENT *clnt)
   if (clnt_call(clnt, AMQPROC_EXPORT,
 		(XDRPROC_T_TYPE) xdr_void, argp,
 		(XDRPROC_T_TYPE) xdr_amq_mount_tree_list,
-		(SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
+		(SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
   return (&res);
@@ -141,7 +140,7 @@ amqproc_setopt_1(amq_setopt *argp, CLIENT *clnt)
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_SETOPT, (XDRPROC_T_TYPE) xdr_amq_setopt,
 		(SVC_IN_ARG_TYPE) argp, (XDRPROC_T_TYPE) xdr_int,
-		(SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
+		(SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
   return (&res);
@@ -156,7 +155,7 @@ amqproc_getmntfs_1(voidp argp, CLIENT *clnt)
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_GETMNTFS, (XDRPROC_T_TYPE) xdr_void, argp,
 		(XDRPROC_T_TYPE) xdr_amq_mount_info_list,
-		(SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
+		(SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
   return (&res);
@@ -170,7 +169,7 @@ amqproc_mount_1(voidp argp, CLIENT *clnt)
 
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_MOUNT, (XDRPROC_T_TYPE) xdr_amq_string, argp,
-		(XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) & res,
+		(XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) &res,
 		TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
@@ -185,7 +184,7 @@ amqproc_getvers_1(voidp argp, CLIENT *clnt)
 
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_GETVERS, (XDRPROC_T_TYPE) xdr_void, argp,
-		(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) & res,
+		(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) &res,
 		TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
@@ -200,7 +199,23 @@ amqproc_getpid_1(voidp argp, CLIENT *clnt)
 
   memset((char *) &res, 0, sizeof(res));
   if (clnt_call(clnt, AMQPROC_GETPID, (XDRPROC_T_TYPE) xdr_void, argp,
-		(XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) & res,
+		(XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) &res,
+		TIMEOUT) != RPC_SUCCESS) {
+    return (NULL);
+  }
+  return (&res);
+}
+
+
+amq_string *
+amqproc_pawd_1(amq_string *argp, CLIENT *clnt)
+{
+  static amq_string res;
+
+  memset((char *) &res, 0, sizeof(res));
+  if (clnt_call(clnt, AMQPROC_PAWD,
+		(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
+		(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) &res,
 		TIMEOUT) != RPC_SUCCESS) {
     return (NULL);
   }
diff --git a/contrib/amd/amq/amq_xdr.c b/contrib/amd/amq/amq_xdr.c
index 26b93b3..692a0a4 100644
--- a/contrib/amd/amq/amq_xdr.c
+++ b/contrib/amd/amq/amq_xdr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amq_xdr.c,v 1.2 1999/01/10 21:53:59 ezk Exp $
+ * File: am-utils/amq/amq_xdr.c
  *
  */
 
@@ -107,11 +106,17 @@ xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
     return (FALSE);
   }
 
-  if (!xdr_pointer(xdrs, (char **) &objp->mt_next, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
+  if (!xdr_pointer(xdrs,
+		   (char **) ((voidp) &objp->mt_next),
+		   sizeof(amq_mount_tree),
+		   (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
     return (FALSE);
   }
 
-  if (!xdr_pointer(xdrs, (char **) &objp->mt_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
+  if (!xdr_pointer(xdrs,
+		   (char **) ((voidp) &objp->mt_child),
+		   sizeof(amq_mount_tree),
+		   (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
     return (FALSE);
   }
 
@@ -122,7 +127,10 @@ xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
 bool_t
 xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp)
 {
-  if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
+  if (!xdr_pointer(xdrs,
+		   (char **) objp,
+		   sizeof(amq_mount_tree),
+		   (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
     return (FALSE);
   }
   return (TRUE);
@@ -169,7 +177,7 @@ bool_t
 xdr_amq_mount_info_list(XDR *xdrs, amq_mount_info_list *objp)
 {
   if (!xdr_array(xdrs,
-		 (char **) &objp->amq_mount_info_list_val,
+		 (char **) ((voidp) &objp->amq_mount_info_list_val),
 		 (u_int *) &objp->amq_mount_info_list_len,
 		 ~0,
 		 sizeof(amq_mount_info),
@@ -184,7 +192,7 @@ bool_t
 xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp)
 {
   if (!xdr_array(xdrs,
-		 (char **) &objp->amq_mount_tree_list_val,
+		 (char **) ((voidp) &objp->amq_mount_tree_list_val),
 		 (u_int *) &objp->amq_mount_tree_list_len,
 		 ~0,
 		 sizeof(amq_mount_tree_p),
diff --git a/contrib/amd/amq/pawd.1 b/contrib/amd/amq/pawd.1
index d4e2f44..0ed4cac 100644
--- a/contrib/amd/amq/pawd.1
+++ b/contrib/amd/amq/pawd.1
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-1999 Erez Zadok
+.\" Copyright (c) 1997-2006 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.
@@ -38,11 +38,10 @@
 .\"
 .\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: pawd.1,v 1.2 1998/09/05 06:56:36 obrien Exp $
-.\" $FreeBSD: src/contrib/amd/amq/pawd.1,v 1.4 1999/09/15 05:45:14 obrien Exp $
-.\" $DragonFly: src/contrib/amd/amq/pawd.1,v 1.2 2003/06/17 04:23:57 dillon Exp $
+.\" $Id: pawd.1,v 1.9.2.1 2006/01/02 18:48:24 ezk Exp $
+.\" $FreeBSD: src/contrib/amd/amq/pawd.1,v 1.10 2012/11/17 01:48:41 svnexp Exp $
 .\"
-.Dd January 6, 1998
+.Dd January 2, 2006
 .Dt PAWD 1
 .Os
 .Sh NAME
@@ -52,20 +51,25 @@
 .Nm
 .Op Ar path ...
 .Sh DESCRIPTION
+The
 .Nm
+utility
 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
+possible path.
+In particular, the path printed back does not include any
 of
-.Nm Amd Ns \'s
-local mount points.  Using them is unsafe, because
-.Nm Amd
+.Xr amd 8 Ns 's
+local mount points.
+Using them is unsafe, because
+.Xr amd 8
 may unmount managed file systems from the mount points, and thus including
 them in paths may not always find the files within.
 .Pp
 Without any arguments,
 .Nm
-will print the automounter adjusted current working directory.  With any
+will print the automounter adjusted current working directory.
+With any
 number of arguments, it will print the adjusted
 .Ar path
 of each one of the
@@ -73,9 +77,33 @@ arguments.
 .Sh SEE ALSO
 .Xr pwd 1 ,
 .Xr amd 8 ,
-.Xr amq 8 
+.Xr amq 8
+.Pp
+.Dq am-utils
+.Xr info 1
+entry.
+.Rs
+.%A Erez Zadok
+.%B "Linux NFS and Automounter Administration"
+.%O ISBN 0-7821-2739-8
+.%I Sybex
+.%D 2001
+.Re
+.Pp
+.Pa http://www.am-utils.org/
+.Rs
+.%T Amd \- The 4.4 BSD Automounter
+.Re
 .Sh HISTORY
 The
 .Nm
 utility first appeared in
 .Fx 3.0 .
+.Sh AUTHORS
+.An Erez Zadok Aq ezk@cs.sunysb.edu ,
+Computer Science Department, Stony Brook
+University, Stony Brook, New York, USA.
+.Pp
+Other authors and contributors to am-utils are listed in the
+.Pa AUTHORS
+file distributed with am-utils.
diff --git a/contrib/amd/amq/pawd.c b/contrib/amd/amq/pawd.c
index cf9dce6..c9a32b1 100644
--- a/contrib/amd/amq/pawd.c
+++ b/contrib/amd/amq/pawd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: pawd.c,v 1.5 1999/09/08 23:36:40 ezk Exp $
+ * File: am-utils/amq/pawd.c
  *
  */
 
@@ -58,48 +57,11 @@
 #include <am_defs.h>
 #include <amq.h>
 
+
 /* statics */
-static char *localhost="localhost";
-static char newdir[MAXPATHLEN];
+static char *localhost = "localhost";
 static char transform[MAXPATHLEN];
 
-static int
-find_mt(amq_mount_tree *mt, char *dir)
-{
-  while (mt) {
-    if (STREQ(mt->mt_type, "link") ||
-	STREQ(mt->mt_type, "nfs") ||
-	STREQ(mt->mt_type, "nfsl")) {
-      int len = strlen(mt->mt_mountpoint);
-      if (NSTREQ(mt->mt_mountpoint, dir, len) &&
-	  ((dir[len] == '\0') || (dir[len] == '/'))) {
-	char tmp_buf[MAXPATHLEN];
-	strcpy(tmp_buf, mt->mt_directory);
-	strcat(tmp_buf, &dir[len]);
-	strcpy(newdir, tmp_buf);
-	return 1;
-      }
-    }
-    if (find_mt(mt->mt_next,dir))
-      return 1;
-    mt = mt->mt_child;
-  }
-  return 0;
-}
-
-
-static int
-find_mlp(amq_mount_tree_list *mlp, char *dir)
-{
-  int i;
-
-  for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
-    if (find_mt(mlp->amq_mount_tree_list_val[i], dir))
-      return 1;
-  }
-  return 0;
-}
-
 
 #ifdef HAVE_CNODEID
 static char *
@@ -160,7 +122,8 @@ hack_name(char *dir)
     fprintf(stderr, "partition %s, username %s\n", partition, username);
 #endif /* DEBUG */
 
-    sprintf(hesiod_lookup, "%s.homes-remote", username);
+    xsnprintf(hesiod_lookup, sizeof(hesiod_lookup),
+	      "%s.homes-remote", username);
     hes = hes_resolve(hesiod_lookup, "amd");
     if (!hes)
       return NULL;
@@ -184,9 +147,10 @@ hack_name(char *dir)
 #ifdef DEBUG
     fprintf(stderr, "A match, munging....\n");
 #endif /* DEBUG */
-    strcpy(transform, "/home/");
-    strcat(transform, username);
-    if (*ch) strcat(transform, ch);
+    xstrlcpy(transform, "/home/", sizeof(transform));
+    xstrlcat(transform, username, sizeof(transform));
+    if (*ch)
+      xstrlcat(transform, ch, sizeof(transform));
 #ifdef DEBUG
     fprintf(stderr, "Munged to <%s>\n", transform);
 #endif /* DEBUG */
@@ -216,8 +180,9 @@ transform_dir(char *dir)
   int s = RPC_ANYSOCK;
   CLIENT *clnt;
   struct hostent *hp;
-  amq_mount_tree_list *mlp;
   struct timeval tmo = {10, 0};
+  char *dummystr;
+  amq_string *spp;
 
 #ifdef DISK_HOME_HACK
   if (ch = hack_name(dir))
@@ -230,31 +195,37 @@ transform_dir(char *dir)
   server = localhost;
 #endif /* not HAVE_CNODEID */
 
-  if ((hp = gethostbyname(server)) == 0)
+  if ((hp = gethostbyname(server)) == NULL)
     return dir;
   memset(&server_addr, 0, sizeof(server_addr));
+  /* as per POSIX, sin_len need not be set (used internally by kernel) */
   server_addr.sin_family = AF_INET;
   server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
 
   clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
-  if (clnt == 0)
+  if (clnt == NULL)
+    clnt = clnttcp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, &s, 0, 0);
+  if (clnt == NULL)
     return dir;
 
-  strcpy(transform,dir);
-  while ( (mlp = amqproc_export_1((voidp)0, clnt)) &&
-	  find_mlp(mlp,transform) ) {
-    strcpy(transform,newdir);
+  xstrlcpy(transform, dir, sizeof(transform));
+  dummystr = transform;
+  spp = amqproc_pawd_1((amq_string *) &dummystr, clnt);
+  if (spp && *spp && **spp) {
+    xstrlcpy(transform, *spp, sizeof(transform));
+    XFREE(*spp);
   }
+  clnt_destroy(clnt);
   return transform;
 }
 
 
 /* getawd() is a substitute for getwd() which transforms the path */
 static char *
-getawd(char *path)
+getawd(char *path, size_t l)
 {
 #ifdef HAVE_GETCWD
-  char *wd = getcwd(path, MAXPATHLEN+1);
+  char *wd = getcwd(path, MAXPATHLEN);
 #else /* not HAVE_GETCWD */
   char *wd = getwd(path);
 #endif /* not HAVE_GETCWD */
@@ -262,7 +233,7 @@ getawd(char *path)
   if (wd == NULL) {
     return NULL;
   }
-  strcpy(path, transform_dir(wd));
+  xstrlcpy(path, transform_dir(wd), l);
   return path;
 }
 
@@ -273,7 +244,7 @@ main(int argc, char *argv[])
   char tmp_buf[MAXPATHLEN], *wd;
 
   if (argc == 1) {
-    wd = getawd(tmp_buf);
+    wd = getawd(tmp_buf, sizeof(tmp_buf));
     if (wd == NULL) {
       fprintf(stderr, "pawd: %s\n", tmp_buf);
       exit(1);
diff --git a/contrib/amd/aux_conf.h.in b/contrib/amd/aux_conf.h.in
new file mode 100644
index 0000000..8c38bbf
--- /dev/null
+++ b/contrib/amd/aux_conf.h.in
@@ -0,0 +1,58 @@
+/*
+ * aux_conf.h:
+ * This file gets "filled in" for each architecture.
+ * @configure_input@
+ */
+
+#ifndef _AUX_CONF_H
+#define _AUX_CONF_H
+
+/*
+ * The next line is a literal inclusion of a file which includes a
+ * definition for the MOUNT_TRAP macro for a particular architecture.
+ * If it defines the wrong entry, check the AC_CHECK_MOUNT_TRAP m4 macro
+ * in $srcdir/m4/macros.
+ */
+@am_utils_mount_trap@
+/* End of included MOUNT_TRAP macro definition file */
+
+/*
+ * The next line is a literal replacement of a variable which defines the
+ * the UNMOUNT_TRAP macro for a particular architecture.
+ * If it defines the wrong entry, check the AC_CHECK_UNMOUNT_CALL m4 macro
+ * in $srcdir/aclocal.m4.  If the arguments are being defined wrong, check
+ * the macro AC_CHECK_UNMOUNT_ARGS in $srcdir/m4/macros.
+ */
+#define UNMOUNT_TRAP(mnt)	@am_utils_unmount_call@(@am_utils_unmount_args@)
+/* End of replaced UNMOUNT_TRAP macro definition */
+/* umount(8) executable path, for type:=program */
+#define UNMOUNT_PROGRAM		"@UNMOUNT_PROGRAM@"
+
+/*
+ * The next line is a literal inclusion of a file which includes a
+ * definition for the NFS_FH_DREF macro for a particular architecture.
+ * If it defines the wrong entry, check the AC_CHECK_NFS_FH_DREF m4 macro
+ * in $srcdir/m4/macros.
+ */
+@am_utils_nfs_fh_dref@
+/* End of included NFS_FH_DREF macro definition file */
+
+/*
+ * The next line is a literal inclusion of a file which includes a
+ * definition for the NFS_SA_DREF macro for a particular architecture.
+ * If it defines the wrong entry, check the AC_CHECK_NFS_SA_DREF m4 macro
+ * in $srcdir/m4/macros.
+ */
+@am_utils_nfs_sa_dref@
+/* End of included NFS_SA_DREF macro definition file */
+
+/*
+ * The next line is a literal inclusion of a file which includes a
+ * definition for the NFS_HN_DREF macro for a particular architecture.
+ * If it defines the wrong entry, check the AC_CHECK_NFS_HN_DREF m4 macro
+ * in $srcdir/m4/macros.
+ */
+@am_utils_nfs_hn_dref@
+/* End of included NFS_HN_DREF macro definition file */
+
+#endif /* not _AUX_CONF_H */
diff --git a/contrib/amd/bootstrap b/contrib/amd/bootstrap
new file mode 100755
index 0000000..6c35138
--- /dev/null
+++ b/contrib/amd/bootstrap
@@ -0,0 +1,108 @@
+#!/bin/sh
+#set -x
+# helps bootstrapping am-utils, when checked out from CVS
+# requires GNU autoconf and GNU automake
+# this is not meant to go into the distributions
+# Erez Zadok <ezk@cs.columbia.edu>
+
+# test cwd
+test -f ../amd/amd.c && cd ..
+if [ ! -f amd/amd.c ]; then
+    echo "Must run $0 from the top level source directory."
+    exit 1
+fi
+
+# validate macros directory and some macro files
+if [ ! -d m4/macros ]; then
+    echo No m4/macros directory found!
+    exit 1
+fi
+if [ ! -f m4/macros/HEADER ]; then
+    echo No m4/macros/HEADER file found!
+    exit 1
+fi
+
+# remove any remaining autom4te.cache directory
+rm -fr autom4te.cache autom4te-*.cache
+
+# generate acinclude.m4 file
+echo "AMU: prepare acinclude.m4..."
+test -f acinclude.m4 && mv -f acinclude.m4 acinclude.m4.old
+(cd m4/macros
+ for i in HEADER *.m4; do
+     cat $i
+     echo
+     echo
+ done
+ cat TRAILER
+) > acinclude.m4
+
+# generate aclocal.m4 file
+echo "AMU: aclocal..."
+test -f aclocal.m4 && mv -f aclocal.m4 aclocal.m4.old
+# show version
+aclocal --version 2>&1 | head -1
+if aclocal ; then
+    :
+else
+    echo "aclocal command failed.  fix errors and rerun $0."
+    exit 2
+fi
+
+# produce new configure.in (temp) script
+echo "AMU: autoconf..."
+# show version
+autoconf --version 2>&1 | head -1
+LOG=/tmp/amu-$$.log
+rm -f ${LOG}
+autoconf configure.in > configure.new 2> ${LOG}
+# until Automake requires Autoconf 2.50, manual says to ignore this
+CUTWARNMSG1="warning: AC_PROG_LEX invoked multiple times|do not use m4_(patsubst|regexp):"
+egrep -v "${CUTWARNMSG1}" ${LOG} > ${LOG}.new
+mv ${LOG}.new ${LOG}
+if test -s ${LOG}; then
+    echo "AUTOCONF ERRORS (MUST FIX):"
+    cat ${LOG}
+    rm -f ${LOG}
+    exit 2
+fi
+# now prepare the real configure script
+test -f configure && mv -f configure configure.old
+mv -f configure.new configure
+chmod a+rx configure
+rm -f configure.old
+
+# run autoheader to produce C header .in files
+echo "AMU: autoheader..."
+# show version
+autoheader --version 2>&1 | head -1
+autoheader configure.in > config.h.in 2> ${LOG}
+CUTWARNMSG2="autoheader: \`config.h.in' is updated"
+egrep -v "${CUTWARNMSG2}" ${LOG} > ${LOG}.new
+mv ${LOG}.new ${LOG}
+if test -s ${LOG}; then
+    echo "AUTOHEADER ERRORS (MUST FIX):"
+    cat ${LOG}
+    rm -f ${LOG}
+    exit 2
+fi
+rm -f ${LOG}
+
+# generate makefiles
+cmd="automake --add-missing --copy --ignore-deps"
+#cmd="automake --add-missing"
+echo "AMU: $cmd..."
+# show version
+automake --version 2>&1 | head -1
+if ${cmd} ; then
+    :
+else
+    echo "automake command failed.  fix errors and rerun $0."
+    exit 2
+fi
+
+# save timestamp
+echo "AMU: save timestamp..."
+echo timestamp > stamp-h.in
+
+exit 0
diff --git a/contrib/amd/conf/checkmount/checkmount_bsd44.c b/contrib/amd/conf/checkmount/checkmount_bsd44.c
index 4aa61dd..a6ec243 100644
--- a/contrib/amd/conf/checkmount/checkmount_bsd44.c
+++ b/contrib/amd/conf/checkmount/checkmount_bsd44.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: checkmount_bsd44.c,v 1.2 1999/01/10 21:54:06 ezk Exp $
+ * File: am-utils/conf/checkmount/checkmount_bsd44.c
  *
  */
 
diff --git a/contrib/amd/conf/hn_dref/hn_dref_default.h b/contrib/amd/conf/hn_dref/hn_dref_default.h
deleted file mode 100644
index d495ea8..0000000
--- a/contrib/amd/conf/hn_dref/hn_dref_default.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* $srcdir/conf/hn_dref/hn_dref_default.h */
-#define NFS_HN_DREF(dst, src) (dst) = (src)
diff --git a/contrib/amd/conf/mtab/mtab_bsd.c b/contrib/amd/conf/mtab/mtab_bsd.c
index 5849c6a..fe3991a 100644
--- a/contrib/amd/conf/mtab/mtab_bsd.c
+++ b/contrib/amd/conf/mtab/mtab_bsd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: mtab_bsd.c,v 1.2 1999/01/10 21:54:11 ezk Exp $
+ * File: am-utils/conf/mtab/mtab_bsd.c
  *
  */
 
@@ -64,9 +63,9 @@ mnt_dup(struct statfs *mp)
   new_mp->mnt_fsname = strdup(mp->f_mntfromname);
   new_mp->mnt_dir = strdup(mp->f_mntonname);
 
-#ifdef HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME
+#ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME
   ty = mp->f_fstypename;
-#else /* not HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME */
+#else /* not HAVE_STRUCT_STATFS_F_FSTYPENAME */
   switch (mp->f_type) {
 
 # if defined(MOUNT_UFS) && defined(MNTTAB_TYPE_UFS)
@@ -92,7 +91,7 @@ mnt_dup(struct statfs *mp)
 
     break;
   }
-#endif /* not HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME */
+#endif /* not HAVE_STRUCT_STATFS_F_FSTYPENAME */
 
   new_mp->mnt_type = strdup(ty);
   new_mp->mnt_opts = strdup("unset");
diff --git a/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h b/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h
index d2120c1..cf7ba33 100644
--- a/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h
+++ b/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,23 +36,17 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: nfs_prot_freebsd2.h,v 1.2 1999/01/10 21:54:14 ezk Exp $
- * $FreeBSD: src/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h,v 1.4 1999/09/15 05:45:14 obrien Exp $
- * $DragonFly: src/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h,v 1.2 2003/06/17 04:23:57 dillon Exp $
+ * File: am-utils/conf/nfs_prot/nfs_prot_freebsd2.h
  *
  */
 
 #ifndef _AMU_NFS_PROT_H
 #define _AMU_NFS_PROT_H
 
-#ifdef COMMENT_OUT
 #ifdef HAVE_RPCSVC_NFS_PROT_H
 # include <rpcsvc/nfs_prot.h>
 #endif /* HAVE_RPCSVC_NFS_PROT_H */
-#endif	/* COMMENT_OUT */
-# include "nfs_prot.h"
 
 /*
  * MACROS:
diff --git a/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h b/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h
index 13548e8..fc67925 100644
--- a/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h
+++ b/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,22 +36,16 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: nfs_prot_freebsd3.h,v 1.4 1999/03/30 17:22:54 ezk Exp $
- * $FreeBSD: src/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h,v 1.7 1999/09/15 05:45:14 obrien Exp $
- * $DragonFly: src/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h,v 1.3 2003/08/08 04:18:29 dillon Exp $
+ * File: am-utils/conf/nfs_prot/nfs_prot_freebsd3.h
+ * $Id: nfs_prot_freebsd3.h,v 1.5.2.7 2004/01/06 03:15:19 ezk Exp $
+ * $FreeBSD: src/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h,v 1.15 2012/11/17 01:48:41 svnexp Exp $
  *
  */
 
 #ifndef _AMU_NFS_PROT_H
 #define _AMU_NFS_PROT_H
 
-#ifdef COMMENT_OUT
-#ifdef HAVE_RPCSVC_NFS_PROT_H
-# include <rpcsvc/nfs_prot.h>
-#endif /* HAVE_RPCSVC_NFS_PROT_H */
-#endif	/* COMMENT_OUT */
 /* nfs_prot.h defines struct `nfs_fh3', but it is a ``dmr "unwarranted
  * chumminess with the C implementation".  We need the more complete
  * structure, which is defined below.  So get the stock `nfs_fh3'
@@ -59,7 +53,11 @@
  */
 struct nfs_fh3;
 #define nfs_fh3 nfs_fh3_fbsd_
-# include "nfs_prot.h"
+
+#ifdef HAVE_RPCSVC_NFS_PROT_H
+# include <rpcsvc/nfs_prot.h>
+#endif /* HAVE_RPCSVC_NFS_PROT_H */
+
 #undef nfs_fh3
 
 #ifdef HAVE_NFS_RPCV2_H
@@ -69,9 +67,21 @@ struct nfs_fh3;
 # include <nfs/nfs.h>
 #endif /* HAVE_NFS_NFS_H */
 #ifdef	HAVE_UFS_UFS_UFSMOUNT_H
-# include <vfs/ufs/ufsmount.h>
+# ifdef HAVE_UFS_UFS_EXTATTR_H
+/*
+ * Define a dummy struct ufs_extattr_per_mount, which is used in struct
+ * ufsmount in <ufs/ufs/ufsmount.h>.
+ */
+struct ufs_extattr_per_mount;
+# endif /* HAVE_UFS_UFS_EXTATTR_H */
+# include <ufs/ufs/ufsmount.h>
 #endif	/* HAVE_UFS_UFS_UFSMOUNT_H */
 
+/* nfsclient/nfsargs.h was introduced in FreeBSD 5.0, and is needed */
+#ifdef	HAVE_NFSCLIENT_NFSARGS_H
+# include <nfsclient/nfsargs.h>
+#endif	/* HAVE_NFSCLIENT_NFSARGS_H */
+
 /*
  * MACROS:
  */
@@ -97,6 +107,7 @@ struct nfs_fh3;
 #define na_nlink	nlink
 #define na_size		size
 #define na_type		type
+#define na_uid		uid
 #define ne_cookie	cookie
 #define ne_fileid	fileid
 #define ne_name		name
@@ -171,25 +182,19 @@ typedef writeargs nfswriteargs;
  */
 #ifdef NFSMNT_NFSV3
 
-# define MOUNT_NFS3 MOUNT_NFS
-# define MNTOPT_NFS3 "nfs"
+# define MOUNT_NFS3	"nfs"	/* is this right? */
+# define MNTOPT_NFS3	"nfs"
 
+# ifndef HAVE_XDR_LOOKUP3RES
 /*
- * as of 3.0-RELEASE the nfs_fh3 that is defined in the system headers
- * (or the one generated by rpcgen) lacks the proper full definition,
- * listed below.  A special macro (aux/macros/struct_nfs_fh3.m4) searches
- * for this special name before other names.
+ * FreeBSD uses different field names than are defined on most other
+ * systems.
  */
-struct nfs_fh3_freebsd3 {
-  u_int fh3_length;
-  union nfs_fh3_u {
-    struct nfs_fh3_i {
-      fhandle_t fh3_i;
-    } nfs_fh3_i;
-    char data[NFS3_FHSIZE];
-  } fh3_u;
-};
-typedef struct nfs_fh3_freebsd3 nfs_fh3_freebsd3;
+#  define AMU_LOOKUP3RES_OK(x)		((x)->LOOKUP3res_u.resok)
+#  define AMU_LOOKUP3RES_FAIL(x)	((x)->LOOKUP3res_u.resfail)
+#  define AMU_LOOKUP3RES_FH_LEN(x)	(AMU_LOOKUP3RES_OK(x).object.data.data_len)
+#  define AMU_LOOKUP3RES_FH_DATA(x)	(AMU_LOOKUP3RES_OK(x).object.data.data_val)
+# endif /* not HAVE_XDR_LOOKUP3RES */
 
 /* since we don't use Am-utils's aux/macros/struct_nfs_fh3.m4, we don't get
    their special searching.  So restore the standard name. */
diff --git a/contrib/amd/conf/sa_dref/sa_dref_bsd44.h b/contrib/amd/conf/sa_dref/sa_dref_bsd44.h
index e76c16b..a807540 100644
--- a/contrib/amd/conf/sa_dref/sa_dref_bsd44.h
+++ b/contrib/amd/conf/sa_dref/sa_dref_bsd44.h
@@ -3,3 +3,4 @@
 		(dst)->addr = (struct sockaddr *) (src); \
 		(dst)->addrlen = sizeof(*src); \
 	}
+#define NFS_ARGS_T_ADDR_IS_POINTER 1
diff --git a/contrib/amd/conf/transp/transp_sockets.c b/contrib/amd/conf/transp/transp_sockets.c
index 3dbd9dc..025e1f3 100644
--- a/contrib/amd/conf/transp/transp_sockets.c
+++ b/contrib/amd/conf/transp/transp_sockets.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: transp_sockets.c,v 1.5 1999/08/22 21:12:31 ezk Exp $
+ * File: am-utils/conf/transp/transp_sockets.c
  *
  * Socket specific utilities.
  *      -Erez Zadok <ezk@cs.columbia.edu>
@@ -55,18 +54,67 @@
  * find the IP address that can be used to connect to the local host
  */
 void
-amu_get_myaddress(struct in_addr *iap)
+amu_get_myaddress(struct in_addr *iap, const char *preferred_localhost)
 {
+  struct hostent *hp;
+  char dq[20];
+
+#ifdef DEBUG_off
+#error this code is old and probably not useful any longer.
+#error Erez, Jan 21, 2004.
   struct sockaddr_in sin;
 
+  /*
+   * Most modern systems should use 127.0.0.1 as the localhost address over
+   * which you can do NFS mounts.  In the past we found that some NFS
+   * clients may not allow mounts from localhost.  So we used
+   * get_myaddress() and that seemed to work.  Alas, on some other systems,
+   * get_myaddress() may return one of the interface addresses at random,
+   * and thus use a less efficient IP address than 127.0.0.1.  The solution
+   * is to hard-code 127.0.0.1, but still check if get_myaddress() returns a
+   * different value and warn about it.
+   */
   memset((char *) &sin, 0, sizeof(sin));
   get_myaddress(&sin);
-  iap->s_addr = sin.sin_addr.s_addr;
+  if (sin.sin_addr.s_addr != htonl(INADDR_LOOPBACK))
+    dlog("amu_get_myaddress: myaddress conflict (0x%x vs. 0x%lx)",
+	 sin.sin_addr.s_addr, (u_long) htonl(INADDR_LOOPBACK));
+#endif /* DEBUG_off */
+
+  if (preferred_localhost == NULL)
+    goto out;
+
+  /* if specified preferred locahost, then try to use it */
+  hp = gethostbyname(preferred_localhost);
+  if (hp == NULL) {
+    /* XXX: if hstrerror()/h_errno aren't portable, then need to port the next statement */
+    plog(XLOG_ERROR, "Unable to resolve localhost_address \"%s\" (%s): using default",
+	 preferred_localhost, hstrerror(h_errno));
+    goto out;
+  }
+  if (hp->h_addr_list == NULL) {
+    plog(XLOG_ERROR, "localhost_address \"%s\" has no IP addresses: using default",
+	 preferred_localhost);
+    goto out;
+  }
+  if (hp->h_addr_list[1] != NULL) {
+    plog(XLOG_ERROR, "localhost_address \"%s\" has more than one IP addresses: using first",
+	 preferred_localhost);
+    goto out;
+  }
+  memmove((voidp) &iap->s_addr, (voidp) hp->h_addr_list[0], sizeof(iap->s_addr));
+  plog(XLOG_INFO, "localhost_address \"%s\" requested, using %s",
+       preferred_localhost, inet_dquad(dq, sizeof(dq), iap->s_addr));
+  return;
+
+ out:
+  iap->s_addr = htonl(INADDR_LOOPBACK);
 }
 
 
 /*
  * How to bind to reserved ports.
+ * Note: if *pp is non-null and is greater than 0, then *pp will not be modified.
  */
 int
 bind_resv_port(int so, u_short *pp)
@@ -78,16 +126,21 @@ bind_resv_port(int so, u_short *pp)
   memset((voidp) &sin, 0, sizeof(sin));
   sin.sin_family = AF_INET;
 
-  port = IPPORT_RESERVED;
-
-  do {
-    --port;
-    sin.sin_port = htons(port);
+  if (pp && *pp > 0) {
+    sin.sin_port = htons(*pp);
     rc = bind(so, (struct sockaddr *) &sin, sizeof(sin));
-  } while (rc < 0 && (int) port > IPPORT_RESERVED / 2);
+  } else {
+    port = IPPORT_RESERVED;
 
-  if (pp && rc == 0)
-    *pp = port;
+    do {
+      --port;
+      sin.sin_port = htons(port);
+      rc = bind(so, (struct sockaddr *) &sin, sizeof(sin));
+    } while (rc < 0 && (int) port > IPPORT_RESERVED / 2);
+
+    if (pp && rc == 0)
+      *pp = port;
+  }
 
   return rc;
 }
@@ -119,7 +172,7 @@ get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv,
      * Bind to a privileged port
      */
     if (bind_resv_port(*sock, (u_short *) 0) < 0)
-      plog(XLOG_ERROR, "can't bind privileged port");
+      plog(XLOG_ERROR, "can't bind privileged port (socket)");
 
     /*
      * Find mountd port to connect to.
@@ -161,9 +214,7 @@ get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv,
     *sock = RPC_ANYSOCK;
     return NULL;
   }
-#ifdef DEBUG
   dlog("get_mount_client: Using udp, port %d", sin->sin_port);
-#endif /* DEBUG */
   return client;
 }
 
@@ -174,7 +225,20 @@ get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv,
 struct sockaddr_in *
 amu_svc_getcaller(SVCXPRT *xprt)
 {
-  return svc_getcaller(xprt);
+  /* glibc 2.2 returns a sockaddr_storage ??? */
+  return (struct sockaddr_in *) svc_getcaller(xprt);
+}
+
+
+/*
+ * register an RPC server
+ */
+int
+amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum,
+		 void (*dispatch)(struct svc_req *rqstp, SVCXPRT *transp),
+		 u_long protocol, struct netconfig *dummy)
+{
+  return svc_register(xprt, prognum, versnum, dispatch, protocol);
 }
 
 
@@ -187,20 +251,28 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*
 
   *soNFSp = socket(AF_INET, SOCK_DGRAM, 0);
 
-  if (*soNFSp < 0 || bind_resv_port(*soNFSp, NULL) < 0) {
-    plog(XLOG_FATAL, "Can't create privileged nfs port");
+  if (*soNFSp < 0 || bind_resv_port(*soNFSp, nfs_portp) < 0) {
+    plog(XLOG_FATAL, "Can't create privileged nfs port (socket)");
+    if (*soNFSp >= 0)
+      close(*soNFSp);
     return 1;
   }
   if ((*nfs_xprtp = svcudp_create(*soNFSp)) == NULL) {
     plog(XLOG_FATAL, "cannot create rpc/udp service");
+    close(*soNFSp);
     return 2;
   }
   if ((*nfs_portp = (*nfs_xprtp)->xp_port) >= IPPORT_RESERVED) {
     plog(XLOG_FATAL, "Can't create privileged nfs port");
+    svc_destroy(*nfs_xprtp);
+    close(*soNFSp);
     return 1;
   }
   if (!svc_register(*nfs_xprtp, NFS_PROGRAM, NFS_VERSION, dispatch_fxn, 0)) {
-    plog(XLOG_FATAL, "unable to register (NFS_PROGRAM, NFS_VERSION, 0)");
+    plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)",
+	 (u_long) NFS_PROGRAM, (u_long) NFS_VERSION);
+    svc_destroy(*nfs_xprtp);
+    close(*soNFSp);
     return 3;
   }
 
@@ -212,7 +284,13 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*
  * Create the amq service for amd (both TCP and UDP)
  */
 int
-create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp)
+create_amq_service(int *udp_soAMQp,
+		   SVCXPRT **udp_amqpp,
+		   struct netconfig **dummy1,
+		   int *tcp_soAMQp,
+		   SVCXPRT **tcp_amqpp,
+		   struct netconfig **dummy2,
+		   u_short preferred_amq_port)
 {
   /* first create TCP service */
   if (tcp_soAMQp) {
@@ -222,12 +300,41 @@ create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPR
       return 1;
     }
 
+    /* next, bind to a specific (TCP) port if asked for */
+    if (preferred_amq_port > 0) {
+      /*
+       * Note: if &preferred_amq_port is non-null and is greater than 0,
+       * then the pointer will not be modified.  We don't want it to be
+       * modified because it was passed down to create_amq_service as a
+       * non-pointer (a variable on the stack, not to be modified!)
+       */
+      if (bind_resv_port(*tcp_soAMQp, &preferred_amq_port) < 0) {
+	plog(XLOG_FATAL, "can't bind amq service to requested TCP port %d: %m)", preferred_amq_port);
+	return 1;
+      }
+    }
+
     /* now create RPC service handle for amq */
     if (tcp_amqpp &&
 	(*tcp_amqpp = svctcp_create(*tcp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) {
       plog(XLOG_FATAL, "cannot create tcp service for amq: soAMQp=%d", *tcp_soAMQp);
-      return 2;
+      return 1;
+    }
+
+#ifdef SVCSET_CONNMAXREC
+    /*
+     * This is *BSD at its best.
+     * They just had to do things differently than everyone else
+     * so they fixed a library DoS issue by forcing client-side changes...
+     */
+# ifndef RPC_MAXDATASIZE
+#  define RPC_MAXDATASIZE 9000
+# endif /* not RPC_MAXDATASIZE */
+    if (tcp_amqpp) {
+      int maxrec = RPC_MAXDATASIZE;
+      SVC_CONTROL(*tcp_amqpp, SVCSET_CONNMAXREC, &maxrec);
     }
+#endif /* not SVCSET_CONNMAXREC */
   }
 
   /* next create UDP service */
@@ -235,14 +342,26 @@ create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPR
     *udp_soAMQp = socket(AF_INET, SOCK_DGRAM, 0);
     if (*udp_soAMQp < 0) {
       plog(XLOG_FATAL, "cannot create udp socket for amq service: %m");
-      return 3;
+      return 1;
+    }
+
+    /* next, bind to a specific (UDP) port if asked for */
+    if (preferred_amq_port > 0) {
+      /*
+       * Note: see comment about using &preferred_amq_port above in this
+       * function.
+       */
+      if (bind_resv_port(*udp_soAMQp, &preferred_amq_port) < 0) {
+	plog(XLOG_FATAL, "can't bind amq service to requested UDP port %d: %m)", preferred_amq_port);
+	return 1;
+      }
     }
 
     /* now create RPC service handle for amq */
     if (udp_amqpp &&
 	(*udp_amqpp = svcudp_bufcreate(*udp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) {
       plog(XLOG_FATAL, "cannot create udp service for amq: soAMQp=%d", *udp_soAMQp);
-      return 4;
+      return 1;
     }
   }
 
@@ -251,34 +370,47 @@ create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPR
 
 
 /*
- * Ping the portmapper on a remote system by calling the nullproc
+ * Check if the portmapper is running and reachable: 0==down, 1==up
  */
-enum clnt_stat
-pmap_ping(struct sockaddr_in *address)
+int check_pmap_up(char *host, struct sockaddr_in* sin)
 {
   CLIENT *client;
   enum clnt_stat clnt_stat = RPC_TIMEDOUT; /* assume failure */
   int socket = RPC_ANYSOCK;
   struct timeval timeout;
 
-  timeout.tv_sec = 3;
+  timeout.tv_sec = 2;
   timeout.tv_usec = 0;
-  address->sin_port = htons(PMAPPORT);
-  client = clntudp_create(address, PMAPPROG, PMAPVERS, timeout, &socket);
-  if (client != (CLIENT *) NULL) {
-    clnt_stat = clnt_call(client,
-			  PMAPPROC_NULL,
-			  (XDRPROC_T_TYPE) xdr_void,
-			  NULL,
-			  (XDRPROC_T_TYPE) xdr_void,
-			  NULL,
-			  timeout);
-    clnt_destroy(client);
+  sin->sin_port = htons(PMAPPORT);
+  client = clntudp_create(sin, PMAPPROG, PMAPVERS, timeout, &socket);
+
+  if (client == (CLIENT *) NULL) {
+    plog(XLOG_ERROR,
+	 "check_pmap_up: cannot create connection to contact portmapper on host \"%s\"%s",
+	 host, clnt_spcreateerror(""));
+    return 0;
   }
+
+  timeout.tv_sec = 6;
+  /* Ping the portmapper on a remote system by calling the nullproc */
+  clnt_stat = clnt_call(client,
+			PMAPPROC_NULL,
+			(XDRPROC_T_TYPE) xdr_void,
+			NULL,
+			(XDRPROC_T_TYPE) xdr_void,
+			NULL,
+			timeout);
+  clnt_destroy(client);
   close(socket);
-  address->sin_port = 0;
+  sin->sin_port = 0;
 
-  return clnt_stat;
+  if (clnt_stat == RPC_TIMEDOUT) {
+    plog(XLOG_ERROR,
+	 "check_pmap_up: failed to contact portmapper on host \"%s\": %s",
+	 host, clnt_sperrno(clnt_stat));
+    return 0;
+  }
+  return 1;
 }
 
 
@@ -293,6 +425,7 @@ get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const c
   enum clnt_stat clnt_stat;
   struct timeval tv;
   int sock;
+  char *errstr;
 
   /*
    * If not set or set wrong, then try from NFS_VERS_MAX on down. If
@@ -302,23 +435,15 @@ get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const c
     nfs_version = NFS_VERS_MAX;
     again = 1;
   }
-  tv.tv_sec = 3;		/* retry every 3 seconds, but also timeout */
+  tv.tv_sec = 2;		/* retry every 2 seconds, but also timeout */
   tv.tv_usec = 0;
 
-  /*
-   * First check if remote portmapper is up (verify if remote host is up).
-   */
-  clnt_stat = pmap_ping(sin);
-  if (clnt_stat == RPC_TIMEDOUT) {
-    plog(XLOG_ERROR, "get_nfs_version: failed to contact portmapper on host \"%s\": %s", host, clnt_sperrno(clnt_stat));
-    return 0;
-  }
-
 #ifdef HAVE_FS_NFS3
 try_again:
 #endif /* HAVE_FS_NFS3 */
 
   sock = RPC_ANYSOCK;
+  errstr = NULL;
   if (STREQ(proto, "tcp"))
     clnt = clnttcp_create(sin, NFS_PROGRAM, nfs_version, &sock, 0, 0);
   else if (STREQ(proto, "udp"))
@@ -326,61 +451,90 @@ try_again:
   else
     clnt = NULL;
 
-  if (clnt == NULL) {
+  if (clnt != NULL) {
+    /* Try three times (6/2=3) to verify the CLIENT handle. */
+    tv.tv_sec = 6;
+    clnt_stat = clnt_call(clnt,
+			  NFSPROC_NULL,
+			  (XDRPROC_T_TYPE) xdr_void,
+			  0,
+			  (XDRPROC_T_TYPE) xdr_void,
+			  0,
+			  tv);
+
+    if (clnt_stat != RPC_SUCCESS)
+      errstr = clnt_sperrno(clnt_stat);
+
+    close(sock);
+    clnt_destroy(clnt);
+  } else {
 #ifdef HAVE_CLNT_SPCREATEERROR
-    plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s :%s",
-	 (int) nfs_version, proto, host, clnt_spcreateerror(""));
+    errstr = clnt_spcreateerror("");
 #else /* not HAVE_CLNT_SPCREATEERROR */
-    plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s",
-	 (int) nfs_version, proto, host);
+    errstr = "";
 #endif /* not HAVE_CLNT_SPCREATEERROR */
-    return 0;
   }
 
-  /* Try a couple times to verify the CLIENT handle. */
-  tv.tv_sec = 6;
-  clnt_stat = clnt_call(clnt,
-			NFSPROC_NULL,
-			(XDRPROC_T_TYPE) xdr_void,
-			0,
-			(XDRPROC_T_TYPE) xdr_void,
-			0,
-			tv);
-  close(sock);
-  clnt_destroy(clnt);
-  if (clnt_stat != RPC_SUCCESS) {
+  if (errstr) {
+    plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s%s",
+ 	 (int) nfs_version, proto, host, errstr);
     if (again) {
 #ifdef HAVE_FS_NFS3
       if (nfs_version == NFS_VERSION3) {
-	plog(XLOG_INFO, "get_nfs_version trying a lower version");
 	nfs_version = NFS_VERSION;
 	again = 0;
+	plog(XLOG_INFO, "get_nfs_version trying a lower version: NFS(%d,%s)", (int) nfs_version, proto);
       }
       goto try_again;
 #endif /* HAVE_FS_NFS3 */
     }
-    plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s",
- 	 (int) nfs_version, proto, host);
     return 0;
   }
 
-  plog(XLOG_INFO, "get_nfs_version: returning (%d,%s) on host %s",
+  plog(XLOG_INFO, "get_nfs_version: returning NFS(%d,%s) on host %s",
        (int) nfs_version, proto, host);
   return nfs_version;
 }
 
 
+#if defined(HAVE_FS_AUTOFS) && defined(AUTOFS_PROG)
 /*
- * AUTOFS FUNCTIONS FOR SOCKETS:
- */
-#ifdef HAVE_FS_AUTOFS
-/*
- * Create the nfs service for amd
+ * Register the autofs service for amd
  */
 int
-create_autofs_service(int *soAUTOFSp, u_short *autofs_portp, SVCXPRT **autofs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp))
+register_autofs_service(char *autofs_conftype, void (*autofs_dispatch)(struct svc_req *rqstp, SVCXPRT *transp))
+{
+  int autofs_socket;
+  SVCXPRT *autofs_xprt = NULL;
+
+  autofs_socket = socket(AF_INET, SOCK_DGRAM, 0);
+
+  if (autofs_socket < 0 || bind_resv_port(autofs_socket, NULL) < 0) {
+    plog(XLOG_FATAL, "Can't create privileged autofs port (socket)");
+    return 1;
+  }
+  if ((autofs_xprt = svcudp_create(autofs_socket)) == NULL) {
+    plog(XLOG_FATAL, "Can't create autofs rpc/udp service");
+    return 2;
+  }
+  if (autofs_xprt->xp_port >= IPPORT_RESERVED) {
+    plog(XLOG_FATAL, "Can't create privileged autofs port");
+    return 1;
+  }
+  if (!svc_register(autofs_xprt, AUTOFS_PROG, AUTOFS_VERS, autofs_dispatch, 0)) {
+    plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)",
+	 (u_long) AUTOFS_PROG, (u_long) AUTOFS_VERS);
+    return 3;
+  }
+
+  return 0;			/* all is well */
+}
+
+
+int
+unregister_autofs_service(char *autofs_conftype)
 {
-  /* NOT IMPLEMENTED! */
-  return -1;
+  svc_unregister(AUTOFS_PROG, AUTOFS_VERS);
+  return 0;
 }
-#endif /* HAVE_FS_AUTOFS */
+#endif /* HAVE_FS_AUTOFS && AUTOFS_PROG */
diff --git a/contrib/amd/conf/trap/trap_default.h b/contrib/amd/conf/trap/trap_default.h
index a132b0e..edf22e2 100644
--- a/contrib/amd/conf/trap/trap_default.h
+++ b/contrib/amd/conf/trap/trap_default.h
@@ -1,2 +1,3 @@
+/* $FreeBSD: src/contrib/amd/conf/trap/trap_default.h,v 1.5 2012/11/17 01:48:41 svnexp Exp $ */
 /* $srcdir/conf/trap/trap_default.h */
 #define MOUNT_TRAP(type, mnt, flags, mnt_data) mount(type, mnt->mnt_dir, flags, mnt_data)
diff --git a/contrib/amd/conf/umount/umount_bsd44.c b/contrib/amd/conf/umount/umount_bsd44.c
index 1c4380e..d05944d 100644
--- a/contrib/amd/conf/umount/umount_bsd44.c
+++ b/contrib/amd/conf/umount/umount_bsd44.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: umount_bsd44.c,v 1.2 1999/01/10 21:54:22 ezk Exp $
+ * File: am-utils/conf/umount/umount_bsd44.c
  *
  */
 
@@ -54,12 +53,12 @@
 
 
 int
-umount_fs(char *fs_name, const char *mnttabname)
+umount_fs(char *mntdir, const char *mnttabname, u_int unmount_flags)
 {
   int error;
 
 eintr:
-  error = unmount(fs_name, 0);
+  error = unmount(mntdir, 0);
   if (error < 0)
     error = errno;
 
@@ -67,23 +66,55 @@ eintr:
   case EINVAL:
   case ENOTBLK:
   case ENOENT:
-    plog(XLOG_WARNING, "unmount: %s is not mounted", fs_name);
+    plog(XLOG_WARNING, "unmount: %s is not mounted", mntdir);
     error = 0;			/* Not really an error */
     break;
 
   case EINTR:
-#ifdef DEBUG
     /* not sure why this happens, but it does.  ask kirk one day... */
-    dlog("%s: unmount: %m", fs_name);
-#endif /* DEBUG */
+    dlog("%s: unmount: %m", mntdir);
     goto eintr;
 
-#ifdef DEBUG
+#ifdef MNT2_GEN_OPT_FORCE
+  case EBUSY:
+  case EIO:
+  case ESTALE:
+    /* caller determines if forced unmounts should be used */
+    if (unmount_flags & AMU_UMOUNT_FORCE) {
+      error = umount2_fs(mntdir, unmount_flags);
+      if (error < 0)
+	error = errno;
+      else
+	return error;
+    }
+    /* fallthrough */
+#endif /* MNT2_GEN_OPT_FORCE */
+
   default:
-    dlog("%s: unmount: %m", fs_name);
+    dlog("%s: unmount: %m", mntdir);
     break;
-#endif /* DEBUG */
   }
 
   return error;
 }
+
+
+#ifdef MNT2_GEN_OPT_FORCE
+/* force unmount, no questions asked, without touching mnttab file */
+int
+umount2_fs(const char *mntdir, u_int unmount_flags)
+{
+  int error = 0;
+  if (unmount_flags & AMU_UMOUNT_FORCE) {
+    plog(XLOG_INFO, "umount2_fs: trying unmount/forced on %s", mntdir);
+    error = unmount(mntdir, MNT2_GEN_OPT_FORCE);
+    if (error < 0 && (errno == EINVAL || errno == ENOENT))
+      error = 0;		/* ignore EINVAL/ENOENT */
+    if (error < 0)
+      plog(XLOG_WARNING, "%s: unmount/force: %m", mntdir);
+    else
+      dlog("%s: unmount/force: OK", mntdir);
+  }
+  return error;
+}
+#endif /* MNT2_GEN_OPT_FORCE */
diff --git a/contrib/amd/doc/am-utils.texi b/contrib/amd/doc/am-utils.texi
index 12bda8f..1cc46b6 100644
--- a/contrib/amd/doc/am-utils.texi
+++ b/contrib/amd/doc/am-utils.texi
@@ -1,6 +1,6 @@
 \input texinfo          @c -*-texinfo-*-
 @c
-@c Copyright (c) 1997-1999 Erez Zadok
+@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.
@@ -36,20 +36,20 @@
 @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      %W% (Berkeley) %G%
 @c
-@c $Id: am-utils.texi,v 1.12 1999/09/30 21:01:39 ezk Exp $
+@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
+@settitle Am-utils (4.4BSD Automounter Utilities)
 @setchapternewpage odd
 
 @titlepage
@@ -60,7 +60,7 @@
 (Originally by Jan-Simon Pendry and Nick Williams)
 
 @page
-Copyright @copyright{} 1997-1999 Erez Zadok
+Copyright @copyright{} 1997-2006 Erez Zadok
 @*
 Copyright @copyright{} 1989 Jan-Simon Pendry
 @*
@@ -84,8 +84,28 @@ copyright notice and statement of permission are included.
 
 @c ################################################################
 @node Top, License, , (DIR)
-Am-utils - The 4.4BSD Automounter Tool Suite
-*********************************************
+
+@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
@@ -97,12 +117,13 @@ tools within Am-utils.
 * 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. 
+* 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.
@@ -111,7 +132,7 @@ tools within Am-utils.
 * 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
+* Acknowledgments & Trademarks:: Legal Notes.
 
 Indexes
 * Index::                    An item for each concept.
@@ -187,24 +208,24 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 THE POSSIBILITY OF SUCH DAMAGE.
 
 @c ################################################################
-@node Distrib, Intro, License, Top
+@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.cs.columbia.edu/~ezk/am-utils/}
+@url{http://www.am-utils.org/}
 @end example
 
 You can get the latest distribution version of @i{Am-utils} from
 @example
-@url{ftp://shekel.mcl.cs.columbia.edu/pub/am-utils/am-utils.tar.gz}
+@url{ftp://ftp.am-utils.org/pub/am-utils/am-utils.tar.gz}
 @end example
 
-Alpha and beta distributions are available in
+Additional alpha, beta, and release distributions are available in
 @example
-@url{ftp://shekel.mcl.cs.columbia.edu/pub/am-utils/}.
+@url{ftp://ftp.am-utils.org/pub/am-utils/}.
 @end example
 
 Revision 5.2 was part of the 4.3BSD Reno distribution.
@@ -212,31 +233,50 @@ 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 @uref{http://www.cs.columbia.edu/,Computer Science
-Department} of @uref{http://www.columbia.edu/,Columbia University}, as
-part of his @uref{http://www.cs.columbia.edu/~ezk/research/tp/thesis_proposal.html,PhD thesis work}. @xref{History}, for more details.
+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.cs.columbia.edu/~ezk/am-utils/BUGS.txt,bugs} file.
-Send all bug reports to @email{amd-dev@@majordomo.cs.columbia.edu}
-quoting the details of the release and your configuration.  These 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
+@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.cs.columbia.edu/~ezk/am-utils/AUTHORS.txt,authors
+the @uref{http://www.am-utils.org/docs/am-utils/AUTHORS.txt,authors
 file}.
 
-@unnumberedsec Mailing List
-@cindex Mailing list
+@unnumberedsec Mailing Lists
+@cindex Mailing lists
 
-There are two mailing lists for people interested in keeping up-to-date
+There are several mailing lists for people interested in keeping up-to-date
 with developments.
 
 @c ###############
@@ -244,15 +284,7 @@ with developments.
 @enumerate
 
 @item
-The older list, @samp{amd-workers} is for general "how to" questions and
-announcements.  To subscribe, send a note to
-@email{amd-workers-request@@majordomo.glue.umd.edu}.@footnote{Note that
-the older address, @email{amd-workers-request@@acl.lanl.gov}, is
-defunct.}  To post a message to this list, send mail to
-@email{amd-workers@@majordomo.glue.umd.edu}.
-
-@item
-The developers only list, @samp{amd-dev} is for
+The users mailing list, @samp{am-utils} is for
 
 @itemize @minus
 @item
@@ -265,24 +297,65 @@ discussions of new features for am-utils
 implementation and porting issues
 @end itemize
 
-To subscribe, send a note to @email{majordomo@@majordomo.cs.columbia.edu}
-with the single body text line @samp{subscribe amd-dev}.  To post a
-message to this list, send mail to
-@email{amd-dev@@majordomo.cs.columbia.edu}.  To avoid as much spam as
+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{amd-dev} are most suitable if they have the time
-and resources to test new and buggy 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, and of course,
-be very familiar with the complex code in the am-utils package.  In
-other words, subscribers on this list should be able to contribute
-meaningfully to the development of amd.
+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, Distrib, Top
+@node Intro, History, AddInfo, Top
 @unnumbered Introduction
 @cindex Introduction
 
@@ -316,8 +389,8 @@ numerous flavors of Unix.
 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.columbia.edu,Erez Zadok}), and available from
-@url{ftp://ftp.cs.columbia.edu/pub/amd/}.  The last such unofficial
+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
@@ -339,14 +412,23 @@ 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, Autofs support, 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.
+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
@@ -365,12 +447,12 @@ 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.
 
-@c @i{Amd} supports the notion of @dfn{replicated} filesystems by evaluating
-@c each member of a list of possible filesystem locations in parallel.
-@c @i{Amd} checks that each cached mapping remains valid.  Should a mapping be
-@c lost -- such as happens when a fileserver goes down -- @i{Amd} automatically
-@c selects a replacement should one be available.
-@c
+@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::
@@ -574,7 +656,11 @@ Option, -w}) or the @i{amd.conf} parameter @samp{dismount_interval}
 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}.
+@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
@@ -606,7 +692,8 @@ 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.
+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
@@ -630,9 +717,6 @@ 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.
-
-By default, fileserver state is not maintained for NFS/TCP mounts.  The
-remote fileserver is always assumed to be up.
 @c
 @c With a suitable combination of filesystem management and mount-maps,
 @c machines can be protected against most server downtime.  This can be
@@ -680,378 +764,6 @@ machines, as well as 32 bit and 64 bit architectures.  Furthermore, when
 readily portable to the same Operating System on all platforms on which
 it is available.
 
-The table below lists those platforms supported by the latest release.
-The listing is based on the standard output from GNU's
-@code{config.guess} script.  Since significant changes have been made to
-am-utils, not all systems listed here have been verified working for all
-features.
-
-@multitable {Auto-Configured System Name} {Config} {Compile} {Amd} {NFS3} {Shlib} {Hlfsd}
-@c @multitable @columnfractions .5 .1 .1 .1 .1 .1
-
-@item @b{Auto-Configured System Name}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab @b{Config} @tab @b{Compile} @tab @b{Amd} @tab @b{NFS3} @tab @b{Shlib} @tab @b{Hlfsd}
-
-@item @b{alpha-dec-osf2.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab ?     @tab no   @tab ?
-
-@item @b{alpha-dec-osf4.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{alphaev5-unknown-linux-gnu}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{alphaev5-unknown-linux-gnu-rh5.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{hppa1.0-hp-hpux11.00}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab no    @tab yes  @tab ?
-
-@item @b{hppa1.1-hp-hpux10.10}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab no   @tab ?
-
-@item @b{hppa1.1-hp-hpux10.20}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab no    @tab no   @tab ?
-
-@item @b{hppa1.1-hp-hpux9.01}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{hppa1.1-hp-hpux9.05}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{hppa1.1-hp-hpux9.07}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{hppa2.0w-hp-hpux11.00}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i386-pc-bsdi2.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab no   @tab ?
-
-@item @b{i386-pc-bsdi3.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab no   @tab ?
-
-@item @b{i386-pc-bsdi3.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab no   @tab ?
-
-@item @b{i386-pc-bsdi4.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-pc-bsdi4.0.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-pc-solaris2.5.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab yes
-
-@item @b{i386-pc-solaris2.6}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab yes
-
-@item @b{i386-pc-solaris2.7}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab yes
-
-@item @b{i386-unknown-freebsd2.1.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab ?    @tab ?
-
-@item @b{i386-unknown-freebsd2.2.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i386-unknown-freebsd2.2.6}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i386-unknown-freebsd2.2.7}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i386-unknown-freebsd2.2.8}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i386-unknown-freebsd3.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-freebsdelf3.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-freebsdelf3.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-freebsdelf3.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-freebsdelf3.3}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-freebsdelf4.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-netbsd1.2.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-netbsd1.3}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-netbsd1.3.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-netbsd1.3.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-netbsd1.3.3}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-netbsd1.4}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-openbsd2.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-openbsd2.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-openbsd2.3}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-openbsd2.4}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i386-unknown-openbsd2.5}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{i486-ncr-sysv4.3.03}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab ?    @tab yes   @tab yes  @tab ?
-
-@item @b{i486-pc-linux-gnu-rh6.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i486-pc-linux-gnulibc1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i486-pc-linux-gnulibc1-rh4.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i486-pc-linux-gnuoldld}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i586-pc-linux-gnu}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i586-pc-linux-gnu-rh5.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i586-pc-linux-gnu-rh6.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i586-pc-linux-gnu-rh6.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i586-pc-linux-gnulibc1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i586-pc-linux-gnulibc1-rh4.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-
-@item @b{i686-pc-linux-gnu}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i686-pc-linux-gnu-rh5.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i686-pc-linux-gnu-rh6.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i686-pc-linux-gnulibc}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{i686-pc-linux-gnulibc1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{m68k-hp-hpux9.00}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab ?    @tab ?
-
-@item @b{m68k-sun-sunos4.1.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab no   @tab ?
-
-@item @b{m68k-next-nextstep3}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab no   @tab ?
-
-@item @b{mips-dec-ultrix4.3}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab ?    @tab ?
-
-@item @b{mips-sgi-irix5.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab ?       @tab ?     @tab ?    @tab ?     @tab ?    @tab ?
-
-@item @b{mips-sgi-irix5.3}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{mips-sgi-irix6.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{mips-sgi-irix6.4}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{mips-sgi-irix6.5}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab ?    @tab yes   @tab yes  @tab ?
-
-@item @b{powerpc-ibm-aix4.1.5.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab no/broken @tab ?
-
-@item @b{powerpc-ibm-aix4.2.1.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab no/broken @tab ?
-
-@item @b{powerpc-ibm-aix4.3.1.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab ?    @tab yes   @tab ?    @tab ?
-
-@item @b{powerpc-unknown-linux-gnu}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{rs6000-ibm-aix3.2}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab ?    @tab ?
-
-@item @b{rs6000-ibm-aix3.2.5}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab ?    @tab ?
-
-@item @b{rs6000-ibm-aix4.1.4.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab no/broken @tab ?
-
-@item @b{rs6000-ibm-aix4.1.5.0}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab no/broken @tab ?
-
-@item @b{sparc-sun-solaris2.3}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{sparc-sun-solaris2.4}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{sparc-sun-solaris2.5}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab ?
-
-@item @b{sparc-sun-solaris2.5.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab yes
-
-@item @b{sparc-sun-solaris2.6}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab yes
-
-@item @b{sparc-sun-solaris2.7}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab yes   @tab yes  @tab yes
-
-@item @b{sparc-sun-sunos4.1.1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{sparc-sun-sunos4.1.3}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{sparc-sun-sunos4.1.3C}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{sparc-sun-sunos4.1.3_U1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{sparc-sun-sunos4.1.4}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{sparc-unknown-linux-gnulibc1}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@item @b{sparc-unknown-netbsd1.2E}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab ?     @tab ?    @tab ?
-
-@item @b{sparc-unknown-netbsd1.2G}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab ?     @tab ?    @tab ?
-
-@item @b{sparc64-unknown-linux-gnu}
-@c {Config}  {Compile}  {Amd}     {NFS V.3}  {Shlib}   {Hlfsd}
-@tab yes     @tab yes   @tab yes  @tab n/a   @tab yes  @tab ?
-
-@end multitable
-
 See the @file{INSTALL} in the distribution for more specific details on
 building and/or configuring for some systems.
 
@@ -1128,8 +840,10 @@ list of map types configured on your machine.
 * 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
@@ -1184,6 +898,7 @@ 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
@@ -1197,8 +912,10 @@ 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}).
+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
@@ -1239,9 +956,10 @@ $(YPTSDIR)/amd.home.time: $(ETCDIR)/amd.home
     fi
 @end example
 
-Here @code{$(YPTSDIR)} contains the time stamp files, and @code{$(YPDBDIR)} contains
-the dbm format NIS files.
+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
@@ -1252,6 +970,7 @@ 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
@@ -1262,7 +981,7 @@ 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 the key is @samp{jsp} and map name is
+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}.
 
@@ -1277,6 +996,7 @@ 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
@@ -1317,13 +1037,14 @@ Similarly, if the password file entry was
 /home/cc/sugar/mjh
 @end example
 
-the map entry used by @i{Amd} would be 
+the map entry used by @i{Amd} would be
 
 @example
 rfs:=/home/sugar;rhost:=sugar.cc;sublink:=jsp
 @end example
 
-@node Union maps, LDAP maps , Password maps, Map Types
+@c ----------------------------------------------------------------
+@node Union maps, LDAP maps, Password maps, Map Types
 @comment  node-name,  next,  previous,  up
 @subsection Union maps
 @cindex Union file maps
@@ -1338,7 +1059,8 @@ 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.
 
-@node LDAP maps, , Union maps, Map Types
+@c ----------------------------------------------------------------
+@node LDAP maps, Executable maps, Union maps, Map Types
 @comment  node-name,  next,  previous,  up
 @subsection LDAP maps
 @cindex LDAP maps
@@ -1378,8 +1100,8 @@ dn: cn=amdmap amd.home[], CUCS
 cn          : amdmap amd.home[]
 objectClass : amdmap
 amdmapName  : amd.home
-amdmapKey   : 
-amdmapValue : 
+amdmapKey   :
+amdmapValue :
 
 dn: cn=amdmap amd.home[zing], CUCS
 cn          : amdmap amd.home[zing]
@@ -1389,8 +1111,42 @@ amdmapKey   : zing
 amdmapValue : -rhost:=shekel host==shekel host!=shekel;type:=nfs
 @end example
 
-@c subsection Gdbm
+@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
@@ -1474,10 +1230,17 @@ 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.  @dfn{location-selection}s are separated by the
-@samp{||} operator.  The effect of this operator is to prevent use of
+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
+its left were selected, whether or not any of them were successfully
 mounted (@pxref{Selectors}).@refill
 
 The location-selection, and singleton @dfn{location-list},
@@ -1629,7 +1392,7 @@ 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}.
 
-These are the selectors currently implemented.
+The following selectors are currently implemented.
 
 @menu
 * arch Selector Variable::
@@ -1637,6 +1400,7 @@ These are the selectors currently implemented.
 * byte Selector Variable::
 * cluster Selector Variable::
 * domain Selector Variable::
+* dollar Selector Variable::
 * host Selector Variable::
 * hostd Selector Variable::
 * karch Selector Variable::
@@ -1651,6 +1415,8 @@ These are the selectors currently implemented.
 * network Selector Variable::
 * path Selector Variable::
 * wire Selector Variable::
+* uid Selector Variable::
+* gid Selector Variable::
 
 * exists Selector Function::
 * false Selector Function::
@@ -1658,6 +1424,7 @@ These are the selectors currently implemented.
 * netgrpd Selector Function::
 * in_network Selector Function::
 * true Selector Function::
+* xhost Selector Function::
 @end menu
 
 @c ----------------------------------------------------------------
@@ -1671,7 +1438,8 @@ These are the selectors currently implemented.
 
 The machine architecture which was automatically determined at compile
 time.  The architecture type can be displayed by running the command
-@samp{amd -v}.  @xref{Supported Platforms}.@refill
+@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
@@ -1716,7 +1484,7 @@ filesystems.  @code{$@{cluster@}} defaults to the value of
 command line option.
 
 @c ----------------------------------------------------------------
-@node domain Selector Variable, host Selector Variable, cluster Selector Variable, Selectors
+@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
@@ -1728,7 +1496,22 @@ The local domain name as specified by the @code{-d} command line option.
 @xref{host Selector Variable}.
 
 @c ----------------------------------------------------------------
-@node host Selector Variable, hostd Selector Variable, domain Selector Variable, Selectors
+@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
@@ -1832,6 +1615,7 @@ 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>
@@ -1912,7 +1696,7 @@ The full pathname of the name being resolved.  For example
 @file{/home/foo} in the example above.
 
 @c ----------------------------------------------------------------
-@node wire Selector Variable, exists Selector Function, path Selector Variable, Selectors
+@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
@@ -1927,6 +1711,43 @@ 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
@@ -1937,7 +1758,7 @@ 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, wire Selector Variable, Selectors
+@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
@@ -1971,20 +1792,43 @@ Always evaluates to false.  @i{ARG} is ignored.
 @cindex Mount selector; netgrp
 @cindex Selector; netgrp
 
-If the current host as determined by the value of @code{$@{host@}}
-(e.g., short host name) is a member of the netgroup @i{ARG}, this
-selector evaluates to true.  Otherwise it evaluates to false.
+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:
+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
@@ -1995,14 +1839,15 @@ home/*  netgrp(ppp-hosts);type:=link;fs:=/local/$@{key@} \
 @cindex Mount selector; netgrpd
 @cindex Selector; netgrpd
 
-If the current host as determined by the value of @code{$@{hostd@}} is a
-member of the netgroup @i{ARG}, this selector evaluates to true.
-Otherwise it evaluates to false.
+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
-(@code{$@{hostd@}}) to match netgroup names, while the @samp{netgrp}
-function (@pxref{netgrp Selector Function}) uses short host names
-(@code{$@{host@}}).
+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
@@ -2014,9 +1859,18 @@ function (@pxref{netgrp Selector Function}) uses short host names
 @cindex Mount selector; in_network
 @cindex Selector; in_network
 
-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.  Otherwise it evaluates to false.
+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
@@ -2031,7 +1885,7 @@ opt in_network(foo-net.site.com);rhost:=serv1;rfs:=/opt \
 @end example
 
 @c ----------------------------------------------------------------
-@node true Selector Function, , in_network Selector Function, Selectors
+@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
@@ -2042,6 +1896,22 @@ opt in_network(foo-net.site.com);rhost:=serv1;rfs:=/opt \
 
 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
@@ -2241,6 +2111,13 @@ UID 0, and GID 0.  Useful for CD-ROMs formatted as ISO-9660.
 @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
@@ -2260,6 +2137,13 @@ Set ID of filesystem.
 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.
@@ -2270,6 +2154,24 @@ Use BSD directory group-id semantics.
 @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.
@@ -2316,10 +2218,23 @@ ISO-9660.
 @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
@@ -2338,6 +2253,15 @@ Don't allow set-uid or set-gid executables on this filesystem.
 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.
@@ -2354,6 +2278,15 @@ Set the NFS port to @var{n}.
 @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"}).
@@ -2400,6 +2333,10 @@ NFS/UDP through a gateway or a slow link.
 @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.
@@ -2414,7 +2351,7 @@ Allow set-uid programs on this mount.
 
 @item symttl
 @cindex Mount flags; symttl
-Turn of the symbolic link cache time-to-live.
+Turn off the symbolic link cache time-to-live.
 
 @item sync
 @cindex Mount flags; sync
@@ -2429,9 +2366,16 @@ support TCP/IP mounts.
 @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).
+Use NFS protocol version number @var{n} (can be 2 or 3).
 
 @item wsize=@var{n}
 @cindex Mount flags; wsize
@@ -2447,8 +2391,10 @@ passed to the kernel.
 
 @item nounmount
 @cindex Mount flags; nounmount
-Configures the mount so that its time-to-live will
-never expire.  This is also the default for some filesystem types.
+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:
 
@@ -2456,21 +2402,74 @@ never expire.  This is also the default for some filesystem types.
 @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 less than zero,
-no pings are sent and the host is assumed to be always
-up.  By default, pings are not sent for an NFS/TCP mount.
+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, by which the mount's
-time-to-live is extended after an unmount attempt
-has failed.  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.
+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
 
@@ -2557,7 +2556,7 @@ 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 nodaemon} on the command line.
+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.
@@ -2583,13 +2582,14 @@ exists.
 * -w Option::   Wait interval after failed unmount.
 * -x Option::   Log options.
 * -y Option::   NIS domain.
-* -C-Option::   Cluster name.
-* -D-Option::   Debug flags.
+* -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.
+* -O Option::   Operating system name.
 * -S Option::   Lock executable pages in memory.
-* -T-Option::   Set tag for configuration file.
+* -T Option::   Set tag for configuration file.
 @end menu
 
 @c ----------------------------------------------------------------
@@ -2777,7 +2777,7 @@ 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 nodaemon} debug flag, this
+If @i{Amd} is started with the @code{-D daemon} debug flag, this
 option is ignored.
 
 @c ----------------------------------------------------------------
@@ -2828,7 +2828,7 @@ 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, 
+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).
@@ -2941,7 +2941,7 @@ 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, -C-Option, -x Option, Amd Command Line Options
+@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
@@ -2956,7 +2956,22 @@ immediately attempts to bind to a server for this domain.
 @c is specified, and whenever required in a mount map.
 
 @c ----------------------------------------------------------------
-@node -C-Option, -D-Option, -y Option, Amd Command Line Options
+@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
@@ -2976,7 +2991,7 @@ amd -C `clustername` ...
 @end example
 
 @c ----------------------------------------------------------------
-@node -D-Option, -F Option, -C-Option, Amd Command Line Options
+@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
@@ -2996,37 +3011,44 @@ can be prefixed with @samp{no} to turn it off.
 
 @table @code
 @item all
-all options
+all ``reasonable'' options (currently trace|str|full|mem|info|readdir)
 @item amq
-register for amq
+do not register for amq
 @item daemon
-enter daemon mode
+do not enter daemon mode
 @item fork
-fork server
+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
+@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
+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
+@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
@@ -3044,7 +3066,7 @@ 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
+@node -H Option, -O Option, -F Option, Amd Command Line Options
 @comment  node-name,  next,  previous,  up
 @section @code{-H}
 @cindex Displaying brief help
@@ -3053,7 +3075,7 @@ option on the command line.
 Print a brief help and usage string.
 
 @c ----------------------------------------------------------------
-@node -O-Option, -S Option, -H Option, Amd Command Line Options
+@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
@@ -3066,14 +3088,16 @@ backward compatibility reasons.  For example, if the build in name is
 older maps which were written with the latter in mind.
 
 @c ----------------------------------------------------------------
-@node -S Option, -T-Option, -O-Option, Amd Command Line Options
+@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,
@@ -3082,12 +3106,12 @@ 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
+@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}
@@ -3142,7 +3166,6 @@ effect visible to the user.@refill
 * Union Filesystem::
 * Error Filesystem::
 * Top-level Filesystem::
-* Autofs Filesystem::           Sun's kernel-based automounter filesystem.
 * Root Filesystem::
 * Inheritance Filesystem::
 @end menu
@@ -3186,16 +3209,24 @@ 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.  @i{Amd} @dfn{does not} wait for
-a response; it notes that one of the locations needs retrying, but
-continues with any remaining locations.  When the file handle becomes
-available, and assuming none of the other locations was successfully
-mounted, @i{Amd} will retry the mount.  This mechanism allows several
-NFS filesystems to be mounted in parallel.
+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.}
-The first one which responds with a valid file handle will be used.
+@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:
@@ -3291,21 +3322,24 @@ The @dfn{nfsx} (@samp{type:=nfsx}) filesystem allows a group of filesystems to b
 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.
+difference for @samp{rfs}, as explained below.
 
 @noindent
-The following options must be specified:
+The following options should be specified:
 
 @table @code
 @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
+the remote fileserver.  The default value is taken from the local
 host name (@code{$@{host@}}) if no other value is specified.
 
 @item rfs
-as a list of filesystems to mount.  The list is in the form of a comma
-separated strings.
+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
@@ -3319,7 +3353,7 @@ pub  type:=nfsx;rhost:=gould;\
 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 parallel operation is used to determine the local mount points to
+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},
@@ -3379,6 +3413,11 @@ 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
@@ -3418,6 +3457,10 @@ 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!
@@ -3607,7 +3650,7 @@ Remote Virtual Disk (RVD) which has a programmatic interface via the
 commands @samp{rvdmount} and @samp{rvdunmount}.
 
 @noindent
-The following options must be specified:
+Both of the following options must be specified:
 
 @table @code
 @cindex mount, mount option
@@ -3616,29 +3659,47 @@ The following options must be specified:
 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
-the program which will perform the 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
+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 quote character.
+the single quote character.
 
-To run the program @samp{rvdmount} with a host name and filesystem as
-arguments would be specified by
-@samp{fs:=$@{autodir@}$@{path@};mount:="/etc/rvdmount rvdmount fserver
-$@{fs@}"}.
+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}.  This means
-that the split string must have at least two elements.  The program is
-directly executed by @i{Amd}, not via a shell.  This means that scripts
-must begin with a @code{#!} interpreter specification.
+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
@@ -3649,6 +3710,10 @@ 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
@@ -3726,7 +3791,7 @@ entries.  In this case, a list of possible targets can be given and
 
 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@}}, or if the target pathname listed in
+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
@@ -3859,8 +3924,19 @@ we are now stuck with it due to historical accident.
 
 @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.
+@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:
@@ -3909,6 +3985,18 @@ 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
@@ -3963,7 +4051,7 @@ directory''.  All other operations trivially succeed.
 The error filesystem is not directly accessible.
 
 @c ----------------------------------------------------------------
-@node Top-level Filesystem, Autofs Filesystem, Error Filesystem, Filesystem Types
+@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
@@ -3972,13 +4060,10 @@ The error filesystem is not directly accessible.
 
 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 and can
-also be passed in by using the @code{-M} option of the @dfn{Amq} command.
-That option is insecure, and is unavailable unless am-utils was
-configured with @samp{--with-amq-mount}.
+type are automatically generated from the command line arguments.
 
 @c ----------------------------------------------------------------
-@node Root Filesystem, Inheritance Filesystem, Autofs Filesystem, Filesystem Types
+@node Root Filesystem, Inheritance Filesystem, Top-level Filesystem, Filesystem Types
 @comment  node-name,  next,  previous,  up
 @section Root Filesystem (@samp{root})
 @cindex Root filesystem
@@ -3994,24 +4079,6 @@ undefined.
 The root filesystem is not directly accessible.
 
 @c ----------------------------------------------------------------
-@node Autofs Filesystem, Root Filesystem, Top-level Filesystem, Filesystem Types
-@comment  node-name,  next,  previous,  up
-@section Autofs Filesystem (@samp{autofs})
-@cindex Autofs filesystem
-@cindex autofs, filesystem type
-@cindex Filesystem type; autofs
-
-The @dfn{autofs} (@samp{type:=autofs}) filesystem uses Sun's kernel-based automounter
-supporting filesystem for @i{Amd}'s mount points.  Hence it is another
-type of top level filesystem.
-
-The autofs filesystem is not directly accessible from @i{Amd} maps, but
-only from the @file{amd.conf} file (@pxref{mount_type Parameter}).
-
-Note that Autofs support is still very early.  See the distribution file
-@file{README.autofs} for detail of what works and what does not.
-
-@c ----------------------------------------------------------------
 @node Inheritance Filesystem, , Root Filesystem, Filesystem Types
 @comment  node-name,  next,  previous,  up
 @section Inheritance Filesystem (@samp{inherit})
@@ -4128,15 +4195,43 @@ 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 browsable_dirs Parameter, map_options Parameter, Common Parameters, Common Parameters
+@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
@@ -4152,8 +4247,23 @@ 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_options Parameter, map_type Parameter, browsable_dirs Parameter, Common Parameters
+@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
@@ -4205,7 +4315,7 @@ 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, , mount_type Parameter, Common Parameters
+@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
@@ -4215,6 +4325,28 @@ an autofs server for those mount points.
 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
@@ -4224,52 +4356,150 @@ distributed maps in several locations as needed.
 The following parameters are applicable to the @samp{[global]} section only.
 
 @menu
-* arch Parameter::    
+* arch Parameter::
+* auto_attrcache Parameter::
 * auto_dir Parameter::
 * cache_duration Parameter::
-* cluster 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::   
+* 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::
-* os Parameter::      
-* osver Parameter::   
+* normalize_slashes Parameter::
+* os Parameter::
+* osver Parameter::
 * pid_file Parameter::
-* plock Parameter::   
+* plock Parameter::
 * portmap_program Parameter::
+* preferred_amq_port Parameter::
 * print_pid Parameter::
 * print_version Parameter::
 * restart_mounts Parameter::
-* selectors_on_default Parameter::
 * show_statfs_entries Parameter::
+* truncate_log Parameter::
 * unmount_on_exit Parameter::
+* use_tcpwrappers Parameter::
 * vendor Parameter::
 @end menu
 
 @c ----------------------------------------------------------------
-@node arch Parameter, auto_dir Parameter, Global Parameters, Global Parameters
+@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).  Allows you to override the
-value of the @i{arch} @i{Amd} variable.
+(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, arch Parameter, Global Parameters
+@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
@@ -4284,12 +4514,12 @@ sub-directories for its real mount points.
 @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 map entries remain
-in the cache.
+(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_options Parameter, cache_duration Parameter, Global Parameters
+@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
@@ -4297,8 +4527,18 @@ in the cache.
 (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, cluster Parameter, Global Parameters
+@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
@@ -4306,38 +4546,15 @@ in the cache.
 (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 @samp{mem} option, as well as all other options, 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 are:
-
-@table @samp
-@item all
-all options
-@item amq
-register for amq
-@item daemon
-enter daemon mode
-@item fork
-fork server
-@item full
-program trace
-@item mem
-trace memory allocations
-@item mtab
-use local @file{./mtab} file
-@item str
-debug string munging
-@item test
-full debug but no daemon
-@item trace
-trace RPC protocol and NFS mount arguments
-@end table
+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, full_os Parameter, debug_options Parameter, Global Parameters
+@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
@@ -4347,7 +4564,70 @@ trace RPC protocol and NFS mount arguments
 systems that have exceeded their cached times.
 
 @c ----------------------------------------------------------------
-@node full_os Parameter, fully_qualified_hosts Parameter, dismount_interval Parameter, Global Parameters
+@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
@@ -4400,8 +4680,9 @@ sun4m, sun4u, etc.)  Note that if not specified, @i{Amd} will use
 @subsection @t{ldap_base} Parameter
 @cindex ldap_base Parameter
 
-(type=string, default not set).  Specify the base name for
-LDAP.
+(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
@@ -4422,16 +4703,25 @@ should use to cache LDAP entries.
 entries in the cache.
 
 @c ----------------------------------------------------------------
-@node ldap_hostports Parameter, local_domain Parameter, ldap_cache_seconds Parameter, Global Parameters
+@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
-LDAP-specific values such as country and organization.
+(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, log_file Parameter, ldap_hostports Parameter, Global Parameters
+@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
@@ -4442,7 +4732,20 @@ the domain name is determined from the hostname, by removing the first
 component of the fully-qualified host name.
 
 @c ----------------------------------------------------------------
-@node log_file Parameter, log_options Parameter, local_domain Parameter, Global Parameters
+@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
@@ -4466,7 +4769,7 @@ 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, nfs_retransmit_counter Parameter, log_file Parameter, Global Parameters
+@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
@@ -4503,7 +4806,64 @@ warnings
 @end table
 
 @c ----------------------------------------------------------------
-@node nfs_retransmit_counter Parameter, nfs_retry_interval Parameter, log_options Parameter, Global Parameters
+@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
@@ -4511,10 +4871,48 @@ warnings
 (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}.  @xref{-t Option}.
+with @i{Amd} using either UDP or TCP mounts.  @xref{-t Option}.
 
 @c ----------------------------------------------------------------
-@node nfs_retry_interval Parameter, nis_domain Parameter, nfs_retransmit_counter Parameter, Global Parameters
+@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
@@ -4522,17 +4920,70 @@ with @i{Amd}.  @xref{-t Option}.
 (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 only).  This is the value that the kernel will use to
+(for UDP or TCP).  This is the value that the kernel will use to
 communicate with @i{Amd}.  @xref{-t Option}.
 
-Amd relies on the kernel RPC retransmit mechanism to trigger mount
+@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 nis_domain Parameter, normalize_hostnames Parameter, nfs_retry_interval Parameter, Global Parameters
+@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
@@ -4543,7 +4994,7 @@ 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, os Parameter, nis_domain Parameter, Global Parameters
+@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
@@ -4554,7 +5005,20 @@ relative to the host database before being used.  The effect is to
 translate aliases into ``official'' names.
 
 @c ----------------------------------------------------------------
-@node os Parameter, osver Parameter, normalize_hostnames Parameter, Global Parameters
+@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
@@ -4604,6 +5068,7 @@ This file is used only if the @samp{print_pid} option is on
 (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
@@ -4611,7 +5076,7 @@ cost of reserving the memory used by the @i{Amd} process (making it
 unavailable for other processes).
 
 @c ----------------------------------------------------------------
-@node portmap_program Parameter, print_pid Parameter, plock Parameter, Global Parameters
+@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
@@ -4627,7 +5092,21 @@ 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 print_pid Parameter, print_version Parameter, portmap_program Parameter, Global Parameters
+@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
@@ -4647,7 +5126,7 @@ will print its version information string, which includes some
 configuration and compilation values.
 
 @c ----------------------------------------------------------------
-@node restart_mounts Parameter, selectors_on_default Parameter, print_version Parameter, Global Parameters
+@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
@@ -4658,26 +5137,7 @@ systems are currently mounted.  Whenever one of these would have been
 auto-mounted, @i{Amd} inherits it.
 
 @c ----------------------------------------------------------------
-@node selectors_on_default Parameter, show_statfs_entries Parameter, restart_mounts Parameter, Global Parameters
-@comment  node-name,  next,  previous,  up
-@subsection @t{selectors_on_default} Parameter
-@cindex selectors_on_default Parameter
-
-(type=boolean, default=@samp{no}).  If @samp{yes}, then the @samp{/defaults} entry of
-maps will be looked for and any selectors processed 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
-
-@c ----------------------------------------------------------------
-@node show_statfs_entries Parameter, unmount_on_exit Parameter, selectors_on_default Parameter, Global Parameters
+@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
@@ -4688,19 +5148,65 @@ browsable will also show the number of entries (keys) they have when
 the @b{statfs}(2) system call).
 
 @c ----------------------------------------------------------------
-@node unmount_on_exit Parameter, vendor Parameter, show_statfs_entries Parameter, Global Parameters
+@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
+(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 vendor Parameter, , unmount_on_exit Parameter, Global Parameters
+@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
@@ -4721,7 +5227,7 @@ The following parameters are applicable only to regular map sections.
 
 @menu
 * map_name Parameter::
-* tag Parameter::     
+* tag Parameter::
 @end menu
 
 @c ----------------------------------------------------------------
@@ -4751,7 +5257,7 @@ command-line option matches that in the map section.
 @section amd.conf Examples
 @cindex amd.conf examples
 
-The following is the actual @code{amd.conf} file I use at the
+The following is the actual @code{amd.conf} file I used at the
 Computer Science Department of Columbia University.
 
 @example
@@ -4767,7 +5273,7 @@ log_file =               /var/log/amd
 log_options =            all
 #debug_options =         all
 plock =                  no
-selectors_on_default =   yes
+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.
@@ -4780,20 +5286,20 @@ fully_qualified_hosts =  no
 # DEFINE AN AMD MOUNT POINT
 [ /u ]
 map_name =               amd.u
-                         
-[ /proj ]                
+
+[ /proj ]
 map_name =               amd.proj
-                         
-[ /src ]                 
+
+[ /src ]
 map_name =               amd.src
-                         
-[ /misc ]                
+
+[ /misc ]
 map_name =               amd.misc
-                         
-[ /import ]              
+
+[ /import ]
 map_name =               amd.import
-                         
-[ /tftpboot/.amd ]       
+
+[ /tftpboot/.amd ]
 tag =                    tftpboot
 map_name =               amd.tftpboot
 @end example
@@ -4925,16 +5431,17 @@ mount point.
 * 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 -M-option::     Mounting a volume.
 * Amq -p option::     Getting Amd's process ID.
-* Amq -P-option::     Contacting alternate Amd processes.
+* 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::     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
 
@@ -5027,7 +5534,27 @@ also be synchronized with the map source by using the @samp{sync} option
 (@pxref{Automount Filesystem}).@refill
 
 @c ----------------------------------------------------------------
-@node Amq -l option, Amq -m option, Amq -h option, Controlling Amd
+@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
@@ -5041,18 +5568,7 @@ file handle on the log file, so that it can be rotated and compressed
 via daily cron jobs.
 
 @c ----------------------------------------------------------------
-@node Amq -h option, Amq -l 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 -m option, Amq -M-option, Amq -l option, Controlling Amd
+@node Amq -m option, Amq -p option, Amq -l option, Controlling Amd
 @comment  node-name,  next,  previous,  up
 @subsection @i{Amq} @code{-m} option
 
@@ -5094,32 +5610,9 @@ the mount point and server information is still being maintained
 by @i{Amd}.
 
 @c ----------------------------------------------------------------
-@node Amq -M-option, Amq -p option, Amq -m option, Controlling Amd
-@comment  node-name,  next,  previous,  up
-@subsection @i{Amq} @code{-M} option
-
-The @code{-M} option passes a new map entry to @i{Amd} and waits for it to
-be evaluated, possibly causing a mount.  For example, the following
-command would cause @samp{/home/toytown} on host @samp{toytown} to be
-mounted locally on @samp{/mnt/toytown}.
-
-@example
-amq -M '/mnt/toytown type:=nfs;rfs:=/home/toytown;rhost:=toytown;fs:=$@{key@}'
-@end example
-
-@i{Amd} applies some simple security checks before allowing this
-operation.  The check tests whether the incoming request is from a
-privileged UDP port on the local machine.  ``Permission denied'' is
-returned if the check fails.
-
-This option is very insecure as it is vulnerable to attacks such as IP
-Spoofing.  In other words, it is relatively easy for an attacker who
-really wants to, to make your @i{Amd} process mount any filesystem from
-the Internet!  Therefore, the @emph{complete} code which supports the
-@code{-M} option in @i{Amd} and @i{Amq} is turned off by default.  To turn
-it on, you have to reconfigure am-utils with @code{configure
---enable-amq-mount}.  Think twice before doing so, and use this option
-only if you absolutely need to.
+@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:
@@ -5131,8 +5624,10 @@ mount -t amd /vol hesiod.vol
 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
+@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
@@ -5146,7 +5641,7 @@ 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
+@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
@@ -5169,7 +5664,7 @@ kill `amq -p -P 300020`
 @end example
 
 @c ----------------------------------------------------------------
-@node Amq -s option, Amq -T option, Amq -P-option, Controlling Amd
+@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
@@ -5206,7 +5701,7 @@ should be increased.
 @end table
 
 @c ----------------------------------------------------------------
-@node Amq -T option, Amq -U-option, Amq -s option, Controlling Amd
+@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
@@ -5217,7 +5712,7 @@ 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
+@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
@@ -5228,7 +5723,7 @@ 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
+@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
@@ -5240,11 +5735,11 @@ 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 has hung -
-@c as if its keepalive timer had expired.
+@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, Other Amq options, Amq -u option, Controlling Amd
+@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
@@ -5253,7 +5748,17 @@ The @code{-v} option displays the version of @i{Amd} in a similar way to
 @i{Amd}'s @code{-v} option.
 
 @c ----------------------------------------------------------------
-@node Other Amq options, , Amq -v option, Controlling Amd
+@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
@@ -5285,7 +5790,7 @@ 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 host attributes::          Definable host attributes.
 * FSinfo filesystems::              Defining locally attached filesystems.
 * FSinfo static mounts::            Defining additional static mounts.
 * FSinfo automount definitions::
@@ -5306,7 +5811,7 @@ 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 amongst the set of hosts described in the
+@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
@@ -5487,14 +5992,14 @@ host @{
 The options that can be given as host attributes are shown below.
 
 @menu
-* netif Option:         FSinfo host netif:
-* config Option:        FSinfo host config:
-* arch Option:          FSinfo host arch:
-* os Option:            FSinfo host os:
-* cluster Option:       FSinfo host cluster:
+* 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 host netif, FSinfo host config, , FSinfo host attributes
+@node FSinfo netif Option, FSinfo config Option, , FSinfo host attributes
 @comment  node-name,  next,  previous,  up
 @subsection netif Option
 
@@ -5525,7 +6030,7 @@ netif ie0 @{
 netif ec0 @{ @}
 @end example
 
-@node FSinfo host config, FSinfo host arch, FSinfo host netif, FSinfo host attributes
+@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
@@ -5544,7 +6049,7 @@ config "ZEPHYR=true"
 
 This option is currently unsupported.
 
-@node FSinfo host arch, FSinfo host os, FSinfo host config, FSinfo host attributes
+@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
@@ -5559,7 +6064,7 @@ arch = hp300
 This is intended to be of use when building architecture specific
 mountmaps, however, the option is currently unsupported.
 
-@node FSinfo host os, FSinfo host cluster, FSinfo host arch, FSinfo host attributes
+@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
@@ -5575,7 +6080,7 @@ 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 host cluster, , FSinfo host os, FSinfo host attributes
+@node FSinfo cluster Option, , FSinfo os Option, FSinfo host attributes
 @comment  node-name,  next,  previous,  up
 @subsection cluster Option
 @cindex FSinfo cluster host attribute
@@ -5686,16 +6191,16 @@ fs /dev/dsk/5s0 @{
 @end example
 
 @menu
-* fstype Option:        FSinfo filesystems fstype:
-* opts Option:          FSinfo filesystems opts:
-* passno Option:        FSinfo filesystems passno:
-* freq Option:          FSinfo filesystems freq:
-* mount Option:         FSinfo filesystems mount:
-* dumpset Option:       FSinfo filesystems dumpset:
-* log Option:           FSinfo filesystems log:
+* 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 filesystems fstype, FSinfo filesystems opts, , FSinfo filesystems
+@node FSinfo fstype Option, FSinfo opts Option, , FSinfo filesystems
 @comment  node-name,  next,  previous,  up
 @subsection fstype Option
 @cindex FSinfo fstype filesystems option
@@ -5720,7 +6225,7 @@ Example:
 fstype = swap
 @end example
 
-@node FSinfo filesystems opts, FSinfo filesystems passno, FSinfo filesystems fstype, FSinfo filesystems
+@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
@@ -5733,7 +6238,7 @@ This defines any options that should be given to @b{mount}(8) in the
 opts = rw,nosuid,grpid
 @end example
 
-@node FSinfo filesystems passno, FSinfo filesystems freq, FSinfo filesystems opts, FSinfo filesystems
+@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
@@ -5748,7 +6253,7 @@ Example:
 passno = 1
 @end example
 
-@node FSinfo filesystems freq, FSinfo filesystems mount, FSinfo filesystems passno, FSinfo filesystems
+@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
@@ -5763,7 +6268,7 @@ Example:
 freq = 3
 @end example
 
-@node FSinfo filesystems mount, FSinfo filesystems dumpset, FSinfo filesystems freq, FSinfo filesystems
+@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
@@ -5833,7 +6338,7 @@ filesystem.@refill
 
 @end table
 
-@node FSinfo filesystems dumpset, FSinfo filesystems log, FSinfo filesystems mount, FSinfo filesystems
+@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
@@ -5842,7 +6347,7 @@ filesystem.@refill
 This provides support for Imperial College's local file backup tools and
 is not documented further here.
 
-@node FSinfo filesystems log, , FSinfo filesystems dumpset, FSinfo filesystems    
+@node FSinfo log Option, , FSinfo dumpset Option, FSinfo filesystems
 @comment  node-name,  next,  previous,  up
 @subsection log Option
 @cindex FSinfo log filesystems option
@@ -6197,7 +6702,7 @@ 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[=defn]}
+@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.
@@ -6338,8 +6843,8 @@ 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 filesystems fstype}.
+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
@@ -6403,7 +6908,7 @@ from anywhere.  It was designed and implemented by
 @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.cs.columbia.edu/~ezk/research/hlfsd/hlfsd.html,paper}
+@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
@@ -6424,8 +6929,8 @@ dump its internal table of user IDs and home directories to the file
 
 @menu
 * Introduction to Hlfsd::
-* Background to Mail Delivery::        
-* Using Hlfsd::       
+* Background to Mail Delivery::
+* Using Hlfsd::
 @end menu
 
 @c ================================================================
@@ -6787,9 +7292,9 @@ discussed.
 @cindex Hlfsd; using
 
 @menu
-* Controlling Hlfsd:: 
-* Hlfsd Options::     
-* Hlfsd Files::       
+* Controlling Hlfsd::
+* Hlfsd Options::
+* Hlfsd Files::
 @end menu
 
 @c ----------------------------------------------------------------
@@ -6847,6 +7352,16 @@ 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
@@ -6940,11 +7455,7 @@ 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.  A @samp{SIGUSR1} 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).
+description is available in the program source.
 
 @item -P @var{password-file}
 Read the user-name, user-id, and home directory information from the
@@ -6983,6 +7494,12 @@ 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
@@ -6998,24 +7515,25 @@ 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::       
+* 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::              
-* wait4amd::          
-* wait4amd2die::      
-* wire-test::         
+* mk-amd-map::
+* pawd::
+* redhat-ctl-amd::
+* wait4amd::
+* wait4amd2die::
+* wire-test::
 @end menu
 
 @c ----------------------------------------------------------------
@@ -7033,7 +7551,7 @@ then attempts to eject the removable device.
 @section amd.conf-sample
 @pindex amd.conf-sample
 
-A sample @i{Amd} configuration file. @xref{Amd Configuration File}. 
+A sample @i{Amd} configuration file. @xref{Amd Configuration File}.
 
 @c ----------------------------------------------------------------
 @node amd2ldif, amd2sun, amd.conf-sample, Assorted Tools
@@ -7107,8 +7625,8 @@ 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 newer Sun Automount map
-syntax, those used by autofs.
+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
@@ -7232,7 +7750,7 @@ 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. 
+script does.
 
 Use it as follows:
 
@@ -7270,7 +7788,7 @@ mk-amd-map @i{mapname}
 @end example
 
 @c ----------------------------------------------------------------
-@node pawd, wait4amd, mk-amd-map, Assorted Tools
+@node pawd, redhat-ctl-amd, mk-amd-map, Assorted Tools
 @comment  node-name,  next,  previous,  up
 @section pawd
 @pindex pawd
@@ -7288,7 +7806,20 @@ current working directory.  With any number of arguments, it will print
 the adjusted path of each one of the arguments.
 
 @c ----------------------------------------------------------------
-@node wait4amd, wait4amd2die, pawd, Assorted Tools
+@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
@@ -7720,8 +8251,8 @@ bsd          -opts:=rw,grpid,nosuid;arch==hp9000;rhost:=thpfs \
 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_on_default = yes} in the @file{amd.conf} file.
-@xref{selectors_on_default Parameter}.
+@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
@@ -7738,7 +8269,7 @@ file service performance.
 @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
+@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
@@ -8000,7 +8531,7 @@ The mount daemon refused to return a file handle for the requested filesystem.
 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. 
+@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.
@@ -8050,13 +8581,19 @@ XXX: This section needs to be updated
 @comment  node-name,  next,  previous,  up
 @unnumbered Acknowledgments & Trademarks
 
-Many thanks to the @email{amd-dev@@majordomo.cs.columbia.edu,Amd
-Developers} 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.cs.columbia.edu/~ezk/am-utils/AUTHORS.txt,authors} who
-have submitted patches.
+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.
@@ -8065,8 +8602,9 @@ 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 @email{amd-workers@@majordomo.glue.umd.edu,Amd Workers}
-mailing list members for many suggestions and bug reports to @i{Amd}.
+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
@@ -8140,4 +8678,9 @@ All other registered trademarks are owned by their respective owners.
 @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
+@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/contrib/amd/doc/stamp-vti b/contrib/amd/doc/stamp-vti
index 6032c23..41b19a3 100644
--- a/contrib/amd/doc/stamp-vti
+++ b/contrib/amd/doc/stamp-vti
@@ -1,3 +1,4 @@
-@set UPDATED 7 October 1999
-@set EDITION 6.0.3s1
-@set VERSION 6.0.3s1
+@set UPDATED 20 April 2006
+@set UPDATED-MONTH April 2006
+@set EDITION 6.1.5
+@set VERSION 6.1.5
diff --git a/contrib/amd/doc/texinfo.tex b/contrib/amd/doc/texinfo.tex
index 2b8a9cc..e758ced 100644
--- a/contrib/amd/doc/texinfo.tex
+++ b/contrib/amd/doc/texinfo.tex
@@ -3,10 +3,11 @@
 % Load plain if necessary, i.e., if running under initex.
 \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
 %
-\def\texinfoversion{1998-11-13}%
+\def\texinfoversion{2004-09-06.16}
 %
-% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98
-% Free Software Foundation, Inc.
+% 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
@@ -23,36 +24,40 @@
 % to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 % Boston, MA 02111-1307, USA.
 %
-% In other words, you are welcome to use, share and improve this program.
-% You are forbidden to forbid anyone else to use, share and improve
-% what you give them.   Help stamp out software-hoarding!
+% 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:
-%   ftp://ftp.gnu.org/pub/gnu/texinfo.tex
-%   /home/gd/gnu/doc/texinfo.tex on the GNU machines.
-%   (and all GNU mirrors, see http://www.gnu.org/order/ftp.html)
+%   http://www.gnu.org/software/texinfo/ (the Texinfo home page), or
 %   ftp://tug.org/tex/texinfo.tex
-%   ftp://ctan.org/macros/texinfo/texinfo.tex
-%   (and all CTAN mirrors, finger ctan@ctan.org for a list).
-% The texinfo.tex in the texinfo distribution itself could well be out
+%     (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 a precise test case in each bug report,
-% including a complete document with which we can reproduce the problem.
-% 
+%
+% 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 simple
-% manuals, however, you can get away with:
+% 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, to process the dvi file.
-% The extra runs of TeX get the cross-reference information correct.
+%   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]:}
 
@@ -62,8 +67,14 @@
 \everyjob{\message{[Texinfo version \texinfoversion]}%
   \catcode`+=\active \catcode`\_=\active}
 
-% Save some parts of plain tex whose names we will redefine.
+\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
@@ -73,77 +84,187 @@
 \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
 
-% We never want plain's outer \+ definition in Texinfo.
-% For @tex, we can use \tabalign.
-\let\+ = \relax
-
-
-\message{Basics,}
-\chardef\other=12
-
 % 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\putwordInfo\undefined     \gdef\putwordInfo{Info}\fi
-\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\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\putwordShortContents\undefined  \gdef\putwordShortContents{Short Contents}\fi
-\ifx\putwordTableofContents\undefined\gdef\putwordTableofContents{Table of Contents}\fi
+\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{}
 
-\hyphenation{ap-pen-dix}
-\hyphenation{mini-buf-fer mini-buf-fers}
-\hyphenation{eshell}
-\hyphenation{white-space}
+% 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\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.
+% 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}%
-\ifx\eTeXversion\undefined
-\def\loggingall{\tracingcommands2 \tracingstats2
-   \tracingpages1 \tracingoutput1 \tracinglostchars1
-   \tracingmacros2 \tracingparagraphs1 \tracingrestores1
-   \showboxbreadth\maxdimen\showboxdepth\maxdimen
-}%
-\else
-\def\loggingall{\tracingcommands3 \tracingstats2
-   \tracingpages1 \tracingoutput1 \tracinglostchars1
-   \tracingmacros2 \tracingparagraphs1 \tracingrestores1
-   \tracingscantokens1 \tracingassigns1 \tracingifs1
-   \tracinggroups1 \tracingnesting2
-   \showboxbreadth\maxdimen\showboxdepth\maxdimen
+\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
 }%
-\fi
+
+% 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
 %
@@ -185,6 +306,9 @@
     \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
@@ -231,7 +355,7 @@
       \egroup % \vbox from first cropmarks clause
       \fi
     }% end of \shipout\vbox
-  }% end of group with \turnoffactive
+  }% end of group with \normalturnoffactive
   \advancepageno
   \ifnum\outputpenalty>-20000 \else\dosupereject\fi
 }
@@ -264,143 +388,162 @@
 % the input line (except we remove a trailing comment).  #1 should be a
 % macro which expects an ordinary undelimited TeX argument.
 %
-\def\parsearg#1{%
-  \let\next = #1%
+\def\parsearg{\parseargusing{}}
+\def\parseargusing#1#2{%
+  \def\next{#2}%
   \begingroup
     \obeylines
-    \futurelet\temp\parseargx
-}
-
-% If the next token is an obeyed space (from an @example environment or
-% the like), remove it and recurse.  Otherwise, we're done.
-\def\parseargx{%
-  % \obeyedspace is defined far below, after the definition of \sepspaces.
-  \ifx\obeyedspace\temp
-    \expandafter\parseargdiscardspace
-  \else
-    \expandafter\parseargline
-  \fi
+    \spaceisspace
+    #1%
+    \parseargline\empty% Insert the \empty token, see \finishparsearg below.
 }
 
-% Remove a single space (as the delimiter token to the macro call).
-{\obeyspaces %
- \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
-
 {\obeylines %
   \gdef\parseargline#1^^M{%
     \endgroup % End of the group started in \parsearg.
-    %
-    % First remove any @c comment, then any @comment.
-    % Result of each macro is put in \toks0.
-    \argremovec #1\c\relax %
-    \expandafter\argremovecomment \the\toks0 \comment\relax %
-    %
-    % Call the caller's macro, saved as \next in \parsearg.
-    \expandafter\next\expandafter{\the\toks0}%
+    \argremovecomment #1\comment\ArgTerm%
   }%
 }
 
-% Since all \c{,omment} does is throw away the argument, we can let TeX
-% do that for us.  The \relax here is matched by the \relax in the call
-% in \parseargline; it could be more or less anything, its purpose is
-% just to delimit the argument to the \c.
-\def\argremovec#1\c#2\relax{\toks0 = {#1}}
-\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+% 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}
 
-% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+% 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
-% will have two active spaces as part of the argument with the
-% `itemize'.  Here we remove all active spaces from #1, and assign the
-% result to \toks0.
-%
-% This loses if there are any *other* active characters besides spaces
-% in the argument -- _ ^ +, for example -- since they get expanded.
-% Fortunately, Texinfo does not define any such commands.  (If it ever
-% does, the catcode of the characters in questionwill have to be changed
-% here.)  But this means we cannot call \removeactivespaces as part of
-% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
-% that \parsearg gets might well have any character at all in it.
-%
-\def\removeactivespaces#1{%
-  \begingroup
-    \ignoreactivespaces
-    \edef\temp{#1}%
-    \global\toks0 = \expandafter{\temp}%
-  \endgroup
+% 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
 }
 
-% Change the active space to expand to nothing.
+% 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.
 %
-\begingroup
+% 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\ignoreactivespaces{\obeyspaces\let =\empty}
-\endgroup
+  \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}
 
-%% These are used to keep @begin/@end levels from running away
-%% Call \inENV within environments (after a \begingroup)
-\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
-\def\ENVcheck{%
-\ifENV\errmessage{Still within an environment; press RETURN to continue}
-\endgroup\fi} % This is not perfect, but it should reduce lossage
+% 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.)
 
-% @begin foo  is the same as @foo, for now.
-\newhelp\EMsimple{Press RETURN to continue.}
 
-\outer\def\begin{\parsearg\beginxxx}
+% At runtime, environments start with this:
+\def\startenvironment#1{\begingroup\def\thisenv{#1}}
+% initialize
+\let\thisenv\empty
 
-\def\beginxxx #1{%
-\expandafter\ifx\csname #1\endcsname\relax
-{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
-\csname #1\endcsname\fi}
+% ... 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}}
 
-% @end foo executes the definition of \Efoo.
-%
-\def\end{\parsearg\endxxx}
-\def\endxxx #1{%
-  \removeactivespaces{#1}%
-  \edef\endthing{\the\toks0}%
-  %
-  \expandafter\ifx\csname E\endthing\endcsname\relax
-    \expandafter\ifx\csname \endthing\endcsname\relax
-      % There's no \foo, i.e., no ``environment'' foo.
-      \errhelp = \EMsimple
-      \errmessage{Undefined command `@end \endthing'}%
-    \else
-      \unmatchedenderror\endthing
-    \fi
+% Check whether we're in the right environment:
+\def\checkenv#1{%
+  \def\temp{#1}%
+  \ifx\thisenv\temp
   \else
-    % Everything's ok; the right environment has been started.
-    \csname E\endthing\endcsname
+    \badenverr
   \fi
 }
 
-% There is an environment #1, but it hasn't been started.  Give an error.
-%
-\def\unmatchedenderror#1{%
+% Evironment mismatch, #1 expected:
+\def\badenverr{%
   \errhelp = \EMsimple
-  \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+  \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
 }
 
-% Define the control sequence \E#1 to give an unmatched @end error.
+% @end foo executes the definition of \Efoo.
+% But first, it executes a specialized version of \checkenv
 %
-\def\defineunmatchedend#1{%
-  \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+\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.}
 
-% Single-spacing is done by various environments (specifically, in
-% \nonfillstart and \quotations).
-\newskip\singlespaceskip \singlespaceskip = 12.5pt
-\def\singlespace{%
-  % Why was this kern here?  It messes up equalizing space above and below
-  % environments.  --karl, 6may93
-  %{\advance \baselineskip by -\singlespaceskip
-  %\kern \baselineskip}%
-  \setleading \singlespaceskip
-}
 
 %% Simple single-character @ commands
 
@@ -421,16 +564,22 @@
 \let\{=\mylbrace
 \let\}=\myrbrace
 \begingroup
-  % Definitions to produce actual \{ & \} command in an index.
-  \catcode`\{ = 12 \catcode`\} = 12
+  % Definitions to produce \{ and \} commands for indices,
+  % and @{ and @} for the aux file.
+  \catcode`\{ = \other \catcode`\} = \other
   \catcode`\[ = 1 \catcode`\] = 2
-  \catcode`\@ = 0 \catcode`\\ = 12
-  @gdef@lbracecmd[\{]%
-  @gdef@rbracecmd[\}]%
-@endgroup
+  \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: @` @' @" @^ @~ @= @v @H.
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
 \let\, = \c
 \let\dotaccent = \.
 \def\ringaccent#1{{\accent23 #1}}
@@ -438,10 +587,12 @@
 \let\ubaraccent = \b
 \let\udotaccent = \d
 
-% Other special characters: @questiondown @exclamdown
-% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss.
+% 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}
@@ -454,6 +605,25 @@
   \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
@@ -472,6 +642,9 @@
 % @* forces a line break.
 \def\*{\hfil\break\hbox{}\ignorespaces}
 
+% @/ allows a line break.
+\let\/=\allowbreak
+
 % @. is an end-of-sentence period.
 \def\.{.\spacefactor=3000 }
 
@@ -494,47 +667,24 @@
 % therefore, no glue is inserted, and the space between the headline and
 % the text is small, which looks bad.
 %
-\def\group{\begingroup
-  \ifnum\catcode13=\active \else
+% 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
   %
-  % The \vtop we start below 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.  (See p.82 of
-  % the TeXbook.)  Thus, space below is not quite equal to space
-  % above.  But it's pretty close.
-  \def\Egroup{%
-    \egroup           % End the \vtop.
-    \endgroup         % End the \group.
-  }%
-  %
-  \vtop\bgroup
-    % We have to put a strut on the last line in case the @group is in
-    % the midst of an example, rather than completely enclosing it.
-    % Otherwise, the interline space between the last line of the group
-    % and the first line afterwards is too small.  But we can't put the
-    % strut in \Egroup, since there it would be on a line by itself.
-    % Hence this just inserts a strut at the beginning of each line.
-    \everypar = {\strut}%
-    %
-    % Since we have a strut on every line, we don't need any of TeX's
-    % normal interline spacing.
-    \offinterlineskip
-    %
-    % OK, but now we have to do something about blank
-    % lines in the input in @example-like environments, which normally
-    % just turn into \lisppar, which will insert no space now that we've
-    % turned off the interline space.  Simplest is to make them be an
-    % empty paragraph.
-    \ifx\par\lisppar
-      \edef\par{\leavevmode \par}%
-      %
-      % Reset ^^M's definition to new definition of \par.
-      \obeylines
-    \fi
-    %
+  \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
@@ -544,6 +694,32 @@
     \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 ...'.
 %
@@ -556,10 +732,8 @@ where each line of input produces a line of output.}
 
 \newdimen\mil  \mil=0.001in
 
-\def\need{\parsearg\needx}
-
 % Old definition--didn't work.
-%\def\needx #1{\par %
+%\parseargdef\need{\par %
 %% This method tries to make TeX break the page naturally
 %% if the depth of the box does not fit.
 %{\baselineskip=0pt%
@@ -567,70 +741,50 @@ where each line of input produces a line of output.}
 %\prevdepth=-1000pt
 %}}
 
-\def\needx#1{%
-  % Go into vertical mode, so we don't make a big box in the middle of a
+\parseargdef\need{%
+  % Ensure vertical mode, so we don't make a big box in the middle of a
   % paragraph.
   \par
   %
-  % Don't add any leading before our big empty box, but allow a page
-  % break, since the best break might be right here.
-  \allowbreak
-  \nointerlineskip
-  \vtop to #1\mil{\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
+  % 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
+% @br   forces paragraph break (and is undocumented).
 
 \let\br = \par
 
-% @dots{} output 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 minus 0.25fil
-    .\hss.\hss.%
-    \hskip 0pt plus 0.5fil minus 0.5fil
-  }%
-}
-
-% @enddots{} is an end-of-sentence ellipsis.
-% 
-\def\enddots{%
-  \leavevmode
-  \hbox to 2em{%
-    \hskip 0pt plus 0.25fil minus 0.25fil
-    .\hss.\hss.\hss.%
-    \hskip 0pt plus 0.5fil minus 0.5fil
-  }%
-  \spacefactor=3000
-}
-
-
-% @page    forces the start of a new page
+% @page forces the start of a new page.
 %
 \def\page{\par\vfill\supereject}
 
@@ -642,57 +796,127 @@ where each line of input produces a line of output.}
 \newskip\exdentamount
 
 % This defn is used inside fill environments such as @defun.
-\def\exdent{\parsearg\exdentyyy}
-\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}
 
 % This defn is used inside nofill environments such as @example.
-\def\nofillexdent{\parsearg\nofillexdentyyy}
-\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
-\leftline{\hskip\leftskip{\rm#1}}}}
+\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount
+  \leftline{\hskip\leftskip{\rm#1}}}}
 
-% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph.
-
-\def\inmargin#1{%
-\strut\vadjust{\nobreak\kern-\strutdepth
-  \vtop to \strutdepth{\baselineskip\strutdepth\vss
-  \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}}
+% @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}
-
-%\hbox{{\rm#1}}\hfil\break}}
+%
+\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.
-% Allow normal characters that  we make active in the argument (a file name).
-\def\include{\begingroup
-  \catcode`\\=12
-  \catcode`~=12
-  \catcode`^=12
-  \catcode`_=12
-  \catcode`|=12
-  \catcode`<=12
-  \catcode`>=12
-  \catcode`+=12
-  \parsearg\includezzz}
-% Restore active chars for included file.
-\def\includezzz#1{\endgroup\begingroup
-  % Read the included file in a group so nested @include's work.
+%
+\def\include{\parseargusing\filenamecatcodes\includezzz}
+\def\includezzz#1{%
+  \pushthisfilestack
   \def\thisfile{#1}%
-  \input\thisfile
-\endgroup}
+  {%
+    \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\thisfile{}
+\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}}%
+}
 
-% @center line   outputs that line, centered
+\def\popthisfilestack{\errthisfilestackempty}
+\def\errthisfilestackempty{\errmessage{Internal error:
+  the stack of filenames is empty.}}
+
+\def\thisfile{}
 
-\def\center{\parsearg\centerzzz}
-\def\centerzzz #1{{\advance\hsize by -\leftskip
-\advance\hsize by -\rightskip
-\centerline{#1}}}
+% @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
 
-\def\sp{\parsearg\spxxx}
-\def\spxxx #1{\vskip #1\baselineskip}
+\parseargdef\sp{\vskip #1\baselineskip}
 
 % @comment ...line which is ignored...
 % @c is the same as @comment
@@ -705,374 +929,175 @@ where each line of input produces a line of output.}
 
 \let\c=\comment
 
-% @paragraphindent  is defined for the Info formatting commands only.
-\let\paragraphindent=\comment
-
-% Prevent errors for section commands.
-% Used in @ignore and in failing conditionals.
-\def\ignoresections{%
-\let\chapter=\relax
-\let\unnumbered=\relax
-\let\top=\relax
-\let\unnumberedsec=\relax
-\let\unnumberedsection=\relax
-\let\unnumberedsubsec=\relax
-\let\unnumberedsubsection=\relax
-\let\unnumberedsubsubsec=\relax
-\let\unnumberedsubsubsection=\relax
-\let\section=\relax
-\let\subsec=\relax
-\let\subsubsec=\relax
-\let\subsection=\relax
-\let\subsubsection=\relax
-\let\appendix=\relax
-\let\appendixsec=\relax
-\let\appendixsection=\relax
-\let\appendixsubsec=\relax
-\let\appendixsubsection=\relax
-\let\appendixsubsubsec=\relax
-\let\appendixsubsubsection=\relax
-\let\contents=\relax
-\let\smallbook=\relax
-\let\titlepage=\relax
-}
-
-% Used in nested conditionals, where we have to parse the Texinfo source
-% and so want to turn off most commands, in case they are used
-% incorrectly.
-%
-\def\ignoremorecommands{%
-  \let\defcodeindex = \relax
-  \let\defcv = \relax
-  \let\deffn = \relax
-  \let\deffnx = \relax
-  \let\defindex = \relax
-  \let\defivar = \relax
-  \let\defmac = \relax
-  \let\defmethod = \relax
-  \let\defop = \relax
-  \let\defopt = \relax
-  \let\defspec = \relax
-  \let\deftp = \relax
-  \let\deftypefn = \relax
-  \let\deftypefun = \relax
-  \let\deftypevar = \relax
-  \let\deftypevr = \relax
-  \let\defun = \relax
-  \let\defvar = \relax
-  \let\defvr = \relax
-  \let\ref = \relax
-  \let\xref = \relax
-  \let\printindex = \relax
-  \let\pxref = \relax
-  \let\settitle = \relax
-  \let\setchapternewpage = \relax
-  \let\setchapterstyle = \relax
-  \let\everyheading = \relax
-  \let\evenheading = \relax
-  \let\oddheading = \relax
-  \let\everyfooting = \relax
-  \let\evenfooting = \relax
-  \let\oddfooting = \relax
-  \let\headings = \relax
-  \let\include = \relax
-  \let\lowersections = \relax
-  \let\down = \relax
-  \let\raisesections = \relax
-  \let\up = \relax
-  \let\set = \relax
-  \let\clear = \relax
-  \let\item = \relax
-}
-
-% Ignore @ignore ... @end ignore.
-%
-\def\ignore{\doignore{ignore}}
-
-% Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text.
+% @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\ifinfo{\doignore{ifinfo}}
-\def\ifhtml{\doignore{ifhtml}}
-\def\ifnottex{\doignore{ifnottex}}
-\def\html{\doignore{html}}
-\def\menu{\doignore{menu}}
-\def\direntry{\doignore{direntry}}
-
-% @dircategory CATEGORY  -- specify a category of the dir file
-% which this file should belong to.  Ignore this in TeX.
-\let\dircategory = \comment
-
-% Ignore text until a line `@end #1'.
+\def\asisword{asis} % no translation, these are keywords
+\def\noneword{none}
 %
-\def\doignore#1{\begingroup
-  % Don't complain about control sequences we have declared \outer.
-  \ignoresections
-  %
-  % Define a command to swallow text until we reach `@end #1'.
-  % This @ is a catcode 12 token (that is the normal catcode of @ in
-  % this texinfo.tex file).  We change the catcode of @ below to match.
-  \long\def\doignoretext##1@end #1{\enddoignore}%
-  %
-  % Make sure that spaces turn into tokens that match what \doignoretext wants.
-  \catcode32 = 10
-  %
-  % Ignore braces, too, so mismatched braces don't cause trouble.
-  \catcode`\{ = 9
-  \catcode`\} = 9
-  %
-  % We must not have @c interpreted as a control sequence.
-  \catcode`\@ = 12
-  %
-  % Make the letter c a comment character so that the rest of the line
-  % will be ignored. This way, the document can have (for example)
-  %   @c @end ifinfo
-  % and the @end ifinfo will be properly ignored.
-  % (We've just changed @ to catcode 12.)
-  \catcode`\c = 14
-  %
-  % And now expand that command.
-  \doignoretext
-}
-
-% What we do to finish off ignored text.
-%
-\def\enddoignore{\endgroup\ignorespaces}%
-
-\newif\ifwarnedobs\warnedobsfalse
-\def\obstexwarn{%
-  \ifwarnedobs\relax\else
-  % We need to warn folks that they may have trouble with TeX 3.0.
-  % This uses \immediate\write16 rather than \message to get newlines.
-    \immediate\write16{}
-    \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
-    \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
-    \immediate\write16{If you are running another version of TeX, relax.}
-    \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
-    \immediate\write16{  Then upgrade your TeX installation if you can.}
-    \immediate\write16{  (See ftp://ftp.gnu.org/pub/gnu/TeX.README.)}
-    \immediate\write16{If you are stuck with version 3.0, run the}
-    \immediate\write16{  script ``tex3patch'' from the Texinfo distribution}
-    \immediate\write16{  to use a workaround.}
-    \immediate\write16{}
-    \global\warnedobstrue
+\parseargdef\paragraphindent{%
+  \def\temp{#1}%
+  \ifx\temp\asisword
+  \else
+    \ifx\temp\noneword
+      \defaultparindent = 0pt
+    \else
+      \defaultparindent = #1em
     \fi
+  \fi
+  \parindent = \defaultparindent
 }
 
-% **In TeX 3.0, setting text in \nullfont hangs tex.  For a
-% workaround (which requires the file ``dummy.tfm'' to be installed),
-% uncomment the following line:
-%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+% @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
+}
 
-% Ignore text, except that we keep track of conditional commands for
-% purposes of nesting, up to an `@end #1' command.
+% @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.
 %
-\def\nestedignore#1{%
-  \obstexwarn
-  % We must actually expand the ignored text to look for the @end
-  % command, so that nested ignore constructs work.  Thus, we put the
-  % text into a \vbox and then do nothing with the result.  To minimize
-  % the change of memory overflow, we follow the approach outlined on
-  % page 401 of the TeXbook: make the current font be a dummy font.
-  %
-  \setbox0 = \vbox\bgroup
-    % Don't complain about control sequences we have declared \outer.
-    \ignoresections
-    %
-    % Define `@end #1' to end the box, which will in turn undefine the
-    % @end command again.
-    \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
-    %
-    % We are going to be parsing Texinfo commands.  Most cause no
-    % trouble when they are used incorrectly, but some commands do
-    % complicated argument parsing or otherwise get confused, so we
-    % undefine them.
-    %
-    % We can't do anything about stray @-signs, unfortunately;
-    % they'll produce `undefined control sequence' errors.
-    \ignoremorecommands
-    %
-    % Set the current font to be \nullfont, a TeX primitive, and define
-    % all the font commands to also use \nullfont.  We don't use
-    % dummy.tfm, as suggested in the TeXbook, because not all sites
-    % might have that installed.  Therefore, math mode will still
-    % produce output, but that should be an extremely small amount of
-    % stuff compared to the main input.
-    %
-    \nullfont
-    \let\tenrm = \nullfont  \let\tenit = \nullfont  \let\tensl = \nullfont
-    \let\tenbf = \nullfont  \let\tentt = \nullfont  \let\smallcaps = \nullfont
-    \let\tensf = \nullfont
-    % Similarly for index fonts (mostly for their use in
-    % smallexample)
-    \let\indrm = \nullfont  \let\indit = \nullfont  \let\indsl = \nullfont
-    \let\indbf = \nullfont  \let\indtt = \nullfont  \let\indsc = \nullfont
-    \let\indsf = \nullfont
-    %
-    % Don't complain when characters are missing from the fonts.
-    \tracinglostchars = 0
-    %
-    % Don't bother to do space factor calculations.
-    \frenchspacing
-    %
-    % Don't report underfull hboxes.
-    \hbadness = 10000
-    %
-    % Do minimal line-breaking.
-    \pretolerance = 10000
-    %
-    % Do not execute instructions in @tex
-    \def\tex{\doignore{tex}}%
-    % Do not execute macro definitions.
-    % `c' is a comment character, so the word `macro' will get cut off.
-    \def\macro{\doignore{ma}}%
+% 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
 }
 
-% @set VAR sets the variable VAR to an empty value.
-% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+% Here is how we actually suppress indentation.  Redefine \everypar to
+% \kern backwards by \parindent, and then reset itself to empty.
 %
-% 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.  Make sure the catcode of space is correct to avoid
-% losing inside @example, for instance.
+% We also make \indent itself not actually do anything until the next
+% paragraph.
 %
-\def\set{\begingroup\catcode` =10
-  \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR.
-  \parsearg\setxxx}
-\def\setxxx#1{\setyyy#1 \endsetyyy}
-\def\setyyy#1 #2\endsetyyy{%
-  \def\temp{#2}%
-  \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
-  \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
-  \fi
-  \endgroup
+\gdef\dosuppressfirstparagraphindent{%
+  \gdef\indent{%
+    \restorefirstparagraphindent
+    \indent
+  }%
+  \gdef\noindent{%
+    \restorefirstparagraphindent
+    \noindent
+  }%
+  \global\everypar = {%
+    \kern -\parindent
+    \restorefirstparagraphindent
+  }%
 }
-% Can't use \xdef to pre-expand #2 and save some time, since \temp or
-% \next or other control sequences that we've defined might get us into
-% an infinite loop. Consider `@set foo @cite{bar}'.
-\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}}
 
-% @clear VAR clears (i.e., unsets) the variable VAR.
+\gdef\restorefirstparagraphindent{%
+  \global \let \indent = \ptexindent
+  \global \let \noindent = \ptexnoindent
+  \global \everypar = {}%
+}
+
+
+% @asis just yields its argument.  Used with @table, for example.
 %
-\def\clear{\parsearg\clearxxx}
-\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+\def\asis#1{#1}
 
-% @value{foo} gets the text saved in variable foo.
+% @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`\_ = \active
-  %
-  % We might end up with active _ or - characters in the argument if
-  % we're called from @code, as @code{@value{foo-bar_}}.  So \let any
-  % such active characters to their normal equivalents.
-  \gdef\value{\begingroup
-    \catcode`\-=12 \catcode`\_=12
-    \indexbreaks \let_\normalunderscore
-    \valuexxx}
-}
-\def\valuexxx#1{\expandablevalue{#1}\endgroup}
-
-% We have this subroutine so that we can handle at least some @value's
-% properly in indexes (we \let\value to this in \indexdummies).  Ones
-% whose names contain - or _ still won't work, but we can't do anything
-% about that.  The command has to be fully expandable, 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'']}%
-  \else
-    \csname SET#1\endcsname
-  \fi
+  \catcode\underChar = \active
+  \gdef\mathunderscore{%
+    \catcode\underChar=\active
+    \def_{\ifnum\fam=\slfam \_\else\sb\fi}%
+  }
 }
-
-% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
-% with @set.
+% 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 @\.
 %
-\def\ifset{\parsearg\ifsetxxx}
-\def\ifsetxxx #1{%
-  \expandafter\ifx\csname SET#1\endcsname\relax
-    \expandafter\ifsetfail
-  \else
-    \expandafter\ifsetsucceed
-  \fi
+% 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
+  }
 }
-\def\ifsetsucceed{\conditionalsucceed{ifset}}
-\def\ifsetfail{\nestedignore{ifset}}
-\defineunmatchedend{ifset}
 
-% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
-% defined with @set, or has been undefined with @clear.
+% @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\ifclear{\parsearg\ifclearxxx}
-\def\ifclearxxx #1{%
-  \expandafter\ifx\csname SET#1\endcsname\relax
-    \expandafter\ifclearsucceed
-  \else
-    \expandafter\ifclearfail
-  \fi
-}
-\def\ifclearsucceed{\conditionalsucceed{ifclear}}
-\def\ifclearfail{\nestedignore{ifclear}}
-\defineunmatchedend{ifclear}
-
-% @iftex, @ifnothtml, @ifnotinfo always succeed; we read the text
-% following, through the first @end iftex (etc.).  Make `@end iftex'
-% (etc.) valid only after an @iftex.
-%
-\def\iftex{\conditionalsucceed{iftex}}
-\def\ifnothtml{\conditionalsucceed{ifnothtml}}
-\def\ifnotinfo{\conditionalsucceed{ifnotinfo}}
-\defineunmatchedend{iftex}
-\defineunmatchedend{ifnothtml}
-\defineunmatchedend{ifnotinfo}
-
-% We can't just want to start a group at @iftex (for example) and end it
-% at @end iftex, since then @set commands inside the conditional have no
-% effect (they'd get reverted at the end of the group).  So we must
-% define \Eiftex to redefine itself to be its previous value.  (We can't
-% just define it to fail again with an ``unmatched end'' error, since
-% the @ifset might be nested.)
-%
-\def\conditionalsucceed#1{%
-  \edef\temp{%
-    % Remember the current value of \E#1.
-    \let\nece{prevE#1} = \nece{E#1}%
-    %
-    % At the `@end #1', redefine \E#1 to be its previous value.
-    \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+\def\dots{%
+  \leavevmode
+  \hbox to 1.5em{%
+    \hskip 0pt plus 0.25fil
+    .\hfil.\hfil.%
+    \hskip 0pt plus 0.5fil
   }%
-  \temp
 }
 
-% We need to expand lots of \csname's, but we don't want to expand the
-% control sequences after we've constructed them.
-%
-\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
-
-% @asis just yields its argument.  Used with @table, for example.
+% @enddots{} is an end-of-sentence ellipsis.
 %
-\def\asis#1{#1}
+\def\enddots{%
+  \dots
+  \spacefactor=3000
+}
 
-% @math means output in math mode.
-% We don't use $'s directly in the definition of \math because control
-% sequences like \math are expanded when the toc file is written.  Then,
-% we read the toc file back, the $'s will be normal characters (as they
-% should be, according to the definition of Texinfo).  So we must use a
-% control sequence to switch into and out of math mode.
-%
-% This isn't quite enough for @math to work properly in indices, but it
-% seems unlikely it will ever be needed there.
+% @comma{} is so commas can be inserted into text without messing up
+% Texinfo's parsing.
 %
-\let\implicitmath = $
-\def\math#1{\implicitmath #1\implicitmath}
-
-% @bullet and @minus need the same treatment as @math, just above.
-\def\bullet{\implicitmath\ptexbullet\implicitmath}
-\def\minus{\implicitmath-\implicitmath}
+\let\comma = ,
 
 % @refill is a no-op.
 \let\refill=\relax
@@ -1088,26 +1113,26 @@ where each line of input produces a line of output.}
 % 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{%
-   \iflinks 
-     \readauxfile
+   \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
-   \fixbackslash  % Turn off hack to swallow `\input texinfo'.
-   \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+   \let\setfilename=\comment % Ignore extra @setfilename cmds.
    %
    % If texinfo.cnf is present on the system, read it.
    % Useful for site-wide @afourpaper, etc.
-   % Just to be on the safe side, close the input stream before the \input.
    \openin 1 texinfo.cnf
-   \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi
-   \closein1
-   \temp
+   \ifeof 1 \else \input texinfo.cnf \fi
+   \closein 1
    %
    \comment % Ignore the actual filename.
 }
 
 % Called from \setfilename.
-% 
+%
 \def\openindices{%
   \newindex{cp}%
   \newcodeindex{fn}%
@@ -1121,21 +1146,298 @@ where each line of input produces a line of output.}
 \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,}
-% Font-change commands.
+
+% 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 analogous to plain's \rm, etc.
+% So we set up a \sf.
 \newfam\sffam
-\def\sf{\fam=\sffam \tensf}
+\def\sf{\fam=\sffam \setfontstyle{sf}}
 \let\li = \sf % Sometimes we call it \li, not \sf.
 
-% We don't need math for this one.
-\def\ttsl{\tenttsl}
+% We don't need math for this font style.
+\def\ttsl{\setfontstyle{ttsl}}
 
-% Use Computer Modern fonts at \magstephalf (11pt).
-\newcount\mainmagstep
-\mainmagstep=\magstephalf
+% 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').
@@ -1165,17 +1467,18 @@ where each line of input produces a line of output.}
 \def\scshape{csc}
 \def\scbshape{csc}
 
+% Text fonts (11.2pt, magstep1).
+\newcount\mainmagstep
 \ifx\bigger\relax
-\let\mainmagstep=\magstep1
-\setfont\textrm\rmshape{12}{1000}
-\setfont\texttt\ttshape{12}{1000}
+  % not really supported.
+  \mainmagstep=\magstep1
+  \setfont\textrm\rmshape{12}{1000}
+  \setfont\texttt\ttshape{12}{1000}
 \else
-\setfont\textrm\rmshape{10}{\mainmagstep}
-\setfont\texttt\ttshape{10}{\mainmagstep}
+  \mainmagstep=\magstephalf
+  \setfont\textrm\rmshape{10}{\mainmagstep}
+  \setfont\texttt\ttshape{10}{\mainmagstep}
 \fi
-% Instead of cmb10, you many want to use cmbx10.
-% cmbx10 is a prettier font on its own, but cmb10
-% looks better when embedded in a line with cmr10.
 \setfont\textbf\bfshape{10}{\mainmagstep}
 \setfont\textit\itshape{10}{\mainmagstep}
 \setfont\textsl\slshape{10}{\mainmagstep}
@@ -1185,30 +1488,37 @@ where each line of input produces a line of output.}
 \font\texti=cmmi10 scaled \mainmagstep
 \font\textsy=cmsy10 scaled \mainmagstep
 
-% A few fonts for @defun, etc.
-\setfont\defbf\bxshape{10}{\magstep1} %was 1314
+% A few fonts for @defun names and args.
+\setfont\defbf\bfshape{10}{\magstep1}
 \setfont\deftt\ttshape{10}{\magstep1}
-\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
-
-% Fonts for indices and small examples (9pt).
-% We actually use the slanted font rather than the italic,
-% because texinfo normally uses the slanted fonts for that.
-% Do not make many font distinctions in general in the index, since they
-% aren't very useful.
-\setfont\ninett\ttshape{9}{1000}
-\setfont\ninettsl\ttslshape{10}{900}
-\setfont\indrm\rmshape{9}{1000}
-\setfont\indit\itshape{9}{1000}
-\setfont\indsl\slshape{9}{1000}
-\let\indtt=\ninett
-\let\indttsl=\ninettsl
-\let\indsf=\indrm
-\let\indbf=\indrm
-\setfont\indsc\scshape{10}{900}
-\font\indi=cmmi9
-\font\indsy=cmsy9
-
-% Fonts for title page:
+\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}
@@ -1220,6 +1530,7 @@ where each line of input produces a line of output.}
 \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}
@@ -1245,20 +1556,6 @@ where each line of input produces a line of output.}
 \font\seci=cmmi12 scaled \magstep1
 \font\secsy=cmsy10 scaled \magstep2
 
-% \setfont\ssecrm\bxshape{10}{\magstep1}    % This size an font looked bad.
-% \setfont\ssecit\itshape{10}{\magstep1}    % The letters were too crowded.
-% \setfont\ssecsl\slshape{10}{\magstep1}
-% \setfont\ssectt\ttshape{10}{\magstep1}
-% \setfont\ssecsf\sfshape{10}{\magstep1}
-
-%\setfont\ssecrm\bfshape{10}{1315}      % Note the use of cmb rather than cmbx.
-%\setfont\ssecit\itshape{10}{1315}      % Also, the size is a little larger than
-%\setfont\ssecsl\slshape{10}{1315}      % being scaled magstep1.
-%\setfont\ssectt\ttshape{10}{1315}
-%\setfont\ssecsf\sfshape{10}{1315}
-
-%\let\ssecbf=\ssecrm
-
 % Subsection fonts (13.15pt).
 \setfont\ssecrm\rmbshape{12}{\magstephalf}
 \setfont\ssecit\itbshape{10}{1315}
@@ -1267,68 +1564,124 @@ where each line of input produces a line of output.}
 \setfont\ssecttsl\ttslshape{10}{1315}
 \setfont\ssecsf\sfbshape{12}{\magstephalf}
 \let\ssecbf\ssecrm
-\setfont\ssecsc\scbshape{10}{\magstep1}
+\setfont\ssecsc\scbshape{10}{1315}
 \font\sseci=cmmi12 scaled \magstephalf
 \font\ssecsy=cmsy10 scaled 1315
-% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
-% but that is not a standard magnification.
+
+% 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, we
-% don't bother to reset \scriptfont and \scriptscriptfont (which would
-% also require loading a lot more fonts).
+% 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
+  \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 so that font changes will continue to work
-% in math mode, where it is the current \fam that is relevant in most
-% cases, not the current font.  Plain TeX does \def\bf{\fam=\bffam
-% \tenbf}, for example.  By redefining \tenbf, we obviate the need to
-% redefine \bf itself.
+% 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
-  \resetmathfonts}
+  \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
+  \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
+  \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+  \let\tenttsl=\ssecttsl
+  \def\lsize{text}\def\lllsize{small}%
   \resetmathfonts \setleading{15pt}}
-\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf?
-\def\indexfonts{%
-  \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
-  \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
-  \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl
-  \resetmathfonts \setleading{12pt}}
+\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
+\textfonts \rm
 
 % Define these so they can be easily changed for other fonts.
 \def\angleleft{$\langle$}
@@ -1339,23 +1692,33 @@ where each line of input produces a line of output.}
 
 % Fonts for short table of contents.
 \setfont\shortcontrm\rmshape{12}{1000}
-\setfont\shortcontbf\bxshape{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\/\fi\fi\fi}
-\def\smartslanted#1{{\sl #1}\futurelet\next\smartitalicx}
-\def\smartitalic#1{{\it #1}\futurelet\next\smartitalicx}
+\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
-\let\cite=\smartslanted
 
 \def\b#1{{\bf #1}}
 \let\strong=\b
@@ -1367,15 +1730,25 @@ where each line of input produces a line of output.}
 \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
 }
-\let\ttfont=\t
 \def\samp#1{`\tclose{#1}'\null}
-\setfont\smallrm\rmshape{8}{1000}
-\font\smallsy=cmsy9
-\def\key#1{{\smallrm\textfont2=\smallsy \leavevmode\hbox{%
+\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}}%
@@ -1412,7 +1785,7 @@ where each line of input produces a line of output.}
   \null
 }
 
-% We *must* turn on hyphenation at `-' and `_' in \code.
+% 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.
 
@@ -1430,27 +1803,30 @@ where each line of input produces a line of output.}
     \catcode`\_=\active \let_\codeunder
     \codex
   }
-  %
-  % If we end up with any active - characters when handling the index,
-  % just treat them as a normal -.
-  \global\def\indexbreaks{\catcode`\-=\active \let-\realdash}
 }
 
 \def\realdash{-}
 \def\codedash{-\discretionary{}{}{}}
-\def\codeunder{\ifusingtt{\normalunderscore\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}
 
-%\let\exp=\tclose  %Was temporary
-
 % @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).
-\def\kbdinputstyle{\parsearg\kbdinputstylexxx}
-\def\kbdinputstylexxx#1{%
+\parseargdef\kbdinputstyle{%
   \def\arg{#1}%
   \ifx\arg\worddistinct
     \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
@@ -1458,15 +1834,17 @@ where each line of input produces a line of output.}
     \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 kbdinputdistinct.  (Too much of a hassle to call the macro,
-% the catcodes are wrong for parsearg to work.)
-\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}
+% Default is `distinct.'
+\kbdinputstyle distinct
 
 \def\xkey{\key}
 \def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
@@ -1474,29 +1852,59 @@ where each line of input produces a line of output.}
 \else{\tclose{\kbdfont\look}}\fi
 \else{\tclose{\kbdfont\look}}\fi}
 
-% For @url, @env, @command quotes seem unnecessary, so use \code.
-\let\url=\code
+% 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 second argument
-% specifying the text to display.  First (mandatory) arg is the url.
-% Perhaps eventually put in a hypertex \special here.
-% 
-\def\uref#1{\urefxxx #1,,\finish}
-\def\urefxxx#1,#2,#3\finish{%
-  \setbox0 = \hbox{\ignorespaces #2}%
+% @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\ (\code{#1})%
+    \unhbox0 % third arg given, show only that
   \else
-    \code{#1}%
+    \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 the angle brackets --karl, 17may97.
-% So now @email is just like @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}
-\let\email=\uref
+\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
@@ -1522,12 +1930,53 @@ where each line of input produces a line of output.}
 \def\sc#1{{\smallcaps#1}}       % smallcaps font
 \def\ii#1{{\it #1}}             % italic font
 
-% @acronym downcases the argument and prints in smallcaps.
-\def\acronym#1{{\smallcaps \lowercase{#1}}}
+% @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.
+% @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,}
 
@@ -1539,91 +1988,110 @@ where each line of input produces a line of output.}
 \newif\iffinishedtitlepage
 
 % Do an implicit @contents or @shortcontents after @end titlepage if the
-% user says @contentsaftertitlepage or @shortcontentsaftertitlepage.
-% 
+% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage.
+%
 \newif\ifsetcontentsaftertitlepage
  \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue
 \newif\ifsetshortcontentsaftertitlepage
  \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue
 
-\def\shorttitlepage{\parsearg\shorttitlepagezzz}
-\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
         \endgroup\page\hbox{}\page}
 
-\def\titlepage{\begingroup \parindent=0pt \textfonts
-   \let\subtitlerm=\tenrm
-   \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
-   %
-   \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
-   %
-   % Leave some space at the very top of the page.
-   \vglue\titlepagetopglue
-   %
-   % Now you can print the title using @title.
-   \def\title{\parsearg\titlezzz}%
-   \def\titlezzz##1{\leftline{\titlefonts\rm ##1}
-                    % print a rule at the page bottom also.
-                    \finishedtitlepagefalse
-                    \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
-   % No rule at page bottom unless we print one at the top with @title.
-   \finishedtitlepagetrue
-   %
-   % Now you can put text using @subtitle.
-   \def\subtitle{\parsearg\subtitlezzz}%
-   \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
-   %
-   % @author should come last, but may come many times.
-   \def\author{\parsearg\authorzzz}%
-   \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
-      {\authorfont \leftline{##1}}}%
-   %
-   % 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{%
+\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
+	 \finishtitlepage
       \fi
-      \oldpage
       \let\page = \oldpage
-      \hbox{}}%
-%   \def\page{\oldpage \hbox{}}
+      \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
-   %
-   % 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
-   %
-   \HEADINGSon
+    \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
+  \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
@@ -1633,7 +2101,7 @@ where each line of input produces a line of output.}
 \newtoks\evenfootline    % footline on even pages
 \newtoks\oddfootline     % footline on odd pages
 
-% Now make Tex use those variables
+% Now make TeX use those variables
 \headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
                             \else \the\evenheadline \fi}}
 \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
@@ -1647,32 +2115,27 @@ where each line of input produces a line of output.}
 % @evenfooting @thisfile||
 % @oddfooting ||@thisfile
 
-\def\evenheading{\parsearg\evenheadingxxx}
-\def\oddheading{\parsearg\oddheadingxxx}
-\def\everyheading{\parsearg\everyheadingxxx}
-
-\def\evenfooting{\parsearg\evenfootingxxx}
-\def\oddfooting{\parsearg\oddfootingxxx}
-\def\everyfooting{\parsearg\everyfootingxxx}
-
-{\catcode`\@=0 %
 
-\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
-\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\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}}}
 
-\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
-\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\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}}}
 
-\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
+\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
 
-\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
-\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\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}}}
 
-\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
-\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\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
@@ -1681,9 +2144,8 @@ where each line of input produces a line of output.}
   \global\advance\vsize by -\baselineskip
 }
 
-\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}}
-%
-}% unbind the catcode of @.
+\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}}
+
 
 % @headings double      turns headings on for double-sided printing.
 % @headings single      turns headings on for single-sided printing.
@@ -1697,7 +2159,7 @@ where each line of input produces a line of output.}
 
 \def\headings #1 {\csname HEADINGS#1\endcsname}
 
-\def\HEADINGSoff{
+\def\HEADINGSoff{%
 \global\evenheadline={\hfil} \global\evenfootline={\hfil}
 \global\oddheadline={\hfil} \global\oddfootline={\hfil}}
 \HEADINGSoff
@@ -1706,7 +2168,7 @@ where each line of input produces a line of output.}
 % 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{
+\def\HEADINGSdouble{%
 \global\pageno=1
 \global\evenfootline={\hfil}
 \global\oddfootline={\hfil}
@@ -1718,7 +2180,7 @@ where each line of input produces a line of output.}
 
 % For single-sided printing, chapter title goes across top left of page,
 % page number on top right.
-\def\HEADINGSsingle{
+\def\HEADINGSsingle{%
 \global\pageno=1
 \global\evenfootline={\hfil}
 \global\oddfootline={\hfil}
@@ -1748,29 +2210,28 @@ where each line of input produces a line of output.}
 }
 
 % Subroutines used in generating headings
-% Produces Day Month Year style of output.
-\def\today{\number\day\space
-\ifcase\month\or
-January\or February\or March\or April\or May\or June\or
-July\or August\or September\or October\or November\or December\fi
-\space\number\year}
-
-% Use this if you want the Month Day, Year style of output.
-%\def\today{\ifcase\month\or
-%January\or February\or March\or April\or May\or June\or
-%July\or August\or September\or October\or November\or December\fi
-%\space\number\day, \number\year}
-
-% @settitle line...  specifies the title of the document, for headings
-% It generates no output of its own
+% 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
 
-\def\thistitle{No Title}
-\def\settitle{\parsearg\settitlezzz}
-\def\settitlezzz #1{\gdef\thistitle{#1}}
+% @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), @kitem(x), @xitem(x).
+% Tables -- @table, @ftable, @vtable, @item(x).
 
 % default indentation of table text
 \newdimen\tableindent \tableindent=.8in
@@ -1782,7 +2243,7 @@ July\or August\or September\or October\or November\or December\fi
 % used internally for \itemindent minus \itemmargin
 \newdimen\itemmax
 
-% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% 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).
@@ -1794,22 +2255,10 @@ July\or August\or September\or October\or November\or December\fi
 \def\internalBitem{\smallbreak \parsearg\itemzzz}
 \def\internalBitemx{\itemxpar \parsearg\itemzzz}
 
-\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
-\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz}
-
-\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
-\def\internalBkitemx{\itemxpar \parsearg\kitemzzz}
-
-\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
-                 \itemzzz {#1}}
-
-\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
-                 \itemzzz {#1}}
-
 \def\itemzzz #1{\begingroup %
   \advance\hsize by -\rightskip
   \advance\hsize by -\tableindent
-  \setbox0=\hbox{\itemfont{#1}}%
+  \setbox0=\hbox{\itemindicate{#1}}%
   \itemindex{#1}%
   \nobreak % This prevents a break before @itemx.
   %
@@ -1833,15 +2282,19 @@ July\or August\or September\or October\or November\or December\fi
     % \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.  Unfortunately
-    % we can't prevent a possible page break at the following
-    % \baselineskip glue.
-    \nobreak
+    % 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.  
+    % 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
@@ -1855,97 +2308,95 @@ July\or August\or September\or October\or November\or December\fi
   \fi
 }
 
-\def\item{\errmessage{@item while not in a table}}
-\def\itemx{\errmessage{@itemx while not in a table}}
-\def\kitem{\errmessage{@kitem while not in a table}}
-\def\kitemx{\errmessage{@kitemx while not in a table}}
-\def\xitem{\errmessage{@xitem while not in a table}}
-\def\xitemx{\errmessage{@xitemx while not in a table}}
-
-% Contains a kludge to get @end[description] to work.
-\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+\def\item{\errmessage{@item while not in a list environment}}
+\def\itemx{\errmessage{@itemx while not in a list environment}}
 
 % @table, @ftable, @vtable.
-\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
-{\obeylines\obeyspaces%
-\gdef\tablex #1^^M{%
-\tabley\dontindex#1        \endtabley}}
-
-\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
-{\obeylines\obeyspaces%
-\gdef\ftablex #1^^M{%
-\tabley\fnitemindex#1        \endtabley
-\def\Eftable{\endgraf\afterenvbreak\endgroup}%
-\let\Etable=\relax}}
-
-\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
-{\obeylines\obeyspaces%
-\gdef\vtablex #1^^M{%
-\tabley\vritemindex#1        \endtabley
-\def\Evtable{\endgraf\afterenvbreak\endgroup}%
-\let\Etable=\relax}}
-
-\def\dontindex #1{}
-\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
-\def\vritemindex #1{\doind {vr}{\code{#1}}}%
-
-{\obeyspaces %
-\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
-\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
-
-\def\tablez #1#2#3#4#5#6{%
-\aboveenvbreak %
-\begingroup %
-\def\Edescription{\Etable}% Necessary kludge.
-\let\itemindex=#1%
-\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
-\ifnum 0#4>0 \tableindent=#4\mil \fi %
-\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
-\def\itemfont{#2}%
-\itemmax=\tableindent %
-\advance \itemmax by -\itemmargin %
-\advance \leftskip by \tableindent %
-\exdentamount=\tableindent
-\parindent = 0pt
-\parskip = \smallskipamount
-\ifdim \parskip=0pt \parskip=2pt \fi%
-\def\Etable{\endgraf\afterenvbreak\endgroup}%
-\let\item = \internalBitem %
-\let\itemx = \internalBitemx %
-\let\kitem = \internalBkitem %
-\let\kitemx = \internalBkitemx %
-\let\xitem = \internalBxitem %
-\let\xitemx = \internalBxitemx %
+\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
 
-\def\itemize{\parsearg\itemizezzz}
+\envdef\itemize{\parsearg\doitemize}
 
-\def\itemizezzz #1{%
-  \begingroup % ended by the @end itemize
-  \itemizey {#1}{\Eitemize}
+\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
 }
 
-\def\itemizey #1#2{%
-\aboveenvbreak %
-\itemmax=\itemindent %
-\advance \itemmax by -\itemmargin %
-\advance \leftskip by \itemindent %
-\exdentamount=\itemindent
-\parindent = 0pt %
-\parskip = \smallskipamount %
-\ifdim \parskip=0pt \parskip=2pt \fi%
-\def#2{\endgraf\afterenvbreak\endgroup}%
-\def\itemcontents{#1}%
-\let\item=\itemizeitem}
-
-% Set sfcode to normal for the chars that usually have another value.
-% These are `.?!:;,'
-\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
-  \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+% 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.
@@ -1956,11 +2407,8 @@ July\or August\or September\or October\or November\or December\fi
 % or number, to specify the first label in the enumerated list.  No
 % argument is the same as `1'.
 %
-\def\enumerate{\parsearg\enumeratezzz}
-\def\enumeratezzz #1{\enumeratey #1  \endenumeratey}
+\envparseargdef\enumerate{\enumeratey #1  \endenumeratey}
 \def\enumeratey #1 #2\endenumeratey{%
-  \begingroup % ended by the @end enumerate
-  %
   % If we were given no argument, pretend we were given `1'.
   \def\thearg{#1}%
   \ifx\thearg\empty \def\thearg{1}\fi
@@ -2031,13 +2479,13 @@ July\or August\or September\or October\or November\or December\fi
   }%
 }
 
-% Call itemizey, adding a period to the first argument and supplying the
+% 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
-  \itemizey{#1.}\Eenumerate\flushcr
+  \doitemize{#1.}\flushcr
 }
 
 % @alphaenumerate and @capsenumerate are abbreviations for giving an arg
@@ -2048,16 +2496,6 @@ July\or August\or September\or October\or November\or December\fi
 \def\Ealphaenumerate{\Eenumerate}
 \def\Ecapsenumerate{\Eenumerate}
 
-% Definition of @item while inside @itemize.
-
-\def\itemizeitem{%
-\advance\itemno by 1
-{\let\par=\endgraf \smallbreak}%
-\ifhmode \errmessage{In hmode at itemizeitem}\fi
-{\parskip=0in \hskip 0pt
-\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
-\vadjust{\penalty 1200}}%
-\flushcr}
 
 % @multitable macros
 % Amy Hendrickson, 8/18/94, 3/6/96
@@ -2084,24 +2522,14 @@ July\or August\or September\or October\or November\or December\fi
 %   @multitable {Column 1 template} {Column 2 template} {Column 3 template}
 %   @item ...
 %   using the widest term desired in each column.
-%
-% For those who want to use more than one line's worth of words in
-% the preamble, break the line within one argument and it
-% will parse correctly, i.e.,
-%
-%     @multitable {Column 1 template} {Column 2 template} {Column 3
-%      template}
-% Not:
-%     @multitable {Column 1 template} {Column 2 template}
-%      {Column 3 template}
 
 % 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, @multitable or @end multitable do not need to be on their
-% own lines, but it will not hurt if they are.
+% @item, @tab do not need to be on their own lines, but it will not hurt
+% if they are.
 
 % Sample multitable:
 
@@ -2138,50 +2566,78 @@ July\or August\or September\or October\or November\or December\fi
 \multitablelinespace=0pt
 
 % Macros used to set up halign preamble:
-% 
+%
 \let\endsetuptable\relax
 \def\xendsetuptable{\endsetuptable}
 \let\columnfractions\relax
 \def\xcolumnfractions{\columnfractions}
 \newif\ifsetpercent
 
-% 2/1/96, to allow fractions to be given with more than one digit.
-\def\pickupwholefraction#1 {\global\advance\colcount by1 %
-\expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}%
-\setuptable}
+% #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%
+\def\setuptable#1{%
+  \def\firstarg{#1}%
+  \ifx\firstarg\xendsetuptable
+    \let\go = \relax
   \else
-    \ifsetpercent
-       \let\go\pickupwholefraction   % In this case arg of setuptable
-                                     % is the decimal point before the
-                                     % number given in percent of hsize.
-                                     % We don't need this so we don't use it.
+    \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
-       \global\advance\colcount by1
-       \setbox0=\hbox{#1 }% 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}%
+      \let\go = \setuptable
     \fi%
-  \fi%
-\ifx\go\pickupwholefraction\else\let\go\setuptable\fi%
-\fi\go}
+  \fi
+  \go
+}
 
-% multitable syntax
-\def\tab{&\hskip1sp\relax} % 2/2/96
-                           % tiny skip here makes sure this column space is
-                           % maintained, even if it is never used.
+% 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:
-
-\def\multitable{\parsearg\dotable}
-\def\dotable#1{\bgroup
+%
+\newtoks\everytab  % insert after every tab.
+%
+\envdef\multitable{%
   \vskip\parskip
-  \let\item\crcr
+  \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
@@ -2189,81 +2645,98 @@ July\or August\or September\or October\or November\or December\fi
   \parindent=\multitableparindent
   \overfullrule=0pt
   \global\colcount=0
-  \def\Emultitable{\global\setpercentfalse\cr\egroup\egroup}%
   %
+  \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
   %
-  % \everycr will reset column counter, \colcount, at the end of
-  % each line. Every column entry will cause \colcount to advance by one.
-  % The table preamble
-  % looks at the current \colcount to find the correct column width.
-  \everycr{\noalign{%
-  %
-  % \filbreak%% keeps underfull box messages off when table breaks over pages.
-  % 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.
-    \global\colcount=0\relax}}%
-  %
   % 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\relax
-    \multistrut\vtop{\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
+  \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
-%% 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.
 \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
@@ -2276,6 +2749,216 @@ width0pt\relax} \fi
 \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
 
@@ -2302,42 +2985,48 @@ width0pt\relax} \fi
 }
 
 % @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}}
+    \noexpand\docodeindex{#1}}%
 }
 
-\def\defcodeindex{\parsearg\newcodeindex}
 
 % @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.
-% The \closeout helps reduce unnecessary open files; the limit on the
-% Acorn RISC OS is a mere 16 files.
-\def\synindex#1 #2 {%
-  \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
-  \expandafter\closeout\csname#1indfile\endcsname
-  \expandafter\let\csname#1indfile\endcsname=\synindexfoo
-  \expandafter\xdef\csname#1index\endcsname{% define \xxxindex
-    \noexpand\doindex{#2}}%
-}
-
+%
 % @syncodeindex foo bar   similar, but put all entries made for index foo
 % inside @code.
-\def\syncodeindex#1 #2 {%
-  \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
-  \expandafter\closeout\csname#1indfile\endcsname
-  \expandafter\let\csname#1indfile\endcsname=\synindexfoo
-  \expandafter\xdef\csname#1index\endcsname{% define \xxxindex
-    \noexpand\docodeindex{#2}}%
+%
+\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.
@@ -2357,255 +3046,402 @@ width0pt\relax} \fi
 \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\ { }%
-% Take care of the plain tex accent commands.
-\def\"{\realbackslash "}%
-\def\`{\realbackslash `}%
-\def\'{\realbackslash '}%
-\def\^{\realbackslash ^}%
-\def\~{\realbackslash ~}%
-\def\={\realbackslash =}%
-\def\b{\realbackslash b}%
-\def\c{\realbackslash c}%
-\def\d{\realbackslash d}%
-\def\u{\realbackslash u}%
-\def\v{\realbackslash v}%
-\def\H{\realbackslash H}%
-% Take care of the plain tex special European modified letters.
-\def\oe{\realbackslash oe}%
-\def\ae{\realbackslash ae}%
-\def\aa{\realbackslash aa}%
-\def\OE{\realbackslash OE}%
-\def\AE{\realbackslash AE}%
-\def\AA{\realbackslash AA}%
-\def\o{\realbackslash o}%
-\def\O{\realbackslash O}%
-\def\l{\realbackslash l}%
-\def\L{\realbackslash L}%
-\def\ss{\realbackslash ss}%
-% Take care of texinfo commands likely to appear in an index entry.
-% (Must be a way to avoid doing expansion at all, and thus not have to
-% laboriously list every single command here.)
-\def\@{@}% will be @@ when we switch to @ as escape char.
-%\let\{ = \lbracecmd
-%\let\} = \rbracecmd
-\def\_{{\realbackslash _}}%
-\def\w{\realbackslash w }%
-\def\bf{\realbackslash bf }%
-%\def\rm{\realbackslash rm }%
-\def\sl{\realbackslash sl }%
-\def\sf{\realbackslash sf}%
-\def\tt{\realbackslash tt}%
-\def\gtr{\realbackslash gtr}%
-\def\less{\realbackslash less}%
-\def\hat{\realbackslash hat}%
-\def\TeX{\realbackslash TeX}%
-\def\dots{\realbackslash dots }%
-\def\result{\realbackslash result}%
-\def\equiv{\realbackslash equiv}%
-\def\expansion{\realbackslash expansion}%
-\def\print{\realbackslash print}%
-\def\error{\realbackslash error}%
-\def\point{\realbackslash point}%
-\def\copyright{\realbackslash copyright}%
-\def\tclose##1{\realbackslash tclose {##1}}%
-\def\code##1{\realbackslash code {##1}}%
-\def\uref##1{\realbackslash uref {##1}}%
-\def\url##1{\realbackslash url {##1}}%
-\def\env##1{\realbackslash env {##1}}%
-\def\command##1{\realbackslash command {##1}}%
-\def\option##1{\realbackslash option {##1}}%
-\def\dotless##1{\realbackslash dotless {##1}}%
-\def\samp##1{\realbackslash samp {##1}}%
-\def\,##1{\realbackslash ,{##1}}%
-\def\t##1{\realbackslash t {##1}}%
-\def\r##1{\realbackslash r {##1}}%
-\def\i##1{\realbackslash i {##1}}%
-\def\b##1{\realbackslash b {##1}}%
-\def\sc##1{\realbackslash sc {##1}}%
-\def\cite##1{\realbackslash cite {##1}}%
-\def\key##1{\realbackslash key {##1}}%
-\def\file##1{\realbackslash file {##1}}%
-\def\var##1{\realbackslash var {##1}}%
-\def\kbd##1{\realbackslash kbd {##1}}%
-\def\dfn##1{\realbackslash dfn {##1}}%
-\def\emph##1{\realbackslash emph {##1}}%
-\def\acronym##1{\realbackslash acronym {##1}}%
-%
-% Handle some cases of @value -- where the variable name does not
-% contain - or _, and the value does not contain any
-% (non-fully-expandable) commands.
-\let\value = \expandablevalue
-%
-\unsepspaces
-}
-
-% 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 \ ).
-{\obeyspaces
- \gdef\unsepspaces{\obeyspaces\let =\space}}
-
-% \indexnofonts no-ops all font-change commands.
-% This is used when outputting the strings to sort the index by.
-\def\indexdummyfont#1{#1}
-\def\indexdummytex{TeX}
-\def\indexdummydots{...}
+  \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{%
-% Just ignore accents.
-\let\,=\indexdummyfont
-\let\"=\indexdummyfont
-\let\`=\indexdummyfont
-\let\'=\indexdummyfont
-\let\^=\indexdummyfont
-\let\~=\indexdummyfont
-\let\==\indexdummyfont
-\let\b=\indexdummyfont
-\let\c=\indexdummyfont
-\let\d=\indexdummyfont
-\let\u=\indexdummyfont
-\let\v=\indexdummyfont
-\let\H=\indexdummyfont
-\let\dotless=\indexdummyfont
-% Take care of the plain tex special European modified letters.
-\def\oe{oe}%
-\def\ae{ae}%
-\def\aa{aa}%
-\def\OE{OE}%
-\def\AE{AE}%
-\def\AA{AA}%
-\def\o{o}%
-\def\O{O}%
-\def\l{l}%
-\def\L{L}%
-\def\ss{ss}%
-\let\w=\indexdummyfont
-\let\t=\indexdummyfont
-\let\r=\indexdummyfont
-\let\i=\indexdummyfont
-\let\b=\indexdummyfont
-\let\emph=\indexdummyfont
-\let\strong=\indexdummyfont
-\let\cite=\indexdummyfont
-\let\sc=\indexdummyfont
-%Don't no-op \tt, since it isn't a user-level command
-% and is used in the definitions of the active chars like <, >, |...
-%\let\tt=\indexdummyfont
-\let\tclose=\indexdummyfont
-\let\code=\indexdummyfont
-\let\url=\indexdummyfont
-\let\uref=\indexdummyfont
-\let\env=\indexdummyfont
-\let\command=\indexdummyfont
-\let\option=\indexdummyfont
-\let\file=\indexdummyfont
-\let\samp=\indexdummyfont
-\let\kbd=\indexdummyfont
-\let\key=\indexdummyfont
-\let\var=\indexdummyfont
-\let\TeX=\indexdummytex
-\let\dots=\indexdummydots
-\def\@{@}%
-}
-
-% To define \realbackslash, we must make \ not be an escape.
-% We must first make another character (@) an escape
-% so we do not become unable to do a definition.
-
-{\catcode`\@=0 \catcode`\\=\other
- @gdef@realbackslash{\}}
+  % 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)?
 
-% For \ifx comparisons.
-\def\emptymacro{\empty}
-
 % Most index entries go through here, but \dosubind is the general case.
-% 
-\def\doind#1#2{\dosubind{#1}{#2}\empty}
+% #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 defuns, which call us directly.
-% 
+% 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 #2}}%
+    \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}%
   \fi
-  {%
-    \count255=\lastpenalty
-    {%
-      \indexdummies % Must do this here, since \bf, etc expand at this stage
-      \escapechar=`\\
-      {%
-        \let\folio = 0% We will expand all macros now EXCEPT \folio.
-        \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
-        % so it will be output as is; and it will print as backslash.
-        %
-        \def\thirdarg{#3}%
-        %
-        % If third arg is present, precede it with space in sort key.
-        \ifx\thirdarg\emptymacro
-          \let\subentry = \empty
-        \else
-          \def\subentry{ #3}%
-        \fi
-        %
-        % First process the index-string with all font commands turned off
-        % to get the string to sort by.
-        {\indexnofonts \xdef\indexsorttmp{#2\subentry}}%
-        %
-        % Now produce the complete index entry, with both the sort key and the
-        % original text, including any font commands.
-        \toks0 = {#2}%
-        \edef\temp{%
-          \write\csname#1indfile\endcsname{%
-            \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}%
-        }%
-        %
-        % If third (subentry) arg is present, add it to the index string.
-        \ifx\thirdarg\emptymacro \else
-          \toks0 = {#3}%
-          \edef\temp{\temp{\the\toks0}}%
-        \fi
-        %
-        % 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.
-        % 
-        \iflinks
-          \ifvmode
-            \skip0 = \lastskip
-            \ifdim\lastskip = 0pt \else \nobreak\vskip-\lastskip \fi
-          \fi
-          %
-          \temp % do the write
-          %
-          % 
-          \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi
-        \fi
-      }%
-    }%
-    \penalty\count255
+  %
+  % 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
@@ -2643,13 +3479,12 @@ width0pt\relax} \fi
 % @printindex causes a particular index (the ??s file) to get printed.
 % It does not print any chapter heading (usually an @unnumbered).
 %
-\def\printindex{\parsearg\doprintindex}
-\def\doprintindex#1{\begingroup
+\parseargdef\printindex{\begingroup
   \dobreak \chapheadingskip{10000}%
   %
-  \indexfonts \rm
+  \smallfonts \rm
   \tolerance = 9500
-  \indexbreaks
+  \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
@@ -2663,7 +3498,7 @@ width0pt\relax} \fi
     % 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.
-    (Index is nonexistent)
+    \putwordIndexNonexistent
   \else
     %
     % If the index file exists but is empty, then \openin leaves \ifeof
@@ -2671,12 +3506,12 @@ width0pt\relax} \fi
     % it can discover if there is anything in it.
     \read 1 to \temp
     \ifeof 1
-      (Index is empty)
+      \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{\rawbackslashxx}%
+      \def\indexbackslash{\backslashcurfont}%
       \catcode`\\ = 0
       \escapechar = `\\
       \begindoublecolumns
@@ -2696,88 +3531,115 @@ width0pt\relax} \fi
   %
   % Remove any glue we may have, we'll be inserting our own.
   \removelastskip
-  % 
+  %
   % We like breaks before the index initials, so insert a bonus.
-  \penalty -300
+  \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}%
-  \vskip .33\baselineskip plus .1\baselineskip
-  %
   % Do our best not to break after the initial.
   \nobreak
+  \vskip .33\baselineskip plus .1\baselineskip
 }}
 
-% This typesets a paragraph consisting of #1, dot leaders, and then #2
-% flush to the right margin.  It is used for index and table of contents
-% entries.  The paragraph is indented by \leftskip.
+% \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.
 %
-\def\entry#1#2{\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
-  %
-  % Start a ``paragraph'' for the index entry so the line breaking
-  % parameters we've set above will have an effect.
-  \noindent
-  %
-  % Insert the text of the index entry.  TeX will do line-breaking on it.
-  #1%
-  % 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{#2}%
-  \edef\tempc{\tempa}%
-  \edef\tempd{\tempb}%
-  \ifx\tempc\tempd\ \else%
+% 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
     %
-    % 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.
+    % Start a new paragraph if necessary, so our assignments below can't
+    % affect previous text.
+    \par
     %
-    % The `\ ' here is removed by the implicit \unskip that TeX does as
-    % part of (the primitive) \par.  Without it, a spurious underfull
-    % \hbox ensues.
-    \ #2% The page number ends the paragraph.
-  \fi%
-  \par
-\endgroup}
+    % 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
@@ -2786,11 +3648,18 @@ width0pt\relax} \fi
 \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 #2\par
+\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.
@@ -2803,24 +3672,26 @@ width0pt\relax} \fi
 
 \def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
   % Grab any single-column material above us.
-  \output = {\global\setbox\partialpage = \vbox{%
-    % 
+  \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 must prevent the second \partialpage from
-    % simply overwriting the first, causing us to lose the page.
-    % This will preserve it until a real output routine can ship it
-    % out.  Generally, \partialpage will be empty when this runs and
-    % this will be a no-op.
-    \unvbox\partialpage
+    % 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
     %
-    % Unvbox the main output page.
-    \unvbox255
-    \kern-\topskip \kern\baselineskip
-  }}%
-  \eject
+    \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}%
@@ -2848,13 +3719,12 @@ width0pt\relax} \fi
   %
   % Double the \vsize as well.  (We don't need a separate register here,
   % since nobody clobbers \vsize.)
-  \advance\vsize by -\ht\partialpage
   \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
@@ -2862,6 +3732,7 @@ width0pt\relax} \fi
   % 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@
@@ -2869,19 +3740,21 @@ width0pt\relax} \fi
   \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{%
-  % Re-output the contents of the output page -- any previous material,
-  % followed by the two boxes we just split, in box0 and box2.
-  \advance\vsize by \ht\partialpage
   \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 on the
+    % Split the last of the double-column material.  Leave it on the
     % current page, no automatic page break.
     \balancecolumns
     %
@@ -2893,17 +3766,19 @@ width0pt\relax} \fi
     % called on to balance too much material, but if it is, this makes
     % the output somewhat more palatable.)
     \global\output = {\onepageout{\pagecontents\PAGE}}%
-    %
-    % \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.
-    \pagegoal = \vsize
   }%
   \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{%
-  % Called at the end of the double column material.
   \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120.
   \dimen@ = \ht0
   \advance\dimen@ by \topskip
@@ -2931,8 +3806,14 @@ width0pt\relax} \fi
 
 
 \message{sectioning,}
-% Define chapters, sections, etc.
-
+% 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
@@ -2940,15 +3821,55 @@ width0pt\relax} \fi
 
 % This counter is funny since it counts through charcodes of letters A, B, ...
 \newcount\appendixno  \appendixno = `\@
-\def\appendixletter{\char\the\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 % @raise/lowersections modify this count
+\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}
@@ -2958,287 +3879,246 @@ width0pt\relax} \fi
 \def\lowersections{\global\advance\secbase by 1}
 \let\down=\lowersections % original BFox name
 
-% Choose a numbered-heading macro
-% #1 is heading level if unmodified by @raisesections or @lowersections
-% #2 is text for heading
-\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
-\ifcase\absseclevel
-  \chapterzzz{#2}
-\or
-  \seczzz{#2}
-\or
-  \numberedsubseczzz{#2}
-\or
-  \numberedsubsubseczzz{#2}
-\else
-  \ifnum \absseclevel<0
-    \chapterzzz{#2}
+% 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
-    \numberedsubsubseczzz{#2}
+    \ifnum \absseclevel > 3
+      \absseclevel = 3
+    \fi
   \fi
-\fi
-}
-
-% like \numhead, but chooses appendix heading levels
-\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
-\ifcase\absseclevel
-  \appendixzzz{#2}
-\or
-  \appendixsectionzzz{#2}
-\or
-  \appendixsubseczzz{#2}
-\or
-  \appendixsubsubseczzz{#2}
-\else
-  \ifnum \absseclevel<0
-    \appendixzzz{#2}
+  % The heading type:
+  \def\headtype{#1}%
+  \if \headtype U%
+    \ifnum \absseclevel < \unmlevel
+      \chardef\unmlevel = \absseclevel
+    \fi
   \else
-    \appendixsubsubseczzz{#2}
+    % 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
-\fi
-}
-
-% like \numhead, but chooses numberless heading levels
-\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
-\ifcase\absseclevel
-  \unnumberedzzz{#2}
-\or
-  \unnumberedseczzz{#2}
-\or
-  \unnumberedsubseczzz{#2}
-\or
-  \unnumberedsubsubseczzz{#2}
-\else
-  \ifnum \absseclevel<0
-    \unnumberedzzz{#2}
+  % Now print the heading:
+  \if \headtype U%
+    \ifcase\absseclevel
+	\unnumberedzzz{#3}%
+    \or \unnumberedseczzz{#3}%
+    \or \unnumberedsubseczzz{#3}%
+    \or \unnumberedsubsubseczzz{#3}%
+    \fi
   \else
-    \unnumberedsubsubseczzz{#2}
+    \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
-\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
 }
 
-% @chapter, @appendix, @unnumbered.
-\def\thischaptername{No Chapter Title}
-\outer\def\chapter{\parsearg\chapteryyy}
-\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
-\def\chapterzzz #1{%
-\secno=0 \subsecno=0 \subsubsecno=0
-\global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}%
-\chapmacro {#1}{\the\chapno}%
-\gdef\thissection{#1}%
-\gdef\thischaptername{#1}%
-% We don't substitute the actual chapter name into \thischapter
-% because we don't want its macros evaluated now.
-\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}%
-                                  {\the\chapno}}}%
-\temp
-\donoderef
-\global\let\section = \numberedsec
-\global\let\subsection = \numberedsubsec
-\global\let\subsubsection = \numberedsubsubsec
-}
-
-\outer\def\appendix{\parsearg\appendixyyy}
-\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
-\def\appendixzzz #1{%
-\secno=0 \subsecno=0 \subsubsecno=0
-\global\advance \appendixno by 1
-\message{\putwordAppendix\space \appendixletter}%
-\chapmacro {#1}{\putwordAppendix{} \appendixletter}%
-\gdef\thissection{#1}%
-\gdef\thischaptername{#1}%
-\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}%
-                       {\putwordAppendix{} \appendixletter}}}%
-\temp
-\appendixnoderef
-\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\def\centerchap{\parsearg\centerchapyyy}
-\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}}
+\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.
-\outer\def\top{\parsearg\unnumberedyyy}
-
-\outer\def\unnumbered{\parsearg\unnumberedyyy}
-\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
-\def\unnumberedzzz #1{%
-\secno=0 \subsecno=0 \subsubsecno=0
-%
-% 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)}%
-%
-\unnumbchapmacro {#1}%
-\gdef\thischapter{#1}\gdef\thissection{#1}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash unnumbchapentry{\the\toks0}}}%
-\temp
-\unnumbnoderef
-\global\let\section = \unnumberedsec
-\global\let\subsection = \unnumberedsubsec
-\global\let\subsubsection = \unnumberedsubsubsec
-}
+\let\top\unnumbered
 
 % Sections.
-\outer\def\numberedsec{\parsearg\secyyy}
-\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
-\def\seczzz #1{%
-\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
-\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}%
-                                  {\the\chapno}{\the\secno}}}%
-\temp
-\donoderef
-\nobreak
-}
-
-\outer\def\appendixsection{\parsearg\appendixsecyyy}
-\outer\def\appendixsec{\parsearg\appendixsecyyy}
-\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
-\def\appendixsectionzzz #1{%
-\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
-\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}%
-                                  {\appendixletter}{\the\secno}}}%
-\temp
-\appendixnoderef
-\nobreak
-}
-
-\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
-\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
-\def\unnumberedseczzz #1{%
-\plainsecheading {#1}\gdef\thissection{#1}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsecentry{\the\toks0}}}%
-\temp
-\unnumbnoderef
-\nobreak
+\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\def\numberedsubsec{\parsearg\numberedsubsecyyy}
-\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
-\def\numberedsubseczzz #1{%
-\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
-\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}%
-                                    {\the\chapno}{\the\secno}{\the\subsecno}}}%
-\temp
-\donoderef
-\nobreak
-}
-
-\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
-\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
-\def\appendixsubseczzz #1{%
-\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
-\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}%
-                                {\appendixletter}{\the\secno}{\the\subsecno}}}%
-\temp
-\appendixnoderef
-\nobreak
-}
-
-\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
-\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
-\def\unnumberedsubseczzz #1{%
-\plainsubsecheading {#1}\gdef\thissection{#1}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsecentry%
-                                    {\the\toks0}}}%
-\temp
-\unnumbnoderef
-\nobreak
+\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\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
-\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
-\def\numberedsubsubseczzz #1{%
-\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
-\subsubsecheading {#1}
-  {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}%
-  {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
-\temp
-\donoderef
-\nobreak
-}
-
-\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
-\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
-\def\appendixsubsubseczzz #1{%
-\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
-\subsubsecheading {#1}
-  {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}%
-  {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
-\temp
-\appendixnoderef
-\nobreak
-}
-
-\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
-\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
-\def\unnumberedsubsubseczzz #1{%
-\plainsubsubsecheading {#1}\gdef\thissection{#1}%
-\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsubsecentry%
-                                    {\the\toks0}}}%
-\temp
-\unnumbnoderef
-\nobreak
-}
-
-% These are variants which are not "outer", so they can appear in @ifinfo.
-% Actually, they should now be obsolete; ordinary section commands should work.
-\def\infotop{\parsearg\unnumberedzzz}
-\def\infounnumbered{\parsearg\unnumberedzzz}
-\def\infounnumberedsec{\parsearg\unnumberedseczzz}
-\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
-\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
-
-\def\infoappendix{\parsearg\appendixzzz}
-\def\infoappendixsec{\parsearg\appendixseczzz}
-\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
-\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
-
-\def\infochapter{\parsearg\chapterzzz}
-\def\infosection{\parsearg\sectionzzz}
-\def\infosubsection{\parsearg\subsectionzzz}
-\def\infosubsubsection{\parsearg\subsubsectionzzz}
+\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.
-\global\let\section = \numberedsec
-\global\let\subsection = \numberedsubsec
-\global\let\subsubsection = \numberedsubsubsec
+\let\section = \numberedsec
+\let\subsection = \numberedsubsec
+\let\subsubsection = \numberedsubsubsec
 
 % Define @majorheading, @heading and @subheading
 
@@ -3251,23 +4131,27 @@ width0pt\relax} \fi
 %          if justification is not attempted.  Hence \raggedright.
 
 
-\def\majorheading{\parsearg\majorheadingzzz}
-\def\majorheadingzzz #1{%
-{\advance\chapheadingskip by 10pt \chapbreak }%
-{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
-                  \parindent=0pt\raggedright
-                  \rm #1\hfill}}\bigskip \par\penalty 200}
+\def\majorheading{%
+  {\advance\chapheadingskip by 10pt \chapbreak }%
+  \parsearg\chapheadingzzz
+}
 
-\def\chapheading{\parsearg\chapheadingzzz}
-\def\chapheadingzzz #1{\chapbreak %
-{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
-                  \parindent=0pt\raggedright
-                  \rm #1\hfill}}\bigskip \par\penalty 200}
+\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.
-\def\heading{\parsearg\plainsecheading}
-\def\subheading{\parsearg\plainsubsecheading}
-\def\subsubheading{\parsearg\plainsubsubsecheading}
+\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),
@@ -3276,8 +4160,6 @@ width0pt\relax} \fi
 %%% Args are the skip and penalty (usually negative)
 \def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
 
-\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
-
 %%% Define plain chapter starts, and page on/off switching for it
 % Parameter controlling skip before chapter headings (if needed)
 
@@ -3300,7 +4182,7 @@ width0pt\relax} \fi
 \global\let\pagealignmacro=\chappager
 \global\def\HEADINGSon{\HEADINGSsingle}}
 
-\def\CHAPPAGodd{
+\def\CHAPPAGodd{%
 \global\let\contentsalignmacro = \chapoddpage
 \global\let\pchapsepmacro=\chapoddpage
 \global\let\pagealignmacro=\chapoddpage
@@ -3308,258 +4190,394 @@ width0pt\relax} \fi
 
 \CHAPPAGon
 
-\def\CHAPFplain{
-\global\let\chapmacro=\chfplain
-\global\let\unnumbchapmacro=\unnchfplain
-\global\let\centerchapmacro=\centerchfplain}
-
-% Plain chapter opening.
-% #1 is the text, #2 the chapter number or empty if unnumbered.
-\def\chfplain#1#2{%
+% 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
-    \def\chapnum{#2}%
-    \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}%
+    %
+    % 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
+          \hangindent=\wd0 \centerparametersmaybe
           \unhbox0 #1\par}%
   }%
   \nobreak\bigskip % no page break after a chapter title
   \nobreak
 }
 
-% Plain opening for unnumbered.
-\def\unnchfplain#1{\chfplain{#1}{}}
-
 % @centerchap -- centered and unnumbered.
 \let\centerparametersmaybe = \relax
-\def\centerchfplain#1{{%
-  \def\centerparametersmaybe{%
-    \advance\rightskip by 3\rightskip
-    \leftskip = \rightskip
-    \parfillskip = 0pt
-  }%
-  \chfplain{#1}{}%
-}}
+\def\centerparameters{%
+  \advance\rightskip by 3\rightskip
+  \leftskip = \rightskip
+  \parfillskip = 0pt
+}
 
-\CHAPFplain % The default
 
+% 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\unnumbchapmacro=\unnchfopen
-\global\let\centerchapmacro=\centerchfopen}
+\def\CHAPFopen{%
+  \global\let\chapmacro=\chfopen
+  \global\let\centerchapmacro=\centerchfopen}
 
 
-% Section titles.
+% 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}}
-\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}}
-\def\plainsecheading#1{\sectionheading{sec}{}{#1}}
+\def\secheadingbreak{\dobreak \secheadingskip{-1000}}
 
 % Subsection titles.
-\newskip \subsecheadingskip
-\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
-\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}}
-\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}}
+\newskip\subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}}
 
 % Subsubsection titles.
-\let\subsubsecheadingskip = \subsecheadingskip
-\let\subsubsecheadingbreak = \subsecheadingbreak
-\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}}
-\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}}
+\def\subsubsecheadingskip{\subsecheadingskip}
+\def\subsubsecheadingbreak{\subsecheadingbreak}
 
 
-% Print any size section title.
+% Print any size, any type, section title.
 %
-% #1 is the section type (sec/subsec/subsubsec), #2 is the section
-% number (maybe empty), #3 the text.
-\def\sectionheading#1#2#3{%
-  {%
-    \expandafter\advance\csname #1headingskip\endcsname by \parskip
-    \csname #1headingbreak\endcsname
-  }%
+% #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 #1fonts\endcsname \rm
+    \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
     %
-    % Only insert the separating space if we have a section number.
-    \def\secnum{#2}%
-    \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\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 #3}%
+          \hangindent=\wd0  % zero if no section number
+          \unhbox0 #1}%
   }%
-  \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak
+  % 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.  We supply {\folio} at the end of the
-% argument, which will end up as the last argument to the \...entry macro.
-% 
-% We open the .toc file here instead of at @setfilename or any other
-% given time so that @contents can be put in the document anywhere.
-% 
+% 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\writetocentry#1{%
-  \iftocfileopened\else
-    \immediate\openout\tocfile = \jobname.toc
-    \global\tocfileopenedtrue
+\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
-  \iflinks \write\tocfile{#1{\folio}}\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
 
-% Finish up the main text and prepare to read what we've written
-% to \tocfile.
-% 
+% 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.
-   \unnumbchapmacro{#1}\def\thischapter{}%
-   \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 \pageno = \lastnegativepageno \fi
+  % 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{\putwordTableofContents}%
-     \openin 1 \jobname.toc
-     \ifeof 1 \else
-       \closein 1
-       \input \jobname.toc
-     \fi
-     \vfill \eject
-   \endgroup
-   \lastnegativepageno = \pageno
-   \pageno = \savepageno
+  \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{\putwordShortContents}%
-      %
-      \let\chapentry = \shortchapentry
-      \let\unnumbchapentry = \shortunnumberedentry
-      % We want a true roman here for the page numbers.
-      \secfonts
-      \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
-      \rm
-      \hyphenpenalty = 10000
-      \advance\baselineskip by 1pt % Open it up a little.
-      \def\secentry ##1##2##3##4{}
-      \def\unnumbsecentry ##1##2{}
-      \def\subsecentry ##1##2##3##4##5{}
-      \def\unnumbsubsecentry ##1##2{}
-      \def\subsubsecentry ##1##2##3##4##5##6{}
-      \def\unnumbsubsubsecentry ##1##2{}
-      \openin 1 \jobname.toc
-      \ifeof 1 \else
-        \closein 1
-        \input \jobname.toc
-      \fi
-     \vfill \eject
-   \endgroup
-   \lastnegativepageno = \pageno
-   \pageno = \savepageno
+  \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, ...
 
-% Chapter-level things, for both the long and short contents.
-\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
-
-% See comments in \dochapentry re vbox and related settings
-\def\shortchapentry#1#2#3{%
-  \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+% 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}%
 }
 
-% Typeset the label for a chapter or appendix for the short contents.
-% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
-% We could simplify the code here by writing out an \appendixentry
-% command in the toc file for appendices, instead of using \chapentry
-% for both, but it doesn't seem worth it.
-\setbox0 = \hbox{\shortcontrm \putwordAppendix }
-\newdimen\shortappendixwidth \shortappendixwidth = \wd0
-
-\def\shortchaplabel#1{%
-  % We typeset #1 in a box of constant width, regardless of the text of
-  % #1, so the chapter titles will come out aligned.
-  \setbox0 = \hbox{#1}%
-  \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
-  %
-  % This space should be plenty, since a single number is .5em, and the
-  % widest letter (M) is 1em, at least in the Computer Modern fonts.
-  % (This space doesn't include the extra space that gets added after
-  % the label; that gets put in by \shortchapentry above.)
-  \advance\dimen0 by 1.1em
-  \hbox to \dimen0{#1\hfil}%
-}
+% 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}}
 
-\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
-\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+% 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\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
-\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+\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\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
-\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+\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\subsubsecentry#1#2#3#4#5#6{%
-  \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
-\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+\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.
-\newdimen\tocindent \tocindent = 3pc
+% 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.
@@ -3570,37 +4588,28 @@ width0pt\relax} \fi
    \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
    \begingroup
      \chapentryfonts
-     \tocentry{#1}{\dopageno{#2}}%
+     \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{#2}}%
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
 \endgroup}
 
 \def\dosubsecentry#1#2{\begingroup
   \subsecentryfonts \leftskip=2\tocindent
-  \tocentry{#1}{\dopageno{#2}}%
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
 \endgroup}
 
 \def\dosubsubsecentry#1#2{\begingroup
   \subsubsecentryfonts \leftskip=3\tocindent
-  \tocentry{#1}{\dopageno{#2}}%
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
 \endgroup}
 
-% Final typesetting of a toc entry; we use the same \entry macro as for
-% the index entries, but we want to suppress hyphenation here.  (We
-% can't do that in the \entry macro, since index entries might consist
-% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
-\def\tocentry#1#2{\begingroup
-  \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks
-  % Do not use \turnoffactive in these arguments.  Since the toc is
-  % typeset in cmr, so characters such as _ would come out wrong; we
-  % have to do the usual translation tricks.
-  \entry{#1}{#2}%
-\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}
@@ -3610,71 +4619,61 @@ width0pt\relax} \fi
 
 \def\chapentryfonts{\secfonts \rm}
 \def\secentryfonts{\textfonts}
-\let\subsecentryfonts = \textfonts
-\let\subsubsecentryfonts = \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.
-% Furthermore, these definitions must come after we define our fonts.
-\newbox\dblarrowbox    \newbox\longdblarrowbox
-\newbox\pushcharbox    \newbox\bullbox
-\newbox\equivbox       \newbox\errorbox
-
-%{\tentt
-%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
-%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
-%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
-%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
-% Adapted from the manmac format (p.420 of TeXbook)
-%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
-%                                      depth .1ex\hfil}
-%}
-
-% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+%
 \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}
-
-\global\setbox\errorbox=\hbox to \dimen0{\hfil
+%
+\setbox\errorbox=\hbox to \dimen0{\hfil
    \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
    \advance\hsize by -2\dimen2 % Rules.
-   \vbox{
+   \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}
-
-% The @error{} command.
+%
 \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.
 
-\def\tex{\begingroup
+\envdef\tex{%
   \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
   \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
-  \catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+  \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie
   \catcode `\%=14
-  \catcode 43=12 % plus
-  \catcode`\"=12
-  \catcode`\==12
-  \catcode`\|=12
-  \catcode`\<=12
-  \catcode`\>=12
+  \catcode `\+=\other
+  \catcode `\"=\other
+  \catcode `\|=\other
+  \catcode `\<=\other
+  \catcode `\>=\other
   \escapechar=`\\
   %
   \let\b=\ptexb
@@ -3686,20 +4685,24 @@ width0pt\relax} \fi
   \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\@{@}%
-\let\Etex=\endgroup}
+}
+% There is no need to define \Etex.
 
-% Define @lisp ... @endlisp.
-% @lisp does a \begingroup so it can rebind things,
-% including the definition of @endlisp (which normally is erroneous).
+% 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
@@ -3709,30 +4712,29 @@ width0pt\relax} \fi
 % have any width.
 \def\lisppar{\null\endgraf}
 
-% 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.
-%
-{\obeyspaces %
-\gdef\sepspaces{\obeyspaces\let =\tie}}
-
-% Define \obeyedspace to be our active space, whatever it is.  This is
-% for use in \parsearg.
-{\sepspaces%
-\global\let\obeyedspace= }
-
 % 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
+% start of the next paragraph will insert \parskip.
 %
-\def\aboveenvbreak{{\advance\envskipamount by \parskip
-\endgraf \ifdim\lastskip<\envskipamount
-\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+\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
 
@@ -3760,54 +4762,54 @@ width0pt\relax} \fi
 %
 \newskip\lskip\newskip\rskip
 
-\long\def\cartouche{%
-\begingroup
-        \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
-                                \hsize=\cartinner
-                                \kern3pt
-                                \begingroup
-                                        \baselineskip=\normbskip
-                                        \lineskip=\normlskip
-                                        \parskip=\normpskip
-                                        \vskip -\parskip
+\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{%
-                                \endgroup
-                                \kern3pt
-                        \egroup
-                        \kern3pt\vrule
-                        \hskip\rskip
-                \egroup
-                \cartbot
-        \egroup
-\endgroup
-}}
+              \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
-  \inENV % This group ends at the end of the body
   \hfuzz = 12pt % Don't be fussy
   \sepspaces % Make spaces be word-separators rather than space tokens.
-  \singlespace
   \let\par = \lisppar % don't ignore blank lines
   \obeylines % each line of input is a line of output
   \parskip = 0pt
@@ -3818,114 +4820,99 @@ width0pt\relax} \fi
   \ifx\nonarrowing\relax
     \advance \leftskip by \lispnarrowing
     \exdentamount=\lispnarrowing
-    \let\exdent=\nofillexdent
-    \let\nonarrowing=\relax
   \fi
+  \let\exdent=\nofillexdent
 }
 
-% Define the \E... control sequence only if we are inside the particular
-% environment, so the error checking in \end will work.
-% 
-% To end an @example-like environment, we first end the paragraph (via
-% \afterenvbreak's vertical glue), and then the group.  That way we keep
-% the zero \parskip that the environments set -- \parskip glue will be
-% inserted at the beginning of the next paragraph in the document, after
-% the environment.
+% 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\nonfillfinish{\afterenvbreak\endgroup}
-
-% @lisp: indented, narrowed, typewriter font.
-\def\lisp{\begingroup
-  \nonfillstart
-  \let\Elisp = \nonfillfinish
-  \tt
-  \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
-  \gobble       % eat return
+\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
 }
 
-% @example: Same as @lisp.
-\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
-
-% @small... is usually equivalent to the non-small (@smallbook
-% redefines).  We must call \example (or whatever) last in the
-% definition, since it reads the return following the @example (or
-% whatever) command.
-% 
-% This actually allows (for example) @end display inside an
-% @smalldisplay.  Too bad, but makeinfo will catch the error anyway.
-%
-\def\smalldisplay{\begingroup\def\Esmalldisplay{\nonfillfinish\endgroup}\display}
-\def\smallexample{\begingroup\def\Esmallexample{\nonfillfinish\endgroup}\lisp}
-\def\smallformat{\begingroup\def\Esmallformat{\nonfillfinish\endgroup}\format}
-\def\smalllisp{\begingroup\def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+% 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
+}
 
-% Real @smallexample and @smalllisp (when @smallbook): use smaller fonts.
-% Originally contributed by Pavel@xerox.
-\def\smalllispx{\begingroup
-  \def\Esmalllisp{\nonfillfinish\endgroup}%
-  \def\Esmallexample{\nonfillfinish\endgroup}%
-  \indexfonts
-  \lisp
+% Define two synonyms:
+\def\maketwodispenvs #1#2#3{
+  \makedispenv{#1}{#3}
+  \makedispenv{#2}{#3}
 }
 
-% @display: same as @lisp except keep current font.
+% @lisp: indented, narrowed, typewriter font; @example: same as @lisp.
 %
-\def\display{\begingroup
+% @smallexample and @smalllisp: use smaller fonts.
+% Originally contributed by Pavel@xerox.
+%
+\maketwodispenvs {lisp}{example}{%
   \nonfillstart
-  \let\Edisplay = \nonfillfinish
-  \gobble
+  \tt
+  \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
+  \gobble       % eat return
 }
 
-% @smalldisplay (when @smallbook): @display plus smaller fonts.
+% @display/@smalldisplay: same as @lisp except keep current font.
 %
-\def\smalldisplayx{\begingroup
-  \def\Esmalldisplay{\nonfillfinish\endgroup}%
-  \indexfonts \rm
-  \display
+\makedispenv {display}{%
+  \nonfillstart
+  \gobble
 }
 
-% @format: same as @display except don't narrow margins.
+% @format/@smallformat: same as @display except don't narrow margins.
 %
-\def\format{\begingroup
-  \let\nonarrowing = t
+\makedispenv{format}{%
+  \let\nonarrowing = t%
   \nonfillstart
-  \let\Eformat = \nonfillfinish
   \gobble
 }
 
-% @smallformat (when @smallbook): @format plus smaller fonts.
-%
-\def\smallformatx{\begingroup
-  \def\Esmallformat{\nonfillfinish\endgroup}%
-  \indexfonts \rm
-  \format
+% @flushleft: same as @format, but doesn't obey \SETdispenvsize.
+\envdef\flushleft{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  \gobble
 }
-
-% @flushleft (same as @format).
-%
-\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format}
+\let\Eflushleft = \afterenvbreak
 
 % @flushright.
-% 
-\def\flushright{\begingroup
-  \let\nonarrowing = t
+%
+\envdef\flushright{%
+  \let\nonarrowing = t%
   \nonfillstart
-  \let\Eflushright = \nonfillfinish
   \advance\leftskip by 0pt plus 1fill
   \gobble
 }
+\let\Eflushright = \afterenvbreak
+
 
 % @quotation does normal linebreaking (hence we can't use \nonfillstart)
-% and narrows the margins.
+% 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.
 %
-\def\quotation{%
-  \begingroup\inENV %This group ends at the end of the @quotation body
+\envdef\quotation{%
   {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
-  \singlespace
   \parindent=0pt
-  % We have retained a nonzero parskip for the environment, since we're
-  % doing normal filling. So to avoid extra space below the environment...
-  \def\Equotation{\parskip = 0pt \nonfillfinish}%
   %
   % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
   \ifx\nonarrowing\relax
@@ -3934,557 +4921,580 @@ width0pt\relax} \fi
     \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}%
+}
 
-\message{defuns,}
-% Define formatter for defuns
-% First, allow user to change definition object font (\df) internally
-\def\setdeffont #1 {\csname DEF#1\endcsname}
-
-\newskip\defbodyindent \defbodyindent=.4in
-\newskip\defargsindent \defargsindent=50pt
-\newskip\deftypemargin \deftypemargin=12pt
-\newskip\deflastargmargin \deflastargmargin=18pt
-
-\newcount\parencount
-% define \functionparens, which makes ( and ) and & do special things.
-% \functionparens affects the group it is contained in.
-\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 = )
+% 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
+}
 
-{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
 
-% 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.
-\global\let(=\lparen \global\let)=\rparen
-\global\let[=\lbrack \global\let]=\rbrack
-
-\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
-\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
-% This is used to turn on special parens
-% but make & act ordinary (given that it's active).
-\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr}
-
-% Definitions of (, ) and & used in args for functions.
-% This is the definition of ( outside of all parentheses.
-\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested
-  \global\advance\parencount by 1
+% 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\"%
 }
 %
-% This is the definition of ( when already inside a level of parens.
-\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+% [Knuth] p. 380
+\def\uncatcodespecials{%
+  \def\do##1{\catcode`##1=\other}\dospecials}
 %
-\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
-  % also in that case restore the outer-level definition of (.
-  \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
-  \global\advance \parencount by -1 }
-% If we encounter &foo, then turn on ()-hacking afterwards
-\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
-%
-\gdef\normalparens{\boldbrax\let&=\ampnr}
-} % End of definition inside \activeparens
-%% These parens (in \boldbrax) actually are a little bolder than the
-%% contained text.  This is especially needed for [ and ]
-\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 }
-\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 }
-\def\ampnr{\&}
-\def\lbrb{{\bf\char`\[}}
-\def\rbrb{{\bf\char`\]}}
-
-% First, defname, which formats the header line itself.
-% #1 should be the function name.
-% #2 should be the type of definition, such as "Function".
-
-\def\defname #1#2{%
-% Get the values of \leftskip and \rightskip as they were
-% outside the @def...
-\dimen2=\leftskip
-\advance\dimen2 by -\defbodyindent
-\noindent
-\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
-\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
-\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
-\parshape 2 0in \dimen0 \defargsindent \dimen1
-% Now output arg 2 ("Function" or some such)
-% ending at \deftypemargin from the right margin,
-% but stuck inside a box of width 0 so it does not interfere with linebreaking
-{% Adjust \hsize to exclude the ambient margins,
-% so that \rightline will obey them.
-\advance \hsize by -\dimen2
-\rlap{\rightline{{\rm #2}\hskip -1.25pc }}}%
-% Make all lines underfull and no complaints:
-\tolerance=10000 \hbadness=10000
-\advance\leftskip by -\defbodyindent
-\exdentamount=\defbodyindent
-{\df #1}\enskip        % Generate function name
-}
-
-% Actually process the body of a definition
-% #1 should be the terminating control sequence, such as \Edefun.
-% #2 should be the "another name" control sequence, such as \defunx.
-% #3 should be the control sequence that actually processes the header,
-%    such as \defunheader.
-
-\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup %
-\catcode 61=\active % 61 is `='
-\obeylines\activeparens\spacesplit#3}
-
-% #1 is the \E... control sequence to end the definition (which we define).
-% #2 is the \...x control sequence for consecutive fns (which we define).
-% #3 is the control sequence to call to resume processing.
-% #4, delimited by the space, is the class name.
-% 
-\def\defmethparsebody#1#2#3#4 {\begingroup\inENV %
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
-
-% @deftypemethod has an extra argument that nothing else does.  Sigh.
-% #1 is the \E... control sequence to end the definition (which we define).
-% #2 is the \...x control sequence for consecutive fns (which we define).
-% #3 is the control sequence to call to resume processing.
-% #4, delimited by the space, is the class name.
-% #5 is the method's return type.
-% 
-\def\deftypemethparsebody#1#2#3#4 #5 {\begingroup\inENV %
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2##1 ##2 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}{##2}}}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup\obeylines\activeparens\spacesplit{#3{#4}{#5}}}
-
-\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2##1 ##2 {\def#4{##1}%
-\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
-
-% These parsing functions are similar to the preceding ones
-% except that they do not make parens into active characters.
-% These are used for "variables" since they have no arguments.
-
-\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2{\begingroup\obeylines\spacesplit#3}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup %
-\catcode 61=\active %
-\obeylines\spacesplit#3}
-
-% This is used for \def{tp,vr}parsebody.  It could probably be used for
-% some of the others, too, with some judicious conditionals.
-%
-\def\parsebodycommon#1#2#3{%
-  \begingroup\inENV %
-  \medbreak %
-  % Define the end token that this defining construct specifies
-  % so that it will exit this group.
-  \def#1{\endgraf\endgroup\medbreak}%
-  \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
-  \parindent=0in
-  \advance\leftskip by \defbodyindent
-  \exdentamount=\defbodyindent
-  \begingroup\obeylines
+% [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
 
-\def\defvrparsebody#1#2#3#4 {%
-  \parsebodycommon{#1}{#2}{#3}%
-  \spacesplit{#3{#4}}%
-}
 
-% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the
-% type is just `struct', because we lose the braces in `{struct
-% termios}' when \spacesplit reads its undelimited argument.  Sigh.
-% \let\deftpparsebody=\defvrparsebody
+% @verbatiminclude FILE - insert text of file in verbatim environment.
 %
-% So, to get around this, we put \empty in with the type name.  That
-% way, TeX won't find exactly `{...}' as an undelimited argument, and
-% won't strip off the braces.
+\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude}
 %
-\def\deftpparsebody #1#2#3#4 {%
-  \parsebodycommon{#1}{#2}{#3}%
-  \spacesplit{\parsetpheaderline{#3{#4}}}\empty
+\def\doverbatiminclude#1{%
+  {%
+    \makevalueexpandable
+    \setupverbatim
+    \input #1
+    \afterenvbreak
+  }%
 }
 
-% Fine, but then we have to eventually remove the \empty *and* the
-% braces (if any).  That's what this does.
+% @copying ... @end copying.
+% Save the text away for @insertcopying later.
 %
-\def\removeemptybraces\empty#1\relax{#1}
-
-% After \spacesplit has done its work, this is called -- #1 is the final
-% thing to call, #2 the type name (which starts with \empty), and #3
-% (which might be empty) the arguments.
+% 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\parsetpheaderline#1#2#3{%
-  #1{\removeemptybraces#2\relax}{#3}%
-}%
-
-\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2##1 ##2 {\def#4{##1}%
-\begingroup\obeylines\spacesplit{#3{##2}}}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup\obeylines\spacesplit{#3{#5}}}
-
-% Split up #2 at the first space token.
-% call #1 with two arguments:
-%  the first is all of #2 before the space token,
-%  the second is all of #2 after that space token.
-% If #2 contains no space token, all of it is passed as the first arg
-% and the second is passed as empty.
-
-{\obeylines
-\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
-\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
-\ifx\relax #3%
-#1{#2}{}\else #1{#2}{#3#4}\fi}}
-
-% So much for the things common to all kinds of definitions.
+\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
+}
 
-% Define @defun.
+\message{defuns,}
+% @defun etc.
 
-% First, define the processing that is wanted for arguments of \defun
-% Use this to expand the args and terminate the paragraph they make up
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deflastargmargin \deflastargmargin=18pt
 
-\def\defunargs #1{\functionparens \sl
-% Expand, preventing hyphenation at `-' chars.
-% Note that groups don't affect changes in \hyphenchar.
-\hyphenchar\tensl=0
-#1%
-\hyphenchar\tensl=45
-\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi%
-\interlinepenalty=10000
-\advance\rightskip by 0pt plus 1fil
-\endgraf\nobreak\vskip -\parskip\nobreak
+% 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\deftypefunargs #1{%
-% Expand, preventing hyphenation at `-' chars.
-% Note that groups don't affect changes in \hyphenchar.
-% Use \boldbraxnoamp, not \functionparens, so that & is not special.
-\boldbraxnoamp
-\tclose{#1}% avoid \code because of side effects on active chars
-\interlinepenalty=10000
-\advance\rightskip by 0pt plus 1fil
-\endgraf\nobreak\vskip -\parskip\nobreak
+\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{}
 
-% Do complete processing of one @defun or @defunx line already parsed.
-
-% @deffn Command forward-char nchars
-
-\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
-
-\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
-\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
-\catcode 61=\other % Turn off change made in \defparsebody
+% \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
 }
 
-% @defun == @deffn Function
+\def\Edefun{\endgraf\medbreak}
 
-\def\defun{\defparsebody\Edefun\defunx\defunheader}
-
-\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
-\begingroup\defname {#1}{Function}%
-\defunargs {#2}\endgroup %
-\catcode 61=\other % Turn off change made in \defparsebody
+% \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
 }
 
-% @deftypefun int foobar (int @var{foo}, float @var{bar})
-
-\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
-
-% #1 is the data type.  #2 is the name and args.
-\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
-% #1 is the data type, #2 the name, #3 the args.
-\def\deftypefunheaderx #1#2 #3\relax{%
-\doind {fn}{\code{#2}}% Make entry in function index
-\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}%
-\deftypefunargs {#3}\endgroup %
-\catcode 61=\other % Turn off change made in \defparsebody
+% \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%
 }
 
-% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+%%% Untyped functions:
 
-\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+% @deffn category name args
+\makedefun{deffn}{\deffngeneral{}}
 
-% \defheaderxcond#1\relax$$$
-% puts #1 in @code, followed by a space, but does nothing if #1 is null.
-\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi}
+% @deffn category class name args
+\makedefun{defop}#1 {\defopon{#1\ \putwordon}}
 
-% #1 is the classification.  #2 is the data type.  #3 is the name and args.
-\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
-% #1 is the classification, #2 the data type, #3 the name, #4 the args.
-\def\deftypefnheaderx #1#2#3 #4\relax{%
-\doind {fn}{\code{#3}}% Make entry in function index
-\begingroup
-\normalparens % notably, turn off `&' magic, which prevents
-%               at least some C++ text from working
-\defname {\defheaderxcond#2\relax$$$#3}{#1}%
-\deftypefunargs {#4}\endgroup %
-\catcode 61=\other % Turn off change made in \defparsebody
-}
+% \defopon {category on}class name args
+\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
 
-% @defmac == @deffn Macro
-
-\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
-
-\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
-\begingroup\defname {#1}{Macro}%
-\defunargs {#2}\endgroup %
-\catcode 61=\other % Turn off change made in \defparsebody
+% \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}%
 }
 
-% @defspec == @deffn Special Form
+%%% Typed functions:
 
-\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+% @deftypefn category type name args
+\makedefun{deftypefn}{\deftypefngeneral{}}
 
-\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
-\begingroup\defname {#1}{Special Form}%
-\defunargs {#2}\endgroup %
-\catcode 61=\other % Turn off change made in \defparsebody
-}
+% @deftypeop category class type name args
+\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}}
 
-% This definition is run if you use @defunx
-% anywhere other than immediately after a @defun or @defunx.
+% \deftypeopon {category on}class type name args
+\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
 
-\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
-\def\defunx #1 {\errmessage{@defunx in invalid context}}
-\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
-\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
-\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
-\def\deftypemethodx #1 {\errmessage{@deftypemethodx in invalid context}}
-\def\deftypefunx #1 {\errmessage{@deftypefunx in invalid context}}
+% \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}%
+}
 
-% @defmethod, and so on
+%%% Typed variables:
 
-% @defop CATEGORY CLASS OPERATION ARG...
+% @deftypevr category type var args
+\makedefun{deftypevr}{\deftypecvgeneral{}}
 
-\def\defop #1 {\def\defoptype{#1}%
-\defopparsebody\Edefop\defopx\defopheader\defoptype}
+% @deftypecv category class type var args
+\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}}
 
-\def\defopheader #1#2#3{%
-\dosubind {fn}{\code{#2}}{\putwordon\ #1}% Make entry in function index
-\begingroup\defname {#2}{\defoptype{} on #1}%
-\defunargs {#3}\endgroup %
-}
+% \deftypecvof {category of}class type var args
+\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} }
 
-% @deftypemethod CLASS RETURN-TYPE METHOD ARG...
+% \deftypecvgeneral {subind}category type var args
 %
-\def\deftypemethod{%
-  \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader}
+\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.
 %
-% #1 is the class name, #2 the data type, #3 the method name, #4 the args.
-\def\deftypemethodheader#1#2#3#4{%
-  \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index
-  \begingroup
-    \defname{\defheaderxcond#2\relax$$$#3}{\putwordMethodon\ \code{#1}}%
-    \deftypefunargs{#4}%
-  \endgroup
+% 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.
 }
 
-% @defmethod == @defop Method
+% 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\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
-%
-% #1 is the class name, #2 the method name, #3 the args.
-\def\defmethodheader#1#2#3{%
-  \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index
-  \begingroup
-    \defname{#2}{\putwordMethodon\ \code{#1}}%
-    \defunargs{#3}%
-  \endgroup
+\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
 }
 
-% @defcv {Class Option} foo-class foo-flag
-
-\def\defcv #1 {\def\defcvtype{#1}%
-\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
-
-\def\defcvarheader #1#2#3{%
-\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
-\begingroup\defname {#2}{\defcvtype{} of #1}%
-\defvarargs {#3}\endgroup %
+% We want ()&[] to print specially on the defun line.
+%
+\def\activeparens{%
+  \catcode`\(=\active \catcode`\)=\active
+  \catcode`\[=\active \catcode`\]=\active
+  \catcode`\&=\active
 }
 
-% @defivar == @defcv {Instance Variable}
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
 
-\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+% 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& = \&
 
-\def\defivarheader #1#2#3{%
-\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
-\begingroup\defname {#2}{Instance Variable of #1}%
-\defvarargs {#3}\endgroup %
+  \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+  \gdef\magicamp{\let&=\amprm}
 }
 
-% These definitions are run if you use @defmethodx, etc.,
-% anywhere other than immediately after a @defmethod, etc.
-
-\def\defopx #1 {\errmessage{@defopx in invalid context}}
-\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
-\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
-\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
-
-% Now @defvar
-
-% First, define the processing that is wanted for arguments of @defvar.
-% This is actually simple: just print them in roman.
-% This must expand the args and terminate the paragraph they make up
-\def\defvarargs #1{\normalparens #1%
-\interlinepenalty=10000
-\endgraf\nobreak\vskip -\parskip\nobreak}
-
-% @defvr Counter foo-count
-
-\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
-
-\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
-\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
-
-% @defvar == @defvr Variable
-
-\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+\newcount\parencount
 
-\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
-\begingroup\defname {#1}{Variable}%
-\defvarargs {#2}\endgroup %
+% 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
 }
-
-% @defopt == @defvr {User Option}
-
-\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
-
-\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
-\begingroup\defname {#1}{User Option}%
-\defvarargs {#2}\endgroup %
+\def\infirstlevel#1{%
+  \ifampseen
+    \ifnum\parencount=1
+      #1%
+    \fi
+  \fi
 }
+\def\bfafterword#1 {#1 \bf}
 
-% @deftypevar int foobar
-
-\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
-
-% #1 is the data type.  #2 is the name, perhaps followed by text that
-% is actually part of the data type, which should not be put into the index.
-\def\deftypevarheader #1#2{%
-\dovarind#2 \relax% Make entry in variables index
-\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}%
-\interlinepenalty=10000
-\endgraf\nobreak\vskip -\parskip\nobreak
-\endgroup}
-\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}}
-
-% @deftypevr {Global Flag} int enable
-
-\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
-
-\def\deftypevrheader #1#2#3{\dovarind#3 \relax%
-\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1}
-\interlinepenalty=10000
-\endgraf\nobreak\vskip -\parskip\nobreak
-\endgroup}
-
-% This definition is run if you use @defvarx
-% anywhere other than immediately after a @defvar or @defvarx.
-
-\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
-\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
-\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
-\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
-\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
-
-% Now define @deftp
-% Args are printed in bold, a slight difference from @defvar.
-
-\def\deftpargs #1{\bf \defvarargs{#1}}
-
-% @deftp Class window height width ...
-
-\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
-
-\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
-\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+\def\opnr{%
+  \global\advance\parencount by 1
+  {\parenfont(}%
+  \infirstlevel \bfafterword
+}
+\def\clnr{%
+  {\parenfont)}%
+  \infirstlevel \sl
+  \global\advance\parencount by -1
+}
 
-% This definition is run if you use @deftpx, etc
-% anywhere other than immediately after a @deftp, etc.
+\newcount\brackcount
+\def\lbrb{%
+  \global\advance\brackcount by 1
+  {\bf[}%
+}
+\def\rbrb{%
+  {\bf]}%
+  \global\advance\brackcount by -1
+}
 
-\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+\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, 
+% 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\scanmacro#1{%
-   \begingroup \newlinechar`\^^M
-   \immediate\openout\macscribble=\jobname.tmp
-   \immediate\write\macscribble{#1}%
-   \immediate\closeout\macscribble
-   \let\xeatspaces\eatspaces
-   \input \jobname.tmp
-   \endgroup
-}
-\else
-\def\scanmacro#1{%
-\begingroup \newlinechar`\^^M
-\let\xeatspaces\eatspaces\scantokens{#1}\endgroup}
+  \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.
-% Thisdoes \let #1 = #2, except with \csnames.
+% 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\expandafter
-\expandafter\let
-\expandafter\expandafter
-\csname#1\endcsname
-\csname#2\endcsname}
+  \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).
@@ -4497,7 +5507,7 @@ width0pt\relax} \fi
 }
 
 % Trim a single trailing ^^M off a string.
-{\catcode`\^^M=12\catcode`\Q=3%
+{\catcode`\^^M=\other \catcode`\Q=3%
 \gdef\eatcr #1{\eatcra #1Q^^MQ}%
 \gdef\eatcra#1^^MQ{\eatcrb#1Q}%
 \gdef\eatcrb#1Q#2Q{#1}%
@@ -4507,37 +5517,43 @@ width0pt\relax} \fi
 % 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 
+% 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{%
-  \catcode`\~=12
-  \catcode`\^=12
-  \catcode`\_=12
-  \catcode`\|=12
-  \catcode`\<=12
-  \catcode`\>=12
-  \catcode`\+=12
-  \catcode`\{=12
-  \catcode`\}=12
-  \catcode`\@=12
-  \catcode`\^^M=12
-  \usembodybackslash}
+  \scanctxt
+  \catcode`\{=\other
+  \catcode`\}=\other
+  \catcode`\^^M=\other
+  \usembodybackslash
+}
 
 \def\macroargctxt{%
-  \catcode`\~=12
-  \catcode`\^=12
-  \catcode`\_=12
-  \catcode`\|=12
-  \catcode`\<=12
-  \catcode`\>=12
-  \catcode`\+=12
-  \catcode`\@=12
-  \catcode`\\=12}
+  \scanctxt
+  \catcode`\\=\other
+}
 
 % \mbodybackslash is the definition of \ in @macro bodies.
-% It maps \foo\ => \csname macarg.foo\endcsname => #N 
+% 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.
@@ -4556,25 +5572,48 @@ width0pt\relax} \fi
   \ifx\argl\empty       % no arguments
      \paramno=0%
   \else
-     \expandafter\parsemargdef \argl;% 
+     \expandafter\parsemargdef \argl;%
   \fi
-  \expandafter\ifx \csname macsave.\the\macname\endcsname \relax
-     \cslet{macsave.\the\macname}{\the\macname}%
-  \else
+  \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 
+  \else \expandafter\parsemacbody
   \fi}
 
-\def\unmacro{\parsearg\unmacroxxx}
-\def\unmacroxxx#1{%
-  \expandafter\ifx \csname macsave.\the\macname\endcsname \relax
-    \errmessage{Macro \the\macname\ not defined.}%
+\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
-    \cslet{#1}{macsave.#1}%
-    \expandafter\let \csname macsave.\the\macname\endcsname \undefined
+    \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
 }
 
@@ -4633,19 +5672,20 @@ width0pt\relax} \fi
     \or % 1
       \expandafter\xdef\csname\the\macname\endcsname{%
          \bgroup\noexpand\macroargctxt
-         \noexpand\braceorline\csname\the\macname xxx\endcsname}%
+         \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}
+         \noexpand\csname\the\macname xx\endcsname}%
       \expandafter\xdef\csname\the\macname xx\endcsname##1{%
-          \csname\the\macname xxx\endcsname ##1,}%
+          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
       \expandafter\expandafter
       \expandafter\xdef
       \expandafter\expandafter
-        \csname\the\macname xxx\endcsname 
+        \csname\the\macname xxx\endcsname
           \paramlist{\egroup\noexpand\scanmacro{\temp}}%
     \fi
   \else
@@ -4657,7 +5697,8 @@ width0pt\relax} \fi
     \or % 1
       \expandafter\xdef\csname\the\macname\endcsname{%
          \bgroup\noexpand\macroargctxt
-         \noexpand\braceorline\csname\the\macname xxx\endcsname}%
+         \noexpand\braceorline
+         \expandafter\noexpand\csname\the\macname xxx\endcsname}%
       \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
         \egroup
         \noexpand\norecurse{\the\macname}%
@@ -4665,9 +5706,9 @@ width0pt\relax} \fi
     \else % many
       \expandafter\xdef\csname\the\macname\endcsname{%
          \bgroup\noexpand\macroargctxt
-         \noexpand\csname\the\macname xx\endcsname}
+         \expandafter\noexpand\csname\the\macname xx\endcsname}%
       \expandafter\xdef\csname\the\macname xx\endcsname##1{%
-          \csname\the\macname xxx\endcsname ##1,}%
+          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
       \expandafter\expandafter
       \expandafter\xdef
       \expandafter\expandafter
@@ -4688,11 +5729,45 @@ width0pt\relax} \fi
 \def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx}
 \def\braceorlinexxx{%
   \ifx\nchar\bgroup\else
-    \expandafter\parsearg 
+    \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.
@@ -4703,53 +5778,70 @@ width0pt\relax} \fi
 \def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
   node \samp{\ignorespaces#1{}}}
 
-% @node's job is to define \lastnode.
-\def\node{\ENVcheck\parsearg\nodezzz}
-\def\nodezzz#1{\nodexxx [#1,]}
-\def\nodexxx[#1,#2]{\gdef\lastnode{#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=\relax
-
-% The sectioning commands (@chapter, etc.) call these.
-\def\donoderef{%
-  \ifx\lastnode\relax\else
-    \expandafter\expandafter\expandafter\setref{\lastnode}%
-      {Ysectionnumberandtype}%
-    \global\let\lastnode=\relax
-  \fi
-}
-\def\unnumbnoderef{%
-  \ifx\lastnode\relax\else
-    \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}%
-    \global\let\lastnode=\relax
-  \fi
-}
-\def\appendixnoderef{%
-  \ifx\lastnode\relax\else
-    \expandafter\expandafter\expandafter\setref{\lastnode}%
-      {Yappendixletterandtype}%
-    \global\let\lastnode=\relax
+\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.
-% 
-\def\anchor#1{\setref{#1}{Ynothing}}
-
-
-% \setref{NAME}{SNT} defines a cross-reference point NAME, namely
-% NAME-title, NAME-pg, and NAME-SNT.  Called from \foonoderef.  We have
-% to set \indexdummies so commands such as @code in a section title
-% aren't expanded.  It would be nicer not to expand the titles in the
-% first place, but there's so many layers that that is hard to do.
-% 
-\def\setref#1#2{{%
-  \indexdummies
-  \dosetq{#1-title}{Ytitle}%
-  \dosetq{#1-pg}{Ypagenumber}%
-  \dosetq{#1-snt}{#2}
-}}
+%
+\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
@@ -4760,122 +5852,158 @@ width0pt\relax} \fi
 \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\printednodename{\ignorespaces #3}%
-  \setbox1=\hbox{\printedmanual}%
-  \setbox0=\hbox{\printednodename}%
+  \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\printednodename{\ignorespaces #1}%
+      \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\printednodename{\ignorespaces #1}%
+        \def\printedrefname{\ignorespaces #1}%
       \else
         \ifhavexrefs
           % We know the real title if we have the xref values.
-          \def\printednodename{\refx{#1-title}{}}%
+          \def\printedrefname{\refx{#1-title}{}}%
         \else
           % Otherwise just copy the Info node name.
-          \def\printednodename{\ignorespaces #1}%
+          \def\printedrefname{\ignorespaces #1}%
         \fi%
       \fi
     \fi
   \fi
   %
-  % 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{} ``\printednodename'' in \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.
-    {\normalturnoffactive
-     % 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
+  % 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
     }%
-    % [mynode], 
-    [\printednodename],\space
-    % page 3
-    \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+    \linkcolor
   \fi
-\endgroup}
-
-% \dosetq is the interface for calls from other macros
-
-% Use \normalturnoffactive so that punctuation chars such as underscore
-% and backslash work in node names.  (\turnoffactive doesn't do \.)
-\def\dosetq#1#2{%
-  {\let\folio=0
-   \normalturnoffactive
-   \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}%
-   \iflinks
-     \next
-   \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
   }%
-}
-
-% \internalsetq {foo}{page} expands into
-% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
-% When the aux file is read, ' is the escape character
-
-\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
-
-% Things to be expanded by \internalsetq
-
-\def\Ypagenumber{\folio}
-
-\def\Ytitle{\thissection}
-
-\def\Ynothing{}
+  \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}
 
-\def\Ysectionnumberandtype{%
-\ifnum\secno=0 \putwordChapter\xreftie\the\chapno %
-\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno %
-\else \ifnum \subsubsecno=0 %
-\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno %
-\else %
-\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
-\fi \fi \fi }
-
-\def\Yappendixletterandtype{%
-\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}%
-\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno %
-\else \ifnum \subsubsecno=0 %
-\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
-\else %
-\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
-\fi \fi \fi }
-
-\gdef\xreftie{'tie}
+% 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]}
 
-% 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.
+% Things referred to by \setref.
 %
-\ifx\inputlineno\thisisundefined
-  \let\linenumber = \empty % Non-3.0.
-\else
-  \def\linenumber{\the\inputlineno:\space}
-\fi
+\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{%
-  \expandafter\ifx\csname X#1\endcsname\relax
+  {%
+    \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
@@ -4890,21 +6018,49 @@ width0pt\relax} \fi
     \fi
   \else
     % It's defined, so just use it.
-    \csname X#1\endcsname
+    \thisrefX
   \fi
   #2% Output the suffix in any case.
 }
 
-% This is the macro invoked by entries in the aux file.
-% 
-\def\xrdef#1{\begingroup
-  % Reenable \ as an escape while reading the second argument.
-  \catcode`\\ = 0
-  \afterassignment\endgroup
-  \expandafter\gdef\csname X#1\endcsname
+% 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
@@ -4933,9 +6089,7 @@ width0pt\relax} \fi
   \catcode`\^^]=\other
   \catcode`\^^^=\other
   \catcode`\^^_=\other
-  \catcode`\@=\other
-  \catcode`\^=\other
-  % It was suggested to define this as 7, which would allow ^^e4 etc.
+  % 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 ^
@@ -4948,6 +6102,9 @@ width0pt\relax} \fi
   % \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
@@ -4959,8 +6116,19 @@ width0pt\relax} \fi
   \catcode`\$=\other
   \catcode`\#=\other
   \catcode`\&=\other
+  \catcode`\%=\other
   \catcode`+=\other % avoid \+ for paranoia even though we've turned it off
-  % Make the characters 128-255 be printing characters
+  %
+  % 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{%
@@ -4969,31 +6137,18 @@ width0pt\relax} \fi
       \ifnum \count 1<256 \loop \fi
     }%
   }%
-  % The aux file uses ' as the escape (for now).
-  % Turn off \ as an escape so we do not lose on
-  % entries which were dumped with control sequences in their names.
-  % For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
-  % Reference to such entries still does not work the way one would wish,
-  % but at least they do not bomb out when the aux file is read in.
+  %
+  % @ is our escape character in .aux files, and we need braces.
   \catcode`\{=1
   \catcode`\}=2
-  \catcode`\%=\other
-  \catcode`\'=0
-  \catcode`\\=\other
+  \catcode`\@=0
   %
-  \openin 1 \jobname.aux
-  \ifeof 1 \else
-    \closein 1
-    \input \jobname.aux
-    \global\havexrefstrue
-    \global\warnedobstrue
-  \fi
-  % Open the new aux file.  TeX will close it automatically at exit.
-  \openout\auxfile=\jobname.aux
+  \input \jobname.aux
 \endgroup}
 
 
-% Footnotes.
+\message{insertions,}
+% including footnotes.
 
 \newcount \footnoteno
 
@@ -5007,37 +6162,39 @@ width0pt\relax} \fi
 % @footnotestyle is meaningful for info output only.
 \let\footnotestyle=\comment
 
-\let\ptexfootnote=\footnote
-
 {\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}\/\fi
+  \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi
   %
   % Remove inadvertent blank space before typesetting the footnote number.
   \unskip
   \thisfootno\@sf
-  \footnotezzz
+  \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 fail inside footnotes because the tokens are fixed when
+% 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.
 %
-\long\gdef\footnotezzz{\insert\footins\bgroup
+\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
@@ -5048,8 +6205,17 @@ width0pt\relax} \fi
   \xspaceskip\z@skip
   \parindent\defaultparindent
   %
-  % Hang the footnote text off the number.
-  \hang
+  \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
@@ -5058,88 +6224,90 @@ width0pt\relax} \fi
   \footstrut
   \futurelet\next\fo@t
 }
-\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t
-  \else\let\next\f@t\fi \next}
-\def\f@@t{\bgroup\aftergroup\@foot\let\next}
-\def\f@t#1{#1\@foot}
-\def\@foot{\strut\egroup}
-
 }%end \catcode `\@=11
 
-% 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}
+% 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\setleading#1{%
-  \normalbaselineskip = #1\relax
-  \normallineskip = \lineskipfactor\normalbaselineskip
-  \normalbaselines
-  \setbox\strutbox =\hbox{%
-    \vrule width0pt height\strutheightpercent\baselineskip
-                    depth \strutdepthpercent \baselineskip
-  }%
+\def\startsavinginserts{%
+  \ifx \insert\ptexinsert
+    \let\insert\saveinsert
+  \else
+    \let\checkinserts\relax
+  \fi
 }
 
-% @| 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).
+% This \insert replacement works for both \insert\footins{foo} and
+% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}.
 %
-\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
-    }%
-  }%
+\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
 
-% 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}
 
 % @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
-  \closein 1
-  % Do not bother showing banner with post-v2.7 epsf.tex (available in
-  % doc/epsf.tex until it shows up on ctan).
+  % 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://ftp.tug.org/tex/epsf.tex.}
+  it from ftp://tug.org/tex/epsf.tex.}
 %
-% Only complain once about lack of epsf.tex.
 \def\image#1{%
   \ifx\epsfbox\undefined
     \ifwarnednoepsf \else
@@ -5148,33 +6316,342 @@ width0pt\relax} \fi
       \global\warnednoepsftrue
     \fi
   \else
-    \imagexxx #1,,,\finish
+    \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 just the usual extra ignored arg for parsing this stuff.
-\def\imagexxx#1,#2,#3,#4\finish{%
-  % \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
+% #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
-    \nobreak\medskip
+    \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
-    \centerline{\epsfbox{#1.eps}}%
-    \bigbreak
+    \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.}
 
 
-\message{paper sizes,}
-% And other related parameters.
+% @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
@@ -5194,24 +6671,25 @@ width0pt\relax} \fi
 % 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.  This makes it come to about 9pt for the 8.5x11 format.  We
-% call this whenever the paper size is set.
+% \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 = \hsize
-    \divide\emergencystretch by 45
+    \emergencystretch = .15\hsize
   \fi
 }
 
 % Parameters in order: 1) textheight; 2) textwidth; 3) voffset;
-% 4) hoffset; 5) binding offset; 6) topskip.  Then whoever calls us can
-% set \parskip and call \setleading for \baselineskip.
+% 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8)
+% physical page width.
 %
-\def\internalpagesizes#1#2#3#4#5#6{%
+% 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
@@ -5230,6 +6708,13 @@ width0pt\relax} \fi
   \normaloffset = #4\relax
   \bindingoffset = #5\relax
   %
+  \ifpdf
+    \pdfpageheight #7\relax
+    \pdfpagewidth #8\relax
+  \fi
+  %
+  \setleading{\textleading}
+  %
   \parindent = \defaultparindent
   \setemergencystretch
 }
@@ -5237,82 +6722,129 @@ width0pt\relax} \fi
 % @letterpaper (the default).
 \def\letterpaper{{\globaldefs = 1
   \parskip = 3pt plus 2pt minus 1pt
-  \setleading{13.2pt}%
+  \textleading = 13.2pt
   %
   % If page is nothing but text, make it come out even.
-  \internalpagesizes{46\baselineskip}{6in}{\voffset}{.25in}{\bindingoffset}{36pt}%
+  \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
-  \setleading{12pt}%
+  \textleading = 12pt
   %
-  \internalpagesizes{7.5in}{5.in}{\voffset}{.25in}{\bindingoffset}{16pt}%
+  \internalpagesizes{7.5in}{5in}%
+                    {\voffset}{.25in}%
+                    {\bindingoffset}{16pt}%
+                    {9.25in}{7in}%
   %
   \lispnarrowing = 0.3in
   \tolerance = 700
   \hfuzz = 1pt
   \contentsrightmargin = 0pt
-  \deftypemargin = 0pt
   \defbodyindent = .5cm
-  %
-  \let\smalldisplay = \smalldisplayx
-  \let\smallexample = \smalllispx
-  \let\smallformat = \smallformatx
-  \let\smalllisp = \smalllispx
 }}
 
 % Use @afourpaper to print on European A4 paper.
 \def\afourpaper{{\globaldefs = 1
-  \setleading{12pt}%
   \parskip = 3pt plus 2pt minus 1pt
+  \textleading = 13.2pt
   %
-  \internalpagesizes{53\baselineskip}{160mm}{\voffset}{4mm}{\bindingoffset}{44pt}%
+  % 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
 }}
 
-% A specific text layout, 24x15cm overall, intended for A4 paper.  Top margin
-% 29mm, hence bottom margin 28mm, nominal side margin 3cm.
-\def\afourlatex{{\globaldefs = 1
-  \setleading{13.6pt}%
+% 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}{3.6mm}{3.6mm}{3mm}{7mm}%
+  \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 European A4 paper in wide format.
-\def\afourwide{%
+% Use @afourwide to print on A4 paper in landscape format.
+\def\afourwide{{\globaldefs = 1
   \afourpaper
-  \internalpagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}%
-  %
+  \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.
-% 
-\def\pagesizes{\parsearg\pagesizesxxx}
-\def\pagesizesxxx#1{\pagesizesyyy #1,,\finish}
+%
+\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{13.2pt}%
+  \setleading{\textleading}%
+  %
+  \dimen0 = #1
+  \advance\dimen0 by \voffset
   %
-  \internalpagesizes{#1}{\hsize}{\voffset}{\normaloffset}{\bindingoffset}{44pt}%
+  \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.
@@ -5324,6 +6856,7 @@ width0pt\relax} \fi
 \catcode`\<=\other
 \catcode`\>=\other
 \catcode`\+=\other
+\catcode`\$=\other
 \def\normaldoublequote{"}
 \def\normaltilde{~}
 \def\normalcaret{^}
@@ -5332,9 +6865,10 @@ width0pt\relax} \fi
 \def\normalless{<}
 \def\normalgreater{>}
 \def\normalplus{+}
+\def\normaldollar{$}%$ font-lock fix
 
-% This macro is used to make a character print one way in ttfont
-% where it can probably just be output, and another way in other fonts,
+% 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
@@ -5342,7 +6876,13 @@ width0pt\relax} \fi
 % 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\the\font=0pt #1\else #2\fi}
+\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).
@@ -5361,7 +6901,7 @@ width0pt\relax} \fi
 \catcode`\_=\active
 \def_{\ifusingtt\normalunderscore\_}
 % Subroutine for the previous macro.
-\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }
 
 \catcode`\|=\active
 \def|{{\tt\char124}}
@@ -5373,15 +6913,8 @@ width0pt\relax} \fi
 \def>{{\tt \gtr}}
 \catcode`\+=\active
 \def+{{\tt \char 43}}
-%\catcode 27=\active
-%\def^^[{$\diamondsuit$}
-
-% Set up an active definition for =, but don't enable it most of the time.
-{\catcode`\==\active
-\global\def={{\tt \char 61}}}
-
-\catcode`+=\active
-\catcode`\_=\active
+\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.
@@ -5391,45 +6924,48 @@ width0pt\relax} \fi
 
 \catcode`\@=0
 
-% \rawbackslashxx output one backslash character in current font
-\global\chardef\rawbackslashxx=`\\
-%{\catcode`\\=\other
-%@gdef@rawbackslashxx{\}}
+% \backslashcurfont outputs one backslash character in current font,
+% as in \char`\\.
+\global\chardef\backslashcurfont=`\\
+\global\let\rawbackslashxx=\backslashcurfont  % let existing .??s files work
 
-% \rawbackslash redefines \ as input to do \rawbackslashxx.
+% \rawbackslash defines an active \ to do \backslashcurfont.
+% \otherbackslash defines an active \ to be a literal `\' character with
+% catcode other.
 {\catcode`\\=\active
-@gdef@rawbackslash{@let\=@rawbackslashxx }}
+ @gdef@rawbackslash{@let\=@backslashcurfont}
+ @gdef@otherbackslash{@let\=@realbackslash}
+}
 
-% \normalbackslash outputs one backslash in fixed width font.
-\def\normalbackslash{{\tt\rawbackslashxx}}
+% \realbackslash is an actual character `\' with catcode other.
+{\catcode`\\=\other @gdef@realbackslash{\}}
 
-% Say @foo, not \foo, in error messages.
-\escapechar=`\@
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\backslashcurfont}}
 
-% \catcode 17=0   % Define control-q
 \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}
-
-@def@normalturnoffactive{@let"=@normaldoublequote
-@let\=@normalbackslash
-@let~=@normaltilde
-@let^=@normalcaret
-@let_=@normalunderscore
-@let|=@normalverticalbar
-@let<=@normalless
-@let>=@normalgreater
-@let+=@normalplus}
+@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.
@@ -5448,20 +6984,31 @@ width0pt\relax} \fi
 % 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}
+@gdef@fixbackslash{%
+  @ifx\@eatinput @let\ = @normalbackslash @fi
+  @catcode`+=@active
+  @catcode`@_=@active
+}
 
-% These look ok in all fonts, so just make them not special.  The @rm below
-% makes sure that the current font starts out as the newly loaded cmr10
-@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+% 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
 
-@textfonts
-@rm
 
 @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"
+@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/contrib/amd/doc/version.texi b/contrib/amd/doc/version.texi
index 6032c23..41b19a3 100644
--- a/contrib/amd/doc/version.texi
+++ b/contrib/amd/doc/version.texi
@@ -1,3 +1,4 @@
-@set UPDATED 7 October 1999
-@set EDITION 6.0.3s1
-@set VERSION 6.0.3s1
+@set UPDATED 20 April 2006
+@set UPDATED-MONTH April 2006
+@set EDITION 6.1.5
+@set VERSION 6.1.5
diff --git a/contrib/amd/fixmount/fixmount.8 b/contrib/amd/fixmount/fixmount.8
index e99ddd6..cd3d6cb 100644
--- a/contrib/amd/fixmount/fixmount.8
+++ b/contrib/amd/fixmount/fixmount.8
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-1999 Erez Zadok
+.\" Copyright (c) 1997-2006 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.
@@ -38,11 +38,10 @@
 .\"
 .\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: fixmount.8,v 1.2 1999/01/10 21:54:26 ezk Exp $
-.\" $FreeBSD: src/contrib/amd/fixmount/fixmount.8,v 1.5.2.2 2001/03/06 16:54:05 ru Exp $
-.\" $DragonFly: src/contrib/amd/fixmount/fixmount.8,v 1.2 2003/06/17 04:23:57 dillon Exp $
+.\" $Id: fixmount.8,v 1.12.2.1 2006/01/02 18:48:25 ezk Exp $
+.\" $FreeBSD: src/contrib/amd/fixmount/fixmount.8,v 1.17 2012/11/17 01:48:41 svnexp Exp $
 .\"
-.Dd February 26, 1993
+.Dd January 2, 2006
 .Dt FIXMOUNT 8
 .Os
 .Sh NAME
@@ -52,20 +51,22 @@
 .Nm
 .Op Fl adervq
 .Op Fl h Ar name
-.Ar host
-\&...
+.Ar host ...
 .Sh DESCRIPTION
+The
 .Nm
-is a variant of 
+utility
+is a variant of
 .Xr showmount 8
 that can delete bogus mount entries in remote
 .Xr mountd 8
-daemons.  The actions specified by the options are performed for each
-.Ar host 
+daemons.
+The actions specified by the options are performed for each
+.Ar host
 in turn.
 .Sh OPTIONS
-.Bl -tag -width Ds
-.It Fl a Fl d Fl e
+.Bl -tag -width indent
+.It Fl a , d , e
 These options work as in
 .Xr showmount 8
 except that only entries pertaining to the local host are printed.
@@ -77,27 +78,31 @@ from a crash or are the result of improper mount protocol.
 The actuality of mounts is verified using the entries in
 .Pa /etc/mtab .
 .It Fl v
-Verify remote mounts.  Similar to
+Verify remote mounts.
+Similar to
 .Fl r
 except that only a notification message is printed for each bogus entry
-found.  The remote mount table is not changed.
+found.
+The remote mount table is not changed.
 .It Fl A
 Issues a command to the remote mountd declaring that
 .Em all
-of its filesystems have been unmounted.  This should be used with caution, as
-it removes all remote mount entries pertaining to the local system, whether or
-not any filesystems are still mounted locally.
-.It Fl v
-Be quiet.  Suppresses error messages due to timeouts and
-.Dq Program not Registered ,
+of its file systems have been unmounted.
+This should be used with caution, as it removes all
+remote mount entries pertaining to the local system, whether or not any
+file systems are still mounted locally.
+.It Fl q
+Be quiet.
+Suppresses error messages due to timeouts and
+.Dq Li "Program not registered" ,
 i.e., due to remote hosts not supporting RPC or not running
-.Nm mountd .
+.Xr mountd 8 .
 .It Fl h Ar name
 Pretend the local hostname is
 .Ar name .
 This is useful after the local hostname has been changed and rmtab entries
 using the old name remain on a remote machine.
-Unfortunately, most mountd's won't be able to successfully handle removal
+Unfortunately, most mountd's will not be able to successfully handle removal
 of such entries, so this option is useful in combination with
 .Fl v
 only.
@@ -106,7 +111,7 @@ This option also saves time as comparisons of remotely recorded and local
 hostnames by address are avoided.
 .El
 .Sh FILES
-.Bl -tag -width /axx
+.Bl -tag -width ".Pa /etc/rmtab"
 .It Pa /etc/mtab
 List of current mounts.
 .It Pa /etc/rmtab
@@ -119,6 +124,49 @@ server.
 .Xr rmtab 5 ,
 .Xr mountd 8 ,
 .Xr showmount 8
+.Pp
+.Dq am-utils
+.Xr info 1
+entry.
+.Rs
+.%A Erez Zadok
+.%B "Linux NFS and Automounter Administration"
+.%O ISBN 0-7821-2739-8
+.%I Sybex
+.%D 2001
+.Re
+.Pp
+.Pa http://www.am-utils.org/
+.Rs
+.%T Amd \- The 4.4 BSD Automounter
+.Re
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Fx 3.0 .
+.Sh AUTHORS
+.An Jan-Simon Pendry Aq jsp@doc.ic.ac.uk ,
+Department of Computing, Imperial College, London, UK.
+.Pp
+.An Erez Zadok Aq ezk@cs.columbia.edu ,
+Department of Computer Science, Columbia University, New York, USA.
+.Pp
+.An Other authors and contributors to
+.Nm am-utils
+are listed in the
+.Pa AUTHORS
+file distributed with
+.Nm am-utils .
+.Sh AUTHORS
+.An Andreas Stolcke Aq stolcke@icsi.berkeley.edu
+.Pp
+.An Erez Zadok Aq ezk@cs.sunysb.edu ,
+Computer Science Department, Stony Brook University, Stony Brook, New York, USA.
+.Pp
+Other authors and contributors to am-utils are listed in the
+.Pa AUTHORS
+file distributed with am-utils.
 .Sh BUGS
 No attempt is made to verify the information in
 .Pa /etc/mtab
@@ -127,16 +175,16 @@ itself.
 Since swap file mounts are not recorded in
 .Pa /etc/mtab ,
 a heuristic specific to SunOS is used to determine whether such a mount
-is actual (replacing the string 
-.Ql swap 
-with 
-.Ql root
+is actual (replacing the string
+.Dq Li swap
+with
+.Dq Li root
 and verifying the resulting path).
 .Pp
 Symbolic links on the server will cause the path in the remote entry to differ
-from the one in 
+from the one in
 .Pa /etc/mtab .
-To catch those cases, a filesystem is also deemed mounted if its
+To catch those cases, a file system is also deemed mounted if its
 .Em local
 mount point is identical to the remote entry.
 I.e., on a SunOS diskless client,
@@ -147,35 +195,20 @@ Since the local mount point is
 .Pa /usr/share
 as well this will be handled correctly.
 .Pp
-There is no way to clear a stale entry in a remote 
-.Nm mountd 
-after the local hostname (or whatever reverse name resolution 
-returns for it) has been changed.  To take care of these cases,
+There is no way to clear a stale entry in a remote
+.Xr mountd 8
+after the
+local hostname (or whatever reverse name resolution returns for it)
+has been changed.
+To take care of these cases,
 the remote
 .Pa /etc/rmtab
 file has to be edited and
-.Nm mountd
+.Xr mountd 8
 restarted.
 .Pp
 The RPC timeouts for
-.Nm mountd
-calls can only be changed by recompiling. The defaults are 2 seconds 
-for client handle creation and 5 seconds for RPC calls.
-.Sh AUTHORS
-.An Jan-Simon Pendry Aq jsp@doc.ic.ac.uk ,
-Department of Computing, Imperial College, London, UK.
-.Pp
-.An Erez Zadok Aq ezk@cs.columbia.edu ,
-Department of Computer Science, Columbia University, New York, USA.
-.Pp
-.An Other authors and contributors to 
-.Nm am-utils
-are listed in the
-.Nm AUTHORS 
-file distributed with
-.Nm am-utils .
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Fx 3.0 .
+.Xr mountd 8
+calls can only be changed by recompiling.
+The defaults are 2 seconds for client handle creation and 5 seconds for
+RPC calls.
diff --git a/contrib/amd/fixmount/fixmount.c b/contrib/amd/fixmount/fixmount.c
index ad112e4..c7c6910 100644
--- a/contrib/amd/fixmount/fixmount.c
+++ b/contrib/amd/fixmount/fixmount.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: fixmount.c,v 1.4 1999/02/04 07:24:42 ezk Exp $
- * $FreeBSD: src/contrib/amd/fixmount/fixmount.c,v 1.5 1999/09/15 05:45:14 obrien Exp $
- * $DragonFly: src/contrib/amd/fixmount/fixmount.c,v 1.2 2003/06/17 04:23:57 dillon Exp $
+ * File: am-utils/fixmount/fixmount.c
  *
  */
 
@@ -52,10 +49,6 @@
 #define CREATE_TIMEOUT	2	/* seconds */
 #define CALL_TIMEOUT	5	/* seconds */
 
-#ifndef INADDR_NONE
-# define INADDR_NONE	0xffffffff
-#endif /* not INADDR_NONE */
-
 /* Constant defs */
 #define	ALL		1
 #define	DIRS		2
@@ -122,7 +115,7 @@ is_same_host(char *name1, char *name2, struct in_addr addr2)
     } else if (!(he = gethostbyname(name1))) {
       return 0;
     } else {
-      strncpy(lasthost, name1, sizeof(lasthost) - 1);
+      xstrlcpy(lasthost, name1, MAXHOSTNAMELEN);
       memcpy(&addr1, he->h_addr, sizeof(addr1));
       return (addr1.s_addr == addr2.s_addr);
     }
@@ -166,7 +159,7 @@ remove_mount(CLIENT *client, char *host, mountlist ml, int fixit)
   struct timeval tv;
   char *pathp = dir_path;
 
-  strncpy(dir_path, ml->ml_directory, sizeof(dir_path));
+  xstrlcpy(dir_path, ml->ml_directory, sizeof(dir_path));
 
   if (!fixit) {
     printf("%s: bogus mount %s:%s\n", host, ml->ml_hostname, ml->ml_directory);
@@ -328,8 +321,7 @@ main(int argc, char *argv[])
       break;
 
     case 'h':
-      strncpy(thishost, optarg, sizeof(thishost));
-      thishost[sizeof(thishost) - 1] = '\0';
+      xstrlcpy(thishost, optarg, sizeof(thishost));
       break;
 
     case '?':
@@ -369,8 +361,7 @@ main(int argc, char *argv[])
 	      inet_ntoa(thisaddr));
       exit(1);
     }
-    strncpy(thishost, he->h_name, sizeof(thishost));
-    thishost[sizeof(thishost) - 1] = '\0';
+    xstrlcpy(thishost, he->h_name, sizeof(thishost));
   } else {
     thisaddr.s_addr = INADDR_NONE;
   }
@@ -499,8 +490,10 @@ inetresport(int ty)
   struct sockaddr_in addr;
   int fd;
 
-  /* Use internet address family */
-  addr.sin_family = AF_INET;
+  memset(&addr, 0, sizeof(addr));
+  /* as per POSIX, sin_len need not be set (used internally by kernel) */
+
+  addr.sin_family = AF_INET;	/* use internet address family */
   addr.sin_addr.s_addr = INADDR_ANY;
   if ((fd = socket(AF_INET, ty, 0)) < 0)
     return -1;
@@ -570,7 +563,8 @@ clnt_create_timeout(char *host, struct timeval *tvp)
     fprintf(stderr, "can't get address of %s\n", host);
     return NULL;
   }
-  memset(&host_addr, 0, sizeof host_addr);
+  memset(&host_addr, 0, sizeof(host_addr));
+  /* as per POSIX, sin_len need not be set (used internally by kernel) */
   host_addr.sin_family = AF_INET;
   if (hp) {
     memmove((voidp) &host_addr.sin_addr, (voidp) hp->h_addr,
diff --git a/contrib/amd/fsinfo/fsi_analyze.c b/contrib/amd/fsinfo/fsi_analyze.c
index 7ba7a95..9da4097 100644
--- a/contrib/amd/fsinfo/fsi_analyze.c
+++ b/contrib/amd/fsinfo/fsi_analyze.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: fsi_analyze.c,v 1.2 1999/01/10 21:54:27 ezk Exp $
+ * File: am-utils/fsinfo/fsi_analyze.c
  *
  */
 
@@ -112,10 +111,11 @@ domain_strip(char *otherdom, char *localdom)
 static char *
 compute_hostpath(char *hn)
 {
-  char *p = strdup(hn);
+  char *p = xmalloc(MAXPATHLEN);
   char *d;
   char path[MAXPATHLEN];
 
+  xstrlcpy(p, hn, MAXPATHLEN);
   domain_strip(p, hostname);
   path[0] = '\0';
 
@@ -123,16 +123,16 @@ compute_hostpath(char *hn)
     d = strrchr(p, '.');
     if (d) {
       *d = 0;
-      strcat(path, d + 1);
-      strcat(path, "/");
+      xstrlcat(path, d + 1, sizeof(path));
+      xstrlcat(path, "/", sizeof(path));
     } else {
-      strcat(path, p);
+      xstrlcat(path, p, sizeof(path));
     }
   } while (d);
 
-  log("hostpath of '%s' is '%s'", hn, path);
+  fsi_log("hostpath of '%s' is '%s'", hn, path);
 
-  strcpy(p, path);
+  xstrlcpy(p, path, MAXPATHLEN);
   return p;
 }
 
@@ -145,7 +145,7 @@ find_volname(char *nn)
   char *q;
 
   do {
-    log("Searching for volname %s", p);
+    fsi_log("Searching for volname %s", p);
     de = dict_locate(dict_of_volnames, p);
     q = strrchr(p, '/');
     if (q)
@@ -161,7 +161,7 @@ static void
 show_required(ioloc *l, int mask, char *info, char *hostname, char *strings[])
 {
   int i;
-  log("mask left for %s:%s is %#x", hostname, info, mask);
+  fsi_log("mask left for %s:%s is %#x", hostname, info, mask);
 
   for (i = 0; strings[i]; i++)
     if (ISSET(mask, i))
@@ -218,15 +218,15 @@ analyze_dkmount_tree(qelem *q, fsi_mount *parent, disk_fs *dk)
   int errors = 0;
 
   ITER(mp, fsi_mount, q) {
-    log("Mount %s:", mp->m_name);
+    fsi_log("Mount %s:", mp->m_name);
     if (parent) {
       char n[MAXPATHLEN];
-      sprintf(n, "%s/%s", parent->m_name, mp->m_name);
+      xsnprintf(n, sizeof(n), "%s/%s", parent->m_name, mp->m_name);
       if (*mp->m_name == '/')
 	lerror(mp->m_ioloc, "sub-directory %s of %s starts with '/'", mp->m_name, parent->m_name);
       else if (STREQ(mp->m_name, "default"))
 	lwarning(mp->m_ioloc, "sub-directory of %s is named \"default\"", parent->m_name);
-      log("Changing name %s to %s", mp->m_name, n);
+      fsi_log("Changing name %s to %s", mp->m_name, n);
       XFREE(mp->m_name);
       mp->m_name = strdup(n);
     }
@@ -281,13 +281,13 @@ analyze_dkmounts(disk_fs *dk, qelem *q)
   /*
    * Now see if a default mount point is required
    */
-  if (STREQ(mp2->m_name, "default")) {
+  if (mp2 && STREQ(mp2->m_name, "default")) {
     if (ISSET(mp2->m_mask, DM_VOLNAME)) {
       char nbuf[1024];
-      compute_automount_point(nbuf, dk->d_host, mp2->m_volname);
+      compute_automount_point(nbuf, sizeof(nbuf), dk->d_host, mp2->m_volname);
       XFREE(mp2->m_name);
       mp2->m_name = strdup(nbuf);
-      log("%s:%s has default mount on %s", dk->d_host->h_hostname, dk->d_dev, mp2->m_name);
+      fsi_log("%s:%s has default mount on %s", dk->d_host->h_hostname, dk->d_dev, mp2->m_name);
     } else {
       lerror(dk->d_ioloc, "no volname given for %s:%s", dk->d_host->h_hostname, dk->d_dev);
       errors++;
@@ -422,24 +422,24 @@ fixup_required_mount_info(fsmount *fp, dict_ent *de)
 	abort();
       fp->f_ref = mp;
       set_fsmount(fp, FM_FROM, mp->m_dk->d_host->h_hostname);
-      log("set: %s comes from %s", fp->f_volname, fp->f_from);
+      fsi_log("set: %s comes from %s", fp->f_volname, fp->f_from);
     }
   }
 
   if (!ISSET(fp->f_mask, FM_FSTYPE)) {
     set_fsmount(fp, FM_FSTYPE, strdup("nfs"));
-    log("set: fstype is %s", fp->f_fstype);
+    fsi_log("set: fstype is %s", fp->f_fstype);
   }
 
   if (!ISSET(fp->f_mask, FM_OPTS)) {
     set_fsmount(fp, FM_OPTS, strdup("rw,nosuid,grpid,defaults"));
-    log("set: opts are %s", fp->f_opts);
+    fsi_log("set: opts are %s", fp->f_opts);
   }
 
   if (!ISSET(fp->f_mask, FM_LOCALNAME)) {
     if (fp->f_ref) {
       set_fsmount(fp, FM_LOCALNAME, strdup(fp->f_volname));
-      log("set: localname is %s", fp->f_localname);
+      fsi_log("set: localname is %s", fp->f_localname);
     } else {
       lerror(fp->f_ioloc, "cannot determine localname since volname %s is not uniquely defined", fp->f_volname);
     }
@@ -461,7 +461,7 @@ analyze_drives(host *hp)
 
   ITER(dp, disk_fs, q) {
     int req;
-    log("Disk %s:", dp->d_dev);
+    fsi_log("Disk %s:", dp->d_dev);
     dp->d_host = hp;
     fixup_required_disk_info(dp);
     req = ~dp->d_mask & DF_REQUIRED;
@@ -498,7 +498,7 @@ analyze_mounts(host *hp)
       do {
 	p = 0;
 	de = find_volname(nn);
-	log("Mount: %s (trying %s)", fp->f_volname, nn);
+	fsi_log("Mount: %s (trying %s)", fp->f_volname, nn);
 
 	if (de) {
 	  found = 1;
@@ -516,7 +516,8 @@ analyze_mounts(host *hp)
 	    ITER(dd, dict_data, &de->de_q) {
 	      fsi_mount *mp = (fsi_mount *) dd->dd_data;
 
-	      if (STREQ(mp->m_dk->d_host->h_hostname, fp->f_from)) {
+	      if (fp->f_from &&
+		  STREQ(mp->m_dk->d_host->h_hostname, fp->f_from)) {
 		mp2 = mp;
 		break;
 	      }
@@ -542,7 +543,8 @@ analyze_mounts(host *hp)
       lerror(fp->f_ioloc, "volname %s unknown", fp->f_volname);
     } else if (matched) {
 
-      fixup_required_mount_info(fp, de);
+      if (de)
+	fixup_required_mount_info(fp, de);
       req = ~fp->f_mask & FM_REQUIRED;
       if (req) {
 	show_required(fp->f_ioloc, req, fp->f_volname, hp->h_hostname,
@@ -577,7 +579,7 @@ analyze_hosts(qelem *q)
    * Check all drives
    */
   ITER(hp, host, q) {
-    log("disks on host %s", hp->h_hostname);
+    fsi_log("disks on host %s", hp->h_hostname);
     show_new("ana-host");
     hp->h_hostpath = compute_hostpath(hp->h_hostname);
 
@@ -592,7 +594,7 @@ analyze_hosts(qelem *q)
    * Check static mounts
    */
   ITER(hp, host, q) {
-    log("mounts on host %s", hp->h_hostname);
+    fsi_log("mounts on host %s", hp->h_hostname);
     show_new("ana-mount");
     if (hp->h_mount)
       analyze_mounts(hp);
@@ -631,24 +633,24 @@ analyze_automount_tree(qelem *q, char *pref, int lvl)
     if (lvl > 0 || ap->a_mount)
       if (ap->a_name[1] && strchr(ap->a_name + 1, '/'))
 	lerror(ap->a_ioloc, "not allowed '/' in a directory name");
-    sprintf(nname, "%s/%s", pref, ap->a_name);
+    xsnprintf(nname, sizeof(nname), "%s/%s", pref, ap->a_name);
     XFREE(ap->a_name);
     ap->a_name = strdup(nname[1] == '/' ? nname + 1 : nname);
-    log("automount point %s:", ap->a_name);
+    fsi_log("automount point %s:", ap->a_name);
     show_new("ana-automount");
 
     if (ap->a_mount) {
       analyze_automount_tree(ap->a_mount, ap->a_name, lvl + 1);
     } else if (ap->a_hardwiredfs) {
-      log("\thardwired from %s to %s", ap->a_volname, ap->a_hardwiredfs);
+      fsi_log("\thardwired from %s to %s", ap->a_volname, ap->a_hardwiredfs);
     } else if (ap->a_volname) {
-      log("\tautomount from %s", ap->a_volname);
+      fsi_log("\tautomount from %s", ap->a_volname);
       analyze_automount(ap);
     } else if (ap->a_symlink) {
-      log("\tsymlink to %s", ap->a_symlink);
+      fsi_log("\tsymlink to %s", ap->a_symlink);
     } else {
       ap->a_volname = strdup(ap->a_name);
-      log("\timplicit automount from %s", ap->a_volname);
+      fsi_log("\timplicit automount from %s", ap->a_volname);
       analyze_automount(ap);
     }
   }
diff --git a/contrib/amd/fsinfo/fsi_data.h b/contrib/amd/fsinfo/fsi_data.h
index 96472bb..8276caf 100644
--- a/contrib/amd/fsinfo/fsi_data.h
+++ b/contrib/amd/fsinfo/fsi_data.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,12 +36,14 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: fsi_data.h,v 1.2 1999/01/10 21:54:27 ezk Exp $
+ * File: am-utils/fsinfo/fsi_data.h
  *
  */
 
+#ifndef _FSI_DATA_H
+#define _FSI_DATA_H
+
 typedef struct auto_tree auto_tree;
 typedef struct automount automount;
 typedef struct dict dict;
@@ -233,3 +235,4 @@ struct ioloc {
   int i_line;
   char *i_file;
 };
+#endif /* not _FSI_DATA_H */
diff --git a/contrib/amd/fsinfo/fsi_dict.c b/contrib/amd/fsinfo/fsi_dict.c
index 395317d..29cd1a3 100644
--- a/contrib/amd/fsinfo/fsi_dict.c
+++ b/contrib/amd/fsinfo/fsi_dict.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: fsi_dict.c,v 1.2 1999/01/10 21:54:28 ezk Exp $
+ * File: am-utils/fsinfo/fsi_dict.c
  *
  */
 
diff --git a/contrib/amd/fsinfo/fsi_gram.y b/contrib/amd/fsinfo/fsi_gram.y
index 97a76bf..961a89f 100644
--- a/contrib/amd/fsinfo/fsi_gram.y
+++ b/contrib/amd/fsinfo/fsi_gram.y
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	%W% (Berkeley) %G%
  *
- * $Id: fsi_gram.y,v 1.3 1999/04/16 14:21:14 ezk Exp $
+ * File: am-utils/fsinfo/fsi_gram.y
  *
  */
 
@@ -50,22 +49,6 @@
 #include <fsi_data.h>
 #include <fsinfo.h>
 
-/* AIX requires this to be the first thing in the file. */
-#ifndef __GNUC__
-# if HAVE_ALLOCA_H
-#  include <alloca.h>
-# else /* not HAVE_ALLOCA_H */
-#  ifdef _AIX
-#pragma alloca
-#  else /* not _AIX */
-#   ifndef alloca
-  /* predefined by HP cc +Olibcalls */
-voidp alloca();
-#   endif /* not alloca */
-#  endif /* not _AIX */
-# endif /* not HAVE_ALLOCA_H */
-#endif /* not __GNUC__ */
-
 extern qelem *list_of_hosts, *list_of_automounts;
 %}
 
diff --git a/contrib/amd/fsinfo/fsi_lex.l b/contrib/amd/fsinfo/fsi_lex.l
index 7ae097c..6bca59b 100644
--- a/contrib/amd/fsinfo/fsi_lex.l
+++ b/contrib/amd/fsinfo/fsi_lex.l
@@ -1,6 +1,6 @@
 %{
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -37,9 +37,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	%W% (Berkeley) %G%
  *
- * $Id: fsi_lex.l,v 1.3 1999/09/30 21:01:41 ezk Exp $
+ * File: am-utils/fsinfo/fsi_lex.l
  *
  */
 
@@ -48,8 +47,9 @@
  * TODO: Needs rewriting.
  */
 
-#ifdef FLEX_SCANNER
 static int ayylineno;
+
+#ifdef FLEX_SCANNER
 # define INIT_STATE {				\
 		switch ((yy_start - 1) / 2) {	\
 		case 0:				\
@@ -159,6 +159,13 @@ struct r {
 
 %}
 
+/* This option causes Solaris lex to fail.  Use flex.  See BUGS file */
+/* no need to use yyunput() */
+%option nounput
+
+/* allocate more output slots so lex scanners don't run out of mem */
+%o 1024
+
 %start F Q
 
 %%
@@ -236,11 +243,10 @@ yyerror(char *fmt, ...)
   va_start(ap, fmt);
   col_cleanup(0);
   fprintf(stderr, "%s:%d: ", fsi_filename ? fsi_filename : "/dev/stdin", ayylineno);
-  fprintf(stderr, fmt, ap);
+  vfprintf(stderr, fmt, ap);
   fputc('\n', stderr);
   parse_errors++;
   va_end(ap);
-  if (0) unput(0);/* dummy to shut gcc up: "unput defined but not used" */
   return 0;
 }
 
diff --git a/contrib/amd/fsinfo/fsi_util.c b/contrib/amd/fsinfo/fsi_util.c
index f3fe793..5e7571f 100644
--- a/contrib/amd/fsinfo/fsi_util.c
+++ b/contrib/amd/fsinfo/fsi_util.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -33,9 +33,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: fsi_util.c,v 1.2 1999/01/10 21:54:28 ezk Exp $
+ * File: am-utils/fsinfo/fsi_util.c
  *
  */
 
@@ -77,7 +76,7 @@ show_total(void)
 
     if (total_mmm < 0)
       fputc('*', stdout);
-    sprintf(n, "%d", total_shown);
+    xsnprintf(n, sizeof(n), "%d", total_shown);
     len = strlen(n);
     if (col_output(len))
       fputc(' ', stdout);
@@ -115,7 +114,7 @@ error(char *fmt, ...)
   va_start(ap, fmt);
   col_cleanup(0);
   fprintf(stderr, "%s: Error, ", progname);
-  fprintf(stderr, fmt, ap);
+  vfprintf(stderr, fmt, ap);
   fputc('\n', stderr);
   errors++;
   va_end(ap);
@@ -130,7 +129,7 @@ lerror(ioloc *l, char *fmt, ...)
   va_start(ap, fmt);
   col_cleanup(0);
   fprintf(stderr, "%s:%d: ", l->i_file, l->i_line);
-  fprintf(stderr, fmt, ap);
+  vfprintf(stderr, fmt, ap);
   fputc('\n', stderr);
   errors++;
   va_end(ap);
@@ -145,7 +144,7 @@ lwarning(ioloc *l, char *fmt, ...)
   va_start(ap, fmt);
   col_cleanup(0);
   fprintf(stderr, "%s:%d: ", l->i_file, l->i_line);
-  fprintf(stderr, fmt, ap);
+  vfprintf(stderr, fmt, ap);
   fputc('\n', stderr);
   va_end(ap);
 }
@@ -159,7 +158,7 @@ fatal(char *fmt, ...)
   va_start(ap, fmt);
   col_cleanup(1);
   fprintf(stderr, "%s: Fatal, ", progname);
-  fprintf(stderr, fmt, ap);
+  vfprintf(stderr, fmt, ap);
   fputc('\n', stderr);
   va_end(ap);
   exit(1);
@@ -170,7 +169,7 @@ fatal(char *fmt, ...)
  * Debug log
  */
 void
-log(char *fmt, ...)
+fsi_log(char *fmt, ...)
 {
   va_list ap;
 
@@ -178,7 +177,7 @@ log(char *fmt, ...)
     va_start(ap, fmt);
     fputc('#', stdout);
     fprintf(stdout, "%s: ", progname);
-    fprintf(stdout, fmt, ap);
+    vfprintf(stdout, fmt, ap);
     putc('\n', stdout);
     va_end(ap);
   }
@@ -276,8 +275,8 @@ pref_open(char *pref, char *hn, void (*hdr) (FILE *, char *), char *arg)
   char p[MAXPATHLEN];
   FILE *ef;
 
-  sprintf(p, "%s%s", pref, hn);
-  log("Writing %s info for %s to %s", pref, hn, p);
+  xsnprintf(p, sizeof(p), "%s%s", pref, hn);
+  fsi_log("Writing %s info for %s to %s", pref, hn, p);
   ef = fopen(p, "w");
   if (ef) {
     (*hdr) (ef, arg);
@@ -301,20 +300,9 @@ pref_close(FILE *fp)
  * Determine where Amd would automount the host/volname pair
  */
 void
-compute_automount_point(char *buf, host *hp, char *vn)
+compute_automount_point(char *buf, size_t l, host *hp, char *vn)
 {
-  sprintf(buf, "%s/%s%s", autodir, hp->h_lochost, vn);
-}
-
-
-char *
-xcalloc(int i, int s)
-{
-  char *p = (char *) calloc(i, (unsigned) s);
-
-  if (!p)
-    fatal("Out of memory");
-  return p;
+  xsnprintf(buf, l, "%s/%s%s", autodir, hp->h_lochost, vn);
 }
 
 
@@ -463,7 +451,7 @@ set_ether_if(ether_if *ep, int k, char *v)
 
   case EF_INADDR:{
       ep->e_inaddr.s_addr = inet_addr(v);
-      if (ep->e_inaddr.s_addr == (u_long) - 1)
+      if ((int) ep->e_inaddr.s_addr == (int) INADDR_NONE)
 	yyerror("malformed IP dotted quad: %s", v);
       XFREE(v);
     }
diff --git a/contrib/amd/fsinfo/fsinfo.8 b/contrib/amd/fsinfo/fsinfo.8
index 1acef51..f22af8e 100644
--- a/contrib/amd/fsinfo/fsinfo.8
+++ b/contrib/amd/fsinfo/fsinfo.8
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-1999 Erez Zadok
+.\" Copyright (c) 1997-2006 Erez Zadok
 .\" Copyright (c) 1993 Jan-Simon Pendry.
 .\" Copyright (c) 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -33,16 +33,15 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     from: @(#)fsinfo.8	8.1 (Berkeley) 6/28/93
-.\"	$Id: fsinfo.8,v 1.2 1999/01/10 21:54:28 ezk Exp $
-.\"	$FreeBSD: src/contrib/amd/fsinfo/fsinfo.8,v 1.4.2.2 2001/03/06 16:54:05 ru Exp $
-.\"	$DragonFly: src/contrib/amd/fsinfo/fsinfo.8,v 1.2 2003/06/17 04:23:57 dillon Exp $
+.\"	$Id: fsinfo.8,v 1.13.2.1 2006/01/02 18:48:25 ezk Exp $
+.\"	$FreeBSD: src/contrib/amd/fsinfo/fsinfo.8,v 1.16 2012/11/17 01:48:41 svnexp Exp $
 .\"
-.Dd June 26, 1999
+.Dd January 2, 2006
 .Dt FSINFO 8
 .Os
 .Sh NAME
 .Nm fsinfo
-.Nd co-ordinate site-wide filesystem information
+.Nd co-ordinate site-wide file system information
 .Sh SYNOPSIS
 .Nm
 .Op Fl qv
@@ -64,23 +63,25 @@
 The
 .Nm
 utility takes a set of system configuration information, and generates
-a co-ordinated set of
-.Xr amd ,
-.Xr mount
+a coordinated set of
+.Xr amd 8 ,
+.Xr mount 8
 and
-.Xr mountd
+.Xr mountd 8
 configuration files.
 .Pp
 The following options are available:
 .Bl -tag -width Fl
 .It Fl a Ar autodir
 Specifies the directory name in which to place the automounter's
-mount points.  This defaults to
+mount points.
+This defaults to
 .Pa /a .
 .It Fl b Ar bootparams_prefix
-Specifies the prefix for the 
+Specifies the prefix for the
 .Pa bootparams
-file.  If it is not given, then the file will not be generated.
+file.
+If it is not given, then the file will not be generated.
 The file will be constructed for the destination machine and will be
 placed into a file named
 .Pa bootparams
@@ -92,7 +93,8 @@ diskless client that can boot from the destination machine.
 .It Fl d Ar dumpsets_prefix
 Specifies the prefix for the
 .Pa dumpsets
-file.  If it is not specified, then the file will not be generated.
+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 file
 named
 .Pa dumpsets
@@ -105,7 +107,8 @@ local backup system.
 .It Fl e Ar exports_prefix
 Defines the prefix for the
 .Pa exports
-files.  If it is not given, then the file will not be generated.
+files.
+If it is not given, then the file will not be generated.
 For each machine defined in the configuration files as having disks,
 and
 .Pa exports
@@ -114,37 +117,45 @@ machine, prefixed with the
 .Ar exports_prefix
 string.
 If a machine is defined as diskless, then no
-file will be created for it.  The files contain entries
+file will be created for it.
+The files contain entries
 for directories on the machine that may be exported to clients.
 .It Fl f Ar fstabs_prefix
 This defines the prefix for the
 .Pa fstab
-files.  The files will only be created if this prefix is defined.
+files.
+The files will only be created if this prefix is defined.
 For each machine defined in the configuration files, a
 .Pa fstab
 file is created with the file name determined by prefixing this
 .Ar fstabs_prefix
-string with the name of the machine.  These files contain entries
-for filesystems and partitions to mount at boot time.
+string with the name of the machine.
+These files contain entries
+for file systems and partitions to mount at boot time.
 .It Fl h Ar hostname
 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
 .Xr gethostname 3 .
 .It Fl m Ar automounts_prefix
-Defines the prefix for the automounter files.  The maps will
-only be produced if this option is specified.  The mount maps
+Defines the prefix for the automounter files.
+The maps will
+only be produced if this option is specified.
+The mount maps
 suitable for the network defined by the configuration files will
 be placed into files with names calculated by prefixing the
 .Ar automounts_prefix
 string to the name of each map.
 .It Fl q
-Selects quite mode.  Only error messages that are generated will
+Selects quite mode.
+Only error messages that are generated will
 be displayed.
 .It Fl v
-Selects verbose mode.  When this is activated, more messages
+Selects verbose mode.
+When this is activated, more messages
 will be displayed, and all information discovered when performing the semantic
-analysis phase will be displayed.  Each verbose message
+analysis phase will be displayed.
+Each verbose message
 is output to the standard output on a line starting with a `#'
 character.
 .It Fl D Xo
@@ -158,7 +169,8 @@ Equivalent to the
 directive.
 .It Fl I Ar dir
 This option is passed into the preprocessor for the configuration
-files.  It specifies directories in which to find include files.
+files.
+It specifies directories in which to find include files.
 .It Fl U Ar name
 Removes and initial definition of the symbol
 .Ar name .
@@ -166,24 +178,46 @@ Inverse of the
 .Fl D
 option.
 .It Ar config
-One or more configuration files to be passed as input to 
-.Nm fsinfo .
+One or more configuration files to be passed as input to
+.Nm .
 .El
 .Pp
 The
 .Nm
 command is fully described in the document
-.%T "Amd - The 4.4BSD Automounter"
-and in the
-.Nm amd
-section in
-.Xr info 1 .
-.Sh "SEE ALSO"
+.%T "Amd - The 4.4BSD Automounter" .
+.Sh SEE ALSO
 .Xr amd 8 ,
 .Xr mount 8 ,
 .Xr mountd 8
+.Pp
+.Dq am-utils
+.Xr info 1
+entry.
+.Rs
+.%A Erez Zadok
+.%B "Linux NFS and Automounter Administration"
+.%O ISBN 0-7821-2739-8
+.%I Sybex
+.%D 2001
+.Re
+.Pp
+.Pa http://www.am-utils.org/
+.Rs
+.%T Amd \- The 4.4 BSD Automounter
+.Re
 .Sh HISTORY
 The
 .Nm
 command first appeared in
 .Bx 4.4 .
+.Sh AUTHORS
+.An Jan-Simon Pendry Aq jsp@doc.ic.ac.uk ,
+Department of Computing, Imperial College, London, UK.
+.Pp
+.An Erez Zadok Aq ezk@cs.sunysb.edu ,
+Computer Science Department, Stony Brook University, Stony Brook, New York, USA.
+.Pp
+Other authors and contributors to am-utils are listed in the
+.Pa AUTHORS
+file distributed with am-utils.
diff --git a/contrib/amd/fsinfo/fsinfo.c b/contrib/amd/fsinfo/fsinfo.c
index 2ff6588..e441a47 100644
--- a/contrib/amd/fsinfo/fsinfo.c
+++ b/contrib/amd/fsinfo/fsinfo.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: fsinfo.c,v 1.4 1999/02/04 07:24:44 ezk Exp $
- * $FreeBSD: src/contrib/amd/fsinfo/fsinfo.c,v 1.4 1999/09/15 05:45:15 obrien Exp $
- * $DragonFly: src/contrib/amd/fsinfo/fsinfo.c,v 1.2 2003/06/17 04:23:57 dillon Exp $
+ * File: am-utils/fsinfo/fsinfo.c
  *
  */
 
@@ -127,7 +124,7 @@ fsi_get_args(int c, char *v[])
       break;
 
     case 'h':
-      strncpy(hostname, optarg, sizeof(hostname) - 1);
+      xstrlcpy(hostname, optarg, sizeof(hostname));
       break;
 
     case 'e':
@@ -159,7 +156,8 @@ fsi_get_args(int c, char *v[])
     case 'I':
     case 'D':
     case 'U':
-      sprintf(iptr, "-%c%s ", ch, optarg);
+      /* sizeof(iptr) is actually that of idvbuf.  See declaration above */
+      xsnprintf(iptr, sizeof(idvbuf), "-%c%s ", ch, optarg);
       iptr += strlen(iptr);
       break;
 
@@ -170,7 +168,9 @@ fsi_get_args(int c, char *v[])
 
   if (c != optind) {
     g_argv = v + optind - 1;
+#ifdef yywrap
     if (yywrap())
+#endif /* yywrap */
       fatal("Cannot read any input files");
   } else {
     usage++;
@@ -186,9 +186,9 @@ Usage: %s [-v] [-a autodir] [-h hostname] [-b bootparams] [-d dumpsets]\n\
   }
 
   if (g_argv[0])
-    log("g_argv[0] = %s", g_argv[0]);
+    fsi_log("g_argv[0] = %s", g_argv[0]);
   else
-    log("g_argv[0] = (nil)");
+    fsi_log("g_argv[0] = (nil)");
 }
 
 
@@ -198,7 +198,7 @@ Usage: %s [-v] [-a autodir] [-h hostname] [-b bootparams] [-d dumpsets]\n\
 static char *
 find_username(void)
 {
-  char *u = getlogin();
+  const char *u = getlogin();
 
   if (!u) {
     struct passwd *pw = getpwuid(getuid());
@@ -235,6 +235,7 @@ main(int argc, char *argv[])
     perror("gethostname");
     exit(1);
   }
+  hostname[sizeof(hostname) - 1] = '\0';
 
   /*
    * Get the username
diff --git a/contrib/amd/fsinfo/fsinfo.h b/contrib/amd/fsinfo/fsinfo.h
index 626cb4c..99b407b 100644
--- a/contrib/amd/fsinfo/fsinfo.h
+++ b/contrib/amd/fsinfo/fsinfo.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: fsinfo.h,v 1.3 1999/01/10 21:54:29 ezk Exp $
+ * File: am-utils/fsinfo/fsinfo.h
  *
  */
 
@@ -81,17 +80,22 @@ extern fsi_mount *new_mount(void);
 extern qelem *new_que(void);
 extern void analyze_automounts(qelem *);
 extern void analyze_hosts(qelem *);
-extern void compute_automount_point(char *, host *, char *);
+extern void compute_automount_point(char *, size_t, host *, char *);
 extern void dict_add(dict *, char *, char *);
-extern void error(char *fmt, ...);
-extern void fatal(char *fmt, ...);
+extern void error(char *fmt, ...)
+	__attribute__((__format__(__printf__, 1, 2)));
+extern void fatal(char *fmt, ...)
+	__attribute__((__format__(__printf__, 1, 2)));
 extern void gen_hdr(FILE *ef, char *hn);
 extern void info_hdr(FILE *ef, char *info);
 extern void init_que(qelem *);
 extern void ins_que(qelem *, qelem *);
-extern void lerror(ioloc *l, char *fmt, ...);
-extern void log(char *fmt, ...);
-extern void lwarning(ioloc *l, char *fmt, ...);
+extern void lerror(ioloc *l, char *fmt, ...)
+	__attribute__((__format__(__printf__, 2, 3)));
+extern void fsi_log(char *fmt, ...)
+	__attribute__((__format__(__printf__, 1, 2)));
+extern void lwarning(ioloc *l, char *fmt, ...)
+	__attribute__((__format__(__printf__, 2, 3)));
 extern void rem_que(qelem *);
 extern void set_disk_fs(disk_fs *, int, char *);
 extern void set_fsmount(fsmount *, int, char *);
@@ -100,7 +104,8 @@ extern void show_area_being_processed(char *area, int n);
 extern void show_new(char *msg);
 extern void warning(void);
 
-extern int yyerror(char *fmt, ...);
+extern int yyerror(char *fmt, ...)
+	__attribute__((__format__(__printf__, 1, 2)));
 extern void domain_strip(char *otherdom, char *localdom);
 /*
  * some systems such as DU-4.x have a different GNU flex in /usr/bin
diff --git a/contrib/amd/fsinfo/wr_atab.c b/contrib/amd/fsinfo/wr_atab.c
index bf6bb40..e02db07 100644
--- a/contrib/amd/fsinfo/wr_atab.c
+++ b/contrib/amd/fsinfo/wr_atab.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: wr_atab.c,v 1.2 1999/01/10 21:54:29 ezk Exp $
+ * File: am-utils/fsinfo/wr_atab.c
  *
  */
 
@@ -54,7 +53,7 @@
  * Write a sequence of automount mount map entries
  */
 static int
-write_amount_info(FILE *af, automount *ap,  int sk)
+write_amount_info(FILE *af, automount *ap,  u_int sk)
 {
   int errors = 0;
 
@@ -135,7 +134,8 @@ write_amount_info(FILE *af, automount *ap,  int sk)
        */
       if (mp->m_dk->d_host->h_lochost) {
 	char amountpt[1024];
-	compute_automount_point(amountpt, mp->m_dk->d_host, mp->m_exported->m_volname);
+	compute_automount_point(amountpt, sizeof(amountpt),
+				mp->m_dk->d_host, mp->m_exported->m_volname);
 	if (!STREQ(mp->m_dk->d_mountpt, amountpt)) {
 	  /*
 	   * ap->a_volname is the name of the aliased volume
@@ -221,12 +221,12 @@ write_amount_info(FILE *af, automount *ap,  int sk)
 	char sublink[1024];
 	sublink[0] = '\0';
 	if (exp_namelen < namelen) {
-	  strcat(sublink, mp->m_name + exp_namelen + 1);
+	  xstrlcat(sublink, mp->m_name + exp_namelen + 1, sizeof(sublink));
 	  if (mvolnlen < volnlen)
-	    strcat(sublink, "/");
+	    xstrlcat(sublink, "/", sizeof(sublink));
 	}
 	if (mvolnlen < volnlen)
-	  strcat(sublink, ap->a_volname + mvolnlen + 1);
+	  xstrlcat(sublink, ap->a_volname + mvolnlen + 1, sizeof(sublink));
 
 	fprintf(af, ";sublink:=%s", sublink);
       }
diff --git a/contrib/amd/fsinfo/wr_bparam.c b/contrib/amd/fsinfo/wr_bparam.c
index 61956c6..9220762 100644
--- a/contrib/amd/fsinfo/wr_bparam.c
+++ b/contrib/amd/fsinfo/wr_bparam.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: wr_bparam.c,v 1.2 1999/01/10 21:54:29 ezk Exp $
+ * File: am-utils/fsinfo/wr_bparam.c
  *
  */
 
diff --git a/contrib/amd/fsinfo/wr_dumpset.c b/contrib/amd/fsinfo/wr_dumpset.c
index 0428c09..69c1257 100644
--- a/contrib/amd/fsinfo/wr_dumpset.c
+++ b/contrib/amd/fsinfo/wr_dumpset.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: wr_dumpset.c,v 1.2 1999/01/10 21:54:30 ezk Exp $
+ * File: am-utils/fsinfo/wr_dumpset.c
  *
  */
 
diff --git a/contrib/amd/fsinfo/wr_exportfs.c b/contrib/amd/fsinfo/wr_exportfs.c
index 16e18c8..818d893 100644
--- a/contrib/amd/fsinfo/wr_exportfs.c
+++ b/contrib/amd/fsinfo/wr_exportfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: wr_exportfs.c,v 1.2 1999/01/10 21:54:30 ezk Exp $
+ * File: am-utils/fsinfo/wr_exportfs.c
  *
  */
 
diff --git a/contrib/amd/fsinfo/wr_fstab.c b/contrib/amd/fsinfo/wr_fstab.c
index a63d47d..52cebbf 100644
--- a/contrib/amd/fsinfo/wr_fstab.c
+++ b/contrib/amd/fsinfo/wr_fstab.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: wr_fstab.c,v 1.2 1999/01/10 21:54:30 ezk Exp $
+ * File: am-utils/fsinfo/wr_fstab.c
  *
  */
 
@@ -326,7 +325,7 @@ write_fstab(qelem *q)
 	  if (hp->h_disk_fs)
 	    errors += write_dkfstab(ef, hp->h_disk_fs, op->op_fstab);
 	  else
-	    log("No local disk mounts on %s", hp->h_hostname);
+	    fsi_log("No local disk mounts on %s", hp->h_hostname);
 
 	  if (hp->h_mount)
 	    errors += write_dkrmount(ef, hp->h_mount, hp->h_hostname, op->op_mount);
diff --git a/contrib/amd/hlfsd/hlfsd.8 b/contrib/amd/hlfsd/hlfsd.8
index 64c28e2..d41ad45 100644
--- a/contrib/amd/hlfsd/hlfsd.8
+++ b/contrib/amd/hlfsd/hlfsd.8
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-1999 Erez Zadok
+.\" Copyright (c) 1997-2006 Erez Zadok
 .\" Copyright (c) 1989 Jan-Simon Pendry
 .\" Copyright (c) 1989 Imperial College of Science, Technology & Medicine
 .\" Copyright (c) 1989 The Regents of the University of California.
@@ -36,48 +36,46 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $Id: hlfsd.8,v 1.2 1999/01/10 21:54:32 ezk Exp $
-.\" $FreeBSD: src/contrib/amd/hlfsd/hlfsd.8,v 1.5.2.5 2001/08/16 10:53:40 ru Exp $
-.\" $DragonFly: src/contrib/amd/hlfsd/hlfsd.8,v 1.2 2003/06/17 04:23:57 dillon Exp $
+.\" $Id: hlfsd.8,v 1.11.2.1 2006/01/02 18:48:25 ezk Exp $
+.\" $FreeBSD: src/contrib/amd/hlfsd/hlfsd.8,v 1.18 2012/11/17 01:48:41 svnexp Exp $
 .\"
 .\" HLFSD was written at Columbia University Computer Science Department, by
 .\" Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@smarts.com>
 .\" It is distributed under the same terms and conditions as AMD.
 .\"
-.Dd September 14, 1993
+.Dd January 2, 2006
 .Dt HLFSD 8
 .Os
 .Sh NAME
 .Nm hlfsd
 .Nd home-link file system daemon
 .Sh SYNOPSIS
-.Nm 
+.Nm
 .Op Fl fhnpvC
 .Op Fl a Ar alt_dir
-.Bk -words
 .Op Fl c Ar cache-interval
-.Ek
 .Op Fl g Ar group
-.Bk -words
 .Op Fl i Ar reload-interval
-.Ek
 .Op Fl l Ar logfile
-.Bk -words
 .Op Fl o Ar mount-options
 .Op Fl x Ar log-options
 .Op Fl D Ar debug-options
 .Op Fl P Ar password-file
-.Ek
-.Op linkname Op subdir
+.Op Ar linkname Op Ar subdir
 .Sh DESCRIPTION
-.Nm 
-is a daemon which implements a filesystem containing a symbolic link to
+The
+.Nm
+utility
+is a daemon which implements a file system 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
+which accessed that link.
+It was primarily designed to redirect
 incoming mail to users' home directories, so that it can read from
 anywhere.
 .Pp
+The
 .Nm
+utility
 operates by mounting itself as an
 .Tn NFS
 server for the directory containing
@@ -85,167 +83,205 @@ server for the directory containing
 which defaults to
 .Pa /hlfs/home .
 Lookups within that directory are handled by
-.Nm 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
+.Nm ,
+which uses the password map to determine how to resolve the lookup.
+The directory will be created if it does not already exist.
+The symbolic link will be to the accessing user's home directory, with
 .Ar subdir
-appended to it.  If not specified,
+appended to it.
+If not specified,
 .Ar subdir
-defaults to 
+defaults to
 .Pa .hlfsdir .
 This directory will also be created if it does not already exist.
 .Pp
 A
-.Er 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 
-.Er SIGUSR1
-will cause it to dump its internal table of user IDs and home directories to
-the file
+.Dv SIGTERM
+sent to
+.Nm
+will cause it to shutdown.
+A
+.Dv 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
+.Dv SIGUSR1
+will cause it to dump its internal
+table of user IDs and home directories to the file
 .Pa /usr/tmp/hlfsd.dump.XXXXXX .
 .Sh OPTIONS
-.Bl -tag -width Ds
+.Bl -tag -width indent
 .It Fl a Ar alt_dir
-Alternate directory.  The name of the directory to which
+Alternate directory.
+The name of the directory to which
 the symbolic link returned by
 .Nm
-will point, if it cannot access the home directory of the user.  This
+will point, if it cannot access the home directory of the user.
+This
 defaults to
 .Pa /var/hlfs .
-This directory will be created  if it doesn't exist.  It is expected
+This directory will be created if it does not exist.
+It is expected
 that either users will read these files, or the system administrators
 will run a script to resend this
 .Dq lost mail
 to its owner.
 .It Fl c Ar cache-interval
 Caching interval.
+The
 .Nm
+utility
 will cache the validity of home directories for this interval, in
-seconds.  Entries which have been verified within the last
+seconds.
+Entries which have been verified within the last
 .Ar 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,
 .Nm
 will re-verify the validity of the user's home directory, and
-reset the cache time-counter.  The default value for
+reset the cache time-counter.
+The default value for
 .Ar cache-interval
-is 300 seconds 
-(5 minutes).
-.It Fl f 
-Force fast startup.  This option tells
+is 300 seconds (5 minutes).
+.It Fl f
+Force fast startup.
+This option tells
 .Nm
 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.
 .It Fl g Ar group
 Set the special group
-.Va HLFS_GID
+.Dv HLFS_GID
 to
 .Ar group .
 Programs such as
-.Ic comsat ,
-(which access the mailboxes of other users)
-must be setgid
-.Va HLFS_GID
-to work properly.  The default group is
-.Dq hlfs .
-If no group is provided, and there is no group 
-.Dq hlfs , 
+.Xr comsat 8 ,
+(which access the mailboxes of other users) must be setgid
+.Dv HLFS_GID
+to work properly.
+The default group is
+.Dq Li hlfs .
+If no group is provided,
+and there is no group
+.Dq Li hlfs ,
 this feature is disabled.
 .It Fl h
-Help.  Print a brief help message, and exit.
+Help.
+Print a brief help message, and exit.
 .It Fl i Ar reload-interval
-Map-reloading interval.  Each
+Map-reloading interval.
+Each
 .Ar reload-interval
 seconds,
 .Nm
 will reload the password map.
+The
 .Nm
+utility
 needs the password map for the UIDs and home directory pathnames.
+The
 .Nm
-schedules a 
-.Va SIGALRM 
-to reload the password maps.  A 
-.Va SIGHUP 
+utility schedules a
+.Dv SIGALRM
+to reload the password maps.
+A
+.Dv SIGHUP
 sent to
 .Nm
-will force it to reload the maps immediately.   The default value for
+will force it to reload the maps immediately.
+The default
+value for
 .Ar reload-interval
-is 900 seconds 
-(15 minutes).
+is 900 seconds (15 minutes).
 .It Fl l Ar logfile
 Specify a log file to which
 .Nm
-will record events.  If
-.Pa logfile
+will record events.
+If
+.Ar logfile
 is the string
-.Pa syslog
+.Dq Li syslog
 then the log messages will be sent to the system log daemon by
 .Xr syslog 3 ,
-using the 
-.Va LOG_DAEMON
-facility.  This is also the default.
+using the
+.Dv LOG_DAEMON
+facility.
+This is also the default.
 .It Fl n
 No verify.
+The
 .Nm
+utility
 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
+sufficient disk-space for spooling.
+This can speed up
 .Nm
 at the cost of possibly returning symbolic links to home
 directories which are not currently accessible or are full.
 By default,
 .Nm
 validates the symbolic-link in the background.
-The 
+The
 .Fl n
 option overrides the meaning of the
 .Fl c
 option, since no caching is necessary.
 .It Fl o Ar mount-options
-Mount options.  Mount options which
+Mount options.
+Mount options which
 .Nm
 will use to mount itself on top of
-.Pa dirname .
+.Ar dirname .
 By default,
 .Ar mount-options
 is set to
-.Qq ro .
+.Dq Li ro .
 If the system supports symbolic-link caching, default
-options are set to 
-.Qq ro,nocache .
+options are set to
+.Dq Li ro,nocache .
 .It Fl p
-Prints 
-.Va PID .
-Outputs the process-id of
+Print PID.
+Outputs the process ID of
 .Nm
 to standard output where it can be saved into a file.
 .It Fl v
-Version.  Displays version information to standard error.
+Version.
+Displays version information to standard error.
 .It Fl x Ar log-options
-Specify run-time logging options.  The options are a comma separated
-list chosen from: fatal, error, user, warn, info, map, stats, all.
+Specify run-time logging options.
+The options are a comma separated
+list chosen from:
+.Li fatal , error , user , warn , info , map , stats , all .
 .It Fl C
 Force
 .Nm
-to run on systems that cannot turn off the NFS attribute-cache.  Use of
+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
+or mis-delivery of mail.
+The option is ignored on systems that can turn
 off the attribute-cache.
 .It Fl D Ar log-options
-Select from a variety of debugging options.  Prefixing an
+Select from a variety of debugging options.
+Prefixing an
 option with the string
-.Qq no
-reverses the effect of that option.  Options are cumulative.
+.Dq Li no
+reverses the effect of that option.
+Options are cumulative.
 The most useful option is
-.Em all .
+.Dq Li all .
 Since this option is only used for debugging other options are not
-documented here.  A fuller description is available in the program
-source.  A 
-.Va SIGUSR1
+documented here.
+A fuller description is available in the program
+source.
+A
+.Dv SIGUSR1
 sent to
 .Nm
 will cause it to dump its internal password map to the file
@@ -257,20 +293,24 @@ Normally,
 .Nm
 will use
 .Xr getpwent 3
-to read the password database.  This option allows you to override the
+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
+directory other than their home directory.
+Only the username, uid, and
 home-directory fields of the file
 .Ar password-file
-are read and checked.  All other fields are ignored.  The file
+are read and checked.
+All other fields are ignored.
+The file
 .Ar password-file
-must be compliant with 
-.Ux 
+must otherwise be compliant with
+.Ux
 System 7 colon-delimited format
 .Xr passwd 5 .
 .El
 .Sh FILES
-.Bl -tag -width /axx
+.Bl -tag -width ".Pa /var/hlfs"
 .It Pa /hlfs
 directory under which
 .Nm
@@ -297,24 +337,40 @@ user's home directory is accessible.
 .Xr mtab 5 ,
 .Xr passwd 5 ,
 .Xr amd 8 ,
-.Xr cron 8 , 
+.Xr cron 8 ,
 .Xr mount 8 ,
 .Xr sendmail 8 ,
 .Xr umount 8
 .Rs
-.%T HLFSD:  Delivering Email to Your $HOME
+.%T HLFSD: Delivering Email to Your $HOME
 .%B Proc. LISA-VII, The 7th Usenix System Administration Conference
 .%D November 1993
 .Re
-.Sh AUTHORS
-.An Erez Zadok Aq ezk@cs.columbia.edu ,
-Department of Computer Science, Columbia University,
-New York, USA.
 .Pp
-.An Alexander Dupuy Aq dupuy@smarts.com ,
-System Management ARTS, White Plains, New York, USA.
+.Dq am-utils
+.Xr info 1
+entry.
+.Rs
+.%A Erez Zadok
+.%B "Linux NFS and Automounter Administration"
+.%O ISBN 0-7821-2739-8
+.%I Sybex
+.%D 2001
+.Re
+.Pp
+.Pa http://www.am-utils.org/
 .Sh HISTORY
 The
 .Nm
 utility appeared in
 .Fx 3.0 .
+.Sh AUTHORS
+.An Erez Zadok Aq ezk@cs.sunysb.edu ,
+Computer Science Department, Stony Brook University, Stony Brook, New York, USA.
+.Pp
+.An Alexander Dupuy Aq dupuy@smarts.com ,
+System Management ARTS, White Plains, New York, USA.
+.Pp
+Other authors and contributors to am-utils are listed in the
+.Pa AUTHORS
+file distributed with am-utils.
diff --git a/contrib/amd/hlfsd/hlfsd.c b/contrib/amd/hlfsd/hlfsd.c
index c50d117..8703f59 100644
--- a/contrib/amd/hlfsd/hlfsd.c
+++ b/contrib/amd/hlfsd/hlfsd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: hlfsd.c,v 1.5 1999/09/08 23:36:51 ezk Exp $
- * $FreeBSD: src/contrib/amd/hlfsd/hlfsd.c,v 1.5 1999/09/15 05:45:15 obrien Exp $
- * $DragonFly: src/contrib/amd/hlfsd/hlfsd.c,v 1.2 2003/06/17 04:23:57 dillon Exp $
+ * File: am-utils/hlfsd/hlfsd.c
  *
  * HLFSD was written at Columbia University Computer Science Department, by
  * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
@@ -87,7 +84,7 @@ char *logfile = DEFAULT_LOGFILE;
 char *passwdfile = NULL;	/* alternate passwd file to use */
 char *slinkname = 0;
 char hostname[MAXHOSTNAMELEN + 1] = "localhost";
-int cache_interval = DEFAULT_CACHE_INTERVAL;
+u_int cache_interval = DEFAULT_CACHE_INTERVAL;
 gid_t hlfs_gid = (gid_t) INVALIDID;
 int masterpid = 0;
 int noverify = 0;
@@ -97,11 +94,11 @@ nfstime startup;
 u_short nfs_port;
 
 /* symbol must be available always */
-#ifdef MOUNT_TABLE_ON_FILE
+#ifdef MNTTAB_FILE_NAME
 char *mnttab_file_name = MNTTAB_FILE_NAME;
-#else /* not MOUNT_TABLE_ON_FILE */
+#else /* not MNTTAB_FILE_NAME */
 char *mnttab_file_name = NULL;
-#endif /* not MOUNT_TABLE_ON_FILE */
+#endif /* not MNTTAB_FILE_NAME */
 
 /* forward declarations */
 void hlfsd_going_down(int rc);
@@ -123,6 +120,17 @@ usage(void)
 }
 
 
+void
+fatalerror(char *str)
+{
+#define ERRM ": %m"
+  size_t l = strlen(str) + sizeof(ERRM) - 1;
+  char *tmp = strnsave(str, l);
+  xstrlcat(tmp, ERRM, l);
+  fatal(tmp);
+}
+
+
 int
 main(int argc, char *argv[])
 {
@@ -265,12 +273,12 @@ main(int argc, char *argv[])
  * Terminate if did not ask to forcecache (-C) and hlfsd would not be able
  * to set the minimum cache intervals.
  */
-#if !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_FIELD_NFS_ARGS_T_ACREGMIN)
+#if !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_NFS_ARGS_T_ACREGMIN)
   if (!forcecache) {
     fprintf(stderr, "%s: will not be able to turn off attribute caches.\n", am_get_progname());
     exit(1);
   }
-#endif /* !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_FIELD_NFS_ARGS_T_ACREGMIN) */
+#endif /* !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_NFS_ARGS_T_ACREGMIN) */
 
 
   switch (argc - optind) {
@@ -310,12 +318,12 @@ main(int argc, char *argv[])
     *dot = '\0';
   orig_umask = umask(0);
   if (logfile)
-    switch_to_logfile(logfile, orig_umask);
+    switch_to_logfile(logfile, orig_umask, 0);
 
-#if defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE)
-  if (debug_flags & D_MTAB)
+#ifndef MOUNT_TABLE_ON_FILE
+  if (amuDebug(D_MTAB))
     dlog("-D mtab option ignored");
-#endif /* defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE) */
+#endif /* not MOUNT_TABLE_ON_FILE */
 
   /* avoid hanging on other NFS servers if started elsewhere */
   if (chdir("/") < 0)
@@ -339,8 +347,6 @@ main(int argc, char *argv[])
     exit(3);
   }
 
-  clock_valid = 0;		/* invalidate logging clock */
-
   if (!forcefast) {
     /* make sure mount point exists and is at least mode 555 */
     if (stat(dir_name, &stmodes) < 0)
@@ -385,7 +391,7 @@ main(int argc, char *argv[])
     chmod(alt_spooldir, OPEN_SPOOLMODE);
 
     /* create failsafe link to alternate spool directory */
-    slinkname[-1] = '/';	/* unsplit dir_name to include link */
+    *(slinkname-1) = '/';	/* unsplit dir_name to include link */
     if (lstat(dir_name, &stmodes) == 0 &&
 	(stmodes.st_mode & S_IFMT) != S_IFLNK) {
       fprintf(stderr, "%s: failsafe %s not a symlink\n",
@@ -406,7 +412,7 @@ main(int argc, char *argv[])
       }
     }
 
-    slinkname[-1] = '\0';	/* resplit dir_name */
+    *(slinkname-1) = '\0';	/* resplit dir_name */
   } /* end of "if (!forcefast) {" */
 
   /*
@@ -443,53 +449,57 @@ main(int argc, char *argv[])
   signal(SIGCHLD, reaper);
 #endif /* not HAVE_SIGACTION */
 
-#ifdef DEBUG
   /*
-   * In the parent, if -D nodaemon (or -D daemon) , we don't need to
+   * In the parent, if -D daemon, we don't need to
    * set this signal handler.
    */
-  amuDebug(D_DAEMON) {
-#endif /* DEBUG */
-    /* XXX: port to use pure svr4 signals */
+  if (!amuDebug(D_DAEMON)) {
     s = -99;
     while (stoplight != SIGUSR2) {
       plog(XLOG_INFO, "parent waits for child to setup (stoplight=%d)", stoplight);
+#ifdef HAVE_SIGSUSPEND
+      {
+	sigset_t mask;
+	sigemptyset(&mask);
+	s = sigsuspend(&mask);	/* wait for child to set up */
+      }
+#else /* not HAVE_SIGSUSPEND */
       s = sigpause(0);		/* wait for child to set up */
+#endif /* not HAVE_SIGSUSPEND */
       sleep(1);
     }
-#ifdef DEBUG
   }
-#endif /* DEBUG */
 
   /*
    * setup options to mount table (/etc/{mtab,mnttab}) entry
    */
-  sprintf(hostpid_fs, "%s:(pid%d)", hostname, masterpid);
+  xsnprintf(hostpid_fs, sizeof(hostpid_fs),
+	    "%s:(pid%d)", hostname, masterpid);
   memset((char *) &mnt, 0, sizeof(mnt));
   mnt.mnt_dir = dir_name;	/* i.e., "/mail" */
   mnt.mnt_fsname = hostpid_fs;
   if (mntopts) {
     mnt.mnt_opts = mntopts;
   } else {
-    strcpy(preopts, default_mntopts);
+    xstrlcpy(preopts, default_mntopts, sizeof(preopts));
     /*
      * Turn off all kinds of attribute and symlink caches as
      * much as possible.  Also make sure that mount does not
      * show up to df.
      */
 #ifdef MNTTAB_OPT_INTR
-    strcat(preopts, ",");
-    strcat(preopts, MNTTAB_OPT_INTR);
+    xstrlcat(preopts, ",", sizeof(preopts));
+    xstrlcat(preopts, MNTTAB_OPT_INTR, sizeof(preopts));
 #endif /* MNTTAB_OPT_INTR */
 #ifdef MNTTAB_OPT_IGNORE
-    strcat(preopts, ",");
-    strcat(preopts, MNTTAB_OPT_IGNORE);
+    xstrlcat(preopts, ",", sizeof(preopts));
+    xstrlcat(preopts, MNTTAB_OPT_IGNORE, sizeof(preopts));
 #endif /* MNTTAB_OPT_IGNORE */
 #ifdef MNT2_GEN_OPT_CACHE
-    strcat(preopts, ",nocache");
+    xstrlcat(preopts, ",nocache", sizeof(preopts));
 #endif /* MNT2_GEN_OPT_CACHE */
 #ifdef MNT2_NFS_OPT_SYMTTL
-    strcat(preopts, ",symttl=0");
+    xstrlcat(preopts, ",symttl=0", sizeof(preopts));
 #endif /* MNT2_NFS_OPT_SYMTTL */
     mnt.mnt_opts = preopts;
   }
@@ -500,11 +510,15 @@ main(int argc, char *argv[])
    * If they don't appear to support the either the "ignore" mnttab
    * option entry, or the "auto" one, set the mount type to "nfs".
    */
+#ifdef HIDE_MOUNT_TYPE
   mnt.mnt_type = HIDE_MOUNT_TYPE;
+#else /* not HIDE_MOUNT_TYPE */
+  mnt.mnt_type = "nfs";
+#endif /* not HIDE_MOUNT_TYPE */
   /* some systems don't have a mount type, but a mount flag */
 
 #ifndef HAVE_TRANSPORT_TYPE_TLI
-  amu_get_myaddress(&localsocket.sin_addr);
+  amu_get_myaddress(&localsocket.sin_addr, NULL);
   localsocket.sin_family = AF_INET;
   localsocket.sin_port = htons(nfsxprt->xp_port);
 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
@@ -513,11 +527,13 @@ main(int argc, char *argv[])
    * Update hostname field.
    * Make some name prog:pid (i.e., hlfsd:174) for hostname
    */
-  sprintf(progpid_fs, "%s:%d", am_get_progname(), masterpid);
+  xsnprintf(progpid_fs, sizeof(progpid_fs),
+	    "%s:%d", am_get_progname(), masterpid);
 
   /* Most kernels have a name length restriction. */
   if ((int) strlen(progpid_fs) >= (int) MAXHOSTNAMELEN)
-    strcpy(progpid_fs + MAXHOSTNAMELEN - 3, "..");
+    xstrlcpy(progpid_fs + MAXHOSTNAMELEN - 3, "..",
+	     sizeof(progpid_fs) - MAXHOSTNAMELEN + 3);
 
   genflags = compute_mount_flags(&mnt);
 
@@ -525,7 +541,7 @@ main(int argc, char *argv[])
   if (retry <= 0)
     retry = 1;			/* XXX */
 
-  memmove(&anh.v2.fhs_fh, root_fhp, sizeof(*root_fhp));
+  memmove(&anh.v2, root_fhp, sizeof(*root_fhp));
 #ifdef HAVE_TRANSPORT_TYPE_TLI
   compute_nfs_args(&nfs_args,
 		   &mnt,
@@ -551,6 +567,7 @@ main(int argc, char *argv[])
   compute_nfs_args(&nfs_args,
 		   &mnt,
 		   genflags,
+		   NULL,
 		   &localsocket,
 		   NFS_VERSION, /* version 2 */
 		   "udp",	/* XXX: shouldn't this be "udp"? */
@@ -566,33 +583,26 @@ main(int argc, char *argv[])
    *************************************************************************/
   compute_automounter_nfs_args(&nfs_args, &mnt);
 
-  clock_valid = 0;		/* invalidate logging clock */
-
-/*
- * The following code could be cleverly ifdef-ed, but I duplicated the
- * mount_fs call three times for simplicity and readability.
- */
-#ifdef DEBUG
 /*
  * For some reason, this mount may have to be done in the background, if I am
- * using -D nodebug.  I suspect that the actual act of mounting requires
+ * using -D daemon.  I suspect that the actual act of mounting requires
  * calling to hlfsd itself to invoke one or more of its nfs calls, to stat
- * /mail.  That means that even if you say -D nodaemon, at least the mount
+ * /mail.  That means that even if you say -D daemon, at least the mount
  * of hlfsd itself on top of /mail will be done in the background.
  * The other alternative I have is to run svc_run, but set a special
  * signal handler to perform the mount in N seconds via some alarm.
  *      -Erez Zadok.
  */
-  if (debug_flags & D_DAEMON) {	/* asked for -D daemon */
-    plog(XLOG_INFO, "parent NFS mounting hlfsd service points");
-    if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name) < 0)
+  if (!amuDebug(D_DAEMON)) {	/* Normal case */
+    plog(XLOG_INFO, "normal NFS mounting hlfsd service points");
+    if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name, 0) < 0)
       fatal("nfsmount: %m");
-  } else {			/* asked for -D nodaemon */
+  } else {			/* asked for -D daemon */
     if (fork() == 0) {		/* child runs mount */
       am_set_mypid();
       foreground = 0;
       plog(XLOG_INFO, "child NFS mounting hlfsd service points");
-      if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name) < 0) {
+      if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name, 0) < 0) {
 	fatal("nfsmount: %m");
       }
       exit(0);			/* all went well */
@@ -600,11 +610,6 @@ main(int argc, char *argv[])
       plog(XLOG_INFO, "parent waiting 1sec for mount...");
     }
   }
-#else /* not DEBUG */
-  plog(XLOG_INFO, "normal NFS mounting hlfsd service points");
-  if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 2, "udp", mnttab_file_name) < 0)
-    fatal("nfsmount: %m");
-#endif /* not DEBUG */
 
 #ifdef HAVE_TRANSPORT_TYPE_TLI
   /*
@@ -622,15 +627,14 @@ main(int argc, char *argv[])
     printf("%d\n", masterpid);
 
   plog(XLOG_INFO, "hlfsd ready to serve");
-#ifdef DEBUG
   /*
-   * If asked not to fork a daemon (-D nodaemon), then hlfsd_init()
+   * If asked not to fork a daemon (-D daemon), then hlfsd_init()
    * will not run svc_run.  We must start svc_run here.
    */
-  dlog("starting no-daemon debugging svc_run");
-  amuDebugNo(D_DAEMON)
+  if (amuDebug(D_DAEMON)) {
+    plog(XLOG_DEBUG, "starting no-daemon debugging svc_run");
     svc_run();
-#endif /* DEBUG */
+  }
 
   cleanup(0);			/* should never happen here */
   return (0);			/* everything went fine? */
@@ -645,20 +649,16 @@ hlfsd_init(void)
   struct sigaction sa;
 #endif /* HAVE_SIGACTION */
 
-  clock_valid = 0;		/* invalidate logging clock */
-
   /*
    * Initialize file handles.
    */
   plog(XLOG_INFO, "initializing hlfsd file handles");
   hlfsd_init_filehandles();
 
-#ifdef DEBUG
   /*
-   * If -D daemon then we must fork.
+   * If not -D daemon then we must fork.
    */
-  amuDebug(D_DAEMON)
-#endif /* DEBUG */
+  if (!amuDebug(D_DAEMON))
     child = fork();
 
   if (child < 0)
@@ -748,17 +748,14 @@ hlfsd_init(void)
   if (setitimer(ITIMER_REAL, &reloadinterval, (struct itimerval *) 0) < 0)
     fatal("setitimer: %m");
 
-  gettimeofday((struct timeval *) &startup, (struct timezone *) 0);
+  clocktime(&startup);
 
-#ifdef DEBUG
   /*
-   * If -D daemon, then start serving here in the child,
-   * and the parent will exit.  But if -D nodaemon, then
+   * If not -D daemon, then start serving here in the child,
+   * and the parent will exit.  But if -D daemon, then
    * skip this code and make sure svc_run is entered elsewhere.
    */
-  amuDebug(D_DAEMON) {
-#endif /* DEBUG */
-
+  if (!amuDebug(D_DAEMON)) {
     /*
      * Dissociate from the controlling terminal
      */
@@ -773,9 +770,7 @@ hlfsd_init(void)
     plog(XLOG_INFO, "starting svc_run");
     svc_run();
     cleanup(0);		/* should never happen, just in case */
-#ifdef DEBUG
-  } /* end of code that runs iff hlfsd daemonizes */
-#endif /* DEBUG */
+  }
 
 }
 
@@ -793,8 +788,6 @@ reload(int signum)
   int child;
   int status;
 
-  clock_valid = 0;		/* invalidate logging clock */
-
   if (getpid() != masterpid)
     return;
 
@@ -803,7 +796,7 @@ reload(int signum)
    * can be rotated)
    */
   if (signum == SIGHUP && logfile)
-    switch_to_logfile(logfile, orig_umask);
+    switch_to_logfile(logfile, orig_umask, 0);
 
   /*
    * parent performs the reload, while the child continues to serve
@@ -846,29 +839,21 @@ cleanup(int signum)
   struct stat stbuf;
   int umount_result;
 
-  clock_valid = 0;		/* invalidate logging clock */
-
-#ifdef DEBUG
-  amuDebug(D_DAEMON)
-#endif /* DEBUG */
+  if (!amuDebug(D_DAEMON)) {
     if (getpid() != masterpid)
-    return;
+      return;
 
-#ifdef DEBUG
-  amuDebug(D_DAEMON)
-#endif /* DEBUG */
     if (fork() != 0) {
-    masterpid = 0;
-    am_set_mypid();
-    return;
+      masterpid = 0;
+      am_set_mypid();
+      return;
+    }
   }
   am_set_mypid();
 
   for (;;) {
-    while ((umount_result = UMOUNT_FS(dir_name, mnttab_file_name)) == EBUSY) {
-#ifdef DEBUG
+    while ((umount_result = UMOUNT_FS(dir_name, mnttab_file_name, 0)) == EBUSY) {
       dlog("cleanup(): umount delaying for 10 seconds");
-#endif /* DEBUG */
       sleep(10);
     }
     if (stat(dir_name, &stbuf) == 0 && stbuf.st_ino == ROOTID) {
@@ -880,19 +865,14 @@ cleanup(int signum)
     break;
   }
 
-#ifdef DEBUG
-  dlog("cleanup(): killing processes and terminating");
-  amuDebug(D_DAEMON)
-#endif /* DEBUG */
+  if (!amuDebug(D_DAEMON)) {
+    plog(XLOG_INFO, "cleanup(): killing processes and terminating");
     kill(masterpid, SIGKILL);
-
-#ifdef DEBUG
-  amuDebug(D_DAEMON)
-#endif /* DEBUG */
     kill(serverpid, SIGKILL);
+  }
 
   plog(XLOG_INFO, "hlfsd terminating with status 0\n");
-  exit(0);
+  _exit(0);
 }
 
 
@@ -902,7 +882,7 @@ reaper(int signum)
   int result;
 
   if (wait(&result) == masterpid) {
-    exit(4);
+    _exit(4);
   }
 }
 
@@ -933,23 +913,14 @@ fatal(char *mess)
     if (!STREQ(&mess[messlen + 1 - sizeof(ERRM)], ERRM))
       fprintf(stderr, "%s: %s\n", am_get_progname(), mess);
     else {
-      strcpy(lessmess, mess);
+      xstrlcpy(lessmess, mess, sizeof(lessmess));
       lessmess[messlen - 4] = '\0';
 
-      if (errno < sys_nerr)
-	fprintf(stderr, "%s: %s: %s\n", am_get_progname(), lessmess,
-#ifdef HAVE_STRERROR
-		strerror(errno)
-#else /* not HAVE_STRERROR */
-		sys_errlist[errno]
-#endif /* not HAVE_STRERROR */
-		);
-      else
-	fprintf(stderr, "%s: %s: Error %d\n",
-		am_get_progname(), lessmess, errno);
+      fprintf(stderr, "%s: %s: %s\n",
+	      am_get_progname(), lessmess, strerror(errno));
     }
   }
-  plog(XLOG_FATAL, mess);
+  plog(XLOG_FATAL, "%s", mess);
 
   hlfsd_going_down(1);
 }
diff --git a/contrib/amd/hlfsd/hlfsd.h b/contrib/amd/hlfsd/hlfsd.h
index 6fcbe5e..ed136b6 100644
--- a/contrib/amd/hlfsd/hlfsd.h
+++ b/contrib/amd/hlfsd/hlfsd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: hlfsd.h,v 1.2 1999/01/10 21:54:32 ezk Exp $
+ * File: am-utils/hlfsd/hlfsd.h
  *
  * HLFSD was written at Columbia University Computer Science Department, by
  * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
@@ -52,7 +51,7 @@
  * MACROS AND CONSTANTS:
  */
 
-#define HLFSD_VERSION	"hlfsd 1.1 (March 4, 1997-1999)"
+#define HLFSD_VERSION	"hlfsd 1.2 (1993-2002)"
 #define PERS_SPOOLMODE	0755
 #define OPEN_SPOOLMODE	01777
 #define DOTSTRING	"."
@@ -70,21 +69,16 @@
  * which define uid_t to be unsigned short, so I used the lowest common
  * size which is unsigned short.
  */
-#ifdef EXPERIMENTAL_UID_SIZE
-#define UID_SHIFT	30
-# define ROOTID		((1 << UID_SHIFT) - 1)
-# define SLINKID	((1 << UID_SHIFT) - 2)
-# define INVALIDID	((1 << UID_SHIFT) - 3)
-#else /* not EXPERIMENTAL_UID_SIZE */
 /*
  * XXX: this will cause problems to systems with UIDs greater than
  * MAX_UNSIGNED_SHORT-3.
  */
-# define ROOTID		(((unsigned short) ~0) - 1)
-# define SLINKID	(((unsigned short) ~0) - 2)
+#define ROOTID		(((unsigned short) ~0) - 1)
+#define SLINKID		(((unsigned short) ~0) - 2)
+#ifndef INVALIDID
+/* this is also defined in include/am_utils.h */
 # define INVALIDID	(((unsigned short) ~0) - 3)
-#endif /* not EXPERIMENTAL_UID_SIZE */
-
+#endif /* not INVALIDID */
 
 #define DOTCOOKIE	1
 #define DOTDOTCOOKIE	2
@@ -105,9 +99,6 @@
 # define DEFAULT_LOGFILE 0
 #endif /* not HAVE)_SYSLOG */
 
-#define ERRM ": %m"
-#define fatalerror(str) \
-  (fatal (strcat (strnsave ((str), strlen ((str)) + sizeof (ERRM) - 1), ERRM)))
 
 /*
  * TYPEDEFS:
@@ -143,20 +134,19 @@ extern SVCXPRT *nfs_program_2_transp;	/* For quick_reply() */
 extern SVCXPRT *nfsxprt;
 extern char *alt_spooldir;
 extern char *home_subdir;
-extern char *homedir(int);
+extern char *homedir(int, int);
 extern char *mailbox(int, char *);
 extern char *passwdfile;
 extern char *slinkname;
-extern char mboxfile[];
 extern gid_t hlfs_gid;
-extern int cache_interval;
+extern u_int cache_interval;
 extern int noverify;
 extern int serverpid;
 extern int untab_index(char *username);
 extern am_nfs_fh *root_fhp;
 extern am_nfs_fh root;
 extern nfstime startup;
-extern uid2home_t *plt_search(int);
+extern uid2home_t *plt_search(u_int);
 extern username2uid_t *untab;	/* user name table */
 extern void fatal(char *);
 extern void plt_init(void);
diff --git a/contrib/amd/hlfsd/homedir.c b/contrib/amd/hlfsd/homedir.c
index 69856ca..2ade32f 100644
--- a/contrib/amd/hlfsd/homedir.c
+++ b/contrib/amd/hlfsd/homedir.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: homedir.c,v 1.4 1999/01/13 23:31:19 ezk Exp $
- * $FreeBSD: src/contrib/amd/hlfsd/homedir.c,v 1.4 1999/09/15 05:45:15 obrien Exp $
- * $DragonFly: src/contrib/amd/hlfsd/homedir.c,v 1.2 2003/06/17 04:23:57 dillon Exp $
+ * File: am-utils/hlfsd/homedir.c
  *
  * HLFSD was written at Columbia University Computer Science Department, by
  * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
@@ -68,35 +65,30 @@ static struct passwd passwd_ent;
 static uid2home_t *lastchild;
 static uid2home_t *pwtab;
 static void delay(uid2home_t *, int);
-static void table_add(int, const char *, const char *);
+static void table_add(u_int, const char *, const char *);
+static char mboxfile[MAXPATHLEN];
+static char *root_home;		/* root's home directory */
 
 /* GLOBAL FUNCTIONS */
 char *homeof(char *username);
 int uidof(char *username);
 
 /* GLOBALS VARIABLES */
-char mboxfile[MAXPATHLEN];
 username2uid_t *untab;		/* user name table */
 
-
 /*
  * Return the home directory pathname for the user with uid "userid".
  */
 char *
-homedir(int userid)
+homedir(int userid, int groupid)
 {
   static char linkval[MAXPATHLEN + 1];
   static struct timeval tp;
   uid2home_t *found;
   char *homename;
   struct stat homestat;
+  int old_groupid, old_userid;
 
-  clock_valid = 0;		/* invalidate logging clock */
-
-  if ((int) userid == 0) {	/* force superuser to use "/" as home */
-    sprintf(linkval, "/%s", home_subdir);
-    return linkval;
-  }
   if ((found = plt_search(userid)) == (uid2home_t *) NULL) {
     return alt_spooldir;	/* use alt spool for unknown uid */
   }
@@ -106,7 +98,10 @@ homedir(int userid)
     found->last_status = 1;
     return alt_spooldir;	/* use alt spool for / or rel. home */
   }
-  sprintf(linkval, "%s/%s", homename, home_subdir);
+  if ((int) userid == 0)	/* force all uid 0 to use root's home */
+    xsnprintf(linkval, sizeof(linkval), "%s/%s", root_home, home_subdir);
+  else
+    xsnprintf(linkval, sizeof(linkval), "%s/%s", homename, home_subdir);
 
   if (noverify) {
     found->last_status = 0;
@@ -115,9 +110,9 @@ homedir(int userid)
 
   /*
    * To optimize hlfsd, we don't actually check the validity of the
-   * symlink if it has been in checked in the last N seconds.  It is
+   * symlink if it has been checked in the last N seconds.  It is
    * very likely that the link, machine, and filesystem are still
-   * valid, as long as N is small.  But if N ls large, that may not be
+   * valid, as long as N is small.  But if N is large, that may not be
    * true.  That's why the default N is 5 minutes, but we allow the
    * user to override this value via a command line option.  Note that
    * we do not update the last_access_time each time it is accessed,
@@ -137,13 +132,10 @@ homedir(int userid)
     }
   }
 
-#ifdef DEBUG
   /*
-   * only run this forking code if asked for -D fork
-   * or if did not ask for -D nofork
+   * only run this forking code if did not ask for -D fork
    */
-  amuDebug(D_FORK) {
-#endif /* DEBUG */
+  if (!amuDebug(D_FORK)) {
     /* fork child to process request if none in progress */
     if (found->child && kill(found->child, 0))
       found->child = 0;
@@ -159,21 +151,17 @@ homedir(int userid)
       return alt_spooldir;
     }
     if (found->child) {		/* PARENT */
-#ifdef DEBUG
       if (lastchild)
-	plog(XLOG_INFO, "cache spill uid = %ld, pid = %ld, home = %s",
+	dlog("cache spill uid = %ld, pid = %ld, home = %s",
 	     (long) lastchild->uid, (long) lastchild->child,
 	     lastchild->home);
-#endif /* DEBUG */
       lastchild = found;
       return (char *) NULL;	/* return NULL to parent, so it can continue */
     }
-#ifdef DEBUG
-  }				/* end of Debug(D_FORK) */
-#endif /* DEBUG */
+  }
 
   /*
-   * CHILD: (or parent if -D nofork)
+   * CHILD: (or parent if -D fork)
    *
    * Check and create dir if needed.
    * Check disk space and/or quotas too.
@@ -185,21 +173,28 @@ homedir(int userid)
    *
    */
   am_set_mypid();		/* for logging routines */
-  if (seteuid(userid) < 0) {
+  if ((old_groupid = setgid(groupid)) < 0) {
+    plog(XLOG_WARNING, "could not setgid to %d: %m", groupid);
+    return linkval;
+  }
+  if ((old_userid = seteuid(userid)) < 0) {
     plog(XLOG_WARNING, "could not seteuid to %d: %m", userid);
+    setgid(old_groupid);
     return linkval;
   }
   if (hlfsd_stat(linkval, &homestat) < 0) {
     if (errno == ENOENT) {	/* make the spool dir if possible */
       /* don't use recursive mkdirs here */
       if (mkdir(linkval, PERS_SPOOLMODE) < 0) {
-	seteuid(0);
+	seteuid(old_userid);
+	setgid(old_groupid);
 	plog(XLOG_WARNING, "can't make directory %s: %m", linkval);
 	return alt_spooldir;
       }
       /* fall through to testing the disk space / quota */
     } else {			/* the home dir itself must not exist then */
-      seteuid(0);
+      seteuid(old_userid);
+      setgid(old_groupid);
       plog(XLOG_WARNING, "bad link to %s: %m", linkval);
       return alt_spooldir;
     }
@@ -214,11 +209,13 @@ homedir(int userid)
    * We are still seteuid to the user at this point.
    */
   if (hlfsd_diskspace(linkval) < 0) {
-    seteuid(0);
+    seteuid(old_userid);
+    setgid(old_groupid);
     plog(XLOG_WARNING, "no more space in %s: %m", linkval);
     return alt_spooldir;
   } else {
-    seteuid(0);
+    seteuid(old_userid);
+    setgid(old_groupid);
     return linkval;
   }
 }
@@ -230,9 +227,7 @@ hlfsd_diskspace(char *path)
   char buf[MAXPATHLEN];
   int fd, len;
 
-  clock_valid = 0;		/* invalidate logging clock */
-
-  sprintf(buf, "%s/._hlfstmp_%lu", path, (long) getpid());
+  xsnprintf(buf, sizeof(buf), "%s/._hlfstmp_%lu", path, (long) getpid());
   if ((fd = open(buf, O_RDWR | O_CREAT, 0600)) < 0) {
     plog(XLOG_ERROR, "cannot open %s: %m", buf);
     return -1;
@@ -270,10 +265,7 @@ delay(uid2home_t *found, int secs)
 {
   struct timeval tv;
 
-#ifdef DEBUG
-  if (found)
-    dlog("delaying on child %ld for %d seconds", (long) found->child, secs);
-#endif /* DEBUG */
+  dlog("delaying on child %ld for %d seconds", (long) found->child, secs);
 
   tv.tv_usec = 0;
 
@@ -403,9 +395,11 @@ mailbox(int uid, char *username)
   if ((home = homeof(username)) == (char *) NULL)
     return (char *) NULL;
   if (STREQ(home, "/"))
-    sprintf(mboxfile, "/%s/%s", home_subdir, username);
+    xsnprintf(mboxfile, sizeof(mboxfile),
+	      "/%s/%s", home_subdir, username);
   else
-    sprintf(mboxfile, "%s/%s/%s", home, home_subdir, username);
+    xsnprintf(mboxfile, sizeof(mboxfile),
+	      "%s/%s/%s", home, home_subdir, username);
   return mboxfile;
 }
 
@@ -487,8 +481,6 @@ hlfsd_getpwent(void)
     return getpwent();
   }
 
-  clock_valid = 0;		/* invalidate logging clock */
-
   /* return here to read another entry */
 readent:
 
@@ -511,7 +503,8 @@ readent:
     plog(XLOG_ERROR, "no user name on line %d of %s", passwd_line, passwdfile);
     goto readent;
   }
-  strcpy(pw_name, cp);		/* will show up in passwd_ent.pw_name */
+  /* pw_name will show up in passwd_ent.pw_name */
+  xstrlcpy(pw_name, cp, sizeof(pw_name));
 
   /* skip passwd */
   strtok(NULL, ":");
@@ -534,7 +527,8 @@ readent:
     plog(XLOG_ERROR, "no home dir on line %d of %s", passwd_line,  passwdfile);
     goto readent;
   }
-  strcpy(pw_dir, cp);	/* will show up in passwd_ent.pw_dir */
+  /* pw_dir will show up in passwd_ent.pw_dir */
+  xstrlcpy(pw_dir, cp, sizeof(pw_dir));
 
   /* the rest of the fields are unimportant and not being considered */
 
@@ -561,6 +555,18 @@ plt_init(void)
   hlfsd_setpwent();			/* prepare to read passwd entries */
   while ((pent_p = hlfsd_getpwent()) != (struct passwd *) NULL) {
     table_add(pent_p->pw_uid, pent_p->pw_dir, pent_p->pw_name);
+    if (STREQ("root", pent_p->pw_name)) {
+      int len;
+      if (root_home)
+	XFREE(root_home);
+      root_home = strdup(pent_p->pw_dir);
+      len = strlen(root_home);
+      /* remove any trailing '/' chars from root's home (even if just one) */
+      while (len > 0 && root_home[len - 1] == '/') {
+	len--;
+	root_home[len] = '\0';
+      }
+    }
   }
   hlfsd_endpwent();
 
@@ -569,6 +575,9 @@ plt_init(void)
   qsort((char *) untab, cur_pwtab_num, sizeof(username2uid_t),
 	unt_compare_fxn);
 
+  if (!root_home)
+    root_home = strdup("");
+
   plog(XLOG_INFO, "password map read and sorted");
 }
 
@@ -582,8 +591,6 @@ plt_reset(void)
 {
   int i;
 
-  clock_valid = 0;		/* invalidate logging clock */
-
   hlfsd_setpwent();
   if (hlfsd_getpwent() == (struct passwd *) NULL) {
     hlfsd_endpwent();
@@ -611,6 +618,9 @@ plt_reset(void)
     }
   cur_pwtab_num = 0;		/* zero current size */
 
+  if (root_home)
+    XFREE(root_home);
+
   return 0;			/* resetting ok */
 }
 
@@ -621,12 +631,10 @@ plt_reset(void)
  * n: user ID name
  */
 static void
-table_add(int u, const char *h, const char *n)
+table_add(u_int u, const char *h, const char *n)
 {
   int i;
 
-  clock_valid = 0;		/* invalidate logging clock */
-
   if (max_pwtab_num <= 0) {	/* was never initialized */
     max_pwtab_num = 1;
     pwtab = (uid2home_t *) xmalloc(max_pwtab_num *
@@ -657,10 +665,8 @@ table_add(int u, const char *h, const char *n)
   /* do NOT add duplicate entries (this is an O(N^2) algorithm... */
   for (i=0; i<cur_pwtab_num; ++i)
     if (u == pwtab[i].uid  &&  u != 0 ) {
-#ifdef DEBUG
       dlog("ignoring duplicate home %s for uid %d (already %s)",
 	   h, u, pwtab[i].home);
-#endif /* DEBUG */
       return;
     }
 
@@ -688,7 +694,7 @@ table_add(int u, const char *h, const char *n)
  * return entry in lookup table
  */
 uid2home_t *
-plt_search(int u)
+plt_search(u_int u)
 {
   int max, min, mid;
 
@@ -736,7 +742,7 @@ plt_print(int signum)
 #else /* not HAVE_MKSTEMP */
   mktemp(dumptmp);
   if (!dumptmp) {
-    plot(XLOG_ERROR, "cannot create temporary dump file");
+    plog(XLOG_ERROR, "cannot create temporary dump file");
     return;
   }
   dumpfd = open(dumptmp, O_RDONLY);
diff --git a/contrib/amd/hlfsd/nfs_prot_svc.c b/contrib/amd/hlfsd/nfs_prot_svc.c
index 3fdd196..8cea0dc 100644
--- a/contrib/amd/hlfsd/nfs_prot_svc.c
+++ b/contrib/amd/hlfsd/nfs_prot_svc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: nfs_prot_svc.c,v 1.3 1999/01/13 23:31:19 ezk Exp $
+ * File: am-utils/hlfsd/nfs_prot_svc.c
  *
  */
 
@@ -50,23 +49,23 @@
 
 /* EXTERNAL FUNCTIONS */
 extern voidp nfsproc_null_2_svc(voidp, struct svc_req *);
-extern nfsattrstat * nfsproc_getattr_2_svc(am_nfs_fh *, struct svc_req *);
-extern nfsattrstat * nfsproc_setattr_2_svc(nfssattrargs *, struct svc_req *);
+extern nfsattrstat *nfsproc_getattr_2_svc(am_nfs_fh *, struct svc_req *);
+extern nfsattrstat *nfsproc_setattr_2_svc(nfssattrargs *, struct svc_req *);
 extern voidp nfsproc_root_2_svc(voidp, struct svc_req *);
-extern nfsdiropres * nfsproc_lookup_2_svc(nfsdiropargs *, struct svc_req *);
-extern nfsreadlinkres * nfsproc_readlink_2_svc(am_nfs_fh *, struct svc_req *);
-extern nfsreadres * nfsproc_read_2_svc(nfsreadargs *, struct svc_req *);
+extern nfsdiropres *nfsproc_lookup_2_svc(nfsdiropargs *, struct svc_req *);
+extern nfsreadlinkres *nfsproc_readlink_2_svc(am_nfs_fh *, struct svc_req *);
+extern nfsreadres *nfsproc_read_2_svc(nfsreadargs *, struct svc_req *);
 extern voidp nfsproc_writecache_2_svc(voidp, struct svc_req *);
-extern nfsattrstat * nfsproc_write_2_svc(nfswriteargs *, struct svc_req *);
-extern nfsdiropres * nfsproc_create_2_svc(nfscreateargs *, struct svc_req *);
-extern nfsstat * nfsproc_remove_2_svc(nfsdiropargs *, struct svc_req *);
-extern nfsstat * nfsproc_rename_2_svc(nfsrenameargs *, struct svc_req *);
-extern nfsstat * nfsproc_link_2_svc(nfslinkargs *, struct svc_req *);
-extern nfsstat * nfsproc_symlink_2_svc(nfssymlinkargs *, struct svc_req *);
-extern nfsdiropres * nfsproc_mkdir_2_svc(nfscreateargs *, struct svc_req *);
-extern nfsstat * nfsproc_rmdir_2_svc(nfsdiropargs *, struct svc_req *);
-extern nfsreaddirres * nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *);
-extern nfsstatfsres * nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
+extern nfsattrstat *nfsproc_write_2_svc(nfswriteargs *, struct svc_req *);
+extern nfsdiropres *nfsproc_create_2_svc(nfscreateargs *, struct svc_req *);
+extern nfsstat *nfsproc_remove_2_svc(nfsdiropargs *, struct svc_req *);
+extern nfsstat *nfsproc_rename_2_svc(nfsrenameargs *, struct svc_req *);
+extern nfsstat *nfsproc_link_2_svc(nfslinkargs *, struct svc_req *);
+extern nfsstat *nfsproc_symlink_2_svc(nfssymlinkargs *, struct svc_req *);
+extern nfsdiropres *nfsproc_mkdir_2_svc(nfscreateargs *, struct svc_req *);
+extern nfsstat *nfsproc_rmdir_2_svc(nfsdiropargs *, struct svc_req *);
+extern nfsreaddirres *nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *);
+extern nfsstatfsres *nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
 
 /* GLOBALS */
 SVCXPRT *nfs_program_2_transp;
diff --git a/contrib/amd/hlfsd/stubs.c b/contrib/amd/hlfsd/stubs.c
index 490166a..becf402 100644
--- a/contrib/amd/hlfsd/stubs.c
+++ b/contrib/amd/hlfsd/stubs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: stubs.c,v 1.3 1999/01/13 23:31:19 ezk Exp $
+ * File: am-utils/hlfsd/stubs.c
  *
  * HLFSD was written at Columbia University Computer Science Department, by
  * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
@@ -61,7 +60,6 @@ static nfsfattr slinkfattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
 				/* user name file attributes */
 static nfsfattr un_fattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
 			    (NFS_MAXPATHLEN + 1) / 512, 0, INVALIDID};
-static int getcreds(struct svc_req *, uid_t *, gid_t *);
 static int started;
 static am_nfs_fh slink;
 static am_nfs_fh un_fhandle;
@@ -124,7 +122,22 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
     un_fattr.na_mtime = startup;
   }
 
+  if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
+    res.ns_status = NFSERR_STALE;
+    return &res;
+  }
   if (eq_fh(argp, &root)) {
+#if 0
+    /*
+     * XXX: increment mtime of parent directory, causes NFS clients to
+     * invalidate their cache for that directory.
+     * Some NFS clients may need this code.
+     */
+    if (uid != rootfattr.na_uid) {
+      clocktime(&rootfattr.na_mtime);
+      rootfattr.na_uid = uid;
+    }
+#endif
     res.ns_status = NFS_OK;
     res.ns_u.ns_attr_u = rootfattr;
   } else if (eq_fh(argp, &slink)) {
@@ -135,19 +148,19 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
      * values cache.  It forces the last-modified time of the symlink to be
      * current.  It is not needed if the O/S has an nfs flag to turn off the
      * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
+     *
+     * Additionally, Linux currently ignores the nt_useconds field,
+     * so we must update the nt_seconds field every time.
      */
-    if (++slinkfattr.na_mtime.nt_useconds == 0)
-      ++slinkfattr.na_mtime.nt_seconds;
+    if (uid != slinkfattr.na_uid) {
+      clocktime(&slinkfattr.na_mtime);
+      slinkfattr.na_uid = uid;
+    }
 #endif /* not MNT2_NFS_OPT_SYMTTL */
 
     res.ns_status = NFS_OK;
     res.ns_u.ns_attr_u = slinkfattr;
   } else {
-
-    if (getcreds(rqstp, &uid, &gid) < 0) {
-      res.ns_status = NFSERR_STALE;
-      return &res;
-    }
     if (gid != hlfs_gid) {
       res.ns_status = NFSERR_STALE;
     } else {
@@ -157,10 +170,8 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
 	res.ns_status = NFS_OK;
 	un_fattr.na_fileid = uid;
 	res.ns_u.ns_attr_u = un_fattr;
-#ifdef DEBUG
 	dlog("nfs_getattr: successful search for uid=%ld, gid=%ld",
 	     (long) uid, (long) gid);
-#endif /* DEBUG */
       } else {			/* not found */
 	res.ns_status = NFSERR_STALE;
       }
@@ -211,11 +222,26 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
     return &res;
   }
 
+  if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) {
+    res.dr_status = NFSERR_NOENT;
+    return &res;
+  }
   if (eq_fh(&argp->da_fhandle, &root)) {
     if (argp->da_name[0] == '.' &&
 	(argp->da_name[1] == '\0' ||
 	 (argp->da_name[1] == '.' &&
 	  argp->da_name[2] == '\0'))) {
+#if 0
+    /*
+     * XXX: increment mtime of parent directory, causes NFS clients to
+     * invalidate their cache for that directory.
+     * Some NFS clients may need this code.
+     */
+      if (uid != rootfattr.na_uid) {
+	clocktime(&rootfattr.na_mtime);
+	rootfattr.na_uid = uid;
+      }
+#endif
       res.dr_u.dr_drok_u.drok_fhandle = root;
       res.dr_u.dr_drok_u.drok_attributes = rootfattr;
       res.dr_status = NFS_OK;
@@ -223,13 +249,28 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
     }
 
     if (STREQ(argp->da_name, slinkname)) {
+#ifndef MNT2_NFS_OPT_SYMTTL
+      /*
+       * This code is needed to defeat Solaris 2.4's (and newer) symlink
+       * values cache.  It forces the last-modified time of the symlink to be
+       * current.  It is not needed if the O/S has an nfs flag to turn off the
+       * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
+       *
+       * Additionally, Linux currently ignores the nt_useconds field,
+       * so we must update the nt_seconds field every time.
+       */
+      if (uid != slinkfattr.na_uid) {
+	clocktime(&slinkfattr.na_mtime);
+	slinkfattr.na_uid = uid;
+      }
+#endif /* not MNT2_NFS_OPT_SYMTTL */
       res.dr_u.dr_drok_u.drok_fhandle = slink;
       res.dr_u.dr_drok_u.drok_attributes = slinkfattr;
       res.dr_status = NFS_OK;
       return &res;
     }
 
-    if (getcreds(rqstp, &uid, &gid) < 0 || gid != hlfs_gid) {
+    if (gid != hlfs_gid) {
       res.dr_status = NFSERR_NOENT;
       return &res;
     }
@@ -243,15 +284,13 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
       res.dr_u.dr_drok_u.drok_attributes = un_fattr;
       memset((char *) &un_fhandle, 0, sizeof(am_nfs_fh));
       *(u_int *) un_fhandle.fh_data = (u_int) untab[idx].uid;
-      strncpy((char *) &un_fhandle.fh_data[sizeof(int)],
-	      untab[idx].username,
-	      sizeof(am_nfs_fh) - sizeof(int));
+      xstrlcpy((char *) &un_fhandle.fh_data[sizeof(int)],
+	       untab[idx].username,
+	       sizeof(am_nfs_fh) - sizeof(int));
       res.dr_u.dr_drok_u.drok_fhandle = un_fhandle;
       res.dr_status = NFS_OK;
-#ifdef DEBUG
       dlog("nfs_lookup: successful lookup for uid=%ld, gid=%ld: username=%s",
 	   (long) uid, (long) gid, untab[idx].username);
-#endif /* DEBUG */
       return &res;
     }
   } /* end of "if (eq_fh(argp->dir.data, root.data)) {" */
@@ -260,40 +299,6 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
   return &res;
 }
 
-static int
-getcreds(struct svc_req *rp, uid_t *u, gid_t *g)
-{
-  struct authunix_parms *aup = (struct authunix_parms *) NULL;
-#ifdef HAVE_RPC_AUTH_DES_H
-  struct authdes_cred *adp;
-#endif /* HAVE_RPC_AUTH_DES_H */
-
-  switch (rp->rq_cred.oa_flavor) {
-
-  case AUTH_UNIX:
-    aup = (struct authunix_parms *) rp->rq_clntcred;
-    *u = aup->aup_uid;
-    *g = aup->aup_gid;
-    break;
-
-#ifdef HAVE_RPC_AUTH_DES_H
-  case AUTH_DES:
-    adp = (struct authdes_cred *) rp->rq_clntcred;
-    *g = INVALIDID;		/* some unknown group id */
-    if (sscanf(adp->adc_fullname.name, "unix.%lu@", (u_long *) u) == 1)
-        break;
-    /* fall through */
-#endif /* HAVE_RPC_AUTH_DES_H */
-
-  default:
-    *u = *g = INVALIDID;	/* just in case */
-    svcerr_weakauth(nfsxprt);
-    return -1;
-  }
-
-  return 0;			/* everything is ok */
-}
-
 
 nfsreadlinkres *
 nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
@@ -309,15 +314,15 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
   if (eq_fh(argp, &root)) {
     res.rlr_status = NFSERR_ISDIR;
   } else if (eq_fh(argp, &slink)) {
-    if (getcreds(rqstp, &userid, &groupid) < 0)
+    if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0)
       return (nfsreadlinkres *) NULL;
 
-    gettimeofday((struct timeval *) &slinkfattr.na_atime, (struct timezone *) 0);
+    clocktime(&slinkfattr.na_atime);
 
     res.rlr_status = NFS_OK;
     if (groupid == hlfs_gid) {
       res.rlr_u.rlr_data_u = DOTSTRING;
-    } else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid))) {
+    } else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid, groupid))) {
       /*
        * parent process (fork in homedir()) continues
        * processing, by getting a NULL returned as a
@@ -328,7 +333,7 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
 
   } else {			/* check if asked for user mailbox */
 
-    if (getcreds(rqstp, &userid, &groupid) < 0) {
+    if (getcreds(rqstp, &userid, &groupid, nfsxprt) < 0) {
       return (nfsreadlinkres *) NULL;
     }
 
@@ -350,7 +355,7 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
     last_uid = userid;
   }
 
-  /* I don't think will pass this if -D nofork */
+  /* I don't think it will pass this if -D fork */
   if (serverpid == getpid())
     return &res;
 
@@ -369,15 +374,13 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
   else
     retval = 0;
 
-#ifdef DEBUG
   /*
-   * If asked for -D nofork, then must return the value,
+   * If asked for -D fork, then must return the value,
    * NOT exit, or else the main hlfsd server exits.
-   * Bug where is that status information being collected?
+   * Bug: where is that status information being collected?
    */
-  amuDebugNo(D_FORK)
+  if (amuDebug(D_FORK))
     return &res;
-#endif /* DEBUG */
 
   exit(retval);
 }
@@ -486,7 +489,7 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
   if (eq_fh(&argp->rda_fhandle, &slink)) {
     res.rdr_status = NFSERR_NOTDIR;
   } else if (eq_fh(&argp->rda_fhandle, &root)) {
-    gettimeofday((struct timeval *) &rootfattr.na_atime, (struct timezone *) 0);
+    clocktime(&rootfattr.na_atime);
 
     res.rdr_status = NFS_OK;
     switch (argp->rda_cookie[0]) {
diff --git a/contrib/amd/include/am_compat.h b/contrib/amd/include/am_compat.h
index 876f2ea..dc3b71d 100644
--- a/contrib/amd/include/am_compat.h
+++ b/contrib/amd/include/am_compat.h
@@ -1,5 +1,47 @@
 /*
- * am_compat.h:
+ * Copyright (c) 1997-2006 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.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * 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.
+ *
+ *
+ * File: am-utils/include/am_compat.h
+ *
+ */
+
+/*
  *
  * This file contains compatibility functions and macros, all of which
  * should be auto-discovered, but for one reason or another (mostly
@@ -59,6 +101,10 @@
 # define MNTTAB_OPT_PGTHRESH "pgthresh"
 #endif /* defined(MNT2_NFS_OPT_PGTHRESH) && !defined(MNTTAB_OPT_PGTHRESH) */
 
+#if defined(MNT2_NFS_OPT_PRIVATE) && !defined(MNTTAB_OPT_PRIVATE)
+# define MNTTAB_OPT_PRIVATE "private"
+#endif /* defined(MNT2_NFS_OPT_PRIVATE) && !defined(MNTTAB_OPT_PRIVATE) */
+
 #if defined(MNT2_NFS_OPT_RETRANS) && !defined(MNTTAB_OPT_RETRANS)
 # define MNTTAB_OPT_RETRANS "retrans"
 #endif /* defined(MNT2_NFS_OPT_RETRANS) && !defined(MNTTAB_OPT_RETRANS) */
@@ -86,6 +132,18 @@
 # define MNTTAB_OPT_MAXGROUPS "maxgroups"
 #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && !defined(MNTTAB_OPT_MAXGROUPS) */
 
+#if defined(MNT2_NFS_OPT_PROPLIST) && !defined(MNTTAB_OPT_PROPLIST)
+# define MNTTAB_OPT_PROPLIST "proplist"
+#endif /* defined(MNT2_NFS_OPT_PROPLIST) && !defined(MNTTAB_OPT_PROPLIST) */
+
+#if defined(MNT2_NFS_OPT_NONLM) && !defined(MNTTAB_OPT_NOLOCK)
+# define MNTTAB_OPT_NOLOCK "nolock"
+#endif /* defined(MNT2_NFS_OPT_NONLM) && !defined(MNTTAB_OPT_NOLOCK) */
+
+#if defined(MNT2_NFS_OPT_XLATECOOKIE) && !defined(MNTTAB_OPT_XLATECOOKIE)
+# define MNTTAB_OPT_XLATECOOKIE "xlatecookie"
+#endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && !defined(MNTTAB_OPT_XLATECOOKIE) */
+
 /*
  * Complete MNTTAB_OPT_* options based on MNT2_CDFS_OPT_* mount options.
  */
@@ -123,6 +181,19 @@
 #endif /* defined(MNT2_CDFS_OPT_EXTATT) && !defined(MNTTAB_OPT_EXTATT) */
 
 /*
+ * Complete MNTTAB_OPT_* options based on MNT2_PCFS_OPT_* mount options.
+ */
+#if defined(MNT2_PCFS_OPT_LONGNAME) && !defined(MNTTAB_OPT_LONGNAME)
+# define MNTTAB_OPT_LONGNAME "longnames"
+#endif /* defined(MNT2_PCFS_OPT_LONGNAME) && !defined(MNTTAB_OPT_LONGNAME) */
+#if defined(MNT2_PCFS_OPT_NOWIN95) && !defined(MNTTAB_OPT_NOWIN95)
+# define MNTTAB_OPT_NOWIN95 "nowin95"
+#endif /* defined(MNT2_PCFS_OPT_NOWIN95) && !defined(MNTTAB_OPT_NOWIN95) */
+#if defined(MNT2_PCFS_OPT_SHORTNAME) && !defined(MNTTAB_OPT_SHORTNAME)
+# define MNTTAB_OPT_SHORTNAME "shortnames"
+#endif /* defined(MNT2_PCFS_OPT_SHORTNAME) && !defined(MNTTAB_OPT_SHORTNAME) */
+
+/*
  * Complete MNTTAB_OPT_* options based on MNT2_GEN_OPT_* mount options.
  */
 #if defined(MNT2_GEN_OPT_GRPID) && !defined(MNTTAB_OPT_GRPID)
@@ -147,10 +218,6 @@
  */
 #if defined(MNT2_GEN_OPT_NODEV) && !defined(MNTTAB_OPT_NODEV)
 # define MNTTAB_OPT_NODEV "nodev"
-/* this is missing under some versions of Linux */
-# ifndef MNTTAB_OPT_DEV
-#  define MNTTAB_OPT_DEV "dev"
-# endif /* not MNTTAB_OPT_DEV */
 #endif /* defined(MNT2_GEN_OPT_NODEV) && !defined(MNTTAB_OPT_NODEV) */
 
 #if defined(MNT2_GEN_OPT_NOEXEC) && !defined(MNTTAB_OPT_NOEXEC)
@@ -185,6 +252,10 @@
 # define MNTTAB_OPT_PORT "port"
 #endif /* not MNTTAB_OPT_PORT */
 
+#ifndef MNTTAB_OPT_PUBLIC
+# define MNTTAB_OPT_PUBLIC "public"
+#endif /* not MNTTAB_OPT_PUBLIC */
+
 #ifndef MNTTAB_OPT_RETRANS
 # define MNTTAB_OPT_RETRANS "retrans"
 #endif /* not MNTTAB_OPT_RETRANS */
@@ -213,6 +284,19 @@
 # define MNTTAB_OPT_WSIZE "wsize"
 #endif /* not MNTTAB_OPT_WSIZE */
 
+/* next four are useful for pcfs mounts */
+#ifndef MNTTAB_OPT_USER
+# define MNTTAB_OPT_USER "user"
+#endif /* not MNTTAB_OPT_USER */
+#ifndef MNTTAB_OPT_GROUP
+# define MNTTAB_OPT_GROUP "group"
+#endif /* not MNTTAB_OPT_GROUP */
+#ifndef MNTTAB_OPT_MASK
+# define MNTTAB_OPT_MASK "mask"
+#endif /* not MNTTAB_OPT_MASK */
+#ifndef MNTTAB_OPT_DIRMASK
+# define MNTTAB_OPT_DIRMASK "dirmask"
+#endif /* not MNTTAB_OPT_DIRMASK */
 
 /*
  * Incomplete filesystem definitions (sunos4, irix6, solaris2)
@@ -233,7 +317,7 @@ struct hsfs_args {
         int norrip;
 };
 # define cdfs_args_t struct hsfs_args
-# define HAVE_FIELD_CDFS_ARGS_T_NORRIP
+# define HAVE_CDFS_ARGS_T_NORRIP
 #endif /* not cdfs_args_t */
 
 /*
@@ -250,6 +334,20 @@ struct hsfs_args {
 # define ufs_args_t u_int
 #endif /* defined(HAVE_FS_UFS) && !defined(ufs_args_t) */
 
+/*
+ * if does not define struct efs_args, assume integer bit-field (linux)
+ */
+#if defined(HAVE_FS_EFS) && !defined(efs_args_t)
+# define efs_args_t u_int
+#endif /* defined(HAVE_FS_EFS) && !defined(efs_args_t) */
+
+/*
+ * if does not define struct xfs_args, assume integer bit-field (linux)
+ */
+#if defined(HAVE_FS_XFS) && !defined(xfs_args_t)
+# define xfs_args_t u_int
+#endif /* defined(HAVE_FS_XFS) && !defined(xfs_args_t) */
+
 #if defined(HAVE_FS_AUTOFS) && defined(MOUNT_TYPE_AUTOFS) && !defined(MNTTYPE_AUTOFS)
 # define MNTTYPE_AUTOFS "autofs"
 #endif /* defined(HAVE_FS_AUTOFS) && defined(MOUNT_TYPE_AUTOFS) && !defined(MNTTYPE_AUTOFS) */
@@ -267,4 +365,29 @@ struct hsfs_args {
 # endif /* not MNTTAB_OPT_PROTO */
 #endif /* not HAVE_FS_NFS3 */
 
+/*
+ * If loop device (header file) exists, define mount table option
+ */
+#if defined(HAVE_LOOP_DEVICE) && !defined(MNTTAB_OPT_LOOP)
+# define MNTTAB_OPT_LOOP "loop"
+#endif /* defined(HAVE_LOOP_DEVICE) && !defined(MNTTAB_OPT_LOOP) */
+
+/*
+ * Define a dummy struct netconfig for non-TLI systems
+ */
+#if !defined(HAVE_NETCONFIG_H) && !defined(HAVE_SYS_NETCONFIG_H)
+struct netconfig {
+  int dummy;
+};
+#endif /* not HAVE_NETCONFIG_H and not HAVE_SYS_NETCONFIG_H */
+
+/* some OSs don't define INADDR_NONE and assume it's unsigned -1 */
+#ifndef INADDR_NONE
+# define INADDR_NONE	0xffffffffU
+#endif /* INADDR_NONE */
+/* some OSs don't define INADDR_LOOPBACK */
+#ifndef INADDR_LOOPBACK
+# define INADDR_LOOPBACK	0x7f000001
+#endif /* not INADDR_LOOPBACK */
+
 #endif /* not _AM_COMPAT_H */
diff --git a/contrib/amd/include/am_defs.h b/contrib/amd/include/am_defs.h
index 239004e..53c66bf 100644
--- a/contrib/amd/include/am_defs.h
+++ b/contrib/amd/include/am_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,11 +36,10 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: am_defs.h,v 1.11 1999/09/18 08:38:05 ezk Exp $
- * $FreeBSD: src/contrib/amd/include/am_defs.h,v 1.8 1999/11/05 11:58:03 obrien Exp $
- * $DragonFly: src/contrib/amd/include/am_defs.h,v 1.4 2005/04/29 09:51:32 joerg Exp $
+ * File: am-utils/include/am_defs.h
+ * $Id: am_defs.h,v 1.15.2.16 2004/05/12 15:54:31 ezk Exp $
+ * $FreeBSD: src/contrib/amd/include/am_defs.h,v 1.16 2012/11/17 01:48:41 svnexp Exp $
  *
  */
 
@@ -107,6 +106,15 @@ char *strchr(), *strrchr(), *strdup();
  */
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
+# ifdef _ALL_SOURCE
+/*
+ * AIX 5.2 needs struct sigevent from signal.h to be defined, but I
+ * don't want to move the inclusion of signal.h this early into this
+ * file.  Luckily, amd doesn't need the size of this structure in any
+ * other structure that it uses.  So we sidestep it for now.
+ */
+struct sigevent;
+# endif /* _ALL_SOURCE */
 # include <time.h>
 #else /* not TIME_WITH_SYS_TIME */
 # if HAVE_SYS_TIME_H
@@ -140,6 +148,13 @@ char *strchr(), *strrchr(), *strdup();
 #endif /* HAVE_SYS_TYPES_H */
 
 /*
+ * Actions to take if HAVE_LIMITS_H is defined.
+ */
+#if HAVE_LIMITS_H_H
+# include <limits.h>
+#endif /* HAVE_LIMITS_H */
+
+/*
  * Actions to take if HAVE_UNISTD_H is defined.
  */
 #if HAVE_UNISTD_H
@@ -194,6 +209,12 @@ char *strchr(), *strrchr(), *strdup();
  * Actions to take if HAVE_FCNTL_H is defined.
  */
 #if HAVE_FCNTL_H
+# ifdef HAVE_LINUX_LOOP_H
+/* so I can mount large files as loop devices */
+/* XXX: need to move these two LARGEFILE defines to a better place */
+#  define _LARGEFILE64_SOURCE
+#  define __USE_LARGEFILE64
+# endif /* HAVE_LINUX_LOOP_H */
 # include <fcntl.h>
 #endif /* HAVE_FCNTL_H */
 
@@ -277,10 +298,13 @@ typedef bool_t (*xdrproc_t) __P ((XDR *, __ptr_t, ...));
 
 /*
  * Actions to take if <malloc.h> exists.
+ * Don't include malloc.h if stdlib.h exists, because modern
+ * systems complain if you use malloc.h instead of stdlib.h.
+ * XXX: let's hope there are no systems out there that need both.
  */
-#ifdef HAVE_MALLOC_H
+#if defined(HAVE_MALLOC_H) && !defined(HAVE_STDLIB_H)
 # include <malloc.h>
-#endif /* HAVE_MALLOC_H */
+#endif /* defined(HAVE_MALLOC_H) && !defined(HAVE_STDLIB_H) */
 
 /*
  * Actions to take if <mntent.h> exists.
@@ -298,6 +322,7 @@ typedef bool_t (*xdrproc_t) __P ((XDR *, __ptr_t, ...));
  */
 #ifdef HAVE_SYS_ERRNO_H
 # include <sys/errno.h>
+extern int errno;
 #endif /* HAVE_SYS_ERRNO_H */
 
 /*
@@ -326,20 +351,13 @@ typedef bool_t (*xdrproc_t) __P ((XDR *, __ptr_t, ...));
  * Should be included before <rpcsvc/yp_prot.h> because on some systems
  * like Linux, it also defines "struct datum".
  */
-#ifdef HAVE_NDBM_H
-# include <ndbm.h>
+#ifdef HAVE_MAP_NDBM
+# include NEW_DBM_H
 # ifndef DATUM
 /* ensure that struct datum is not included again from <rpcsvc/yp_prot.h> */
 #  define DATUM
 # endif /* not DATUM */
-#endif /* HAVE_NDBM_H */
-#ifdef HAVE_DB1_NDBM_H
-# include <db1/ndbm.h>
-# ifndef DATUM
-/* ensure that struct datum is not included again from <rpcsvc/yp_prot.h> */
-#  define DATUM
-# endif /* not DATUM */
-#endif /* HAVE_DB1_NDBM_H */
+#endif /* HAVE_MAP_NDBM */
 
 /*
  * Actions to take if <net/errno.h> exists.
@@ -349,6 +367,13 @@ typedef bool_t (*xdrproc_t) __P ((XDR *, __ptr_t, ...));
 #endif /* HAVE_NET_ERRNO_H */
 
 /*
+ * Actions to take if <net/if.h> exists.
+ */
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif /* HAVE_NET_IF_H */
+
+/*
  * Actions to take if <net/route.h> exists.
  */
 #ifdef HAVE_NET_ROUTE_H
@@ -382,11 +407,11 @@ typedef bool_t (*xdrproc_t) __P ((XDR *, __ptr_t, ...));
 #endif /* HAVE_SYS_MBUF_H */
 
 /*
- * Actions to take if <net/if.h> exists.
+ * Actions to take if <sys/mman.h> exists.
  */
-#ifdef HAVE_NET_IF_H
-# include <net/if.h>
-#endif /* HAVE_NET_IF_H */
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif /* HAVE_SYS_MMAN_H */
 
 /*
  * Actions to take if <netdb.h> exists.
@@ -458,32 +483,29 @@ struct ypall_callback;
  * NFS and other definitions included.
  */
 # ifndef NFSCLIENT
-#  define NFSCLIENT
+#  define NFSCLIENT 1
 # endif /* not NFSCLIENT */
 # ifndef NFS
-#  define NFS
+#  define NFS 1
 # endif /* not NFS */
 # ifndef PCFS
-#  define PCFS
+#  define PCFS 1
 # endif /* not PCFS */
 # ifndef LOFS
-#  define LOFS
+#  define LOFS 1
 # endif /* not LOFS */
 # ifndef RFS
-#  define RFS
+#  define RFS 1
 # endif /* not RFS */
 # ifndef MSDOSFS
-#  define MSDOSFS
+#  define MSDOSFS 1
 # endif /* not MSDOSFS */
 # ifndef MFS
-#  define MFS
+#  define MFS 1
 # endif /* not MFS */
 # ifndef CD9660
-#  define CD9660
+#  define CD9660 1
 # endif /* not CD9660 */
-# ifndef NFS
-#  define NFS
-# endif /* not NFS */
 # include <sys/mount.h>
 #endif /* HAVE_SYS_MOUNT_H */
 
@@ -493,8 +515,10 @@ struct ypall_callback;
 
 /*
  * Actions to take if <linux/fs.h> exists.
+ * There is no point in including this on a glibc2 system,
+ * we're only asking for trouble
  */
-#ifdef HAVE_LINUX_FS_H
+#if defined HAVE_LINUX_FS_H && (!defined __GLIBC__ || __GLIBC__ < 2)
 /*
  * There are various conflicts in definitions between RedHat Linux, newer
  * 2.2 kernels, and <netinet/in.h> and <linux/fs.h>.
@@ -560,8 +584,21 @@ struct ypall_callback;
 /* conflicts with <statfsbuf.h> */
 #  define _SYS_STATFS_H
 # endif /* _SYS_MOUNT_H */
+# ifndef _LINUX_STRING_H_
+#  define _LINUX_STRING_H_
+# endif /* not _LINUX_STRING_H_ */
+# ifdef HAVE_LINUX_KDEV_T_H
+#  define __KERNEL__
+#  include <linux/kdev_t.h>
+#  undef __KERNEL__
+# endif /* HAVE_LINUX_KDEV_T_H */
+# ifdef HAVE_LINUX_LIST_H
+#  define __KERNEL__
+#  include <linux/list.h>
+#  undef __KERNEL__
+# endif /* HAVE_LINUX_LIST_H */
 # include <linux/fs.h>
-#endif /* HAVE_LINUX_FS_H */
+#endif /* HAVE_LINUX_FS_H && (!__GLIBC__ || __GLIBC__ < 2) */
 
 #ifdef HAVE_CDFS_CDFS_MOUNT_H
 # include <cdfs/cdfs_mount.h>
@@ -572,11 +609,36 @@ struct ypall_callback;
 #endif /* HAVE_CDFS_CDFSMOUNT_H */
 
 /*
- * Actions to take if <linux/auto_fs.h> exists.
+ * Actions to take if <linux/loop.h> exists.
  */
-#ifdef HAVE_LINUX_AUTO_FS_H
-# include <linux/auto_fs.h>
-#endif /* HAVE_LINUX_AUTO_FS_H */
+#ifdef HAVE_LINUX_LOOP_H
+# ifdef HAVE_LINUX_POSIX_TYPES_H
+#  include <linux/posix_types.h>
+# endif /* HAVE_LINUX_POSIX_TYPES_H */
+/* next dev_t lines needed due to changes in kernel code */
+# undef dev_t
+# define dev_t unsigned short	/* compatible with Red Hat and SuSE */
+# include <linux/loop.h>
+#endif /* HAVE_LINUX_LOOP_H */
+
+/*
+ * AUTOFS PROTOCOL HEADER FILES:
+ */
+
+/*
+ * Actions to take if <linux/auto_fs[4].h> exists.
+ * We really don't want <linux/fs.h> pulled in here
+ */
+#ifndef _LINUX_FS_H
+#define _LINUX_FS_H
+#endif /* _LINUX_FS_H */
+#ifdef HAVE_LINUX_AUTO_FS4_H
+# include <linux/auto_fs4.h>
+#else  /* not HAVE_LINUX_AUTO_FS4_H */
+# ifdef HAVE_LINUX_AUTO_FS_H
+#  include <linux/auto_fs.h>
+# endif /* HAVE_LINUX_AUTO_FS_H */
+#endif /* not HAVE_LINUX_AUTO_FS4_H */
 
 /*
  * Actions to take if <sys/fs/autofs.h> exists.
@@ -586,11 +648,38 @@ struct ypall_callback;
 #endif /* HAVE_SYS_FS_AUTOFS_H */
 
 /*
- * Actions to take if <sys/fs/autofs_prot.h> exists.
+ * Actions to take if <rpcsvc/autofs_prot.h> or <sys/fs/autofs_prot.h> exist.
  */
-#ifdef HAVE_SYS_FS_AUTOFS_PROT_H
-# include <sys/fs/autofs_prot.h>
-#endif /* HAVE_SYS_FS_AUTOFS_PROT_H */
+#ifdef HAVE_RPCSVC_AUTOFS_PROT_H
+# include <rpcsvc/autofs_prot.h>
+#else  /* not HAVE_RPCSVC_AUTOFS_PROT_H */
+# ifdef HAVE_SYS_FS_AUTOFS_PROT_H
+#  include <sys/fs/autofs_prot.h>
+# endif /* HAVE_SYS_FS_AUTOFS_PROT_H */
+#endif /* not HAVE_RPCSVC_AUTOFS_PROT_H */
+
+/*
+ * Actions to take if <lber.h> exists.
+ * This header file is required before <ldap.h> can be included.
+ */
+#ifdef HAVE_LBER_H
+# include <lber.h>
+#endif /* HAVE_LBER_H */
+
+/*
+ * Actions to take if <ldap.h> exists.
+ */
+#ifdef HAVE_LDAP_H
+# include <ldap.h>
+#endif /* HAVE_LDAP_H */
+
+/****************************************************************************
+ ** IMPORTANT!!!							   **
+ ** We always include am-utils' amu_autofs_prot.h.			   **
+ ** That is actually defined in "conf/autofs/autofs_${autofs_style}.h"     **
+ ****************************************************************************/
+#include <amu_autofs_prot.h>
+
 
 /*
  * NFS PROTOCOL HEADER FILES:
@@ -605,7 +694,7 @@ struct ypall_callback;
 
 /****************************************************************************
  ** IMPORTANT!!!							   **
- ** We always include am-util's amu_nfs_prot.h.				   **
+ ** We always include am-utils' amu_nfs_prot.h.				   **
  ** That is actually defined in "conf/nfs_prot/nfs_prot_${host_os_name}.h" **
  ****************************************************************************/
 #include <amu_nfs_prot.h>
@@ -633,7 +722,7 @@ struct ypall_callback;
 # include <nfs/mount.h>
 #endif /* HAVE_NFS_MOUNT_H */
 #ifdef HAVE_NFS_NFS_MOUNT_H_off
-/* broken on nexttep3 (includes non-existing headers) */
+/* broken on nextstep3 (includes non-existing headers) */
 # include <nfs/nfs_mount.h>
 #endif /* HAVE_NFS_NFS_MOUNT_H */
 #ifdef HAVE_NFS_PATHCONF_H
@@ -648,8 +737,29 @@ struct ypall_callback;
 #ifdef HAVE_SYS_FS_NFS_CLNT_H
 # include <sys/fs/nfs_clnt.h>
 #endif /* HAVE_SYS_FS_NFS_CLNT_H */
+
+/* complex rules for linux/nfs_mount.h: broken on so many systems */
 #ifdef HAVE_LINUX_NFS_MOUNT_H
+# ifndef _LINUX_NFS_H
+#  define _LINUX_NFS_H
+# endif /* not _LINUX_NFS_H */
+# ifndef _LINUX_NFS2_H
+#  define _LINUX_NFS2_H
+# endif /* not _LINUX_NFS2_H */
+# ifndef _LINUX_NFS3_H
+#  define _LINUX_NFS3_H
+# endif /* not _LINUX_NFS3_H */
+# ifndef _LINUX_NFS_FS_H
+#  define _LINUX_NFS_FS_H
+# endif /* not _LINUX_NFS_FS_H */
+# ifndef _LINUX_IN_H
+#  define _LINUX_IN_H
+# endif /* not _LINUX_IN_H */
+# ifndef __KERNEL__
+#  define __KERNEL__
+# endif /* __KERNEL__ */
 # include <linux/nfs_mount.h>
+# undef __KERNEL__
 #endif /* HAVE_LINUX_NFS_MOUNT_H */
 
 /*
@@ -667,21 +777,6 @@ struct ypall_callback;
 #endif /* HAVE_HESIOD_H */
 
 /*
- * Actions to take if <lber.h> exists.
- * This header file is required before <ldap.h> can be included.
- */
-#ifdef HAVE_LBER_H
-# include <lber.h>
-#endif /* HAVE_LBER_H */
-
-/*
- * Actions to take if <ldap.h> exists.
- */
-#ifdef HAVE_LDAP_H
-# include <ldap.h>
-#endif /* HAVE_LDAP_H */
-
-/*
  * Actions to take if <arpa/nameser.h> exists.
  * Should be included before <resolv.h>.
  */
@@ -714,6 +809,14 @@ struct sockaddr_dl;
  * Actions to take if <resolv.h> exists.
  */
 #ifdef HAVE_RESOLV_H
+/*
+ * On AIX 5.2, both <resolv.h> and <arpa/nameser_compat.h> define MAXDNAME,
+ * if compiling with gcc -D_USE_IRS (so that we get extern definitions for
+ * hstrerror() and others).
+ */
+# if defined(_AIX) && defined(MAXDNAME) && defined(_USE_IRS)
+#  undef MAXDNAME
+# endif /* defined(_AIX) && defined(MAXDNAME) && defined(_USE_IRS) */
 # include <resolv.h>
 #endif /* HAVE_RESOLV_H */
 
@@ -744,6 +847,16 @@ struct sockaddr_dl;
 #ifdef HAVE_MSDOSFS_MSDOSFSMOUNT_H
 # include <msdosfs/msdosfsmount.h>
 #endif /* HAVE_MSDOSFS_MSDOSFSMOUNT_H */
+#ifdef HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H
+# include <fs/msdosfs/msdosfsmount.h>
+#endif /* HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H */
+
+/*
+ * Actions to take if <fs/msdosfs/msdosfsmount.h> exists.
+ */
+#ifdef HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H
+# include <fs/msdosfs/msdosfsmount.h>
+#endif /* HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H */
 
 /*
  * Actions to take if <sys/fs/tmp.h> exists.
@@ -758,11 +871,13 @@ struct sockaddr_dl;
 #ifdef HAVE_SYS_FS_UFS_MOUNT_H
 # include <sys/fs/ufs_mount.h>
 #endif /* HAVE_SYS_FS_UFS_MOUNT_H */
-#ifdef	HAVE_UFS_UFS_UFSMOUNT_H_off
-# error do not include this file here because on netbsd/openbsd it
-# error causes errors with other header files.  Instead, add it to the
-# error specific conf/nfs_prot_*.h file.
-# include <vfs/ufs/ufsmount.h>
+/* 
+ * HAVE_UFS_UFS_UFSMOUNT_H should NOT be defined on netbsd/openbsd because it
+ * causes errors with other header files.  Instead, add it to the specific
+ * conf/nfs_prot_*.h file.
+ */
+#ifdef	HAVE_UFS_UFS_UFSMOUNT_H
+# include <ufs/ufs/ufsmount.h>
 #endif	/* HAVE_UFS_UFS_UFSMOUNT_H */
 
 /*
@@ -883,19 +998,32 @@ struct sockaddr_dl;
  * AIX does not protect against this file doubly included,
  * so I have to do my own protection here.
  */
-#ifdef COMMENT_OUT
 #ifdef HAVE_RPCSVC_MOUNT_H
 # ifndef _RPCSVC_MOUNT_H
 #  include <rpcsvc/mount.h>
 # endif /* not _RPCSVC_MOUNT_H */
 #endif /* HAVE_RPCSVC_MOUNT_H */
-#endif
-#  include "mount.h"
 
 /*
  * Actions to take if <rpcsvc/nis.h> exists.
  */
 #ifdef HAVE_RPCSVC_NIS_H
+/*
+ * Solaris 10 (build 72) defines GROUP_OBJ in <sys/acl.h>, which is included
+ * in many other header files.  <rpcsvc/nis.h> uses GROUP_OBJ inside enum
+ * zotypes.  So if you're unlucky enough to include both headers, you get a
+ * compile error because the two symbols conflict.
+ * A similar conflict arises with Sun cc and the definition of "GROUP".
+ *
+ * Temp hack: undefine acl.h's GROUP_OBJ and GROUP because they're not needed
+ * for am-utils.
+ */
+# ifdef GROUP_OBJ
+#  undef GROUP_OBJ
+# endif /* GROUP_OBJ */
+# ifdef GROUP
+#  undef GROUP
+# endif /* GROUP */
 # include <rpcsvc/nis.h>
 #endif /* HAVE_RPCSVC_NIS_H */
 
@@ -1100,6 +1228,13 @@ extern char *nc_sperror(void);
 #endif /* HAVE_SYS_STATFS_H */
 
 /*
+ * Actions to take if <sys/statvfs.h> exists.
+ */
+#ifdef HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h>
+#endif /* HAVE_SYS_STATVFS_H */
+
+/*
  * Actions to take if <sys/vfs.h> exists.
  */
 #ifdef HAVE_SYS_VFS_H
@@ -1117,7 +1252,7 @@ extern char *nc_sperror(void);
  * Actions to take if <ufs/ufs_mount.h> exists.
  */
 #ifdef HAVE_UFS_UFS_MOUNT_H
-# include <vfs/ufs/ufsmount.h>
+# include <ufs/ufs_mount.h>
 #endif /* HAVE_UFS_UFS_MOUNT_H */
 
 /*
@@ -1192,6 +1327,13 @@ extern char *nc_sperror(void);
 # include <regex.h>
 #endif /* HAVE_REGEX_H */
 
+/*
+ * Actions to take if <tcpd.h> exists.
+ */
+#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
+# include <tcpd.h>
+#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
+
 
 /****************************************************************************/
 /*
@@ -1273,13 +1415,23 @@ typedef struct _am_mntent {
 # endif /* not HAVE_STRUCT_MNTTAB */
 #endif /* not HAVE_STRUCT_MNTENT */
 
+/*
+ * Provide FD_* macros for systems that lack them.
+ */
+#ifndef FD_SET
+# define FD_SET(fd, set) (*(set) |= (1 << (fd)))
+# define FD_ISSET(fd, set) (*(set) & (1 << (fd)))
+# define FD_CLR(fd, set) (*(set) &= ~(1 << (fd)))
+# define FD_ZERO(set) (*(set) = 0)
+#endif /* not FD_SET */
+
 
 /*
  * Complete external definitions missing from some systems.
  */
 
 #ifndef HAVE_EXTERN_SYS_ERRLIST
-extern const char * const sys_errlist[];
+extern const char *const sys_errlist[];
 #endif /* not HAVE_EXTERN_SYS_ERRLIST */
 
 #ifndef HAVE_EXTERN_OPTARG
@@ -1329,6 +1481,10 @@ extern int getpagesize(void);
 extern char *getwd(char *s);
 #endif /* not HAVE_EXTERN_GETWD */
 
+#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) && !defined(HAVE_EXTERN_HOSTS_CTL)
+extern int hosts_ctl(char *daemon, char *client_name, char *client_addr, char *client_user);
+#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) && !defined(HAVE_EXTERN_HOSTS_CTL) */
+
 #ifndef HAVE_EXTERN_INNETGR
 extern int innetgr(char *, char *, char *, char *);
 #endif /* not HAVE_EXTERN_INNETGR */
@@ -1349,6 +1505,10 @@ extern int seteuid(uid_t euid);
 extern int setitimer(int, struct itimerval *, struct itimerval *);
 #endif /* defined(HAVE_SETITIMER) && !defined(HAVE_EXTERN_SETITIMER) */
 
+#ifndef HAVE_EXTERN_SLEEP
+extern unsigned int sleep(unsigned int seconds);
+#endif /* not HAVE_EXTERN_SETITIMER */
+
 #ifndef HAVE_EXTERN_STRCASECMP
 /*
  * define this extern even if function does not exist, for it will
@@ -1365,6 +1525,22 @@ extern int strcasecmp(const char *s1, const char *s2);
 extern char *strdup(const char *s);
 #endif /* not HAVE_EXTERN_STRDUP */
 
+#ifndef HAVE_EXTERN_STRLCAT
+/*
+ * define this extern even if function does not exist, for it will
+ * be filled in by libamu/strlcat.c
+ */
+extern size_t strlcat(char *dst, const char *src, size_t siz);
+#endif /* not HAVE_EXTERN_STRLCAT */
+
+#ifndef HAVE_EXTERN_STRLCPY
+/*
+ * define this extern even if function does not exist, for it will
+ * be filled in by libamu/strlcpy.c
+ */
+extern size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif /* not HAVE_EXTERN_STRLCPY */
+
 #if defined(HAVE_STRSTR) && !defined(HAVE_EXTERN_STRSTR)
 extern char *strstr(const char *s1, const char *s2);
 #endif /* defined(HAVE_STRSTR) && !defined(HAVE_EXTERN_STRSTR) */
@@ -1385,6 +1561,10 @@ extern int wait3(int *statusp, int options, struct rusage *rusage);
 extern int vsnprintf(char *, int, const char *, ...);
 #endif /* defined(HAVE_VSNPRINTF) && !defined(HAVE_EXTERN_VSNPRINTF) */
 
+#ifndef HAVE_EXTERN_XDR_CALLMSG
+extern bool_t xdr_callmsg(XDR *xdrs, struct rpc_msg *msg);
+#endif /* not HAVE_EXTERN_XDR_CALLMSG */
+
 #ifndef HAVE_EXTERN_XDR_OPAQUE_AUTH
 extern bool_t xdr_opaque_auth(XDR *xdrs, struct opaque_auth *auth);
 #endif /* not HAVE_EXTERN_XDR_OPAQUE_AUTH */
@@ -1396,11 +1576,11 @@ extern bool_t xdr_opaque_auth(XDR *xdrs, struct opaque_auth *auth);
 #ifdef THIS_HEADER_FILE_IS_INCLUDED_ABOVE
 # include <amu_nfs_prot.h>
 #endif /* THIS_HEADER_FILE_IS_INCLUDED_ABOVE */
+#include <am_compat.h>
+#include <am_xdr_func.h>
 #include <am_utils.h>
 #include <amq_defs.h>
 #include <aux_conf.h>
-/* compatibility with old amd, while autoconfiscating it */
-#include <am_compat.h>
 
 
 /****************************************************************************/
@@ -1409,14 +1589,14 @@ extern bool_t xdr_opaque_auth(XDR *xdrs, struct opaque_auth *auth);
  * and those are probably declared in any of the above headers.
  */
 
-#ifndef HAVE_HASMNTOPT
-extern char *hasmntopt(mntent_t *mnt, char *opt);
+#ifdef HAVE_HASMNTOPT
+# ifdef HAVE_BAD_HASMNTOPT
+extern char *amu_hasmntopt(mntent_t *mnt, char *opt);
+# else /* not HAVE_BAD_HASMNTOPT */
+#  define amu_hasmntopt hasmntopt
+# endif /* not HAVE_BAD_HASMNTOPT */
+#else /* not HAVE_HASMNTOPT */
+extern char *amu_hasmntopt(mntent_t *mnt, char *opt);
 #endif /* not HAVE_HASMNTOPT */
 
-/*
- * include definitions of all possible xdr functions that are otherwise
- * not defined elsewhere.
- */
-#include <am_xdr_func.h>
-
 #endif /* not _AM_DEFS_H */
diff --git a/contrib/amd/include/am_utils.h b/contrib/amd/include/am_utils.h
index 4098cd4..b7e55ce 100644
--- a/contrib/amd/include/am_utils.h
+++ b/contrib/amd/include/am_utils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: am_utils.h,v 1.6 1999/08/22 05:12:55 ezk Exp $
+ * File: am-utils/include/am_utils.h
  *
  */
 
@@ -50,6 +49,8 @@
 #define _AM_UTILS_H
 
 
+#include "aux_conf.h"
+
 /**************************************************************************/
 /*** MACROS								***/
 /**************************************************************************/
@@ -76,16 +77,25 @@
 # ifdef HOSTNAMESZ
 #  define MAXHOSTNAMELEN HOSTNAMESZ
 # else /* not HOSTNAMESZ */
-#  define MAXHOSTNAMELEN 64
+#  define MAXHOSTNAMELEN 256
 # endif /* not HOSTNAMESZ */
 #endif /* not MAXHOSTNAMELEN */
 
 /*
+ * for hlfsd, and amd for detecting uid/gid
+ */
+#ifndef INVALIDID
+/* this is also defined in include/am_utils.h */
+# define INVALIDID	(((unsigned short) ~0) - 3)
+#endif /* not INVALIDID */
+
+/*
  * String comparison macros
  */
 #define STREQ(s1, s2)		(strcmp((s1), (s2)) == 0)
 #define STRCEQ(s1, s2)		(strcasecmp((s1), (s2)) == 0)
 #define NSTREQ(s1, s2, n)	(strncmp((s1), (s2), (n)) == 0)
+#define NSTRCEQ(s1, s2, n)	(strncasecmp((s1), (s2), (n)) == 0)
 #define FSTREQ(s1, s2)		((*(s1) == *(s2)) && STREQ((s1),(s2)))
 
 /*
@@ -102,16 +112,9 @@
 #define XLOG_DEFSTR	"all,nomap,nostats"	/* Default log options */
 #define XLOG_ALL	(XLOG_FATAL|XLOG_ERROR|XLOG_USER|XLOG_WARNING|XLOG_INFO|XLOG_MAP|XLOG_STATS)
 
-#define clocktime() (clock_valid ? clock_valid : time(&clock_valid))
-
-#ifndef ROOT_MAP
-# define ROOT_MAP "\"root\""
-#endif /* not ROOT_MAP */
-
-#define NO_SUBNET	"notknown"	/* default subnet name for no subnet */
-#define	NEXP_AP		(1022)	/* gdmr: was 254 */
-#define NEXP_AP_MARGIN	(128)
-#define	MAX_READDIR_ENTRIES	16
+#define NO_SUBNET	"notknown"   /* default subnet name for no subnet */
+#define	NEXP_AP		(1022)			/* gdmr: was 254 */
+#define NEXP_AP_MARGIN	(128)			/* ???? not used */
 
 /*
  * Linked list macros
@@ -126,84 +129,30 @@
 
 /* allocate anything of type ty */
 #define	ALLOC(ty)	((ty *) xmalloc(sizeof(ty)))
-#define	CALLOC(ty)	((ty *) xcalloc(1, sizeof(ty)))
+#define	CALLOC(ty)	((ty *) xzalloc(sizeof(ty)))
 /* simply allocate b bytes */
 #define	SALLOC(b)	xmalloc((b))
 
-/* converting am-filehandles to mount-points */
-#define	fh_to_mp2(fhp, rp) fh_to_mp3(fhp, rp, VLOOK_CREATE)
-
 /*
  * Systems which have the mount table in a file need to read it before
  * they can perform an unmount() system call.
  */
-#define UMOUNT_FS(dir, mtb_name)	umount_fs(dir, mtb_name)
-/* imported via $srcdir/conf/umount/umount_*.c */
-extern int umount_fs(char *fs_name, const char *mnttabname);
+#define UMOUNT_FS(dir, mtb_name, unmount_flags)	umount_fs(dir, mtb_name, unmount_flags)
+/* next two are imported via $srcdir/conf/umount/umount_*.c */
+extern int umount_fs(char *mntdir, const char *mnttabname, u_int unmount_flags);
+#ifdef MNT2_GEN_OPT_FORCE
+extern int umount2_fs(const char *mntdir, u_int unmount_flags);
+#endif /* MNT2_GEN_OPT_FORCE */
 
-/*
- * macros for automounter vfs/vnode operations.
- */
-#define	VLOOK_CREATE	0x1
-#define	VLOOK_DELETE	0x2
-#define FS_DIRECTORY	0x0001	/* This looks like a dir, not a link */
-#define	FS_MBACKGROUND	0x0002	/* Should background this mount */
-#define	FS_NOTIMEOUT	0x0004	/* Don't bother with timeouts */
-#define FS_MKMNT	0x0008	/* Need to make the mount point */
-#define FS_UBACKGROUND	0x0010	/* Unmount in background */
-#define	FS_BACKGROUND	(FS_MBACKGROUND|FS_UBACKGROUND)
-#define	FS_DISCARD	0x0020	/* Discard immediately on last reference */
-#define	FS_AMQINFO	0x0040	/* Amq is interested in this fs type */
-
-/*
- * macros for struct fserver.
- */
-#define	FSF_VALID	0x0001	/* Valid information available */
-#define	FSF_DOWN	0x0002	/* This fileserver is thought to be down */
-#define	FSF_ERROR	0x0004	/* Permanent error has occurred */
-#define	FSF_WANT	0x0008	/* Want a wakeup call */
-#define	FSF_PINGING	0x0010	/* Already doing pings */
-#define	FSRV_ISDOWN(fs)	(((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID))
-#define	FSRV_ISUP(fs)	(((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID))
-
-/*
- * macros for struct mntfs (list of mounted filesystems)
- */
-#define	MFF_MOUNTED	0x0001	/* Node is mounted */
-#define	MFF_MOUNTING	0x0002	/* Mount is in progress */
-#define	MFF_UNMOUNTING	0x0004	/* Unmount is in progress */
-#define	MFF_RESTART	0x0008	/* Restarted node */
-#define MFF_MKMNT	0x0010	/* Delete this node's am_mount */
-#define	MFF_ERROR	0x0020	/* This node failed to mount */
-#define	MFF_LOGDOWN	0x0040	/* Logged that this mount is down */
-#define	MFF_RSTKEEP	0x0080	/* Don't timeout this filesystem - restarted */
-#define	MFF_WANTTIMO	0x0100	/* Need a timeout call when not busy */
-#ifdef HAVE_AM_FS_NFSL
-# define MFF_NFSLINK	0x0200	/* nfsl type, and deemed a link */
-#endif /* HAVE_AM_FS_NFSL */
-
-/*
- * macros for struct am_node (map of auto-mount points).
- */
-#define	AMF_NOTIMEOUT	0x0001	/* This node never times out */
-#define	AMF_ROOT	0x0002	/* This is a root node */
-#ifdef HAVE_FS_AUTOFS
-# define AMF_AUTOFS	0x0004	/* this node is of type autofs */
-#endif /* HAVE_FS_AUTOFS */
+/* unmount-related flags (special handling of autofs, forced/lazy, etc.) */
+#define AMU_UMOUNT_FORCE        0x1
+#define AMU_UMOUNT_DETACH       0x2
+#define AMU_UMOUNT_AUTOFS       0x4
 
 /*
  * The following values can be tuned...
  */
 #define	ALLOWED_MOUNT_TIME	40	/* 40s for a mount */
-#define	AM_TTL			(5 * 60)	/* Default cache period */
-#define	AM_TTL_W		(2 * 60)	/* Default unmount interval */
-#define	AM_PINGER		30 /* NFS ping interval for live systems */
-#define	AMFS_AUTO_TIMEO		8 /* Default amfs_auto timeout - .8s */
-
-/*
- * default amfs_auto retrans - 1/10th seconds
- */
-#define	AMFS_AUTO_RETRANS	((ALLOWED_MOUNT_TIME*10+5*gopt.amfs_auto_timeo)/gopt.amfs_auto_timeo * 2)
 
 /*
  * RPC-related macros.
@@ -211,6 +160,7 @@ extern int umount_fs(char *fs_name, const char *mnttabname);
 #define	RPC_XID_PORTMAP		0
 #define	RPC_XID_MOUNTD		1
 #define	RPC_XID_NFSPING		2
+#define	RPC_XID_WEBNFS		3
 #define	RPC_XID_MASK		(0x0f)	/* 16 id's for now */
 #define	MK_RPC_XID(type_id, uniq)	((type_id) | ((uniq) << 4))
 
@@ -221,20 +171,6 @@ extern int umount_fs(char *fs_name, const char *mnttabname);
  */
 #define	AMD_COMPAT	5000000	/* 5.0 */
 
-/*
- * Error to return if remote host is not available.
- * Try, in order, "host down", "host unreachable", "invalid argument".
- */
-#ifdef EHOSTDOWN
-# define AM_ERRNO_HOST_DOWN	EHOSTDOWN
-# else /* not EHOSTDOWN */
-# ifdef EHOSTUNREACH
-#  define AM_ERRNO_HOST_DOWN	EHOSTUNREACH
-# else /* not EHOSTUNREACH */
-#  define AM_ERRNO_HOST_DOWN	EINVAL
-# endif /* not EHOSTUNREACH */
-#endif /* not EHOSTDOWN */
-
 
 /**************************************************************************/
 /*** STRUCTURES AND TYPEDEFS						***/
@@ -242,13 +178,8 @@ extern int umount_fs(char *fs_name, const char *mnttabname);
 
 /* some typedefs must come first */
 typedef char *amq_string;
-typedef struct mntfs mntfs;
-typedef struct am_opts am_opts;
-typedef struct am_ops am_ops;
-typedef struct am_node am_node;
 typedef struct _qelem qelem;
 typedef struct mntlist mntlist;
-typedef struct fserver fserver;
 
 /*
  * Linked list
@@ -278,121 +209,6 @@ typedef enum {
   Done
 } serv_state;
 
-/*
- * Options
- */
-struct am_opts {
-  char *fs_glob;		/* Smashed copy of global options */
-  char *fs_local;		/* Expanded copy of local options */
-  char *fs_mtab;		/* Mount table entry */
-  /* Other options ... */
-  char *opt_dev;
-  char *opt_delay;
-  char *opt_dir;
-  char *opt_fs;
-  char *opt_group;
-  char *opt_mount;
-  char *opt_opts;
-  char *opt_remopts;
-  char *opt_pref;
-  char *opt_autopref;
-  char *opt_cache;
-  char *opt_rfs;
-  char *opt_rhost;
-  char *opt_sublink;
-  char *opt_type;
-  char *opt_unmount;
-  char *opt_user;
-  char *opt_maptype;		/* map type: file, nis, hesiod, etc. */
-  char *opt_cachedir;		/* cache directory */
-  char *opt_addopts;		/* options to add to opt_opts */
-};
-
-/*
- * List of mounted filesystems
- */
-struct mntfs {
-  qelem mf_q;			/* List of mounted filesystems */
-  am_ops *mf_ops;		/* Operations on this mountpoint */
-  am_opts *mf_fo;		/* File opts */
-  char *mf_mount;		/* "/a/kiska/home/kiska" */
-  char *mf_info;		/* Mount info */
-  char *mf_auto;		/* Automount opts */
-  char *mf_mopts;		/* FS mount opts */
-  char *mf_remopts;		/* Remote FS mount opts */
-  fserver *mf_server;		/* File server */
-  int mf_flags;			/* Flags MFF_* */
-  int mf_error;			/* Error code from background mount */
-  int mf_refc;			/* Number of references to this node */
-  int mf_cid;			/* Callout id */
-  void (*mf_prfree) (voidp);	/* Free private space */
-  voidp mf_private;		/* Private - per-fs data */
-};
-
-/*
- * File Handle
- *
- * This is interpreted by indexing the exported array
- * by fhh_id.
- *
- * The whole structure is mapped onto a standard fhandle_t
- * when transmitted.
- */
-struct am_fh {
-  int fhh_pid;			/* process id */
-  int fhh_id;			/* map id */
-  int fhh_gen;			/* generation number */
-};
-
-/*
- * Multi-protocol NFS file handle
- */
-union am_nfs_handle {
-				/* placeholder for V4 file handle */
-#ifdef HAVE_FS_NFS3
-  struct mountres3	v3;	/* NFS version 3 handle */
-#endif /* HAVE_FS_NFS3 */
-  struct fhstatus	v2;	/* NFS version 2 handle */
-};
-typedef union am_nfs_handle am_nfs_handle_t;
-
-/*
- * automounter vfs/vnode operations.
- */
-typedef char *(*vfs_match) (am_opts *);
-typedef int (*vfs_init) (mntfs *);
-typedef int (*vmount_fs) (am_node *);
-typedef int (*vfmount_fs) (mntfs *);
-typedef int (*vumount_fs) (am_node *);
-typedef int (*vfumount_fs) (mntfs *);
-typedef am_node *(*vlookuppn) (am_node *, char *, int *, int);
-typedef int (*vreaddir) (am_node *, nfscookie, nfsdirlist *, nfsentry *, int);
-typedef am_node *(*vreadlink) (am_node *, int *);
-typedef void (*vmounted) (mntfs *);
-typedef void (*vumounted) (am_node *);
-typedef fserver *(*vffserver) (mntfs *);
-
-struct am_ops {
-  char		*fs_type;	/* type of filesystems "nfsx" */
-  vfs_match	fs_match;	/* fxn: match */
-  vfs_init	fs_init;	/* fxn: initialization */
-  vmount_fs	mount_fs;	/* fxn: mount vnode */
-  vfmount_fs	fmount_fs;	/* fxn: mount VFS */
-  vumount_fs	umount_fs;	/* fxn: unmount vnode */
-  vfumount_fs	fumount_fs;	/* fxn: unmount VFS */
-  vlookuppn	lookuppn;	/* fxn: lookup path-name */
-  vreaddir	readdir;	/* fxn: read directory */
-  vreadlink	readlink;	/* fxn: read link */
-  vmounted	mounted;	/* fxn: after-mount extra actions */
-  vumounted	umounted;	/* fxn: after-umount extra actions */
-  vffserver	ffserver;	/* fxn: find a file server */
-  int		fs_flags;	/* filesystem flags FS_* */
-};
-
-typedef int (*task_fun) (voidp);
-typedef void (*cb_fun) (int, int, voidp);
-typedef void (*fwd_fun) P((voidp, int, struct sockaddr_in *,
-			   struct sockaddr_in *, voidp, int));
 
 /*
  * List of mount table entries
@@ -407,76 +223,6 @@ struct mntlist {
  */
 typedef struct mnt_map mnt_map;
 
-/*
- * Per-mountpoint statistics
- */
-struct am_stats {
-  time_t s_mtime;		/* Mount time */
-  u_short s_uid;		/* Uid of mounter */
-  int s_getattr;		/* Count of getattrs */
-  int s_lookup;			/* Count of lookups */
-  int s_readdir;		/* Count of readdirs */
-  int s_readlink;		/* Count of readlinks */
-  int s_statfs;			/* Count of statfs */
-};
-typedef struct am_stats am_stats;
-
-/*
- * System statistics
- */
-struct amd_stats {
-  int d_drops;			/* Dropped requests */
-  int d_stale;			/* Stale NFS handles */
-  int d_mok;			/* Successful mounts */
-  int d_merr;			/* Failed mounts */
-  int d_uerr;			/* Failed unmounts */
-};
-extern struct amd_stats amd_stats;
-
-/*
- * List of fileservers
- */
-struct fserver {
-  qelem fs_q;			/* List of fileservers */
-  int fs_refc;			/* Number of references to this node */
-  char *fs_host;		/* Normalized hostname of server */
-  struct sockaddr_in *fs_ip;	/* Network address of server */
-  int fs_cid;			/* Callout id */
-  int fs_pinger;		/* Ping (keepalive) interval */
-  int fs_flags;			/* Flags */
-  char *fs_type;		/* File server type */
-  u_long fs_version;		/* NFS version of server (2, 3, etc.)*/
-  char *fs_proto;		/* NFS protocol of server (tcp, udp, etc.) */
-  voidp fs_private;		/* Private data */
-  void (*fs_prfree) (voidp);	/* Free private data */
-};
-
-/*
- * Map of auto-mount points.
- */
-struct am_node {
-  int am_mapno;		/* Map number */
-  mntfs *am_mnt;	/* Mounted filesystem */
-  char *am_name;	/* "kiska": name of this node */
-  char *am_path;	/* "/home/kiska": path of this node's mount point */
-  char *am_link;	/* "/a/kiska/home/kiska/this/that": link to sub-dir */
-  am_node *am_parent;	/* Parent of this node */
-  am_node *am_ysib;	/* Younger sibling of this node */
-  am_node *am_osib;	/* Older sibling of this node */
-  am_node *am_child;	/* First child of this node */
-  nfsattrstat am_attr;	/* File attributes */
-#define am_fattr	am_attr.ns_u.ns_attr_u
-  int am_flags;		/* Boolean flags AMF_* */
-  int am_error;		/* Specific mount error */
-  time_t am_ttl;	/* Time to live */
-  int am_timeo_w;	/* Wait interval */
-  int am_timeo;		/* Timeout interval */
-  u_int am_gen;		/* Generation number */
-  char *am_pref;	/* Mount info prefix */
-  am_stats am_stats;	/* Statistics gathering */
-  SVCXPRT *am_transp;	/* Info for quick reply */
-};
-
 
 /**************************************************************************/
 /*** EXTERNALS								***/
@@ -490,8 +236,6 @@ extern char *cpu;		/* "CPU type" */
 extern char *endian;		/* "big" */
 extern char *hostdomain;	/* "southseas.nz" */
 extern char copyright[];	/* Copyright info */
-extern char hostd[];		/* "kiska.southseas.nz" */
-extern char pid_fsname[];	/* kiska.southseas.nz:(pid%d) */
 extern char version[];		/* Version info */
 
 /*
@@ -499,42 +243,26 @@ extern char version[];		/* Version info */
  */
 extern AUTH *nfs_auth;		/* Dummy authorization for remote servers */
 extern FILE *logfp;		/* Log file */
-extern am_node **exported_ap;	/* List of nodes */
-extern am_node *root_node;	/* Node for "root" */
+extern SVCXPRT *nfsxprt;
 extern char *PrimNetName;	/* Name of primary connected network */
 extern char *PrimNetNum;	/* Name of primary connected network */
 extern char *SubsNetName;	/* Name of subsidiary connected network */
 extern char *SubsNetNum;	/* Name of subsidiary connected network */
 
-#if 0
-extern char *progname;		/* "amd" */
-#endif
-extern void am_set_progname(char *pn);	/* "amd" */
-extern const char * am_get_progname(void); /* "amd" */
+extern void am_set_progname(char *pn); /* "amd" */
+extern const char *am_get_progname(void); /* "amd" */
 extern void am_set_hostname(char *hn);
-extern const char * am_get_hostname(void);
+extern const char *am_get_hostname(void);
 extern pid_t am_set_mypid(void);
 extern pid_t am_mypid;
 
-#if 0
-extern char hostname[];		/* "kiska" */
-extern pid_t mypid;		/* Current process id */
-#endif
-
-extern int first_free_map;	/* First free node */
 extern int foreground;		/* Foreground process */
-extern int immediate_abort;	/* Should close-down unmounts be retried */
-extern int last_used_map;	/* Last map being used for mounts */
 extern int orig_umask;		/* umask() on startup */
-extern int task_notify_todo;	/* Task notifier needs running */
 extern int xlog_level;		/* Logging level */
 extern int xlog_level_init;
 extern serv_state amd_state;	/* Should we go now */
 extern struct in_addr myipaddr;	/* (An) IP address of this host */
 extern struct opt_tab xlog_opt[];
-extern time_t clock_valid;	/* Clock needs recalculating */
-extern time_t do_mapc_reload;	/* Flush & reload mount map cache */
-extern time_t next_softclock;	/* Time to call softclock() */
 extern u_short nfs_port;	/* Our NFS service port */
 
 /*
@@ -542,132 +270,92 @@ extern u_short nfs_port;	/* Our NFS service port */
  */
 extern CLIENT *get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, int *sock, u_long mnt_version);
 extern RETSIGTYPE sigchld(int);
-extern SVCXPRT *nfsxprt;
-extern am_node *efs_lookuppn(am_node *, char *, int *, int);
-extern am_node *exported_ap_alloc(void);
-extern am_node *fh_to_mp(am_nfs_fh *);
-extern am_node *fh_to_mp3(am_nfs_fh *, int *, int);
-extern am_node *find_mf(mntfs *);
-extern am_node *next_map(int *);
-extern am_node *root_ap(char *, int);
-extern am_ops *ops_match(am_opts *, char *, char *, char *, char *, char *);
 extern bool_t xdr_amq_string(XDR *xdrs, amq_string *objp);
 extern bool_t xdr_dirpath(XDR *xdrs, dirpath *objp);
 extern char **strsplit(char *, int, int);
-extern char *expand_key(char *);
+extern char *expand_selectors(char *);
 extern char *get_version_string(void);
-extern char *inet_dquad(char *, u_long);
+extern char *inet_dquad(char *, size_t, u_long);
 extern char *print_wires(void);
 extern char *str3cat(char *, char *, char *, char *);
 extern char *strealloc(char *, char *);
 extern char *strip_selectors(char *, char *);
 extern char *strnsave(const char *, int);
-extern fserver *dup_srvr(fserver *);
 extern int amu_close(int fd);
-extern int background(void);
 extern int bind_resv_port(int, u_short *);
 extern int cmdoption(char *, struct opt_tab *, int *);
 extern int compute_automounter_mount_flags(mntent_t *);
 extern int compute_mount_flags(mntent_t *);
-extern int efs_readdir(am_node *, nfscookie, nfsdirlist *, nfsentry *, int);
-extern int eval_fs_opts(am_opts *, char *, char *, char *, char *, char *);
-extern int fwd_init(void);
-extern int fwd_packet(int, voidp, int, struct sockaddr_in *, struct sockaddr_in *, voidp, fwd_fun);
 extern int get_amd_program_number(void);
+extern int getcreds(struct svc_req *, uid_t *, gid_t *, SVCXPRT *);
 extern int hasmntval(mntent_t *, char *);
+extern unsigned int hasmntvalerr(mntent_t *, char *, int *);
+extern char *hasmntstr(mntent_t *, char *);
+extern char *hasmnteq(mntent_t *, char *);
+extern char *haseq(char *);
 extern int is_network_member(const char *net);
+extern int is_interface_local(u_long);
 extern int islocalnet(u_long);
-extern int make_nfs_auth(void);
 extern int make_rpc_packet(char *, int, u_long, struct rpc_msg *, voidp, XDRPROC_T_TYPE, AUTH *);
-extern int mapc_keyiter(mnt_map *, void(*)(char *, voidp), voidp);
-extern int mapc_search(mnt_map *, char *, char **);
-extern int mapc_type_exists(const char *type);
 extern int mkdirs(char *, int);
-extern int mount_auto_node(char *, voidp);
-extern int mount_automounter(int);
-extern int mount_exported(void);
-extern int mount_fs(mntent_t *, int, caddr_t, int, MTYPE_TYPE, u_long, const char *, const char *);
-extern int mount_node(am_node *);
-extern int nfs_srvr_port(fserver *, u_short *, voidp);
+extern int mount_fs(mntent_t *, int, caddr_t, int, MTYPE_TYPE, u_long, const char *, const char *, int);
+extern void nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp);
 extern int pickup_rpc_reply(voidp, int, voidp, XDRPROC_T_TYPE);
-extern int root_keyiter(void(*)(char *, voidp), voidp);
-extern int softclock(void);
 extern int switch_option(char *);
-extern int switch_to_logfile(char *logfile, int orig_umask);
-extern int timeout(u_int, void (*fn)(voidp), voidp);
-extern int valid_key(char *);
-extern mnt_map *mapc_find(char *, char *, const char *);
-extern mntfs *dup_mntfs(mntfs *);
-extern mntfs *find_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
-extern mntfs *new_mntfs(void);
-extern mntfs *realloc_mntfs(mntfs *, am_ops *, am_opts *, char *, char *, char *, char *, char *);
+extern int switch_to_logfile(char *logfile, int orig_umask, int truncate_log);
 extern mntlist *read_mtab(char *, const char *);
+#ifndef HAVE_TRANSPORT_TYPE_TLI
 extern struct sockaddr_in *amu_svc_getcaller(SVCXPRT *xprt);
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
 extern time_t time(time_t *);
-extern void am_mounted(am_node *);
-extern void am_unmounted(am_node *);
-extern void amq_program_1(struct svc_req *rqstp, SVCXPRT * transp);
-extern void amu_get_myaddress(struct in_addr *iap);
+extern void amu_get_myaddress(struct in_addr *iap, const char *preferred_localhost);
 extern void amu_release_controlling_tty(void);
 extern void compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp);
-extern void deslashify(char *);
 extern void discard_mntlist(mntlist *mp);
-extern void do_task_notify(void);
-extern void flush_mntfs(void);
-extern void flush_nfs_fhandle_cache(fserver *);
-extern void forcibly_timeout_mp(am_node *);
-extern void free_map(am_node *);
-extern void free_mntfs(voidp);
 extern void free_mntlist(mntlist *);
-extern void free_opts(am_opts *);
-extern void free_srvr(fserver *);
-extern void fwd_reply(void);
-extern void get_args(int argc, char *argv[]);
 extern void getwire(char **name1, char **number1);
 extern void going_down(int);
-extern void host_normalize(char **);
-extern void init_map(am_node *, char *);
-extern void ins_que(qelem *, qelem *);
-extern void insert_am(am_node *, am_node *);
-extern void make_root_node(void);
-extern void map_flush_srvr(fserver *);
-extern void mapc_add_kv(mnt_map *, char *, char *);
-extern void mapc_free(voidp);
-extern void mapc_reload(void);
-extern void mapc_showtypes(char *buf);
-extern void mk_fattr(am_node *, nfsftype);
 extern void mnt_free(mntent_t *);
-extern void mp_to_fh(am_node *, am_nfs_fh *);
-extern void new_ttl(am_node *);
-extern void nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp);
-extern void normalize_slash(char *);
-extern void ops_showamfstypes(char *buf);
-extern void ops_showfstypes(char *outbuf);
-extern void plog(int, char *,...)
+extern void plog(int, const char *,...)
      __attribute__ ((__format__ (__printf__, 2, 3)));
-extern void rem_que(qelem *);
-extern void reschedule_timeout_mp(void);
-extern void restart(void);
 extern void rmdirs(char *);
 extern void rpc_msg_init(struct rpc_msg *, u_long, u_long, u_long);
-extern void run_task(task_fun, voidp, cb_fun, voidp);
-extern void sched_task(cb_fun, voidp, voidp);
 extern void set_amd_program_number(int program);
 extern void show_opts(int ch, struct opt_tab *);
-extern void show_rcs_info(const char *, char *);
-extern void srvrlog(fserver *, char *);
-extern void timeout_mp(voidp);
-extern void umount_exported(void);
 extern void unregister_amq(void);
-extern void untimeout(int);
-extern void wakeup(voidp);
-extern void wakeup_srvr(fserver *);
-extern void wakeup_task(int, int, voidp);
 extern voidp xmalloc(int);
 extern voidp xrealloc(voidp, int);
 extern voidp xzalloc(int);
+extern int check_pmap_up(char *host, struct sockaddr_in* sin);
 extern u_long get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto);
+extern long get_server_pid(void);
+extern void setup_sighandler(int signum, void (*handler)(int));
+extern time_t clocktime(nfstime *nt);
+
+#if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS))
+# ifdef HAVE_C99_VARARGS_MACROS
+#define xsnprintf(str,size,fmt,...)	_xsnprintf(__FILE__,__LINE__,(str),(size),(fmt),__VA_ARGS__)
+# endif /* HAVE_C99_VARARGS_MACROS */
+# ifdef HAVE_GCC_VARARGS_MACROS
+#define xsnprintf(str,size,fmt,args...)		_xsnprintf(__FILE__,__LINE__,(str),(size),(fmt),args)
+# endif /* HAVE_GCC_VARARGS_MACROS */
+extern int _xsnprintf(const char *filename, int lineno, char *str, size_t size, const char *format, ...);
+#define xvsnprintf(str,size,fmt,ap)	_xvsnprintf(__FILE__,__LINE__,(str),(size),(fmt),(ap))
+extern int _xvsnprintf(const char *filename, int lineno, char *str, size_t size, const char *format, va_list ap);
+#else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
+extern int xsnprintf(char *str, size_t size, const char *format, ...);
+extern int xvsnprintf(char *str, size_t size, const char *format, va_list ap);
+#endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
 
+#ifdef DEBUG
+extern void _xstrlcat(const char *filename, int lineno, char *dst, const char *src, size_t len);
+# define xstrlcat(d,s,l)	_xstrlcat(__FILE__,__LINE__,(d),(s),(l))
+extern void _xstrlcpy(const char *filename, int lineno, char *dst, const char *src, size_t len);
+# define xstrlcpy(d,s,l)	_xstrlcpy(__FILE__,__LINE__,(d),(s),(l))
+#else /* not DEBUG */
+extern void xstrlcat(char *dst, const char *src, size_t len);
+extern void xstrlcpy(char *dst, const char *src, size_t len);
+#endif /* not DEBUG */
 
 #ifdef MOUNT_TABLE_ON_FILE
 extern void rewrite_mtab(mntlist *, const char *);
@@ -679,81 +367,28 @@ extern void write_mntent(mntent_t *, const char *);
 extern int syslogging;
 #endif /* defined(HAVE_SYSLOG_H) || defined(HAVE_SYS_SYSLOG_H) */
 
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-
 extern void compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct netconfig *nfsncp, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name);
-extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp);
+extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp, u_short preferred_amq_port);
 extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp));
+extern int amu_svc_register(SVCXPRT *, u_long, u_long, void (*)(struct svc_req *, SVCXPRT *), u_long, struct netconfig *);
+
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+
 extern int get_knetconfig(struct knetconfig **kncpp, struct netconfig *in_ncp, char *nc_protoname);
 extern struct netconfig *nfsncp;
 extern void free_knetconfig(struct knetconfig *kncp);
 
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
+#endif /* HAVE_TRANSPORT_TYPE_TLI */
 
-extern void compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name);
-extern enum clnt_stat pmap_ping(struct sockaddr_in *address);
-extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp);
-extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp));
+#ifdef HAVE_FS_AUTOFS
+extern int register_autofs_service(char *autofs_conftype, void (*autofs_dispatch)(struct svc_req *rqstp, SVCXPRT *xprt));
+extern int unregister_autofs_service(char *autofs_conftype);
+#endif /* HAVE_FS_AUTOFS */
 
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
 
-#ifndef HAVE_FIELD_STRUCT_FHSTATUS_FHS_FH
+#ifndef HAVE_STRUCT_FHSTATUS_FHS_FH
 # define fhs_fh  fhstatus_u.fhs_fhandle
-#endif /* not HAVE_FIELD_STRUCT_FHSTATUS_FHS_FH */
-
-
-/**************************************************************************/
-/*** Generic file-system types, implemented as part of the native O/S.	***/
-/**************************************************************************/
-
-/*
- * Loopback File System
- * Many systems can't support this, and in any case most of the
- * functionality is available with Symlink FS.
- */
-#ifdef HAVE_FS_LOFS
-extern am_ops lofs_ops;
-#endif /* HAVE_FS_LOFS */
-
-/*
- * CD-ROM File System (CD-ROM)
- * (HSFS: High Sierra F/S on some machines)
- * Many systems can't support this, and in any case most of the
- * functionality is available with program FS.
- */
-#ifdef HAVE_FS_CDFS
-extern am_ops cdfs_ops;
-#endif /* HAVE_FS_CDFS */
-
-/*
- * PC File System (MS-DOS)
- * Many systems can't support this, and in any case most of the
- * functionality is available with program FS.
- */
-#ifdef HAVE_FS_PCFS
-extern am_ops pcfs_ops;
-#endif /* HAVE_FS_PCFS */
-
-/*
- * Caching File System (Solaris)
- */
-#ifdef HAVE_FS_CACHEFS
-extern am_ops cachefs_ops;
-#endif /* HAVE_FS_CACHEFS */
-
-/*
- * Network File System
- * Good, slow, NFS V.2.
- */
-#ifdef HAVE_FS_NFS
-extern am_ops nfs_ops;		/* NFS */
-extern fserver *find_nfs_srvr (mntfs *);
-extern int nfs_fmount(mntfs *mf);
-extern int nfs_fumount(mntfs *mf);
-extern int nfs_init(mntfs *mf);
-extern qelem nfs_srvr_list;
-extern void nfs_umounted(am_node *mp);
-#endif /* HAVE_FS_NFS */
+#endif /* not HAVE_STRUCT_FHSTATUS_FHS_FH */
 
 
 /*
@@ -766,131 +401,6 @@ extern void nfs_umounted(am_node *mp);
 # endif /* not NFS_VERSION3 */
 #endif /* HAVE_FS_NFS3 */
 
-/*
- * Un*x File System
- * Normal local disk file system.
- */
-#ifdef HAVE_FS_UFS
-extern am_ops ufs_ops;		/* Un*x file system */
-#endif /* HAVE_FS_UFS */
-
-
-/**************************************************************************/
-/*** Automounter file-system types, implemented by amd.			***/
-/**************************************************************************/
-
-/*
- * Automount File System
- */
-#ifdef HAVE_AM_FS_AUTO
-extern am_ops amfs_auto_ops;	/* Automount file system (this!) */
-extern am_ops amfs_toplvl_ops;	/* Top-level automount file system */
-extern am_ops amfs_root_ops;	/* Root file system */
-extern qelem amfs_auto_srvr_list;
-extern am_node *amfs_auto_lookuppn(am_node *mp, char *fname, int *error_return, int op);
-extern am_node *next_nonerror_node(am_node *xp);
-extern char *amfs_auto_match(am_opts *fo);
-extern fserver *find_amfs_auto_srvr(mntfs *);
-extern int amfs_auto_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count);
-extern int amfs_auto_umount(am_node *mp);
-extern int amfs_auto_fmount(am_node *mp);
-extern int amfs_auto_fumount(am_node *mp);
-#endif /* HAVE_AM_FS_AUTO */
-
-/*
- * Toplvl Automount File System
- */
-#ifdef HAVE_AM_FS_TOPLVL
-extern am_ops amfs_toplvl_ops;	/* Toplvl Automount file system */
-extern int amfs_toplvl_mount(am_node *mp);
-extern int amfs_toplvl_umount(am_node *mp);
-extern void amfs_toplvl_mounted(mntfs *mf);
-#endif /* HAVE_AM_FS_TOPLVL */
-
-/*
- * Direct Automount File System
- */
-#ifdef HAVE_AM_FS_DIRECT
-extern am_ops amfs_direct_ops;	/* Direct Automount file system (this too) */
-#endif /* HAVE_AM_FS_DIRECT */
-
-/*
- * Error File System
- */
-#ifdef HAVE_AM_FS_ERROR
-extern am_ops amfs_error_ops;	/* Error file system */
-extern am_node *amfs_error_lookuppn(am_node *mp, char *fname, int *error_return, int op);
-extern int amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count);
-#endif /* HAVE_AM_FS_ERROR */
-
-/*
- * Inheritance File System
- */
-#ifdef HAVE_AM_FS_INHERIT
-extern am_ops amfs_inherit_ops;	/* Inheritance file system */
-#endif /* HAVE_AM_FS_INHERIT */
-
-/*
- * NFS mounts with local existence check.
- */
-#ifdef HAVE_AM_FS_NFSL
-extern am_ops amfs_nfsl_ops;	/* NFSL */
-#endif /* HAVE_AM_FS_NFSL */
-
-/*
- * Multi-nfs mounts.
- */
-#ifdef HAVE_AM_FS_NFSX
-extern am_ops amfs_nfsx_ops;	/* NFSX */
-#endif /* HAVE_AM_FS_NFSX */
-
-/*
- * NFS host - a whole tree.
- */
-#ifdef HAVE_AM_FS_HOST
-extern am_ops amfs_host_ops;	/* NFS host */
-#endif /* HAVE_AM_FS_HOST */
-
-/*
- * Program File System
- * This is useful for things like RVD.
- */
-#ifdef HAVE_AM_FS_PROGRAM
-extern am_ops amfs_program_ops;	/* Program File System */
-#endif /* HAVE_AM_FS_PROGRAM */
-
-/*
- * Symbolic-link file system.
- * A "filesystem" which is just a symbol link.
- */
-#ifdef HAVE_AM_FS_LINK
-extern am_ops amfs_link_ops;	/* Symlink FS */
-extern int amfs_link_fmount(mntfs *mf);
-#endif /* HAVE_AM_FS_LINK */
-
-/*
- * Symbolic-link file system, which also checks that the target of
- * the symlink exists.
- * A "filesystem" which is just a symbol link.
- */
-#ifdef HAVE_AM_FS_LINKX
-extern am_ops amfs_linkx_ops;	/* Symlink FS with existence check */
-#endif /* HAVE_AM_FS_LINKX */
-
-/*
- * Union file system
- */
-#ifdef HAVE_AM_FS_UNION
-extern am_ops amfs_union_ops;	/* Union FS */
-#endif /* HAVE_AM_FS_UNION */
-
-/*
- * Autofs file system
- */
-#ifdef HAVE_FS_AUTOFS
-extern am_ops autofs_ops;	/* (Sun) Autofs FS */
-#endif /* HAVE_FS_AUTOFS */
-
 
 /**************************************************************************/
 /*** DEBUGGING								***/
@@ -899,39 +409,39 @@ extern am_ops autofs_ops;	/* (Sun) Autofs FS */
 /*
  * DEBUGGING:
  */
+
 #ifdef DEBUG
 
-# define	D_ALL		(~0)
-# define	D_DAEMON	0x0001	/* Enter daemon mode */
+# define	D_ALL		(~(D_MTAB|D_HRTIME|D_XDRTRACE|D_DAEMON|D_FORK|D_AMQ))
+# define	D_DAEMON	0x0001	/* Don't enter daemon mode */
 # define	D_TRACE		0x0002	/* Do protocol trace */
 # define	D_FULL		0x0004	/* Do full trace */
 # define	D_MTAB		0x0008	/* Use local mtab */
-# define	D_AMQ		0x0010	/* Register amq program */
+# define	D_AMQ		0x0010	/* Don't register amq program */
 # define	D_STR		0x0020	/* Debug string munging */
-#  ifdef DEBUG_MEM
-# define	D_MEM		0x0040	/* Trace memory allocations */
-#  endif /* DEBUG_MEM */
-# define	D_FORK		0x0080	/* Fork server */
+# ifdef DEBUG_MEM
+#  define	D_MEM		0x0040	/* Trace memory allocations */
+# else /* not DEBUG_MEM */
+#  define	D_MEM		0x0000	/* Dummy */
+# endif /* not DEBUG_MEM */
+# define	D_FORK		0x0080	/* Don't fork server */
 		/* info service specific debugging (hesiod, nis, etc) */
 # define	D_INFO		0x0100
+# define	D_HRTIME	0x0200	/* Print high resolution time stamps */
+# define	D_XDRTRACE	0x0400	/* Trace xdr routines */
+# define	D_READDIR	0x0800	/* Show browsable_dir progress */
 
 /*
- * Normally, don't enter daemon mode, and don't register amq
+ * Test mode is test mode: don't daemonize, don't register amq, don't fork,
+ * don't touch system mtab, etc.
  */
-#  ifdef DEBUG_MEM
-# define	D_TEST	(~(D_DAEMON|D_MEM|D_STR))
-#  else /* not DEBUG_MEM */
-# define	D_TEST	(~(D_DAEMON|D_STR))
-#  endif /* not DEBUG_MEM */
+# define	D_TEST	(~(D_MEM|D_STR|D_XDRTRACE))
 
-# define	amuDebug(x)	if (debug_flags & (x))
-# define	dlog		amuDebug(D_FULL) dplog
-# define	amuDebugNo(x)	if (!(debug_flags & (x)))
+# define	amuDebug(x)	(debug_flags & (x))
+# define	dlog		if (amuDebug(D_FULL)) dplog
 
-/* debugging mount-table file to use */
-# ifndef DEBUG_MNTTAB
-#  define	DEBUG_MNTTAB	"./mnttab"
-# endif /* not DEBUG_MNTTAB */
+/* my favorite debugging tool -Erez */
+#define EZKDBG plog(XLOG_INFO,"EZK:%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__)
 
 # ifdef DEBUG_MEM
 /*
@@ -951,22 +461,34 @@ extern void malloc_verify(void);
 
 /* functions that depend solely on debugging */
 extern void print_nfs_args(const nfs_args_t *nap, u_long nfs_version);
+extern int debug_option (char *opt);
+extern void dplog(const char *fmt, ...)
+     __attribute__ ((__format__ (__printf__, 1, 2)));
 
 #else /* not DEBUG */
 
 /*
- * if not debugging, then simple perform free, and don't bother
- * resetting the pointer.
+ * If not debugging, then also reset the pointer.
+ * It's safer -- and besides, free() should do that anyway.
  */
-#  define	XFREE(x) free(x)
+#  define	XFREE(x) do { free((voidp)x); x = NULL;} while (0)
+
+#define		amuDebug(x)	(0)
+
+#ifdef __GNUC__
+#define		dlog(fmt...)
+#else  /* not __GNUC__ */
+/* this define means that we CCP leaves code behind the (list,of,args)  */
+#define		dlog
+#endif /* not __GNUC__ */
+
+#define		print_nfs_args(nap, nfs_version)
+#define		debug_option(x)	(1)
 
 #endif /* not DEBUG */
 
 extern int debug_flags;		/* Debug options */
-extern int debug_option (char *opt);
 extern struct opt_tab dbg_opt[];
-extern void dplog(char *fmt, ...)
-     __attribute__ ((__format__ (__printf__, 1, 2)));
 
 /**************************************************************************/
 /*** MISC (stuff left to autoconfiscate)				***/
diff --git a/contrib/amd/include/am_xdr_func.h b/contrib/amd/include/am_xdr_func.h
index b50e008..c415918 100644
--- a/contrib/amd/include/am_xdr_func.h
+++ b/contrib/amd/include/am_xdr_func.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,12 +36,147 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: am_xdr_func.h,v 1.2 1999/01/10 21:54:35 ezk Exp $
+ * File: am-utils/include/am_xdr_func.h
  *
  */
 
+#ifdef HAVE_FS_NFS3
+
+#define AM_FHSIZE3 64		/* size in bytes of a file handle (v3) */
+#define	AM_MOUNTVERS3 ((unsigned long)(3))
+
+/* NFSv3 handle */
+struct am_nfs_fh3 {
+  u_int am_fh3_length;
+  char am_fh3_data[AM_FHSIZE3];
+};
+typedef struct am_nfs_fh3 am_nfs_fh3;
+
+#define AM_NFSPROC3_LOOKUP ((u_long) 3)
+enum am_nfsstat3 {
+	AM_NFS3_OK = 0,
+	AM_NFS3ERR_PERM = 1,
+	AM_NFS3ERR_NOENT = 2,
+	AM_NFS3ERR_IO = 5,
+	AM_NFS3ERR_NXIO = 6,
+	AM_NFS3ERR_ACCES = 13,
+	AM_NFS3ERR_EXIST = 17,
+	AM_NFS3ERR_XDEV = 18,
+	AM_NFS3ERR_NODEV = 19,
+	AM_NFS3ERR_NOTDIR = 20,
+	AM_NFS3ERR_ISDIR = 21,
+	AM_NFS3ERR_INVAL = 22,
+	AM_NFS3ERR_FBIG = 27,
+	AM_NFS3ERR_NOSPC = 28,
+	AM_NFS3ERR_ROFS = 30,
+	AM_NFS3ERR_MLINK = 31,
+	AM_NFS3ERR_NAMETOOLONG = 63,
+	AM_NFS3ERR_NOTEMPTY = 66,
+	AM_NFS3ERR_DQUOT = 69,
+	AM_NFS3ERR_STALE = 70,
+	AM_NFS3ERR_REMOTE = 71,
+	AM_NFS3ERR_BADHANDLE = 10001,
+	AM_NFS3ERR_NOT_SYNC = 10002,
+	AM_NFS3ERR_BAD_COOKIE = 10003,
+	AM_NFS3ERR_NOTSUPP = 10004,
+	AM_NFS3ERR_TOOSMALL = 10005,
+	AM_NFS3ERR_SERVERFAULT = 10006,
+	AM_NFS3ERR_BADTYPE = 10007,
+	AM_NFS3ERR_JUKEBOX = 10008
+};
+typedef enum am_nfsstat3 am_nfsstat3;
+
+typedef struct {
+  u_int fhandle3_len;
+  char *fhandle3_val;
+} am_fhandle3;
+
+enum am_mountstat3 {
+       AM_MNT3_OK = 0,
+       AM_MNT3ERR_PERM = 1,
+       AM_MNT3ERR_NOENT = 2,
+       AM_MNT3ERR_IO = 5,
+       AM_MNT3ERR_ACCES = 13,
+       AM_MNT3ERR_NOTDIR = 20,
+       AM_MNT3ERR_INVAL = 22,
+       AM_MNT3ERR_NAMETOOLONG = 63,
+       AM_MNT3ERR_NOTSUPP = 10004,
+       AM_MNT3ERR_SERVERFAULT = 10006
+};
+typedef enum am_mountstat3 am_mountstat3;
+
+struct am_mountres3_ok {
+       am_fhandle3 fhandle;
+       struct {
+               u_int auth_flavors_len;
+               int *auth_flavors_val;
+       } auth_flavors;
+};
+typedef struct am_mountres3_ok am_mountres3_ok;
+
+struct am_mountres3 {
+       am_mountstat3 fhs_status;
+       union {
+               am_mountres3_ok mountinfo;
+       } mountres3_u;
+};
+typedef struct am_mountres3 am_mountres3;
+
+typedef char *am_filename3;
+
+struct am_diropargs3 {
+	am_nfs_fh3 dir;
+	am_filename3 name;
+};
+typedef struct am_diropargs3 am_diropargs3;
+
+struct am_LOOKUP3args {
+	am_diropargs3 what;
+};
+typedef struct am_LOOKUP3args am_LOOKUP3args;
+
+struct am_LOOKUP3resok {
+	am_nfs_fh3 object;
+#if 0
+	post_op_attr obj_attributes;
+	post_op_attr dir_attributes;
+#endif
+};
+typedef struct am_LOOKUP3resok am_LOOKUP3resok;
+
+struct am_LOOKUP3resfail {
+#if 0
+	post_op_attr dir_attributes;
+#else
+	char dummy;		/* cannot have an empty declaration */
+#endif
+};
+typedef struct am_LOOKUP3resfail am_LOOKUP3resfail;
+
+struct am_LOOKUP3res {
+	am_nfsstat3 status;
+	union {
+		am_LOOKUP3resok ok;
+		am_LOOKUP3resfail fail;
+	} res_u;
+};
+typedef struct am_LOOKUP3res am_LOOKUP3res;
+#endif /* HAVE_FS_NFS3 */
+
+/*
+ * Multi-protocol NFS file handle
+ */
+union am_nfs_handle {
+				/* placeholder for V4 file handle */
+#ifdef HAVE_FS_NFS3
+  am_nfs_fh3		v3;	/* NFS version 3 handle */
+#endif /* HAVE_FS_NFS3 */
+  am_nfs_fh		v2;	/* NFS version 2 handle */
+};
+typedef union am_nfs_handle am_nfs_handle_t;
+
+
 /*
  * Definitions of all possible xdr functions that are otherwise
  * not defined elsewhere.
@@ -99,7 +234,7 @@ bool_t xdr_ftype(XDR *xdrs, nfsftype *objp);
 bool_t xdr_groupnode(XDR *xdrs, groupnode *objp);
 #endif /* not HAVE_XDR_GROUPNODE */
 #ifndef HAVE_XDR_GROUPS
-bool_t xdr_groups(XDR *xdrs, groups objp);
+bool_t xdr_groups(XDR *xdrs, groups *objp);
 #endif /* not HAVE_XDR_GROUPS */
 #ifndef HAVE_XDR_LINKARGS
 bool_t xdr_linkargs(XDR *xdrs, nfslinkargs *objp);
@@ -110,17 +245,6 @@ bool_t xdr_mountbody(XDR *xdrs, mountbody *objp);
 #ifndef HAVE_XDR_MOUNTLIST
 bool_t xdr_mountlist(XDR *xdrs, mountlist *objp);
 #endif /* not HAVE_XDR_MOUNTLIST */
-
-/*
- * NFS3 XDR FUNCTIONS:
- */
-#if defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3)
-bool_t xdr_fhandle3(XDR *xdrs, fhandle3 *objp);
-bool_t xdr_mountstat3(XDR *xdrs, mountstat3 *objp);
-bool_t xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp);
-bool_t xdr_mountres3(XDR *xdrs, mountres3 *objp);
-#endif /* defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3) */
-
 #ifndef HAVE_XDR_NAME
 bool_t xdr_name(XDR *xdrs, name *objp);
 #endif /* not HAVE_XDR_NAME */
@@ -183,21 +307,21 @@ bool_t xdr_writeargs(XDR *xdrs, nfswriteargs *objp);
 #endif /* not HAVE_XDR_WRITEARGS */
 
 /*
- * AUTOFS XDR FUNCTIONS:
+ * NFS3 XDR FUNCTIONS:
  */
-#ifdef HAVE_FS_AUTOFS
-# ifndef HAVE_XDR_MNTREQUEST
-bool_t xdr_mntrequest(XDR *xdrs, mntrequest *objp);
-# endif /* not HAVE_XDR_MNTREQUEST */
-# ifndef HAVE_XDR_MNTRES
-bool_t xdr_mntres(XDR *xdrs, mntres *objp);
-# endif /* not HAVE_XDR_MNTRES */
-# ifndef HAVE_XDR_UMNTREQUEST
-bool_t xdr_umntrequest(XDR *xdrs, umntrequest *objp);
-# endif /* not HAVE_XDR_UMNTREQUEST */
-# ifndef HAVE_XDR_UMNTRES
-bool_t xdr_umntres(XDR *xdrs, umntres *objp);
-# endif /* not HAVE_XDR_UMNTRES */
-#endif /* HAVE_FS_AUTOFS */
+#ifdef HAVE_FS_NFS3
+bool_t xdr_am_fhandle3(XDR *xdrs, am_fhandle3 *objp);
+bool_t xdr_am_mountstat3(XDR *xdrs, am_mountstat3 *objp);
+bool_t xdr_am_mountres3_ok(XDR *xdrs, am_mountres3_ok *objp);
+bool_t xdr_am_mountres3(XDR *xdrs, am_mountres3 *objp);
+bool_t xdr_am_diropargs3(XDR *xdrs, am_diropargs3 *objp);
+bool_t xdr_am_filename3(XDR *xdrs, am_filename3 *objp);
+bool_t xdr_am_LOOKUP3args(XDR *xdrs, am_LOOKUP3args *objp);
+bool_t xdr_am_LOOKUP3res(XDR *xdrs, am_LOOKUP3res *objp);
+bool_t xdr_am_LOOKUP3resfail(XDR *xdrs, am_LOOKUP3resfail *objp);
+bool_t xdr_am_LOOKUP3resok(XDR *xdrs, am_LOOKUP3resok *objp);
+bool_t xdr_am_nfsstat3(XDR *xdrs, am_nfsstat3 *objp);
+bool_t xdr_am_nfs_fh3(XDR *xdrs, am_nfs_fh3 *objp);
+#endif /* HAVE_FS_NFS3 */
 
 #endif /* not _AM_XDR_FUNC_H */
diff --git a/contrib/amd/include/amq_defs.h b/contrib/amd/include/amq_defs.h
index 6564e24..75c4651 100644
--- a/contrib/amd/include/amq_defs.h
+++ b/contrib/amd/include/amq_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amq_defs.h,v 1.3 1999/09/08 23:36:52 ezk Exp $
+ * File: am-utils/include/amq_defs.h
  *
  */
 
@@ -51,7 +50,7 @@
 #ifndef AMQ_SIZE
 # define AMQ_SIZE 16384
 #endif /* not AMQ_SIZE */
-#define AMQ_STRLEN 2048
+#define AMQ_STRLEN 16384
 #define AMQ_PROGRAM ((u_long)300019)
 #define AMQ_VERSION ((u_long)1)
 #define AMQPROC_NULL ((u_long)0)
@@ -64,6 +63,7 @@
 #define AMQPROC_MOUNT ((u_long)7)
 #define AMQPROC_GETVERS ((u_long)8)
 #define AMQPROC_GETPID ((u_long)9)
+#define AMQPROC_PAWD ((u_long)10)
 
 /*
  * TYPEDEFS
diff --git a/contrib/amd/include/mount_headers1.h b/contrib/amd/include/mount_headers1.h
new file mode 100644
index 0000000..41f26e5
--- /dev/null
+++ b/contrib/amd/include/mount_headers1.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 1997-2006 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.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * 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.
+ *
+ *
+ * File: am-utils/include/mount_headers1.h
+ *
+ */
+
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif /* HAVE_SYS_TYPES_H */
+#ifdef HAVE_SYS_ERRNO_H
+# include <sys/errno.h>
+#endif /* HAVE_SYS_ERRNO_H */
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif /* HAVE_SYS_TIME_H */
+#ifdef HAVE_SYS_UCRED_H
+# include <sys/ucred.h>
+#endif /* HAVE_SYS_UCRED_H */
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif /* HAVE_SYS_SOCKET_H */
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif /* HAVE_NETINET_IN_H */
+#ifdef HAVE_NET_IF_H
+# include <net/if.h>
+#endif /* HAVE_NET_IF_H */
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
+#endif /* HAVE_STDIO_H */
+
+#ifndef KERNEL
+# define KERNEL_off_for_now_breaks_FreeBSD
+#endif /* not KERNEL */
+
+#ifdef HAVE_SYS_MNTENT_H
+# include <sys/mntent.h>
+#endif /* HAVE_SYS_MNTENT_H */
+#ifdef HAVE_MNTENT_H
+# include <mntent.h>
+#endif /* HAVE_MNTENT_H */
+#ifdef HAVE_SYS_MNTTAB_H
+# include <sys/mnttab.h>
+#endif /* HAVE_SYS_MNTTAB_H */
+#if defined(HAVE_MNTTAB_H) && !defined(MNTTAB)
+/*
+ * Do not include it if MNTTAB is already defined because it probably
+ * came from <sys/mnttab.h> and we do not want conflicting definitions.
+ */
+# include <mnttab.h>
+#endif /* defined(HAVE_MNTTAB_H) && !defined(MNTTAB) */
+
+#ifdef HAVE_SYS_MOUNT_H
+# ifndef NFSCLIENT
+#  define NFSCLIENT
+# endif /* not NFSCLIENT */
+# ifndef PCFS
+#  define PCFS
+# endif /* not PCFS */
+# ifndef LOFS
+#  define LOFS
+# endif /* not LOFS */
+# ifndef RFS
+#  define RFS
+# endif /* not RFS */
+# ifndef MSDOSFS
+#  define MSDOSFS
+# endif /* not MSDOSFS */
+# ifndef MFS
+#  define MFS 1
+# endif /* not MFS */
+# ifndef CD9660
+#  define CD9660
+# endif /* not CD9660 */
+# ifndef NFS
+#  define NFS
+# endif /* not NFS */
+# include <sys/mount.h>
+#endif /* HAVE_SYS_MOUNT_H */
+
+#ifdef HAVE_SYS_VMOUNT_H
+# include <sys/vmount.h>
+#endif /* HAVE_SYS_VMOUNT_H */
+
+/*
+ * There is no point in including this on a glibc2 system
+ * we're only asking for trouble
+ */
+#if defined HAVE_LINUX_FS_H && (!defined __GLIBC__ || __GLIBC__ < 2)
+/*
+ * There's a conflict of definitions on redhat alpha linux between
+ * <netinet/in.h> and <linux/fs.h>.
+ * Also a conflict in definitions of ntohl/htonl in RH-5.1 sparc64
+ * between <netinet/in.h> and <linux/byteorder/generic.h> (2.1 kernels).
+ */
+# ifdef HAVE_SOCKETBITS_H
+#  define _LINUX_SOCKET_H
+#  undef BLKFLSBUF
+#  undef BLKGETSIZE
+#  undef BLKRAGET
+#  undef BLKRASET
+#  undef BLKROGET
+#  undef BLKROSET
+#  undef BLKRRPART
+#  undef MS_MGC_VAL
+#  undef MS_RMT_MASK
+# endif /* HAVE_SOCKETBITS_H */
+# ifdef HAVE_LINUX_POSIX_TYPES_H
+#  include <linux/posix_types.h>
+# endif /* HAVE_LINUX_POSIX_TYPES_H */
+# ifndef _LINUX_BYTEORDER_GENERIC_H
+#  define _LINUX_BYTEORDER_GENERIC_H
+# endif /* _LINUX_BYTEORDER_GENERIC_H */
+# ifndef _LINUX_STRING_H_
+#  define _LINUX_STRING_H_
+# endif /* not _LINUX_STRING_H_ */
+# ifdef HAVE_LINUX_KDEV_T_H
+#  define __KERNEL__
+#  include <linux/kdev_t.h>
+#  undef __KERNEL__
+# endif /* HAVE_LINUX_KDEV_T_H */
+# ifdef HAVE_LINUX_LIST_H
+#  define __KERNEL__
+#  include <linux/list.h>
+#  undef __KERNEL__
+# endif /* HAVE_LINUX_LIST_H */
+# include <linux/fs.h>
+#endif /* HAVE_LINUX_FS_H && (!__GLIBC__ || __GLIBC__ < 2) */
+
+#ifdef HAVE_SYS_FS_TYPES_H
+# include <sys/fs_types.h>
+#endif /* HAVE_SYS_FS_TYPES_H */
+
+#ifdef HAVE_UFS_UFS_MOUNT_H
+# include <ufs/ufs_mount.h>
+#endif /* HAVE_UFS_UFS_MOUNT_H */
+#ifdef	HAVE_UFS_UFS_UFSMOUNT_H_off
+# error do not include this file here because on *bsd it
+# error causes errors with other header files.  Instead, add it to the
+# error specific conf/nfs_prot_*.h file.
+# include <ufs/ufs/ufsmount.h>
+#endif	/* HAVE_UFS_UFS_UFSMOUNT_H_off */
+
+#ifdef HAVE_CDFS_CDFS_MOUNT_H
+# include <cdfs/cdfs_mount.h>
+#endif /* HAVE_CDFS_CDFS_MOUNT_H */
+#ifdef HAVE_CDFS_CDFSMOUNT_H
+# include <cdfs/cdfsmount.h>
+#endif /* HAVE_CDFS_CDFSMOUNT_H */
+#ifdef HAVE_ISOFS_CD9660_CD9660_MOUNT_H
+# include <isofs/cd9660/cd9660_mount.h>
+#endif /* HAVE_ISOFS_CD9660_CD9660_MOUNT_H */
+
+#ifdef HAVE_SYS_FS_PC_FS_H
+# include <sys/fs/pc_fs.h>
+#endif /* HAVE_SYS_FS_PC_FS_H */
+#ifdef HAVE_MSDOSFS_MSDOSFSMOUNT_H
+# include <msdosfs/msdosfsmount.h>
+#endif /* HAVE_MSDOSFS_MSDOSFSMOUNT_H */
+#ifdef HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H
+# include <fs/msdosfs/msdosfsmount.h>
+#endif /* HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H */
+
+#ifdef HAVE_RPC_RPC_H
+# include <rpc/rpc.h>
+#endif /* HAVE_RPC_RPC_H */
+#ifdef HAVE_RPC_TYPES_H
+# include <rpc/types.h>
+#endif /* HAVE_RPC_TYPES_H */
+/* Prevent multiple inclusion on Ultrix 4 */
+#if defined(HAVE_RPC_XDR_H) && !defined(__XDR_HEADER__)
+# include <rpc/xdr.h>
+#endif /* defined(HAVE_RPC_XDR_H) && !defined(__XDR_HEADER__) */
+
+/* ALWAYS INCLUDE AM-UTILS' SPECIFIC NFS PROTOCOL HEADER NEXT! */
diff --git a/contrib/amd/include/mount_headers2.h b/contrib/amd/include/mount_headers2.h
new file mode 100644
index 0000000..273e89c
--- /dev/null
+++ b/contrib/amd/include/mount_headers2.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1997-2006 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.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * 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.
+ *
+ *
+ * File: am-utils/include/mount_headers2.h
+ *
+ */
+
+
+
+#ifdef HAVE_RPCSVC_MOUNT_H
+# include <rpcsvc/mount.h>
+#endif /* HAVE_RPCSVC_MOUNT_H */
+
+#ifdef HAVE_MOUNT_H
+# include <mount.h>
+#endif /* HAVE_MOUNT_H */
+
+#ifdef HAVE_NFS_NFS_GFS_H
+# include <nfs/nfs_gfs.h>
+#endif /* HAVE_NFS_NFS_GFS_H */
+
+#ifdef HAVE_NFS_MOUNT_H
+# include <nfs/mount.h>
+#endif /* HAVE_NFS_MOUNT_H */
+
+#ifdef HAVE_SYS_FS_NFS_CLNT_H
+# include <sys/fs/nfs_clnt.h>
+#endif /* HAVE_SYS_FS_NFS_CLNT_H */
+
+#ifdef HAVE_LINUX_NFS_MOUNT_H
+# ifndef _LINUX_NFS_H
+#  define _LINUX_NFS_H
+# endif /* not _LINUX_NFS_H */
+# ifndef _LINUX_NFS2_H
+#  define _LINUX_NFS2_H
+# endif /* not _LINUX_NFS2_H */
+# ifndef _LINUX_NFS3_H
+#  define _LINUX_NFS3_H
+# endif /* not _LINUX_NFS3_H */
+# ifndef _LINUX_NFS_FS_H
+#  define _LINUX_NFS_FS_H
+# endif /* not _LINUX_NFS_FS_H */
+# ifndef _LINUX_IN_H
+#  define _LINUX_IN_H
+# endif /* not _LINUX_IN_H */
+# ifndef __KERNEL__
+#  define __KERNEL__
+# endif /* __KERNEL__ */
+# include <linux/nfs_mount.h>
+# undef __KERNEL__
+#endif /* HAVE_LINUX_NFS_MOUNT_H */
diff --git a/contrib/amd/ldap-id.ms b/contrib/amd/ldap-id.ms
new file mode 100644
index 0000000..3c0d308
--- /dev/null
+++ b/contrib/amd/ldap-id.ms
@@ -0,0 +1,306 @@
+.pl 10.0i
+.po 0
+.ll 8.5i
+.lt 8.5i
+.nr LL 8.5i
+.nr LT 8.5i
+.ds LF Johansson
+.ds RF [Page %]
+.ds CF
+.ds LH Internet draft
+.ds RH 30 March 1998
+.ds CH Berkeley AMD LDAP Schema
+.hy 0
+.ad l
+.in 0
+INTERNET-DRAFT                                                         Leif Johansson
+Intented Category: Experimental                                  Stockholm University
+
+
+
+.ce
+A directory (X.500 and LDAPv3) schema for Berkely automounter
+
+
+.ti 0
+1. Status of this Memo
+
+.fi
+.in 3
+This memo describes a directory (LDAP or X.500) schema for storing
+amd (Berkely-style automounter) mount info maps. The schema is currently
+beeing supported by the (beta version of the) am-utils version 6 package
+[AMUTILS].
+
+.ti 0
+2. Overview and Rationale
+
+Directory services such as X.500 [X500] or LDAP [RFC2251] are a natural
+choice of repository for amd mount map databases. All Object Identifiers
+in this document are prefixed by amdSchema-id to be assigned later. The
+relation between this schema and the automount schema elements in [HOWARD]
+are mostly superficial. The model for the elements in [HOWARD] was the SUN
+automounter which has quite a different syntax for mount maps. Furthermore
+the intended usage of this schema differs from that of [HOWARD] in many
+respects.
+
+.ti 0
+3. DSA requirements
+
+Directory servers implementing this schema SHOULD maintain the
+modifyTimestamp operational attribute. If not the amdMapCacheTtl
+attribute SHOULD be set to 0 indicating to clients that caching of
+map entries SHOULD be turned off. Clients wishing to use the amdMap
+schema MAY use the modifyTimestamp information to set the ttl for
+internal caching schemes. A value of 0 for the amdMapCacheTtl must
+result in clients turning off any local caching.
+
+.ti 0
+4. Syntax definitions
+
+The following attribute syntax is defined in this document:
+
+     amdlocationlist
+
+This syntax represents a amd map value. This is the syntax expressed
+in BNF using definitions from [RFC2252]:
+
+     amdlocationlist      = amdlocationselection |
+                            amdlocationlist whsp "||" whsp amdlocationselection
+
+     amdlocationselection = amdlocation |
+                            amdlocationselection whsp amdlocation
+
+     amdlocation          = amdlocationinfo |
+                            "-" amdlocationinfo |
+                            "-"
+
+     amdlocationinfo      = seloropt |
+                            amdlocationinfo ";" seloropt |
+                            ";"
+
+     seloropt             = seletion |
+                            optass
+
+     selection            = keystring "==" printablestring
+                            keystring "!=" printablestring
+
+     optass               = keystring \":=\" printablestring
+
+X.500 servers or LDAPv3 servers (supporting the binary attribute
+option) may use the following syntax definition:
+
+     AmdLocationList ::= SEQUENCE OF {
+                            SEQUENCE OF {
+                               location     AmdLocation
+                            }
+                         }
+
+     AmdLocation     ::= SET OF {
+                            CHOICE {
+                               location     [0] AmdLocationInfo
+                               notlocation  [1] AmdLocationInfo
+                               not          [2] NULL
+                            }
+                         }
+
+     AmdLocationInfo ::= SET OF {
+                            CHOICE {
+                               selection    [0] AmdSelection
+                               option       [1] AmdOption
+                            }
+                         }
+
+     AmdSelection    ::= CHOICE {
+                            eq     [0] AttributeAndValue
+                            ne     [1] AttributeAndValue
+                         }
+
+     AmdOption       ::= AttributeAndValue
+
+     AttributeAndValue ::= SEQUENCE {
+                              attribute     IA5String
+                              value         IA5String
+                           }
+
+.ti 0
+5. Attribute types
+
+The following attribute types are defined in this document:
+
+     amdMapName
+     amdMapCacheTtl
+     amdMapEntry
+     amdMapEntryKey
+     amdMapEntryValue
+
+     amdSchema-a OBJECT IDENTIFIER ::= { amdSchema-id 1 }
+
+     amdMapName
+	ATTRIBUTE ::= {
+           WITH SYNTAX              IA5String
+           EQUALITY MATCHING RULE   caseIgoreExactMatch
+           --ID                     { amdSchema-a 1 }
+           DESCRIPTION
+            "This attribute is the symbolic and in the naming
+             context unique name of an amd map. This corresponds
+             in the case of a flat file database to the name of
+             the file or the mount-point of the map."
+        }
+
+
+     amdMapCacheTtl
+        ATTRIBUTE ::= {
+           WITH SYNTAX              Integer
+           EQUALITY MATCHING RULE   integerExactMatch
+           --ID                     { amdSchema-a 2 }
+           SINGLE VALUED
+           DESCRIPTION
+            "The maximum time-to-live for the entries in this
+             map. After this many milliseconds the map has to
+             be cleared from local caches and reloaded. A value
+             of 0 disables caching."
+        }
+
+     amdMapEntry
+        ATTRIBUTE ::= {
+           WITH SYNTAX              DistinguishedName
+           EQUALITY MATHCING RULE   dNCaseIgnoreExactMatch
+           --ID                     { amdSchema-a 3 }
+           DESCRIPTION
+            "A multivalued attribute listing the distinguished
+             names of the amdMapEntries making up this amdMap
+             object."
+        }
+
+     amdMapEntryKey ::= {
+        ATTRIBUTE ::= {
+           WITH SYNTAX              IA5String
+           EQUALITY MATCHING RULE   stringExactMatch
+           --ID                     { amdSchema-a 4 }
+           SINGLE VALUED
+           DESCRIPTION
+            "The value of this attribute is usually the name of
+             a mountpoint for this amdMapEntry."
+        }
+
+     amdMapEntryValue ::= {
+        ATTRIBUTE ::= {
+           WITH SYNTAX              AmdLocationList
+           --ID                     { amdSchema-a 5 }
+           DESCRIPTION
+            "This is the actual mount information for the amdMapEntry
+             using the syntax described above."
+        }
+
+     amdMapEntryKey ::= {
+        ATTRIBUTE ::= {
+           WITH SYNTAX              IA5String
+           EQUALITY MATCHING RULE   stringExactMatch
+           --ID                     { amdSchema-a 4 }
+           SINGLE VALUED
+           DESCRIPTION
+            "The value of this attribute is usually the name of
+             a mountpoint for this amdMapEntry."
+        }
+
+     amdMapEntryValue ::= {
+        ATTRIBUTE ::= {
+           WITH SYNTAX              AmdLocationList
+           --ID                     { amdSchema-a 5 }
+           DESCRIPTION
+            "This is the actual mount information for the amdMapEntry
+             using the syntax described above."
+        }
+
+.ti 0
+6. Object classes
+
+The following object classes are defined in this document:
+
+          amdMap
+          amdMapEntry
+
+defined as follows:
+
+          amdSchema-oc ::= { amdSchema-id 2 }
+
+          amdMap OBJECT-CLASS ::= {
+                    SUBCLASS OF            { top }
+                    KIND                   auxiliary
+                    --ID                   { amdSchema-oc 1 }
+                    MAY CONTAIN            { amdMapCacheTtl , cn }
+                    MUST CONTAIN           { amdMapName , amdMapEntry }
+                 }
+
+          amdMapEntry OBJECT-CLASS ::= {
+                         SUBCLASS OF       { top }
+                         KIND              structural
+                         --ID              { amdSchema-oc 2 }
+                         MUST CONTAIN      {
+                                             amdMapName ,
+                                             amdEntryKey ,
+                                             amdEntryValue ,
+                                           }
+	                 MAY CONTAIN       { cn }
+	                 DESCRIPTION
+		          "An entry of this object class describes mount
+	                   information relative to a certain amdMap entry"
+                      }
+
+.ti 0
+7. Examples
+
+
+
+.ti 0
+8. Security Considerations
+
+Due to the security problems posed by NFS care should be taken not to
+advertise exported filesystems. Therefore it is often desirable to limit
+access to entries carrying amd mount map information to those systems
+to which the corresponding filesystems have been exported.
+
+.ti 0
+9. References
+
+   [AMUTILS]
+        am-utils homepage: http://shekel.cs.columbia.edu/~erez/am-utils.html
+
+   [RFC2251]
+        M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access
+        Protocol (v3)", RFC 2251, December 1997.
+
+   [RFC2252]
+        M. Wahl, A. Coulbeck, T. Howes, S. Kille, "Lightweight Directory
+        Access Protocol (v3): Attribute Syntax Definitions", RFC 2252,
+        December 1997.
+
+   [RFC2253]
+        M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access
+        Protocol (v3): UTF-8 String Representation of Distinguished
+        Names", RFC 2253, December 1997.
+
+   [HOWARD]
+        Luke Howard, "An Approach for Using LDAP as a Network
+        Information Service", draft-howard-nis-schema-??.txt, Internet
+        draft.
+
+   [X500]
+        ITU something or other.
+
+.in 3
+
+
+.ti 0
+Author's Address
+
+.nf
+
+Leif Johansson
+Department of Mathematics
+Stockholm University
+S-106 91 Stockholm
+         SWEDEN
+
+Email: leifj@matematik.su.se
diff --git a/contrib/amd/ldap-id.txt b/contrib/amd/ldap-id.txt
new file mode 100644
index 0000000..162f663
--- /dev/null
+++ b/contrib/amd/ldap-id.txt
@@ -0,0 +1,360 @@
+
+
+
+
+
+
+INTERNET-DRAFT                                                         Leif Johansson
+Intented Category: Experimental                                  Stockholm University
+
+
+
+            A directory (X.500 and LDAPv3) schema for Berkely automounter
+
+
+1. Status of this Memo
+
+   This memo describes a directory (LDAP or X.500) schema for storing amd (Berkely-
+   style automounter) mount info maps. The schema is currently beeing supported by
+   the (beta version of the) am-utils version 6 package [AMUTILS].
+
+2. Overview and Rationale
+
+   Directory services such as X.500 [X500] or LDAP [RFC2251] are a natural choice of
+   repository for amd mount map databases. All Object Identifiers in this document
+   are prefixed by amdSchema-id to be assigned later. The relation between this
+   schema and the automount schema elements in [HOWARD] are mostly superficial. The
+   model for the elements in [HOWARD] was the SUN automounter which has quite a
+   different syntax for mount maps. Furthermore the intended usage of this schema
+   differs from that of [HOWARD] in many respects.
+
+3. DSA requirements
+
+   Directory servers implementing this schema SHOULD maintain the modifyTimestamp
+   operational attribute. If not the amdMapCacheTtl attribute SHOULD be set to 0
+   indicating to clients that caching of map entries SHOULD be turned off. Clients
+   wishing to use the amdMap schema MAY use the modifyTimestamp information to set
+   the ttl for internal caching schemes. A value of 0 for the amdMapCacheTtl must
+   result in clients turning off any local caching.
+
+4. Syntax definitions
+
+   The following attribute syntax is defined in this document:
+
+        amdlocationlist
+
+   This syntax represents a amd map value. This is the syntax expressed in BNF using
+   definitions from [RFC2252]:
+
+        amdlocationlist      = amdlocationselection |
+                               amdlocationlist whsp "||" whsp amdlocationselection
+
+        amdlocationselection = amdlocation |
+                               amdlocationselection whsp amdlocation
+
+
+
+
+Johansson                                                                    [Page 1]
+
+
+
+
+
+Internet draft                 Berkeley AMD LDAP Schema                 30 March 1998
+
+
+        amdlocation          = amdlocationinfo |
+                               "-" amdlocationinfo |
+                               "-"
+
+        amdlocationinfo      = seloropt |
+                               amdlocationinfo ";" seloropt |
+                               ";"
+
+        seloropt             = seletion |
+                               optass
+
+        selection            = keystring "==" printablestring
+                               keystring "!=" printablestring
+
+        optass               = keystring
+
+   X.500 servers or LDAPv3 servers (supporting the binary attribute option) may use
+   the following syntax definition:
+
+        AmdLocationList ::= SEQUENCE OF {
+                               SEQUENCE OF {
+                                  location     AmdLocation
+                               }
+                            }
+
+        AmdLocation     ::= SET OF {
+                               CHOICE {
+                                  location     [0] AmdLocationInfo
+                                  notlocation  [1] AmdLocationInfo
+                                  not          [2] NULL
+                               }
+                            }
+
+        AmdLocationInfo ::= SET OF {
+                               CHOICE {
+                                  selection    [0] AmdSelection
+                                  option       [1] AmdOption
+                               }
+                            }
+
+        AmdSelection    ::= CHOICE {
+                               eq     [0] AttributeAndValue
+                               ne     [1] AttributeAndValue
+                            }
+
+        AmdOption       ::= AttributeAndValue
+        AttributeAndValue ::= SEQUENCE {
+                                 attribute     IA5String
+
+
+
+Johansson                                                                    [Page 2]
+
+
+
+
+
+Internet draft                 Berkeley AMD LDAP Schema                 30 March 1998
+
+
+                                 value         IA5String
+                              }
+
+5. Attribute types
+
+   The following attribute types are defined in this document:
+
+        amdMapName
+        amdMapCacheTtl
+        amdMapEntry
+        amdMapEntryKey
+        amdMapEntryValue
+
+        amdSchema-a OBJECT IDENTIFIER ::= { amdSchema-id 1 }
+
+        amdMapName      ATTRIBUTE ::= {
+              WITH SYNTAX              IA5String
+              EQUALITY MATCHING RULE   caseIgoreExactMatch
+              --ID                     { amdSchema-a 1 }
+              DESCRIPTION
+               "This attribute is the symbolic and in the naming
+                context unique name of an amd map. This corresponds
+                in the case of a flat file database to the name of
+                the file or the mount-point of the map."
+           }
+
+
+        amdMapCacheTtl
+           ATTRIBUTE ::= {
+              WITH SYNTAX              Integer
+              EQUALITY MATCHING RULE   integerExactMatch
+              --ID                     { amdSchema-a 2 }
+              SINGLE VALUED
+              DESCRIPTION
+               "The maximum time-to-live for the entries in this
+                map. After this many milliseconds the map has to
+                be cleared from local caches and reloaded. A value
+                of 0 disables caching."
+           }
+
+        amdMapEntry
+           ATTRIBUTE ::= {
+              WITH SYNTAX              DistinguishedName
+              EQUALITY MATHCING RULE   dNCaseIgnoreExactMatch
+              --ID                     { amdSchema-a 3 }
+              DESCRIPTION
+               "A multivalued attribute listing the distinguished
+                names of the amdMapEntries making up this amdMap
+
+
+
+Johansson                                                                    [Page 3]
+
+
+
+
+
+Internet draft                 Berkeley AMD LDAP Schema                 30 March 1998
+
+
+                object."
+           }
+
+        amdMapEntryKey ::= {
+           ATTRIBUTE ::= {
+              WITH SYNTAX              IA5String
+              EQUALITY MATCHING RULE   stringExactMatch
+              --ID                     { amdSchema-a 4 }
+              SINGLE VALUED
+              DESCRIPTION
+               "The value of this attribute is usually the name of
+                a mountpoint for this amdMapEntry."
+           }
+
+        amdMapEntryValue ::= {
+           ATTRIBUTE ::= {
+              WITH SYNTAX              AmdLocationList
+              --ID                     { amdSchema-a 5 }
+              DESCRIPTION
+               "This is the actual mount information for the amdMapEntry
+                using the syntax described above."
+           }
+
+        amdMapEntryKey ::= {
+           ATTRIBUTE ::= {
+              WITH SYNTAX              IA5String
+              EQUALITY MATCHING RULE   stringExactMatch
+              --ID                     { amdSchema-a 4 }
+              SINGLE VALUED
+              DESCRIPTION
+               "The value of this attribute is usually the name of
+                a mountpoint for this amdMapEntry."
+           }
+
+        amdMapEntryValue ::= {
+           ATTRIBUTE ::= {
+              WITH SYNTAX              AmdLocationList
+              --ID                     { amdSchema-a 5 }
+              DESCRIPTION
+               "This is the actual mount information for the amdMapEntry
+                using the syntax described above."
+           }
+
+6. Object classes
+
+   The following object classes are defined in this document:
+
+             amdMap
+
+
+
+Johansson                                                                    [Page 4]
+
+
+
+
+
+Internet draft                 Berkeley AMD LDAP Schema                 30 March 1998
+
+
+             amdMapEntry
+
+   defined as follows:
+
+             amdSchema-oc ::= { amdSchema-id 2 }
+
+             amdMap OBJECT-CLASS ::= {
+                       SUBCLASS OF            { top }
+                       KIND                   auxiliary
+                       --ID                   { amdSchema-oc 1 }
+                       MAY CONTAIN            { amdMapCacheTtl , cn }
+                       MUST CONTAIN           { amdMapName , amdMapEntry }
+                    }
+
+             amdMapEntry OBJECT-CLASS ::= {
+                            SUBCLASS OF       { top }
+                            KIND              structural
+                            --ID              { amdSchema-oc 2 }
+                            MUST CONTAIN      {
+                                                amdMapName ,
+                                                amdEntryKey ,
+                                                amdEntryValue ,
+                                              }                       MAY CONTAIN
+   { cn }                       DESCRIPTION                     "An entry of this
+   object class describes mount                         information relative to a
+   certain amdMap entry"
+                         }
+
+7. Examples
+
+
+
+8. Security Considerations
+
+   Due to the security problems posed by NFS care should be taken not to advertise
+   exported filesystems. Therefore it is often desirable to limit access to entries
+   carrying amd mount map information to those systems to which the corresponding
+   filesystems have been exported.
+
+9. References
+
+      [AMUTILS]
+           am-utils homepage: http://shekel.cs.columbia.edu/~erez/am-utils.html
+
+      [RFC2251]
+           M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access
+           Protocol (v3)", RFC 2251, December 1997.
+
+
+
+
+Johansson                                                                    [Page 5]
+
+
+
+
+
+Internet draft                 Berkeley AMD LDAP Schema                 30 March 1998
+
+
+      [RFC2252]
+           M. Wahl, A. Coulbeck, T. Howes, S. Kille, "Lightweight Directory
+           Access Protocol (v3): Attribute Syntax Definitions", RFC 2252,
+           December 1997.
+
+      [RFC2253]
+           M. Wahl, S. Kille, T. Howes, "Lightweight Directory Access
+           Protocol (v3): UTF-8 String Representation of Distinguished
+           Names", RFC 2253, December 1997.
+
+      [HOWARD]
+           Luke Howard, "An Approach for Using LDAP as a Network
+           Information Service", draft-howard-nis-schema-??.txt, Internet
+           draft.
+
+      [X500]
+           ITU something or other.
+
+
+
+Author's Address
+
+
+   Leif Johansson
+   Department of Mathematics
+   Stockholm University
+   S-106 91 Stockholm
+            SWEDEN
+
+   Email: leifj@matematik.su.se
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Johansson                                                                    [Page 6]
+
+
diff --git a/contrib/amd/ldap.schema b/contrib/amd/ldap.schema
new file mode 100644
index 0000000..9594d2f
--- /dev/null
+++ b/contrib/amd/ldap.schema
@@ -0,0 +1,52 @@
+# A schema for the Berkeley automounter (AMD)
+# Authored by Erez Zadok and/or source maintainers
+# Definition by Tim Colles <timc at dai.ed.ac.uk>
+# Revised by Adam Morley <adam at gmi.com>
+
+# OID Base is 1.3.6.1.4.1.10180
+#
+# Syntaxes are under 1.3.6.1.4.1.10180.3.175-199
+# Attribute types are under 1.3.6.1.4.1.10180.2.175-199
+# Object classes are under 1.3.6.1.4.1.10180.1.175-199
+
+# Attribute Type Definitions
+
+attributetype	( 1.3.6.1.4.1.10180.2.175
+	NAME	'amdmapTimestamp'
+	DESC	'Probably the time the map was last modified'
+	EQUALITY	integerMatch
+	SYNTAX	1.3.6.1.4.1.1466.115.121.1.27
+	SINGLE-VALUE )
+
+attributetype	( 1.3.6.1.4.1.10180.2.176
+	NAME	'amdmapName'
+	DESC	'The symbolic name of the map, ie. map_name'
+	EQUALITY	caseIgnoreMatch
+	SYNTAX	1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+
+attributetype	( 1.3.6.1.4.1.10180.2.177
+	NAME	'amdmapKey'
+	DESC	'The key value for this entry'
+	EQUALITY	caseIgnoreMatch
+	SYNTAX	1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+
+attributetype	( 1.3.6.1.4.1.10180.2.178
+	NAME	'amdmapValue'
+	DESC	'The mount information for this entry'
+	EQUALITY	caseIgnoreMatch
+	SYNTAX	1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+
+# Object Class Definitions
+
+objectclass	( 1.3.6.1.4.1.10180.1.175 NAME 'amdmapTimestamp'
+	SUP	top STRUCTURAL
+	DESC	'Timestamp for an AMD map'
+	MUST	( cn $ amdmapName $ amdmapTimestamp ) )
+
+objectclass	( 1.3.6.1.4.1.10180.1.176 NAME 'amdmap'
+	SUP	top STRUCTURAL
+	DESC	'Defines an AMD map entry'
+	MUST	( cn $ amdmapName $ amdmapKey $ amdmapValue ) )
diff --git a/contrib/amd/libamu/alloca.c b/contrib/amd/libamu/alloca.c
deleted file mode 100644
index 31fb4e0..0000000
--- a/contrib/amd/libamu/alloca.c
+++ /dev/null
@@ -1,504 +0,0 @@
-/* alloca.c -- allocate automatically reclaimed memory
-   (Mostly) portable public-domain implementation -- D A Gwyn
-
-   This implementation of the PWB library alloca function,
-   which is used to allocate space off the run-time stack so
-   that it is automatically reclaimed upon procedure exit,
-   was inspired by discussions with J. Q. Johnson of Cornell.
-   J.Otto Tennant <jot@cray.com> contributed the Cray support.
-
-   There are some preprocessor constants that can
-   be defined when compiling for your specific system, for
-   improved efficiency; however, the defaults should be okay.
-
-   The general concept of this implementation is to keep
-   track of all alloca-allocated blocks, and reclaim any
-   that are found to be deeper in the stack than the current
-   invocation.  This heuristic does not reclaim storage as
-   soon as it becomes invalid, but it will do so eventually.
-
-   As a special case, alloca(0) reclaims storage without
-   allocating any.  It is a good idea to use alloca(0) in
-   your main control loop, etc. to force garbage collection.  */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef emacs
-#include "blockinput.h"
-#endif
-
-/* If compiling with GCC 2, this file's not needed.  */
-#if !defined (__GNUC__) || __GNUC__ < 2
-
-/* If someone has defined alloca as a macro,
-   there must be some other way alloca is supposed to work.  */
-#ifndef alloca
-
-#ifdef emacs
-#ifdef static
-/* actually, only want this if static is defined as ""
-   -- this is for usg, in which emacs must undefine static
-   in order to make unexec workable
-   */
-#ifndef STACK_DIRECTION
-you
-lose
--- must know STACK_DIRECTION at compile-time
-#endif /* STACK_DIRECTION undefined */
-#endif /* static */
-#endif /* emacs */
-
-/* If your stack is a linked list of frames, you have to
-   provide an "address metric" ADDRESS_FUNCTION macro.  */
-
-#if defined (CRAY) && defined (CRAY_STACKSEG_END)
-long i00afunc ();
-#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
-#else
-#define ADDRESS_FUNCTION(arg) &(arg)
-#endif
-
-#if __STDC__
-typedef void *pointer;
-#else
-typedef char *pointer;
-#endif
-
-#ifndef NULL
-#define	NULL	0
-#endif
-
-/* Different portions of Emacs need to call different versions of
-   malloc.  The Emacs executable needs alloca to call xmalloc, because
-   ordinary malloc isn't protected from input signals.  On the other
-   hand, the utilities in lib-src need alloca to call malloc; some of
-   them are very simple, and don't have an xmalloc routine.
-
-   Non-Emacs programs expect this to call use xmalloc.
-
-   Callers below should use malloc.  */
-
-#ifndef emacs
-#define malloc xmalloc
-#endif
-extern pointer malloc ();
-
-/* Define STACK_DIRECTION if you know the direction of stack
-   growth for your system; otherwise it will be automatically
-   deduced at run-time.
-
-   STACK_DIRECTION > 0 => grows toward higher addresses
-   STACK_DIRECTION < 0 => grows toward lower addresses
-   STACK_DIRECTION = 0 => direction of growth unknown  */
-
-#ifndef STACK_DIRECTION
-#define	STACK_DIRECTION	0	/* Direction unknown.  */
-#endif
-
-#if STACK_DIRECTION != 0
-
-#define	STACK_DIR	STACK_DIRECTION	/* Known at compile-time.  */
-
-#else /* STACK_DIRECTION == 0; need run-time code.  */
-
-static int stack_dir;		/* 1 or -1 once known.  */
-#define	STACK_DIR	stack_dir
-
-static void
-find_stack_direction ()
-{
-  static char *addr = NULL;	/* Address of first `dummy', once known.  */
-  auto char dummy;		/* To get stack address.  */
-
-  if (addr == NULL)
-    {				/* Initial entry.  */
-      addr = ADDRESS_FUNCTION (dummy);
-
-      find_stack_direction ();	/* Recurse once.  */
-    }
-  else
-    {
-      /* Second entry.  */
-      if (ADDRESS_FUNCTION (dummy) > addr)
-	stack_dir = 1;		/* Stack grew upward.  */
-      else
-	stack_dir = -1;		/* Stack grew downward.  */
-    }
-}
-
-#endif /* STACK_DIRECTION == 0 */
-
-/* An "alloca header" is used to:
-   (a) chain together all alloca'ed blocks;
-   (b) keep track of stack depth.
-
-   It is very important that sizeof(header) agree with malloc
-   alignment chunk size.  The following default should work okay.  */
-
-#ifndef	ALIGN_SIZE
-#define	ALIGN_SIZE	sizeof(double)
-#endif
-
-typedef union hdr
-{
-  char align[ALIGN_SIZE];	/* To force sizeof(header).  */
-  struct
-    {
-      union hdr *next;		/* For chaining headers.  */
-      char *deep;		/* For stack depth measure.  */
-    } h;
-} header;
-
-static header *last_alloca_header = NULL;	/* -> last alloca header.  */
-
-/* Return a pointer to at least SIZE bytes of storage,
-   which will be automatically reclaimed upon exit from
-   the procedure that called alloca.  Originally, this space
-   was supposed to be taken from the current stack frame of the
-   caller, but that method cannot be made to work for some
-   implementations of C, for example under Gould's UTX/32.  */
-
-pointer
-alloca (size)
-     unsigned size;
-{
-  auto char probe;		/* Probes stack depth: */
-  register char *depth = ADDRESS_FUNCTION (probe);
-
-#if STACK_DIRECTION == 0
-  if (STACK_DIR == 0)		/* Unknown growth direction.  */
-    find_stack_direction ();
-#endif
-
-  /* Reclaim garbage, defined as all alloca'd storage that
-     was allocated from deeper in the stack than currently. */
-
-  {
-    register header *hp;	/* Traverses linked list.  */
-
-#ifdef emacs
-    BLOCK_INPUT;
-#endif
-
-    for (hp = last_alloca_header; hp != NULL;)
-      if ((STACK_DIR > 0 && hp->h.deep > depth)
-	  || (STACK_DIR < 0 && hp->h.deep < depth))
-	{
-	  register header *np = hp->h.next;
-
-	  free ((pointer) hp);	/* Collect garbage.  */
-
-	  hp = np;		/* -> next header.  */
-	}
-      else
-	break;			/* Rest are not deeper.  */
-
-    last_alloca_header = hp;	/* -> last valid storage.  */
-
-#ifdef emacs
-    UNBLOCK_INPUT;
-#endif
-  }
-
-  if (size == 0)
-    return NULL;		/* No allocation required.  */
-
-  /* Allocate combined header + user data storage.  */
-
-  {
-    register pointer new = malloc (sizeof (header) + size);
-    /* Address of header.  */
-
-    if (new == 0)
-      abort();
-
-    ((header *) new)->h.next = last_alloca_header;
-    ((header *) new)->h.deep = depth;
-
-    last_alloca_header = (header *) new;
-
-    /* User storage begins just after header.  */
-
-    return (pointer) ((char *) new + sizeof (header));
-  }
-}
-
-#if defined (CRAY) && defined (CRAY_STACKSEG_END)
-
-#ifdef DEBUG_I00AFUNC
-#include <stdio.h>
-#endif
-
-#ifndef CRAY_STACK
-#define CRAY_STACK
-#ifndef CRAY2
-/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
-struct stack_control_header
-  {
-    long shgrow:32;		/* Number of times stack has grown.  */
-    long shaseg:32;		/* Size of increments to stack.  */
-    long shhwm:32;		/* High water mark of stack.  */
-    long shsize:32;		/* Current size of stack (all segments).  */
-  };
-
-/* The stack segment linkage control information occurs at
-   the high-address end of a stack segment.  (The stack
-   grows from low addresses to high addresses.)  The initial
-   part of the stack segment linkage control information is
-   0200 (octal) words.  This provides for register storage
-   for the routine which overflows the stack.  */
-
-struct stack_segment_linkage
-  {
-    long ss[0200];		/* 0200 overflow words.  */
-    long sssize:32;		/* Number of words in this segment.  */
-    long ssbase:32;		/* Offset to stack base.  */
-    long:32;
-    long sspseg:32;		/* Offset to linkage control of previous
-				   segment of stack.  */
-    long:32;
-    long sstcpt:32;		/* Pointer to task common address block.  */
-    long sscsnm;		/* Private control structure number for
-				   microtasking.  */
-    long ssusr1;		/* Reserved for user.  */
-    long ssusr2;		/* Reserved for user.  */
-    long sstpid;		/* Process ID for pid based multi-tasking.  */
-    long ssgvup;		/* Pointer to multitasking thread giveup.  */
-    long sscray[7];		/* Reserved for Cray Research.  */
-    long ssa0;
-    long ssa1;
-    long ssa2;
-    long ssa3;
-    long ssa4;
-    long ssa5;
-    long ssa6;
-    long ssa7;
-    long sss0;
-    long sss1;
-    long sss2;
-    long sss3;
-    long sss4;
-    long sss5;
-    long sss6;
-    long sss7;
-  };
-
-#else /* CRAY2 */
-/* The following structure defines the vector of words
-   returned by the STKSTAT library routine.  */
-struct stk_stat
-  {
-    long now;			/* Current total stack size.  */
-    long maxc;			/* Amount of contiguous space which would
-				   be required to satisfy the maximum
-				   stack demand to date.  */
-    long high_water;		/* Stack high-water mark.  */
-    long overflows;		/* Number of stack overflow ($STKOFEN) calls.  */
-    long hits;			/* Number of internal buffer hits.  */
-    long extends;		/* Number of block extensions.  */
-    long stko_mallocs;		/* Block allocations by $STKOFEN.  */
-    long underflows;		/* Number of stack underflow calls ($STKRETN).  */
-    long stko_free;		/* Number of deallocations by $STKRETN.  */
-    long stkm_free;		/* Number of deallocations by $STKMRET.  */
-    long segments;		/* Current number of stack segments.  */
-    long maxs;			/* Maximum number of stack segments so far.  */
-    long pad_size;		/* Stack pad size.  */
-    long current_address;	/* Current stack segment address.  */
-    long current_size;		/* Current stack segment size.  This
-				   number is actually corrupted by STKSTAT to
-				   include the fifteen word trailer area.  */
-    long initial_address;	/* Address of initial segment.  */
-    long initial_size;		/* Size of initial segment.  */
-  };
-
-/* The following structure describes the data structure which trails
-   any stack segment.  I think that the description in 'asdef' is
-   out of date.  I only describe the parts that I am sure about.  */
-
-struct stk_trailer
-  {
-    long this_address;		/* Address of this block.  */
-    long this_size;		/* Size of this block (does not include
-				   this trailer).  */
-    long unknown2;
-    long unknown3;
-    long link;			/* Address of trailer block of previous
-				   segment.  */
-    long unknown5;
-    long unknown6;
-    long unknown7;
-    long unknown8;
-    long unknown9;
-    long unknown10;
-    long unknown11;
-    long unknown12;
-    long unknown13;
-    long unknown14;
-  };
-
-#endif /* CRAY2 */
-#endif /* not CRAY_STACK */
-
-#ifdef CRAY2
-/* Determine a "stack measure" for an arbitrary ADDRESS.
-   I doubt that "lint" will like this much. */
-
-static long
-i00afunc (long *address)
-{
-  struct stk_stat status;
-  struct stk_trailer *trailer;
-  long *block, size;
-  long result = 0;
-
-  /* We want to iterate through all of the segments.  The first
-     step is to get the stack status structure.  We could do this
-     more quickly and more directly, perhaps, by referencing the
-     $LM00 common block, but I know that this works.  */
-
-  STKSTAT (&status);
-
-  /* Set up the iteration.  */
-
-  trailer = (struct stk_trailer *) (status.current_address
-				    + status.current_size
-				    - 15);
-
-  /* There must be at least one stack segment.  Therefore it is
-     a fatal error if "trailer" is null.  */
-
-  if (trailer == 0)
-    abort ();
-
-  /* Discard segments that do not contain our argument address.  */
-
-  while (trailer != 0)
-    {
-      block = (long *) trailer->this_address;
-      size = trailer->this_size;
-      if (block == 0 || size == 0)
-	abort ();
-      trailer = (struct stk_trailer *) trailer->link;
-      if ((block <= address) && (address < (block + size)))
-	break;
-    }
-
-  /* Set the result to the offset in this segment and add the sizes
-     of all predecessor segments.  */
-
-  result = address - block;
-
-  if (trailer == 0)
-    {
-      return result;
-    }
-
-  do
-    {
-      if (trailer->this_size <= 0)
-	abort ();
-      result += trailer->this_size;
-      trailer = (struct stk_trailer *) trailer->link;
-    }
-  while (trailer != 0);
-
-  /* We are done.  Note that if you present a bogus address (one
-     not in any segment), you will get a different number back, formed
-     from subtracting the address of the first block.  This is probably
-     not what you want.  */
-
-  return (result);
-}
-
-#else /* not CRAY2 */
-/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
-   Determine the number of the cell within the stack,
-   given the address of the cell.  The purpose of this
-   routine is to linearize, in some sense, stack addresses
-   for alloca.  */
-
-static long
-i00afunc (long address)
-{
-  long stkl = 0;
-
-  long size, pseg, this_segment, stack;
-  long result = 0;
-
-  struct stack_segment_linkage *ssptr;
-
-  /* Register B67 contains the address of the end of the
-     current stack segment.  If you (as a subprogram) store
-     your registers on the stack and find that you are past
-     the contents of B67, you have overflowed the segment.
-
-     B67 also points to the stack segment linkage control
-     area, which is what we are really interested in.  */
-
-  stkl = CRAY_STACKSEG_END ();
-  ssptr = (struct stack_segment_linkage *) stkl;
-
-  /* If one subtracts 'size' from the end of the segment,
-     one has the address of the first word of the segment.
-
-     If this is not the first segment, 'pseg' will be
-     nonzero.  */
-
-  pseg = ssptr->sspseg;
-  size = ssptr->sssize;
-
-  this_segment = stkl - size;
-
-  /* It is possible that calling this routine itself caused
-     a stack overflow.  Discard stack segments which do not
-     contain the target address.  */
-
-  while (!(this_segment <= address && address <= stkl))
-    {
-#ifdef DEBUG_I00AFUNC
-      fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
-#endif
-      if (pseg == 0)
-	break;
-      stkl = stkl - pseg;
-      ssptr = (struct stack_segment_linkage *) stkl;
-      size = ssptr->sssize;
-      pseg = ssptr->sspseg;
-      this_segment = stkl - size;
-    }
-
-  result = address - this_segment;
-
-  /* If you subtract pseg from the current end of the stack,
-     you get the address of the previous stack segment's end.
-     This seems a little convoluted to me, but I'll bet you save
-     a cycle somewhere.  */
-
-  while (pseg != 0)
-    {
-#ifdef DEBUG_I00AFUNC
-      fprintf (stderr, "%011o %011o\n", pseg, size);
-#endif
-      stkl = stkl - pseg;
-      ssptr = (struct stack_segment_linkage *) stkl;
-      size = ssptr->sssize;
-      pseg = ssptr->sspseg;
-      result += size;
-    }
-  return (result);
-}
-
-#endif /* not CRAY2 */
-#endif /* CRAY */
-
-#endif /* no alloca */
-#endif /* not GCC version 2 */
diff --git a/contrib/amd/libamu/amu.h b/contrib/amd/libamu/amu.h
index a22371e..1e7834a 100644
--- a/contrib/amd/libamu/amu.h
+++ b/contrib/amd/libamu/amu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: amu.h,v 1.2 1999/01/10 21:54:36 ezk Exp $
+ * File: am-utils/libamu/amu.h
  *
  */
 
@@ -75,4 +74,6 @@ extern amq_mount_info_list *amqproc_getmntfs_1(voidp argp, CLIENT *rqstp);
 extern int *amqproc_mount_1(voidp argp, CLIENT *rqstp);
 extern amq_string *amqproc_getvers_1(voidp argp, CLIENT *rqstp);
 
+extern long get_server_pid(void);
+
 #endif /* not _AMU_H */
diff --git a/contrib/amd/libamu/clnt_sperrno.c b/contrib/amd/libamu/clnt_sperrno.c
deleted file mode 100644
index d3b48d1..0000000
--- a/contrib/amd/libamu/clnt_sperrno.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 1997-1998 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.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry at Imperial College, London.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by the University of
- *      California, Berkeley and its contributors.
- * 4. 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.
- *
- * 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.
- *
- *      %W% (Berkeley) %G%
- *
- * $Id: clnt_sperrno.c,v 5.2.2.1 1992/02/09 15:08:40 jsp beta $
- *
- */
-
-/*
- * Early RPC seems to be missing these..
- * Extracted from the RPC 3.9 sources as indicated
- */
-
-/* @(#)clnt_perror.c    1.1 87/11/04 3.9 RPCSRC */
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part.  Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California  94043
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-#include <am_defs.h>
-#include <amu.h>
-
-
-struct rpc_errtab {
-  enum clnt_stat status;
-  char *message;
-};
-
-static struct rpc_errtab rpc_errlist[] =
-{
-  {RPC_SUCCESS,
-   "RPC: Success"},
-  {RPC_CANTENCODEARGS,
-   "RPC: Can't encode arguments"},
-  {RPC_CANTDECODERES,
-   "RPC: Can't decode result"},
-  {RPC_CANTSEND,
-   "RPC: Unable to send"},
-  {RPC_CANTRECV,
-   "RPC: Unable to receive"},
-  {RPC_TIMEDOUT,
-   "RPC: Timed out"},
-  {RPC_VERSMISMATCH,
-   "RPC: Incompatible versions of RPC"},
-  {RPC_AUTHERROR,
-   "RPC: Authentication error"},
-  {RPC_PROGUNAVAIL,
-   "RPC: Program unavailable"},
-  {RPC_PROGVERSMISMATCH,
-   "RPC: Program/version mismatch"},
-  {RPC_PROCUNAVAIL,
-   "RPC: Procedure unavailable"},
-  {RPC_CANTDECODEARGS,
-   "RPC: Server can't decode arguments"},
-  {RPC_SYSTEMERROR,
-   "RPC: Remote system error"},
-  {RPC_UNKNOWNHOST,
-   "RPC: Unknown host"},
-/*      { RPC_UNKNOWNPROTO,
- * "RPC: Unknown protocol" }, */
-  {RPC_PMAPFAILURE,
-   "RPC: Port mapper failure"},
-  {RPC_PROGNOTREGISTERED,
-   "RPC: Program not registered"},
-  {RPC_FAILED,
-   "RPC: Failed (unspecified error)"}
-};
-
-
-/*
- * This interface for use by clntrpc
- */
-char *
-clnt_sperrno(enum clnt_stat stat)
-{
-  int i;
-
-  for (i = 0; i < sizeof(rpc_errlist) / sizeof(struct rpc_errtab); i++) {
-    if (rpc_errlist[i].status == stat) {
-      return (rpc_errlist[i].message);
-    }
-  }
-  return ("RPC: (unknown error code)");
-}
diff --git a/contrib/amd/libamu/hasmntopt.c b/contrib/amd/libamu/hasmntopt.c
index 5f19e71..14cceb5 100644
--- a/contrib/amd/libamu/hasmntopt.c
+++ b/contrib/amd/libamu/hasmntopt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@ n * modification, are permitted provided that the following conditions
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: hasmntopt.c,v 1.2 1999/01/10 21:54:37 ezk Exp $
+ * File: am-utils/libamu/hasmntopt.c
  *
  */
 
@@ -49,7 +48,7 @@ n * modification, are permitted provided that the following conditions
 #include <amu.h>
 
 #ifndef MNTMAXSTR
-# define MNTMAXSTR	128
+# define MNTMAXSTR	256
 #endif /* not MNTMAXSTR */
 
 
@@ -59,7 +58,6 @@ n * modification, are permitted provided that the following conditions
  *
  * From: Piete Brooks <pb@cl.cam.ac.uk>
  */
-
 static char *
 nextmntopt(char **p)
 {
@@ -69,7 +67,7 @@ nextmntopt(char **p)
   /*
    * Skip past white space
    */
-  while (*cp && isspace(*cp))
+  while (*cp && isspace((int) *cp))
     cp++;
 
   /*
@@ -98,18 +96,19 @@ nextmntopt(char **p)
   return rp;
 }
 
+
 /*
  * replacement for hasmntopt if the system does not have it.
  */
 char *
-hasmntopt(mntent_t *mnt, char *opt)
+amu_hasmntopt(mntent_t *mnt, char *opt)
 {
   char t[MNTMAXSTR];
   char *f;
   char *o = t;
   int l = strlen(opt);
 
-  strcpy(t, mnt->mnt_opts);
+  xstrlcpy(t, mnt->mnt_opts, sizeof(t));
 
   while (*(f = nextmntopt(&o)))
     if (NSTREQ(opt, f, l))
diff --git a/contrib/amd/libamu/misc_rpc.c b/contrib/amd/libamu/misc_rpc.c
index fa402c3..de0a920 100644
--- a/contrib/amd/libamu/misc_rpc.c
+++ b/contrib/amd/libamu/misc_rpc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: misc_rpc.c,v 1.2 1999/01/10 21:54:37 ezk Exp $
+ * File: am-utils/libamu/misc_rpc.c
  *
  */
 
@@ -93,7 +92,7 @@ pickup_rpc_reply(voidp pkt, int len, voidp where, XDRPROC_T_TYPE where_xdr)
   memset((voidp) &reply_msg, 0, sizeof(reply_msg));
   memset((voidp) &reply_xdr, 0, sizeof(reply_xdr));
 
-  reply_msg.acpted_rply.ar_results.where = (caddr_t) where;
+  reply_msg.acpted_rply.ar_results.where = where;
   reply_msg.acpted_rply.ar_results.proc = where_xdr;
 
   xdrmem_create(&reply_xdr, pkt, len, XDR_DECODE);
@@ -127,6 +126,13 @@ make_rpc_packet(char *buf, int buflen, u_long proc, struct rpc_msg *mp, voidp ar
 {
   XDR msg_xdr;
   int len;
+  /*
+   * Never cast pointers between different integer types, it breaks badly
+   * on big-endian platforms if those types have different sizes.
+   *
+   * Cast to a local variable instead, and use that variable's address.
+   */
+  enum_t local_proc = (enum_t) proc;
 
   xdrmem_create(&msg_xdr, buf, buflen, XDR_ENCODE);
 
@@ -139,7 +145,7 @@ make_rpc_packet(char *buf, int buflen, u_long proc, struct rpc_msg *mp, voidp ar
   /*
    * Called procedure number
    */
-  if (!xdr_enum(&msg_xdr, (enum_t *) & proc))
+  if (!xdr_enum(&msg_xdr, &local_proc))
     return -EIO;
 
   /*
@@ -166,3 +172,39 @@ make_rpc_packet(char *buf, int buflen, u_long proc, struct rpc_msg *mp, voidp ar
 
   return len;
 }
+
+
+/* get uid/gid from RPC credentials */
+int
+getcreds(struct svc_req *rp, uid_t *u, gid_t *g, SVCXPRT *nfsxprt)
+{
+  struct authunix_parms *aup = (struct authunix_parms *) NULL;
+#ifdef HAVE_RPC_AUTH_DES_H
+  struct authdes_cred *adp;
+#endif /* HAVE_RPC_AUTH_DES_H */
+
+  switch (rp->rq_cred.oa_flavor) {
+
+  case AUTH_UNIX:
+    aup = (struct authunix_parms *) rp->rq_clntcred;
+    *u = aup->aup_uid;
+    *g = aup->aup_gid;
+    break;
+
+#ifdef HAVE_RPC_AUTH_DES_H
+  case AUTH_DES:
+    adp = (struct authdes_cred *) rp->rq_clntcred;
+    *g = INVALIDID;		/* some unknown group id */
+    if (sscanf(adp->adc_fullname.name, "unix.%lu@", (u_long *) u) == 1)
+        break;
+    /* fall through */
+#endif /* HAVE_RPC_AUTH_DES_H */
+
+  default:
+    *u = *g = INVALIDID;	/* just in case */
+    svcerr_weakauth(nfsxprt);
+    return -1;
+  }
+
+  return 0;			/* everything is ok */
+}
diff --git a/contrib/amd/libamu/mount_fs.c b/contrib/amd/libamu/mount_fs.c
index 73c7623..74f064e 100644
--- a/contrib/amd/libamu/mount_fs.c
+++ b/contrib/amd/libamu/mount_fs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: mount_fs.c,v 1.8 1999/09/18 08:38:06 ezk Exp $
- * $FreeBSD: src/contrib/amd/libamu/mount_fs.c,v 1.4 1999/09/23 05:36:01 obrien Exp $
- * $DragonFly: src/contrib/amd/libamu/mount_fs.c,v 1.2 2003/06/17 04:23:57 dillon Exp $
+ * File: am-utils/libamu/mount_fs.c
  *
  */
 
@@ -52,9 +49,10 @@
 
 
 /* ensure that mount table options are delimited by a comma */
-#define append_opts(old, new) { \
-	if (*(old) != '\0') strcat(old, ","); \
-	strcat(old, new); }
+#define append_opts(old, l, new) { \
+	if (*(old) != '\0') \
+	  xstrlcat(old, ",", l); \
+	xstrlcat(old, new, l); }
 
 /*
  * Standard mount flags
@@ -107,6 +105,13 @@ struct opt_tab mnt_flags[] =
   {MNTTAB_OPT_OVERLAY, MNT2_GEN_OPT_OVERLAY},
 #endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
 
+  /*
+   * Do not define MNT2_NFS_OPT_* entries here!  This is for generic
+   * mount(2) options only, not for NFS mount options.  If you need to put
+   * something here, it's probably not the right place: see
+   * include/am_compat.h.
+   */
+
   {0, 0}
 };
 
@@ -116,33 +121,20 @@ int
 compute_mount_flags(mntent_t *mntp)
 {
   struct opt_tab *opt;
-  int flags;
+  int flags = 0;
 
-  /* start: this must come first */
 #ifdef MNT2_GEN_OPT_NEWTYPE
-  flags = MNT2_GEN_OPT_NEWTYPE;
-#else /* not MNT2_GEN_OPT_NEWTYPE */
-  /* Not all machines have MNT2_GEN_OPT_NEWTYPE (HP-UX 9.01) */
-  flags = 0;
-#endif /* not MNT2_GEN_OPT_NEWTYPE */
-
-#if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
-  /*
-   * Overlay this amd mount (presumably on another amd which died
-   * before and left the machine hung).  This will allow a new amd or
-   * hlfsd to be remounted on top of another one.
-   */
-  if (hasmntopt(mntp, MNTTAB_OPT_OVERLAY)) {
-    flags |= MNT2_GEN_OPT_OVERLAY;
-    plog(XLOG_INFO, "using an overlay mount");
-  }
-#endif /* defined(MNT2_GEN_OVERLAY) && defined(MNTOPT_OVERLAY) */
+  flags |= MNT2_GEN_OPT_NEWTYPE;
+#endif /* MNT2_GEN_OPT_NEWTYPE */
+#ifdef MNT2_GEN_OPT_AUTOMOUNTED
+  flags |= MNT2_GEN_OPT_AUTOMOUNTED;
+#endif /* not MNT2_GEN_OPT_AUTOMOUNTED */
 
   /*
    * Crack basic mount options
    */
   for (opt = mnt_flags; opt->opt; opt++) {
-    flags |= hasmntopt(mntp, opt->opt) ? opt->flag : 0;
+    flags |= amu_hasmntopt(mntp, opt->opt) ? opt->flag : 0;
   }
 
   return flags;
@@ -167,35 +159,33 @@ compute_automounter_mount_flags(mntent_t *mntp)
 
 
 int
-mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto, const char *mnttabname)
+mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto, const char *mnttabname, int on_autofs)
 {
   int error = 0;
 #ifdef MOUNT_TABLE_ON_FILE
-# ifdef MNTTAB_OPT_DEV
-  struct stat stb;
-# endif /* MNTTAB_OPT_DEV */
   char *zopts = NULL, *xopts = NULL;
-# if defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO)
-  char optsbuf[48];
-# endif /* defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO) */
+  size_t l;
 #endif /* MOUNT_TABLE_ON_FILE */
-#ifdef DEBUG
-  char buf[80];			/* buffer for sprintf */
-#endif /* DEBUG */
+  char *mnt_dir = 0;
+
+#ifdef NEED_AUTOFS_SPACE_HACK
+  char *old_mnt_dir = 0;
+  /* perform space hack */
+  if (on_autofs) {
+    old_mnt_dir = mnt->mnt_dir;
+    mnt->mnt_dir = mnt_dir = autofs_strdup_space_hack(old_mnt_dir);
+  } else
+#endif /* NEED_AUTOFS_SPACE_HACK */
+    mnt_dir = strdup(mnt->mnt_dir);
 
-#ifdef DEBUG
-  sprintf(buf, "%s%s%s",
-	  "%s fstype ", MTYPE_PRINTF_TYPE, " (%s) flags %#x (%s)");
-  dlog(buf, mnt->mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
-#endif /* DEBUG */
+  dlog("'%s' fstype " MTYPE_PRINTF_TYPE " (%s) flags %#x (%s)",
+       mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
 
 again:
-  clock_valid = 0;
-
   error = MOUNT_TRAP(type, mnt, flags, mnt_data);
 
   if (error < 0) {
-    plog(XLOG_ERROR, "%s: mount: %m", mnt->mnt_dir);
+    plog(XLOG_ERROR, "'%s': mount: %m", mnt_dir);
     /*
      * The following code handles conditions which shouldn't
      * occur.  They are possible either because amd screws up
@@ -203,33 +193,18 @@ again:
      * messed with the mount point.  Both have been known to
      * happen. -- stolcke 2/22/95
      */
-    if (errno == ENOENT) {
-      /*
-       * Occasionally the mount point vanishes, probably
-       * due to some race condition.  Just recreate it
-       * as necessary.
-       */
-      errno = mkdirs(mnt->mnt_dir, 0555);
-      if (errno != 0 && errno != EEXIST)
-	plog(XLOG_ERROR, "%s: mkdirs: %m", mnt->mnt_dir);
-      else {
-	plog(XLOG_WARNING, "extra mkdirs required for %s",
-	     mnt->mnt_dir);
-	error = MOUNT_TRAP(type, mnt, flags, mnt_data);
-      }
-    } else if (errno == EBUSY) {
+    if (errno == EBUSY) {
       /*
        * Also, sometimes unmount isn't called, e.g., because
        * our mountlist is garbled.  This leaves old mount
        * points around which need to be removed before we
        * can mount something new in their place.
        */
-      errno = umount_fs(mnt->mnt_dir, mnttabname);
+      errno = umount_fs(mnt_dir, mnttabname, on_autofs);
       if (errno != 0)
-	plog(XLOG_ERROR, "%s: umount: %m", mnt->mnt_dir);
+	plog(XLOG_ERROR, "'%s': umount: %m", mnt_dir);
       else {
-	plog(XLOG_WARNING, "extra umount required for %s",
-	     mnt->mnt_dir);
+	plog(XLOG_WARNING, "extra umount required for '%s'", mnt_dir);
 	error = MOUNT_TRAP(type, mnt, flags, mnt_data);
       }
     }
@@ -239,8 +214,16 @@ again:
     sleep(1);
     goto again;
   }
+
+#ifdef NEED_AUTOFS_SPACE_HACK
+  /* Undo space hack */
+  if (on_autofs)
+    mnt->mnt_dir = old_mnt_dir;
+#endif /* NEED_AUTOFS_SPACE_HACK */
+
   if (error < 0) {
-    return errno;
+    error = errno;
+    goto out;
   }
 
 #ifdef MOUNT_TABLE_ON_FILE
@@ -248,23 +231,28 @@ again:
    * Allocate memory for options:
    *        dev=..., vers={2,3}, proto={tcp,udp}
    */
-  zopts = (char *) xmalloc(strlen(mnt->mnt_opts) + 48);
+  l = strlen(mnt->mnt_opts) + 48;
+  zopts = (char *) xmalloc(l);
 
   /* copy standard options */
   xopts = mnt->mnt_opts;
 
-  strcpy(zopts, xopts);
+  xstrlcpy(zopts, xopts, l);
 
 # ifdef MNTTAB_OPT_DEV
-  /* add the extra dev= field to the mount table */
-  if (lstat(mnt->mnt_dir, &stb) == 0) {
-    if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */
-      sprintf(optsbuf, "%s=%04lx",
-	      MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff);
-    else			/* e.g. System Vr4 */
-      sprintf(optsbuf, "%s=%08lx",
-	      MNTTAB_OPT_DEV, (u_long) stb.st_dev);
-    append_opts(zopts, optsbuf);
+  {
+    /* add the extra dev= field to the mount table */
+    struct stat stb;
+    if (lstat(mnt_dir, &stb) == 0) {
+      char optsbuf[48];
+      if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */
+	xsnprintf(optsbuf, sizeof(optsbuf), "%s=%04lx",
+		  MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff);
+      else			/* e.g. System Vr4 */
+	xsnprintf(optsbuf, sizeof(optsbuf), "%s=%08lx",
+		  MNTTAB_OPT_DEV, (u_long) stb.st_dev);
+      append_opts(zopts, l, optsbuf);
+    }
   }
 # endif /* MNTTAB_OPT_DEV */
 
@@ -275,8 +263,10 @@ again:
    */
    if (nfs_version == NFS_VERSION3 &&
        hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) {
-     sprintf(optsbuf, "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3);
-     append_opts(zopts, optsbuf);
+     char optsbuf[48];
+     xsnprintf(optsbuf, sizeof(optsbuf),
+	       "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3);
+     append_opts(zopts, l, optsbuf);
    }
 # endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */
 
@@ -285,9 +275,10 @@ again:
    * add the extra proto={tcp,udp} field to the mount table,
    * unless already specified by user.
    */
-  if (nfs_proto && !hasmntopt(mnt, MNTTAB_OPT_PROTO)) {
-    sprintf(optsbuf, "%s=%s", MNTTAB_OPT_PROTO, nfs_proto);
-    append_opts(zopts, optsbuf);
+  if (nfs_proto && !amu_hasmntopt(mnt, MNTTAB_OPT_PROTO)) {
+    char optsbuf[48];
+    xsnprintf(optsbuf, sizeof(optsbuf), "%s=%s", MNTTAB_OPT_PROTO, nfs_proto);
+    append_opts(zopts, l, optsbuf);
   }
 # endif /* MNTTAB_OPT_PROTO */
 
@@ -298,25 +289,26 @@ again:
    * Additional fields in mntent_t
    * are fixed up here
    */
-# ifdef HAVE_FIELD_MNTENT_T_MNT_CNODE
+# ifdef HAVE_MNTENT_T_MNT_CNODE
   mnt->mnt_cnode = 0;
-# endif /* HAVE_FIELD_MNTENT_T_MNT_CNODE */
+# endif /* HAVE_MNTENT_T_MNT_CNODE */
 
-# ifdef HAVE_FIELD_MNTENT_T_MNT_RO
-  mnt->mnt_ro = (hasmntopt(mnt, MNTTAB_OPT_RO) != NULL);
-# endif /* HAVE_FIELD_MNTENT_T_MNT_RO */
+# ifdef HAVE_MNTENT_T_MNT_RO
+  mnt->mnt_ro = (amu_hasmntopt(mnt, MNTTAB_OPT_RO) != NULL);
+# endif /* HAVE_MNTENT_T_MNT_RO */
 
-# ifdef HAVE_FIELD_MNTENT_T_MNT_TIME
-#  ifdef HAVE_FIELD_MNTENT_T_MNT_TIME_STRING
+# ifdef HAVE_MNTENT_T_MNT_TIME
+#  ifdef HAVE_MNTENT_T_MNT_TIME_STRING
   {				/* allocate enough space for a long */
-    char *str = (char *) xmalloc(13 * sizeof(char));
-    sprintf(str, "%ld", time((time_t *) NULL));
+    size_t l = 13 * sizeof(char);
+    char *str = (char *) xmalloc(l);
+    xsnprintf(str, l, "%ld", time((time_t *) NULL));
     mnt->mnt_time = str;
   }
-#  else /* not HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
+#  else /* not HAVE_MNTENT_T_MNT_TIME_STRING */
   mnt->mnt_time = time((time_t *) NULL);
-#  endif /* not HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
-# endif /* HAVE_FIELD_MNTENT_T_MNT_TIME */
+#  endif /* not HAVE_MNTENT_T_MNT_TIME_STRING */
+# endif /* HAVE_MNTENT_T_MNT_TIME */
 
   write_mntent(mnt, mnttabname);
 
@@ -328,7 +320,126 @@ again:
 # endif /* MNTTAB_OPT_DEV */
 #endif /* MOUNT_TABLE_ON_FILE */
 
-  return 0;
+ out:
+  XFREE(mnt_dir);
+  return error;
+}
+
+
+/*
+ * Compute all NFS attribute cache related flags separately.  Note that this
+ * function now computes attribute-cache flags for both Amd's automount
+ * points (NFS) as well as any normal NFS mount that Amd performs.  Edit
+ * with caution.
+ */
+static void
+compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp)
+{
+  int acval = 0;
+  int err_acval = 1;		/* 1 means we found no 'actimeo' value */
+#if defined(HAVE_NFS_ARGS_T_ACREGMIN) || defined(HAVE_NFS_ARGS_T_ACREGMAX) || defined(HAVE_NFS_ARGS_T_ACDIRMIN) || defined(HAVE_NFS_ARGS_T_ACDIRMAX)
+  int err_acrdmm;		/* for ac{reg,dir}{min,max} */
+#endif /* HAVE_NFS_ARGS_T_AC{REG,DIR}{MIN,MAX} */
+
+  /************************************************************************/
+  /***	ATTRIBUTE CACHES						***/
+  /************************************************************************/
+  /*
+   * acval is set to 0 at the top of the function.  If actimeo mount option
+   * exists and defined in mntopts, then its acval is set to it.
+   * If the value is non-zero, then we set all attribute cache fields to it.
+   * If acval is zero, it means it was never defined in mntopts or the
+   * actimeo mount option does not exist, in which case we check for
+   * individual mount options per attribute cache.
+   * Regardless of the value of acval, mount flags are set based directly
+   * on the values of the attribute caches.
+   */
+#ifdef MNTTAB_OPT_ACTIMEO
+  err_acval = hasmntvalerr(mntp, MNTTAB_OPT_ACTIMEO, &acval);	/* attr cache timeout (sec) */
+#endif /* MNTTAB_OPT_ACTIMEO */
+
+  /*** acregmin ***/
+#ifdef HAVE_NFS_ARGS_T_ACREGMIN
+  err_acrdmm = 1;		/* 1 means we found no acregmin value */
+  if (!err_acval) {
+    nap->acregmin = acval;	/* min ac timeout for reg files (sec) */
+  } else {
+# ifdef MNTTAB_OPT_ACREGMIN
+    err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMIN, (int *) &nap->acregmin);
+# else /* not MNTTAB_OPT_ACREGMIN */
+    nap->acregmin = 0;
+# endif /* not MNTTAB_OPT_ACREGMIN */
+  }
+  /* set this flag iff we changed acregmin (possibly to zero) */
+# ifdef MNT2_NFS_OPT_ACREGMIN
+  if (!err_acval || !err_acrdmm)
+    nap->flags |= MNT2_NFS_OPT_ACREGMIN;
+# endif /* MNT2_NFS_OPT_ACREGMIN */
+#endif /* HAVE_NFS_ARGS_T_ACREGMIN */
+
+  /*** acregmax ***/
+#ifdef HAVE_NFS_ARGS_T_ACREGMAX
+  err_acrdmm = 1;		/* 1 means we found no acregmax value */
+  if (!err_acval) {
+    nap->acregmax = acval;	/* max ac timeout for reg files (sec) */
+  } else {
+# ifdef MNTTAB_OPT_ACREGMAX
+    err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMAX, (int *) &nap->acregmax);
+# else /* not MNTTAB_OPT_ACREGMAX */
+    nap->acregmax = 0;
+# endif /* not MNTTAB_OPT_ACREGMAX */
+  }
+  /* set this flag iff we changed acregmax (possibly to zero) */
+# ifdef MNT2_NFS_OPT_ACREGMAX
+  if (!err_acval || !err_acrdmm)
+    nap->flags |= MNT2_NFS_OPT_ACREGMAX;
+# endif /* MNT2_NFS_OPT_ACREGMAX */
+#endif /* HAVE_NFS_ARGS_T_ACREGMAX */
+
+  /*** acdirmin ***/
+#ifdef HAVE_NFS_ARGS_T_ACDIRMIN
+  err_acrdmm = 1;		/* 1 means we found no acdirmin value */
+  if (!err_acval) {
+    nap->acdirmin = acval;	/* min ac timeout for dirs (sec) */
+  } else {
+# ifdef MNTTAB_OPT_ACDIRMIN
+    err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, (int *) &nap->acdirmin);
+# else /* not MNTTAB_OPT_ACDIRMIN */
+    nap->acdirmin = 0;
+# endif /* not MNTTAB_OPT_ACDIRMIN */
+  }
+  /* set this flag iff we changed acdirmin (possibly to zero) */
+# ifdef MNT2_NFS_OPT_ACDIRMIN
+  if (!err_acval || !err_acrdmm)
+    nap->flags |= MNT2_NFS_OPT_ACDIRMIN;
+# endif /* MNT2_NFS_OPT_ACDIRMIN */
+#endif /* HAVE_NFS_ARGS_T_ACDIRMIN */
+
+  /*** acdirmax ***/
+#ifdef HAVE_NFS_ARGS_T_ACDIRMAX
+  err_acrdmm = 1;		/* 1 means we found no acdirmax value */
+  if (!err_acval) {
+    nap->acdirmax = acval;	/* max ac timeout for dirs (sec) */
+  } else {
+# ifdef MNTTAB_OPT_ACDIRMAX
+    err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, (int *) &nap->acdirmax);
+# else /* not MNTTAB_OPT_ACDIRMAX */
+    nap->acdirmax = 0;
+# endif /* not MNTTAB_OPT_ACDIRMAX */
+  }
+  /* set this flag iff we changed acdirmax (possibly to zero) */
+# ifdef MNT2_NFS_OPT_ACDIRMAX
+  if (!err_acval || !err_acrdmm)
+    nap->flags |= MNT2_NFS_OPT_ACDIRMAX;
+# endif /* MNT2_NFS_OPT_ACDIRMAX */
+#endif /* HAVE_NFS_ARGS_T_ACDIRMAX */
+
+
+  /* don't cache attributes */
+#if defined(MNTTAB_OPT_NOAC) && defined(MNT2_NFS_OPT_NOAC)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOAC) != NULL)
+    nap->flags |= MNT2_NFS_OPT_NOAC;
+#endif /* defined(MNTTAB_OPT_NOAC) && defined(MNT2_NFS_OPT_NOAC) */
 }
 
 
@@ -347,140 +458,82 @@ again:
  * fs_name:	remote file system name to mount
  */
 void
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct netconfig *nfsncp, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name)
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
-compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name)
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+compute_nfs_args(nfs_args_t *nap,
+		 mntent_t *mntp,
+		 int genflags,
+		 struct netconfig *nfsncp,
+		 struct sockaddr_in *ip_addr,
+		 u_long nfs_version,
+		 char *nfs_proto,
+		 am_nfs_handle_t *fhp,
+		 char *host_name,
+		 char *fs_name)
 {
-  int acval = 0;
-#ifdef HAVE_FS_NFS3
-  static am_nfs_fh3 fh3;	/* static, b/c gcc on aix corrupts stack */
-#endif /* HAVE_FS_NFS3 */
-
   /* initialize just in case */
   memset((voidp) nap, 0, sizeof(nfs_args_t));
 
+  /* compute all of the NFS attribute-cache flags */
+  compute_nfs_attrcache_flags(nap, mntp);
+
   /************************************************************************/
   /***	FILEHANDLE DATA AND LENGTH					***/
   /************************************************************************/
 #ifdef HAVE_FS_NFS3
   if (nfs_version == NFS_VERSION3) {
-    memset((voidp) &fh3, 0, sizeof(am_nfs_fh3));
-    fh3.fh3_length = fhp->v3.mountres3_u.mountinfo.fhandle.fhandle3_len;
-    memmove(fh3.fh3_u.data,
-	    fhp->v3.mountres3_u.mountinfo.fhandle.fhandle3_val,
-	    fh3.fh3_length);
-
-# if defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN)
+# if defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN)
     /*
      * Some systems (Irix/bsdi3) have a separate field in nfs_args for
      * the length of the file handle for NFS V3.  They insist that
      * the file handle set in nfs_args be plain bytes, and not
      * include the length field.
      */
-    NFS_FH_DREF(nap->NFS_FH_FIELD, &(fh3.fh3_u.data));
-# else /* not defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN) */
-    NFS_FH_DREF(nap->NFS_FH_FIELD, &fh3);
-# endif /* not defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN) */
+    NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3.am_fh3_data);
+# else /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
+    NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3);
+# endif /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
 # ifdef MNT2_NFS_OPT_NFSV3
     nap->flags |= MNT2_NFS_OPT_NFSV3;
 # endif /* MNT2_NFS_OPT_NFSV3 */
+# ifdef MNT2_NFS_OPT_VER3
+    nap->flags |= MNT2_NFS_OPT_VER3;
+# endif /* MNT2_NFS_OPT_VER3 */
   } else
 #endif /* HAVE_FS_NFS3 */
-    NFS_FH_DREF(nap->NFS_FH_FIELD, &(fhp->v2.fhs_fh));
+    NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v2);
 
-#ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
+#ifdef HAVE_NFS_ARGS_T_FHSIZE
 # ifdef HAVE_FS_NFS3
   if (nfs_version == NFS_VERSION3)
-    nap->fhsize = fh3.fh3_length;
+    nap->fhsize = fhp->v3.am_fh3_length;
   else
 # endif /* HAVE_FS_NFS3 */
     nap->fhsize = FHSIZE;
-#endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
+#endif /* HAVE_NFS_ARGS_T_FHSIZE */
 
   /* this is the version of the nfs_args structure, not of NFS! */
-#ifdef HAVE_FIELD_NFS_ARGS_T_FH_LEN
+#ifdef HAVE_NFS_ARGS_T_FH_LEN
 # ifdef HAVE_FS_NFS3
   if (nfs_version == NFS_VERSION3)
-    nap->fh_len = fh3.fh3_length;
+    nap->fh_len = fhp->v3.am_fh3_length;
   else
 # endif /* HAVE_FS_NFS3 */
     nap->fh_len = FHSIZE;
-#endif /* HAVE_FIELD_NFS_ARGS_T_FH_LEN */
+#endif /* HAVE_NFS_ARGS_T_FH_LEN */
 
   /************************************************************************/
   /***	HOST NAME							***/
   /************************************************************************/
+  /*
+   * XXX: warning, using xstrlcpy in NFS_HN_DREF, which may corrupt a
+   * struct nfs_args, or truncate our concocted "hostname:/path"
+   * string prematurely.
+   */
   NFS_HN_DREF(nap->hostname, host_name);
 #ifdef MNT2_NFS_OPT_HOSTNAME
   nap->flags |= MNT2_NFS_OPT_HOSTNAME;
 #endif /* MNT2_NFS_OPT_HOSTNAME */
 
   /************************************************************************/
-  /***	ATTRIBUTE CACHES						***/
-  /************************************************************************/
-  /*
-   * acval is set to 0 at the top of the function.  If actimeo mount option
-   * exists and defined in mntopts, then it acval is set to it.
-   * If the value is non-zero, then we set all attribute cache fields to it.
-   * If acval is zero, it means it was never defined in mntopts or the
-   * actimeo mount option does not exist, in which case we check for
-   * individual mount options per attribute cache.
-   * Regardless of the value of acval, mount flags are set based directly
-   * on the values of the attribute caches.
-   */
-#ifdef MNTTAB_OPT_ACTIMEO
-  acval = hasmntval(mntp, MNTTAB_OPT_ACTIMEO); /* attr cache timeout (sec) */
-#endif /* MNTTAB_OPT_ACTIMEO */
-
-  if (acval) {
-#ifdef HAVE_FIELD_NFS_ARGS_T_ACREGMIN
-    nap->acregmin = acval;	/* min ac timeout for reg files (sec) */
-    nap->acregmax = acval;	/* max ac timeout for reg files (sec) */
-#endif /* HAVE_FIELD_NFS_ARGS_T_ACREGMIN */
-#ifdef HAVE_FIELD_NFS_ARGS_T_ACDIRMIN
-    nap->acdirmin = acval;	/* min ac timeout for dirs (sec) */
-    nap->acdirmax = acval;	/* max ac timeout for dirs (sec) */
-#endif /* HAVE_FIELD_NFS_ARGS_T_ACDIRMIN */
-  } else {
-#ifdef MNTTAB_OPT_ACREGMIN
-    nap->acregmin = hasmntval(mntp, MNTTAB_OPT_ACREGMIN);
-#endif /* MNTTAB_OPT_ACREGMIN */
-#ifdef MNTTAB_OPT_ACREGMAX
-    nap->acregmax = hasmntval(mntp, MNTTAB_OPT_ACREGMAX);
-#endif /* MNTTAB_OPT_ACREGMAX */
-#ifdef MNTTAB_OPT_ACDIRMIN
-    nap->acdirmin = hasmntval(mntp, MNTTAB_OPT_ACDIRMIN);
-#endif /* MNTTAB_OPT_ACDIRMIN */
-#ifdef MNTTAB_OPT_ACDIRMAX
-    nap->acdirmax = hasmntval(mntp, MNTTAB_OPT_ACDIRMAX);
-#endif /* MNTTAB_OPT_ACDIRMAX */
-  } /* end of "if (acval)" statement */
-
-#ifdef MNT2_NFS_OPT_ACREGMIN
-  if (nap->acregmin)
-    nap->flags |= MNT2_NFS_OPT_ACREGMIN;
-#endif /* MNT2_NFS_OPT_ACREGMIN */
-#ifdef MNT2_NFS_OPT_ACREGMAX
-  if (nap->acregmax)
-    nap->flags |= MNT2_NFS_OPT_ACREGMAX;
-#endif /* MNT2_NFS_OPT_ACREGMAX */
-#ifdef MNT2_NFS_OPT_ACDIRMIN
-  if (nap->acdirmin)
-    nap->flags |= MNT2_NFS_OPT_ACDIRMIN;
-#endif /* MNT2_NFS_OPT_ACDIRMIN */
-#ifdef MNT2_NFS_OPT_ACDIRMAX
-  if (nap->acdirmax)
-    nap->flags |= MNT2_NFS_OPT_ACDIRMAX;
-#endif /* MNT2_NFS_OPT_ACDIRMAX */
-
-#ifdef MNTTAB_OPT_NOAC		/* don't cache attributes */
-  if (hasmntopt(mntp, MNTTAB_OPT_NOAC) != NULL)
-    nap->flags |= MNT2_NFS_OPT_NOAC;
-#endif /* MNTTAB_OPT_NOAC */
-
-  /************************************************************************/
   /***	IP ADDRESS OF REMOTE HOST					***/
   /************************************************************************/
   if (ip_addr) {
@@ -498,7 +551,7 @@ compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_
     nap->flags |= MNT2_NFS_OPT_TCP;
 #endif /* MNT2_NFS_OPT_TCP */
 
-#ifdef HAVE_FIELD_NFS_ARGS_T_SOTYPE
+#ifdef HAVE_NFS_ARGS_T_SOTYPE
   /* bsdi3 uses this */
   if (nfs_proto) {
     if (STREQ(nfs_proto, "tcp"))
@@ -506,9 +559,9 @@ compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_
     else if (STREQ(nfs_proto, "udp"))
       nap->sotype = SOCK_DGRAM;
   }
-#endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
+#endif /* HAVE_NFS_ARGS_T_SOTYPE */
 
-#ifdef HAVE_FIELD_NFS_ARGS_T_PROTO
+#ifdef HAVE_NFS_ARGS_T_PROTO
   nap->proto = 0;		/* bsdi3 sets this field to zero  */
 # ifdef IPPROTO_TCP
   if (nfs_proto) {
@@ -518,25 +571,25 @@ compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_
       nap->proto = IPPROTO_UDP;
   }
 # endif /* IPPROTO_TCP */
-#endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
+#endif /* HAVE_NFS_ARGS_T_SOTYPE */
 
-#ifdef HAVE_FIELD_NFS_ARGS_T_VERSION
+#ifdef HAVE_NFS_ARGS_T_VERSION
 # ifdef NFS_ARGSVERSION
   nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */
 # endif /* NFS_ARGSVERSION */
 # ifdef DG_MOUNT_NFS_VERSION
   nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */
 # endif /* DG_MOUNT_NFS_VERSION */
-#endif /* HAVE_FIELD_NFS_ARGS_VERSION */
+#endif /* HAVE_NFS_ARGS_VERSION */
 
   /************************************************************************/
   /***	OTHER NFS SOCKET RELATED OPTIONS AND FLAGS			***/
   /************************************************************************/
 #ifdef MNT2_NFS_OPT_NOCONN
   /* check if user specified to use unconnected or connected sockets */
-  if (hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
     nap->flags |= MNT2_NFS_OPT_NOCONN;
-  else if (hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL)
+  else if (amu_hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL)
     nap->flags &= ~MNT2_NFS_OPT_NOCONN;
   else {
     /*
@@ -564,7 +617,7 @@ compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_
 
 #ifdef MNT2_NFS_OPT_RESVPORT
 # ifdef MNTTAB_OPT_RESVPORT
-  if (hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL)
     nap->flags |= MNT2_NFS_OPT_RESVPORT;
 # else /* not MNTTAB_OPT_RESVPORT */
   nap->flags |= MNT2_NFS_OPT_RESVPORT;
@@ -598,12 +651,16 @@ compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_
   if (nap->rsize)
     nap->flags |= MNT2_NFS_OPT_RSIZE;
 #endif /* MNT2_NFS_OPT_RSIZE */
+  if (nfs_version == NFS_VERSION && nap->rsize > 8192)
+    nap->rsize = 8192;
 
   nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE);
 #ifdef MNT2_NFS_OPT_WSIZE
   if (nap->wsize)
     nap->flags |= MNT2_NFS_OPT_WSIZE;
 #endif /* MNT2_NFS_OPT_WSIZE */
+  if (nfs_version == NFS_VERSION && nap->wsize > 8192)
+    nap->wsize = 8192;
 
   nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO);
 #ifdef MNT2_NFS_OPT_TIMEO
@@ -622,11 +679,13 @@ compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_
     nap->flags |= MNT2_NFS_OPT_BIODS;
 #endif /* MNT2_NFS_OPT_BIODS */
 
-  if (hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
+#ifdef MNT2_NFS_OPT_SOFT
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
     nap->flags |= MNT2_NFS_OPT_SOFT;
+#endif /* MNT2_NFS_OPT_SOFT */
 
 #ifdef MNT2_NFS_OPT_SPONGY
-  if (hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
     nap->flags |= MNT2_NFS_OPT_SPONGY;
     if (nap->flags & MNT2_NFS_OPT_SOFT) {
       plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
@@ -642,11 +701,17 @@ compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_
 #endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */
 
 #ifdef MNTTAB_OPT_INTR
-  if (hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL)
     /*
      * Either turn on the "allow interrupts" option, or
      * turn off the "disallow interrupts" option"
      */
+# ifdef MNT2_NFS_OPT_INTR
+    nap->flags |= MNT2_NFS_OPT_INTR;
+# endif /* MNT2_NFS_OPT_INTR */
+# ifdef MNT2_NFS_OPT_NOINTR
+    nap->flags &= ~MNT2_NFS_OPT_NOINTR;
+# endif /* MNT2_NFS_OPT_NOINTR */
 # ifdef MNT2_NFS_OPT_INT
     nap->flags |= MNT2_NFS_OPT_INT;
 # endif /* MNT2_NFS_OPT_INT */
@@ -656,17 +721,17 @@ compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_
 #endif /* MNTTAB_OPT_INTR */
 
 #ifdef MNTTAB_OPT_NODEVS
-  if (hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
     nap->flags |= MNT2_NFS_OPT_NODEVS;
 #endif /* MNTTAB_OPT_NODEVS */
 
 #ifdef MNTTAB_OPT_COMPRESS
-  if (hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL)
     nap->flags |= MNT2_NFS_OPT_COMPRESS;
 #endif /* MNTTAB_OPT_COMPRESS */
 
 #ifdef MNTTAB_OPT_PRIVATE	/* mount private, single-client tree */
-  if (hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL)
     nap->flags |= MNT2_NFS_OPT_PRIVATE;
 #endif /* MNTTAB_OPT_PRIVATE */
 
@@ -681,35 +746,50 @@ compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_
 #endif /* MNT2_NFS_OPT_PGTHRESH */
 
 #if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
-  if (hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL)
     nap->flags |= MNT2_NFS_OPT_NOCTO;
 #endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */
 
 #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
-  if (hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
     nap->flags |= MNT2_NFS_OPT_POSIX;
     nap->pathconf = NULL;
   }
 #endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
 
+#if defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_PROPLIST) != NULL)
+    nap->flags |= MNT2_NFS_OPT_PROPLIST;
+#endif /* defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) */
+
 #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
   nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
   if (nap->maxgrouplist != 0)
     nap->flags |= MNT2_NFS_OPT_MAXGRPS;
 #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
 
-#ifdef HAVE_FIELD_NFS_ARGS_T_OPTSTR
+#if defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOLOCK) != NULL)
+    nap->flags |= MNT2_NFS_OPT_NONLM;
+#endif /* defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) */
+
+#if defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_XLATECOOKIE) != NULL)
+    nap->flags |= MNT2_NFS_OPT_XLATECOOKIE;
+#endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) */
+
+#ifdef HAVE_NFS_ARGS_T_OPTSTR
   nap->optstr = mntp->mnt_opts;
-#endif /* HAVE_FIELD_NFS_ARGS_T_OPTSTR */
+#endif /* HAVE_NFS_ARGS_T_OPTSTR */
 
   /************************************************************************/
   /***	FINAL ACTIONS							***/
   /************************************************************************/
 
-#ifdef HAVE_FIELD_NFS_ARGS_T_GFS_FLAGS
+#ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
   /* Ultrix stores generic flags in nfs_args.gfs_flags. */
   nap->gfs_flags = genflags;
-#endif /* HAVE_FIELD_NFS_ARGS_T_FLAGS */
+#endif /* HAVE_NFS_ARGS_T_FLAGS */
 
   return;			/* end of compute_nfs_args() function */
 }
@@ -727,7 +807,7 @@ compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
    * Don't let the kernel cache symbolic links we generate, or else lookups
    * will bypass amd and fail to remount stuff as needed.
    */
-  plog(XLOG_INFO, "turning on NFS option symttl and setting value to %d", 0);
+  plog(XLOG_INFO, "turning on NFS option symttl and setting value to 0");
   nap->flags |= MNT2_NFS_OPT_SYMTTL;
   nap->symttl = 0;
 #endif /* MNT2_NFS_OPT_SYMTTL */
@@ -749,35 +829,16 @@ compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
 
 #ifdef MNT2_NFS_OPT_DUMBTIMR
   /*
-   * Don't let the kernel start computing throughput of Amd The numbers will
-   * be meaningless because of the way Amd does mount retries.
+   * Don't let the kernel start computing throughput of Amd.  The numbers
+   * will be meaningless because of the way Amd does mount retries.
    */
   plog(XLOG_INFO, "%s: disabling nfs congestion window", mntp->mnt_dir);
   nap->flags |= MNT2_NFS_OPT_DUMBTIMR;
 #endif /* MNT2_NFS_OPT_DUMBTIMR */
 
-#ifdef MNT2_NFS_OPT_NOAC
-  /*
-   * Don't cache attributes - they are changing under the kernel's feet.
-   * For example, IRIX5.2 will dispense with nfs lookup calls and hand stale
-   * filehandles to getattr unless we disable attribute caching on the
-   * automount points.
-   */
-  nap->flags |= MNT2_NFS_OPT_NOAC;
-#else /* not MNT2_NFS_OPT_NOAC */
-  /*
-   * Setting these to 0 results in an error on some systems, which is why
-   * it's better to use "noac" if possible.
-   */
-# if defined(MNT2_NFS_OPT_ACREGMIN) && defined(MNT2_NFS_OPT_ACREGMAX)
-  nap->acregmin = nap->acregmax = 0; /* XXX: was 1, but why? */
-  nap->flags |= MNT2_NFS_OPT_ACREGMIN | MNT2_NFS_OPT_ACREGMAX;
-# endif /* defined(MNT2_NFS_OPT_ACREGMIN) && defined(MNT2_NFS_OPT_ACREGMAX) */
-# if defined(MNT2_NFS_OPT_ACDIRMIN) && defined(MNT2_NFS_OPT_ACDIRMAX)
-  nap->acdirmin = nap->acdirmax = 0; /* XXX: was 1, but why? */
-  nap->flags |= MNT2_NFS_OPT_ACDIRMIN | MNT2_NFS_OPT_ACDIRMAX;
-# endif /* defined(MNT2_NFS_OPT_ACDIRMIN) && defined(MNT2_NFS_OPT_ACDIRMAX) */
-#endif /* not MNT2_NFS_OPT_NOAC */
+  /* compute all of the NFS attribute-cache flags */
+  compute_nfs_attrcache_flags(nap, mntp);
+
   /*
    * Provide a slight bit more security by requiring the kernel to use
    * reserved ports.
@@ -793,7 +854,7 @@ compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
 static char *
 get_hex_string(u_int len, const char *fhdata)
 {
-  int i;
+  u_int i;
   static char buf[128];		/* better not go over it! */
   char str[16];
   short int arr[64];
@@ -803,9 +864,9 @@ get_hex_string(u_int len, const char *fhdata)
   buf[0] = '\0';
   memset(&arr[0], 0, (64 * sizeof(short int)));
   memcpy(&arr[0], &fhdata[0], len);
-  for (i=0; i<len/sizeof(short int); i++) {
-    sprintf(str, "%04x", ntohs(arr[i]));
-    strcat(buf, str);
+  for (i=0; i<len/sizeof(unsigned short int); i++) {
+    xsnprintf(str, sizeof(str), "%04x", ntohs(arr[i]));
+    xstrlcat(buf, str, sizeof(buf));
   }
   return buf;
 }
@@ -818,7 +879,7 @@ get_hex_string(u_int len, const char *fhdata)
 void
 print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
 {
-   int fhlen = 32;	/* default: NFS V.2 file handle length is 32 */
+  int fhlen = 32;	/* default: NFS V.2 file handle length is 32 */
 #ifdef HAVE_TRANSPORT_TYPE_TLI
   struct netbuf *nbp;
   struct knetconfig *kncp;
@@ -845,44 +906,52 @@ print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
        nbp->maxlen, nbp->len,
        get_hex_string(nbp->len, nbp->buf));
   nbp = nap->syncaddr;
-  plog(XLOG_DEBUG, "NA->syncaddr {netbuf} 0x%x", (int) nbp);
+  plog(XLOG_DEBUG, "NA->syncaddr {netbuf} %p", nbp);
   kncp = nap->knconf;
-  plog(XLOG_DEBUG, "NA->knconf->semantics %lu", (unsigned long) kncp->knc_semantics);
+  plog(XLOG_DEBUG, "NA->knconf->semantics %lu", (u_long) kncp->knc_semantics);
   plog(XLOG_DEBUG, "NA->knconf->protofmly \"%s\"", kncp->knc_protofmly);
   plog(XLOG_DEBUG, "NA->knconf->proto \"%s\"", kncp->knc_proto);
-  plog(XLOG_DEBUG, "NA->knconf->rdev %lu", kncp->knc_rdev);
+  plog(XLOG_DEBUG, "NA->knconf->rdev %lu", (u_long) kncp->knc_rdev);
   /* don't print knconf->unused field */
 #else /* not HAVE_TRANSPORT_TYPE_TLI */
-  sap = (struct sockaddr_in *) &nap->addr;
+# ifdef NFS_ARGS_T_ADDR_IS_POINTER
+    sap = (struct sockaddr_in *) nap->addr;
+# else /* not NFS_ARGS_T_ADDR_IS_POINTER */
+    sap = (struct sockaddr_in *) &nap->addr;
+# endif /* not NFS_ARGS_T_ADDR_IS_POINTER */
   plog(XLOG_DEBUG, "NA->addr {sockaddr_in} (len=%d) = \"%s\"",
        (int) sizeof(struct sockaddr_in),
        get_hex_string(sizeof(struct sockaddr_in), (const char *)sap));
-#ifdef HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN
-  plog(XLOG_DEBUG, "NA->addr.sin_len = \"%d\"", sap->sin_len);
-#endif /* HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN */
-  plog(XLOG_DEBUG, "NA->addr.sin_family = \"%d\"", sap->sin_family);
-  plog(XLOG_DEBUG, "NA->addr.sin_port = \"%d\"", sap->sin_port);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+  /* as per POSIX, sin_len need not be set (used internally by kernel) */
+  plog(XLOG_DEBUG, "NA->addr.sin_len = %d", sap->sin_len);
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+  plog(XLOG_DEBUG, "NA->addr.sin_family = %d", sap->sin_family);
+  plog(XLOG_DEBUG, "NA->addr.sin_port = %d", sap->sin_port);
   plog(XLOG_DEBUG, "NA->addr.sin_addr = \"%s\"",
        get_hex_string(sizeof(struct in_addr), (const char *) &sap->sin_addr));
 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
+#ifdef HAVE_NFS_ARGS_T_ADDRLEN
+  plog(XLOG_DEBUG, "NA->addrlen = %d", nap->addrlen);
+#endif /* ifdef HAVE_NFS_ARGS_T_ADDRLEN */
 
   plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname ? nap->hostname : "null");
-#ifdef HAVE_FIELD_NFS_ARGS_T_NAMLEN
+#ifdef HAVE_NFS_ARGS_T_NAMLEN
   plog(XLOG_DEBUG, "NA->namlen = %d", nap->namlen);
-#endif /* HAVE_FIELD_NFS_ARGS_T_NAMLEN */
+#endif /* HAVE_NFS_ARGS_T_NAMLEN */
 
 #ifdef MNT2_NFS_OPT_FSNAME
   plog(XLOG_DEBUG, "NA->fsname = \"%s\"", nap->fsname ? nap->fsname : "null");
 #endif /* MNT2_NFS_OPT_FSNAME */
 
-#ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
+#ifdef HAVE_NFS_ARGS_T_FHSIZE
   plog(XLOG_DEBUG, "NA->fhsize = %d", nap->fhsize);
   fhlen = nap->fhsize;
-#endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
-#ifdef HAVE_FIELD_NFS_ARGS_T_FH_LEN
+#endif /* HAVE_NFS_ARGS_T_FHSIZE */
+#ifdef HAVE_NFS_ARGS_T_FH_LEN
   plog(XLOG_DEBUG, "NA->fh_len = %d", nap->fh_len);
   fhlen = nap->fh_len;
-#endif /* HAVE_FIELD_NFS_ARGS_T_FH_LEN */
+#endif /* HAVE_NFS_ARGS_T_FH_LEN */
 
   /*
    * XXX: need to figure out how to correctly print file handles,
@@ -893,32 +962,32 @@ print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
   plog(XLOG_DEBUG, "NA->filehandle = \"%s\"",
        get_hex_string(fhlen, (const char *) &nap->NFS_FH_FIELD));
 
-#ifdef HAVE_FIELD_NFS_ARGS_T_SOTYPE
+#ifdef HAVE_NFS_ARGS_T_SOTYPE
   plog(XLOG_DEBUG, "NA->sotype = %d", nap->sotype);
-#endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
-#ifdef HAVE_FIELD_NFS_ARGS_T_PROTO
+#endif /* HAVE_NFS_ARGS_T_SOTYPE */
+#ifdef HAVE_NFS_ARGS_T_PROTO
   plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto);
-#endif /* HAVE_FIELD_NFS_ARGS_T_PROTO */
-#ifdef HAVE_FIELD_NFS_ARGS_T_VERSION
+#endif /* HAVE_NFS_ARGS_T_PROTO */
+#ifdef HAVE_NFS_ARGS_T_VERSION
   plog(XLOG_DEBUG, "NA->version = %d", nap->version);
-#endif /* HAVE_FIELD_NFS_ARGS_T_VERSION */
+#endif /* HAVE_NFS_ARGS_T_VERSION */
 
   plog(XLOG_DEBUG, "NA->flags = 0x%x", (int) nap->flags);
 
   plog(XLOG_DEBUG, "NA->rsize = %d", (int) nap->rsize);
   plog(XLOG_DEBUG, "NA->wsize = %d", (int) nap->wsize);
-#ifdef HAVE_FIELD_NFS_ARGS_T_BSIZE
+#ifdef HAVE_NFS_ARGS_T_BSIZE
   plog(XLOG_DEBUG, "NA->bsize = %d", nap->bsize);
-#endif /* HAVE_FIELD_NFS_ARGS_T_BSIZE */
+#endif /* HAVE_NFS_ARGS_T_BSIZE */
   plog(XLOG_DEBUG, "NA->timeo = %d", (int) nap->timeo);
   plog(XLOG_DEBUG, "NA->retrans = %d", (int) nap->retrans);
 
-#ifdef HAVE_FIELD_NFS_ARGS_T_ACREGMIN
+#ifdef HAVE_NFS_ARGS_T_ACREGMIN
   plog(XLOG_DEBUG, "NA->acregmin = %d", (int) nap->acregmin);
   plog(XLOG_DEBUG, "NA->acregmax = %d", (int) nap->acregmax);
   plog(XLOG_DEBUG, "NA->acdirmin = %d", (int) nap->acdirmin);
   plog(XLOG_DEBUG, "NA->acdirmax = %d", (int) nap->acdirmax);
-#endif /* HAVE_FIELD_NFS_ARGS_T_ACREGMIN */
+#endif /* HAVE_NFS_ARGS_T_ACREGMIN */
 #ifdef MNTTAB_OPT_SYMTTL
   plog(XLOG_DEBUG, "NA->symttl = %d", nap->symttl);
 #endif /* MNTTAB_OPT_SYMTTL */
diff --git a/contrib/amd/libamu/mtab.c b/contrib/amd/libamu/mtab.c
index 3bcc38d..50ba994 100644
--- a/contrib/amd/libamu/mtab.c
+++ b/contrib/amd/libamu/mtab.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: mtab.c,v 1.2 1999/01/10 21:54:37 ezk Exp $
+ * File: am-utils/libamu/mtab.c
  *
  */
 
@@ -60,11 +59,11 @@ mnt_free(mntent_t *mp)
   XFREE(mp->mnt_type);
   XFREE(mp->mnt_opts);
 
-#ifdef HAVE_FIELD_MNTENT_T_MNT_TIME
-# ifdef HAVE_FIELD_MNTENT_T_MNT_TIME_STRING
+#ifdef HAVE_MNTENT_T_MNT_TIME
+# ifdef HAVE_MNTENT_T_MNT_TIME_STRING
   XFREE(mp->mnt_time);
-# endif /* HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
-#endif /* HAVE_FIELD_MNTENT_T_MNT_TIME */
+# endif /* HAVE_MNTENT_T_MNT_TIME_STRING */
+#endif /* HAVE_MNTENT_T_MNT_TIME */
 
   XFREE(mp);
 }
@@ -101,21 +100,151 @@ free_mntlist(mntlist *mp)
 
 
 /*
- * Utility routine which determines the value of a
- * numeric option in the mount options (such as port=%d).
- * Returns 0 if the option is not specified.
+ * Utility routine which returns a pointer to whatever follows an = in a
+ * string.  Returns null if = is not found in the string.
+ */
+char *
+haseq(char *instr)
+{
+  if (instr) {
+    char *eq = strchr(instr, '=');
+    if (eq) return ++eq;
+  }
+  return NULL;
+}
+
+
+/*
+ * Utility routine which returns a pointer to whatever
+ * follows an = in a mount option.  Returns null if option
+ * doesn't exist or doesn't have an '='.  Won't fail for opt,foo=.
+ */
+char *
+hasmnteq(mntent_t *mnt, char *opt)
+{
+  if (mnt && opt) {		/* disallow null input pointers */
+    if ( *opt ) {		/* disallow the null string as an opt */
+      char *str = amu_hasmntopt(mnt, opt);
+      if ( str ) {		/* option was there */
+	char *eq = str + strlen(opt); /* Look at char just after option */
+	if (*eq == '=')		/* Is it '=' ? */
+	  return ++eq;		/* If so, return pointer to remaining str */
+      }
+    }
+  }
+  return NULL;
+}
+
+
+/*
+ * Wrapper around hasmntvalerr(), which retains backwards compatibiliy with
+ * older use of hasmntval().
+ *
+ * XXX: eventually, all use of hasmntval() should be replaced with
+ * hasmntvalerr().
  */
 int
 hasmntval(mntent_t *mnt, char *opt)
 {
-  char *str = hasmntopt(mnt, opt);
-
-  if (str) {
-    char *eq = strchr(str, '=');
-    if (eq)
-      return atoi(eq + 1);
-    else
-      plog(XLOG_USER, "bad numeric option \"%s\" in \"%s\"", opt, str);
+  int err, val = 0;
+
+  err = hasmntvalerr(mnt, opt, &val);
+  if (err)	   /* if there was an error (hasmntvalerr returned 1) */
+    return 0;	   /* redundant: val==0 above, but leave here for clarity */
+  /* otherwise there was no error */
+  return val;
+}
+
+
+/*
+ * Utility routine which determines the value of a numeric option in the
+ * mount options (such as port=%d), and fills in the value in the argument
+ * valp (argument won't be touched if no value is set, for example due to an
+ * error).
+ *
+ * Returns non-zero (1) on error; returns 0 on success.
+ *
+ * XXX: eventually, all use of hasmntval() should be replaced with
+ * hasmntvalerr().
+ */
+unsigned int
+hasmntvalerr(mntent_t *mnt, char *opt, int *valp)
+{
+  char *str = amu_hasmntopt(mnt, opt);
+  int err = 1;		     /* 1 means no good value was set (an error) */
+  char *eq, *endptr;
+  long int i;
+
+  /* exit if no option specificed */
+  if (!str) {
+    goto out;
+  }
+
+  eq = hasmnteq(mnt, opt);
+
+  if (!eq) {		  /* no argument to option ('=' sign was missing) */
+    plog(XLOG_MAP, "numeric option to \"%s\" missing", opt);
+    goto out;
+  }
+
+  /* if got here, then we had an '=' after option name */
+  endptr = NULL;
+  i = strtol(eq, &endptr, 0); /* hex and octal allowed ;-) */
+  if (!endptr ||
+      (endptr != eq && (*endptr == ',' || *endptr == '\0'))) {
+      /*
+       * endptr set means strtol saw a non-digit.  If the non-digit is a
+       * comma, it's probably the start of the next option.  If the comma is
+       * the first char though, complain about it (foo=,bar is made
+       * noticeable by this).
+       *
+       * Similar reasoning for '\0' instead of comma, it's the end of the
+       * string.
+       */
+    *valp = (int) i;		/* set good value */
+    err = 0;			/* no error */
+  } else {
+    /* whatever was after the '=' sign wasn't a number */
+    plog(XLOG_MAP, "invalid numeric option in \"%s\": \"%s\"", opt, str);
+    /* fall through to error/exit processing */
+  }
+
+ out:
+  return err;
+}
+
+
+/*
+ * Utility routine which returns the string value of
+ * an option in the mount options (such as proto=udp).
+ * Returns NULL if the option is not specified.
+ * Returns malloc'ed string (caller must free!)
+ */
+char *
+hasmntstr(mntent_t *mnt, char *opt)
+{
+  char *str = amu_hasmntopt(mnt, opt);
+
+  if (str) { /* The option was there */
+
+    char *eq = hasmnteq(mnt, opt);
+
+    if (eq) { /* and had an = after it */
+
+      char *endptr = strchr(eq, ',');
+
+      /* if saw no comma, return strdup'd string */
+      if (!endptr)
+	return strdup(eq);
+      else {
+	/* else we need to copy only the chars needed */
+	int len = endptr - eq;
+	char *buf = xmalloc(len + 1);
+	strncpy(buf, eq, len);
+	buf[len] = '\0';
+	return buf;
+      }
+    }
   }
-  return 0;
+  return NULL;
 }
diff --git a/contrib/amd/libamu/nfs_prot_xdr.c b/contrib/amd/libamu/nfs_prot_xdr.c
index 874f57a..df8a0b0 100644
--- a/contrib/amd/libamu/nfs_prot_xdr.c
+++ b/contrib/amd/libamu/nfs_prot_xdr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 Erez Zadok
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 The Regents of the University of California.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: nfs_prot_xdr.c,v 1.2 1999/01/10 21:54:38 ezk Exp $
+ * File: am-utils/libamu/nfs_prot_xdr.c
  *
  */
 
diff --git a/contrib/amd/libamu/strerror.c b/contrib/amd/libamu/strerror.c
new file mode 100644
index 0000000..49dd2fc
--- /dev/null
+++ b/contrib/amd/libamu/strerror.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2002-2006 Ion Badulescu
+ * Copyright (c) 1997-2006 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.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * 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.
+ *
+ *
+ * File: am-utils/libamu/strerror.c
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+
+/*
+ * Convert errno to a string
+ */
+char *
+strerror(int errnum)
+{
+#ifdef HAVE_EXTERN_SYS_ERRLIST
+  if (errnum < 0 || errnum >= (sizeof(sys_errlist) >> 2)) {
+    static char errstr[30];
+    xsnprintf(errstr, sizeof(errstr), "Unknown error #%d", errnum);
+    return errstr;
+  }
+  return sys_errlist[error];
+#else  /* not HAVE_EXTERN_SYS_ERRLIST */
+  return "unknown (strerror not available)";
+#endif /* not HAVE_EXTERN_SYS_ERRLIST */
+}
diff --git a/contrib/amd/libamu/strutil.c b/contrib/amd/libamu/strutil.c
new file mode 100644
index 0000000..5a1e759
--- /dev/null
+++ b/contrib/amd/libamu/strutil.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 1997-2006 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.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgment:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * 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.
+ *
+ *
+ * File: am-utils/libamu/strutil.c
+ *
+ */
+
+/*
+ * String Utilities.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+
+char *
+strnsave(const char *str, int len)
+{
+  char *sp = (char *) xmalloc(len + 1);
+  memmove(sp, str, len);
+  sp[len] = '\0';
+
+  return sp;
+}
+
+
+/*
+ * Concatenate three strings and store the result in the buffer pointed to
+ * by p, making p large enough to hold the strings
+ */
+char *
+str3cat(char *p, char *s1, char *s2, char *s3)
+{
+  int l1 = strlen(s1);
+  int l2 = strlen(s2);
+  int l3 = strlen(s3);
+
+  p = (char *) xrealloc(p, l1 + l2 + l3 + 1);
+  memmove(p, s1, l1);
+  memmove(p + l1, s2, l2);
+  memmove(p + l1 + l2, s3, l3 + 1);
+  return p;
+}
+
+
+/*
+ * Split s using ch as delimiter and qc as quote character
+ */
+char **
+strsplit(char *s, int ch, int qc)
+{
+  char **ivec;
+  int ic = 0;
+  int done = 0;
+
+  ivec = (char **) xmalloc((ic + 1) * sizeof(char *));
+
+  while (!done) {
+    char *v;
+
+    /*
+     * skip to split char
+     */
+    while (*s && (ch == ' ' ? (isascii((unsigned char)*s) && isspace((unsigned char)*s)) : *s == ch))
+      *s++ = '\0';
+
+    /*
+     * End of string?
+     */
+    if (!*s)
+      break;
+
+    /*
+     * remember start of string
+     */
+    v = s;
+
+    /*
+     * skip to split char
+     */
+    while (*s && !(ch == ' ' ? (isascii((unsigned char)*s) && isspace((unsigned char)*s)) : *s == ch)) {
+      if (*s++ == qc) {
+	/*
+	 * Skip past string.
+	 */
+	s++;
+	while (*s && *s != qc)
+	  s++;
+	if (*s == qc)
+	  s++;
+      }
+    }
+
+    if (!*s)
+      done = 1;
+    *s++ = '\0';
+
+    /*
+     * save string in new ivec slot
+     */
+    ivec[ic++] = v;
+    ivec = (char **) xrealloc((voidp) ivec, (ic + 1) * sizeof(char *));
+    if (amuDebug(D_STR))
+      plog(XLOG_DEBUG, "strsplit saved \"%s\"", v);
+  }
+
+  if (amuDebug(D_STR))
+    plog(XLOG_DEBUG, "strsplit saved a total of %d strings", ic);
+
+  ivec[ic] = NULL;
+
+  return ivec;
+}
+
+
+/*
+ * Use generic strlcpy to copy a string more carefully, null-terminating it
+ * as needed.  However, if the copied string was truncated due to lack of
+ * space, then warn us.
+ *
+ * For now, xstrlcpy returns VOID because it doesn't look like anywhere in
+ * the Amd code do we actually use the return value of strncpy/strlcpy.
+ */
+void
+#ifdef DEBUG
+_xstrlcpy(const char *filename, int lineno, char *dst, const char *src, size_t len)
+#else /* not DEBUG */
+xstrlcpy(char *dst, const char *src, size_t len)
+#endif /* not DEBUG */
+{
+  if (len == 0)
+    return;
+  if (strlcpy(dst, src, len) >= len)
+#ifdef DEBUG
+    plog(XLOG_ERROR, "xstrlcpy(%s:%d): string \"%s\" truncated to \"%s\"",
+	 filename, lineno, src, dst);
+#else /* not DEBUG */
+    plog(XLOG_ERROR, "xstrlcpy: string \"%s\" truncated to \"%s\"", src, dst);
+#endif /* not DEBUG */
+}
+
+
+/*
+ * Use generic strlcat to concatenate a string more carefully,
+ * null-terminating it as needed.  However, if the copied string was
+ * truncated due to lack of space, then warn us.
+ *
+ * For now, xstrlcat returns VOID because it doesn't look like anywhere in
+ * the Amd code do we actually use the return value of strncat/strlcat.
+ */
+void
+#ifdef DEBUG
+_xstrlcat(const char *filename, int lineno, char *dst, const char *src, size_t len)
+#else /* not DEBUG */
+xstrlcat(char *dst, const char *src, size_t len)
+#endif /* not DEBUG */
+{
+  if (len == 0)
+    return;
+  if (strlcat(dst, src, len) >= len) {
+    /* strlcat does not null terminate if the size of src is equal to len. */
+    dst[strlen(dst) - 1] = '\0';
+#ifdef DEBUG
+    plog(XLOG_ERROR, "xstrlcat(%s:%d): string \"%s\" truncated to \"%s\"",
+	 filename, lineno, src, dst);
+#else /* not DEBUG */
+    plog(XLOG_ERROR, "xstrlcat: string \"%s\" truncated to \"%s\"", src, dst);
+#endif /* not DEBUG */
+  }
+}
+
+
+/* our version of snprintf */
+int
+#if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS))
+_xsnprintf(const char *filename, int lineno, char *str, size_t size, const char *format, ...)
+#else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
+xsnprintf(char *str, size_t size, const char *format, ...)
+#endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
+{
+  va_list ap;
+  int ret = 0;
+
+  va_start(ap, format);
+#if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS))
+  ret = _xvsnprintf(filename, lineno, str, size, format, ap);
+#else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
+  ret = xvsnprintf(str, size, format, ap);
+#endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
+  va_end(ap);
+
+  return ret;
+}
+
+
+/* our version of vsnprintf */
+int
+#if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS))
+_xvsnprintf(const char *filename, int lineno, char *str, size_t size, const char *format, va_list ap)
+#else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
+xvsnprintf(char *str, size_t size, const char *format, va_list ap)
+#endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
+{
+  int ret = 0;
+
+#ifdef HAVE_VSNPRINTF
+  ret = vsnprintf(str, size, format, ap);
+#else /* not HAVE_VSNPRINTF */
+  ret = vsprintf(str, format, ap); /* less secure version */
+#endif /* not HAVE_VSNPRINTF */
+  /*
+   * If error or truncation, plog error.
+   *
+   * WARNING: we use the static 'maxtrunc' variable below to break out any
+   * possible infinite recursion between plog() and xvsnprintf().  If it
+   * ever happens, it'd indicate a bug in Amd.
+   */
+  if (ret < 0 || (size_t) ret >= size) { /* error or truncation occured */
+    static int maxtrunc;        /* hack to avoid inifinite loop */
+    if (++maxtrunc > 10)
+#if defined(DEBUG) && (defined(HAVE_C99_VARARGS_MACROS) || defined(HAVE_GCC_VARARGS_MACROS))
+      plog(XLOG_ERROR, "xvsnprintf(%s:%d): string %p truncated (ret=%d, format=\"%s\")",
+           filename, lineno, str, ret, format);
+#else /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
+      plog(XLOG_ERROR, "xvsnprintf: string %p truncated (ret=%d, format=\"%s\")",
+           str, ret, format);
+#endif /* not DEBUG or no C99/GCC-style vararg cpp macros supported */
+  }
+
+  return ret;
+}
diff --git a/contrib/amd/libamu/util.c b/contrib/amd/libamu/util.c
deleted file mode 100644
index 72fcdad..0000000
--- a/contrib/amd/libamu/util.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry at Imperial College, London.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgment:
- *      This product includes software developed by the University of
- *      California, Berkeley and its contributors.
- * 4. 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.
- *
- * 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.
- *
- *      %W% (Berkeley) %G%
- *
- * $Id: util.c,v 1.2 1999/01/10 21:54:39 ezk Exp $
- *
- */
-
-/*
- * General Utilities.
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-#include <am_defs.h>
-#include <amu.h>
-
-
-char *
-strnsave(const char *str, int len)
-{
-  char *sp = (char *) xmalloc(len + 1);
-  memmove(sp, str, len);
-  sp[len] = 0;
-
-  return sp;
-}
-
-
-/*
- * Concatenate three strings and store in buffer pointed to
- * by p, making p large enough to hold the strings
- */
-char *
-str3cat(char *p, char *s1, char *s2, char *s3)
-{
-  int l1 = strlen(s1);
-  int l2 = strlen(s2);
-  int l3 = strlen(s3);
-
-  p = (char *) xrealloc(p, l1 + l2 + l3 + 1);
-  memmove(p, s1, l1);
-  memmove(p + l1, s2, l2);
-  memmove(p + l1 + l2, s3, l3 + 1);
-  return p;
-}
-
-
-/*
- * Make all the directories in the path.
- */
-int
-mkdirs(char *path, int mode)
-{
-  /*
-   * take a copy in case path is in readonly store
-   */
-  char *p2 = strdup(path);
-  char *sp = p2;
-  struct stat stb;
-  int error_so_far = 0;
-
-  /*
-   * Skip through the string make the directories.
-   * Mostly ignore errors - the result is tested at the end.
-   *
-   * This assumes we are root so that we can do mkdir in a
-   * mode 555 directory...
-   */
-  while ((sp = strchr(sp + 1, '/'))) {
-    *sp = '\0';
-    if (mkdir(p2, mode) < 0) {
-      error_so_far = errno;
-    } else {
-#ifdef DEBUG
-      dlog("mkdir(%s)", p2);
-#endif /* DEBUG */
-    }
-    *sp = '/';
-  }
-
-  if (mkdir(p2, mode) < 0) {
-    error_so_far = errno;
-  } else {
-#ifdef DEBUG
-    dlog("mkdir(%s)", p2);
-#endif /* DEBUG */
-  }
-
-  XFREE(p2);
-
-  return stat(path, &stb) == 0 &&
-    (stb.st_mode & S_IFMT) == S_IFDIR ? 0 : error_so_far;
-}
-
-
-/*
- * Remove as many directories in the path as possible.
- * Give up if the directory doesn't appear to have
- * been created by Amd (not mode dr-x) or an rmdir
- * fails for any reason.
- */
-void
-rmdirs(char *dir)
-{
-  char *xdp = strdup(dir);
-  char *dp;
-
-  do {
-    struct stat stb;
-    /*
-     * Try to find out whether this was
-     * created by amd.  Do this by checking
-     * for owner write permission.
-     */
-    if (stat(xdp, &stb) == 0 && (stb.st_mode & 0200) == 0) {
-      if (rmdir(xdp) < 0) {
-	if (errno != ENOTEMPTY &&
-	    errno != EBUSY &&
-	    errno != EEXIST &&
-	    errno != EINVAL)
-	  plog(XLOG_ERROR, "rmdir(%s): %m", xdp);
-	break;
-      } else {
-#ifdef DEBUG
-	dlog("rmdir(%s)", xdp);
-#endif /* DEBUG */
-      }
-    } else {
-      break;
-    }
-
-    dp = strrchr(xdp, '/');
-    if (dp)
-      *dp = '\0';
-  } while (dp && dp > xdp);
-
-  XFREE(xdp);
-}
diff --git a/contrib/amd/libamu/wire.c b/contrib/amd/libamu/wire.c
index c8ed892..c1852cd 100644
--- a/contrib/amd/libamu/wire.c
+++ b/contrib/amd/libamu/wire.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: wire.c,v 1.5 1999/09/08 23:36:52 ezk Exp $
+ * File: am-utils/libamu/wire.c
  *
  */
 
@@ -102,31 +101,32 @@ print_wires(void)
   int bufcount = 0;
   int buf_size = 1024;
 
-  buf = SALLOC(1024);
+  buf = SALLOC(buf_size);	/* initial allocation (may grow!) */
   if (!buf)
     return NULL;
 
   if (!localnets) {
-    sprintf(buf, "No networks.\n");
+    xstrlcpy(buf, "No networks\n", buf_size);
     return buf;
   }
   /* check if there's more than one network */
   if (!localnets->ip_next) {
-    sprintf(buf,
-	    "Network: wire=\"%s\" (netnumber=%s).\n",
-	    localnets->ip_net_name, localnets->ip_net_num);
+    /* use buf_size for sizeof(buf) because of the realloc() below */
+    xsnprintf(buf, buf_size,
+	      "Network: wire=\"%s\" (netnumber=%s).\n",
+	      localnets->ip_net_name, localnets->ip_net_num);
     return buf;
   }
   buf[0] = '\0';		/* null out buffer before appending */
   for (i = 1, al = localnets; al; al = al->ip_next, i++) {
-    sprintf(s, "Network %d: wire=\"%s\" (netnumber=%s).\n",
-	    i, al->ip_net_name, al->ip_net_num);
+    xsnprintf(s, sizeof(s), "Network %d: wire=\"%s\" (netnumber=%s).\n",
+	      i, al->ip_net_name, al->ip_net_num);
     bufcount += strlen(s);
     if (bufcount > buf_size) {
       buf_size *= 2;
       buf = xrealloc(buf, buf_size);
     }
-    strcat(buf, s);
+    xstrlcat(buf, s, buf_size);
   }
   return buf;
 }
@@ -169,7 +169,17 @@ getwire_lookup(u_long address, u_long netmask, int ishost)
     u_char addr[4];
 
     if (irs_gen == NULL)
+#ifdef irs_irp_acc
+      /*
+       * bsdi4 added another argument to this function, without changing
+       * its name.  The irs_irp_acc is the one (hacky) distinguishing
+       * feature found in <irs.h> that can differentiate between bsdi3 and
+       * bsdi4.
+       */
+      irs_gen = irs_gen_acc("", NULL);
+#else /* not irs_irp_acc */
       irs_gen = irs_gen_acc("");
+#endif /* not irs_irp_acc */
     if (irs_gen && irs_nw == NULL)
       irs_nw = (*irs_gen->nw_map)(irs_gen);
     net = ntohl(address) & (mask = ntohl(netmask));
@@ -190,7 +200,7 @@ getwire_lookup(u_long address, u_long netmask, int ishost)
      */
     if (!np) {
       u_long short_subnet = subnet;
-      while(short_subnet && (short_subnet & 0x000000ff) == 0)
+      while (short_subnet && (short_subnet & 0x000000ff) == 0)
 	short_subnet >>= 8;
       np = getnetbyaddr(short_subnet, AF_INET);
       if (np)
@@ -201,18 +211,18 @@ getwire_lookup(u_long address, u_long netmask, int ishost)
   }
 
   if ((subnet & 0xffffff) == 0) {
-    sprintf(netNumberBuf, "%lu", C(subnet >> 24));
+    xsnprintf(netNumberBuf, sizeof(netNumberBuf), "%lu", C(subnet >> 24));
   } else if ((subnet & 0xffff) == 0) {
-    sprintf(netNumberBuf, "%lu.%lu",
-	C(subnet >> 24), C(subnet >> 16));
+    xsnprintf(netNumberBuf, sizeof(netNumberBuf), "%lu.%lu",
+	      C(subnet >> 24), C(subnet >> 16));
   } else if ((subnet & 0xff) == 0) {
-    sprintf(netNumberBuf, "%lu.%lu.%lu",
-	C(subnet >> 24), C(subnet >> 16),
-	C(subnet >> 8));
+    xsnprintf(netNumberBuf, sizeof(netNumberBuf), "%lu.%lu.%lu",
+	      C(subnet >> 24), C(subnet >> 16),
+	      C(subnet >> 8));
   } else {
-    sprintf(netNumberBuf, "%lu.%lu.%lu.%lu",
-	C(subnet >> 24), C(subnet >> 16),
-	C(subnet >> 8), C(subnet));
+    xsnprintf(netNumberBuf, sizeof(netNumberBuf), "%lu.%lu.%lu.%lu",
+	      C(subnet >> 24), C(subnet >> 16),
+	      C(subnet >> 8), C(subnet));
   }
 
   /* fill in network number (string) */
@@ -228,11 +238,17 @@ getwire_lookup(u_long address, u_long netmask, int ishost)
     if (hp != NULL)
       s = (char *) hp->h_name;
     else
-      s = inet_dquad(buf, subnet);
+      s = inet_dquad(buf, sizeof(buf), subnet);
   }
 
   /* fill in network name (string) */
   al->ip_net_name = strdup(s);
+  /* Let's be cautious here about buffer overflows -Ion */
+  if (strlen(s) > MAXHOSTNAMELEN) {
+    al->ip_net_name[MAXHOSTNAMELEN] = '\0';
+    plog(XLOG_WARNING, "Long hostname %s truncated to %d characters",
+	 s, MAXHOSTNAMELEN);
+  }
 
   return (al);
 }
@@ -244,14 +260,14 @@ getwire_lookup(u_long address, u_long netmask, int ishost)
  * sizeof(buf) needs to be at least 16.
  */
 char *
-inet_dquad(char *buf, u_long addr)
+inet_dquad(char *buf, size_t l, u_long addr)
 {
   addr = ntohl(addr);
-  sprintf(buf, "%ld.%ld.%ld.%ld",
-	  ((addr >> 24) & 0xff),
-	  ((addr >> 16) & 0xff),
-	  ((addr >> 8) & 0xff),
-	  ((addr >> 0) & 0xff));
+  xsnprintf(buf, l, "%ld.%ld.%ld.%ld",
+	    ((addr >> 24) & 0xff),
+	    ((addr >> 16) & 0xff),
+	    ((addr >> 8) & 0xff),
+	    ((addr >> 0) & 0xff));
   return buf;
 }
 
@@ -264,16 +280,17 @@ int
 islocalnet(u_long addr)
 {
   addrlist *al;
-#ifdef DEBUG
-  char buf[16];
-#endif /* DEBUG */
 
   for (al = localnets; al; al = al->ip_next)
     if (((addr ^ al->ip_addr) & al->ip_mask) == 0)
       return TRUE;
 
 #ifdef DEBUG
-    plog(XLOG_INFO, "%s is on a remote network", inet_dquad(buf, addr));
+  {
+    char buf[16];
+    plog(XLOG_INFO, "%s is on a remote network",
+	 inet_dquad(buf, sizeof(buf), addr));
+  }
 #endif /* DEBUG */
 
   return FALSE;
@@ -289,45 +306,106 @@ is_network_member(const char *net)
 {
   addrlist *al;
 
-  for (al = localnets; al; al = al->ip_next)
-    if (STREQ(net, al->ip_net_name) || STREQ(net, al->ip_net_num))
-      return TRUE;
+  /*
+   * If the network name string does not contain a '/', use old behavior.
+   * If it does contain a '/' then interpret the string as a network/netmask
+   * pair.  If "netmask" doesn't exist, use the interface's own netmask.
+   * Also support fully explicit netmasks such as 255.255.255.0 as well as
+   * bit-length netmask such as /24 (hex formats such 0xffffff00 work too).
+   */
+  if (strchr(net, '/') == NULL) {
+    for (al = localnets; al; al = al->ip_next)
+      if (STREQ(net, al->ip_net_name) || STREQ(net, al->ip_net_num))
+	return TRUE;
+  } else {
+    char *netstr = strdup(net), *maskstr;
+    u_long netnum, masknum = 0;
+    maskstr = strchr(netstr, '/');
+    maskstr[0] = '\0';		/* null terminate netstr */
+    maskstr++;
+    if (*maskstr == '\0')	/* if empty string, make it NULL */
+      maskstr = NULL;
+    /* check if netmask uses a dotted-quad or bit-length, or not defined at all */
+    if (maskstr) {
+      if (strchr(maskstr, '.')) {
+	/* XXX: inet_addr is obsolste, convert to inet_aton() */
+	masknum = inet_addr(maskstr);
+	if (masknum == INADDR_NONE) /* can be invalid (-1) or all-1s */
+	  masknum = 0xffffffff;
+      } else if (NSTRCEQ(maskstr, "0x", 2)) {
+	masknum = strtoul(maskstr, NULL, 16);
+      } else {
+	int bits = atoi(maskstr);
+	if (bits < 0)
+	  bits = 0;
+	if (bits > 32)
+	  bits = 32;
+	masknum = 0xffffffff << (32-bits);
+      }
+    }
+    netnum = inet_addr(netstr);	/* not checking return value, b/c -1 (0xffffffff) is valid */
+    XFREE(netstr);		/* netstr not needed any longer */
+
+    /* now check against each local interface */
+    for (al = localnets; al; al = al->ip_next) {
+      if ((al->ip_addr & (maskstr ? masknum : al->ip_mask)) == netnum)
+	return TRUE;
+    }
+  }
 
   return FALSE;
 }
 
 
+/*
+ * Determine whether a IP address (netnum) is one of the local interfaces,
+ * returns TRUE/FALSE.
+ * Does not include the loopback interface: caller needs to check that.
+ */
+int
+is_interface_local(u_long netnum)
+{
+  addrlist *al;
+
+  for (al = localnets; al; al = al->ip_next) {
+    if (al->ip_addr == netnum)
+      return TRUE;
+  }
+  return FALSE;
+}
+
+
 #ifdef HAVE_GETIFADDRS
 void
 getwire(char **name1, char **number1)
 {
   addrlist *al = NULL, *tail = NULL;
   struct ifaddrs *ifaddrs, *ifap;
-#ifndef HAVE_FIELD_STRUCT_IFADDRS_IFA_NEXT
+#ifndef HAVE_STRUCT_IFADDRS_IFA_NEXT
   int count = 0, i;
-#endif /* not HAVE_FIELD_STRUCT_IFADDRS_IFA_NEXT */
+#endif /* not HAVE_STRUCT_IFADDRS_IFA_NEXT */
 
   ifaddrs = NULL;
-#ifdef HAVE_FIELD_STRUCT_IFADDRS_IFA_NEXT
+#ifdef HAVE_STRUCT_IFADDRS_IFA_NEXT
   if (getifaddrs(&ifaddrs) < 0)
     goto out;
 
   for (ifap = ifaddrs; ifap != NULL; ifap = ifap->ifa_next) {
-#else /* not HAVE_FIELD_STRUCT_IFADDRS_IFA_NEXT */
+#else /* not HAVE_STRUCT_IFADDRS_IFA_NEXT */
   if (getifaddrs(&ifaddrs, &count) < 0)
     goto out;
 
   for (i = 0,ifap = ifaddrs; i < count; ifap++, i++) {
-#endif /* HAVE_FIELD_STRUCT_IFADDRS_IFA_NEXT */
+#endif /* HAVE_STRUCT_IFADDRS_IFA_NEXT */
 
     if (!ifap || !ifap->ifa_addr || ifap->ifa_addr->sa_family != AF_INET)
       continue;
 
     /*
-     * If the interface is a loopback, or its not running
+     * If the interface is the loopback, or it's not running,
      * then ignore it.
      */
-    if ((ifap->ifa_flags & IFF_LOOPBACK) != 0)
+    if (S2IN(ifap->ifa_addr) == htonl(INADDR_LOOPBACK))
       continue;
     if ((ifap->ifa_flags & IFF_RUNNING) == 0)
       continue;
@@ -338,7 +416,7 @@ getwire(char **name1, char **number1)
       al = getwire_lookup(S2IN(ifap->ifa_dstaddr), 0xffffffff, 1);
 
     /* append to the end of the list */
-    if (!localnets) {
+    if (!localnets || tail == NULL) {
       localnets = tail = al;
       tail->ip_next = NULL;
     } else {
@@ -362,11 +440,11 @@ out:
 
 #else /* not HAVE_GETIFADDRS */
 
-#if defined(HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN)
+#if defined(HAVE_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
 # define SIZE(ifr)	(MAX((ifr)->ifr_addr.sa_len, sizeof((ifr)->ifr_addr)) + sizeof(ifr->ifr_name))
-#else /* not defined(HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN) */
+#else /* not defined(HAVE_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_STRUCT_SOCKADDR_SA_LEN) */
 # define SIZE(ifr)	sizeof(struct ifreq)
-#endif /* not defined(HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN) */
+#endif /* not defined(HAVE_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_STRUCT_SOCKADDR_SA_LEN) */
 
 #define clist		(ifc.ifc_ifcu.ifcu_req)
 #define count		(ifc.ifc_len/sizeof(struct ifreq))
@@ -376,18 +454,12 @@ void
 getwire(char **name1, char **number1)
 {
   struct ifconf ifc;
-  struct ifreq *ifr;
+  struct ifreq *ifr, ifrpool;
   caddr_t cp, cplim;
   int fd = -1;
   u_long address;
   addrlist *al = NULL, *tail = NULL;
   char buf[GFBUFLEN];
-#if 0
-  u_long net;
-  u_long mask;
-  u_long subnetshift;
-  char buf[GFBUFLEN], *s;
-#endif
 
 #ifndef SIOCGIFFLAGS
   /* if cannot get interface flags, return nothing */
@@ -430,8 +502,10 @@ getwire(char **name1, char **number1)
   /*
    * Scan the list looking for a suitable interface
    */
-  for (cp = buf; cp < cplim; cp += SIZE(ifr)) {
-    ifr = (struct ifreq *) cp;
+  for (cp = buf; cp < cplim; /* increment in the loop body */) {
+    memcpy(&ifrpool, cp, sizeof(ifrpool));
+    ifr = &ifrpool;
+    cp += SIZE(ifr);
 
     if (ifr->ifr_addr.sa_family != AF_INET)
       continue;
@@ -445,13 +519,11 @@ getwire(char **name1, char **number1)
       continue;
 
     /*
-     * If the interface is a loopback, or its not running
+     * If the interface is the loopback, or it's not running,
      * then ignore it.
      */
-#ifdef IFF_LOOPBACK
-    if ((ifr->ifr_flags & IFF_LOOPBACK) != 0)
+    if (address == htonl(INADDR_LOOPBACK))
       continue;
-#endif /* IFF_LOOPBACK */
     /*
      * Fix for 0.0.0.0 loopback on SunOS 3.X which defines IFF_ROUTE
      * instead of IFF_LOOPBACK.
diff --git a/contrib/amd/libamu/xdr_func.c b/contrib/amd/libamu/xdr_func.c
index deeb205..6bd0254 100644
--- a/contrib/amd/libamu/xdr_func.c
+++ b/contrib/amd/libamu/xdr_func.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,9 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: xdr_func.c,v 1.2 1999/01/10 21:54:39 ezk Exp $
+ * File: am-utils/libamu/xdr_func.c
  *
  */
 
@@ -51,19 +50,23 @@
 #include <am_defs.h>
 #include <amu.h>
 
+#ifdef __RPCSVC_MOUNT_H__
+# error IRIX6 should not include rpcsvc/mount.h
+#endif /* __RPCSVC_MOUNT_H__ */
+
 /*
  * MACROS:
  */
 #ifdef HAVE_FS_AUTOFS
-# ifndef A_MAXNAME
-#  define A_MAXNAME 255
-# endif /* not A_MAXNAME */
-# ifndef A_MAXOPTS
-#  define A_MAXOPTS 255
-# endif /* not A_MAXOPTS */
-# ifndef A_MAXPATH
-#  define A_MAXPATH 1024
-# endif /* not A_MAXPATH */
+# ifndef AUTOFS_MAXCOMPONENTLEN
+#  define AUTOFS_MAXCOMPONENTLEN 255
+# endif /* not AUTOFS_MAXCOMPONENTLEN */
+# ifndef AUTOFS_MAXOPTSLEN
+#  define AUTOFS_MAXOPTSLEN 255
+# endif /* not AUTOFS_MAXOPTSLEN */
+# ifndef AUTOFS_MAXPATHLEN
+#  define AUTOFS_MAXPATHLEN 1024
+# endif /* not AUTOFS_MAXPATHLEN */
 #endif /* HAVE_FS_AUTOFS */
 
 /* forward definitions, are they needed? */
@@ -76,10 +79,8 @@ extern bool_t xdr_name(XDR *xdrs, name *objp);
 bool_t
 xdr_attrstat(XDR *xdrs, nfsattrstat *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_attrstat:");
-#endif /* DEBUG */
 
   if (!xdr_nfsstat(xdrs, &objp->ns_status)) {
     return (FALSE);
@@ -102,10 +103,8 @@ xdr_attrstat(XDR *xdrs, nfsattrstat *objp)
 bool_t
 xdr_createargs(XDR *xdrs, nfscreateargs *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_createargs:");
-#endif /* DEBUG */
 
   if (!xdr_diropargs(xdrs, &objp->ca_where)) {
     return (FALSE);
@@ -122,10 +121,8 @@ xdr_createargs(XDR *xdrs, nfscreateargs *objp)
 bool_t
 xdr_dirlist(XDR *xdrs, nfsdirlist *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_dirlist:");
-#endif /* DEBUG */
 
   if (!xdr_pointer(xdrs, (char **) &objp->dl_entries, sizeof(nfsentry), (XDRPROC_T_TYPE) xdr_entry)) {
     return (FALSE);
@@ -142,10 +139,8 @@ xdr_dirlist(XDR *xdrs, nfsdirlist *objp)
 bool_t
 xdr_diropargs(XDR *xdrs, nfsdiropargs *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_diropargs:");
-#endif /* DEBUG */
 
   if (!xdr_nfs_fh(xdrs, &objp->da_fhandle)) {
     return (FALSE);
@@ -162,10 +157,8 @@ xdr_diropargs(XDR *xdrs, nfsdiropargs *objp)
 bool_t
 xdr_diropokres(XDR *xdrs, nfsdiropokres *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_diropokres:");
-#endif /* DEBUG */
 
   if (!xdr_nfs_fh(xdrs, &objp->drok_fhandle)) {
     return (FALSE);
@@ -182,10 +175,8 @@ xdr_diropokres(XDR *xdrs, nfsdiropokres *objp)
 bool_t
 xdr_diropres(XDR *xdrs, nfsdiropres *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_diropres:");
-#endif /* DEBUG */
 
   if (!xdr_nfsstat(xdrs, &objp->dr_status)) {
     return (FALSE);
@@ -208,10 +199,8 @@ xdr_diropres(XDR *xdrs, nfsdiropres *objp)
 bool_t
 xdr_dirpath(XDR *xdrs, dirpath *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_dirpath:");
-#endif /* DEBUG */
 
   if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
     return (FALSE);
@@ -225,10 +214,8 @@ xdr_dirpath(XDR *xdrs, dirpath *objp)
 bool_t
 xdr_entry(XDR *xdrs, nfsentry *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_entry:");
-#endif /* DEBUG */
 
   if (!xdr_u_int(xdrs, &objp->ne_fileid)) {
     return (FALSE);
@@ -251,19 +238,13 @@ xdr_entry(XDR *xdrs, nfsentry *objp)
 bool_t
 xdr_exportnode(XDR *xdrs, exportnode *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_exportnode:");
-#endif /* DEBUG */
 
   if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
     return (FALSE);
   }
-  /*
-   * This cast to (groups) is needed for Irix6.  If you change it, it
-   * may produce a warning/error on other systems.
-   */
-  if (!xdr_groups(xdrs, (groups) &objp->ex_groups)) {
+  if (!xdr_groups(xdrs, &objp->ex_groups)) {
     return (FALSE);
   }
   if (!xdr_exports(xdrs, &objp->ex_next)) {
@@ -278,10 +259,8 @@ xdr_exportnode(XDR *xdrs, exportnode *objp)
 bool_t
 xdr_exports(XDR *xdrs, exports *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_exports:");
-#endif /* DEBUG */
 
   if (!xdr_pointer(xdrs, (char **) objp, sizeof(exportnode), (XDRPROC_T_TYPE) xdr_exportnode)) {
     return (FALSE);
@@ -295,10 +274,8 @@ xdr_exports(XDR *xdrs, exports *objp)
 bool_t
 xdr_fattr(XDR *xdrs, nfsfattr *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_fattr:");
-#endif /* DEBUG */
 
   if (!xdr_ftype(xdrs, &objp->na_type)) {
     return (FALSE);
@@ -351,10 +328,8 @@ xdr_fattr(XDR *xdrs, nfsfattr *objp)
 bool_t
 xdr_fhandle(XDR *xdrs, fhandle objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_fhandle:");
-#endif /* DEBUG */
 
   if (!xdr_opaque(xdrs, objp, NFS_FHSIZE)) {
     return (FALSE);
@@ -368,10 +343,8 @@ xdr_fhandle(XDR *xdrs, fhandle objp)
 bool_t
 xdr_fhstatus(XDR *xdrs, fhstatus *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_fhstatus:");
-#endif /* DEBUG */
 
   if (!xdr_u_int(xdrs, &objp->fhs_status)) {
     return (FALSE);
@@ -388,10 +361,8 @@ xdr_fhstatus(XDR *xdrs, fhstatus *objp)
 bool_t
 xdr_filename(XDR *xdrs, filename *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_filename:");
-#endif /* DEBUG */
 
   if (!xdr_string(xdrs, objp, NFS_MAXNAMLEN)) {
     return (FALSE);
@@ -405,12 +376,12 @@ xdr_filename(XDR *xdrs, filename *objp)
 bool_t
 xdr_ftype(XDR *xdrs, nfsftype *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  enum_t local_obj = *objp;
+
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_ftype:");
-#endif /* DEBUG */
 
-  if (!xdr_enum(xdrs, (enum_t *) objp)) {
+  if (!xdr_enum(xdrs, &local_obj)) {
     return (FALSE);
   }
   return (TRUE);
@@ -422,19 +393,13 @@ xdr_ftype(XDR *xdrs, nfsftype *objp)
 bool_t
 xdr_groupnode(XDR *xdrs, groupnode *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_groupnode:");
-#endif /* DEBUG */
 
   if (!xdr_name(xdrs, &objp->gr_name)) {
     return (FALSE);
   }
-  /*
-   * This cast to (groups) is needed for Irix6.  If you change it, it
-   * may produce a warning/error on other systems.
-   */
-  if (!xdr_groups(xdrs, (groups) &objp->gr_next)) {
+  if (!xdr_groups(xdrs, &objp->gr_next)) {
     return (FALSE);
   }
   return (TRUE);
@@ -444,12 +409,10 @@ xdr_groupnode(XDR *xdrs, groupnode *objp)
 
 #ifndef HAVE_XDR_GROUPS
 bool_t
-xdr_groups(XDR *xdrs, groups objp)
+xdr_groups(XDR *xdrs, groups *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_groups:");
-#endif /* DEBUG */
 
   if (!xdr_pointer(xdrs, (char **) objp, sizeof(groupnode), (XDRPROC_T_TYPE) xdr_groupnode)) {
     return (FALSE);
@@ -463,10 +426,8 @@ xdr_groups(XDR *xdrs, groups objp)
 bool_t
 xdr_linkargs(XDR *xdrs, nfslinkargs *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_linkargs:");
-#endif /* DEBUG */
 
   if (!xdr_nfs_fh(xdrs, &objp->la_fhandle)) {
     return (FALSE);
@@ -483,10 +444,8 @@ xdr_linkargs(XDR *xdrs, nfslinkargs *objp)
 bool_t
 xdr_mountbody(XDR *xdrs, mountbody *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_mountbody:");
-#endif /* DEBUG */
 
   if (!xdr_name(xdrs, &objp->ml_hostname)) {
     return (FALSE);
@@ -506,10 +465,8 @@ xdr_mountbody(XDR *xdrs, mountbody *objp)
 bool_t
 xdr_mountlist(XDR *xdrs, mountlist *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_mountlist:");
-#endif /* DEBUG */
 
   if (!xdr_pointer(xdrs, (char **) objp, sizeof(mountbody), (XDRPROC_T_TYPE) xdr_mountbody)) {
     return (FALSE);
@@ -519,94 +476,12 @@ xdr_mountlist(XDR *xdrs, mountlist *objp)
 #endif /* not HAVE_XDR_MOUNTLIST */
 
 
-#if defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3)
-/*
- * This ifdef is a hack: this whole file needs to be compiled
- * only if the system has NFS V3 and does not have the xdr_mountres3
- * function.  Autoconf should pick this source file to compile only
- * if these two conditions apply.
- */
-
-bool_t
-xdr_fhandle3(XDR *xdrs, fhandle3 *objp)
-{
-#ifdef DEBUG
-  amuDebug(D_TRACE)
-    plog(XLOG_DEBUG, "xdr_fhandle3:");
-#endif /* DEBUG */
-
-  if (!xdr_bytes(xdrs,
-		 (char **) &objp->fhandle3_val,
-		 (u_int *) &objp->fhandle3_len,
-		 FHSIZE3))
-    return (FALSE);
-  return (TRUE);
-}
-
-
-bool_t
-xdr_mountstat3(XDR *xdrs, mountstat3 *objp)
-{
-#ifdef DEBUG
-  amuDebug(D_TRACE)
-    plog(XLOG_DEBUG, "xdr_mountstat3:");
-#endif /* DEBUG */
-
-  if (!xdr_enum(xdrs, (enum_t *)objp))
-    return (FALSE);
-  return (TRUE);
-}
-
-
-bool_t
-xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp)
-{
-#ifdef DEBUG
-  amuDebug(D_TRACE)
-    plog(XLOG_DEBUG, "xdr_mountres3_ok:");
-#endif /* DEBUG */
-
-  if (!xdr_fhandle3(xdrs, &objp->fhandle))
-    return (FALSE);
-  if (!xdr_array(xdrs,
-		 (char **)&objp->auth_flavors.auth_flavors_val,
-		 (u_int *) &objp->auth_flavors.auth_flavors_len,
-		 ~0,
-		 sizeof (int),
-		 (xdrproc_t) xdr_int))
-    return (FALSE);
-  return (TRUE);
-}
-
-
-bool_t
-xdr_mountres3(XDR *xdrs, mountres3 *objp)
-{
-#ifdef DEBUG
-  amuDebug(D_TRACE)
-    plog(XLOG_DEBUG, "xdr_mountres3:");
-#endif /* DEBUG */
-
-  if (!xdr_mountstat3(xdrs, &objp->fhs_status))
-    return (FALSE);
-
-  if (objp->fhs_status == 0) {	/* 0 == MNT_OK or MNT3_OK */
-    if (!xdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo))
-      return (FALSE);
-  }
-  return (TRUE);
-}
-#endif /* defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3) */
-
-
 #ifndef HAVE_XDR_NAME
 bool_t
 xdr_name(XDR *xdrs, name *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_name:");
-#endif /* DEBUG */
 
   if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
     return (FALSE);
@@ -620,10 +495,8 @@ xdr_name(XDR *xdrs, name *objp)
 bool_t
 xdr_nfs_fh(XDR *xdrs, am_nfs_fh *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_nfs_fh:");
-#endif /* DEBUG */
 
   if (!xdr_opaque(xdrs, (caddr_t) objp->fh_data, NFS_FHSIZE)) {
     return (FALSE);
@@ -637,10 +510,8 @@ xdr_nfs_fh(XDR *xdrs, am_nfs_fh *objp)
 bool_t
 xdr_nfscookie(XDR *xdrs, nfscookie objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_nfscookie:");
-#endif /* DEBUG */
 
   if (!xdr_opaque(xdrs, objp, NFS_COOKIESIZE)) {
     return (FALSE);
@@ -654,10 +525,8 @@ xdr_nfscookie(XDR *xdrs, nfscookie objp)
 bool_t
 xdr_nfspath(XDR *xdrs, nfspath *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_nfspath:");
-#endif /* DEBUG */
 
   if (!xdr_string(xdrs, objp, NFS_MAXPATHLEN)) {
     return (FALSE);
@@ -671,12 +540,12 @@ xdr_nfspath(XDR *xdrs, nfspath *objp)
 bool_t
 xdr_nfsstat(XDR *xdrs, nfsstat *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  enum_t local_obj = *objp;
+
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_nfsstat:");
-#endif /* DEBUG */
 
-  if (!xdr_enum(xdrs, (enum_t *) objp)) {
+  if (!xdr_enum(xdrs, &local_obj)) {
     return (FALSE);
   }
   return (TRUE);
@@ -688,10 +557,8 @@ xdr_nfsstat(XDR *xdrs, nfsstat *objp)
 bool_t
 xdr_nfstime(XDR *xdrs, nfstime *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_nfstime:");
-#endif /* DEBUG */
 
   if (!xdr_u_int(xdrs, (u_int *) &objp->nt_seconds)) {
     return (FALSE);
@@ -708,11 +575,8 @@ xdr_nfstime(XDR *xdrs, nfstime *objp)
 bool_t
 xdr_pointer(register XDR *xdrs, char **objpp, u_int obj_size, XDRPROC_T_TYPE xdr_obj)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_pointer:");
-#endif /* DEBUG */
-
 
   bool_t more_data;
 
@@ -734,10 +598,8 @@ xdr_pointer(register XDR *xdrs, char **objpp, u_int obj_size, XDRPROC_T_TYPE xdr
 bool_t
 xdr_readargs(XDR *xdrs, nfsreadargs *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_readargs:");
-#endif /* DEBUG */
 
   if (!xdr_nfs_fh(xdrs, &objp->ra_fhandle)) {
     return (FALSE);
@@ -760,10 +622,8 @@ xdr_readargs(XDR *xdrs, nfsreadargs *objp)
 bool_t
 xdr_readdirargs(XDR *xdrs, nfsreaddirargs *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_readdirargs:");
-#endif /* DEBUG */
 
   if (!xdr_nfs_fh(xdrs, &objp->rda_fhandle)) {
     return (FALSE);
@@ -783,10 +643,8 @@ xdr_readdirargs(XDR *xdrs, nfsreaddirargs *objp)
 bool_t
 xdr_readdirres(XDR *xdrs, nfsreaddirres *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_readdirres:");
-#endif /* DEBUG */
 
   if (!xdr_nfsstat(xdrs, &objp->rdr_status)) {
     return (FALSE);
@@ -809,10 +667,8 @@ xdr_readdirres(XDR *xdrs, nfsreaddirres *objp)
 bool_t
 xdr_readlinkres(XDR *xdrs, nfsreadlinkres *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_readlinkres:");
-#endif /* DEBUG */
 
   if (!xdr_nfsstat(xdrs, &objp->rlr_status)) {
     return (FALSE);
@@ -835,10 +691,8 @@ xdr_readlinkres(XDR *xdrs, nfsreadlinkres *objp)
 bool_t
 xdr_readokres(XDR *xdrs, nfsreadokres *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_readokres:");
-#endif /* DEBUG */
 
   if (!xdr_fattr(xdrs, &objp->raok_attributes)) {
     return (FALSE);
@@ -858,10 +712,8 @@ xdr_readokres(XDR *xdrs, nfsreadokres *objp)
 bool_t
 xdr_readres(XDR *xdrs, nfsreadres *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_readres:");
-#endif /* DEBUG */
 
   if (!xdr_nfsstat(xdrs, &objp->rr_status)) {
     return (FALSE);
@@ -884,10 +736,8 @@ xdr_readres(XDR *xdrs, nfsreadres *objp)
 bool_t
 xdr_renameargs(XDR *xdrs, nfsrenameargs *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_renameargs:");
-#endif /* DEBUG */
 
   if (!xdr_diropargs(xdrs, &objp->rna_from)) {
     return (FALSE);
@@ -904,10 +754,8 @@ xdr_renameargs(XDR *xdrs, nfsrenameargs *objp)
 bool_t
 xdr_sattr(XDR *xdrs, nfssattr *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_sattr:");
-#endif /* DEBUG */
 
   if (!xdr_u_int(xdrs, &objp->sa_mode)) {
     return (FALSE);
@@ -936,10 +784,8 @@ xdr_sattr(XDR *xdrs, nfssattr *objp)
 bool_t
 xdr_sattrargs(XDR *xdrs, nfssattrargs *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_sattrargs:");
-#endif /* DEBUG */
 
   if (!xdr_nfs_fh(xdrs, &objp->sag_fhandle)) {
     return (FALSE);
@@ -956,10 +802,8 @@ xdr_sattrargs(XDR *xdrs, nfssattrargs *objp)
 bool_t
 xdr_statfsokres(XDR *xdrs, nfsstatfsokres *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_statfsokres:");
-#endif /* DEBUG */
 
   if (!xdr_u_int(xdrs, &objp->sfrok_tsize)) {
     return (FALSE);
@@ -985,10 +829,8 @@ xdr_statfsokres(XDR *xdrs, nfsstatfsokres *objp)
 bool_t
 xdr_statfsres(XDR *xdrs, nfsstatfsres *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_statfsres:");
-#endif /* DEBUG */
 
   if (!xdr_nfsstat(xdrs, &objp->sfr_status)) {
     return (FALSE);
@@ -1011,10 +853,8 @@ xdr_statfsres(XDR *xdrs, nfsstatfsres *objp)
 bool_t
 xdr_symlinkargs(XDR *xdrs, nfssymlinkargs *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_symlinkargs:");
-#endif /* DEBUG */
 
   if (!xdr_diropargs(xdrs, &objp->sla_from)) {
     return (FALSE);
@@ -1034,10 +874,8 @@ xdr_symlinkargs(XDR *xdrs, nfssymlinkargs *objp)
 bool_t
 xdr_writeargs(XDR *xdrs, nfswriteargs *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
+  if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_writeargs:");
-#endif /* DEBUG */
 
   if (!xdr_nfs_fh(xdrs, &objp->wra_fhandle)) {
     return (FALSE);
@@ -1063,93 +901,198 @@ xdr_writeargs(XDR *xdrs, nfswriteargs *objp)
 
 
 /*
- * AUTOFS XDR FUNCTIONS:
+ * NFS V3 XDR FUNCTIONS:
  */
-#ifdef HAVE_FS_AUTOFS
-# ifndef HAVE_XDR_MNTREQUEST
+#ifdef HAVE_FS_NFS3
 bool_t
-xdr_mntrequest(XDR *xdrs, mntrequest *objp)
+xdr_am_fhandle3(XDR *xdrs, am_fhandle3 *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
-    plog(XLOG_DEBUG, "xdr_mntrequest:");
-#endif /* DEBUG */
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_fhandle3:");
 
-  if (!xdr_string(xdrs, &objp->name, A_MAXNAME))
+  if (!xdr_bytes(xdrs,
+		 (char **) &objp->fhandle3_val,
+		 (u_int *) &objp->fhandle3_len,
+		 AM_FHSIZE3))
     return (FALSE);
+  return (TRUE);
+}
+
+
+bool_t
+xdr_am_mountstat3(XDR *xdrs, am_mountstat3 *objp)
+{
+  enum_t local_obj = *objp;
+
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_mountstat3:");
 
-  if (!xdr_string(xdrs, &objp->map, A_MAXNAME))
+  if (!xdr_enum(xdrs, &local_obj))
     return (FALSE);
+  return (TRUE);
+}
 
-  if (!xdr_string(xdrs, &objp->opts, A_MAXOPTS))
+
+bool_t
+xdr_am_mountres3_ok(XDR *xdrs, am_mountres3_ok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_mountres3_ok:");
+
+  if (!xdr_am_fhandle3(xdrs, &objp->fhandle))
     return (FALSE);
+  if (!xdr_array(xdrs,
+		 (char **) ((voidp) &objp->auth_flavors.auth_flavors_val),
+		 (u_int *) &objp->auth_flavors.auth_flavors_len,
+		 ~0,
+		 sizeof(int),
+		 (XDRPROC_T_TYPE) xdr_int))
+    return (FALSE);
+  return (TRUE);
+}
+
+
+bool_t
+xdr_am_mountres3(XDR *xdrs, am_mountres3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_mountres3:");
 
-  if (!xdr_string(xdrs, &objp->path, A_MAXPATH))
+  if (!xdr_am_mountstat3(xdrs, &objp->fhs_status))
     return (FALSE);
 
+  if (objp->fhs_status == AM_MNT3_OK) {
+    if (!xdr_am_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo))
+      return (FALSE);
+  }
   return (TRUE);
 }
-# endif /* not HAVE_XDR_MNTREQUEST */
 
 
-# ifndef HAVE_XDR_MNTRES
 bool_t
-xdr_mntres(XDR *xdrs, mntres *objp)
+xdr_am_diropargs3(XDR *xdrs, am_diropargs3 *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
-    plog(XLOG_DEBUG, "xdr_mntres:");
-#endif /* DEBUG */
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_diropargs3:");
 
-  if (!xdr_int(xdrs, &objp->status))
+  if (!xdr_am_nfs_fh3(xdrs, &objp->dir))
+    return (FALSE);
+  if (!xdr_am_filename3(xdrs, &objp->name))
     return (FALSE);
-
   return (TRUE);
 }
-# endif /* not HAVE_XDR_MNTRES */
 
 
-# ifndef HAVE_XDR_UMNTREQUEST
 bool_t
-xdr_umntrequest(XDR *xdrs, umntrequest *objp)
+xdr_am_filename3(XDR *xdrs, am_filename3 *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
-    plog(XLOG_DEBUG, "xdr_umntrequest:");
-#endif /* DEBUG */
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_filename3:");
 
-  if (!xdr_int(xdrs, &objp->isdirect))
+  if (!xdr_string(xdrs, objp, ~0))
     return (FALSE);
+  return (TRUE);
+}
+
 
-  if (!xdr_u_int(xdrs, (u_int *) &objp->devid))
+bool_t
+xdr_am_LOOKUP3args(XDR *xdrs, am_LOOKUP3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_LOOKUP3args:");
+
+  if (!xdr_am_diropargs3(xdrs, &objp->what))
     return (FALSE);
+  return (TRUE);
+}
+
+
+bool_t
+xdr_am_LOOKUP3res(XDR *xdrs, am_LOOKUP3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_LOOKUP3res:");
 
-#ifdef HAVE_FIELD_UMNTREQUEST_RDEVID
-  if (!xdr_u_long(xdrs, &objp->rdevid))
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
     return (FALSE);
-#endif /* HAVE_FIELD_UMNTREQUEST_RDEVID */
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_LOOKUP3resok(xdrs, &objp->res_u.ok))
+      return (FALSE);
+    break;
+  default:
+    if (!xdr_am_LOOKUP3resfail(xdrs, &objp->res_u.fail))
+      return (FALSE);
+    break;
+  }
+  return (TRUE);
+}
+
+
+bool_t
+xdr_am_LOOKUP3resfail(XDR *xdrs, am_LOOKUP3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_LOOKUP3resfail:");
 
-  if (!xdr_pointer(xdrs, (char **) &objp->next, sizeof(umntrequest), (XDRPROC_T_TYPE) xdr_umntrequest))
+  /*
+   * Don't xdr post_op_attr: amd doesn't need them, but they require many
+   * additional xdr functions.
+   */
+#if 0
+  if (!xdr_post_op_attr(xdrs, &objp->dir_attributes))
     return (FALSE);
+#endif
+  return (TRUE);
+}
+
+
+bool_t
+xdr_am_LOOKUP3resok(XDR *xdrs, am_LOOKUP3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_LOOKUP3resok:");
 
+  if (!xdr_am_nfs_fh3(xdrs, &objp->object))
+    return (FALSE);
+  /*
+   * Don't xdr post_op_attr: amd doesn't need them, but they require many
+   * additional xdr functions.
+   */
+#if 0
+  if (!xdr_post_op_attr(xdrs, &objp->obj_attributes))
+    return (FALSE);
+  if (!xdr_post_op_attr(xdrs, &objp->dir_attributes))
+    return (FALSE);
+#endif
   return (TRUE);
 }
-# endif /* not HAVE_XDR_UMNTREQUEST */
 
 
-# ifndef HAVE_XDR_UMNTRES
 bool_t
-xdr_umntres(XDR *xdrs, umntres *objp)
+xdr_am_nfs_fh3(XDR *xdrs, am_nfs_fh3 *objp)
 {
-#ifdef DEBUG
-  amuDebug(D_TRACE)
-    plog(XLOG_DEBUG, "xdr_mntres:");
-#endif /* DEBUG */
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_nfs_fh3:");
 
-  if (!xdr_int(xdrs, &objp->status))
+  if (!xdr_u_int(xdrs, &objp->am_fh3_length))
+    return (FALSE);
+  if (objp->am_fh3_length > AM_FHSIZE3)
     return (FALSE);
+  if (!xdr_opaque(xdrs, objp->am_fh3_data, objp->am_fh3_length))
+    return (FALSE);
+  return (TRUE);
+}
+
+
+bool_t
+xdr_am_nfsstat3(XDR *xdrs, am_nfsstat3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_nfsstat3:");
 
+  if (!xdr_enum(xdrs, (enum_t *)objp))
+    return (FALSE);
   return (TRUE);
 }
-# endif /* not HAVE_XDR_UMNTRES */
-#endif /* HAVE_FS_AUTOFS */
+#endif /* not HAVE_FS_NFS3 */
diff --git a/contrib/amd/libamu/xutil.c b/contrib/amd/libamu/xutil.c
index 0208045..3a33b9c 100644
--- a/contrib/amd/libamu/xutil.c
+++ b/contrib/amd/libamu/xutil.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,12 +36,15 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: xutil.c,v 1.8 1999/09/30 21:01:42 ezk Exp $
+ * File: am-utils/libamu/xutil.c
  *
  */
 
+/*
+ * Miscellaneous Utilities: Logging, TTY, timers, signals, RPC, memory, etc.
+ */
+
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif /* HAVE_CONFIG_H */
@@ -56,13 +59,11 @@
 FILE *logfp = NULL;
 
 static char *am_progname = "unknown";	/* "amd" */
-static char am_hostname[MAXHOSTNAMELEN + 1] = "unknown"; /* Hostname */
+static char am_hostname[MAXHOSTNAMELEN] = "unknown"; /* Hostname */
 pid_t am_mypid = -1;		/* process ID */
 serv_state amd_state;		/* amd's state */
 int foreground = 1;		/* 1 == this is the top-level server */
-#ifdef DEBUG
 int debug_flags = 0;
-#endif /* DEBUG */
 
 #ifdef HAVE_SYSLOG
 int syslogging;
@@ -71,16 +72,18 @@ int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS;
 int xlog_level_init = ~0;
 static int amd_program_number = AMQ_PROGRAM;
 
-time_t clock_valid = 0;
-time_t xclock_valid = 0;
-
 #ifdef DEBUG_MEM
+# if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY)
 static int mem_bytes;
 static int orig_mem_bytes;
+# endif /* not defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) */
 #endif /* DEBUG_MEM */
 
 /* forward definitions */
-static void real_plog(int lvl, char *fmt, va_list vargs);
+/* for GCC format string auditing */
+static void real_plog(int lvl, const char *fmt, va_list vargs)
+     __attribute__((__format__(__printf__, 2, 0)));
+
 
 #ifdef DEBUG
 /*
@@ -88,20 +91,23 @@ static void real_plog(int lvl, char *fmt, va_list vargs);
  */
 struct opt_tab dbg_opt[] =
 {
-  {"all", D_ALL},		/* All */
-  {"amq", D_AMQ},		/* Register for AMQ program */
-  {"daemon", D_DAEMON},		/* Enter daemon mode */
-  {"fork", D_FORK},		/* Fork server (nofork = don't fork) */
+  {"all", D_ALL},		/* All non-disruptive options */
+  {"amq", D_AMQ},		/* Don't register for AMQ program */
+  {"daemon", D_DAEMON},		/* Don't enter daemon mode */
+  {"fork", D_FORK},		/* Don't fork server */
   {"full", D_FULL},		/* Program trace */
+#ifdef HAVE_CLOCK_GETTIME
+  {"hrtime", D_HRTIME},		/* Print high resolution time stamps */
+#endif /* HAVE_CLOCK_GETTIME */
   /* info service specific debugging (hesiod, nis, etc) */
   {"info", D_INFO},
-# ifdef DEBUG_MEM
   {"mem", D_MEM},		/* Trace memory allocations */
-# endif /* DEBUG_MEM */
   {"mtab", D_MTAB},		/* Use local mtab file */
+  {"readdir", D_READDIR},	/* Check on browsable_dirs progress */
   {"str", D_STR},		/* Debug string munging */
-  {"test", D_TEST},		/* Full debug - but no daemon */
+  {"test", D_TEST},		/* Full debug - no daemon, no amq, local mtab */
   {"trace", D_TRACE},		/* Protocol trace */
+  {"xdrtrace", D_XDRTRACE},	/* Trace xdr routines */
   {0, 0}
 };
 #endif /* DEBUG */
@@ -144,8 +150,7 @@ am_get_progname(void)
 void
 am_set_hostname(char *hn)
 {
-  strncpy(am_hostname, hn, MAXHOSTNAMELEN);
-  am_hostname[MAXHOSTNAMELEN] = '\0';
+  xstrlcpy(am_hostname, hn, MAXHOSTNAMELEN);
 }
 
 
@@ -164,6 +169,13 @@ am_set_mypid(void)
 }
 
 
+long
+get_server_pid()
+{
+  return (long) (foreground ? am_mypid : getppid());
+}
+
+
 voidp
 xmalloc(int len)
 {
@@ -179,10 +191,8 @@ xmalloc(int len)
   do {
     p = (voidp) malloc((unsigned) len);
     if (p) {
-#if defined(DEBUG) && defined(DEBUG_MEM)
-      amuDebug(D_MEM)
-	plog(XLOG_DEBUG, "Allocated size %d; block %#x", len, p);
-#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
+      if (amuDebug(D_MEM))
+	plog(XLOG_DEBUG, "Allocated size %d; block %p", len, p);
       return p;
     }
     if (retries > 0) {
@@ -215,9 +225,8 @@ xzalloc(int len)
 voidp
 xrealloc(voidp ptr, int len)
 {
-#if defined(DEBUG) && defined(DEBUG_MEM)
-  amuDebug(D_MEM) plog(XLOG_DEBUG, "Reallocated size %d; block %#x", len, ptr);
-#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
+  if (amuDebug(D_MEM))
+    plog(XLOG_DEBUG, "Reallocated size %d; block %p", len, ptr);
 
   if (len == 0)
     len = 1;
@@ -236,20 +245,19 @@ xrealloc(voidp ptr, int len)
 }
 
 
-#if defined(DEBUG) && defined(DEBUG_MEM)
+#ifdef DEBUG_MEM
 void
 dxfree(char *file, int line, voidp ptr)
 {
-  amuDebug(D_MEM)
-    plog(XLOG_DEBUG, "Free in %s:%d: block %#x", file, line, ptr);
+  if (amuDebug(D_MEM))
+    plog(XLOG_DEBUG, "Free in %s:%d: block %p", file, line, ptr);
   /* this is the only place that must NOT use XFREE()!!! */
   free(ptr);
   ptr = NULL;			/* paranoid */
 }
-#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
 
 
-#ifdef DEBUG_MEM
+# if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY)
 static void
 checkup_mem(void)
 {
@@ -272,6 +280,7 @@ checkup_mem(void)
   }
   malloc_verify();
 }
+# endif /* not defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) */
 #endif /* DEBUG_MEM */
 
 
@@ -280,34 +289,24 @@ checkup_mem(void)
  * with the current error code taken from errno.  Make sure
  * 'e' never gets longer than maxlen characters.
  */
-static void
-expand_error(char *f, char *e, int maxlen)
+static const char *
+expand_error(const char *f, char *e, size_t maxlen)
 {
-  char *p, *q;
+  const char *p;
+  char *q;
   int error = errno;
   int len = 0;
 
-  for (p = f, q = e; (*q = *p) && len < maxlen; len++, q++, p++) {
+  for (p = f, q = e; (*q = *p) && (size_t) len < maxlen; len++, q++, p++) {
     if (p[0] == '%' && p[1] == 'm') {
-      const char *errstr;
-      if (error < 0 || error >= sys_nerr)
-	errstr = NULL;
-      else
-#ifdef HAVE_STRERROR
-	errstr = strerror(error);
-#else /* not HAVE_STRERROR */
-        errstr = sys_errlist[error];
-#endif /* not HAVE_STRERROR */
-      if (errstr)
-	strcpy(q, errstr);
-      else
-	sprintf(q, "Error %d", error);
+      xstrlcpy(q, strerror(error), maxlen);
       len += strlen(q) - 1;
       q += strlen(q) - 1;
       p++;
     }
   }
   e[maxlen-1] = '\0';		/* null terminate, to be sure */
+  return e;
 }
 
 
@@ -319,13 +318,34 @@ show_time_host_and_name(int lvl)
 {
   static time_t last_t = 0;
   static char *last_ctime = 0;
-  time_t t = clocktime();
+  time_t t;
+#if defined(HAVE_CLOCK_GETTIME) && defined(DEBUG)
+  struct timespec ts;
+#endif /* defined(HAVE_CLOCK_GETTIME) && defined(DEBUG) */
+  char nsecs[11];		/* '.' + 9 digits + '\0' */
   char *sev;
 
+  nsecs[0] = '\0';
+
+#if defined(HAVE_CLOCK_GETTIME) && defined(DEBUG)
+  /*
+   * Some systems (AIX 4.3) seem to implement clock_gettime() as stub
+   * returning ENOSYS.
+   */
+  if (clock_gettime(CLOCK_REALTIME, &ts) == 0) {
+    t = ts.tv_sec;
+    if (amuDebug(D_HRTIME))
+      xsnprintf(nsecs, sizeof(nsecs), ".%09ld", ts.tv_nsec);
+  }
+  else
+#endif /* defined(HAVE_CLOCK_GETTIME) && defined(DEBUG) */
+    t = clocktime(NULL);
+
   if (t != last_t) {
     last_ctime = ctime(&t);
     last_t = t;
   }
+
   switch (lvl) {
   case XLOG_FATAL:
     sev = "fatal:";
@@ -355,8 +375,8 @@ show_time_host_and_name(int lvl)
     sev = "hmm:  ";
     break;
   }
-  fprintf(logfp, "%15.15s %s %s[%ld]/%s ",
-	  last_ctime + 4, am_get_hostname(),
+  fprintf(logfp, "%15.15s%s %s %s[%ld]/%s ",
+	  last_ctime + 4, nsecs, am_get_hostname(),
 	  am_get_progname(),
 	  (long) am_mypid,
 	  sev);
@@ -375,7 +395,7 @@ debug_option(char *opt)
 
 
 void
-dplog(char *fmt, ...)
+dplog(const char *fmt, ...)
 {
   va_list ap;
 
@@ -390,7 +410,7 @@ dplog(char *fmt, ...)
 
 
 void
-plog(int lvl, char *fmt, ...)
+plog(int lvl, const char *fmt, ...)
 {
   va_list ap;
 
@@ -404,7 +424,7 @@ plog(int lvl, char *fmt, ...)
 
 
 static void
-real_plog(int lvl, char *fmt, va_list vargs)
+real_plog(int lvl, const char *fmt, va_list vargs)
 {
   char msg[1024];
   char efmt[1024];
@@ -416,25 +436,20 @@ real_plog(int lvl, char *fmt, va_list vargs)
     return;
 
 #ifdef DEBUG_MEM
+# if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY)
   checkup_mem();
+# endif /* not defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) */
 #endif /* DEBUG_MEM */
 
-  expand_error(fmt, efmt, 1024);
-
-#ifdef HAVE_VSNPRINTF
-  vsnprintf(ptr, 1024, efmt, vargs);
-#else /* not HAVE_VSNPRINTF */
   /*
-   * XXX: ptr is 1024 bytes long.  It is possible to write into it
-   * more than 1024 bytes, if efmt is already large, and vargs expand
-   * as well.  This is not as safe as using vsnprintf().
+   * Note: xvsnprintf() may call plog() if a truncation happened, but the
+   * latter has some code to break out of an infinite loop.  See comment in
+   * xsnprintf() below.
    */
-  vsprintf(ptr, efmt, vargs);
-  msg[1023] = '\0';		/* null terminate, to be sure */
-#endif /* not HAVE_VSNPRINTF */
+  xvsnprintf(ptr, 1023, expand_error(fmt, efmt, 1024), vargs);
 
   ptr += strlen(ptr);
-  if (ptr[-1] == '\n')
+  if (*(ptr-1) == '\n')
     *--ptr = '\0';
 
 #ifdef HAVE_SYSLOG
@@ -482,7 +497,8 @@ real_plog(int lvl, char *fmt, va_list vargs)
   switch (last_count) {
   case 0:			/* never printed at all */
     last_count = 1;
-    strncpy(last_msg, msg, 1024);
+    if (strlcpy(last_msg, msg, 1024) >= 1024) /* don't use xstrlcpy here (recursive!) */
+      fprintf(stderr, "real_plog: string \"%s\" truncated to \"%s\"\n", last_msg, msg);
     last_lvl = lvl;
     show_time_host_and_name(lvl); /* mimic syslog header */
     fwrite(msg, ptr - msg, 1, logfp);
@@ -494,7 +510,8 @@ real_plog(int lvl, char *fmt, va_list vargs)
       last_count++;
     } else {			/* last msg printed once, new one differs */
       /* last_count remains at 1 */
-      strncpy(last_msg, msg, 1024);
+      if (strlcpy(last_msg, msg, 1024) >= 1024) /* don't use xstrlcpy here (recursive!) */
+	fprintf(stderr, "real_plog: string \"%s\" truncated to \"%s\"\n", last_msg, msg);
       last_lvl = lvl;
       show_time_host_and_name(lvl); /* mimic syslog header */
       fwrite(msg, ptr - msg, 1, logfp);
@@ -508,7 +525,8 @@ real_plog(int lvl, char *fmt, va_list vargs)
      * cycles like crazy.
      */
     show_time_host_and_name(last_lvl);
-    sprintf(last_msg, "last message repeated %d times\n", last_count);
+    xsnprintf(last_msg, sizeof(last_msg),
+	      "last message repeated %d times\n", last_count);
     fwrite(last_msg, strlen(last_msg), 1, logfp);
     fflush(logfp);
     last_count = 0;		/* start from scratch */
@@ -519,9 +537,11 @@ real_plog(int lvl, char *fmt, va_list vargs)
       last_count++;
     } else {		/* last msg repeated+skipped, new one differs */
       show_time_host_and_name(last_lvl);
-      sprintf(last_msg, "last message repeated %d times\n", last_count);
+      xsnprintf(last_msg, sizeof(last_msg),
+		"last message repeated %d times\n", last_count);
       fwrite(last_msg, strlen(last_msg), 1, logfp);
-      strncpy(last_msg, msg, 1024);
+      if (strlcpy(last_msg, msg, 1024) >= 1024) /* don't use xstrlcpy here (recursive!) */
+	fprintf(stderr, "real_plog: string \"%s\" truncated to \"%s\"\n", last_msg, msg);
       last_count = 1;
       last_lvl = lvl;
       show_time_host_and_name(lvl); /* mimic syslog header */
@@ -644,6 +664,7 @@ switch_option(char *opt)
   return rc;
 }
 
+
 #ifdef LOG_DAEMON
 /*
  * get syslog facility to use.
@@ -748,7 +769,7 @@ get_syslog_facility(const char *logfile)
  * Change current logfile
  */
 int
-switch_to_logfile(char *logfile, int old_umask)
+switch_to_logfile(char *logfile, int old_umask, int truncate_log)
 {
   FILE *new_logfp = stderr;
 
@@ -766,9 +787,6 @@ switch_to_logfile(char *logfile, int old_umask)
       new_logfp = stderr;
       openlog(am_get_progname(),
 	      LOG_PID
-# ifdef LOG_CONS
-	      | LOG_CONS
-# endif /* LOG_CONS */
 # ifdef LOG_NOWAIT
 	      | LOG_NOWAIT
 # endif /* LOG_NOWAIT */
@@ -780,8 +798,10 @@ switch_to_logfile(char *logfile, int old_umask)
       plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
 #endif /* not HAVE_SYSLOG */
 
-    } else {
+    } else {			/* regular log file */
       (void) umask(old_umask);
+      if (truncate_log)
+	truncate(logfile, 0);
       new_logfp = fopen(logfile, "a");
       umask(0);
     }
@@ -802,7 +822,11 @@ switch_to_logfile(char *logfile, int old_umask)
     (void) fclose(logfp);
   logfp = new_logfp;
 
-  plog(XLOG_INFO, "switched to logfile \"%s\"", logfile);
+  if (logfile)
+    plog(XLOG_INFO, "switched to logfile \"%s\"", logfile);
+  else
+    plog(XLOG_INFO, "no logfile defined; using stderr");
+
   return 0;
 }
 
@@ -810,11 +834,14 @@ switch_to_logfile(char *logfile, int old_umask)
 void
 unregister_amq(void)
 {
-#ifdef DEBUG
-  amuDebug(D_AMQ)
-#endif /* DEBUG */
+  if (!amuDebug(D_AMQ)) {
     /* find which instance of amd to unregister */
-    pmap_unset(get_amd_program_number(), AMQ_VERSION);
+    u_long amd_prognum = get_amd_program_number();
+
+    if (pmap_unset(amd_prognum, AMQ_VERSION) != 1)
+      dlog("failed to de-register Amd program %lu, version %lu",
+	   amd_prognum, AMQ_VERSION);
+  }
 }
 
 
@@ -828,14 +855,21 @@ going_down(int rc)
       unregister_amq();
     }
   }
+
+#ifdef MOUNT_TABLE_ON_FILE
+  /*
+   * Call unlock_mntlist to free any important resources such as an on-disk
+   * lock file (/etc/mtab~).
+   */
+  unlock_mntlist();
+#endif /* MOUNT_TABLE_ON_FILE */
+
   if (foreground) {
     plog(XLOG_INFO, "Finishing with status %d", rc);
   } else {
-#ifdef DEBUG
     dlog("background process exiting with status %d", rc);
-#endif /* DEBUG */
   }
-
+  /* bye bye... */
   exit(rc);
 }
 
@@ -869,9 +903,33 @@ set_amd_program_number(int program)
 void
 amu_release_controlling_tty(void)
 {
-#ifdef TIOCNOTTY
   int fd;
-#endif /* TIOCNOTTY */
+
+  /*
+   * In daemon mode, leaving open file descriptors to terminals or pipes
+   * can be a really bad idea.
+   * Case in point: the redhat startup script calls us through their 'initlog'
+   * program, which exits as soon as the original amd process exits. If,
+   * at some point, a misbehaved library function decides to print something
+   * to the screen, we get a SIGPIPE and die.
+   * And guess what: NIS glibc functions will attempt to print to stderr
+   * "YPBINDPROC_DOMAIN: Domain not bound" if ypbind is running but can't find
+   * a ypserver.
+   *
+   * So we close all of our "terminal" filedescriptors, i.e. 0, 1 and 2, then
+   * reopen them as /dev/null.
+   *
+   * XXX We should also probably set the SIGPIPE handler to SIG_IGN.
+   */
+  fd = open("/dev/null", O_RDWR);
+  if (fd < 0) {
+    plog(XLOG_WARNING, "Could not open /dev/null for rw: %m");
+  } else {
+    fflush(stdin);  close(0); dup2(fd, 0);
+    fflush(stdout); close(1); dup2(fd, 1);
+    fflush(stderr); close(2); dup2(fd, 2);
+    close(fd);
+  }
 
 #ifdef HAVE_SETSID
   /* XXX: one day maybe use vhangup(2) */
@@ -901,3 +959,133 @@ amu_release_controlling_tty(void)
 
   plog(XLOG_ERROR, "unable to release controlling tty");
 }
+
+
+/* setup a single signal handler */
+void
+setup_sighandler(int signum, void (*handler)(int))
+{
+#ifdef HAVE_SIGACTION
+  struct sigaction sa;
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_flags = 0;		/* unnecessary */
+  sa.sa_handler = handler;
+  sigemptyset(&(sa.sa_mask));	/* probably unnecessary too */
+  sigaddset(&(sa.sa_mask), signum);
+  sigaction(signum, &sa, NULL);
+#else /* not HAVE_SIGACTION */
+  (void) signal(signum, handler);
+#endif /* not HAVE_SIGACTION */
+}
+
+
+/*
+ * Return current time in seconds.  If passed a non-null argyument, then
+ * fill it in with the current time in seconds and microseconds (useful
+ * for mtime updates).
+ */
+time_t
+clocktime(nfstime *nt)
+{
+  static struct timeval now;	/* keep last time, as default */
+
+  if (gettimeofday(&now, NULL) < 0) {
+    plog(XLOG_ERROR, "clocktime: gettimeofday: %m");
+    /* hack: force time to have incremented by at least 1 second */
+    now.tv_sec++;
+  }
+  /* copy seconds and microseconds. may demote a long to an int */
+  if (nt) {
+    nt->nt_seconds = (u_int) now.tv_sec;
+    nt->nt_useconds = (u_int) now.tv_usec;
+  }
+  return (time_t) now.tv_sec;
+}
+
+
+/*
+ * Make all the directories in the path.
+ */
+int
+mkdirs(char *path, int mode)
+{
+  /*
+   * take a copy in case path is in readonly store
+   */
+  char *p2 = strdup(path);
+  char *sp = p2;
+  struct stat stb;
+  int error_so_far = 0;
+
+  /*
+   * Skip through the string make the directories.
+   * Mostly ignore errors - the result is tested at the end.
+   *
+   * This assumes we are root so that we can do mkdir in a
+   * mode 555 directory...
+   */
+  while ((sp = strchr(sp + 1, '/'))) {
+    *sp = '\0';
+    if (mkdir(p2, mode) < 0) {
+      error_so_far = errno;
+    } else {
+      dlog("mkdir(%s)", p2);
+    }
+    *sp = '/';
+  }
+
+  if (mkdir(p2, mode) < 0) {
+    error_so_far = errno;
+  } else {
+    dlog("mkdir(%s)", p2);
+  }
+
+  XFREE(p2);
+
+  return stat(path, &stb) == 0 &&
+    (stb.st_mode & S_IFMT) == S_IFDIR ? 0 : error_so_far;
+}
+
+
+/*
+ * Remove as many directories in the path as possible.
+ * Give up if the directory doesn't appear to have
+ * been created by Amd (not mode dr-x) or an rmdir
+ * fails for any reason.
+ */
+void
+rmdirs(char *dir)
+{
+  char *xdp = strdup(dir);
+  char *dp;
+
+  do {
+    struct stat stb;
+    /*
+     * Try to find out whether this was
+     * created by amd.  Do this by checking
+     * for owner write permission.
+     */
+    if (stat(xdp, &stb) == 0 && (stb.st_mode & 0200) == 0) {
+      if (rmdir(xdp) < 0) {
+	if (errno != ENOTEMPTY &&
+	    errno != EBUSY &&
+	    errno != EEXIST &&
+	    errno != EROFS &&
+	    errno != EINVAL)
+	  plog(XLOG_ERROR, "rmdir(%s): %m", xdp);
+	break;
+      } else {
+	dlog("rmdir(%s)", xdp);
+      }
+    } else {
+      break;
+    }
+
+    dp = strrchr(xdp, '/');
+    if (dp)
+      *dp = '\0';
+  } while (dp && dp > xdp);
+
+  XFREE(xdp);
+}
diff --git a/contrib/amd/mk-amd-map/mk-amd-map.8 b/contrib/amd/mk-amd-map/mk-amd-map.8
index 1f941eb..687508a 100644
--- a/contrib/amd/mk-amd-map/mk-amd-map.8
+++ b/contrib/amd/mk-amd-map/mk-amd-map.8
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-1999 Erez Zadok
+.\" Copyright (c) 1997-2006 Erez Zadok
 .\" Copyright (c) 1993 Jan-Simon Pendry
 .\" Copyright (c) 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -33,22 +33,24 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     from: @(#)mk-amd-map.8	8.1 (Berkeley) 6/28/93
-.\"	$Id: mk-amd-map.8,v 1.2 1999/01/10 21:54:41 ezk Exp $
-.\"	$FreeBSD: src/contrib/amd/mk-amd-map/mk-amd-map.8,v 1.3.2.1 2001/08/16 10:53:40 ru Exp $
-.\"	$DragonFly: src/contrib/amd/mk-amd-map/mk-amd-map.8,v 1.2 2003/06/17 04:23:57 dillon Exp $
+.\"	$Id: mk-amd-map.8,v 1.9.2.1 2006/01/02 18:48:26 ezk Exp $
+.\"	$FreeBSD: src/contrib/amd/mk-amd-map/mk-amd-map.8,v 1.10 2012/11/17 01:48:41 svnexp Exp $
 .\"
-.Dd June 28, 1993
+.Dd January 2, 2006
 .Dt MK-AMD-MAP 8
 .Os
 .Sh NAME
 .Nm mk-amd-map
-.Nd create database maps for Amd
+.Nd create database maps for
+.Xr amd 8
 .Sh SYNOPSIS
 .Nm
 .Op Fl p
 .Ar mapname
 .Sh DESCRIPTION
+The
 .Nm
+utility
 creates the database maps used by the keyed map lookups in
 .Xr amd 8 .
 It reads input from the named file
@@ -58,8 +60,35 @@ hashed database.
 The
 .Fl p
 option prints the map on standard output instead of generating
-a database.  This is usually used to merge continuation lines
+a database.
+This is usually used to merge continuation lines
 into one physical line.
 .Sh SEE ALSO
 .Xr amd.conf 5 ,
 .Xr amd 8
+.Pp
+.Dq am-utils
+.Xr info 1
+entry.
+.Rs
+.%A Erez Zadok
+.%B "Linux NFS and Automounter Administration"
+.%O ISBN 0-7821-2739-8
+.%I Sybex
+.%D 2001
+.Re
+.Pp
+.Pa http://www.am-utils.org/
+.Rs
+.%T Amd \- The 4.4 BSD Automounter
+.Re
+.Sh AUTHORS
+.An Jan-Simon Pendry Aq jsp@doc.ic.ac.uk ,
+Department of Computing, Imperial College, London, UK.
+.Pp
+.An Erez Zadok Aq ezk@cs.sunysb.edu ,
+Computer Science Department, Stony Brook University, New York, USA
+.Pp
+Other authors and contributors to am-utils are listed in the
+.Pa AUTHORS
+file distributed with am-utils.
diff --git a/contrib/amd/mk-amd-map/mk-amd-map.c b/contrib/amd/mk-amd-map/mk-amd-map.c
index da428c7..48d82b0 100644
--- a/contrib/amd/mk-amd-map/mk-amd-map.c
+++ b/contrib/amd/mk-amd-map/mk-amd-map.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: mk-amd-map.c,v 1.4 1999/02/04 07:24:50 ezk Exp $
- * $FreeBSD: src/contrib/amd/mk-amd-map/mk-amd-map.c,v 1.7 1999/09/15 05:45:16 obrien Exp $
- * $DragonFly: src/contrib/amd/mk-amd-map/mk-amd-map.c,v 1.2 2003/06/17 04:23:58 dillon Exp $
+ * File: am-utils/mk-amd-map/mk-amd-map.c
  */
 
 /*
@@ -225,7 +222,7 @@ main(int argc, char *argv[])
   char maptpag[16], maptdir[16];
   char *map_name_pag = (char *) NULL, *map_name_dir = (char *) NULL;
 #endif /* not HAVE_DB_SUFFIX */
-  int len;
+  size_t l = 0;
   char *sl;
   int printit = 0;
   int usage = 0;
@@ -274,13 +271,14 @@ main(int argc, char *argv[])
 #endif /* DEBUG */
 
   if (!printit) {
-    len = strlen(mapsrc);
+    /* enough space for ".db" or ".pag" or ".dir" appended */
+    l = strlen(mapsrc) + 5;
 #ifdef HAVE_DB_SUFFIX
-    map_name_db = (char *) malloc(len + 4);
+    map_name_db = (char *) malloc(l);
     error = (map_name_db == NULL);
 #else /* not HAVE_DB_SUFFIX */
-    map_name_pag = (char *) malloc(len + 5);
-    map_name_dir = (char *) malloc(len + 5);
+    map_name_pag = (char *) malloc(l);
+    map_name_dir = (char *) malloc(l);
     error = (map_name_pag == NULL || map_name_dir == NULL);
 #endif /* not HAVE_DB_SUFFIX */
     if (error) {
@@ -288,19 +286,34 @@ main(int argc, char *argv[])
       exit(1);
     }
 
+#ifdef HAVE_MKSTEMP
+    {
+      /*
+       * XXX: hack to avoid compiler complaints about mktemp not being
+       * secure, since we have to do a dbm_open on this anyway.  So use
+       * mkstemp if you can, and then close the fd, but we get a safe
+       * and unique file name.
+       */
+      int dummyfd;
+      dummyfd = mkstemp(maptmp);
+      if (dummyfd >= 0)
+	close(dummyfd);
+    }
+#else /* not HAVE_MKSTEMP */
     mktemp(maptmp);
+#endif /* not HAVE_MKSTEMP */
 
     /* remove existing temps (if any) */
 #ifdef HAVE_DB_SUFFIX
-    sprintf(maptdb, "%s.db", maptmp);
+    xsnprintf(maptdb, sizeof(maptdb), "%s.db", maptmp);
     if (remove_file(maptdb) < 0) {
       fprintf(stderr, "Can't remove existing temporary file; ");
       perror(maptdb);
       exit(1);
     }
 #else /* not HAVE_DB_SUFFIX */
-    sprintf(maptpag, "%s.pag", maptmp);
-    sprintf(maptdir, "%s.dir", maptmp);
+    xsnprintf(maptpag, sizeof(maptpag), "%s.pag", maptmp);
+    xsnprintf(maptdir, sizeof(maptdir), "%s.dir", maptmp);
     if (remove_file(maptpag) < 0 || remove_file(maptdir) < 0) {
       fprintf(stderr, "Can't remove existing temporary files; %s and ", maptpag);
       perror(maptdir);
@@ -308,7 +321,7 @@ main(int argc, char *argv[])
     }
 #endif /* not HAVE_DB_SUFFIX */
 
-    db = dbm_open(maptmp, O_RDWR|O_CREAT, 0444);
+    db = dbm_open(maptmp, O_RDWR|O_CREAT|O_EXCL, 0444);
     if (!db) {
       fprintf(stderr, "cannot initialize temporary database: %s", maptmp);
       exit(1);
@@ -335,7 +348,8 @@ main(int argc, char *argv[])
   /* all went well */
 
 #ifdef HAVE_DB_SUFFIX
-  sprintf(map_name_db, "%s.db", mapsrc);
+  /* sizeof(map_name_db) is malloc'ed above */
+  xsnprintf(map_name_db, l, "%s.db", mapsrc);
   if (rename(maptdb, map_name_db) < 0) {
     fprintf(stderr, "Couldn't rename %s to ", maptdb);
     perror(map_name_db);
@@ -344,8 +358,9 @@ main(int argc, char *argv[])
     exit(1);
   }
 #else /* not HAVE_DB_SUFFIX */
-  sprintf(map_name_pag, "%s.pag", mapsrc);
-  sprintf(map_name_dir, "%s.dir", mapsrc);
+  /* sizeof(map_name_{pag,dir}) are malloc'ed above */
+  xsnprintf(map_name_pag, l, "%s.pag", mapsrc);
+  xsnprintf(map_name_dir, l, "%s.dir", mapsrc);
   if (rename(maptpag, map_name_pag) < 0) {
     fprintf(stderr, "Couldn't rename %s to ", maptpag);
     perror(map_name_pag);
diff --git a/contrib/amd/scripts/am-eject.in b/contrib/amd/scripts/am-eject.in
index ed7e2d0..8754a3b 100644
--- a/contrib/amd/scripts/am-eject.in
+++ b/contrib/amd/scripts/am-eject.in
@@ -2,7 +2,7 @@
 # auto-unmount floppy/cd directory before ejecting device
 # script taken from Debian Linux's amd
 #
-# Package:		am-utils-6.0
+# Package:		am-utils-6.x
 # (Additional) author:	Erez Zadok <ezk@cs.columbia.edu>
 
 # set path
@@ -12,7 +12,7 @@ PATH=@sbindir@:@bindir@:/usr/ucb:/usr/bin:/bin:${PATH}
 export PATH
 
 if [ $# -ne 1 ]; then
-	echo "Usage: $0 cd|fd"
+	echo "Usage: $0 cd|cdrom|fd|floppy"
 	exit 2
 fi
 
@@ -26,7 +26,7 @@ fi
 # append name of medium
 case "$1" in
   cd|fd) fs=$fs/$1;;
-  *)	 echo "Usage: $0 cd|fd"; exit 2;;
+  *)	 echo "Usage: $0 cd|cdrom|fd|floppy"; exit 2;;
 esac
 
 # is the medium mounted?
@@ -47,6 +47,7 @@ else
 fi
 
 case $1 in
-  cd)	eject;; # eject CD-ROM
-  fd)	echo "Ok to remove disk";;
+  cd|cdrom)	eject cdrom || eject ;; # eject CD-ROM
+  fd|floppy)	eject floppy || eject
+		echo "Ok to remove disk" ;;
 esac
diff --git a/contrib/amd/scripts/amd.conf-sample b/contrib/amd/scripts/amd.conf-sample
index 9a60e2d..880a74b 100644
--- a/contrib/amd/scripts/amd.conf-sample
+++ b/contrib/amd/scripts/amd.conf-sample
@@ -1,17 +1,20 @@
-# -*- text -*-
 # A SAMPLE CONFIGURATION FILE FOR AMD
 
 ##############################################################################
 # GLOBAL OPTIONS SECTION (must be first in amd.conf file)
+# For most options, the default value is listed first, but see amd.conf(5)
 [ global ]
 # (amd -n)
-normalize_hostnames =		yes | no
+normalize_hostnames =		no | yes
+# do we want to strip domain names from hostnames or not?
+domain_strip =			yes | no
 # (amd -p)
-print_pid =			yes | no
+print_pid =			no | yes
 pid_file =			/dev/stdout | /var/run/amd.pid
 # (amd -r)
-restart_mounts =		yes | no
+restart_mounts =		no | yes
 unmount_on_exit =		no | yes
+forced_unmounts =		no | yes
 # (amd -a)
 auto_dir =			/a
 # duration in seconds that a looked up name remain cached (amd -c)
@@ -20,8 +23,10 @@ cache_duration =		300
 local_domain =			cs.columbia.edu
 # (amd -k)
 karch =				sun4m
+# (amd -A)
 arch =				sun4
 # if you don't like autoconf picking up "sunos5" as the os-type, override it
+# (amd -O)
 os =				sos5
 # (amd -o)
 osver =				2.5.1
@@ -30,12 +35,28 @@ full_os =			linux-2.2.5
 # OS vendor
 vendor =			redhat
 # if you print_version after setting up "os", it will show it. (amd -v)
-print_version =			yes | no
+print_version =			no | yes
 # (amd -l)
-log_file =			/var/log/amd | syslog | syslog:facility
-# NFS (RPC/UDP) retry interval, in tenths of secs (amd -t interval.counter)
+log_file =			/dev/stderr | /var/log/amd | syslog[:facility]
+# should we truncate the log file on startup?
+truncate_log =			no | yes
+# NFS (RPC) retry interval/counter, in tenths of secs (amd -t interval.counter)
 nfs_retry_interval =		8
-nfs_retransmit_counter =	110
+nfs_retransmit_counter =	11 (eleven retransmission attempts)
+# The next four are the same as the above two, but allow you to set global
+# values for all UDP vs. TCP mounts separately.
+nfs_retry_interval_udp =	16
+nfs_retransmit_counter_udp =	22
+nfs_retry_interval_tcp =	4
+nfs_retransmit_counter_tcp =	5
+# These two are specific to Amd's top-level (NFSv2/udp) mounts
+# and they can also be set separately.
+nfs_retry_interval_toplvl =	6
+nfs_retransmit_counter_toplvl =	8
+# NFS attribute cache value for Amd's automount points
+# (some OSs use this parameter in units of seconds, and others in 0.1 seconds)
+# See README.attrcache for important information about this parameter.
+auto_attrcache =		0
 # (amd -w)
 dismount_interval =		120
 # (amd -y)
@@ -43,32 +64,62 @@ nis_domain =			nisDom-CS.columbia.edu
 # (amd -x)
 log_options =			fatal,error,user,warn,info,map,stats,all
 # (amd -D)
-debug_options =		all,amq,daemon,fork,full,info,mem,mtab,str,test,trace
+debug_options =			all,amq,daemon,fork,full,hrtime,info,mem,mtab,\
+				str,readdir,test,trace,xdrtrace
+# path for mtab file during mtab debug mode
+debug_mtab_file =               /tmp/mnttab
 # (amd -S)
-plock =				no | yes
-# selectors on /defaults are off by default
-selectors_on_default =		yes | no
+plock =				yes | no
 # should browsable maps show number of entries to df/statfs (default=no)
-show_statfs_entries =		yes | no
+show_statfs_entries =		no | yes
 # (hpux) cluster name (amd -C)
 cluster =			???
 # LDAP (Lightweight Directory Access Protocol) options
-ldap_base =			ldap.your.domain:389
-ldap_hostports =		"ou=Marketing, o=AMD Ltd, c=US"
-ldap_cache_seconds =		0 (default)
-ldap_cache_maxmem =		131072 (default)
+ldap_base =			"ou=Marketing, o=AMD Ltd, c=US"
+ldap_hostports =		ldap.your.domain:389
+ldap_cache_seconds =		0
+ldap_cache_maxmem =		131072
+ldap_proto_version =		2
 # default base name for hesiod maps
 hesiod_base =			automount
-# these 5 options can be overridden by each map individually
-browsable_dirs =		yes | no | full
+# interval to check if a reload of any maps is needed
+map_reload_interval =		3600
+# alternate RPC program number to register with the port mapper
+portmap_program =		300019-300029
+# Ask for a different Amq RPC port (both UDP and TCP).
+# If set to 0 (default), Amd will pick a port automatically.
+preferred_amq_port =		1234
+# use fully qualified host names
+fully_qualified_hosts =		no | yes
+# force NFS version or NFS protocol
+nfs_vers =			2 | 3
+nfs_proto =			udp | tcp
+# perform Amq service checks via tcpwrappers (tcpd/libwrap)
+use_tcpwrappers =		yes | no
+# allow NFS requests from insecure (>=1024) ports
+nfs_allow_insecure_port =	no | yes
+# accept local NFS packets from any local interface, not just 127.0.0.1
+nfs_allow_any_interface =	no | yes
+# address used for local NFS mount and RPC server (default to localhost)
+localhost_address =		foo.example.com | 192.168.1.2
+# number of seconds to timeout before map returns output
+exec_map_timeout =		10
+# normalize multiple/trailing slashes or not?
+normalize_slashes =		yes | no
+
+##############################################################################
+# these 8 global options can be overridden by each map individually
+browsable_dirs =		no | yes | full
 map_options =			cache:=all
 map_type =			file|hesiod|ndbm|nis|nisplus|passwd|union|ldap
+# any string that will be used to override to the map /defaults entry
+map_defaults =			opts:=nosuid,rw,intr,bg,noquota;type:=link
 mount_type =			nfs | autofs
+autofs_use_lofs =		yes | no
 search_path =			/etc/local:/etc/amdmaps:/misc/yp
-# alternate RPC program number to register with the port mapper
-portmap_program =		300019-300029
-# Use fully qualified host names
-fully_qualified_hosts =		yes | no
+# selectors are not recognized by default in the /defaults entry
+selectors_in_defaults =		no | yes
+##############################################################################
 
 ##############################################################################
 # DEFINE AN AMD MOUNT POINT
@@ -89,9 +140,25 @@ tag =				test
 ##############################################################################
 # DEFINE ANOTHER AMD MOUNT POINT
 [ /src ]
-map_name = /usr/local/lib/amdmaps/amu.src
+map_name =			/usr/local/lib/amdmaps/amu.src
 # regular amd (nfs) mount point (default)
-# don't try the "autofs" type.  It is not implemented yet.
-mount_type = nfs
+mount_type =			nfs
+# any string that will be used as prefix to the map /defaults entry
+# this overrides what's defined in [global]
+map_defaults =			type:=nfs
+
+##############################################################################
+# DEFINE ANOTHER AMD MOUNT POINT
+[ /test ]
+map_name =			/etc/lookup-entry.sh
+# an executable map type
+map_type =			exec
+
+##############################################################################
+# DEFINE A SUN SYNTAX MOUNT POINT
+[ /proj ]
+map_name =			/etc/amd.proj
+# does this map use Sun Automounter map syntax?
+sun_map_syntax =		yes
 
 ##############################################################################
diff --git a/contrib/amd/scripts/amd.conf.5 b/contrib/amd/scripts/amd.conf.5
index 5017ebb..147e567 100644
--- a/contrib/amd/scripts/amd.conf.5
+++ b/contrib/amd/scripts/amd.conf.5
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-1999 Erez Zadok
+.\" Copyright (c) 1997-2006 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.
@@ -38,64 +38,82 @@
 .\"
 .\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: amd.conf.5,v 1.3 1999/03/30 17:23:08 ezk Exp $
-.\" $FreeBSD: src/contrib/amd/scripts/amd.conf.5,v 1.9.2.3 2001/08/16 10:53:40 ru Exp $
-.\" $DragonFly: src/contrib/amd/scripts/amd.conf.5,v 1.2 2003/06/17 04:23:58 dillon Exp $
+.\" $Id: amd.conf.5,v 1.39.2.5 2006/04/21 01:12:04 ezk Exp $
+.\" $FreeBSD: src/contrib/amd/scripts/amd.conf.5,v 1.21 2012/11/17 01:48:41 svnexp Exp $
 .\"
-.Dd April 7, 1997
+.Dd April 21, 2006
 .Dt AMD.CONF 5
 .Os
 .Sh NAME
 .Nm amd.conf
-.Nd amd configuration file
+.Nd
+.Xr amd 8
+configuration file
 .Sh SYNOPSIS
 .Nm
 .Sh DESCRIPTION
 The
 .Nm
-file is the configuration file for amd, as part of the am-utils suite.
+file is the configuration file for
+.Xr amd 8 ,
+as part of the am-utils suite.
 .Pp
+The
 .Nm
+file
 contains runtime configuration information for the
 .Xr amd 8
 automounter program.
 .Sh FILE FORMAT
-The file consists of sections and parameters.  A section begins with the
+The file consists of sections and parameters.
+A section begins with the
 name of the section in square brackets and continues until the next section
-begins or the end of the file is reached.  Sections contain parameters of
-the form 
-.Sq name = value .
+begins or the end of the file is reached.
+Sections contain parameters of the
+form
+.Dq Ar name No = Ar value .
 .Pp
-The file is line-based - that is, each newline-terminated line represents
-either a comment, a section name or a parameter.  No line-continuation
+The file is line-based \[em] that is, each newline-terminated line represents
+either a comment, a section name or a parameter.
+No line-continuation
 syntax is available.
 .Pp
 Section, parameter names and their values are case sensitive.
 .Pp
-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
+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 
-.Sq name = Qq some\ value .
+parameter value is quoted with double quotes as in
+.Dq Ar name No = Qq Li "some\ value" .
 .Pp
 Any line beginning with a pound sign (#) is ignored, as are lines containing
 only whitespace.
 .Pp
 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 yes/no.  Case is significant in all values.  Some items such as
+be given as
+.Dq Li yes/no .
+Case is significant in all values.
+Some items such as
 cache timeouts are numeric.
 .Sh SECTIONS
 .Ss "The [global] section"
-Parameters in this section either apply to 
+Parameters in this section either apply to
 .Nm 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.
+as a whole, or to all other
+regular map sections which follow.
+There should be only one global section
+defined in one configuration file.
 .Pp
 It is highly recommended that this section be specified first in the
-configuration file.  If it is not, then regular map sections which precede
+configuration file.
+If it is not, then regular map sections which precede
 it will not use global values defined later.
 .Ss "Regular [/map] sections"
 Parameters in regular (non-global) sections apply to a single map entry.
@@ -103,598 +121,908 @@ For example, if the map section
 .Bq Pa /homes
 is defined, then all parameters following it will be applied to the
 .Pa /homes
-amd-managed mount point.
+.Nm amd Ns
+-managed mount point.
 .Sh PARAMETERS
 .Ss "Parameters common to all sections"
 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
+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.
 .Bl -tag -width 4n
-.It Ic browsable_dirs Xo
-(string, default=no)
-.Xc
-If 
-.Qq yes , 
-then amd's top-level mount points will be browsable to
+.It Va browsable_dirs Pq string, default=no
+If
+.Dq Li yes ,
+then
+.Nm amd Ns 's
+top-level mount points will be browsable to
 .Xr readdir 3
-calls.  This means you could run for example
+calls.
+This means you could run for example
 .Xr ls 1
-and see what keys are available to mount in that directory.  Not all entries
-are made visible to 
+and see what keys are available to mount in that directory.
+Not all entries
+are made visible to
 .Xr readdir 3 :
-the 
-.Qq Pa /default
-entry, wildcardentries, and those with a 
-.Qq Pa / 
-in them are not included.  If you specify 
-.Qq full
-to this option, all but 
-.Qq Pa /default
-will be visible.  Note that if you run a command which will attempt to
+the
+.Dq Li /default
+entry, wildcard entries, and those with a
+.Ql /
+in them are not included.
+If you specify
+.Dq Li full
+to this option, all but
+.Dq Li /default
+will be visible.
+Note that if you run a command which will attempt to
 .Xr stat 2
-the entries, such as often done by 
-.Qq ls -l
+the entries, such as often done by
+.Dq Li "ls -l"
 or
-.Qq ls -F ,
-.Nm amd
-will attempt to mount 
+.Dq Li "ls -F" ,
+.Xr amd 8
+will attempt to mount
 .Em every
-entry in that map.  This is often called a 
-.Em mount storm .
-.It Ic map_options Xo
-(string, default no options)
-.Xc
-This option is the same as specifying map options on the command line to 
-.Nm amd ,
+entry in that map.
+This is often called a
+.Dq "mount storm" .
+.It Va map_defaults Pq string, default no empty
+This option sets a string to be used as the map's /defaults entry,
+overriding any /defaults specified in the map.
+This allows local users to
+override map defaults without modifying maps globally.
+.It Va map_options Pq string, default no options
+This option is the same as specifying map options on the command line to
+.Xr amd 8 ,
 such as
-.Ql cache\&:\&=all .
-.It Ic map_type Xo
-(string, default search all map types)
-.Xc
-If specified, amd will initialize the map only for the type given.   
-This is useful to avoid the default map search type used by amd which 
-takes longer and can have undesired side-effects such as initializing 
-NIS even if not used.  Possible values are:
+.Dq Li "cache:=all" .
+.It Va map_type Pq string, default search all map types
+If specified,
+.Xr amd 8
+will initialize the map only for the type given.
+This is
+useful to avoid the default map search type used by
+.Xr amd 8
+which takes longer
+and can have undesired side-effects such as initializing
+.Tn NIS
+even if not
+used.
+Possible values are:
 .Pp
-.Bl -tag -width "nisplus" -compact
-.It Ic file
+.Bl -tag -width ".Cm nisplus" -compact
+.It Cm exec
+executable maps
+.It Cm file
 plain files
-.It Ic hesiod
+.It Cm hesiod
 Hesiod name service from MIT
-.It Ic ldap
+.It Cm ldap
 Lightweight Directory Access Protocol
-.It Ic ndbm
+.It Cm ndbm
 (New) dbm style hash files
-.It Ic nis
+.It Cm nis
 Network Information Services (version 2)
-.It Ic nisplus
+.It Cm nisplus
 Network Information Services Plus (version 3)
-.It Ic passwd
+.It Cm passwd
 local password files
-.It Ic union 
+.It Cm union
 union maps
 .El
-.It Ic mount_type Xo
-(string, default=nfs)
-.Xc
-All amd mount types default to
+.It Va mount_type Pq string, default=nfs
+All
+.Xr amd 8
+mount types default to
 .Tn NFS .
 That is,
-.Nm amd
+.Xr amd 8
 is an
 .Tn NFS
-server on the map mount points, for the local host it is running on.  If 
-.Qq autofs 
-is specified, amd will be an autofs server for those mount points.
-.It Ic search_path Xo
-(string, default no search path)
-.Xc
-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.
+server on the
+map mount points, for the local host it is running on.
+If
+.Dq Li autofs
+is specified,
+.Xr amd 8
+will be an autofs server for those mount points.
+.It Va autofs_use_lofs Pq string, default=yes
+When set to
+.Dq Li yes
+and using Autofs,
+.Xr amd 8
+will use lofs-type (loopback) mounts
+for type:=link mounts.
+This has the advantage of mounting in place, and
+users get to the see the same pathname that they chdir'ed into.
+If this
+option is set to
+.Dq Li no ,
+then
+.Xr amd 8
+will use symlinks instead: that code is more
+tested, but negates autofs's big advantage of in-place mounts.
+.It Va search_path Pq 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
+query
+distributed maps in several locations as needed.
+.It Va selectors_in_defaults Pq boolean, default=no
+If
+.Dq Li yes ,
+then the /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:
+.Bd -literal
+/defaults \\
+	wire==slip-net;opts:=intr,rsize=1024,wsize=1024 \\
+	wire!=slip-net;opts:=intr,rsize=8192,wsize=8192
+.Ed
+Deprecated form: selectors_on_default
 .El
 .Ss "Parameters applicable to the global section only"
 .Bl -tag -width 4n
-.It Ic arch Xo
-(string, default to compiled in value)
-.Xc
+.It Va arch Pq string, default to compiled in value
+Same as the
+.Fl A
+option to
+.Xr amd 8 .
 Allows you to override the value of the
 .Va arch
-.Nm amd
+.Xr amd 8
 variable.
-.It Ic auto_dir Xo
-(string, default=/a)
-.Xc
-Same as the 
+.It Va auto_attrcache Pq 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
+.Nm amd Ns 's
+own automount
+points.
+A value of 0 is supposed to turn off attribute caching, meaning
+that
+.Xr amd 8
+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).
+Warning: some OSs are incapable of turning off the NFS attribute cache
+reliably.
+On such systems,
+.Nm amd
+may not work reliably under heavy load.
+See
+the
+.Pa README.attrcache
+document in the Am-utils distribution for more details.
+.It Va auto_dir Pq string, default= Ns Pa /a
+Same as the
 .Fl a
 option to
-.Nm amd .
-This sets the private directory where amd will create sub-directories for its
-real mount points.
-.It Ic cache_duration Xo
-(numeric, default=300)
-.Xc
+.Xr amd 8 .
+This sets the private directory where
+.Nm amd
+will create
+sub-directories for its real mount points.
+.It Va cache_duration Pq numeric, default=300
 Same as the
 .Fl c
 option to
-.Nm amd .
-Sets the duration in seconds that looked up map entries remain in the cache.
-.It Ic cluster Xo
-(string, default no cluster)
-.Xc
+.Xr amd 8 .
+Sets the duration in seconds that looked-up or mounted map
+entries remain in the cache.
+.It Va cluster Pq string, default no cluster
 Same as the
 .Fl C
 option to
-.Nm amd .
+.Xr amd 8 .
 Specifies the alternate
 .Tn HP-UX
 cluster to use.
-.It Ic debug_options Xo
-(string, default no debug options)
-.Xc
-Same as the 
+.It Va debug_mtab_file Pq string, default= Ns Pa /tmp/mnttab
+Path to mtab file that is used by
+.Xr amd 8
+to store a list of mounted
+file systems during debug-mtab mode.
+This option only applies
+to systems that store mtab information on disk.
+.It Va debug_options Pq string, default no debug options
+Same as the
 .Fl D
 option to
-.Nm amd .
+.Xr amd 8 .
 Specify any debugging options for
-.Nm amd .
-Works only if am-utils was configured for debugging using the
-.Fl -enable-debug
+.Xr amd 8 .
+Works only if
+am-utils was configured for debugging using the
+.Fl Fl enable-debug
 option.
 The
-.Qq mem
+.Cm mem
 option alone can be turned on via
-.Fl -enable-debug Ns = Ns Ic mem .
-Otherwise debugging options are ignored.  Options are comma delimited, and can
-be preceded by the string
-.Qq no
-to negate their meaning.  You can get the list of supported debugging options
-by running 
+.Fl Fl enable-debug Ns = Ns Cm mem .
+Otherwise debugging options are ignored.
+Options are
+comma delimited, and can be preceded by the string
+.Dq Li no
+to negate their
+meaning.
+You can get the list of supported debugging options by running
 .Nm amd Fl v .
 Possible values are:
 .Pp
-.Bl -tag -width "daemon" -compact
-.It Ic all 
+.Bl -tag -width ".Cm xdrtrace" -compact
+.It Cm all
 all options
-.It Ic amq
-register for 
+.It Cm amq
+register for
 .Xr amq 8
-.It Ic daemon
+.It Cm daemon
 enter daemon mode
-.It Ic fork
+.It Cm fork
 fork server
-.It Ic full
+.It Cm full
 program trace
-.It Ic info
+.It Cm info
 info service specific debugging
 (hesiod, nis, etc.)
-.It mem
+.It Cm mem
 trace memory allocations
-.It Ic mtab
+.It Cm mtab
 use local
 .Pa ./mtab
 file
-.It Ic str
+.It Cm str
 debug string munging
-.It Ic test
+.It Cm test
 full debug but no daemon
-.It Ic trace
-protocol trace
+.It Cm trace
+trace protocol and NFS mount arguments
+.It Cm xdrtrace
+trace XDR routines
 .El
-.It Ic dismount_interval Xo
-(numeric, default=120)
-.Xc
+.It Va dismount_interval Pq numeric, default=120
 Same as the
 .Fl w
 option to
-.Nm amd .
-Specify, in seconds, the time between attempts to dismount file systems that
-have exceeded their cached times. 
-.It Ic fully_qualified_hosts Xo
-(string, default=no)
-.Xc
+.Xr amd 8 .
+Specify, in seconds, the time between attempts to dismount
+file systems that have exceeded their cached times.
+.It Va domain_strip Pq boolean, default=yes
+If
+.Dq Li yes ,
+then the domain
+name part referred to by ${rhost} is stripped off.
+This is
+useful to keep logs and smaller.
+If
+.Dq Li 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).
+.It Va exec_map_timeout Pq numeric, default=10
+The timeout in seconds that
+.Xr amd 8
+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,
+.Xr amd 8
+is essentially waiting and is thus not responding to any other queries.
+.It Va forced_unmounts Pq boolean, default=no
+If set to
+.Dq Li yes ,
+and the client OS supports forced or lazy unmounts, then
+.Xr amd 8
+will attempt to use them if it gets any of three serious error conditions
+when trying to unmount an existing mount point or mount on top of one:
+.Er EIO , ESTALE ,
+or
+.Er EBUSY .
+.Pp
+This could be useful to recover from serious conditions such as hardware
+failure of mounted disks, or NFS servers which are down permanently, were
+migrated, or changed their IP address.
+Only
+.Dq Li type:=toplvl
+mounts hung with
+.Er EBUSY
+are forcibly unmounted using this option, which is useful to recover
+from a hung
+.Xr amd 8 ) .
+.It Va full_os Pq 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
+.Dq Li linux ,
+but you can override it to
+.Dq Li linux-2.2.5 .
+.It Va fully_qualified_hosts Pq string, default=no
 If
-.Qq yes ,
-.Nm Amd
-will perform RPC authentication using fully-qualified host names.  This is
+.Dq Li yes ,
+.Xr amd 8
+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
-.Nm amd
-variable 
-.Va ${hostd}
-is used, requiring that
-.Va ${domain}
-not be null.
-.It Ic hesiod_base Xo
-(string, default=automount)
-.Xc
+mounting.
+For this function to work, the
+.Xr amd 8
+variable ${hostd} is used, requiring that ${domain} not be null.
+.It Va hesiod_base Pq string, default=automount
 Specify the base name for hesiod maps.
-.It Ic karch Xo
-(string, default to karch of the system)
-.Xc
+.It Va karch Pq string, default to karch of the system
 Same as the
 .Fl k
 option to
-.Nm amd .
-Allows you to override the kernel-architecture of your system.  Useful for
-example on Sun
-(Sparc)
-machines, where you can build one
+.Xr amd 8 .
+Allows you to override the kernel-architecture of your
+system.
+Useful for example on Sun (Sparc) machines, where you can build one
 .Nm amd
-binary and run it on multiple machines, yet you want each one to get the
-correct 
+binary and run it on multiple machines, yet you want each one to get
+the correct
 .Va karch
-variable set
-(for example, sun4c, sun4m, sun4u, etc.)
+variable set (for example, sun4c, sun4m, sun4u, etc.)
 Note that if not
 specified,
-.Nm amd
+.Xr amd 8
 will use
 .Xr uname 3
-to figure out the kernel architecture of the machine.
-.It Ic ldap_base Xo
-(string, default not set)
-.Xc
+to figure out the kernel architecture of
+the machine.
+.It Va ldap_base Pq string, default not set
 Specify the base name for LDAP.
-.It Ic ldap_cache_maxmem Xo
-(numeric, default=131072)
-.Xc
-Specify the maximum memory amd should use to cache LDAP entries.
-.It Ic ldap_cache_seconds Xo
-(numeric, default=0)
-.Xc
+This often includes LDAP-specific
+values such as country and organization.
+.It Va ldap_cache_maxmem Pq numeric, default=131072
+Specify the maximum memory
+.Xr amd 8
+should use to cache LDAP entries.
+.It Va ldap_cache_seconds Pq numeric, default=0
 Specify the number of seconds to keep entries in the cache.
-.It Ic ldap_hostports Xo
-(string, default not set)
-.Xc
-Specify LDAP-specific values such as country and organization.
-.It Ic local_domain Xo
-(string, default no sub-domain)
-.Xc
+.It Va ldap_hostports Pq string, default not set
+Specify the LDAP host and port values.
+.It Va ldap_proto_version Pq numeric, default=2
+Specify the version of the LDAP protocol to use.
+.It Va local_domain Pq string, default no sub-domain
 Same as the
 .Fl d
 option to
-.Nm 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.
-.It Ic log_file Xo
-(string, default=/dev/stderr)
-.Xc
+.Xr amd 8 .
+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.
+.It Va localhost_address Pq string, default to localhost or 127.0.0.1
+Specify the name or IP address for
+.Xr amd 8
+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
+.Xr amd 8
+to connect to a
+specific address.
+.It Va log_file Pq string, default= Ns Pa /dev/stderr
 Same as the
 .Fl l
 option to
-.Nm amd .
+.Xr amd 8 .
 Specify a file name to log
-.Nm amd
-events to.  If the string
+.Xr amd 8
+events to.
+If the string
 .Pa /dev/stderr
 is specified,
-.Nm amd
-will send its events to the standard error file descriptor.  IF the string
+.Xr amd 8
+will send its events to the standard error file descriptor.
+If the string
 .Pa syslog
 is given,
-.Nm amd
+.Xr amd 8
 will record its events with the system logger
 .Xr syslogd 8 .
 The default syslog facility used is
-.Ev LOG_DAEMON .
-If you wish to change it, append its name to the log file name, delimited by a
-single colon.  For example, if
+.Dv LOG_DAEMON .
+If you
+wish to change it, append its name to the log file name, delimited by a
+single colon.
+For example, if
 .Pa logfile
 is the string
-.Qq syslog:local7
+.Dq Li syslog:local7
 then
-.Nm amd
+.Xr amd 8
 will log messages via
 .Xr syslog 3
 using the
-.Ev LOG_LOCAL7
-facility
-(if it exists on the system).
-.It Ic log_options Xo
-(string, default no logging options)
-.Xc
+.Dv LOG_LOCAL7
+facility (if it exists on the system).
+.It Va log_options Pq string, default no logging options
 Same as the
 .Fl x
 option to
-.Nm amd .
+.Xr amd 8 .
 Specify any logging options for
-.Nm amd .
-Options are comma delimited, and can be preceded by the string
-.Dq no
-to negate their meaning.  The
-.Dq debug
+.Xr amd 8 .
+Options are comma
+delimited, and can be preceded by the string
+.Dq Li no
+to negate their meaning.
+The
+.Dq Li debug
 logging option is only available if am-utils was configured with
-.Fl -enable-debug .
-You can get the list of supported debugging options by running
-.Nm amd Fl v .
+.Fl Fl enable-debug .
+You can get the list of supported debugging and logging
+options by running
+.Nm amd Fl H .
 Possible values are:
 .Pp
-.Bl -tag -width "warning" -compact
-.It Ic all 
+.Bl -tag -width ".Cm warning" -compact
+.It Cm all
 all messages
-.It Ic debug
+.It Cm debug
 debug messages
-.It Ic error
+.It Cm error
 non-fatal system errors
-.It Ic fatal
+.It Cm fatal
 fatal errors
-.It Ic info
+.It Cm info
 information
-.It Ic map
+.It Cm map
 map errors
-.It Ic stats
+.It Cm stats
 additional statistical information
-.It Ic user
+.It Cm user
 non-fatal user errors
-.It Ic warn
+.It Cm warn
 warnings
-.It Ic warning
+.It Cm warning
 warnings
 .El
-.It Ic nfs_retransmit_counter Xo
-(numeric, default=110)
-.Xc
+.It Va map_reload_interval Pq numeric, default=3600
+The number of seconds that
+.Xr amd 8
+will wait before it checks to see if any maps
+have changed at their source (NIS servers, LDAP servers, files, etc.).
+.Xr amd 8
+will reload only those maps that have changed.
+.It Va nfs_allow_any_interface Pq string, default=no
+Normally
+.Xr amd 8
+accepts local NFS packets only from 127.0.0.1.
+If this
+parameter is set to
+.Dq Li yes
+then
+.Xr amd 8
+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.
+.It Va nfs_allow_insecure_port Pq string, default=no
+Normally
+.Xr amd 8
+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
+.Xr amd 8
+to stop dead in its tracks.
+This parameter allows
+.Xr amd 8
+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
+.Dq Li "ignoring request from foo:1234, port not reserved"
+in your
+.Xr amd 8
+log, try enabling this parameter and give it another go.
+.It Va nfs_proto Pq string, default to trying version tcp then udp
+By default,
+.Xr amd 8
+tries TCP and then UDP.
+This option forces the overall
+.Tn NFS
+protocol used to TCP or UDP.
+It overrides what is in the
+.Xr amd 8
+maps, and is
+useful when
+.Nm 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
+.Nm amd )
+until such time as NFSv3 support is
+desired again.
+.It Va nfs_retransmit_counter Pq numeric, default=11
 Same as the
-.Ic counter
+.Ar retransmit
+counter
 part of the
-.Fl t Ar interval.counter
+.Fl t Ar timeout.retransmit
 option to
-.Nm amd .
-Specifies the retransmit counter's value in tenths of seconds.
-.It Ic nfs_retry_interval Xo
-(numeric, default=8)
-.Xc
+.Xr amd 8 .
+Specifies the number of NFS retransmissions that the kernel will use to
+communicate with
+.Xr amd 8 .
+.It Va nfs_retransmit_counter_udp Pq numeric, default=11
+Same as the
+.Va nfs_retransmit_counter
+option, but for all UDP mounts only.
+.It Va nfs_retransmit_counter_tcp Pq numeric, default=11
+Same as the
+.Va nfs_retransmit_counter
+option, but for all TCP mounts only.
+.It Va nfs_retransmit_counter_toplvl Pq numeric, default=11
+Same as the
+.Va nfs_retransmit_counter
+option, but only for
+.Nm amd Ns 's
+top-level UDP mounts.
+.It Va nfs_retry_interval Pq numeric, default=8
 Same as the
-.Ic interval
-part of the 
-.Fl t Ar interval.counter
+.Ar timeout
+interval
+part of the
+.Fl t Ar timeout.retransmit
 option to
-.Nm amd .
-Specifies the interval in tenths of seconds, between NFS/RPC/UDP retries.
-.It Ic nis_domain Xo
-(string, default to local NIS domain name)
-.Xc
+.Xr amd 8 .
+Specifies the
+.Tn NFS
+timeout interval, in
+.Em tenths
+of seconds, between NFS/RPC retries (for UDP and TCP).
+This is the value that the kernel will use to
+communicate with
+.Xr amd 8 .
+.Pp
+.Xr amd 8
+relies on the kernel RPC retransmit mechanism to trigger mount retries.
+The values of the
+.Va nfs_retransmit_counter
+and the
+.Va nfs_retry_interval
+parameters change the overall retry interval.
+Too long an interval gives
+poor interactive response; too short an interval causes excessive retries.
+.It Va nfs_retry_interval_udp Pq numeric, default=8
+Same as the
+.Va nfs_retry_interval
+option, but for all UDP mounts only.
+.It Va nfs_retry_interval_tcp Pq numeric, default=8
+Same as the
+.It nfs_retry_interval
+option, but for all TCP mounts only.
+.It Va nfs_retry_interval_toplvl Pq numeric, default=8
+Same as the
+.It nfs_retry_interval
+option, but only for
+.Nm amd Ns 's
+top-level UDP mounts.
+.It Va nfs_vers Pq numeric, default to trying version 3 then 2
+By default,
+.Xr amd 8
+tries version 3 and then version 2.
+This option forces the
+overall
+.Tn NFS
+protocol used to version 3 or 2.
+It overrides what is in the
+.Xr amd 8
+maps, and is useful when
+.Nm 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
+.Nm amd )
+until such time as NFSv3
+support is desired again.
+.It Va nis_domain Pq string, default to local Tn NIS domain name
 Same as the
 .Fl y
 option to
-.Nm amd .
+.Xr amd 8 .
 Specify an alternative
 .Tn NIS
 domain from which to fetch the
 .Tn NIS
-maps.  The default is the system domain name.  This option is ignored if
+maps.
+The default is the system domain name.
+This option is ignored if
 .Tn NIS
 support is not available.
-.It Ic normalize_hostnames Xo
-(boolean, default=no)
-.Xc
+.It Va normalize_hostnames Pq boolean, default=no
 Same as the
 .Fl n
 option to
-.Nm amd .
+.Xr amd 8 .
 If
-.Dq yes ,
-then the name refereed to by
+.Dq Li yes ,
+then the name referred to by
 .Va ${rhost}
-is normalized relative to the host database before being used.  The effect is
+is normalized relative to the host database before being used.
+The effect is
 to translate aliases into
-.Qq official
+.Dq official
 names.
-.It Ic os Xo
-(string, default to compiled in value)
-.Xc
+.It Va normalize_slashes Pq boolean, default=yes
+If
+.Dq Li yes ,
+then
+.Xr amd 8
+will condense all multiple
+.Ql /
+(slash) characters into
+one and remove all trailing slashes.
+If
+.Dq Li no ,
+then
+.Xr amd 8
+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.
+.It Va os Pq string, default to compiled in value
 Same as the
 .Fl O
 option to
-.Nm amd .
+.Xr amd 8 .
 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 build in name is
-.Dq sunos5 ,
+system.
+Useful when the built-in name is not desired for backward
+compatibility reasons.
+For example, if the build in name is
+.Dq Li sunos5 ,
 you can override it to
-.Dq sos5 ,
-and use older maps which were written with the latter in mind.
-.It Ic osver Xo
-(string, default to compiled in value)
-.Xc
+.Dq Li sos5 ,
+and use older maps which were written with the
+latter in mind.
+.It Va osver Pq string, default to compiled in value
 Same as the
 .Fl o
 option to
-.Nm amd .
-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 
-.Dq 2.5.1 ,
+.Xr amd 8 .
+Overrides 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
+.Dq Li 2.5.1 ,
 you can override it to
-.Dq 5.5.1 ,
-and use older maps that were written with the latter in mind.
-.It Ic pid_file Xo
-(string, default=/dev/stdout)
-.Xc
-Specify a file to store the process ID of the running daemon into.  If not
+.Dq Li 5.5.1 ,
+and use older maps that were written with
+the latter in mind.
+.It Va pid_file Pq string, default= Ns Pa /dev/stdout
+Specify a file to store the process ID of the running daemon into.
+If not
 specified,
+.Xr amd 8
+will print its process ID onto the standard output.
+Useful
+for killing
+.Xr amd 8
+after it had run.
+Note that the PID of a running
 .Nm amd
-will print its process id only the standard output.  Useful for killing
-.Nm amd
-after it had run.  Note that the PID of a running
-.Nm amd
-can also be retrieved via
+can
+also be retrieved via
 .Nm amq Fl p .
 This file is used only if the
-.Ar print_pid
+.Va print_pid
 option is on.
-.It Ic plock Xo
-(boolean, default=yes)
-.Xc
+.It Va plock Pq boolean, default=yes
 Same as the
 .Fl S
 option to
-.Nm amd .
+.Xr amd 8 .
 If
-.Dq yes ,
+.Dq Li yes ,
 lock the running executable pages of
 .Nm amd
-into memory.  To improve
+into memory.
+To improve
 .Nm amd Ns 's
 performance, systems that support the
 .Xr plock 3
+or
+.Xr mlockall 2
 call can lock the
 .Nm amd
-process into memory.  This way there is less chance it that the operating
-system will schedule, page out, and swap the
+process into memory.
+This way there is less chance that
+the operating system will schedule, page out, and swap the
 .Nm amd
-process as needed.  This improves
+process as needed.
+This improves
 .Nm amd Ns 's
-performance, at the cost of reserving the memory used by the
+performance, at the cost of reserving the
+memory used by the
 .Nm amd
-process
-(making it unavailable for other processes).
-.It Ic portmap_program Xo
-(numeric, default=300019)
-.Xc
+process (making it unavailable for other processes).
+.It Va portmap_program Pq numeric, default=300019
 Specify an alternate Port-mapper RPC program number, other than the official
-number.  This is useful when running multiple
-.Nm amd
-processes.  For example, you can run another
+number.
+This is useful when running multiple
 .Nm amd
+processes.
+For example,
+you can run another
+.Xr amd 8
 in
 .Dq test
 mode, without affecting the primary
 .Nm amd
-process in any way.  For safety reasons, the alternate program numbers that
+process in any way.
+For safety reasons, the alternate program numbers that
 can be specified must be in the range 300019-300029, inclusive.
-.Nm amq
+The
+.Xr amq 8
+utility
 has an option
 .Fl P
 which can be used to specify an alternate program number of an
 .Nm amd
-to contact.  In this way,
+to contact.
+In this way,
 .Nm amq
 can fully control any number of
 .Nm amd
 processes running on the same host.
-.It Ic print_pid Xo
-(boolean, default=no)
-.Xc
+.It Va preferred_amq_port Pq numeric, default=0
+Specify an alternate Port-mapper RPC port number for
+.Nm amd Ns 's
+.Xr amq 8
+service.
+This is used for both UDP and TCP.
+Setting this value to 0 (or
+not defining it) will cause
+.Xr amd 8
+to select an arbitrary port number.
+Setting the
+.Xr amq 8
+RPC service port to a specific number is useful in firewalled or NAT'ed
+environments, where you need to know which port
+.Xr amd 8
+will listen on.
+.It Va print_pid Pq boolean, default=no
 Same as the
 .Fl p
 option to
-.Nm amd .
+.Xr amd 8 .
 If
-.Dq yes ,
+.Dq Li yes ,
 .Nm amd
 will print its process ID upon starting.
-.It Ic print_version Xo
-(boolean, default=no)
-.Xc
+.It Va print_version Pq boolean, default=no
 Same as the
 .Fl v
 option to
-.Nm amd ,
+.Xr amd 8 ,
 but the version prints and
 .Nm amd
-continues to run.  If
-.Dq yes ,
+continues to run.
+If
+.Dq Li yes ,
 .Nm amd
-will print its version information string, which includes some configuration
-and compilation values.
-.It Ic restart_mounts Xo
-(boolean, default=no)
-.Xc
+will print its version information string, which includes some
+configuration and compilation values.
+.It Va restart_mounts Pq boolean, default=no
 Same as the
 .Fl r
 option to
-.Nm amd .
+.Xr amd 8 .
 If
-.Dq yes ,
+.Dq Li yes ,
 .Nm amd
 will scan the mount table to determine which file systems are currently
-mounted.  Whenever one of these would have been auto-mounted,
+mounted.
+Whenever one of these would have been auto-mounted,
 .Nm amd
 inherits it.
-.It Ic selectors_on_default Xo
-(boolean, default=no)
-.Xc
-If
-.Dq yes ,
-then the
-.Pa /default
-entry of maps will be looked 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
-.Tn NFS
-performance over slow slip-based networks as
-follows:
-.Pp
-.Bd -literal
-/defaults \\
-    wire==slip-net;opts:=intr,rsize=1024,wsize=1024 \\
-    wire!=slip-net;opts:=intr,rsize=8192,wsize=8192
-.Ed
-.It Ic show_statfs_entries Xo
-(boolean, default=no)
-.Xc
+.It Va show_statfs_entries Pq boolean, default=no
 If
-.Dq yes ,
-then all maps which are browsable will also show the number of entries
-(keys)
-they have when
-.Qq df
+.Dq Li yes ,
+then all maps which are browsable will also show the number of
+entries (keys) they have when
+.Xr df 1
 runs.
-(This is accomplished by returning non-zero values to the
+(This is accomplished by returning
+non-zero values to the
 .Xr statfs 2
 system call.)
-.It Ic unmount_on_exit Xo
-(boolean, default=no)
-.Xc
+.It Va truncate_log Pq boolean, default=no
 If
-.Dq yes ,
-then 
-.Nm amd
-will attempt to unmount all file systems which it knows about.  Normally
+.Dq Li yes ,
+then the log file (if it is a regular file), will be truncated
+upon startup.
+.It Va unmount_on_exit Pq boolean, default=no
+If
+.Dq Li yes ,
+then
+.Xr amd 8
+will attempt to unmount all file systems which it knows
+about.
+Normally
 .Nm amd
-leaves all 
-(esp.\&)
-.Tn NFS
-mounted filesystems intact.  Note that
+leaves all
+(esp.\&
+.Tn NFS )
+mounted file systems intact.
+Note that
 .Nm amd
-does not know about file systems mounted before it starts up, unless the
-.Ar restart_mounts
+does not know about file systems mounted before it starts up,
+unless the
+.Va restart_mounts
 option or
 .Fl r
 flag are used.
+.It Va use_tcpwrappers Pq boolean, default=yes
+If
+.Dq Li yes ,
+then
+.Xr amd 8
+will use the tcpd/libwrap tcpwrappers library
+(if available) to control
+access to
+.Nm amd
+via the
+.Pa /etc/hosts.allow
+and
+.Pa /etc/hosts.deny
+files.
+.It Va vendor Pq 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
+.Dq Li unknown ,
+but you can set it to
+.Dq Li redhat .
 .El
 .Ss "Parameters applicable to regular map sections"
 .Bl -tag -width 4n
-.It Ic map_name Xo
-(string, must be specified)
-.Xc
+.It Va map_name Pq string, must be specified
 Name of the map where the keys are located.
-.It Ic tag Xo
-(string, default no tag)
-.Xc
-Each map entry in the configuration file can be tagged.  If no tag is
+.It Va tag Pq 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
-.Nm amd .
-If it is specified, then
+.Xr amd 8 .
+If it is
+specified, then
 .Nm amd
 will process the map if the
 .Fl T
 option was given to
-.Nm amd ,
-and the value given to that command-line option matches that in the map
-section. 
+.Xr amd 8 ,
+and the value given to that command-line option
+matches that in the map section.
 .El
 .Sh EXAMPLES
-Here is a real 
-.Nm amd
+Here is a real
+.Xr amd 8
 configuration I use daily.
 .Bd -literal
 # GLOBAL OPTIONS SECTION
@@ -707,7 +1035,7 @@ log_file =               /var/log/amd
 log_options =            all
 #debug_options =         all
 plock =                  no
-selectors_on_default =   yes
+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.
@@ -737,20 +1065,34 @@ tag =                    tftpboot
 map_name =               amd.tftpboot
 .Ed
 .Sh SEE ALSO
+.Xr hosts_access 5 ,
 .Xr amd 8 ,
-.Xr amq 8 
-.Sh AUTHORS
-.An Erez Zadok Aq ezk@cs.columbia.edu ,
-Department of Computer Science, Columbia University, New York, USA.
+.Xr amq 8
 .Pp
-.An Jan-Simon Pendry Aq jsp@doc.ic.ac.uk ,
-Department of Computing, Imperial College, London, UK.
+.Dq am-utils
+.Xr info 1
+entry.
+.Rs
+.%A Erez Zadok
+.%B "Linux NFS and Automounter Administration"
+.%O ISBN 0-7821-2739-8
+.%I Sybex
+.%D 2001
+.Re
 .Pp
-Other authors and contributers to am-utils are listed in the 
-.Pa AUTHORS
-file distributed with am-utils.
+.Pa http://www.am-utils.org/
+.Rs
+.%T Amd \- The 4.4 BSD Automounter
+.Re
 .Sh HISTORY
 The
-.Nm amd
+.Xr amd 8
 utility first appeared in
 .Bx 4.4 .
+.Sh AUTHORS
+.An Erez Zadok Aq ezk@cs.sunysb.edu ,
+Computer Science Department, Stony Brook University, Stony Brook, New York, USA.
+.Pp
+Other authors and contributors to am-utils are listed in the
+.Pa AUTHORS
+file distributed with am-utils.
diff --git a/contrib/amd/scripts/amd2ldif.in b/contrib/amd/scripts/amd2ldif.in
index 6d3c28a..34cee97 100755
--- a/contrib/amd/scripts/amd2ldif.in
+++ b/contrib/amd/scripts/amd2ldif.in
@@ -18,10 +18,12 @@ my $mapname = $ARGV[0] or die $usage;
 my $base = $ARGV[1] or die $usage;
 $time = time();
 
-print "dn: cn=amdmap timestamp, $base\n";
-printf "$tfmt", "cn", "amdmap timestamp";
+print "dn: cn=amdmap $mapname timestamp, $base\n";
+printf "$tfmt", "cn", "amdmap $mapname timestamp";
 printf "$tfmt", "objectClass", "amdmapTimestamp";
+printf "$tfmt", "amdmapName", "$mapname";
 printf "$tfmt", "amdmapTimestamp", $time;
+printf "$tfmt", "amdmapName", $mapname;
 print "\n";
 
 my $line = "";
diff --git a/contrib/amd/scripts/amd2sun.in b/contrib/amd/scripts/amd2sun.in
index df69b09..7616c83 100755
--- a/contrib/amd/scripts/amd2sun.in
+++ b/contrib/amd/scripts/amd2sun.in
@@ -2,7 +2,7 @@
 # convert amd maps to Sun automount maps
 # usage: amd2sun file
 #
-# Package:	am-utils-6.0
+# Package:	am-utils-6.x
 # Author:	"Mark D. Baushke" <mdb@cisco.com>
 
 print "# file created by amd2sun
diff --git a/contrib/amd/scripts/automount2amd.8 b/contrib/amd/scripts/automount2amd.8
index c1c1d8b..bd3b612 100644
--- a/contrib/amd/scripts/automount2amd.8
+++ b/contrib/amd/scripts/automount2amd.8
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-1999 Erez Zadok
+.\" Copyright (c) 1997-2006 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.
@@ -38,7 +38,7 @@
 .\"
 .\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: automount2amd.8,v 1.1 1999/08/16 01:16:36 ezk Exp $
+.\" $Id: automount2amd.8,v 1.8.2.1 2006/01/02 18:48:26 ezk Exp $
 .\"
 .TH AUTOMOUNT2AMD 8L "24 May 1993"
 .SH NAME
@@ -100,7 +100,22 @@ moon \
 does not understand newer Sun Automount map syntax, those used by autofs.
 .SH "SEE ALSO"
 .BR conv2amd (8), amd (8).
+.LP
+``am-utils''
+.BR info (1)
+entry.
+.LP
+.I "Linux NFS and Automounter Administration"
+by Erez Zadok, ISBN 0-7821-2739-8, (Sybex, 2001).
+.LP
+.I http://www.am-utils.org
+.LP
+.I "Amd \- The 4.4 BSD Automounter"
 .SH AUTHORS
-Original author Mike Walker <mike@tab00.larc.nasa.gov>.  Script modified by
-Erez Zadok <ezk@cs.columbia.edu>, Department of Computer Science, Columbia
-University, New York, USA.
+Original author Mike Walker <mike@tab00.larc.nasa.gov>.
+Script modified by Erez Zadok <ezk@cs.sunysb.edu>, Computer Science
+Department, Stony Brook University, Stony Brook, New York, USA.
+.P
+Other authors and contributors to am-utils are listed in the
+.B AUTHORS
+file distributed with am-utils.
diff --git a/contrib/amd/scripts/automount2amd.in b/contrib/amd/scripts/automount2amd.in
index e99c74b..79a7b77 100755
--- a/contrib/amd/scripts/automount2amd.in
+++ b/contrib/amd/scripts/automount2amd.in
@@ -2,7 +2,7 @@
 #
 # Convert Sun automount map format to amd format
 #
-# Package:      am-utils-6.0
+# Package:      am-utils-6.x
 # Author:       Mike Walker <mike@tab00.larc.nasa.gov>
 #		Erez Zadok <ezk@cs.columbia.edu>
 #
@@ -26,7 +26,7 @@
 #
 # You should set the DOMAIN and DEFAULT variables to your preferences.
 #
-# $Id: automount2amd.in,v 1.1 1999/08/16 01:16:36 ezk Exp $
+# $Id: automount2amd.in,v 1.2 2002/01/15 18:25:25 ezk Exp $
 #
 
 require "ctime.pl";
diff --git a/contrib/amd/scripts/ctl-amd.in b/contrib/amd/scripts/ctl-amd.in
index 22c3677..694b31a 100755
--- a/contrib/amd/scripts/ctl-amd.in
+++ b/contrib/amd/scripts/ctl-amd.in
@@ -1,8 +1,8 @@
 #!/bin/sh
 # control starting, stopping, or restarting amd.
-# usage: ctl-amd [start | stop | restart]
+# usage: ctl-amd [start|stop|status|restart|condrestart|reload]
 #
-# Package:	am-utils-6.0
+# Package:	am-utils-6.x
 # Author:	Erez Zadok <ezk@cs.columbia.edu>
 #
 # chkconfig: - 72 28
@@ -60,16 +60,20 @@ fi
 return 1
 }
 
+# before running any real programs, chdir to / to avoid possible hangs on
+# (NFS) mounts which may be restarting.
+cd /
+
 # search for amd.conf file
-CF_FILE="${prefix}/etc/amd.conf"
+CF_FILE="@sysconfdir@/amd.conf"
 # any local copy of the conf file overrides the "global" one
 if [ -f /etc/amd.conf ]
 then
 	CF_FILE="/etc/amd.conf"
 fi
-if [ -f ${prefix}/etc/amd.conf ]
+if [ -f @sysconfdir@/amd.conf ]
 then
-	CF_FILE="${prefix}/etc/amd.conf"
+	CF_FILE="@sysconfdir@/amd.conf"
 fi
 if [ -f /etc/local/amd.conf ]
 then
@@ -85,13 +89,12 @@ fi
 
 case "$1" in
 'start')
-	#
 	# Start the amd automounter.
-	#
 	if [ -x @sbindir@/amd ]
 	then
 		# do not specify full path of amd so killproc() works
 		amd -F $CF_FILE $CF_TAG
+		test -x /var/lock/subsys && touch /var/lock/subsys/amd
 	fi
 	;;
 
@@ -100,6 +103,7 @@ case "$1" in
 	echo "killing amd..."
 	killproc " amd"
 	wait4amd2die
+	rm -f /var/lock/subsys/amd
 	;;
 
 'restart')
@@ -115,7 +119,37 @@ case "$1" in
 	fi
 	;;
 
+'condrestart')
+     if [ -f /var/lock/subsys/amd ]; then
+            ctl-amd stop
+            ctl-amd start
+        fi
+     ;;
+
+'reload')
+        amq -f
+        ;;
+
+'status')
+	# run amq -v to produce status
+	pid=`amq -p 2>/dev/null`
+	if [ $? = 0 ]
+	then
+		echo "amd (pid $pid) is running..."
+	else
+		echo "amd is stopped"
+	fi
+	;;
+
+# start_msg and stop_msg are for HPUX
+'start_msg')
+	echo "Start am-utils 6.1 automounter"
+	;;
+'stop_msg')
+	echo "Stop am-utils 6.1 automounter"
+	;;
+
 *)
-	echo "Usage: @sbindir@/ctl-amd [ start | stop | restart ]"
+	echo "Usage: $0 [start|stop|status|restart|condrestart|reload]"
 	;;
 esac
diff --git a/contrib/amd/scripts/ctl-hlfsd.in b/contrib/amd/scripts/ctl-hlfsd.in
index ebb12b8..ee0dd27 100755
--- a/contrib/amd/scripts/ctl-hlfsd.in
+++ b/contrib/amd/scripts/ctl-hlfsd.in
@@ -2,7 +2,7 @@
 # control starting, stopping, or restarting hlfsd.
 # usage: ctl-hlfsd [start | stop | restart]
 #
-# Package:	am-utils-6.0
+# Package:	am-utils-6.x
 # Author:	Erez Zadok <ezk@cs.columbia.edu>
 #
 # chkconfig: - 72 28
@@ -51,6 +51,10 @@ fi
 return 1
 }
 
+# before running any real programs, chdir to / to avoid possible hangs on (NFS)
+# mounts.
+cd /
+
 # locate logs directory
 if [ -d /var/log ]; then
 	logdir="/var/log"
@@ -62,14 +66,17 @@ fi
 if [ -d /var/mail/. ]; then
 	maildir="/var/mail"
 	altmaildir="/var/alt_mail"
+elif [ -d /var/spool/mail/. ]; then
+	maildir="/var/spool/mail"
+	altmaildir="/var/spool/alt_mail"
 else
 	maildir="/usr/spool/mail"
 	altmaildir="/usr/spool/alt_mail"
 fi
 
 # locate any optional password file
-if [ -f ${prefix}/etc/passwd ]; then
-	PASSWD_FILE="-P ${prefix}/etc/passwd"
+if [ -f @sysconfdir@/passwd ]; then
+	PASSWD_FILE="-P @sysconfdir@/passwd"
 else
 	PASSWD_FILE=""
 fi
@@ -81,14 +88,16 @@ case "$1" in
 	#
 	if [ -x @sbindir@/hlfsd -a -h $maildir ]
 	then
-		echo @sbindir@/hlfsd ${PASSWD_FILE} -a $altmaildir -x all -D fork -l $logdir/hlfsd /mail/home .mailspool
-		@sbindir@/hlfsd ${PASSWD_FILE} -a $altmaildir -x all -D fork -l $logdir/hlfsd /mail/home .mailspool &
+		echo @sbindir@/hlfsd ${PASSWD_FILE} -a $altmaildir -x all -l $logdir/hlfsd /mail/home .mailspool
+		@sbindir@/hlfsd ${PASSWD_FILE} -a $altmaildir -x all -l $logdir/hlfsd /mail/home .mailspool &
+		test -x /var/lock/subsys && touch /var/lock/subsys/hlfsd
 	fi
 	;;
 
 'stop')
 	# prepend space to program name to ensure only amd process dies
 	killproc " hlfsd"
+	test -f /var/lock/subsys/hlfsd && rm -f /var/lock/subsys/hlfsd
 	;;
 
 'restart')
diff --git a/contrib/amd/scripts/expn.1 b/contrib/amd/scripts/expn.1
index 5795241..f316247 100644
--- a/contrib/amd/scripts/expn.1
+++ b/contrib/amd/scripts/expn.1
@@ -16,7 +16,7 @@ $sockaddr = 'S n a4 x8';
 # system requirements:
 # 	must have 'nslookup' and 'hostname' programs.
 
-# $Header: /src/cvsroot/am-utils-6.0/scripts/expn.1,v 1.1.1.1 1998/11/05 02:04:58 ezk Exp $
+# $Header: /home/cvsroot/am-utils/scripts/expn.1,v 1.4 2003/07/18 15:17:37 ezk Exp $
 
 # TODO:
 #	less magic should apply to command-line addresses
@@ -43,7 +43,7 @@ $sockaddr = 'S n a4 x8';
 #     notice, this list of conditions and the following disclaimer in the
 #     documentation and/or other materials provided with the distribution.
 #  3. All advertising materials mentioning features or use of this software
-#     must display the following acknowledgement:
+#     must display the following acknowledgment:
 #       This product includes software developed by the David Muir Sharnoff.
 #  4. The name of David Sharnoff may not be used to endorse or promote products
 #     derived from this software without specific prior written permission.
@@ -60,7 +60,7 @@ $sockaddr = 'S n a4 x8';
 #  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 #  SUCH DAMAGE.
 #
-# This copyright notice derrived from material copyrighted by the Regents
+# This copyright notice derived from material copyrighted by the Regents
 # of the University of California.
 #
 # Contributions accepted.
@@ -88,7 +88,7 @@ $sockaddr = 'S n a4 x8';
 # $names{"$users[0] *** $server"} : the 'name' associated with the address
 # $mxbacktrace{"$users[0] *** $server"} : record of mx expansion
 # $mx_secondary{$server} : other mx relays at the same priority
-# $domainify_fallback{"$users[0] *** $server"} : alternative names to try 
+# $domainify_fallback{"$users[0] *** $server"} : alternative names to try
 #	instead of $server if $server doesn't work
 # $temporary_redirect{"$users[0] *** $server"} : when trying alternates,
 #	temporarily channel all tries along current path
@@ -177,14 +177,14 @@ while (@hosts) {
 		&mxlookup(1,$server,"$server: could not resolve name",*users);
 		next HOST;
 	}
-				
+
 	# get a connection, or look for an mx
 	$0 = "$av0 - socket to $server";
 	$that = pack($sockaddr, &AF_INET, $port, $thataddr);
 	socket(S, &AF_INET, &SOCK_STREAM, $proto)
 		|| die "socket: $!";
 	$0 = "$av0 - bind to $server";
-	bind(S, $this) 
+	bind(S, $this)
 		|| die "bind $hostname,0: $!";
 	$0 = "$av0 - connect to $server";
 	print "debug = $debug server = $server\n" if $debug > 8;
@@ -231,7 +231,7 @@ while (@hosts) {
 		&alarm("greeting with $server",'');
 	}
 	alarm(0);
-	
+
 	# if this causes problems, remove it
 	$0 = "$av0 - sending helo to $server";
 	&alarm("sending helo to $server","");
@@ -254,11 +254,11 @@ while (@hosts) {
 		print &compact($u,$server)." ->\n" if ($verbose && ! $valid);
 		if ($valid) {
 			#
-			# when running with -a, we delay taking any action 
+			# when running with -a, we delay taking any action
 			# on the results of our query until we have looked
 			# at the complete output.  @toFinal stores expansions
 			# that will be final if we take them.  @toExpn stores
-			# expnansions that are not final.  @isValid keeps
+			# expansions that are not final.  @isValid keeps
 			# track of our ability to send mail to each of the
 			# expansions.
 			#
@@ -304,11 +304,11 @@ while (@hosts) {
 					}
 				} else {
 					$newmxhost = &mx($newhost,$newaddr);
-					print "$newmxhost = &mx($newhost)\n" 
+					print "$newmxhost = &mx($newhost)\n"
 						if ($debug && $newhost ne $newmxhost);
 					$0 = "$av0 - parsing $newaddr [@$newmxhost]";
 					print "levels = $levels, level{$u *** $server} = ".$level{"$u *** $server"}."\n" if ($debug > 1);
-					# If the new server is the current one, 
+					# If the new server is the current one,
 					# it would have expanded things for us
 					# if it could have.  Mx records must be
 					# followed to compare server names.
@@ -337,7 +337,7 @@ while (@hosts) {
 			# 550 is a known code...  Should the be
 			# included in -a output?  Might be a bug
 			# here.  Does it matter?  Can assume that
-			# there won't be UNKNOWN USER responses 
+			# there won't be UNKNOWN USER responses
 			# mixed with valid users?
 			if ($s =~ /^(550)([- ])/) {
 				if ($valid) {
@@ -347,8 +347,8 @@ while (@hosts) {
 				}
 				last if ($2 eq " ");
 				next;
-			} 
-			# 553 is a known code...  
+			}
+			# 553 is a known code...
 			if ($s =~ /^(553)([- ])/) {
 				if ($valid) {
 					print STDERR "\@$server:$u ($oldname) USER AMBIGUOUS\n";
@@ -357,8 +357,8 @@ while (@hosts) {
 				}
 				last if ($2 eq " ");
 				next;
-			} 
-			# 252 is a known code...  
+			}
+			# 252 is a known code...
 			if ($s =~ /^(252)([- ])/) {
 				if ($valid) {
 					print STDERR "\@$server:$u ($oldname) REFUSED TO VRFY\n";
@@ -367,7 +367,7 @@ while (@hosts) {
 				}
 				last if ($2 eq " ");
 				next;
-			} 
+			}
 			&giveup('',"$server: did not grok '$s'",$u);
 			last USER;
 		}
@@ -467,7 +467,7 @@ sub giveup
 #
 # This routine is used only within &giveup.  It checks to
 # see if we really have to giveup or if there is a second
-# chance because we did something before that can be 
+# chance because we did something before that can be
 # backtracked.
 #
 # %fallback{"$user *** $host"} tracks what is able to fallback
@@ -491,7 +491,7 @@ sub try_fallback
 		}
 		print "U: $user H: $host\n";
 	}
-	
+
 	$us = "$user *** $host";
 	if (defined $fellback{$us}) {
 		#
@@ -539,7 +539,7 @@ sub try_fallback
 			delete $fall_table{$ft};
 		}
 		if (defined $create_host_backtrack{$us}) {
-			$create_host_backtrack{"$user *** $newhost"} 
+			$create_host_backtrack{"$user *** $newhost"}
 				= $create_host_backtrack{$us};
 		}
 		$fellback{"$user *** $newhost"} = $oldhost;
@@ -619,7 +619,7 @@ sub expn_vrfy
 				@ret = ("",$s);
 				push(@ret,&read_response($2,$debug));
 				return (@ret);
-			} 
+			}
 			if ($1 == 551 || $1 == 251) {
 				$code = $1;
 				@ret = ("",$s);
@@ -645,7 +645,7 @@ sub expn_vrfy
 	return @ret;
 }
 # sometimes the old parse routine (now parse2) didn't
-# reject funky addresses. 
+# reject funky addresses.
 sub parse
 {
 	local($oldaddr,$server,$oldname,$one_to_one) = @_;
@@ -658,9 +658,9 @@ sub parse
 }
 
 # returns ($new_smtp_server,$new_address,$new_name)
-# given a response from a SMTP server ($newaddr), the 
+# given a response from a SMTP server ($newaddr), the
 # current host ($server), the old "name" and a flag that
-# indicates if it is being called during the initial 
+# indicates if it is being called during the initial
 # command line parsing ($parsing_args)
 sub parse2
 {
@@ -763,7 +763,7 @@ sub trim
 	return(@r);
 }
 # using the host part of an address, and the server name, add the
-# servers' domain to the address if it doesn't already have a 
+# servers' domain to the address if it doesn't already have a
 # domain.  Since this sometimes fails, save a back reference so
 # it can be unrolled.
 sub domainify
@@ -771,7 +771,7 @@ sub domainify
 	local($host,$domain_host,$u) = @_;
 	local($domain,$newhost);
 
-	# cut of trailing dots 
+	# cut of trailing dots
 	$host =~ s/\.$//;
 	$domain_host =~ s/\.$//;
 
@@ -783,23 +783,23 @@ sub domainify
 		return $host;
 	}
 
-	# 
-	# There are several weird situtations that need to be 
+	#
+	# There are several weird situations that need to be
 	# accounted for.  They have to do with domain relay hosts.
 	#
-	# Examples: 
+	# Examples:
 	#	host		server		"right answer"
-	#	
+	#
 	#	shiva.cs	cs.berkeley.edu	shiva.cs.berkeley.edu
 	#	shiva		cs.berkeley.edu	shiva.cs.berekley.edu
 	#	cumulus		reed.edu	@reed.edu:cumulus.uucp
 	# 	tiberius	tc.cornell.edu	tiberius.tc.cornell.edu
 	#
-	# The first try must always be to cut the domain part out of 
+	# The first try must always be to cut the domain part out of
 	# the server and tack it onto the host.
 	#
 	# A reasonable second try is to tack the whole server part onto
-	# the host and for each possible repeated element, eliminate 
+	# the host and for each possible repeated element, eliminate
 	# just that part.
 	#
 	# These extra "guesses" get put into the %domainify_fallback
@@ -809,7 +809,7 @@ sub domainify
 
 	local(%fallback);
 
-	local($long); 
+	local($long);
 	$long = "$host $domain_host";
 	$long =~ tr/A-Z/a-z/;
 	print "long = $long\n" if $debug;
@@ -854,7 +854,7 @@ sub domainify
 	$domainify_fallback{"$u *** $newhost"} = join(' ',sort {$fallback{$b} <=> $fallback{$a};} keys %fallback) if %fallback;
 	if ($debug) {
 		print "fallback = ";
-		print $domainify_fallback{"$u *** $newhost"} 
+		print $domainify_fallback{"$u *** $newhost"}
 			if defined($domainify_fallback{"$u *** $newhost"});
 		print "\n";
 	}
@@ -911,7 +911,7 @@ sub ps
 	print S "$p\n";
 }
 # return case-adjusted name for a host (for comparison purposes)
-sub trhost 
+sub trhost
 {
 	# treat foo.bar as an alias for Foo.BAR
 	local($host) = @_;
@@ -955,7 +955,7 @@ sub mxredirect
 	return undef;
 }
 # follow mx records, return a hostname
-# also follow temporary redirections comming from &domainify and
+# also follow temporary redirections coming from &domainify and
 # &mxlookup
 sub mx
 {
@@ -990,7 +990,7 @@ sub mx
 # look up mx records with the name server.
 # re-queue expansion requests if possible
 # optionally give up on this host.
-sub mxlookup 
+sub mxlookup
 {
 	local($lastchance,$server,$giveup,*users) = @_;
 	local(*T);
@@ -1033,18 +1033,18 @@ sub mxlookup
 		}
 		if (/Non-existent domain/) {
 			#
-			# These addresss are hosed.  Kaput!  Dead! 
+			# These addresses are hosed.  Kaput!  Dead!
 			# However, if we created the address in the
-			# first place then there is a chance of 
+			# first place then there is a chance of
 			# salvation.
 			#
-			1 while(<NSLOOKUP>);	
+			1 while(<NSLOOKUP>);
 			close(NSLOOKUP);
 			return 0 unless $lastchance;
 			&giveup('domainify',"$server: Non-existent domain",undef,1);
-			return 0;	
+			return 0;
 		}
-				
+
 	}
 	close(NSLOOKUP);
 	unlink("/tmp/expn$$");
@@ -1082,7 +1082,7 @@ sub mxlookup
 	return 1;
 }
 # if mx expansion did not help to resolve an address
-# (ie: foo@bar became @baz:foo@bar, then undo the 
+# (ie: foo@bar became @baz:foo@bar, then undo the
 # expansion).
 # this is only used by &final
 sub mxunroll
@@ -1092,10 +1092,10 @@ sub mxunroll
 	print "looking for mxbacktrace{$addr *** $host}\n"
 		if ($debug > 1);
 	while (defined $mxbacktrace{"$addr *** $host"}) {
-		print "Unrolling MX expnasion: \@$host:$addr -> " 
+		print "Unrolling MX expansion: \@$host:$addr -> "
 			if ($debug || $verbose);
 		$host = $mxbacktrace{"$addr *** $host"};
-		print "\@$host:$addr\n" 
+		print "\@$host:$addr\n"
 			if ($debug || $verbose);
 		$r = 1;
 	}
@@ -1104,7 +1104,7 @@ sub mxunroll
 		if ($host =~ /\./);
 	return 0;
 }
-# register a completed expnasion.  Make the final address as 
+# register a completed expansion.  Make the final address as
 # simple as possible.
 sub final
 {
@@ -1114,7 +1114,7 @@ sub final
 	local($au,$ah);
 
 	if ($error =~ /Non-existent domain/) {
-		# 
+		#
 		# If we created the domain, then let's undo the
 		# damage...
 		#
@@ -1126,7 +1126,7 @@ sub final
 			}
 			$error = "$host: could not locate";
 		} else {
-			# 
+			#
 			# If we only want valid addresses, toss out
 			# bad host names.
 			#
@@ -1161,17 +1161,17 @@ sub final
 					# host part has a . in it - foo.bar
 					($hb, $hr) = ($1, $2);
 					if ($addr =~ /\@([^\.\@]+)$/ && ($1 eq $hb)) {
-						# addr part has not . 
+						# addr part has not .
 						# and matches beginning of
-						# host part -- tack on a 
+						# host part -- tack on a
 						# domain name.
 						$addr .= $hr;
 					} else {
-						&mxunroll(*host,*addr) 
+						&mxunroll(*host,*addr)
 							&& redo MXUNWIND;
 					}
 				} else {
-					&mxunroll(*host,*addr) 
+					&mxunroll(*host,*addr)
 						&& redo MXUNWIND;
 				}
 			} else {
@@ -1231,13 +1231,13 @@ $flag_1;
 %already_domainify_fellback;
 %already_mx_fellback;
 &handle_alarm;
-################### BEGIN PERL/TROFF TRANSITION 
-.00 ;	
+################### BEGIN PERL/TROFF TRANSITION
+.00 ;
 
 'di
 .nr nl 0-1
 .nr % 0
-.\\"'; __END__ 
+.\\"'; __END__
 .\" ############## END PERL/TROFF TRANSITION
 .TH EXPN 1 "March 11, 1993"
 .AT 3
@@ -1256,25 +1256,25 @@ expn \- recursively expand mail aliases
 .B expn
 will use the SMTP
 .B expn
-and 
+and
 .B vrfy
-commands to expand mail aliases.  
+commands to expand mail aliases.
 It will first look up the addresses you provide on the command line.
-If those expand into addresses on other systems, it will 
-connect to the other systems and expand again.  It will keep 
+If those expand into addresses on other systems, it will
+connect to the other systems and expand again.  It will keep
 doing this until no further expansion is possible.
 .SH OPTIONS
-The default output of 
+The default output of
 .B expn
 can contain many lines which are not valid
-email addresses.  With the 
+email addresses.  With the
 .I -aa
 flag, only expansions that result in legal addresses
 are used.  Since many mailing lists have an illegal
 address or two, the single
 .IR -a ,
 address, flag specifies that a few illegal addresses can
-be mixed into the results.   More 
+be mixed into the results.   More
 .I -a
 flags vary the ratio.  Read the source to track down
 the formula.  With the
@@ -1282,13 +1282,13 @@ the formula.  With the
 option, you should be able to construct a new mailing
 list out of an existing one.
 .LP
-If you wish to limit the number of levels deep that 
+If you wish to limit the number of levels deep that
 .B expn
 will recurse as it traces addresses, use the
 .I -1
-option.  For each 
+option.  For each
 .I -1
-another level will be traversed.  So, 
+another level will be traversed.  So,
 .I -111
 will traverse no more than three levels deep.
 .LP
@@ -1297,38 +1297,37 @@ The normal mode of operation for
 is to do all of its work silently.
 The following options make it more verbose.
 It is not necessary to make it verbose to see what it is
-doing because as it works, it changes its 
+doing because as it works, it changes its
 .BR argv [0]
 variable to reflect its current activity.
-To see how it is expanding things, the 
+To see how it is expanding things, the
 .IR -v ,
-verbose, flag will cause 
-.B expn 
+verbose, flag will cause
+.B expn
 to show each address before
 and after translation as it works.
-The 
+The
 .IR -w ,
 watch, flag will cause
 .B expn
 to show you its conversations with the mail daemons.
-Finally, the 
+Finally, the
 .IR -d ,
 debug, flag will expose many of the inner workings so that
 it is possible to eliminate bugs.
 .SH ENVIRONMENT
-No enviroment variables are used.
+No environment variables are used.
 .SH FILES
-.PD 0
 .B /tmp/expn$$
-.B temporary file used as input to 
+.B temporary file used as input to
 .BR nslookup .
 .SH SEE ALSO
-.BR aliases (5), 
+.BR aliases (5),
 .BR sendmail (8),
 .BR nslookup (8),
 RFC 823, and RFC 1123.
 .SH BUGS
-Not all mail daemons will implement 
+Not all mail daemons will implement
 .B expn
 or
 .BR vrfy .
@@ -1340,19 +1339,19 @@ When attempting to connect to a system to verify an address,
 only tries one IP address.  Most mail daemons
 will try harder.
 .LP
-It is assumed that you are running domain names and that 
-the 
-.BR nslookup (8) 
-program is available.  If not, 
+It is assumed that you are running domain names and that
+the
+.BR nslookup (8)
+program is available.  If not,
 .B expn
 will not be able to verify many addresses.  It will also pause
 for a long time unless you change the code where it says
 .I $have_nslookup = 1
 to read
-.I $have_nslookup = 
+.I $have_nslookup =
 .IR 0 .
 .LP
-Lastly, 
+Lastly,
 .B expn
 does not handle every valid address.  If you have an example,
 please submit a bug report.
@@ -1362,7 +1361,7 @@ that did about the same thing.  It has since suffered bit rot
 and Jon Broome has dropped off the face of the earth!
 (Jon, if you are out there, drop me a line)
 .SH AVAILABILITY
-The latest version of 
+The latest version of
 .B expn
 is available through anonymous ftp at
 .IR ftp://ftp.idiom.com/pub/muir-programs/expn .
diff --git a/contrib/amd/scripts/expn.in b/contrib/amd/scripts/expn.in
index de48f8d..9ae5757 100755
--- a/contrib/amd/scripts/expn.in
+++ b/contrib/amd/scripts/expn.in
@@ -15,7 +15,7 @@ $SOCK_STREAM = &SOCK_STREAM;
 # system requirements:
 # 	must have 'nslookup' and 'hostname' programs.
 
-# $Header: /src/cvsroot/am-utils-6.0/scripts/expn.in,v 1.2 1999/09/18 08:38:07 ezk Exp $
+# $Header: /home/cvsroot/am-utils/scripts/expn.in,v 1.5 2002/07/11 14:28:20 ezk Exp $
 
 # TODO:
 #	less magic should apply to command-line addresses
@@ -59,7 +59,7 @@ $SOCK_STREAM = &SOCK_STREAM;
 #  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 #  SUCH DAMAGE.
 #
-# This copyright notice derrived from material copyrighted by the Regents
+# This copyright notice derived from material copyrighted by the Regents
 # of the University of California.
 #
 # Contributions accepted.
@@ -114,7 +114,7 @@ $0 = "$av0 - lookup host FQDN and IP addr";
 ($hostname,$aliases,$type,$len,$thisaddr) = gethostbyname($name);
 
 $0 = "$av0 - parsing args";
-$usage = "Usage: $av0 [-1avwd] user[\@host] [user2[host2] ...]";
+$usage = "Usage: $av0 [-1avwd] user[\@host] [user2[\@host2] ...]";
 for $a (@ARGV) {
 	die $usage if $a eq "-";
 	while ($a =~ s/^(-.*)([1avwd])/$1/) {
@@ -257,7 +257,7 @@ while (@hosts) {
 			# on the results of our query until we have looked
 			# at the complete output.  @toFinal stores expansions
 			# that will be final if we take them.  @toExpn stores
-			# expnansions that are not final.  @isValid keeps
+			# expansions that are not final.  @isValid keeps
 			# track of our ability to send mail to each of the
 			# expansions.
 			#
@@ -783,7 +783,7 @@ sub domainify
 	}
 
 	#
-	# There are several weird situtations that need to be
+	# There are several weird situations that need to be
 	# accounted for.  They have to do with domain relay hosts.
 	#
 	# Examples:
@@ -954,7 +954,7 @@ sub mxredirect
 	return undef;
 }
 # follow mx records, return a hostname
-# also follow temporary redirections comming from &domainify and
+# also follow temporary redirections coming from &domainify and
 # &mxlookup
 sub mx
 {
@@ -1032,7 +1032,7 @@ sub mxlookup
 		}
 		if (/Non-existent domain/) {
 			#
-			# These addresss are hosed.  Kaput!  Dead!
+			# These addresses are hosed.  Kaput!  Dead!
 			# However, if we created the address in the
 			# first place then there is a chance of
 			# salvation.
@@ -1091,7 +1091,7 @@ sub mxunroll
 	print "looking for mxbacktrace{$addr *** $host}\n"
 		if ($debug > 1);
 	while (defined $mxbacktrace{"$addr *** $host"}) {
-		print "Unrolling MX expnasion: \@$host:$addr -> "
+		print "Unrolling MX expansion: \@$host:$addr -> "
 			if ($debug || $verbose);
 		$host = $mxbacktrace{"$addr *** $host"};
 		print "\@$host:$addr\n"
@@ -1103,7 +1103,7 @@ sub mxunroll
 		if ($host =~ /\./);
 	return 0;
 }
-# register a completed expnasion.  Make the final address as
+# register a completed expansion.  Make the final address as
 # simple as possible.
 sub final
 {
@@ -1315,7 +1315,7 @@ Finally, the
 debug, flag will expose many of the inner workings so that
 it is possible to eliminate bugs.
 .SH ENVIRONMENT
-No enviroment variables are used.
+No environment variables are used.
 .SH FILES
 .PD 0
 .B /tmp/expn$$
diff --git a/contrib/amd/scripts/fix-amd-map.in b/contrib/amd/scripts/fix-amd-map.in
index 6746462..9bbc9b6 100755
--- a/contrib/amd/scripts/fix-amd-map.in
+++ b/contrib/amd/scripts/fix-amd-map.in
@@ -5,7 +5,7 @@
 # takes any number of files on the command line, and produces
 # a fixed map on stdout.
 #
-# Package:	am-utils-6.0
+# Package:	am-utils-6.x
 # Author:	Erez Zadok <ezk@cs.columbia.edu>
 #
 
diff --git a/contrib/amd/scripts/fixrmtab.in b/contrib/amd/scripts/fixrmtab.in
index 33b7bcf..2300380 100755
--- a/contrib/amd/scripts/fixrmtab.in
+++ b/contrib/amd/scripts/fixrmtab.in
@@ -5,7 +5,7 @@
 #
 # usage: fixrmtab host1 host2 ...
 #
-# Package:	am-utils-6.0
+# Package:	am-utils-6.x
 # Author:	Andreas Stolcke <stolcke@icsi.berkeley.edu>
 
 #set -x
diff --git a/contrib/amd/scripts/lostaltmail.conf-sample b/contrib/amd/scripts/lostaltmail.conf-sample
deleted file mode 100644
index a20158c..0000000
--- a/contrib/amd/scripts/lostaltmail.conf-sample
+++ /dev/null
@@ -1,84 +0,0 @@
-# -*- perl -*-
-##############################################################################
-#									     #
-#			CONFIGURABLE VALUES				     #
-#									     #
-##############################################################################
-
-$MAILGRUNT="postmaster";	# To whom to send log mail if mail is prefered.
-
-$TMPDIR="/tmp/";		# Place lostmail can do its dirty work.
-
-$LOCAL_LOCK_EXT=".lock";	# Name of file local mailer uses to lock
-				# spool file.  This the correct setting for
-				# /bin/mail
-
-$SYSTEM_FROM_ADDRESS="Mailer-Daemon";
-
-$MAILDIR="/var/alt_mail";	# What directory should I run out of.
-$MAILER='/usr/lib/sendmail -t'; # Which mailer should I use.
-
-$LOCALMAILJUNK='.*~|\#.*|core';	# Files name patterns that might appear in 
-				# alt_mail and should be ignored. This REGEXP
-				# gets or'ed with $MAILJUNK below.
-
-$SMTPHOST='localhost';		# The name of a local host which speaks SMTP
-				# and knows *all* your aliases. You probably
-				# don't want to change this.  If the machine
-				# running lost_alt mail doesn't run an SMTP,
-				# daemon then something is either wrong or you
-				# should be setting `noverify' to prevent
-				# SMTP verification.
-
-$HOSTNAME='localhost';		# Hostname to use for SMTP HELO 
-
-# Subject of lost log mail message. Must define $MAILGRUNT.
-# I overwrite this variable in the subroutine Clean_up. Please make sure I
-# haven't noodle-headdly forgotten to remove that hack in the distribution!
-# No newline here please. The script will insert it for you.
-$LOG_SUBJECT="Log of lostmail resends";
-
-##############################################################################
-#									     #
-#			DEFAULTED CONFIGURATIONS			     #
-#									     #
-##############################################################################
-
-$LOGFILE="$TMPDIR" . "lostlog";
-
-
-# MAILJUNK is a pattern of ignorable alt_mail files which are either common
-# to most platforms or actually produced by this script.  You should customize
-# this REGEXP by hacking at $LOCALMAILJUNK above.
-$MAILJUNK='[a-z]\.[0-9]*|\.\.?|lost\+found';
-
-$LOCKEXT=".lostlock";		# our lock file extension. Should not need to
-				# modify
-
-$MESSAGE_DELIM="^From[^:]";	# /bin/mail message delimiter. Your milage
-				# may differ
-
-$HEADER_BODY_DELIM="\n";	# RFC 822 header-body delimiter.
-
-$RESENT_TO="Resent-To: ";	# 
-$RESENT_FROM="Resent-From: ";	# Resent headers (RFC 822).
-$RESENT_DATE="Resent-Date: ";	#  You probably don't want to muck with these.
-$RESENT_INFO="X-Resent-Info: ";	# (special one to alert folks about mail).
-
-
-##############################################################################
-#									     #
-#			LOSTMAIL DEFINITIONS (DON'T TOUCH)		     #
-#									     #
-##############################################################################
-
-$FALSE=0;
-$TRUE=(! $FALSE);
-
-$OK=$TRUE;
-$ABORT_RESEND=2;
-$LOCK_RETRIES=10;	# The number of seconds/retries lost mail
-				#  should wait before requeing or aborting a
-				# resend.
-
-TRUE;				# Ansures true return from include file.
diff --git a/contrib/amd/scripts/lostaltmail.in b/contrib/amd/scripts/lostaltmail.in
deleted file mode 100755
index 8d1e6ec..0000000
--- a/contrib/amd/scripts/lostaltmail.in
+++ /dev/null
@@ -1,649 +0,0 @@
-#!@PERL@ -sw
-#
-# Package:	am-utils-6.0
-# Author:	James Tanis <jtt@cs.columbia.edu>
-#
-
-############################################################################
-#
-# lostaltmail -- remail files files found alt_mail (or -a argument to hlfsd) to
-# whomever should receive it. This version is for SMTP varient which
-# support VRFY as a non-expanding verifier!!! (sendmail V8 is a an
-# example).
-#
-# Usage: lostaltmail [-debug] [-nomail] [-noverify]
-#
-# 		GLOBAL VARIABLES (as if you care :-) )
-# Probably a very incomplete list.
-#
-# Everything in the config file for this program *and* ...
-#
-# $debug: set it from the command line with -debug. Does the obvious
-# $nomail: set it from the command line with -nomail. *Not* implied by
-#	 $debug
-# $currentTO: The addresss we are currently checking on.  Actually this is
-#	left over from an earlier version of lostaltmail and will hopefully
-#	go away.
-# $noverify: set it from the address line. Avoid verification of $currentTO.
-#	This should be relatively safe as long as your are willing to
-#	endure bounces from mail that cannot be redelivered as opposed to
-#	just getting a warning. UNTESTED (but should work).
-#
-# $logopen: state variable indicating weather the log file (should there be
-#	one) is in fact open.
-#
-# @allentries: Array of all the directory entries in $MAILDIR
-# @allnames: Array of all *likely* recipients. It is created from @allentries
-#	sans junk files (see $MAILJUNK and $LOCALMAILJUNK)
-# @wanderers: Array of all the files associated with a *single* address
-#	which might need remailing.  Should lostaltmail die unexpectedly,
-#	it might leave a temporary file containing messages it was
-#	currently trying to deliver.  These will get picked and resent
-#	later.
-#
-# VRFY: Handle onto SMTP verification channel.  Not to be confused with mail
-#	delivery; only verification occurs accross this handle.
-#
-############################################################################
-
-##############################################################################
-#									     #
-#				SMTP_SEND				     #
-#								     	     #
-##############################################################################
-#
-# Send a message to the smtp channel. Inserts the necessary NEWLINE if it
-# does not exist;
-# I stole this from myself. It shouldn nott be printing errors to STDERR, but
-# this is a quick hack.
-#
-sub smtp_send {
-    local ($msg) = @_;
-    local ($length);
-
-    $length=length($msg);
-
-    if ( $msg !~ /^.*\n$/ ) {
-	$msg = $msg . "\n";
-	$length++;
-    }
-
-
-    if ( ! syswrite (VRFY, $msg, $length)) {
-	print STDERR "Failing SMTP write: $msg";
-	return 0;
-    }
-
-    return 1;
-}
-
-##############################################################################
-#									     #
-#				SMTP_RECV				     #
-#								     	     #
-##############################################################################
-#
-# Read in lines from SMTP connection and return the final
-# 	Really hideous -- please excuse.
-#
-sub smtp_recv {
-    local ($line,$rin, $win, $ein, $readbuf, $ret);
-    $readbuf = "";
-
-    $rin = $win = $ein = '';	# Null fd sets,
-    vec ($rin, fileno(VRFY), 1) = 1; # Stolen straight from the example;
-    $ein = $rin | $win;		# This is probably useless
-
-
-LINE_OF_INPUT:
-    while (1) {			# Read in all the input
-
-	if ((select ( $rin, $win, $ein, 600.0))[0]  == 0 ) {
-	    print "select returned -1" if ($debug);
-	    return -1;	# timeout
-	}
-	sysread (VRFY, $readbuf, 1024);
-	chop ($readbuf);
-
-	foreach $line (	split('\n', $readbuf)) {
-
-	    # This loop is actually needed since V8 has a multi-line greet.
-
-	    ( $line =~ /^(\d\d\d).*/ && ($SMTP_retval=$1)) ||
-		warn "Badly formed reply from SMTP peer: $line\n";
-
-	    # Space after return code indicates EOT
-
-	    if ($line =~ /^\d\d\d /) {
-		$ret = $line;	# Oddly $line is in a different context here;
-				# and thus we need to export it out of the
-				# while loop via $ret.
-		last LINE_OF_INPUT;
-	    }
-	} # End of read.
-    } # End of input.
-
-    return $ret;
-}
-
-
-
-
-##############################################################################
-#									     #
-#				LOG_INFO				     #
-#								     	     #
-##############################################################################
-#
-#
-# Opens appropriate logging file -- STDOUT (cron) or temp file (mail).
-#
-sub Log_info {
-    local($message) = @_;
-
-    if ( !$logopened )  {
-	if ( $MAILGRUNT eq "" || $debug) {
-	    open (LOGFILE, ">-") || die  "Unable to open stdout";
-	}
-	else {
-	    # Snarf the log into a tmp file for final mailing to MAILGRUNT
-	    $logfile = $LOGFILE . ".$$";
-	    open (LOGFILE, (">". "$logfile")) || die "Unable to create log file";
-	}
-    }
-
-    $logopened=1;		# Note that the log is now open
-
-    # Heart of the function.
-    print LOGFILE "$message";
-
-    print LOGFILE "\n" if ( index($message,"\n") == -1 );
-}
-
-##############################################################################
-#									     #
-#				LOCK_FILE				     #
-#									     #
-##############################################################################
-
-#
-# Tries to grab a lock on the supplied file name.
-# Spins for a bit if it can't on the assumption that the lock will be released
-#	quickly.  If it times out and it's allowed to requeue, it will defer
-#	until later, other wise write a message to loginfo.
-
-# If a recurring error or really unexpected situation arrises, return
-# 	ABORT_RESEND
-#
-#  PARAMETERS
-# mailfile: path to the file to resend.
-# should_requeue: BOOLEAN - TRUE if the mailfile should be put on the
-# queue for a later retry if we can not finish
-# now.
-
-sub Lock_file {
-
-    local($mailfile,$should_requeue,$i,$new_lost_file) = @_;
-
-# We need to rename the current mailbox so that mail can loop back into it if
-# the resent mail just gets looped right back to us.
-    $new_lost_file = $mailfile . ".$$";
-
-#  make a tmpfile name based on mailfile;
-    $lostlockfile = "$mailfile" . "$LOCKEXT";
-
-    if ( ! open(LOCKFILE, (">" . $lostlockfile)) ) {
-	printf(STDERR "Could not create lostlockfile for %s: %s\n", $mailfile,$!);
-	return $ABORT_RESEND;
-    }
-    close(LOCKFILE);
-
-    $maillockfile = "$mailfile" . "$LOCAL_LOCK_EXT";
-
-    for ($i=0; $i < $LOCK_RETRIES && ! link ($lostlockfile, $maillockfile);
-	 $i++) {
-	sleep(1);
-    }
-
-    unlink($lostlockfile);	# No matter what eliminate our cruft
-
-    if ( $i == $LOCK_RETRIES ) {
-	&Log_info("Could not grab lock on: " . "$mailfile" . " :timed out");
-	if ( $should_requeue ) {
-	    &Log_info("Requeing " . "$mailfile" . " for later retry");
-	    $retry_list .= " $mailfile";
-	}
-	else {
-	    &Log_info("Giving up on: " . "$mailfile");
-	}
-
-	return $ABORT_RESEND;
-    }
-
-    # We created the link and therefore have the lock
-
-    if (rename ($mailfile, $new_lost_file) == 0 ){
-	# Failed to rename file -- this is serious.
-	unlink($maillockfile);
-	return $ABORT_RESEND;
-    }
-
-    unlink($maillockfile);
-    return $new_lost_file;
-
-}
-
-##############################################################################
-#									     #
-#			PARSE NEXT MAIL MESSAGE				     #
-#									     #
-##############################################################################
-#
-# Parameters:
-#  mailfile: handle of mailfile to use.
-#
-# Parses the next message in the mail file and inserts it in $current_msg
-#
-sub Get_next_msg {
-    local($mailfile,$found_body_delimiter) = @_;
-
-    # If this is the first message in the spool file, read the first line
-    # otherwise use the MESSAGE_DELIM line from the previous message (which we
-    # were forced to overread).
-
-    $done=$FALSE;
-    $found_body_delimiter=$FALSE;
-
-    # This if eats the very first "From " line and should never fire again.
-    if ( ! defined $current_msg ) {<$mailfile>};
-    undef ($current_msg);	# Erase the old message.
-
-
-    # Read the mailfile and pass through all the lines up until the next
-    # message delimiter. Kill any previous resend headers.
-    while ( <$mailfile> ) {
-	last if (/$MESSAGE_DELIM/);
-	next if ( !$found_body_delimiter && /[Rr][Ee][Ss][Ee][Nn][Tt]-.+:/);
-	if (  !$found_body_delimiter && /^$HEADER_BODY_DELIM/) {
-	    &Splice_in_resent_headers();
-	    $found_body_delimiter=$TRUE;
-	}
-	if (defined($current_msg)) {
-	    $current_msg .= $_;
-	} else {
-	    $current_msg = $_;
-	}
-    }
-
-    # Return TRUE when we have hit the end of the file.
-    if (!defined($_) || $_ eq "" ) {
-	return $TRUE;
-    } else {
-	return $FALSE;
-    }
-}
-
-##############################################################################
-#									     #
-#			SPLICE IN RESENT_HEADERS			     #
-#									     #
-##############################################################################
-#
-# Insert the Resent- headers at the *current location* of the message stream
-# (In Engish, print out a few Resent-X: lines and return :-) )
-# In addition splice in the X-resent-info: header.
-
-#
-# Paremters: None.
-# Return: None
-#
-sub Splice_in_resent_headers {
-    local($date,$utctime,$weekday,$time,$month,$hostname);
-
-    $current_msg .= "$RESENT_TO" . "$currentTO" . "\n";
-    $current_msg .= "$RESENT_FROM" . "$SYSTEM_FROM_ADDRESS" . "\n";
-
-    # Calculate date and time.  It is a bit of a shame to do this each time
-    # the time needs to be acurate.
-
-    @utctime=gmtime(time);
-
-    $weekday=(Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$utctime[6]];
-
-
-    # If the minutes or second do not take two columns each, patch em up.
-    if ( $utctime[1] < 10 ) {
-	if ( $utctime[0] < 10 ) {
-	    $time=sprintf("%d:0%d:0%d",$utctime[2],$utctime[1],$utctime[0]);
-	}
-	else {
-	    $time=sprintf("%d:0%d:%d",$utctime[2],$utctime[1],$utctime[0]);
-	}
-    }
-    else {
-	if ( $utctime[0] < 10 ) {
-	    $time=sprintf("%d:%d:0%d",$utctime[2],$utctime[1],$utctime[0]);
-	}
-        else {
-	    $time=sprintf("%d:%2d:%2d",$utctime[2],$utctime[1],$utctime[0]);
-	}
-    }
-
-    $month=(Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$utctime[4]];
-
-    # Ensure Y2K format
-    $date=sprintf("%s, %d %s %d %s UTC", $weekday, $utctime[3], $month, $utctime[5]+1900, $time);
-
-    $current_msg .= "$RESENT_DATE" . $date . "\n";
-
-    if ( defined $RESENT_INFO && $RESENT_INFO ne "") {
-	$hostname=`uname -n`;
-	$current_msg .= "$RESENT_INFO" . "Lost mail resent from ". $hostname;
-    }
-
-    return;
-}
-
-##############################################################################
-#									     #
-#				DO_REMAIL				     #
-#									     #
-##############################################################################
-#
-# Actually resends the mail.   Talks to the process configured as $MAILER
-# We need better handling.
-#
-sub Do_remail {
-    open (MAILER, "| $MAILER $currentTO") || return $ABORT_RESEND;
-    print MAILER $current_msg;
-    close (MAILER);
-}
-
-##############################################################################
-#									     #
-#				CLEAN_UP				     #
-#									     #
-##############################################################################
-#
-# Clean up my messes.
-#
-sub Clean_up {
-    local ($hostname);
-
-    # Ugly local hack that you should never have seen, but I forgot to
-    # remove.  Hopefully it did not kill you (I tried as you see), but you
-    # should eiter remove or update it for yourself.  I find the message
-    # subject needs to have the hostname to be useful.
-    #
-    chop ($hostname=`uname -n`);
-    $LOG_SUBJECT="$LOG_SUBJECT from $hostname" if ( $hostname =~ /.*\.cs\.columbia\.edu/ );
-    #
-    # End of ugly local hack
-
-    # Mail any log info to MAILGRUNT.
-    if (defined($logfile) && $logfile ne "" ) {
-	close (LOGFILE);	# Flush logfile output.
-	if ( -s $logfile ) {
-	    open (MAILER, "| $MAILER $MAILGRUNT");
-
-	    print MAILER "To: $MAILGRUNT\n";
-	    print MAILER "Subject: $LOG_SUBJECT\n";
-	    print MAILER "$HEADER_BODY_DELIM";
-
-	    open (LOGFILE, "< $logfile");
-
-	    while (<LOGFILE>) {
-		print MAILER $_;
-	    }
-	    close (MAILER);
-	    close (LOGFILE);
-	}
-
-	unlink($logfile);
-    }
-    exit(0);
-}
-
-
-##############################################################################
-#									     #
-#				COLLECT_WANDERERS			     #
-#									     #
-##############################################################################
-
-#
-# Collects other files that appear to be mail file for the $currentTO
-# but were not remailed successfully.
-#
-# Parameters: none (but uses $currentTO)
-# Return:  True if a old mail directory is found. False otherwise.
-# Side effects: $wanderers set.
-#
-sub Collect_wanderers {
-
-    undef (@wanderers);
-
-    # Slurp in the directory and close.
-
-    return ($found);
-}
-
-#############################################################################
-#									    #
-#				REMAIL ALL				    #
-#									    #
-#############################################################################
-
-#
-# Takes an array of files that all seem to share a common repcipient and
-# remails them if possible.
-#
-# Parameters: None (uses @wanderers).
-#
-sub Remail_all {
-    local($file,$i);
-
-    $i=0;
-    foreach $file (@wanderers) {
-	if ( !open (LOSTFILE, "< $file"))  {
-	    &Log_info("Could not open " . "$file" . " for remailing");
-	    next;
-	}
-
-	do {			# Power loop!
-	    $done = &Get_next_msg(LOSTFILE); # Retrieve the next message...
-	    &Do_remail;		# and remail it.
-	} until $done;
-	undef ($current_msg);	# Erase the final remailed message.
-
-	close(LOSTFILE);	# Tidy up.
-
-	unlink ($file);		# Remove the remailed file
-	$i++;
-    }
-
-}
-
-#############################################################################
-#									    #
-#				CHECK_USER				    #
-#									    #
-#############################################################################
-
-#
-# Checks the password tables for the uid of $currentTO. If the user is
-# uid 0 (ie *supposed* to get mail in altmail) or unknown the resend is
-# aborted.
-#
-#
-sub Check_user {
-    local (@passwdinfo);
-    undef (@passwdinfo);
-
-    if ( !&vrfy_user($currentTO) ) {
-    	&Log_info("Possible non user mail file: $currentTO");
-	return $ABORT_RESEND;
-    }
-
-    @passwdinfo = getpwnam($currentTO);
-
-    print "Non user mailable mail: Name: $currentTO\n"
-	if ( $debug && ! defined @passwdinfo );
-
-    return !$ABORT_RESEND if ( ! defined @passwdinfo ); # A non user but evidently mailable
-
-    print "Check User(): Name: $currentTO  -- UID: $passwdinfo[2]\n" if ($debug);
-
-    return $ABORT_RESEND if ( $passwdinfo[2] == 0 );
-
-
-    return !$ABORT_RESEND;
-}
-
-#############################################################################
-#									    #
-#				VRFY USER				    #
-#									    #
-#############################################################################
-#
-# Use SMTP VRFY to insure that argument is in fact a legal mail id.
-#  Boolean: TRUE if mailable account, FALSE if not.
-
-sub vrfy_user {
-
-	local ($mailname,$repl) = @_;
-
-	if ( !&smtp_send("vrfy $mailname") ) {
-	    &Log_info("Failed sending to vrfy smtp command for: $mailname");
-	    return 0;
-	}
-
-	$repl = &smtp_recv;
-
-	print "VRFY REPLY: $repl\n" if ($debug);
-
-	return ( $repl =~ /^2\d\d/ );
-
-
-}
-
-
-#############################################################################
-#									    #
-#				MAIN PROC				    #
-#									    #
-#############################################################################
-
-# dummy code to shut up perl -w
-$debug = 0 if !defined($debug);
-print $nomail if $debug > 1;
-print $RESENT_FROM if $debug > 1;
-print $logopen if $debug > 1;
-print $LOCAL_LOCK_EXT if $debug > 1;
-print $RESENT_TO if $debug > 1;
-print $LOCKEXT if $debug > 1;
-print $RESENT_DATE if $debug > 1;
-print $MESSAGE_DELIM if $debug > 1;
-print $SMTP_retval if $debug > 1;
-print $found if $debug > 1;
-print $retry_list if $debug > 1;
-print $MAILJUNK if $debug > 1;
-print $noverify if $debug > 1;
-print $SYSTEM_FROM_ADDRESS if $debug > 1;
-
-# BEGIN: stuff
-$prefix="@prefix@";
-$CONFIGDIR="@sysconfdir@";	# Directory where global config lives
-require "$CONFIGDIR/lostaltmail.conf" if (-f "$CONFIGDIR/lostaltmail.conf");
-require "/etc/global/lostaltmail.conf" if (-f "/etc/global/lostaltmail.conf");
-require "/etc/os/lostaltmail.conf" if (-f "/etc/os/lostaltmail.conf");
-require "/etc/local/lostaltmail.conf" if (-f "/etc/local/lostaltmail.conf");
-
-
-require "ctime.pl";
-use Socket;
-#require "sys/socket.ph";
-
-# SET some initial state variales
-$logopen = 0;
-
-#
-# Change to alt_dir
-#
-# Important!! This directory should be local.  Folks will be responsible
-# for finding this out for themselves.
-#
-chdir ( $MAILDIR ) || die "Cannot change to $MAILDIR (`x' bit not set?)";
-
-#
-# slurp in directory
-#
-opendir (MAIL, ".") || die "Cannot open $MAILDIR (`r' bit not set?)";
-@allentries= readdir (MAIL);
-closedir (MAIL);
-@allnames = grep (!/$LOCALMAILJUNK|$MAILJUNK/, @allentries);
-
-# Open chanel to SMTP for verification -- unless this option is
-# configured off.
-
-if ( ! $noverify ) {
-    local($addr, $port,$sockaddr);
-
-    socket (VRFY, &AF_INET, &SOCK_STREAM, 0) ||
-	die "Could not create TCP socket (SMTP channel)";
-
-    $addr = (gethostbyname($SMTPHOST))[4]; # Just use the first addr
-
-    die "Could not obtain STMP host ($SMTPHOST) address"
-	if ( $addr eq "" );
-
-    $port = (getservbyname('smtp','tcp'))[2]; # Get smtp port.
-    die "Could not obtain SMTP port number" if (!defined($port));
-
-    printf("SMTP: address: %s   port: $port\n",
-	   join ('.',unpack('C4',$addr))) if ($debug);
-
-    $sockaddr = sockaddr_in($port, $addr);
-
-    printf("Sockaddr: %s\n", join (' ',unpack('C14',$sockaddr))) if ($debug);
-
-    connect (VRFY, $sockaddr) ||
-	die "Could not connect to SMTP daemon on $SMTPHOST";
-
-    print "Establshed SMTP channel\n" if ($debug);
-
-    &smtp_recv;	# Greet wait
-    &smtp_send("helo $SMTPHOST"); # Helo message for picky SMTPs
-    &smtp_recv;		# Helo reply
-
-    # Connection is up and ready to VRFY
-}
-
-# main stuff starts here
-foreach $currentTO (@allnames) {
-    next if ( &Check_user == $ABORT_RESEND);
-
-    undef (@wanderers);	# Just reset this at each pass.
-    @wanderers=grep (/$currentTO\.\d+/, @allentries);
-
-    $remail_file = &Lock_file($currentTO,$FALSE); # Need to lock the spool.
-
-    next if ( $remail_file eq $ABORT_RESEND); # Could not get that lock
-
-    push (@wanderers, $remail_file); # Try to resend "old" files.
-    print "List to remail: @wanderers\n" if ($debug);
-    # check if  there is something to remail
-    &Remail_all if ( defined @wanderers && !$nomail);
-}
-
-# this stuff should run at the end
-foreach $file (grep (/$LOCALMAILJUNK/,@allentries)) {
-
-    if ($debug) {
-	print "Would unlink $file\n" if ($debug);
-    } else {
-	unlink $file  if (-f $file);
-    }
-
-}
-&Clean_up;			# Do a clean exit.
diff --git a/contrib/amd/scripts/redhat-ctl-amd.in b/contrib/amd/scripts/redhat-ctl-amd.in
new file mode 100755
index 0000000..4d00d47
--- /dev/null
+++ b/contrib/amd/scripts/redhat-ctl-amd.in
@@ -0,0 +1,106 @@
+#!/bin/bash
+#
+# Version: 1.3
+#
+# chkconfig: - 72 28
+# description: Runs the automount daemon that mounts devices and NFS hosts \
+#	       on demand.
+# processname: amd
+# config: /etc/amd.conf
+#
+
+# we require the /etc/amd.conf file
+[ -f /etc/amd.conf ] || exit 0
+[ -f /etc/sysconfig/amd ] || exit 0
+
+# Source function library.
+. /etc/init.d/functions
+
+# Recover AMDOPTS from /etc/sysconfig/amd.
+if [ -f /etc/sysconfig/amd ] ; then
+	. /etc/sysconfig/amd
+fi
+
+RETVAL=0
+prog=amd
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+amd=@sbindir@/amd
+
+start() {
+	echo -n "Starting $prog: "
+	daemon $amd -F /etc/amd.conf $AMDOPTS $OPTIONS $MOUNTPTS
+	RETVAL=$?
+	echo
+	[ $RETVAL = 0 ] && touch /var/lock/subsys/amd
+	return $RETVAL
+}
+
+stop() {
+
+	echo -n "Stopping $prog: "
+        # modeled from /usr/sbin/ctl-amd
+	pid=`/usr/sbin/amq -p 2>/dev/null`
+	if [ "$pid" = "" ] ; then
+		# amq -p did not give pid, so try ps
+		pid=`ps acx 2>/dev/null | grep "amd" | sed -e 's/^  *//' -e 's/ .*//'`
+	fi
+	if [ "$pid" = "" ] ; then
+		failure "amd shutdown pid"
+		echo
+		return 1
+	fi
+	kill $pid
+        # and this part is from wait4amd2die
+	delay=5
+	count=6
+	i=1
+	maxcount=`expr $count + 1`
+	while [ $i != $maxcount ]; do
+		# run amq
+		/usr/sbin/amq > /dev/null 2>&1
+		if [ $? != 0 ]
+		then
+			# amq failed to run (because amd is dead)
+			success "amd shutdown"
+			rm -f /var/lock/subsys/amd
+			echo
+			return 0
+		fi
+		sleep $delay
+		i=`expr $i + 1`
+	done
+	failure "amd shutdown (still up)"
+	echo
+	return 1
+}
+# See how we were called.
+case "$1" in
+  start)
+        start
+	;;
+  stop)
+        stop
+	;;
+  status)
+	status $amd
+	;;
+  restart)
+	stop
+	start
+	;;
+  condrestart)
+        if [ -f /var/lock/subsys/amd ]; then
+	    stop
+	    start
+	fi
+	;;
+  reload)
+	action "Reloading $prog:" killall -HUP $amd
+	;;
+  *)
+ 	echo "Usage: $0 {start|stop|restart|reload|condrestart|status}"
+	exit 1
+esac
+
+exit 0
diff --git a/contrib/amd/scripts/test-attrcache.in b/contrib/amd/scripts/test-attrcache.in
new file mode 100755
index 0000000..061308b
--- /dev/null
+++ b/contrib/amd/scripts/test-attrcache.in
@@ -0,0 +1,135 @@
+#!/bin/sh
+# Script to test the attribute cache behavior of the local OS client.
+# If this script fails, it means that Amd cannot turn off the attrcache
+# reliably on this host, and Amd therefore may not run reliably.  See
+# the README.attrcache file distributed with this am-utils.
+#	-Erez Zadok, September 29, 2005
+
+# set PATH (must install am-utils first)
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+PATH=@sbindir@:@bindir@:/usr/ucb:/usr/bin:/bin:${PATH}
+export PATH
+
+# test if amd is running
+amq -p > /dev/null 2>&1
+if test $? = 0
+then
+	echo "### Amd already running... please shutdown Amd first"
+	exit 1
+fi
+
+mapfile="/tmp/amd.testmap.$$"
+logfile="/var/log/amd"
+delay=1
+a=/a
+
+CreateMap1 () {
+	echo "### Creating correct map"
+	cat - >$mapfile <<EOF
+a	type:=link;fs:=/tmp/a
+EOF
+}
+
+CreateMap2 () {
+	echo "### Creating weird map"
+	cat - >$mapfile <<EOF
+a	type:=link;fs:=/tmp/b
+EOF
+}
+
+StopAMD () {
+	ctl-amd stop
+# do not delete files we may need to use to debug Amd
+#	rm -f /tmp/a /tmp/b $mapfile $logfile
+}
+
+touch /tmp/a
+touch /tmp/b
+
+CreateMap1
+echo amd -x all -D all -r -l $logfile $a $mapfile -cache:=mapdefault,sync
+amd -x all -D all -r -l $logfile $a $mapfile -cache:=mapdefault,sync
+sleep 3				# give amd chance to start properly
+amq
+inode_a=`ls -lLi /tmp/a | awk '{print $1}'`
+inode_b=`ls -lLi /tmp/b | awk '{print $1}'`
+ls -lLi $a/a
+ls -lLi $a/b
+ls -l $mapfile
+
+# how many times to try until we call it a success...
+maxtry=10
+while test $maxtry -gt 0
+do
+	echo "$maxtry tries left ..."
+	let maxtry=maxtry-1
+	amq
+	CreateMap1
+	sleep $delay
+
+	ls -l $mapfile
+	echo "### looking at a... should get a"
+	ino=`ls -lLi $a/a | awk '{print $1}'`
+	if test -z "$ino"
+	then
+		ls -li $a/a
+		amq
+		amq -m
+		stat $a
+		echo "a link does not exist!"
+		StopAMD
+		exit 1
+	fi
+	if test $ino -ne $inode_a
+	then
+		ls -li $a/a
+		amq
+		amq -m
+		stat $a
+		echo "a link does not point to A!"
+		StopAMD
+		exit 1
+	fi
+
+# Here is the main trick we try: force amd to flush one entry, then
+# change the amd map on disk, and then see if the kernel will have
+# flushed the attribute cache; if it did, then Amd will see the
+# correctly changed map entry.
+
+	amq -u $a/a
+	sleep $delay
+	stat $a
+
+	CreateMap2
+	sleep $delay
+
+	ls -l $mapfile
+	echo "### looking at a... should get b"
+	ino=`ls -lLi $a/a | awk '{print $1}'`
+	if test -z "$ino"
+	then
+		ls -li $a/a
+		amq
+		amq -m
+		stat $a
+		echo "a link does not exist!"
+		StopAMD
+		exit 1
+	fi
+	if test $ino -ne $inode_b
+	then
+		ls -li $a/a
+		amq
+		amq -m
+		stat $a
+		echo "a link does not point to B!"
+		StopAMD
+		exit 1
+	fi
+
+	amq -u $a/a
+	sleep $delay
+	stat $a
+done
+StopAMD
diff --git a/contrib/amd/scripts/wait4amd.in b/contrib/amd/scripts/wait4amd.in
index 5fd5030..5e6c33a 100755
--- a/contrib/amd/scripts/wait4amd.in
+++ b/contrib/amd/scripts/wait4amd.in
@@ -3,7 +3,7 @@
 # usage: wait4amd <hostname> [<command> [args ...]]
 # If only hostname is supplied, command defaults to rsh $hostname
 #
-# Package:	am-utils-6.0
+# Package:	am-utils-6.x
 # Author:	Erez Zadok <ezk@cs.columbia.edu>
 
 #set -x
diff --git a/contrib/amd/scripts/wait4amd2die.in b/contrib/amd/scripts/wait4amd2die.in
index d3541e7..94a0851 100755
--- a/contrib/amd/scripts/wait4amd2die.in
+++ b/contrib/amd/scripts/wait4amd2die.in
@@ -4,7 +4,7 @@
 # If not specified, delay=5 seconds and count=6 (total 30 seconds)
 # If at end of total delay amd is till up, return 1; else return 0.
 #
-# Package:	am-utils-6.0
+# Package:	am-utils-6.x
 # Author:	Erez Zadok <ezk@cs.columbia.edu>
 
 #set -x
@@ -20,14 +20,14 @@ if test -n "$1"
 then
 	delay=$1
 else
-	delay=5
+	delay=3
 fi
 # how many times to delay
 if test -n "$2"
 then
 	count=$2
 else
-	count=6
+	count=10
 fi
 
 i=1
diff --git a/contrib/amd/tasks b/contrib/amd/tasks
index 976d3b2..24b6834 100644
--- a/contrib/amd/tasks
+++ b/contrib/amd/tasks
@@ -1,65 +1,37 @@
-# -*- text -*-
-
-			  AM-UTILS-6.0 TASKS TODO
+			  AM-UTILS-6.1 TASKS TODO
 
 Please volunteer to do any of the following:
 
-- complete testing of untested platforms in INSTALL file
-	ncr2
-	sunos 3.5
-
 - autofs support: see README.autofs for details.
-	needs to be re-ported to solaris 2.6 (headers changed)
 
 - deal with everything that has XXX on it in the sources
 - documentation update ("XXX: FILL IN" sections).
 
-- hlfsd should be able to not use /var/alt_mail, but send code 75 back to
-  sendmail (telling it to re-queue the mail and retry later).
-
 - compatibility with Sun's automount maps?
 	should be easier via the amd.conf file to specify type of map
-	perhaps done at the same time autofs support is done.
-
-- a selector ala if_exists() for networkmask(1.2.3.4/5.6.7.8), will match
-  against all known IP addresses of this host.
 
 - convert to using my own rpcgen .x files for amq/amq/nfs (v2 and v3)
 
-- support multiple "fail-over" NFS mounts in Solaris 2.6.
-
-- use packaging info for various OSs (such as RPM, Redhat Package Format)
+- use packaging info for various OSs (such as RPM, Redhat Package Manager)
 
 - $mindelay and $maxdelay in milliseconds
 
 - multiple nfsl should be matched if one matched and nfs mount failed.  fall
   through.
-- fall through syntax?  opts:=nofail,fallthrough?
+- support multiple "fail-over read-only" NFS mounts in Solaris 2.6+.
 
 - random nfs rhost:={srv1, srv2, srv3}
 
 - nfslx, same as nfsl, but using linkx
 
-- find out why this sometimes works and sometimes not:
-	mcl	-rhost:=minetta host!=${rhost};type:=nfs host==${rhost}
-
 - loadable info_*, amfs_*, and ops_* modules (lazy evaluation).
 
-- hlfsd for ~root/.mailspool (getpwnam("root"))
 - hlfsd should daemonize even if -DDEBUG, then use -D nofork
 
 - fixmount should use generic code from transp/transp_{tli,sockets}.c
 
-- report netbsd/openbsd bugs in BUGS file
-
 - reverse notion of -F and other cmd-line options, so they override the
-amd.conf file (right now amd.conf overrides cmd-line options).
-
-- y2k compliance.
-
-- an un/install script for binaries
-
-- update README
+  amd.conf file (right now amd.conf overrides cmd-line options).
 
 - add am-utils URL and COPYRIGHT to all distributed scripts and sources and
   programs etc. also to amq -v output.
@@ -67,38 +39,73 @@ amd.conf file (right now amd.conf overrides cmd-line options).
 - ion: browsable_dirs only works for nis if in [global] broken if it is file
   maps.
 
-- all if statements should have an else clause because of Ultrix's /bin/sh.
-
-- look for obsolete AM_* macros and use newer AC_* ones
-- use 3rd arg to AC_CHECK_TYPE (headers)
-
-- FreeBSD 3.1 doesn't have SYMTTL flag, so the mtime of the hlfsd symlink is
-  always new.  This breaks hlfsd on FreeBSD 3.1, b/c the acregmin/max code
-  depends on the time that the symlink was created.  Solution: best is to
-  support NOAC in the FreeBSD kernel, otherwise hlfsd will have to know not
-  to turn on this code in hlfsd/stubs.c:
-
-    if (++slinkfattr.na_mtime.nt_useconds == 0)
-      ++slinkfattr.na_mtime.nt_seconds;
-
-- support nqnfs as per Jeffrey C Honig <jch@BSDI.COM>: "Besides having
-  NFSMNT_NQNFS set when you try to do the mount, NQNFS requires that you do
-  the nfssvc() call to create an nqnfs client daemon.  I can't see any
-  obvious way to check if the server supports NQNFS."
-
 - browsable 'auto' style maps.
 
-- amq man page: amq -f also reloads maps that are not updated
-
 - mention signals in amd man page
 
 - ALLOWED_MOUNT_TIME of 40 seconds is way too long!
-- need option to turn off pings of portmapper before trying a mount
+- detecting down'ed hosts faster: use default portmap TTL variables?
+- push get_nfs_version() down into a child process
 
-- type:=program should not require umount command. can use defult
+- type:=program should not require umount command. can use default
   umount(). it works for smbmount/umount.
 
 - document var[0-7] variables/selectors
 
 - need a way to export a nfs-mount point after it is being mounted (jukebox
   mounts).  can do this with type:=program.
+
+- support port=n, for machines that use NFS on a different port
+
+- nfsl may be buggy when fs:= is specified explicitly (lockup?)
+
+- y2k: amq /home (mounted time uses YY instead of YYYY)
+
+- new amd.conf option to disable amq listener altogether (security)
+	Should be available even if DEBUG is off.
+
+- new amd.conf option dynamic_system_params to recompute osver, karch,
+  etc. from uname() dynamically.
+
+- solaris 8 doesn't pick up hsfs/pcfs/etc *_args structures and mount flags
+
+- avoid having to compile ops_nfs3.o
+
+- linux support for ext3
+
+- be able to pass generic mount options to systems w/ a mount(2) that
+  supports it (Linux).  Perhaps genopt="foo,bar" syntax.
+
+- support several different nfs servers inside one nfsx entry
+
+- reimplement the "parallel mounting" for multiple matching sub-entries
+
+- fix amd.conf parser so it can parse key=value without spaces around the
+  "=" sign.  Note this isn't so trivial because 'value' may include "="
+  signs.
+
+- NFSv4 support (such a short "tasks" entry given how much work it is :-)
+
+
+* documentation
+- document what can and what can't be a top-level mount type (i.e. a
+  map-backed or map-holding type). Currently that's toplvl, auto, and
+  direct.
+- document how to add a direct map to amd.conf.
+
+* autofs stuff
+Linux:
+- host mounts broken with autofs v3
+- nfsx status unknown
+- local filesystems (ufs, etc) status unknown
+
+Solaris:
+- host mounts status unknown
+- nfsx status unknown
+- local filesystems (ufs, etc) status unknown
+
+FreeBSD:
+- just do it
+
+All:
+- mntfs->mf_fo->opt_fs can contain garbage sometimes??
diff --git a/contrib/amd/vers.m4 b/contrib/amd/vers.m4
new file mode 100644
index 0000000..7343910
--- /dev/null
+++ b/contrib/amd/vers.m4
@@ -0,0 +1 @@
+[6.1.5]dnl
diff --git a/contrib/amd/wire-test/wire-test.8 b/contrib/amd/wire-test/wire-test.8
index 4ba8b15..07b7a14 100644
--- a/contrib/amd/wire-test/wire-test.8
+++ b/contrib/amd/wire-test/wire-test.8
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-1999 Erez Zadok
+.\" Copyright (c) 1997-2006 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.
@@ -38,11 +38,10 @@
 .\"
 .\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: wire-test.8,v 1.2 1999/01/10 21:54:44 ezk Exp $
-.\" $FreeBSD: src/contrib/amd/wire-test/wire-test.8,v 1.3 1999/09/15 05:45:17 obrien Exp $
-.\" $DragonFly: src/contrib/amd/wire-test/wire-test.8,v 1.2 2003/06/17 04:23:58 dillon Exp $
+.\" $Id: wire-test.8,v 1.10.2.1 2006/01/02 18:48:26 ezk Exp $
+.\" $FreeBSD: src/contrib/amd/wire-test/wire-test.8,v 1.9 2012/11/17 01:48:41 svnexp Exp $
 .\"
-.Dd February 26, 1993
+.Dd January 2, 2006
 .Dt WIRE-TEST 8
 .Os
 .Sh NAME
@@ -52,12 +51,15 @@
 .Nm
 .Op Ar host
 .Sh DESCRIPTION
+The
 .Nm
+utility
 is used to find out what
-.Nm Amd
-thinks are the first two network interfaces and network names/numbers
-used, as well as the IP address used for
-.Nm Amd
+.Xr amd 8
+thinks are the first two network
+interfaces and network names/numbers used, as well as the IP address
+used for
+.Xr amd 8
 to NFS-mount itself.
 .Pp
 If
@@ -73,11 +75,34 @@ server
 If not specified,
 .Ar host
 defaults to
-.Dq localhost .
+.Dq Li localhost .
 .Sh SEE ALSO
-.Xr amd 8 
+.Xr amd 8
+.Pp
+.Dq am-utils
+.Xr info 1
+entry.
+.Rs
+.%A Erez Zadok
+.%B "Linux NFS and Automounter Administration"
+.%O ISBN 0-7821-2739-8
+.%I Sybex
+.%D 2001
+.Re
+.Pp
+.Pa http://www.am-utils.org/
+.Rs
+.%T Amd \- The 4.4 BSD Automounter
+.Re
 .Sh HISTORY
 The
 .Nm
 utility appeared in
 .Fx 3.0 .
+.Sh AUTHORS
+.An Erez Zadok Aq ezk@cs.sunysb.edu ,
+Computer Science Department, Stony Brook University, Stony Brook, New York, USA.
+.Pp
+Other authors and contributors to am-utils are listed in the
+.Pa AUTHORS
+file distributed with am-utils.
diff --git a/contrib/amd/wire-test/wire-test.c b/contrib/amd/wire-test/wire-test.c
index 1cbf921..bcaaf5a 100644
--- a/contrib/amd/wire-test/wire-test.c
+++ b/contrib/amd/wire-test/wire-test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-1999 Erez Zadok
+ * Copyright (c) 1997-2006 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.
@@ -36,11 +36,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *      %W% (Berkeley) %G%
  *
- * $Id: wire-test.c,v 1.4 1999/02/04 07:24:54 ezk Exp $
- * $FreeBSD: src/contrib/amd/wire-test/wire-test.c,v 1.5 1999/09/15 05:45:17 obrien Exp $
- * $DragonFly: src/contrib/amd/wire-test/wire-test.c,v 1.2 2003/06/17 04:23:58 dillon Exp $
+ * File: am-utils/wire-test/wire-test.c
  *
  */
 
@@ -81,7 +78,7 @@ main(int argc, char **argv)
   }
 
   /* also print my IP address */
-  amu_get_myaddress(&myipaddr);
+  amu_get_myaddress(&myipaddr, NULL);
   fprintf(stderr, "My IP address is 0x%x.\n", (unsigned int) htonl(myipaddr.s_addr));
 
   /*
@@ -100,6 +97,7 @@ main(int argc, char **argv)
   }
   ip = (struct sockaddr_in *) xmalloc(sizeof(struct sockaddr_in));
   memset((voidp) ip, 0, sizeof(*ip));
+  /* as per POSIX, sin_len need not be set (used internally by kernel) */
   ip->sin_family = AF_INET;
   memmove((voidp) &ip->sin_addr, (voidp) hp->h_addr, sizeof(ip->sin_addr));
   ip->sin_port = htons(NFS_PORT);
diff --git a/etc/amd.map b/etc/amd.map
index fbd3050..2cb37f0 100644
--- a/etc/amd.map
+++ b/etc/amd.map
@@ -1,5 +1,4 @@
-# $FreeBSD: src/etc/amd.map,v 1.8 1999/09/13 17:09:07 peter Exp $
-# $DragonFly: src/etc/amd.map,v 1.2 2003/06/17 04:24:45 dillon Exp $
+# $FreeBSD: src/etc/amd.map,v 1.11 2012/11/17 01:49:01 svnexp Exp $
 #
 /defaults       type:=host;fs:=${autodir}/${rhost}/host;rhost:=${key}
-*               opts:=rw,grpid,resvport,vers=2,proto=udp,nosuid,nodev
+*               opts:=rw,grpid,resvport,vers=3,proto=tcp,nosuid,nodev
diff --git a/etc/rc.d/amd b/etc/rc.d/amd
index 2ba0019..1825bd0 100644
--- a/etc/rc.d/amd
+++ b/etc/rc.d/amd
@@ -1,51 +1,47 @@
 #!/bin/sh
 #
-# $NetBSD: amd,v 1.10 2002/04/29 12:08:17 lukem Exp $
-# $FreeBSD: src/etc/rc.d/amd,v 1.9 2002/10/12 10:31:31 schweikh Exp $
-# $DragonFly: src/etc/rc.d/amd,v 1.5 2005/11/19 21:47:32 swildner Exp $
+# $FreeBSD: src/etc/rc.d/amd,v 1.27 2012/11/17 01:49:04 svnexp Exp $
 #
 
 # PROVIDE: amd
-# REQUIRE: rpcbind mountcritremote ypbind nfsclient
+# REQUIRE: rpcbind ypset nfsclient mountcritremote ldconfig
 # BEFORE: DAEMON
+# KEYWORD: nojail shutdown
 
 . /etc/rc.subr
 
 name="amd"
-rcvar=`set_rcvar`
+rcvar="amd_enable"
 command="/usr/sbin/${name}"
-
-	start_precmd="amd_precmd"
-	command_args="&"
+start_precmd="amd_precmd"
+command_args="&"
+extra_commands="reload"
 
 amd_precmd()
 {
-		if ! checkyesno nfs_client_enable; then
-			force_depend nfsclient || return 1
-		fi
-
-		if ! checkyesno rpcbind_enable  && \
-			! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1
-			then
-				force_depend rpcbind || return 1
+	force_depend nfsclient nfs_client || return 1
+	force_depend rpcbind || return 1
+
+	case ${amd_map_program} in
+	[Nn][Oo] | '')
+		;;
+	*)
+		rc_flags="${rc_flags} `echo $(eval ${amd_map_program})`"
+		;;
+	esac
+
+	case "${amd_flags}" in
+	'')
+		if [ ! -r /etc/amd.conf ]; then
+			warn 'amd will not load without arguments'
+			return 1
 		fi
-
-		case ${amd_map_program} in
-			[Nn][Oo] | '')
-			;;
-		*)
-			rc_flags="${rc_flags} `eval ${amd_map_program}`"
-			;;
-		esac
-
-		case "${amd_flags}" in
-			'')
-			if [ ! -r /etc/amd.conf ]; then
-				warn 'amd will not load without arguments'
-				return 1
-			fi
-			;;
-		esac
+		;;
+	*)
+		rc_flags="-p ${rc_flags}"
+		command_args="> /var/run/amd.pid 2> /dev/null"
+		;;
+	esac
 }
 
 load_rc_config $name
diff --git a/usr.sbin/amd/Makefile b/usr.sbin/amd/Makefile
index 9700962..b411849 100644
--- a/usr.sbin/amd/Makefile
+++ b/usr.sbin/amd/Makefile
@@ -3,10 +3,9 @@
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998
 #
-# $FreeBSD: src/usr.sbin/amd/Makefile,v 1.6.2.1 2001/04/25 12:09:12 ru Exp $
-# $DragonFly: src/usr.sbin/amd/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
-#
+# $FreeBSD: src/usr.sbin/amd/Makefile,v 1.9 2012/11/17 01:54:36 svnexp Exp $
 
-SUBDIR= include libamu amd amq doc fixmount fsinfo hlfsd mk-amd-map pawd scripts wire-test
+SUBDIR= include libamu amd amq doc fixmount fsinfo hlfsd mk-amd-map pawd \
+	scripts wire-test
 
 .include <bsd.subdir.mk>
diff --git a/usr.sbin/amd/Makefile.inc b/usr.sbin/amd/Makefile.inc
index add2c42..4b243fb 100644
--- a/usr.sbin/amd/Makefile.inc
+++ b/usr.sbin/amd/Makefile.inc
@@ -1,7 +1,6 @@
 # ex:ts=8
 #
-# $FreeBSD: src/usr.sbin/amd/Makefile.inc,v 1.5.2.1 2001/04/25 12:09:12 ru Exp $
-# $DragonFly: src/usr.sbin/amd/Makefile.inc,v 1.2 2003/06/17 04:29:52 dillon Exp $
+# $FreeBSD: src/usr.sbin/amd/Makefile.inc,v 1.18 2012/11/17 01:54:36 svnexp Exp $
 #
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998.
@@ -9,16 +8,24 @@
 #	$NetBSD: Makefile.inc,v 1.10 1998/08/08 22:33:27 christos Exp $
 #	Portions derived from amd/libamu/Makefile
 #	$NetBSD: Makefile,v 1.8 1998/08/08 22:33:37 christos Exp $
-#
 
-CFLAGS+=	-I. -I${.CURDIR} 
-CFLAGS+=	-I${.CURDIR}/../include
+.include <bsd.own.mk>
+
+CFLAGS+= -I. -I${.CURDIR} 
+CFLAGS+= -I${.CURDIR}/../include
 .if exists(${.OBJDIR}/../include)
-CFLAGS+=	-I${.OBJDIR}/../include
+CFLAGS+= -I${.OBJDIR}/../include
 .endif
-CFLAGS+=	-I${.CURDIR}/../../../contrib/amd/include
-CFLAGS+=	-I${.CURDIR}/../../../contrib/amd
-CFLAGS+=	-DHAVE_CONFIG_H
+CFLAGS+= -I${.CURDIR}/../../../contrib/amd/include
+CFLAGS+= -I${.CURDIR}/../../../contrib/amd
+CFLAGS+= -DHAVE_CONFIG_H
+CFLAGS+= -DHAVE_LOCALCONFIG_H
+
+.if defined(WANT_HESIOD)
+CFLAGS+= -DYES_HESIOD
+.endif
+
+CFLAGS+= -DHOST_CPU=\"${MACHINE_CPUARCH}\" -DHOST_ARCH=\"${MACHINE_ARCH}\"
 
 .if exists(${.OBJDIR}/../libamu)
 LIBAMUDIR=	${.OBJDIR}/../libamu
@@ -27,11 +34,11 @@ LIBAMUDIR=	${.CURDIR}/../libamu
 .endif
 LIBAMU=		${LIBAMUDIR}/libamu.a
 
-RPCCOM=		rpcgen
+RPCCOM=		RPCGEN_CPP=${CPP:Q} rpcgen
 MOUNT_X=	${DESTDIR}/usr/include/rpcsvc/mount.x
 NFS_PROT_X=	${DESTDIR}/usr/include/rpcsvc/nfs_prot.x
 
-WARNS?=		0
+WARNS?=	1
 
 .if exists(${.CURDIR}/../../Makefile.inc)
 .include "${.CURDIR}/../../Makefile.inc"
diff --git a/usr.sbin/amd/amd/Makefile b/usr.sbin/amd/amd/Makefile
index fec2910..6c05512 100644
--- a/usr.sbin/amd/amd/Makefile
+++ b/usr.sbin/amd/amd/Makefile
@@ -3,35 +3,36 @@
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998
 #
-# $FreeBSD: src/usr.sbin/amd/amd/Makefile,v 1.17.2.1 2001/04/25 12:09:12 ru Exp $
-# $DragonFly: src/usr.sbin/amd/amd/Makefile,v 1.4 2006/05/14 18:07:29 swildner Exp $
+# $FreeBSD: src/usr.sbin/amd/amd/Makefile,v 1.30 2012/11/17 01:54:36 svnexp Exp $
 #
 
-.PATH:		${.CURDIR}/../../../contrib/amd/amd
+.include <bsd.own.mk>
 
-PROG=		amd
-MAN=		amd.8
+.PATH: ${.CURDIR}/../../../contrib/amd/amd
 
-SRCS=		conf_parse.y conf_tok.l
-SRCS+=		am_ops.c amd.c amfs_auto.c amfs_direct.c amfs_error.c
-SRCS+=		amfs_host.c amfs_inherit.c amfs_link.c amfs_linkx.c amfs_nfsl.c
-SRCS+=		amfs_nfsx.c amfs_program.c amfs_root.c amfs_toplvl.c
-SRCS+=		amfs_union.c amq_subr.c amq_svc.c autil.c clock.c conf.c
-SRCS+=		get_args.c info_file.c info_ndbm.c info_nis.c info_passwd.c 
-SRCS+=		info_union.c map.c mapc.c mntfs.c nfs_prot_svc.c nfs_start.c 
-SRCS+=		nfs_subr.c ops_cdfs.c ops_lofs.c ops_mfs.c ops_nfs.c ops_nfs3.c 
-SRCS+=		ops_nullfs.c ops_pcfs.c ops_tfs.c ops_ufs.c
-SRCS+=		ops_unionfs.c opts.c restart.c rpc_fwd.c sched.c
-SRCS+=		srvr_amfs_auto.c srvr_nfs.c
+PROG=	amd
+MAN=	amd.8
+SRCS=	conf_parse.y conf_tok.l
+SRCS+=	am_ops.c amd.c amfs_auto.c amfs_direct.c amfs_error.c amfs_generic.c
+SRCS+=	amfs_host.c amfs_link.c amfs_linkx.c amfs_nfsl.c
+SRCS+=	amfs_nfsx.c amfs_program.c amfs_root.c amfs_toplvl.c
+SRCS+=	amfs_union.c amq_subr.c amq_svc.c autil.c clock.c conf.c
+SRCS+=	get_args.c info_exec.c info_file.c info_ndbm.c info_passwd.c
+SRCS+=	info_union.c map.c mapc.c mntfs.c nfs_prot_svc.c nfs_start.c
+SRCS+=	nfs_subr.c ops_cdfs.c ops_mfs.c ops_nfs.c ops_nfs3.c
+SRCS+=	ops_nullfs.c ops_pcfs.c ops_tfs.c ops_ufs.c ops_umapfs.c
+SRCS+=	ops_unionfs.c opts.c readdir.c restart.c rpc_fwd.c sched.c
+SRCS+=	srvr_amfs_auto.c srvr_nfs.c
 
-CFLAGS+=	-I${.CURDIR}/../../../contrib/amd/amd
+CFLAGS+= -I${.CURDIR}/../../../contrib/amd/amd \
+	 -I${DESTDIR}/usr/include/rpcsvc
 
-DPADD=		${LIBAMU} ${LIBRPCSVC}
-LDADD=		${LIBAMU} -lrpcsvc
+DPADD=	${LIBAMU} ${LIBWRAP}
+LDADD=	${LIBAMU} -lwrap
 
 CLEANFILES+=	conf_parse.c conf_parse.h conf_tok.c
 
-conf_tok.o:	conf_parse.h
+conf_tok.o: conf_parse.h
 
 #		These are generated at compile time
 SRCS+=		mount_xdr.c
@@ -40,4 +41,12 @@ CLEANFILES+=	mount_xdr.c
 mount_xdr.c: ${MOUNT_X}
 	${RPCCOM} -c -DWANT_NFS3 ${MOUNT_X} -o ${.TARGET}
 
+.if defined(WANT_HESIOD)
+SRCS+=	info_hesiod.c
+CFLAGS+= -DHAVE_MAP_HESIOD
+.endif
+
+SRCS+=	info_nis.c
+CFLAGS+= -DHAVE_MAP_NIS
+
 .include <bsd.prog.mk>
diff --git a/usr.sbin/amd/amq/Makefile b/usr.sbin/amd/amq/Makefile
index 8bf0651..8ab7c00 100644
--- a/usr.sbin/amd/amq/Makefile
+++ b/usr.sbin/amd/amq/Makefile
@@ -3,20 +3,18 @@
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998
 #
-# $FreeBSD: src/usr.sbin/amd/amq/Makefile,v 1.12.2.1 2001/04/25 12:09:13 ru Exp $
-# $DragonFly: src/usr.sbin/amd/amq/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
+# $FreeBSD: src/usr.sbin/amd/amq/Makefile,v 1.16 2012/11/17 01:54:36 svnexp Exp $
 #
 
-.PATH:		${.CURDIR}/../../../contrib/amd/amq
+.PATH: ${.CURDIR}/../../../contrib/amd/amq
 
-PROG=		amq
-MAN=		amq.8
+PROG=	amq
+MAN=	amq.8
+SRCS=	amq.c amq_clnt.c amq_xdr.c
 
-SRCS=		amq.c amq_clnt.c amq_xdr.c
+CFLAGS+= -I${.CURDIR}/../../../contrib/amd/amq
 
-CFLAGS+=	-I${.CURDIR}/../../../contrib/amd/amq
-
-DPADD+=		${LIBAMU}
-LDADD+=		${LIBAMU}
+DPADD=	${LIBAMU}
+LDADD=	${LIBAMU}
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/amd/doc/Makefile b/usr.sbin/amd/doc/Makefile
index a36fb61..78e68ab 100644
--- a/usr.sbin/amd/doc/Makefile
+++ b/usr.sbin/amd/doc/Makefile
@@ -1,7 +1,8 @@
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998.
 
-# $FreeBSD: src/usr.sbin/amd/doc/Makefile,v 1.10 1999/08/28 01:15:14 peter Exp $
-# $DragonFly: src/usr.sbin/amd/doc/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
+# $FreeBSD: src/usr.sbin/amd/doc/Makefile,v 1.12 2012/11/17 01:54:36 svnexp Exp $
+
+.PATH: ${.CURDIR}/../../../contrib/amd/doc
 
 INFO=	am-utils
 
@@ -10,6 +11,4 @@ INFOENTRY= 	"* Am-utils: (am-utils).	The Amd automounter suite of utilities"
 
 MAKEINFOFLAGS+=	-I ${.CURDIR}/../../../contrib/amd/doc
 
-.PATH:	${.CURDIR}/../../../contrib/amd/doc
-
 .include <bsd.info.mk>
diff --git a/usr.sbin/amd/fixmount/Makefile b/usr.sbin/amd/fixmount/Makefile
index 3d4b78b..39a00ed 100644
--- a/usr.sbin/amd/fixmount/Makefile
+++ b/usr.sbin/amd/fixmount/Makefile
@@ -3,22 +3,19 @@
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998
 #
-# $FreeBSD: src/usr.sbin/amd/fixmount/Makefile,v 1.4.2.1 2001/04/25 12:09:13 ru Exp $
-# $DragonFly: src/usr.sbin/amd/fixmount/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
-#
-
-.PATH:		${.CURDIR}/../../../contrib/amd/fixmount \
-		${.CURDIR}/../../../contrib/amd/conf/checkmount
+# $FreeBSD: src/usr.sbin/amd/fixmount/Makefile,v 1.9 2012/11/17 01:54:36 svnexp Exp $
 
-PROG=		fixmount
-MAN=		fixmount.8
+.PATH: ${.CURDIR}/../../../contrib/amd/fixmount \
+       ${.CURDIR}/../../../contrib/amd/conf/checkmount
 
-SRCS=		fixmount.c 
+PROG=	fixmount
+MAN=	fixmount.8
+SRCS=	fixmount.c 
 
-#		These would be links created by the GNU-style configure
-SRCS+=		checkmount_bsd44.c
+#	These would be links created by the GNU-style configure
+SRCS+=	checkmount_bsd44.c
 
-DPADD=		${LIBAMU} ${LIBRPCSVC}
-LDADD=		${LIBAMU} -lrpcsvc
+DPADD=	${LIBAMU} ${LIBRPCSVC}
+LDADD=	${LIBAMU} -lrpcsvc
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/amd/fsinfo/Makefile b/usr.sbin/amd/fsinfo/Makefile
index 2ac274d..dbfe67d 100644
--- a/usr.sbin/amd/fsinfo/Makefile
+++ b/usr.sbin/amd/fsinfo/Makefile
@@ -3,23 +3,23 @@
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998
 #
-# $FreeBSD: src/usr.sbin/amd/fsinfo/Makefile,v 1.10.2.1 2001/04/25 12:09:14 ru Exp $
-# $DragonFly: src/usr.sbin/amd/fsinfo/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
-#
+# $FreeBSD: src/usr.sbin/amd/fsinfo/Makefile,v 1.15 2012/11/17 01:54:36 svnexp Exp $
 
-.PATH:		${.CURDIR}/../../../contrib/amd/fsinfo
+.PATH: ${.CURDIR}/../../../contrib/amd/fsinfo
 
-PROG=		fsinfo
-MAN=		fsinfo.8
+PROG=	fsinfo
+MAN=	fsinfo.8
+SRCS=	fsi_gram.y fsi_lex.l
+SRCS+=	fsi_analyze.c fsi_dict.c fsi_util.c fsinfo.c wr_atab.c 
+SRCS+=	wr_bparam.c wr_dumpset.c wr_exportfs.c wr_fstab.c
 
-SRCS=		fsi_gram.y fsi_lex.l
-SRCS+=		fsi_analyze.c fsi_dict.c fsi_util.c fsinfo.c wr_atab.c 
-SRCS+=		wr_bparam.c wr_dumpset.c wr_exportfs.c wr_fstab.c
+CFLAGS+= -I${.CURDIR}/../../../contrib/amd/fsinfo
 
-CFLAGS+=	-I${.CURDIR}/../../../contrib/amd/fsinfo
+DPADD=	${LIBAMU}
+LDADD=	${LIBAMU}
 
 CLEANFILES+=	fsi_gram.c fsi_gram.h fsi_lex.c
 
-fsi_lex.o:	fsi_gram.h
+fsi_lex.o: fsi_gram.h
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/amd/hlfsd/Makefile b/usr.sbin/amd/hlfsd/Makefile
index fef54cf..e353e52 100644
--- a/usr.sbin/amd/hlfsd/Makefile
+++ b/usr.sbin/amd/hlfsd/Makefile
@@ -3,20 +3,17 @@
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998
 #
-# $FreeBSD: src/usr.sbin/amd/hlfsd/Makefile,v 1.4.2.1 2001/04/25 12:09:14 ru Exp $
-# $DragonFly: src/usr.sbin/amd/hlfsd/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
-#
-
-.PATH:		${.CURDIR}/../../../contrib/amd/hlfsd
+# $FreeBSD: src/usr.sbin/amd/hlfsd/Makefile,v 1.9 2012/11/17 01:54:36 svnexp Exp $
 
-PROG=		hlfsd
-MAN=		hlfsd.8
+.PATH: ${.CURDIR}/../../../contrib/amd/hlfsd
 
-SRCS=		hlfsd.c homedir.c nfs_prot_svc.c stubs.c
+PROG=	hlfsd
+MAN=	hlfsd.8
+SRCS=	hlfsd.c homedir.c nfs_prot_svc.c stubs.c
 
-CFLAGS+=	-I${.CURDIR}/../../../contrib/amd/hlfsd
+CFLAGS+= -I${.CURDIR}/../../../contrib/amd/hlfsd
 
-DPADD=		${LIBAMU} ${LIBRPCSVC}
-LDADD=		${LIBAMU} -lrpcsvc
+DPADD=	${LIBAMU}
+LDADD=	${LIBAMU}
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/amd/include/Makefile b/usr.sbin/amd/include/Makefile
index 61f8b8e..e36a403 100644
--- a/usr.sbin/amd/include/Makefile
+++ b/usr.sbin/amd/include/Makefile
@@ -1,27 +1,28 @@
 # ex:ts=8
 #
-# $FreeBSD: src/usr.sbin/amd/include/Makefile,v 1.2.2.2 2001/07/19 19:06:18 ru Exp $
-# $DragonFly: src/usr.sbin/amd/include/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
+# $FreeBSD: src/usr.sbin/amd/include/Makefile,v 1.11 2012/11/17 01:54:36 svnexp Exp $
 #
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998.
 #	Portions derived from amd/libamu/Makefile
 #	$NetBSD: Makefile,v 1.8 1998/08/08 22:33:37 christos Exp $
-#
 
-SRCS=		config_local.h mount.h nfs_prot.h
+.include <bsd.own.mk>
+
+SRCS=	config_local.h
+SRCS+=	localconfig.h
 CLEANFILES=	${SRCS}
 
-all: ${SRCS}
+all depend: ${SRCS}
 
 config_local.h: newvers.sh
 	@rm -f ${.TARGET}
-	sh ${.ALLSRC} > ${.TARGET}
+	sh -x ${.ALLSRC} ${.CURDIR}/../../../sys/conf/newvers.sh > ${.TARGET}
 
-mount.h: ${MOUNT_X}
-	${RPCCOM} -h -C -DWANT_NFS3 ${MOUNT_X} -o ${.TARGET}
-
-nfs_prot.h: ${NFS_PROT_X}
-	${RPCCOM} -h -C -DWANT_NFS3 ${NFS_PROT_X} -o ${.TARGET}
+localconfig.h:
+	@rm -f ${.TARGET}
+	:> ${.TARGET}
+#	@echo "/* NIS disabled by WITHOUT_NIS src.conf option */" >> ${.TARGET}
+#	@echo "#undef HAVE_MAP_NIS" >> ${.TARGET}
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/amd/include/amu_autofs_prot.h b/usr.sbin/amd/include/amu_autofs_prot.h
new file mode 100644
index 0000000..bc4fd4c
--- /dev/null
+++ b/usr.sbin/amd/include/amu_autofs_prot.h
@@ -0,0 +1,8 @@
+// $FreeBSD: src/usr.sbin/amd/include/amu_autofs_prot.h,v 1.2 2012/11/17 01:54:36 svnexp Exp $
+
+/* Adjust once we have some form of Autofs support. */
+
+#if 0
+#include "conf/autofs/autofs_default.h"
+#endif
+
diff --git a/usr.sbin/amd/include/aux_conf.h b/usr.sbin/amd/include/aux_conf.h
index 802b7a4..ea4936b 100644
--- a/usr.sbin/amd/include/aux_conf.h
+++ b/usr.sbin/amd/include/aux_conf.h
@@ -1,7 +1,9 @@
+/* $FreeBSD: src/usr.sbin/amd/include/aux_conf.h,v 1.6 2012/11/17 01:54:36 svnexp Exp $ */
+
 /*
  * aux_conf.h:
  * This file gets "filled in" for each architecture.
- * Generated automatically from aux_conf.h.in by configure.
+ * aux_conf.h.  Generated from aux_conf.h.in by configure.
  */
 
 #ifndef _AUX_CONF_H
@@ -11,70 +13,60 @@
  * The next line is a literal inclusion of a file which includes a
  * definition for the MOUNT_TRAP macro for a particular architecture.
  * If it defines the wrong entry, check the AC_CHECK_MOUNT_TRAP m4 macro
- * in $srcdir/aux/macros.
+ * in $srcdir/m4/macros.
  */
 
 /* $srcdir/conf/trap/trap_default.h */
-#ifdef COMMENT_GET_DIRECTLY_FROM_FILE
 #define MOUNT_TRAP(type, mnt, flags, mnt_data) mount(type, mnt->mnt_dir, flags, mnt_data)
-#endif	/* COMMENT_GET_DIRECTLY_FROM_FILE */
-#include "conf/trap/trap_default.h"
 /* End of included MOUNT_TRAP macro definition file */
 
-
 /*
  * The next line is a literal replacement of a variable which defines the
  * the UNMOUNT_TRAP macro for a particular architecture.
  * If it defines the wrong entry, check the AC_CHECK_UNMOUNT_CALL m4 macro
  * in $srcdir/aclocal.m4.  If the arguments are being defined wrong, check
- * the macro AC_CHECK_UNMOUNT_ARGS in $srcdir/aux/macros.
+ * the macro AC_CHECK_UNMOUNT_ARGS in $srcdir/m4/macros.
  */
 #define UNMOUNT_TRAP(mnt)	unmount(mnt->mnt_dir)
 /* End of replaced UNMOUNT_TRAP macro definition */
+/* umount(8) executable path, for type:=program */
+#define UNMOUNT_PROGRAM		"/sbin/umount"
 
 /*
  * The next line is a literal inclusion of a file which includes a
  * definition for the NFS_FH_DREF macro for a particular architecture.
  * If it defines the wrong entry, check the AC_CHECK_NFS_FH_DREF m4 macro
- * in $srcdir/aux/macros.
+ * in $srcdir/m4/macros.
  */
 
 /* $srcdir/conf/fh_dref/fh_dref_freebsd22.h */
-#ifdef COMMENT_GET_DIRECTLY_FROM_FILE
 #define	NFS_FH_DREF(dst, src) (dst) = (u_char *) (src)
-#endif	/* COMMENT_GET_DIRECTLY_FROM_FILE */
-#include "conf/fh_dref/fh_dref_freebsd22.h"
 /* End of included NFS_FH_DREF macro definition file */
 
 /*
  * The next line is a literal inclusion of a file which includes a
  * definition for the NFS_SA_DREF macro for a particular architecture.
  * If it defines the wrong entry, check the AC_CHECK_NFS_SA_DREF m4 macro
- * in $srcdir/aux/macros.
+ * in $srcdir/m4/macros.
  */
 
 /* $srcdir/conf/sa_dref/sa_dref_bsd44.h */
-#ifdef COMMENT_GET_DIRECTLY_FROM_FILE
 #define	NFS_SA_DREF(dst, src) { \
 		(dst)->addr = (struct sockaddr *) (src); \
 		(dst)->addrlen = sizeof(*src); \
 	}
-#endif	/* COMMENT_GET_DIRECTLY_FROM_FILE */
-#include "conf/sa_dref/sa_dref_bsd44.h"
+#define NFS_ARGS_T_ADDR_IS_POINTER 1
 /* End of included NFS_SA_DREF macro definition file */
 
 /*
  * The next line is a literal inclusion of a file which includes a
  * definition for the NFS_HN_DREF macro for a particular architecture.
  * If it defines the wrong entry, check the AC_CHECK_NFS_HN_DREF m4 macro
- * in $srcdir/aux/macros.
+ * in $srcdir/m4/macros.
  */
 
 /* $srcdir/conf/hn_dref/hn_dref_default.h */
-#ifdef COMMENT_GET_DIRECTLY_FROM_FILE
 #define NFS_HN_DREF(dst, src) (dst) = (src)
-#endif	/* COMMENT_GET_DIRECTLY_FROM_FILE */
-#include "conf/hn_dref/hn_dref_default.h"
 /* End of included NFS_HN_DREF macro definition file */
 
 #endif /* not _AUX_CONF_H */
diff --git a/usr.sbin/amd/include/build_version.h b/usr.sbin/amd/include/build_version.h
index cfd9795..9cfc1d0 100644
--- a/usr.sbin/amd/include/build_version.h
+++ b/usr.sbin/amd/include/build_version.h
@@ -1,7 +1,8 @@
-/* $DragonFly: src/usr.sbin/amd/include/build_version.h,v 1.2 2004/08/09 15:06:44 eirikn Exp $ */
-/* do not edit this file by hand */
-/* auto-generated by update_build_version script */
-/* #define AMU_BUILD_VERSION 1 */
+/* $FreeBSD: src/usr.sbin/amd/include/build_version.h,v 1.3 2012/11/17 01:54:36 svnexp Exp $ */
 
 #include <sys/param.h>
+/*#define AMU_BUILD_VERSION 1 */
 #define AMU_BUILD_VERSION __DragonFly_version
+#define USER_NAME "David O'Brien <obrien"
+#define HOST_NAME "FreeBSD.org>"
+#define CONFIG_DATE "4-December-2007 PST"
diff --git a/usr.sbin/amd/include/config.h b/usr.sbin/amd/include/config.h
index 13e6c5d..df2b470 100644
--- a/usr.sbin/amd/include/config.h
+++ b/usr.sbin/amd/include/config.h
@@ -1,2007 +1,2188 @@
-/* 
- * $FreeBSD: src/usr.sbin/amd/include/config.h,v 1.15.2.1 2001/08/29 08:46:52 alfred Exp $
- * $DragonFly: src/usr.sbin/amd/include/config.h,v 1.5 2006/05/14 18:07:29 swildner Exp $
- *
- * portions derived from 
- *	$NetBSD: config.h,v 1.11 1998/08/08 22:33:37 christos Exp $
- *
- */
-
-/* config.h.  Generated automatically by configure.  */
-/* aux/config.h.in.  Generated automatically from ./aux/configure.in by autoheader.  */
 /*
- * Start of am-utils-6.x config.h file.
- * Erez Zadok <ezk@cs.columbia.edu>
+ * $FreeBSD: src/usr.sbin/amd/include/config.h,v 1.34 2012/11/17 01:54:36 svnexp Exp $
  *
- * DO NOT EDIT BY HAND.
- * Note: acconfig.h generates config.h.in, which generates config.h.
+ * portions derived from
+ *      $NetBSD: config.h,v 1.11 1998/08/08 22:33:37 christos Exp $
  */
 
 #ifndef _CONFIG_H
 #define _CONFIG_H
 
+/* We [FREEBSD-NATIVE] pick some parameters from our local config file */
+#include "config_local.h"
 
-/*
- * Check for types of amd filesystems available.
- */
+/* define name of am-utils' NFS protocol header */
+#define AMU_NFS_PROTOCOL_HEADER "./conf/nfs_prot/nfs_prot_freebsd3.h"
+
+/* Type of the 5rd argument to authunix_create() */
+#define AUTH_CREATE_GIDLIST_TYPE gid_t
+
+/* Define configuration date */
+/* #define CONFIG_DATE "Tue Dec 4 21:39:00 PST 2007" */
+
+/* Turn off general debugging by default */
+/* #undef DEBUG */
+
+/* Turn off memory debugging by default */
+/* #undef DEBUG_MEM */
+
+/* Define name of host OS's distribution name (eg. debian, redhat, suse, etc.)
+   */
+#define DISTRO_NAME "The FreeBSD Project"
+
+/* Define to the type of elements in the array set by `getgroups'. Usually
+   this is either `int' or `gid_t'. */
+#define GETGROUPS_T gid_t
+
+/* Define to 1 if the `getpgrp' function requires zero arguments. */
+#define GETPGRP_VOID 1
 
 /* Define if have automount filesystem */
-#define HAVE_AM_FS_AUTO 1
+#define HAVE_AMU_FS_AUTO 1
 
 /* Define if have direct automount filesystem */
-#define HAVE_AM_FS_DIRECT 1
-
-/* Define if have "top-level" filesystem */
-#define HAVE_AM_FS_TOPLVL 1
+#define HAVE_AMU_FS_DIRECT 1
 
 /* Define if have error filesystem */
-#define HAVE_AM_FS_ERROR 1
-
-/* Define if have inheritance filesystem */
-#define HAVE_AM_FS_INHERIT 1
+#define HAVE_AMU_FS_ERROR 1
 
-/* Define if have program filesystem */
-#define HAVE_AM_FS_PROGRAM 1
+/* Define if have NFS host-tree filesystem */
+#define HAVE_AMU_FS_HOST 1
 
 /* Define if have symbolic-link filesystem */
-#define HAVE_AM_FS_LINK 1
+#define HAVE_AMU_FS_LINK 1
 
 /* Define if have symlink with existence check filesystem */
-#define HAVE_AM_FS_LINKX 1
-
-/* Define if have NFS host-tree filesystem */
-#define HAVE_AM_FS_HOST 1
+#define HAVE_AMU_FS_LINKX 1
 
 /* Define if have nfsl (NFS with local link check) filesystem */
-#define HAVE_AM_FS_NFSL 1
+#define HAVE_AMU_FS_NFSL 1
 
 /* Define if have multi-NFS filesystem */
-#define HAVE_AM_FS_NFSX 1
+#define HAVE_AMU_FS_NFSX 1
 
-/* Define if have union filesystem */
-#define HAVE_AM_FS_UNION 1
+/* Define if have program filesystem */
+#define HAVE_AMU_FS_PROGRAM 1
 
+/* Define if have "top-level" filesystem */
+#define HAVE_AMU_FS_TOPLVL 1
 
-/*
- * Check for types of maps available.
- */
+/* Define if have union filesystem */
+#define HAVE_AMU_FS_UNION 1
 
-/* Define if have file maps (everyone should have it!) */
-#define HAVE_MAP_FILE 1
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
 
-/* Define if have NIS maps */
-#define HAVE_MAP_NIS 1
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
 
-/* Define if have NIS+ maps */
-/* #undef HAVE_MAP_NISPLUS */
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
 
-/* Define if have DBM maps */
-/* #undef HAVE_MAP_DBM */
+/* Define to 1 if `addr' is member of `autofs_args_t'. */
+/* #undef HAVE_AUTOFS_ARGS_T_ADDR */
 
-/* Define if have NDBM maps */
-#define HAVE_MAP_NDBM 1
+/* define if have a bad version of hasmntopt() */
+/* #undef HAVE_BAD_HASMNTOPT */
 
-/* Define if have HESIOD maps */
-/* #undef HAVE_MAP_HESIOD */
+/* define if have a bad version of memcmp() */
+/* #undef HAVE_BAD_MEMCMP */
 
-/* Define if have LDAP maps */
-/* #undef HAVE_MAP_LDAP */
+/* define if have a bad version of yp_all() */
+/* #undef HAVE_BAD_YP_ALL */
 
-/* Define if have PASSWD maps */
-#define HAVE_MAP_PASSWD 1
+/* Define to 1 if you have the `bcmp' function. */
+#define HAVE_BCMP 1
 
-/* Define if have UNION maps */
-#define HAVE_MAP_UNION 1
+/* Define to 1 if you have the `bcopy' function. */
+#define HAVE_BCOPY 1
 
-/*
- * Check for filesystem types available.
- */
+/* Define to 1 if you have the <bsd/rpc/rpc.h> header file. */
+/* #undef HAVE_BSD_RPC_RPC_H */
 
-/* Define if have UFS filesystem */
-#define HAVE_FS_UFS 1
+/* Define to 1 if you have the `bzero' function. */
+#define HAVE_BZERO 1
 
-/* Define if have XFS filesystem (irix) */
-/* #undef HAVE_FS_XFS */
+/* System supports C99-style variable-length argument macros */
+#define HAVE_C99_VARARGS_MACROS 1
 
-/* Define if have EFS filesystem (irix) */
-/* #undef HAVE_FS_EFS */
+/* Define to 1 if `flags' is member of `cdfs_args_t'. */
+#define HAVE_CDFS_ARGS_T_FLAGS 1
 
-/* Define if have NFS filesystem */
-#define HAVE_FS_NFS 1
+/* Define to 1 if `fspec' is member of `cdfs_args_t'. */
+#define HAVE_CDFS_ARGS_T_FSPEC 1
 
-/* Define if have NFS3 filesystem */
-#define HAVE_FS_NFS3 1
+/* Define to 1 if `iso_flags' is member of `cdfs_args_t'. */
+/* #undef HAVE_CDFS_ARGS_T_ISO_FLAGS */
 
-/* Define if have PCFS filesystem */
-#define HAVE_FS_PCFS 1
+/* Define to 1 if `iso_pgthresh' is member of `cdfs_args_t'. */
+/* #undef HAVE_CDFS_ARGS_T_ISO_PGTHRESH */
 
-/* Define if have LOFS filesystem */
-#define HAVE_FS_LOFS 1
+/* Define to 1 if `norrip' is member of `cdfs_args_t'. */
+/* #undef HAVE_CDFS_ARGS_T_NORRIP */
 
-/* Define if have HSFS filesystem */
-/* #undef HAVE_FS_HSFS */
+/* Define to 1 if `ssector' is member of `cdfs_args_t'. */
+#define HAVE_CDFS_ARGS_T_SSECTOR 1
 
-/* Define if have CDFS filesystem */
-#define HAVE_FS_CDFS 1
+/* Define to 1 if you have the <cdfs/cdfsmount.h> header file. */
+/* #undef HAVE_CDFS_CDFSMOUNT_H */
 
-/* Define if have TFS filesystem */
-/* #undef HAVE_FS_TFS */
+/* Define to 1 if you have the <cdfs/cdfs_mount.h> header file. */
+/* #undef HAVE_CDFS_CDFS_MOUNT_H */
 
-/* Define if have TMPFS filesystem */
-/* #undef HAVE_FS_TMPFS */
+/* Define to 1 if you have the `clnt_create' function. */
+#define HAVE_CLNT_CREATE 1
 
-/* Define if have MFS filesystem */
-#define HAVE_FS_MFS 1
+/* Define to 1 if you have the `clnt_create_vers' function. */
+#define HAVE_CLNT_CREATE_VERS 1
 
-/* Define if have CFS (crypto) filesystem */
-/* #undef HAVE_FS_CFS */
+/* Define to 1 if you have the `clnt_create_vers_timed' function. */
+#define HAVE_CLNT_CREATE_VERS_TIMED 1
 
-/* Define if have AUTOFS filesystem */
-/* #undef HAVE_FS_AUTOFS */
+/* Define to 1 if you have the `clnt_spcreateerror' function. */
+#define HAVE_CLNT_SPCREATEERROR 1
 
-/* Define if have CACHEFS filesystem */
-/* #undef HAVE_FS_CACHEFS */
+/* Define to 1 if you have the `clnt_sperrno' function. */
+#define HAVE_CLNT_SPERRNO 1
 
-/* Define if have NULLFS (loopback on bsd44) filesystem */
-#define HAVE_FS_NULLFS 1
+/* Define to 1 if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
 
-/* Define if have UNIONFS filesystem */
-#define HAVE_FS_UNIONFS 1
+/* Define to 1 if you have the <cluster.h> header file. */
+/* #undef HAVE_CLUSTER_H */
 
+/* Define to 1 if you have the `cnodeid' function. */
+/* #undef HAVE_CNODEID */
 
-/*
- * Check for the type of the mount(2) system name for a filesystem.
- * Normally this is "nfs" (e.g. Solaris) or an integer (older systems)
- */
+/* Define to 1 if you have the <ctype.h> header file. */
+#define HAVE_CTYPE_H 1
 
-/* Mount(2) type/name for UFS filesystem */
-#define MOUNT_TYPE_UFS "ufs"
+/* Define to 1 if you have the <db1/ndbm.h> header file. */
+/* #undef HAVE_DB1_NDBM_H */
 
-/* Mount(2) type/name for XFS filesystem (irix) */
-/* #undef MOUNT_TYPE_XFS */
+/* Define to 1 if you have the `dbm_open' function. */
+#define HAVE_DBM_OPEN 1
 
-/* Mount(2) type/name for EFS filesystem (irix) */
-/* #undef MOUNT_TYPE_EFS */
+/* Define to 1 if you have the `dg_mount' function. */
+/* #undef HAVE_DG_MOUNT */
 
-/* Mount(2) type/name for NFS filesystem */
-#define MOUNT_TYPE_NFS "nfs"
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
 
-/* Mount(2) type/name for NFS3 filesystem */
-#define MOUNT_TYPE_NFS3 "nfs"
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
 
-/* Mount(2) type/name for PCFS filesystem */
-/* XXX: conf/trap/trap_hpux.h may override this definition for HPUX 9.0 */
-#define MOUNT_TYPE_PCFS "msdos"
+/* Define to 1 if `flags' is member of `efs_args_t'. */
+/* #undef HAVE_EFS_ARGS_T_FLAGS */
 
-/* Mount(2) type/name for LOFS filesystem */
-#define MOUNT_TYPE_LOFS "lofs"
+/* Define to 1 if `fspec' is member of `efs_args_t'. */
+/* #undef HAVE_EFS_ARGS_T_FSPEC */
 
-/* Mount(2) type/name for CDFS filesystem */
-#define MOUNT_TYPE_CDFS "cd9660"
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
 
-/* Mount(2) type/name for TFS filesystem */
-/* #undef MOUNT_TYPE_TFS */
+/* does extern definition for clnt_spcreateerror() exist? */
+#define HAVE_EXTERN_CLNT_SPCREATEERROR 1
 
-/* Mount(2) type/name for TMPFS filesystem */
-/* #undef MOUNT_TYPE_TMPFS */
+/* does extern definition for clnt_sperrno() exist? */
+#define HAVE_EXTERN_CLNT_SPERRNO 1
 
-/* Mount(2) type/name for MFS filesystem */
-#define MOUNT_TYPE_MFS "mfs"
+/* does extern definition for free() exist? */
+#define HAVE_EXTERN_FREE 1
 
-/* Mount(2) type/name for CFS (crypto) filesystem */
-/* #undef MOUNT_TYPE_CFS */
+/* does extern definition for getccent() (hpux) exist? */
+/* #undef HAVE_EXTERN_GETCCENT */
 
-/* Mount(2) type/name for AUTOFS filesystem */
-/* #undef MOUNT_TYPE_AUTOFS */
+/* does extern definition for getdomainname() exist? */
+#define HAVE_EXTERN_GETDOMAINNAME 1
 
-/* Mount(2) type/name for CACHEFS filesystem */
-/* #undef MOUNT_TYPE_CACHEFS */
+/* does extern definition for getdtablesize() exist? */
+#define HAVE_EXTERN_GETDTABLESIZE 1
 
-/* Mount(2) type/name for IGNORE filesystem (not real just ignore for df) */
-/* #undef MOUNT_TYPE_IGNORE */
+/* does extern definition for gethostname() exist? */
+#define HAVE_EXTERN_GETHOSTNAME 1
 
-/* Mount(2) type/name for NULLFS (loopback on bsd44) filesystem */
-#define MOUNT_TYPE_NULLFS "null"
+/* does extern definition for getlogin() exist? */
+#define HAVE_EXTERN_GETLOGIN 1
 
-/* Mount(2) type/name for UNIONFS filesystem */
-#define MOUNT_TYPE_UNIONFS "union"
+/* does extern definition for getpagesize() exist? */
+#define HAVE_EXTERN_GETPAGESIZE 1
 
+/* does extern definition for gettablesize() exist? */
+/* #undef HAVE_EXTERN_GETTABLESIZE */
 
-/*
- * Check for the string name for the mount-table of a filesystem.
- */
+/* does extern definition for getwd() exist? */
+#define HAVE_EXTERN_GETWD 1
 
-/* Mount-table entry name for UFS filesystem */
-#define MNTTAB_TYPE_UFS "ufs"
+/* does extern definition for get_myaddress() exist? */
+#define HAVE_EXTERN_GET_MYADDRESS 1
 
-/* Mount-table entry name for XFS filesystem (irix) */
-/* #undef MNTTAB_TYPE_XFS */
+/* does extern definition for hosts_ctl() exist? */
+/* #undef HAVE_EXTERN_HOSTS_CTL */
 
-/* Mount-table entry name for EFS filesystem (irix) */
-/* #undef MNTTAB_TYPE_EFS */
+/* does extern definition for innetgr() exist? */
+#define HAVE_EXTERN_INNETGR 1
 
-/* Mount-table entry name for NFS filesystem */
-#define MNTTAB_TYPE_NFS "nfs"
+/* does extern definition for ldap_enable_cache() exist? */
+/* #undef HAVE_EXTERN_LDAP_ENABLE_CACHE */
 
-/* Mount-table entry name for NFS3 filesystem */
-#define MNTTAB_TYPE_NFS3 "nfs"
+/* does extern definition for mkstemp() exist? */
+#define HAVE_EXTERN_MKSTEMP 1
 
-/* Mount-table entry name for PCFS filesystem */
-#define MNTTAB_TYPE_PCFS "msdos"
+/* does extern definition for mntctl() exist? */
+/* #undef HAVE_EXTERN_MNTCTL */
 
-/* Mount-table entry name for LOFS filesystem */
-#define MNTTAB_TYPE_LOFS "lofs"
+/* does extern definition for optarg exist? */
+#define HAVE_EXTERN_OPTARG 1
 
-/* Mount-table entry name for CDFS filesystem */
-#define MNTTAB_TYPE_CDFS "cd9660"
+/* does extern definition for sbrk() exist? */
+#define HAVE_EXTERN_SBRK 1
 
-/* Mount-table entry name for TFS filesystem */
-/* #undef MNTTAB_TYPE_TFS */
+/* does extern definition for seteuid() exist? */
+#define HAVE_EXTERN_SETEUID 1
 
-/* Mount-table entry name for TMPFS filesystem */
-/* #undef MNTTAB_TYPE_TMPFS */
+/* does extern definition for setitimer() exist? */
+#define HAVE_EXTERN_SETITIMER 1
 
-/* Mount-table entry name for MFS filesystem */
-#define MNTTAB_TYPE_MFS "mfs"
+/* does extern definition for sleep() exist? */
+#define HAVE_EXTERN_SLEEP 1
 
-/* Mount-table entry name for CFS (crypto) filesystem */
-/* #undef MNTTAB_TYPE_CFS */
+/* does extern definition for strcasecmp() exist? */
+#define HAVE_EXTERN_STRCASECMP 1
 
-/* Mount-table entry name for AUTOFS filesystem */
-/* #undef MNTTAB_TYPE_AUTOFS */
+/* does extern definition for strdup() exist? */
+#define HAVE_EXTERN_STRDUP 1
 
-/* Mount-table entry name for CACHEFS filesystem */
-/* #undef MNTTAB_TYPE_CACHEFS */
+/* does extern definition for strlcat() exist? */
+#define HAVE_EXTERN_STRLCAT 1
 
-/* Mount-table entry name for NULLFS (loopback on bsd44) filesystem */
-#define MNTTAB_TYPE_NULLFS "null"
+/* does extern definition for strlcpy() exist? */
+#define HAVE_EXTERN_STRLCPY 1
 
-/* Mount-table entry name for UNIONFS filesystem */
-#define MNTTAB_TYPE_UNIONFS "union"
+/* does extern definition for strstr() exist? */
+#define HAVE_EXTERN_STRSTR 1
 
-/*
- * Name of mount table file name.
- */
-/* #undef MNTTAB_FILE_NAME */
+/* does extern definition for sys_errlist[] exist? */
+#define HAVE_EXTERN_SYS_ERRLIST 1
 
-/* Name of mount type to hide amd mount from df(1) */
-#define HIDE_MOUNT_TYPE "nfs"
+/* does extern definition for ualarm() exist? */
+#define HAVE_EXTERN_UALARM 1
 
-/*
- * Names of various mount table option strings.
- */
+/* does extern definition for usleep() exist? */
+#define HAVE_EXTERN_USLEEP 1
 
-/* Mount Table option string: Read only */
-/* #undef MNTTAB_OPT_RO */
+/* does extern definition for vsnprintf() exist? */
+#define HAVE_EXTERN_VSNPRINTF 1
 
-/* Mount Table option string: Read/write */
-/* #undef MNTTAB_OPT_RW */
+/* does extern definition for wait3() exist? */
+#define HAVE_EXTERN_WAIT3 1
 
-/* Mount Table option string: Read/write with quotas */
-/* #undef MNTTAB_OPT_RQ */
+/* does extern definition for xdr_callmsg() exist? */
+#define HAVE_EXTERN_XDR_CALLMSG 1
 
-/* Mount Table option string: Check quotas */
-/* #undef MNTTAB_OPT_QUOTA */
+/* does extern definition for xdr_opaque_auth() exist? */
+#define HAVE_EXTERN_XDR_OPAQUE_AUTH 1
 
-/* Mount Table option string: Don't check quotas */
-/* #undef MNTTAB_OPT_NOQUOTA */
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
 
-/* Mount Table option string: action to taken on error */
-/* #undef MNTTAB_OPT_ONERROR */
+/* Define to 1 if `fds_bits' is member of `fd_set'. */
+#define HAVE_FD_SET_FDS_BITS 1
 
-/* Mount Table option string: min. time between inconsistencies */
-/* #undef MNTTAB_OPT_TOOSOON */
+/* Define to 1 if you have the `fgets' function. */
+#define HAVE_FGETS 1
 
-/* Mount Table option string: Soft mount */
-/* #undef MNTTAB_OPT_SOFT */
+/* Define if plain fhandle type exists */
+#define HAVE_FHANDLE 1
 
-/* Mount Table option string: spongy mount */
-/* #undef MNTTAB_OPT_SPONGY */
+/* Define to 1 if you have the `flock' function. */
+#define HAVE_FLOCK 1
 
-/* Mount Table option string: Hard mount */
-/* #undef MNTTAB_OPT_HARD */
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
 
-/* Mount Table option string: Set uid allowed */
-/* #undef MNTTAB_OPT_SUID */
+/* Define to 1 if you have the `fsmount' function. */
+/* #undef HAVE_FSMOUNT */
 
-/* Mount Table option string: Set uid not allowed */
-/* #undef MNTTAB_OPT_NOSUID */
+/* Define if have AUTOFS filesystem */
+/* #undef HAVE_FS_AUTOFS */
 
-/* Mount Table option string: SysV-compatible gid on create */
-/* #undef MNTTAB_OPT_GRPID */
+/* Define if have CACHEFS filesystem */
+/* #undef HAVE_FS_CACHEFS */
 
-/* Mount Table option string: Change mount options */
-/* #undef MNTTAB_OPT_REMOUNT */
+/* Define if have CDFS filesystem */
+#define HAVE_FS_CDFS 1
 
-/* Mount Table option string: Disallow mounts on subdirs */
-/* #undef MNTTAB_OPT_NOSUB */
+/* Define if have CFS (crypto) filesystem */
+/* #undef HAVE_FS_CFS */
 
-/* Mount Table option string: Do multi-component lookup */
-/* #undef MNTTAB_OPT_MULTI */
+/* Define if have EFS filesystem (irix) */
+/* #undef HAVE_FS_EFS */
 
-/* Mount Table option string: Allow NFS ops to be interrupted */
-/* #undef MNTTAB_OPT_INTR */
+/* Define if have FFS filesystem */
+/* #undef HAVE_FS_FFS */
 
-/* Mount Table option string: Don't allow interrupted ops */
-/* #undef MNTTAB_OPT_NOINTR */
+/* Define if have HSFS filesystem */
+/* #undef HAVE_FS_HSFS */
 
-/* Mount Table option string: NFS server IP port number */
-/* #undef MNTTAB_OPT_PORT */
+/* Define if have LOFS filesystem */
+/* #undef HAVE_FS_LOFS */
 
-/* Mount Table option string: Secure (AUTH_DES) mounting */
-/* #undef MNTTAB_OPT_SECURE */
+/* Define if have MFS filesystem */
+/* #undef HAVE_FS_MFS */
 
-/* Mount Table option string: Secure (AUTH_Kerb) mounting */
-/* #undef MNTTAB_OPT_KERB */
+/* Define if have NFS filesystem */
+#define HAVE_FS_NFS 1
 
-/* Mount Table option string: Max NFS read size (bytes) */
-/* #undef MNTTAB_OPT_RSIZE */
+/* Define if have NFS3 filesystem */
+#define HAVE_FS_NFS3 1
 
-/* Mount Table option string: Max NFS write size (bytes) */
-/* #undef MNTTAB_OPT_WSIZE */
+/* Define if have NULLFS (loopback on bsd44) filesystem */
+#define HAVE_FS_NULLFS 1
 
-/* Mount Table option string: NFS timeout (1/10 sec) */
-/* #undef MNTTAB_OPT_TIMEO */
+/* Define if have PCFS filesystem */
+#define HAVE_FS_PCFS 1
 
-/* Mount Table option string: Max retransmissions (soft mnts) */
-/* #undef MNTTAB_OPT_RETRANS */
+/* Define if have TFS filesystem */
+/* #undef HAVE_FS_TFS */
 
-/* Mount Table option string: Attr cache timeout (sec) */
-/* #undef MNTTAB_OPT_ACTIMEO */
+/* Define if have TMPFS filesystem */
+/* #undef HAVE_FS_TMPFS */
 
-/* Mount Table option string: Min attr cache timeout (files) */
-/* #undef MNTTAB_OPT_ACREGMIN */
+/* Define if have UFS filesystem */
+#define HAVE_FS_UFS 1
 
-/* Mount Table option string: Max attr cache timeout (files) */
-/* #undef MNTTAB_OPT_ACREGMAX */
+/* Define if have UMAPFS (uid/gid mapping) filesystem */
+/* #undef HAVE_FS_UMAPFS */
 
-/* Mount Table option string: Min attr cache timeout (dirs) */
-/* #undef MNTTAB_OPT_ACDIRMIN */
+/* Define if have UNIONFS filesystem */
+#define HAVE_FS_UNIONFS 1
 
-/* Mount Table option string: Max attr cache timeout (dirs) */
-/* #undef MNTTAB_OPT_ACDIRMAX */
+/* Define if have XFS filesystem (irix) */
+/* #undef HAVE_FS_XFS */
 
-/* Mount Table option string: Don't cache attributes at all */
-/* #undef MNTTAB_OPT_NOAC */
+/* System supports GCC-style variable-length argument macros */
+/* #undef HAVE_GCC_VARARGS_MACROS */
 
-/* Mount Table option string: No close-to-open consistency */
-/* #undef MNTTAB_OPT_NOCTO */
+/* Define to 1 if you have the <gdbm-ndbm.h> header file. */
+/* #undef HAVE_GDBM_NDBM_H */
 
-/* Mount Table option string: Do mount retries in background */
-/* #undef MNTTAB_OPT_BG */
+/* Define to 1 if you have the `getccent' function. */
+/* #undef HAVE_GETCCENT */
 
-/* Mount Table option string: Do mount retries in foreground */
-/* #undef MNTTAB_OPT_FG */
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
 
-/* Mount Table option string: Number of mount retries */
-/* #undef MNTTAB_OPT_RETRY */
+/* Define to 1 if you have the `getdomainname' function. */
+#define HAVE_GETDOMAINNAME 1
 
-/* Mount Table option string: Device id of mounted fs */
-/* #undef MNTTAB_OPT_DEV */
+/* Define to 1 if you have the `getdtablesize' function. */
+#define HAVE_GETDTABLESIZE 1
 
-/* Mount Table option string: Filesystem id of mounted fs */
-/* #undef MNTTAB_OPT_FSID */
+/* Define to 1 if you have the `gethostname' function. */
+#define HAVE_GETHOSTNAME 1
 
-/* Mount Table option string: Get static pathconf for mount */
-/* #undef MNTTAB_OPT_POSIX */
+/* Define to 1 if you have the `getifaddrs' function. */
+#define HAVE_GETIFADDRS 1
 
-/* Mount Table option string: Automount map */
-/* #undef MNTTAB_OPT_MAP */
+/* Define to 1 if you have the `getmntinfo' function. */
+#define HAVE_GETMNTINFO 1
 
-/* Mount Table option string: Automount   direct map mount */
-/* #undef MNTTAB_OPT_DIRECT */
+/* Define to 1 if you have the `getmountent' function. */
+/* #undef HAVE_GETMOUNTENT */
 
-/* Mount Table option string: Automount indirect map mount */
-/* #undef MNTTAB_OPT_INDIRECT */
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
 
-/* Mount Table option string: Local locking (no lock manager) */
-/* #undef MNTTAB_OPT_LLOCK */
+/* Define to 1 if you have the `getpwnam' function. */
+#define HAVE_GETPWNAM 1
 
-/* Mount Table option string: Ignore this entry */
-/* #undef MNTTAB_OPT_IGNORE */
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
 
-/* Mount Table option string: No auto (what?) */
-/* #undef MNTTAB_OPT_NOAUTO */
+/* Define to 1 if you have the `get_myaddress' function. */
+#define HAVE_GET_MYADDRESS 1
 
-/* Mount Table option string: No connection */
-/* #undef MNTTAB_OPT_NOCONN */
+/* define if your system's getopt() is GNU getopt() (are you using glibc) */
+/* #undef HAVE_GNU_GETOPT */
 
-/* Mount Table option string: protocol version number indicator */
-/* #undef MNTTAB_OPT_VERS */
+/* Define to 1 if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
 
-/* Mount Table option string: protocol network_id indicator */
-/* #undef MNTTAB_OPT_PROTO */
+/* Define to 1 if you have the `hasmntopt' function. */
+/* #undef HAVE_HASMNTOPT */
 
-/* Mount Table option string: Synchronous local directory ops */
-/* #undef MNTTAB_OPT_SYNCDIR */
+#ifdef YES_HESIOD
+/* Define to 1 if you have the <hesiod.h> header file. */
+#define HAVE_HESIOD_H 1
 
-/* Mount Table option string: Do no allow setting sec attrs */
-/* #undef MNTTAB_OPT_NOSETSEC */
+/* Define to 1 if you have the `hesiod_init' function. */
+#define HAVE_HESIOD_INIT 1
 
-/* Mount Table option string: set symlink cache time-to-live */
-/* #undef MNTTAB_OPT_SYMTTL */
+/* Define to 1 if you have the `hesiod_reload' function. */
+/* #undef HAVE_HESIOD_RELOAD */
 
-/* Mount Table option string: compress */
-/* #undef MNTTAB_OPT_COMPRESS */
+/* Define to 1 if you have the `hesiod_to_bind' function. */
+#define HAVE_HESIOD_TO_BIND 1
+
+/* Define to 1 if you have the `hes_init' function. */
+#define HAVE_HES_INIT 1
+#else
+#undef HAVE_HESIOD_H
+#undef HAVE_HESIOD_INIT
+#undef HAVE_HESIOD_RELOAD
+#undef HAVE_HESIOD_TO_BIND
+#undef HAVE_HES_INIT
+#endif
 
-/* Mount Table option string: paging threshold */
-/* #undef MNTTAB_OPT_PGTHRESH */
+/* Define to 1 if you have the <hsfs/hsfs.h> header file. */
+/* #undef HAVE_HSFS_HSFS_H */
 
-/* Mount Table option string: max groups */
-/* #undef MNTTAB_OPT_MAXGROUPS */
+/* Define to 1 if you have the `hstrerror' function. */
+#define HAVE_HSTRERROR 1
 
-/*
- * Generic mount(2) options (hex numbers)
- */
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#define HAVE_IFADDRS_H 1
 
-/* asynchronous filesystem access */
-#define MNT2_GEN_OPT_ASYNC 0x40
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
 
-/* automounter filesystem (ignore) flag, used in bsdi-4.1 */
-/* #undef MNT2_GEN_OPT_AUTOMNTFS */
+/* Define to 1 if you have the <irs.h> header file. */
+/* #undef HAVE_IRS_H */
 
-/* cache (what?) */
-/* #undef MNT2_GEN_OPT_CACHE */
+/* Define to 1 if you have the <isofs/cd9660/cd9660_mount.h> header file. */
+#define HAVE_ISOFS_CD9660_CD9660_MOUNT_H 1
 
-/* 6-argument mount */
-/* #undef MNT2_GEN_OPT_DATA */
+/* Define to 1 if you have the <lber.h> header file. */
+/* #undef HAVE_LBER_H */
 
-/* old (4-argument) mount (compatibility) */
-/* #undef MNT2_GEN_OPT_FSS */
+/* Define to 1 if you have the `ldap_enable_cache' function. */
+/* #undef HAVE_LDAP_ENABLE_CACHE */
 
-/* ignore mount entry in df output */
-/* #undef MNT2_GEN_OPT_IGNORE */
+/* Define to 1 if you have the <ldap.h> header file. */
+/* #undef HAVE_LDAP_H */
 
-/* journaling filesystem (AIX's UFS/FFS) */
-/* #undef MNT2_GEN_OPT_JFS */
+/* Define to 1 if you have the `ldap_open' function. */
+/* #undef HAVE_LDAP_OPEN */
 
-/* old BSD group-id on create */
-/* #undef MNT2_GEN_OPT_GRPID */
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
 
-/* do multi-component lookup on files */
-/* #undef MNT2_GEN_OPT_MULTI */
+/* Define to 1 if you have the `malloc' library (-lmalloc). */
+/* #undef HAVE_LIBMALLOC */
 
-/* use type string instead of int */
-/* #undef MNT2_GEN_OPT_NEWTYPE */
+/* Define to 1 if you have the `mapmalloc' library (-lmapmalloc). */
+/* #undef HAVE_LIBMAPMALLOC */
 
-/* NFS mount */
-/* #undef MNT2_GEN_OPT_NFS */
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
 
-/* nocache (what?) */
-/* #undef MNT2_GEN_OPT_NOCACHE */
+/* Define to 1 if you have the `posix4' library (-lposix4). */
+/* #undef HAVE_LIBPOSIX4 */
 
-/* not a device */
-#define MNT2_GEN_OPT_NODEV 0x10
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+/* #undef HAVE_LIBRESOLV */
 
-/* no exec calls allowed */
-#define MNT2_GEN_OPT_NOEXEC 0x4
+/* Define to 1 if you have the `rpc' library (-lrpc). */
+/* #undef HAVE_LIBRPC */
 
-/* not a device  */
-/* #undef MNT2_GEN_OPT_NONDEV */
+/* Define to 1 if you have the `rpcsvc' library (-lrpcsvc). */
+#define HAVE_LIBRPCSVC 1
 
-/* Disallow mounts beneath this mount */
-/* #undef MNT2_GEN_OPT_NOSUB */
+/* Define to 1 if you have the `rt' library (-lrt). */
+/* #undef HAVE_LIBRT */
 
-/* Setuid programs disallowed */
-#define MNT2_GEN_OPT_NOSUID 0x8
+/* does libwrap exist? */
+#define HAVE_LIBWRAP 1
 
-/* Return ENAMETOOLONG for long filenames */
-/* #undef MNT2_GEN_OPT_NOTRUNC */
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
 
-/* allow overlay mounts */
-/* #undef MNT2_GEN_OPT_OVERLAY */
+/* Define to 1 if you have the <linux/auto_fs4.h> header file. */
+/* #undef HAVE_LINUX_AUTO_FS4_H */
 
-/* check quotas */
-#define MNT2_GEN_OPT_QUOTA 0x2000
+/* Define to 1 if you have the <linux/auto_fs.h> header file. */
+/* #undef HAVE_LINUX_AUTO_FS_H */
 
-/* Read-only */
-#define MNT2_GEN_OPT_RDONLY 0x1
+/* Define to 1 if you have the <linux/fs.h> header file. */
+/* #undef HAVE_LINUX_FS_H */
 
-/* change options on an existing mount */
-/* #undef MNT2_GEN_OPT_REMOUNT */
+/* Define to 1 if you have the <linux/kdev_t.h> header file. */
+/* #undef HAVE_LINUX_KDEV_T_H */
 
-/* read only */
-/* #undef MNT2_GEN_OPT_RONLY */
+/* Define to 1 if you have the <linux/list.h> header file. */
+/* #undef HAVE_LINUX_LIST_H */
 
-/* synchronize data immediately to filesystem */
-/* #undef MNT2_GEN_OPT_SYNC */
+/* Define to 1 if you have the <linux/loop.h> header file. */
+/* #undef HAVE_LINUX_LOOP_H */
 
-/* synchronous filesystem access (same as SYNC) */
-#define MNT2_GEN_OPT_SYNCHRONOUS 0x2
+/* Define to 1 if you have the <linux/nfs2.h> header file. */
+/* #undef HAVE_LINUX_NFS2_H */
 
-/* Mount with Sys 5-specific semantics */
-/* #undef MNT2_GEN_OPT_SYS5 */
+/* Define to 1 if you have the <linux/nfs.h> header file. */
+/* #undef HAVE_LINUX_NFS_H */
 
-/* Union mount */
-/* #undef MNT2_GEN_OPT_UNION */
+/* Define to 1 if you have the <linux/nfs_mount.h> header file. */
+/* #undef HAVE_LINUX_NFS_MOUNT_H */
 
-/*
- * NFS-specific mount(2) options (hex numbers)
- */
+/* Define to 1 if you have the <linux/posix_types.h> header file. */
+/* #undef HAVE_LINUX_POSIX_TYPES_H */
 
-/* hide mount type from df(1) */
-/* #undef MNT2_NFS_OPT_AUTO */
+/* Define to 1 if you have the <linux/socket.h> header file. */
+/* #undef HAVE_LINUX_SOCKET_H */
 
-/* set max secs for dir attr cache */
-#define MNT2_NFS_OPT_ACDIRMAX 0x200000
+/* Define to 1 if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
 
-/* set min secs for dir attr cache */
-#define MNT2_NFS_OPT_ACDIRMIN 0x100000
+/* Define to 1 if you have the <machine/endian.h> header file. */
+#define HAVE_MACHINE_ENDIAN_H 1
 
-/* set max secs for file attr cache */
-#define MNT2_NFS_OPT_ACREGMAX 0x80000
+/* Define to 1 if you have the `madvise' function. */
+#define HAVE_MADVISE 1
 
-/* set min secs for file attr cache */
-#define MNT2_NFS_OPT_ACREGMIN 0x40000
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
 
-/* Authentication error */
-/* #undef MNT2_NFS_OPT_AUTHERR */
+/* Define if have DBM maps */
+/* #undef HAVE_MAP_DBM */
 
-/* set dead server retry thresh */
-#define MNT2_NFS_OPT_DEADTHRESH 0x4000
+/* Define if have executable maps */
+#define HAVE_MAP_EXEC 1
 
-/* Dismount in progress */
-/* #undef MNT2_NFS_OPT_DISMINPROG */
+/* Define if have file maps (everyone should have it!) */
+#define HAVE_MAP_FILE 1
 
-/* Dismounted */
-/* #undef MNT2_NFS_OPT_DISMNT */
+#ifdef YES_HESIOD
+/* Define if have HESIOD maps */
+#define HAVE_MAP_HESIOD 1
+#else
+#undef HAVE_MAP_HESIOD
+#endif
 
-/* Don't estimate rtt dynamically */
-#define MNT2_NFS_OPT_DUMBTIMR 0x800
+/* Define if have LDAP maps */
+/* #undef HAVE_MAP_LDAP */
 
-/* System V-style gid inheritance */
-/* #undef MNT2_NFS_OPT_GRPID */
+/* Define if have NDBM maps */
+#define HAVE_MAP_NDBM 1
 
-/* Has authenticator */
-/* #undef MNT2_NFS_OPT_HASAUTH */
+/* Define if have NIS maps */
+#define HAVE_MAP_NIS 1
 
-/* provide name of server's fs to system */
-/* #undef MNT2_NFS_OPT_FSNAME */
+/* Define if have NIS+ maps */
+/* #undef HAVE_MAP_NISPLUS */
 
-/* set hostname for error printf */
-/* #undef MNT2_NFS_OPT_HOSTNAME */
+/* Define if have PASSWD maps */
+#define HAVE_MAP_PASSWD 1
 
-/* ignore mount point */
-/* #undef MNT2_NFS_OPT_IGNORE */
+/* Define if have UNION maps */
+#define HAVE_MAP_UNION 1
 
-/* allow interrupts on hard mount */
-#define MNT2_NFS_OPT_INT 0x40
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
 
-/* Bits set internally */
-/* #undef MNT2_NFS_OPT_INTERNAL */
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
 
-/* Use Kerberos authentication */
-/* #undef MNT2_NFS_OPT_KERB */
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
 
-/* use kerberos credentials */
-/* #undef MNT2_NFS_OPT_KERBEROS */
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
 
-/* transport's knetconfig structure */
-/* #undef MNT2_NFS_OPT_KNCONF */
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
 
-/* set lease term (nqnfs) */
-#define MNT2_NFS_OPT_LEASETERM 0x1000
+/* Define to 1 if you have the `mkdir' function. */
+#define HAVE_MKDIR 1
 
-/* Local locking (no lock manager) */
-/* #undef MNT2_NFS_OPT_LLOCK */
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
 
-/* set maximum grouplist size */
-#define MNT2_NFS_OPT_MAXGRPS 0x20
+/* Define to 1 if you have the `mlockall' function. */
+#define HAVE_MLOCKALL 1
 
-/* Mnt server for mnt point */
-/* #undef MNT2_NFS_OPT_MNTD */
+/* Define to 1 if you have the `mntctl' function. */
+/* #undef HAVE_MNTCTL */
 
-/* Assume writes were mine */
-/* #undef MNT2_NFS_OPT_MYWRITE */
+/* Define to 1 if you have the <mntent.h> header file. */
+/* #undef HAVE_MNTENT_H */
 
-/* mount NFS Version 3 */
-#define MNT2_NFS_OPT_NFSV3 0x200
+/* Define to 1 if `mnt_cnode' is member of `mntent_t'. */
+/* #undef HAVE_MNTENT_T_MNT_CNODE */
 
-/* don't cache attributes */
-/* #undef MNT2_NFS_OPT_NOAC */
+/* Define to 1 if `mnt_ro' is member of `mntent_t'. */
+/* #undef HAVE_MNTENT_T_MNT_RO */
 
-/* Don't Connect the socket */
-#define MNT2_NFS_OPT_NOCONN 0x80
+/* Define to 1 if `mnt_time' is member of `mntent_t'. */
+/* #undef HAVE_MNTENT_T_MNT_TIME */
 
-/* no close-to-open consistency */
-/* #undef MNT2_NFS_OPT_NOCTO */
+/* does mntent_t have mnt_time field and is of type "char *" ? */
+/* #undef HAVE_MNTENT_T_MNT_TIME_STRING */
 
-/* disallow interrupts on hard mounts */
-/* #undef MNT2_NFS_OPT_NOINT */
+/* Define to 1 if you have the <mnttab.h> header file. */
+/* #undef HAVE_MNTTAB_H */
 
-/* Get lease for lookup */
-/* #undef MNT2_NFS_OPT_NQLOOKLEASE */
+/* Define to 1 if you have the `mount' function. */
+#define HAVE_MOUNT 1
 
-/* Use Nqnfs protocol */
-#define MNT2_NFS_OPT_NQNFS 0x100
+/* Define to 1 if `optptr' is member of `mounta'. */
+/* #undef HAVE_MOUNTA_OPTPTR */
 
-/* static pathconf kludge info */
-/* #undef MNT2_NFS_OPT_POSIX */
+/* Define to 1 if you have the `mountsyscall' function. */
+/* #undef HAVE_MOUNTSYSCALL */
 
-/* Rcv socket lock */
-/* #undef MNT2_NFS_OPT_RCVLOCK */
+/* Define to 1 if you have the <mount.h> header file. */
+/* #undef HAVE_MOUNT_H */
 
-/* Do lookup with readdir (nqnfs) */
-/* #undef MNT2_NFS_OPT_RDIRALOOK */
+/* Define to 1 if you have the <msdosfs/msdosfsmount.h> header file. */
+/* #undef HAVE_MSDOSFS_MSDOSFSMOUNT_H */
 
-/* set read ahead */
-#define MNT2_NFS_OPT_READAHEAD 0x2000
+/* Define to 1 if you have the <fs/msdosfs/msdosfsmount.h> header file. */
+#define HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H 1
 
-/* Allocate a reserved port */
-#define MNT2_NFS_OPT_RESVPORT 0x8000
+/* Define to 1 if you have the <ndbm.h> header file. */
+#define HAVE_NDBM_H 1
 
-/* set number of request retries */
-#define MNT2_NFS_OPT_RETRANS 0x10
+/* Define to 1 if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
 
-/* read only */
-/* #undef MNT2_NFS_OPT_RONLY */
+/* Define to 1 if you have the <netconfig.h> header file. */
+#define HAVE_NETCONFIG_H 1
 
-/* use RPC to do secure NFS time sync */
-/* #undef MNT2_NFS_OPT_RPCTIMESYNC */
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
 
-/* set read size */
-#define MNT2_NFS_OPT_RSIZE 0x4
+/* Define to 1 if you have the <netdir.h> header file. */
+/* #undef HAVE_NETDIR_H */
 
-/* secure mount */
-/* #undef MNT2_NFS_OPT_SECURE */
+/* Define to 1 if you have the <netinet/if_ether.h> header file. */
+#define HAVE_NETINET_IF_ETHER_H 1
 
-/* Send socket lock */
-/* #undef MNT2_NFS_OPT_SNDLOCK */
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <net/errno.h> header file. */
+/* #undef HAVE_NET_ERRNO_H */
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if you have the <net/if_var.h> header file. */
+#define HAVE_NET_IF_VAR_H 1
+
+/* Define to 1 if you have the <net/route.h> header file. */
+#define HAVE_NET_ROUTE_H 1
+
+/* Define to 1 if you have the <nfsclient/nfsargs.h> header file. */
+/* #undef HAVE_NFSCLIENT_NFSARGS_H */
+
+/* Define to 1 if `acdirmax' is member of `nfs_args_t'. */
+#define HAVE_NFS_ARGS_T_ACDIRMAX 1
+
+/* Define to 1 if `acdirmin' is member of `nfs_args_t'. */
+#define HAVE_NFS_ARGS_T_ACDIRMIN 1
+
+/* Define to 1 if `acregmax' is member of `nfs_args_t'. */
+#define HAVE_NFS_ARGS_T_ACREGMAX 1
+
+/* Define to 1 if `acregmin' is member of `nfs_args_t'. */
+#define HAVE_NFS_ARGS_T_ACREGMIN 1
+
+/* Define to 1 if `addrlen' is member of `nfs_args_t'. */
+#define HAVE_NFS_ARGS_T_ADDRLEN 1
+
+/* Define to 1 if `bsize' is member of `nfs_args_t'. */
+/* #undef HAVE_NFS_ARGS_T_BSIZE */
+
+/* Define to 1 if `fhsize' is member of `nfs_args_t'. */
+#define HAVE_NFS_ARGS_T_FHSIZE 1
+
+/* Define to 1 if `fh_len' is member of `nfs_args_t'. */
+/* #undef HAVE_NFS_ARGS_T_FH_LEN */
+
+/* Define to 1 if `gfs_flags' is member of `nfs_args_t'. */
+/* #undef HAVE_NFS_ARGS_T_GFS_FLAGS */
+
+/* Define to 1 if `namlen' is member of `nfs_args_t'. */
+/* #undef HAVE_NFS_ARGS_T_NAMLEN */
+
+/* Define to 1 if `optstr' is member of `nfs_args_t'. */
+/* #undef HAVE_NFS_ARGS_T_OPTSTR */
+
+/* Define to 1 if `proto' is member of `nfs_args_t'. */
+#define HAVE_NFS_ARGS_T_PROTO 1
+
+/* Define to 1 if `sotype' is member of `nfs_args_t'. */
+#define HAVE_NFS_ARGS_T_SOTYPE 1
+
+/* Define to 1 if `version' is member of `nfs_args_t'. */
+#define HAVE_NFS_ARGS_T_VERSION 1
+
+/* Define to 1 if you have the <nfs/export.h> header file. */
+/* #undef HAVE_NFS_EXPORT_H */
+
+/* Define to 1 if you have the <nfs/mount.h> header file. */
+/* #undef HAVE_NFS_MOUNT_H */
+
+/* Define to 1 if you have the <nfs/nfsmount.h> header file. */
+/* #undef HAVE_NFS_NFSMOUNT_H */
+
+/* Define to 1 if you have the <nfs/nfsproto.h> header file. */
+#define HAVE_NFS_NFSPROTO_H 1
+
+/* Define to 1 if you have the <nfs/nfsv2.h> header file. */
+/* #undef HAVE_NFS_NFSV2_H */
+
+/* Define to 1 if you have the <nfs/nfs_clnt.h> header file. */
+/* #undef HAVE_NFS_NFS_CLNT_H */
+
+/* Define to 1 if you have the <nfs/nfs_gfs.h> header file. */
+/* #undef HAVE_NFS_NFS_GFS_H */
+
+/* Define to 1 if you have the <nfs/nfs.h> header file. */
+#define HAVE_NFS_NFS_H 1
+
+/* Define to 1 if you have the <nfs/nfs_mount.h> header file. */
+/* #undef HAVE_NFS_NFS_MOUNT_H */
+
+/* Define to 1 if you have the <nfs/pathconf.h> header file. */
+/* #undef HAVE_NFS_PATHCONF_H */
+
+/* define if the host has NFS protocol headers in system headers */
+/* #undef HAVE_NFS_PROT_HEADERS */
+
+/* Define to 1 if you have the <nfs/rpcv2.h> header file. */
+#define HAVE_NFS_RPCV2_H 1
+
+/* Define to 1 if you have the `nis_domain_of' function. */
+/* #undef HAVE_NIS_DOMAIN_OF */
+
+/* Define to 1 if you have the <nsswitch.h> header file. */
+#define HAVE_NSSWITCH_H 1
+
+/* Define to 1 if you have the `opendir' function. */
+#define HAVE_OPENDIR 1
+/* Define to 1 if `dsttime' is member of `pcfs_args_t'. */
+/* #undef HAVE_PCFS_ARGS_T_DSTTIME */
+
+/* Define to 1 if `fspec' is member of `pcfs_args_t'. */
+#define HAVE_PCFS_ARGS_T_FSPEC 1
+
+/* Define to 1 if `gid' is member of `pcfs_args_t'. */
+#define HAVE_PCFS_ARGS_T_GID 1
+
+/* Define to 1 if `mask' is member of `pcfs_args_t'. */
+#define HAVE_PCFS_ARGS_T_MASK 1
+
+/* Define to 1 if `dirmask' is member of `pcfs_args_t'. */
+/* #undef HAVE_PCFS_ARGS_T_DIRMASK */
+
+/* Define to 1 if `secondswest' is member of `pcfs_args_t'. */
+/* #undef HAVE_PCFS_ARGS_T_SECONDSWEST */
+
+/* Define to 1 if `uid' is member of `pcfs_args_t'. */
+#define HAVE_PCFS_ARGS_T_UID 1
+
+/* Define to 1 if you have the `plock' function. */
+/* #undef HAVE_PLOCK */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `regcomp' function. */
+#define HAVE_REGCOMP 1
+
+/* Define to 1 if you have the `regexec' function. */
+#define HAVE_REGEXEC 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define to 1 if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define to 1 if system calls automatically restart after interruption by a
+   signal. */
+#define HAVE_RESTARTABLE_SYSCALLS 1
+
+/* Define to 1 if you have the `rmdir' function. */
+#define HAVE_RMDIR 1
+
+/* Define to 1 if you have the <rpcsvc/autofs_prot.h> header file. */
+/* #undef HAVE_RPCSVC_AUTOFS_PROT_H */
+
+/* Define to 1 if you have the <rpcsvc/mountv3.h> header file. */
+/* #undef HAVE_RPCSVC_MOUNTV3_H */
+
+/* Define to 1 if you have the <rpcsvc/mount.h> header file. */
+#define HAVE_RPCSVC_MOUNT_H 1
+
+/* Define to 1 if you have the <rpcsvc/nfs_prot.h> header file. */
+#define HAVE_RPCSVC_NFS_PROT_H 1
+
+/* Define to 1 if you have the <rpcsvc/nis.h> header file. */
+#define HAVE_RPCSVC_NIS_H 1
+
+/* Define to 1 if you have the <rpcsvc/ypclnt.h> header file. */
+#define HAVE_RPCSVC_YPCLNT_H 1
+
+/* Define to 1 if you have the <rpcsvc/yp_prot.h> header file. */
+#define HAVE_RPCSVC_YP_PROT_H 1
+
+/* Define to 1 if you have the <rpc/auth_des.h> header file. */
+#define HAVE_RPC_AUTH_DES_H 1
+
+/* Define to 1 if you have the <rpc/pmap_clnt.h> header file. */
+#define HAVE_RPC_PMAP_CLNT_H 1
 
-/* soft mount (hard is default) */
-#define MNT2_NFS_OPT_SOFT 0x1
+/* Define to 1 if you have the <rpc/pmap_prot.h> header file. */
+#define HAVE_RPC_PMAP_PROT_H 1
 
-/* spongy mount */
-/* #undef MNT2_NFS_OPT_SPONGY */
+/* Define to 1 if you have the <rpc/rpc.h> header file. */
+#define HAVE_RPC_RPC_H 1
 
-/* set initial timeout */
-#define MNT2_NFS_OPT_TIMEO 0x8
+/* Define to 1 if you have the <rpc/types.h> header file. */
+#define HAVE_RPC_TYPES_H 1
 
-/* use TCP for mounts */
-/* #undef MNT2_NFS_OPT_TCP */
+/* Define to 1 if you have the <rpc/xdr.h> header file. */
+#define HAVE_RPC_XDR_H 1
 
-/* Wait for authentication */
-/* #undef MNT2_NFS_OPT_WAITAUTH */
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
 
-/* Wants an authenticator */
-/* #undef MNT2_NFS_OPT_WANTAUTH */
+/* Define to 1 if you have the `seteuid' function. */
+#define HAVE_SETEUID 1
 
-/* Want receive socket lock */
-/* #undef MNT2_NFS_OPT_WANTRCV */
+/* Define to 1 if you have the `setitimer' function. */
+#define HAVE_SETITIMER 1
 
-/* Want send socket lock */
-/* #undef MNT2_NFS_OPT_WANTSND */
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
 
-/* set write size */
-#define MNT2_NFS_OPT_WSIZE 0x2
+/* Define to 1 if you have the `setresuid' function. */
+#define HAVE_SETRESUID 1
 
-/* set symlink cache time-to-live */
-/* #undef MNT2_NFS_OPT_SYMTTL */
+/* Define to 1 if you have the `setsid' function. */
+#define HAVE_SETSID 1
 
-/* paging threshold */
-/* #undef MNT2_NFS_OPT_PGTHRESH */
+/* Define to 1 if you have the `sigaction' function. */
+#define HAVE_SIGACTION 1
 
-/*
- * CDFS-specific mount(2) options (hex numbers)
- */
+/* Define to 1 if you have the `signal' function. */
+#define HAVE_SIGNAL 1
 
-/* Ignore permission bits */
-/* #undef MNT2_CDFS_OPT_DEFPERM */
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
 
-/* Use on-disk permission bits */
-/* #undef MNT2_CDFS_OPT_NODEFPERM */
+/* Define to 1 if you have the `sigsuspend' function. */
+#define HAVE_SIGSUSPEND 1
 
-/* Strip off extension from version string */
-/* #undef MNT2_CDFS_OPT_NOVERSION */
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
 
-/* Use Rock Ridge Interchange Protocol (RRIP) extensions */
-/* #undef MNT2_CDFS_OPT_RRIP */
+/* Define to 1 if you have the <socketbits.h> header file. */
+/* #undef HAVE_SOCKETBITS_H */
 
-/*
- * Existence of fields in structures.
- */
+/* Define to 1 if you have the <statbuf.h> header file. */
+/* #undef HAVE_STATBUF_H */
 
-/* does mntent_t have mnt_cnode field? */
-/* #undef HAVE_FIELD_MNTENT_T_MNT_CNODE */
+/* Define to 1 if you have the `statfs' function. */
+#define HAVE_STATFS 1
 
-/* does mntent_t have mnt_time field? */
-/* #undef HAVE_FIELD_MNTENT_T_MNT_TIME */
+/* Define to 1 if you have the `statvfs' function. */
+#define HAVE_STATVFS 1
 
-/* does mntent_t have mnt_time field and is of type "char *" ? */
-/* #undef HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
 
-/* does mntent_t have mnt_ro field? */
-/* #undef HAVE_FIELD_MNTENT_T_MNT_RO */
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
 
-/* does cdfs_args_t have flags field? */
-#define HAVE_FIELD_CDFS_ARGS_T_FLAGS 1
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
 
-/* does cdfs_args_t have fspec field? */
-#define HAVE_FIELD_CDFS_ARGS_T_FSPEC 1
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
 
-/* does cdfs_args_t have iso_flags field? */
-/* #undef HAVE_FIELD_CDFS_ARGS_T_ISO_FLAGS */
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
 
-/* does cdfs_args_t have iso_pgthresh field? */
-/* #undef HAVE_FIELD_CDFS_ARGS_T_ISO_PGTHRESH */
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
 
-/* does cdfs_args_t have norrip field? */
-/* #undef HAVE_FIELD_CDFS_ARGS_T_NORRIP */
+/* Define to 1 if you have the `strcspn' function. */
+#define HAVE_STRCSPN 1
 
-/* does cdfs_args_t have ssector field? */
-#define HAVE_FIELD_CDFS_ARGS_T_SSECTOR 1
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
 
-/* does pcfs_args_t have dsttime field? */
-/* #undef HAVE_FIELD_PCFS_ARGS_T_DSTTIME */
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
 
-/* does pcfs_args_t have fspec field? */
-#define HAVE_FIELD_PCFS_ARGS_T_FSPEC 1
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
 
-/* does pcfs_args_t have gid field? */
-#define HAVE_FIELD_PCFS_ARGS_T_GID 1
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
 
-/* does pcfs_args_t have mask field? */
-#define HAVE_FIELD_PCFS_ARGS_T_MASK 1
+/* Define to 1 if you have the `strlcat' function. */
+#define HAVE_STRLCAT 1
 
-/* does pcfs_args_t have secondswest field? */
-/* #undef HAVE_FIELD_PCFS_ARGS_T_SECONDSWEST */
+/* Define to 1 if you have the `strlcpy' function. */
+#define HAVE_STRLCPY 1
 
-/* does pcfs_args_t have uid field? */
-#define HAVE_FIELD_PCFS_ARGS_T_UID 1
+/* Define to 1 if you have the `strspn' function. */
+#define HAVE_STRSPN 1
 
-/* does ufs_args_t have flags field? */
-/* #undef HAVE_FIELD_UFS_ARGS_T_FLAGS */
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
 
-/* does ufs_args_t have fspec field? */
-#define HAVE_FIELD_UFS_ARGS_T_FSPEC 1
+/* Define to 1 if `fhs_fh' is member of `struct fhstatus'. */
+/* #undef HAVE_STRUCT_FHSTATUS_FHS_FH */
 
-/* does efs_args_t have flags field? */
-/* #undef HAVE_FIELD_EFS_ARGS_T_FLAGS */
+/* Define to 1 if `ifa_next' is member of `struct ifaddrs'. */
+#define HAVE_STRUCT_IFADDRS_IFA_NEXT 1
 
-/* does efs_args_t have fspec field? */
-/* #undef HAVE_FIELD_EFS_ARGS_T_FSPEC */
+/* Define to 1 if `ifr_addr' is member of `struct ifreq'. */
+#define HAVE_STRUCT_IFREQ_IFR_ADDR 1
 
-/* does xfs_args_t have flags field? */
-/* #undef HAVE_FIELD_XFS_ARGS_T_FLAGS */
+/* Define if have struct mntent in one of the standard headers */
+/* #undef HAVE_STRUCT_MNTENT */
 
-/* does xfs_args_t have fspec field? */
-/* #undef HAVE_FIELD_XFS_ARGS_T_FSPEC */
+/* Define if have struct mnttab in one of the standard headers */
+/* #undef HAVE_STRUCT_MNTTAB */
 
-/* does ufs_ars_t have ufs_flags field? */
-/* #undef HAVE_FIELD_UFS_ARGS_T_UFS_FLAGS */
+/* Define if have struct nfs_args in one of the standard nfs headers */
+#define HAVE_STRUCT_NFS_ARGS 1
 
-/* does ufs_ars_t have ufs_pgthresh field? */
-/* #undef HAVE_FIELD_UFS_ARGS_T_UFS_PGTHRESH */
+/* Define if have struct nfs_gfs_mount in one of the standard nfs headers */
+/* #undef HAVE_STRUCT_NFS_GFS_MOUNT */
 
-/* does struct fhstatus have a fhs_fh field? */
-/* #undef HAVE_FIELD_STRUCT_FHSTATUS_FHS_FH */
+/* Define to 1 if `sa_len' is member of `struct sockaddr'. */
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
 
-/* does struct statfs have an f_fstypename field? */
-#define HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME 1
+/* Define to 1 if `f_fstypename' is member of `struct statfs'. */
+#define HAVE_STRUCT_STATFS_F_FSTYPENAME 1
 
-/* does struct nfs_args have an acdirmin field? */
-#define HAVE_FIELD_NFS_ARGS_T_ACDIRMIN 1
+/* Define to 1 if `devid' is member of `struct umntrequest'. */
+/* #undef HAVE_STRUCT_UMNTREQUEST_DEVID */
 
-/* does struct nfs_args have an acregmin field? */
-#define HAVE_FIELD_NFS_ARGS_T_ACREGMIN 1
+/* Define to 1 if you have the `svc_getreq' function. */
+#define HAVE_SVC_GETREQ 1
 
-/* does struct nfs_args have a bsize field? */
-/* #undef HAVE_FIELD_NFS_ARGS_T_BSIZE */
+/* Define to 1 if you have the `svc_getreqset' function. */
+#define HAVE_SVC_GETREQSET 1
 
-/* does struct nfs_args have an fh_len field? */
-/* #undef HAVE_FIELD_NFS_ARGS_T_FH_LEN */
+/* Define to 1 if you have the `sysfs' function. */
+/* #undef HAVE_SYSFS */
 
-/* does struct nfs_args have an fhsize field? */
-#define HAVE_FIELD_NFS_ARGS_T_FHSIZE 1
+/* Define to 1 if you have the `syslog' function. */
+#define HAVE_SYSLOG 1
 
-/* does struct nfs_args have a gfs_flags field? */
-/* #undef HAVE_FIELD_NFS_ARGS_T_GFS_FLAGS */
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
 
-/* does struct nfs_args have a namlen field? */
-/* #undef HAVE_FIELD_NFS_ARGS_T_NAMLEN */
+/* Define to 1 if you have the <sys/config.h> header file. */
+/* #undef HAVE_SYS_CONFIG_H */
 
-/* does struct nfs_args have an optstr field? */
-/* #undef HAVE_FIELD_NFS_ARGS_T_OPTSTR */
+/* Define to 1 if you have the <sys/dg_mount.h> header file. */
+/* #undef HAVE_SYS_DG_MOUNT_H */
 
-/* does struct nfs_args have a proto field? */
-#define HAVE_FIELD_NFS_ARGS_T_PROTO 1
+/* Define to 1 if you have the <sys/dir.h> header file. */
+#define HAVE_SYS_DIR_H 1
 
-/* does struct nfs_args have a socket type field? */
-#define HAVE_FIELD_NFS_ARGS_T_SOTYPE 1
+/* Define to 1 if you have the <sys/errno.h> header file. */
+#define HAVE_SYS_ERRNO_H 1
 
-/* does struct nfs_args have a version field? */
-#define HAVE_FIELD_NFS_ARGS_T_VERSION 1
+/* Define to 1 if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
 
-/* does struct ifreq have field ifr_addr? */
-#define HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR 1
+/* Define to 1 if you have the <sys/fsid.h> header file. */
+/* #undef HAVE_SYS_FSID_H */
 
-/* does struct ifaddrs have field ifa_next? */
-/* #undef HAVE_FIELD_STRUCT_IFADDRS_IFA_NEXT */
+/* Define to 1 if you have the <sys/fstyp.h> header file. */
+/* #undef HAVE_SYS_FSTYP_H */
 
-/* does struct sockaddr have field sa_len? */
-#define HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN 1
+/* Define to 1 if you have the <sys/fs/autofs.h> header file. */
+/* #undef HAVE_SYS_FS_AUTOFS_H */
 
-/* does struct autofs_args have an addr field? */
-/* #undef HAVE_FIELD_AUTOFS_ARGS_T_ADDR */
+/* Define to 1 if you have the <sys/fs/autofs_prot.h> header file. */
+/* #undef HAVE_SYS_FS_AUTOFS_PROT_H */
 
-/* does umntrequest have an rdevid field? */
-/* #undef HAVE_FIELD_UMNTREQUEST_RDEVID */
+/* Define to 1 if you have the <sys/fs/cachefs_fs.h> header file. */
+/* #undef HAVE_SYS_FS_CACHEFS_FS_H */
 
+/* Define to 1 if you have the <sys/fs/efs_clnt.h> header file. */
+/* #undef HAVE_SYS_FS_EFS_CLNT_H */
 
-/* should signal handlers be reinstalled? */
-/* #undef REINSTALL_SIGNAL_HANDLER */
+/* Define to 1 if you have the <sys/fs/nfs_clnt.h> header file. */
+/* #undef HAVE_SYS_FS_NFS_CLNT_H */
 
+/* Define to 1 if you have the <sys/fs/nfs.h> header file. */
+/* #undef HAVE_SYS_FS_NFS_H */
 
-/**************************************************************************/
-/*** Everything above this line is part of the "TOP" of acconfig.h.	***/
-/**************************************************************************/
+/* Define to 1 if you have the <sys/fs/nfs/mount.h> header file. */
+/* #undef HAVE_SYS_FS_NFS_MOUNT_H */
 
+/* Define to 1 if you have the <sys/fs/nfs/nfs_clnt.h> header file. */
+/* #undef HAVE_SYS_FS_NFS_NFS_CLNT_H */
 
-/* Define if on AIX 3.
-   System headers sometimes define this.
-   We just want to avoid a redefinition error message.  */
-#ifndef _ALL_SOURCE
-/* #undef _ALL_SOURCE */
-#endif
+/* Define to 1 if you have the <sys/fs/pc_fs.h> header file. */
+/* #undef HAVE_SYS_FS_PC_FS_H */
 
-/* Define if using alloca.c.  */
-/* #undef C_ALLOCA */
+/* Define to 1 if you have the <sys/fs/tmp.h> header file. */
+/* #undef HAVE_SYS_FS_TMP_H */
 
-/* Define to empty if the keyword does not work.  */
-/* #undef const */
+/* Define to 1 if you have the <sys/fs_types.h> header file. */
+/* #undef HAVE_SYS_FS_TYPES_H */
 
-/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
-   This function is required for alloca.c support on those systems.  */
-/* #undef CRAY_STACKSEG_END */
+/* Define to 1 if you have the <sys/fs/ufs_mount.h> header file. */
+/* #undef HAVE_SYS_FS_UFS_MOUNT_H */
 
-/* Define to the type of elements in the array set by `getgroups'.
-   Usually this is either `int' or `gid_t'.  */
-#define GETGROUPS_T gid_t
+/* Define to 1 if you have the <sys/fs/xfs_clnt.h> header file. */
+/* #undef HAVE_SYS_FS_XFS_CLNT_H */
 
-/* Define to `int' if <sys/types.h> doesn't define.  */
-/* #undef gid_t */
+/* Define to 1 if you have the <sys/immu.h> header file. */
+/* #undef HAVE_SYS_IMMU_H */
 
-/* Define if you have alloca, as a function or macro.  */
-#define HAVE_ALLOCA 1
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
 
-/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
-/* #undef HAVE_ALLOCA_H */
+/* Define to 1 if you have the <sys/lock.h> header file. */
+#define HAVE_SYS_LOCK_H 1
 
-/* Define if you support file names longer than 14 characters.  */
-#define HAVE_LONG_FILE_NAMES 1
+/* Define to 1 if you have the <sys/machine.h> header file. */
+/* #undef HAVE_SYS_MACHINE_H */
 
-/* Define if system calls automatically restart after interruption
-   by a signal.  */
-#define HAVE_RESTARTABLE_SYSCALLS 1
+/* Define to 1 if you have the <sys/mbuf.h> header file. */
+#define HAVE_SYS_MBUF_H 1
 
-/* Define if your struct stat has st_rdev.  */
-#define HAVE_ST_RDEV 1
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
 
-/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
-#define HAVE_SYS_WAIT_H 1
+/* Define to 1 if you have the <sys/mntctl.h> header file. */
+/* #undef HAVE_SYS_MNTCTL_H */
 
-/* Define if you have <vfork.h>.  */
-/* #undef HAVE_VFORK_H */
+/* Define to 1 if you have the <sys/mntent.h> header file. */
+/* #undef HAVE_SYS_MNTENT_H */
 
-/* Define if you have the wait3 system call.  */
-#define HAVE_WAIT3 1
+/* Define to 1 if you have the <sys/mnttab.h> header file. */
+/* #undef HAVE_SYS_MNTTAB_H */
 
-/* Define as __inline if that's what the C compiler calls it.  */
-/* #undef inline */
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#define HAVE_SYS_MOUNT_H 1
 
-/* Define if your C compiler doesn't accept -c and -o together.  */
-/* #undef NO_MINUS_C_MINUS_O */
+/* Define to 1 if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
 
-/* Define if you need to in order for stat and other things to work.  */
-/* #undef _POSIX_SOURCE */
+/* Define to 1 if you have the <sys/netconfig.h> header file. */
+/* #undef HAVE_SYS_NETCONFIG_H */
 
-/* Define as the return type of signal handlers (int or void).  */
-#define RETSIGTYPE void
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
 
-/* If using the C implementation of alloca, define if you know the
-   direction of stack growth for your system; otherwise it will be
-   automatically deduced at run-time.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown
- */
-/* #undef STACK_DIRECTION */
+/* Define to 1 if you have the <sys/pathconf.h> header file. */
+/* #undef HAVE_SYS_PATHCONF_H */
 
-/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly.  */
-/* #undef STAT_MACROS_BROKEN */
+/* Define to 1 if you have the <sys/proc.h> header file. */
+#define HAVE_SYS_PROC_H 1
 
-/* Define if you have the ANSI C header files.  */
-#define STDC_HEADERS 1
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
 
-/* Define if you can safely include both <sys/time.h> and <time.h>.  */
-#define TIME_WITH_SYS_TIME 1
+/* Define to 1 if you have the <sys/sema.h> header file. */
+/* #undef HAVE_SYS_SEMA_H */
 
-/* Define if your <sys/time.h> declares struct tm.  */
-/* #undef TM_IN_SYS_TIME */
+/* Define to 1 if you have the <sys/signal.h> header file. */
+#define HAVE_SYS_SIGNAL_H 1
 
-/* Define to `int' if <sys/types.h> doesn't define.  */
-/* #undef uid_t */
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
 
-/* Define vfork as fork if vfork does not work.  */
-/* #undef vfork */
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
 
-/* Define if your processor stores words with the most significant
-   byte first (like Motorola and SPARC, unlike Intel and VAX).  */
-/* #undef WORDS_BIGENDIAN */
-#include <machine/endian.h>
-#if BYTE_ORDER == BIG_ENDIAN
-#define WORDS_BIGENDIAN
-#endif
+/* Define to 1 if you have the <sys/statfs.h> header file. */
+/* #undef HAVE_SYS_STATFS_H */
 
-/* Define if lex declares yytext as a char * by default, not a char[].  */
-#define YYTEXT_POINTER 1
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#define HAVE_SYS_STATVFS_H 1
 
-/* Turn off general debugging by default */
-/* #undef DEBUG */
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
 
-/* Turn off memory debugging by default */
-/* #undef DEBUG_MEM */
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#define HAVE_SYS_SYSCALL_H 1
 
-/* Enable "amq -M" remote mount code (insecure due to IP spoofing) */
-/* #undef ENABLE_AMQ_MOUNT */
+/* Define to 1 if you have the <sys/syslimits.h> header file. */
+#define HAVE_SYS_SYSLIMITS_H 1
 
-/* Define package name (must be defined by configure.in) */
-#define PACKAGE "am-utils"
+/* Define to 1 if you have the <sys/syslog.h> header file. */
+#define HAVE_SYS_SYSLOG_H 1
 
-/* Define version of package (must be defined by configure.in) */
-#define VERSION "6.0.3s1"
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
 
-/* We [FREEBSD-NATIVE] pick some parameters from our local config file */
-#include "config_local.h"
+/* Define to 1 if you have the <sys/tiuser.h> header file. */
+/* #undef HAVE_SYS_TIUSER_H */
 
-/* Define name of host machine's cpu (eg. sparc) */
-/* #define HOST_CPU "i386" */
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
 
-/* Define name of host machine's architecture (eg. sun4) */
-/* #define HOST_ARCH "i386" */
+/* Define to 1 if you have the <sys/ucred.h> header file. */
+#define HAVE_SYS_UCRED_H 1
 
-/* Define name of host machine's vendor (eg. sun) */
-#define HOST_VENDOR "unknown"
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
 
-/* Define name and version of host machine (eg. solaris2.5.1) */
-/* #define HOST_OS "freebsd3.0" */
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
 
-/* Define only name of host machine OS (eg. solaris2) */
-/* #define HOST_OS_NAME "freebsd3" */
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+/* #undef HAVE_SYS_VFS_H */
 
-/* Define only version of host machine (eg. 2.5.1) */
-/* #define HOST_OS_VERSION "3.0" */
+/* Define to 1 if you have the <sys/vmount.h> header file. */
+/* #undef HAVE_SYS_VMOUNT_H */
 
-/* Define the header version of (linux) hosts (eg. 2.2.10) */
-/* #define HOST_HEADER_VERSION "4.0" */
+/* Define to 1 if you have the <sys/vnode.h> header file. */
+#define HAVE_SYS_VNODE_H 1
 
-/* Define name of host */
-/* #define HOST_NAME "dragon.nuxi.com" */
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
 
-/* Define user name */
-/* #define USER_NAME "obrien" */
+/* Define to 1 if you have the <tcpd.h> header file. */
+#define HAVE_TCPD_H 1
 
-/* Define configuration date */
-/* #define CONFIG_DATE "Fri Aug 21 19:35:55 PDT 1998" */
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
 
-/* what type of network transport type is in use?  TLI or sockets? */
-/* #undef HAVE_TRANSPORT_TYPE_TLI */
+/* Define to 1 if you have the <tiuser.h> header file. */
+/* #undef HAVE_TIUSER_H */
 
-/* Define to "void *" if compiler can handle, otherwise "char *" */
-#define voidp void *
+/* Define to 1 if you have the <tmpfs/tmp.h> header file. */
+/* #undef HAVE_TMPFS_TMP_H */
 
-/* Define a type/structure for an NFS V2 filehandle */
-#define am_nfs_fh nfs_fh
+/* what type of network transport type is in use? TLI or sockets? */
+/* #undef HAVE_TRANSPORT_TYPE_TLI */
 
-/* Define a type/structure for an NFS V3 filehandle */
-#define am_nfs_fh3 nfs_fh3
+/* Define to 1 if you have the `ualarm' function. */
+#define HAVE_UALARM 1
 
-/* define name of am-utils' NFS protocol header */
-#define AMU_NFS_PROTOCOL_HEADER "./conf/nfs_prot/nfs_prot_freebsd3.h"
+/* Define to 1 if `flags' is member of `ufs_args_t'. */
+/* #undef HAVE_UFS_ARGS_T_FLAGS */
 
-/* Define a type for the nfs_args structure */
-#define nfs_args_t struct nfs_args
+/* Define to 1 if `fspec' is member of `ufs_args_t'. */
+#define HAVE_UFS_ARGS_T_FSPEC 1
 
-/* Define the field name for the filehandle within nfs_args_t */
-#define NFS_FH_FIELD fh
+/* Define to 1 if `ufs_flags' is member of `ufs_args_t'. */
+/* #undef HAVE_UFS_ARGS_T_UFS_FLAGS */
 
-/* Define if plain fhandle type exists */
-#define HAVE_FHANDLE 1
+/* Define to 1 if `ufs_pgthresh' is member of `ufs_args_t'. */
+/* #undef HAVE_UFS_ARGS_T_UFS_PGTHRESH */
 
-/* Define the type of the 3rd argument ('in') to svc_getargs() */
-#define SVC_IN_ARG_TYPE caddr_t
+/* Define to 1 if you have the <ufs/ufs/extattr.h> header file. */
+#define HAVE_UFS_UFS_EXTATTR_H 1
 
-/* Define to the type of xdr procedure type */
-#define XDRPROC_T_TYPE xdrproc_t
+/* Define to 1 if you have the <ufs/ufs_mount.h> header file. */
+/* #undef HAVE_UFS_UFS_MOUNT_H */
 
-/* Define if mount table is on file, undefine if in kernel */
-/* #undef MOUNT_TABLE_ON_FILE */
+/* Define to 1 if you have the <ufs/ufs/ufsmount.h> header file. */
+#define HAVE_UFS_UFS_UFSMOUNT_H 1
 
-/* Define if have struct mntent in one of the standard headers */
-/* #undef HAVE_STRUCT_MNTENT */
+/* Define to 1 if you have the `umount' function. */
+/* #undef HAVE_UMOUNT */
 
-/* Define if have struct mnttab in one of the standard headers */
-/* #undef HAVE_STRUCT_MNTTAB */
+/* Define to 1 if you have the `umount2' function. */
+/* #undef HAVE_UMOUNT2 */
 
-/* Define if have struct nfs_args in one of the standard nfs headers */
-#define HAVE_STRUCT_NFS_ARGS 1
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
 
-/* Define if have struct nfs_mount_data in one of the standard nfs headers */
-/* #undef HAVE_STRUCT_NFS_MOUNT_DATA */
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
 
-/* Define if have struct nfs_gfs_mount in one of the standard nfs headers */
-/* #undef HAVE_STRUCT_NFS_GFS_MOUNT */
+/* Define to 1 if you have the `unmount' function. */
+#define HAVE_UNMOUNT 1
 
-/* Type of the 3rd argument to yp_order() */
-#define YP_ORDER_OUTORDER_TYPE int
+/* Define to 1 if you have the `uvmount' function. */
+/* #undef HAVE_UVMOUNT */
 
-/* Type of the 6th argument to recvfrom() */
-#define RECVFROM_FROMLEN_TYPE int
+/* Define to 1 if you have the <varargs.h> header file. */
+/* #undef HAVE_VARARGS_H */
 
-/* Type of the 5rd argument to authunix_create() */
-#define AUTH_CREATE_GIDLIST_TYPE gid_t
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
 
-/* The string used in printf to print the mount-type field of mount(2) */
-#define MTYPE_PRINTF_TYPE "%s"
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
 
-/* Type of the mount-type field in the mount() system call */
-#define MTYPE_TYPE const char *
+/* Define to 1 if you have the `vfsmount' function. */
+/* #undef HAVE_VFSMOUNT */
 
-/* Define a type for the pcfs_args structure */
-#define pcfs_args_t struct msdosfs_args
+/* Define to 1 if you have the `vmount' function. */
+/* #undef HAVE_VMOUNT */
 
-/* Define a type for the autofs_args structure */
-/* #undef autofs_args_t */
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
 
-/* Define a type for the cachefs_args structure */
-/* #undef cachefs_args_t */
+/* Define to 1 if you have the `wait3' function. */
+#define HAVE_WAIT3 1
 
-/* Define a type for the tmpfs_args structure */
-/* #undef tmpfs_args_t */
+/* Define to 1 if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
 
-/* Define a type for the ufs_args structure */
-#define ufs_args_t struct ufs_args
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
 
-/* Define a type for the efs_args structure */
-/* #undef efs_args_t */
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
 
-/* Define a type for the xfs_args structure */
-/* #undef xfs_args_t */
+/* Define to 1 if you have the `xdr_attrstat' function. */
+#define HAVE_XDR_ATTRSTAT 1
 
-/* Define a type for the lofs_args structure */
-/* #undef lofs_args_t */
+/* Define to 1 if you have the `xdr_createargs' function. */
+#define HAVE_XDR_CREATEARGS 1
 
-/* Define a type for the cdfs_args structure */
-#define cdfs_args_t struct iso_args
+/* Define to 1 if you have the `xdr_dirlist' function. */
+#define HAVE_XDR_DIRLIST 1
 
-/* Define a type for the mfs_args structure */
-#define mfs_args_t struct mfs_args
+/* Define to 1 if you have the `xdr_diropargs' function. */
+#define HAVE_XDR_DIROPARGS 1
 
-/* Define a type for the rfs_args structure */
-/* #undef rfs_args_t */
+/* Define to 1 if you have the `xdr_diropokres' function. */
+#define HAVE_XDR_DIROPOKRES 1
 
-/* define if have a bad version of memcmp() */
-/* #undef HAVE_BAD_MEMCMP */
+/* Define to 1 if you have the `xdr_diropres' function. */
+#define HAVE_XDR_DIROPRES 1
 
-/* define if have a bad version of yp_all() */
-/* #undef HAVE_BAD_YP_ALL */
+/* Define to 1 if you have the `xdr_dirpath' function. */
+#define HAVE_XDR_DIRPATH 1
 
-/* define if must use NFS "noconn" option */
-/* #undef USE_UNCONNECTED_NFS_SOCKETS */
-/* define if must NOT use NFS "noconn" option */
-#define USE_CONNECTED_NFS_SOCKETS 1
+/* Define to 1 if you have the `xdr_entry' function. */
+#define HAVE_XDR_ENTRY 1
 
-/* Define if you have the __seterr_reply function.  */
-/* #undef HAVE___SETERR_REPLY */
+/* Define to 1 if you have the `xdr_exportnode' function. */
+#define HAVE_XDR_EXPORTNODE 1
 
-/* Define if you have the _seterr_reply function.  */
-#define HAVE__SETERR_REPLY 1
+/* Define to 1 if you have the `xdr_exports' function. */
+#define HAVE_XDR_EXPORTS 1
 
-/* Define if you have the bcmp function.  */
-#define HAVE_BCMP 1
+/* Define to 1 if you have the `xdr_fattr' function. */
+#define HAVE_XDR_FATTR 1
 
-/* Define if you have the bcopy function.  */
-#define HAVE_BCOPY 1
+/* Define to 1 if you have the `xdr_fhandle' function. */
+#define HAVE_XDR_FHANDLE 1
 
-/* Define if you have the bzero function.  */
-#define HAVE_BZERO 1
+/* Define to 1 if you have the `xdr_fhstatus' function. */
+#define HAVE_XDR_FHSTATUS 1
 
-/* Define if you have the clnt_create function.  */
-#define HAVE_CLNT_CREATE 1
+/* Define to 1 if you have the `xdr_filename' function. */
+#define HAVE_XDR_FILENAME 1
 
-/* Define if you have the clnt_create_timed function.  */
-/* #undef HAVE_CLNT_CREATE_TIMED */
+/* Define to 1 if you have the `xdr_ftype' function. */
+#define HAVE_XDR_FTYPE 1
 
-/* Define if you have the clnt_spcreateerror function.  */
-#define HAVE_CLNT_SPCREATEERROR 1
+/* Define to 1 if you have the `xdr_groupnode' function. */
+#define HAVE_XDR_GROUPNODE 1
 
-/* Define if you have the clnt_sperrno function.  */
-#define HAVE_CLNT_SPERRNO 1
+/* Define to 1 if you have the `xdr_groups' function. */
+#define HAVE_XDR_GROUPS 1
 
-/* Define if you have the cnodeid function.  */
-/* #undef HAVE_CNODEID */
+/* Define to 1 if you have the `xdr_linkargs' function. */
+#define HAVE_XDR_LINKARGS 1
 
-/* Define if you have the dbm_open function.  */
-#define HAVE_DBM_OPEN 1
+/* Define to 1 if you have the `xdr_mountbody' function. */
+#define HAVE_XDR_MOUNTBODY 1
 
-/* Define if you have the dg_mount function.  */
-/* #undef HAVE_DG_MOUNT */
+/* Define to 1 if you have the `xdr_mountlist' function. */
+#define HAVE_XDR_MOUNTLIST 1
 
-/* Define if you have the fgets function.  */
-#define HAVE_FGETS 1
+/* Define to 1 if you have the `xdr_name' function. */
+#define HAVE_XDR_NAME 1
 
-/* Define if you have the flock function.  */
-#define HAVE_FLOCK 1
+/* Define to 1 if you have the `xdr_nfscookie' function. */
+#define HAVE_XDR_NFSCOOKIE 1
 
-/* Define if you have the fsmount function.  */
-/* #undef HAVE_FSMOUNT */
+/* Define to 1 if you have the `xdr_nfspath' function. */
+#define HAVE_XDR_NFSPATH 1
 
-/* Define if you have the get_myaddress function.  */
-#define HAVE_GET_MYADDRESS 1
+/* Define to 1 if you have the `xdr_nfsstat' function. */
+#define HAVE_XDR_NFSSTAT 1
 
-/* Define if you have the getccent function.  */
-/* #undef HAVE_GETCCENT */
+/* Define to 1 if you have the `xdr_nfstime' function. */
+#define HAVE_XDR_NFSTIME 1
 
-/* Define if you have the getcwd function.  */
-#define HAVE_GETCWD 1
+/* Define to 1 if you have the `xdr_nfs_fh' function. */
+#define HAVE_XDR_NFS_FH 1
 
-/* Define if you have the getdomainname function.  */
-#define HAVE_GETDOMAINNAME 1
+/* Define to 1 if you have the `xdr_pointer' function. */
+#define HAVE_XDR_POINTER 1
 
-/* Define if you have the getdtablesize function.  */
-#define HAVE_GETDTABLESIZE 1
+/* Define to 1 if you have the `xdr_readargs' function. */
+#define HAVE_XDR_READARGS 1
 
-/* Define if you have the gethostname function.  */
-#define HAVE_GETHOSTNAME 1
+/* Define to 1 if you have the `xdr_readdirargs' function. */
+#define HAVE_XDR_READDIRARGS 1
 
-/* Define if you have the getifaddrs function.  */
-/* #undef HAVE_GETIFADDRS */
+/* Define to 1 if you have the `xdr_readdirres' function. */
+#define HAVE_XDR_READDIRRES 1
 
-/* Define if you have the getmntinfo function.  */
-#define HAVE_GETMNTINFO 1
+/* Define to 1 if you have the `xdr_readlinkres' function. */
+#define HAVE_XDR_READLINKRES 1
 
-/* Define if you have the getmountent function.  */
-/* #undef HAVE_GETMOUNTENT */
+/* Define to 1 if you have the `xdr_readokres' function. */
+#define HAVE_XDR_READOKRES 1
 
-/* Define if you have the getpagesize function.  */
-#define HAVE_GETPAGESIZE 1
+/* Define to 1 if you have the `xdr_readres' function. */
+#define HAVE_XDR_READRES 1
 
-/* Define if you have the getpwnam function.  */
-#define HAVE_GETPWNAM 1
+/* Define to 1 if you have the `xdr_renameargs' function. */
+#define HAVE_XDR_RENAMEARGS 1
 
-/* Define if you have the gettimeofday function.  */
-#define HAVE_GETTIMEOFDAY 1
+/* Define to 1 if you have the `xdr_sattr' function. */
+#define HAVE_XDR_SATTR 1
 
-/* Define if you have the hasmntopt function.  */
-/* #undef HAVE_HASMNTOPT */
+/* Define to 1 if you have the `xdr_sattrargs' function. */
+#define HAVE_XDR_SATTRARGS 1
 
-/* Define if you have the hes_init function.  */
-/* #undef HAVE_HES_INIT */
+/* Define to 1 if you have the `xdr_statfsokres' function. */
+#define HAVE_XDR_STATFSOKRES 1
 
-/* Define if you have the hesiod_init function.  */
-/* #undef HAVE_HESIOD_INIT */
+/* Define to 1 if you have the `xdr_statfsres' function. */
+#define HAVE_XDR_STATFSRES 1
 
-/* Define if you have the hesiod_reload function.  */
-/* #undef HAVE_HESIOD_RELOAD */
+/* Define to 1 if you have the `xdr_symlinkargs' function. */
+#define HAVE_XDR_SYMLINKARGS 1
 
-/* Define if you have the hesiod_to_bind function.  */
-/* #undef HAVE_HESIOD_TO_BIND */
+/* Define to 1 if you have the `xdr_writeargs' function. */
+#define HAVE_XDR_WRITEARGS 1
 
-/* Define if you have the ldap_open function.  */
-/* #undef HAVE_LDAP_OPEN */
+/* Define to 1 if `flags' is member of `xfs_args_t'. */
+/* #undef HAVE_XFS_ARGS_T_FLAGS */
 
-/* Define if you have the memcmp function.  */
-#define HAVE_MEMCMP 1
+/* Define to 1 if `fspec' is member of `xfs_args_t'. */
+/* #undef HAVE_XFS_ARGS_T_FSPEC */
 
-/* Define if you have the memcpy function.  */
-#define HAVE_MEMCPY 1
+/* Define to 1 if you have the `yp_all' function. */
+/* #undef HAVE_YP_ALL */
 
-/* Define if you have the memmove function.  */
-#define HAVE_MEMMOVE 1
+/* Define to 1 if you have the `yp_get_default_domain' function. */
+#define HAVE_YP_GET_DEFAULT_DOMAIN 1
 
-/* Define if you have the memset function.  */
-#define HAVE_MEMSET 1
+/* Define to 1 if you have the `_seterr_reply' function. */
+#define HAVE__SETERR_REPLY 1
 
-/* Define if you have the mkdir function.  */
-#define HAVE_MKDIR 1
+/* Define to 1 if you have the `__rpc_get_local_uid' function. */
+#define HAVE___RPC_GET_LOCAL_UID 1
 
-/* Define if you have the mkstemp function.  */
-#define HAVE_MKSTEMP 1
+/* Define to 1 if you have the `__seterr_reply' function. */
+/* #undef HAVE___SETERR_REPLY */
 
-/* Define if you have the mntctl function.  */
-/* #undef HAVE_MNTCTL */
+/* Name of mount type to hide amd mount from df(1) */
+#define HIDE_MOUNT_TYPE "nfs"
 
-/* Define if you have the mount function.  */
-#define HAVE_MOUNT 1
+/* Define name of host machine's architecture (eg. sun4) */
+/* #define HOST_ARCH "i386" */
 
-/* Define if you have the mountsyscall function.  */
-/* #undef HAVE_MOUNTSYSCALL */
+/* Define name of host machine's cpu (eg. sparc) */
+/* #define HOST_CPU "i386" */
 
-/* Define if you have the nis_domain_of function.  */
-/* #undef HAVE_NIS_DOMAIN_OF */
+/* Define the header version of (linux) hosts (eg. 2.2.10) */
+// #undef define HOST_HEADER_VERSION */
 
-/* Define if you have the opendir function.  */
-#define HAVE_OPENDIR 1
+/* Define name of host */
+/* #define HOST_NAME "trang.nuxi.org" */
 
-/* Define if you have the plock function.  */
-/* #undef HAVE_PLOCK */
+/* Define name and version of host machine (eg. solaris2.5.1) */
+/* #define HOST_OS "freebsd8.0" */
 
-/* Define if you have the regcomp function.  */
-#define HAVE_REGCOMP 1
+/* Define only name of host machine OS (eg. solaris2) */
+/* #define HOST_OS_NAME "freebsd8" */
 
-/* Define if you have the regexec function.  */
-#define HAVE_REGEXEC 1
+/* Define only version of host machine (eg. 2.5.1) */
+/* #define HOST_OS_VERSION "8.0" */
 
-/* Define if you have the rmdir function.  */
-#define HAVE_RMDIR 1
+/* Define name of host machine's vendor (eg. sun) */
+#define HOST_VENDOR "undermydesk"
 
-/* Define if you have the select function.  */
-#define HAVE_SELECT 1
+/* Ignore permission bits */
+/* #undef MNT2_CDFS_OPT_DEFPERM */
 
-/* Define if you have the seteuid function.  */
-#define HAVE_SETEUID 1
+/* Use on-disk permission bits */
+/* #undef MNT2_CDFS_OPT_NODEFPERM */
 
-/* Define if you have the setitimer function.  */
-#define HAVE_SETITIMER 1
+/* Strip off extension from version string */
+/* #undef MNT2_CDFS_OPT_NOVERSION */
 
-/* Define if you have the setresuid function.  */
-/* #undef HAVE_SETRESUID */
+/* Use Rock Ridge Interchange Protocol (RRIP) extensions */
+/* #undef MNT2_CDFS_OPT_RRIP */
 
-/* Define if you have the setsid function.  */
-#define HAVE_SETSID 1
+/* asynchronous filesystem access */
+#define MNT2_GEN_OPT_ASYNC 0x40
 
-/* Define if you have the sigaction function.  */
-#define HAVE_SIGACTION 1
+/* automounter filesystem (ignore) flag, used in bsdi-4.1 */
+/* #undef MNT2_GEN_OPT_AUTOMNTFS */
 
-/* Define if you have the signal function.  */
-#define HAVE_SIGNAL 1
+/* automounter filesystem flag, used in Mac OS X / Darwin */
+/* #undef MNT2_GEN_OPT_AUTOMOUNTED */
 
-/* Define if you have the socket function.  */
-#define HAVE_SOCKET 1
+/* directory hardlink */
+/* #undef MNT2_GEN_OPT_BIND */
 
-/* Define if you have the strcasecmp function.  */
-#define HAVE_STRCASECMP 1
+/* cache (what?) */
+/* #undef MNT2_GEN_OPT_CACHE */
 
-/* Define if you have the strchr function.  */
-#define HAVE_STRCHR 1
+/* 6-argument mount */
+/* #undef MNT2_GEN_OPT_DATA */
 
-/* Define if you have the strcspn function.  */
-#define HAVE_STRCSPN 1
+/* Use a lazy unmount (detach) */
+/* #undef MNT2_GEN_OPT_DETACH */
 
-/* Define if you have the strdup function.  */
-#define HAVE_STRDUP 1
+/* Use a forced unmount */
+#define MNT2_GEN_OPT_FORCE 0x80000
 
-/* Define if you have the strerror function.  */
-#define HAVE_STRERROR 1
+/* old (4-argument) mount (compatibility) */
+/* #undef MNT2_GEN_OPT_FSS */
 
-/* Define if you have the strspn function.  */
-#define HAVE_STRSPN 1
+/* old BSD group-id on create */
+/* #undef MNT2_GEN_OPT_GRPID */
 
-/* Define if you have the strstr function.  */
-#define HAVE_STRSTR 1
+/* ignore mount entry in df output */
+#define MNT2_GEN_OPT_IGNORE 0x800000
 
-/* Define if you have the svc_getreq function.  */
-#define HAVE_SVC_GETREQ 1
+/* journaling filesystem (AIX's UFS/FFS) */
+/* #undef MNT2_GEN_OPT_JFS */
 
-/* Define if you have the svc_getreqset function.  */
-#define HAVE_SVC_GETREQSET 1
+/* do multi-component lookup on files */
+/* #undef MNT2_GEN_OPT_MULTI */
 
-/* Define if you have the sysfs function.  */
-/* #undef HAVE_SYSFS */
+/* use type string instead of int */
+/* #undef MNT2_GEN_OPT_NEWTYPE */
 
-/* Define if you have the syslog function.  */
-#define HAVE_SYSLOG 1
+/* NFS mount */
+/* #undef MNT2_GEN_OPT_NFS */
 
-/* Define if you have the ualarm function.  */
-#define HAVE_UALARM 1
+/* nocache (what?) */
+/* #undef MNT2_GEN_OPT_NOCACHE */
 
-/* Define if you have the umount function.  */
-/* #undef HAVE_UMOUNT */
+/* do not interpret special device files */
+#define MNT2_GEN_OPT_NODEV 0x0
 
-/* Define if you have the uname function.  */
-#define HAVE_UNAME 1
+/* no exec calls allowed */
+#define MNT2_GEN_OPT_NOEXEC 0x4
 
-/* Define if you have the unmount function.  */
-#define HAVE_UNMOUNT 1
+/* do not interpret special device files */
+/* #undef MNT2_GEN_OPT_NONDEV */
 
-/* Define if you have the uvmount function.  */
-/* #undef HAVE_UVMOUNT */
+/* Disallow mounts beneath this mount */
+/* #undef MNT2_GEN_OPT_NOSUB */
 
-/* Define if you have the vfork function.  */
-#define HAVE_VFORK 1
+/* Setuid programs disallowed */
+#define MNT2_GEN_OPT_NOSUID 0x8
 
-/* Define if you have the vfsmount function.  */
-/* #undef HAVE_VFSMOUNT */
+/* Return ENAMETOOLONG for long filenames */
+/* #undef MNT2_GEN_OPT_NOTRUNC */
 
-/* Define if you have the vmount function.  */
-/* #undef HAVE_VMOUNT */
+/* Pass mount option string to kernel */
+/* #undef MNT2_GEN_OPT_OPTIONSTR */
 
-/* Define if you have the vsnprintf function.  */
-#define HAVE_VSNPRINTF 1
+/* allow overlay mounts */
+/* #undef MNT2_GEN_OPT_OVERLAY */
 
-/* Define if you have the wait3 function.  */
-#define HAVE_WAIT3 1
+/* check quotas */
+#define MNT2_GEN_OPT_QUOTA 0x2000
 
-/* Define if you have the waitpid function.  */
-#define HAVE_WAITPID 1
+/* Read-only */
+#define MNT2_GEN_OPT_RDONLY 0x1
 
-/* Define if you have the xdr_attrstat function.  */
-#define HAVE_XDR_ATTRSTAT 1
+/* change options on an existing mount */
+/* #undef MNT2_GEN_OPT_REMOUNT */
 
-/* Define if you have the xdr_createargs function.  */
-#define HAVE_XDR_CREATEARGS 1
+/* read only */
+/* #undef MNT2_GEN_OPT_RONLY */
 
-/* Define if you have the xdr_dirlist function.  */
-#define HAVE_XDR_DIRLIST 1
+/* synchronize data immediately to filesystem */
+/* #undef MNT2_GEN_OPT_SYNC */
 
-/* Define if you have the xdr_diropargs function.  */
-#define HAVE_XDR_DIROPARGS 1
+/* synchronous filesystem access (same as SYNC) */
+#define MNT2_GEN_OPT_SYNCHRONOUS 0x2
 
-/* Define if you have the xdr_diropokres function.  */
-#define HAVE_XDR_DIROPOKRES 1
+/* Mount with Sys 5-specific semantics */
+/* #undef MNT2_GEN_OPT_SYS5 */
 
-/* Define if you have the xdr_diropres function.  */
-#define HAVE_XDR_DIROPRES 1
+/* Union mount */
+/* #undef MNT2_GEN_OPT_UNION */
 
-/* Define if you have the xdr_dirpath function.  */
-#define HAVE_XDR_DIRPATH 1
+/* set max secs for dir attr cache */
+#define MNT2_NFS_OPT_ACDIRMAX 0x200000
 
-/* Define if you have the xdr_entry function.  */
-#define HAVE_XDR_ENTRY 1
+/* set min secs for dir attr cache */
+#define MNT2_NFS_OPT_ACDIRMIN 0x100000
 
-/* Define if you have the xdr_exportnode function.  */
-#define HAVE_XDR_EXPORTNODE 1
+/* set max secs for file attr cache */
+#define MNT2_NFS_OPT_ACREGMAX 0x80000
 
-/* Define if you have the xdr_exports function.  */
-#define HAVE_XDR_EXPORTS 1
+/* set min secs for file attr cache */
+#define MNT2_NFS_OPT_ACREGMIN 0x40000
 
-/* Define if you have the xdr_fattr function.  */
-#define HAVE_XDR_FATTR 1
+/* Authentication error */
+/* #undef MNT2_NFS_OPT_AUTHERR */
 
-/* Define if you have the xdr_fhandle function.  */
-#define HAVE_XDR_FHANDLE 1
+/* hide mount type from df(1) */
+/* #undef MNT2_NFS_OPT_AUTO */
 
-/* Define if you have the xdr_fhstatus function.  */
-#define HAVE_XDR_FHSTATUS 1
+/* set dead server retry thresh */
+#define MNT2_NFS_OPT_DEADTHRESH 0x4000
 
-/* Define if you have the xdr_filename function.  */
-#define HAVE_XDR_FILENAME 1
+/* Dismount in progress */
+/* #undef MNT2_NFS_OPT_DISMINPROG */
 
-/* Define if you have the xdr_ftype function.  */
-#define HAVE_XDR_FTYPE 1
+/* Dismounted */
+/* #undef MNT2_NFS_OPT_DISMNT */
 
-/* Define if you have the xdr_groupnode function.  */
-#define HAVE_XDR_GROUPNODE 1
+/* Don't estimate rtt dynamically */
+#define MNT2_NFS_OPT_DUMBTIMR 0x800
 
-/* Define if you have the xdr_groups function.  */
-#define HAVE_XDR_GROUPS 1
+/* provide name of server's fs to system */
+/* #undef MNT2_NFS_OPT_FSNAME */
 
-/* Define if you have the xdr_linkargs function.  */
-#define HAVE_XDR_LINKARGS 1
+/* System V-style gid inheritance */
+/* #undef MNT2_NFS_OPT_GRPID */
 
-/* Define if you have the xdr_mntrequest function.  */
-/* #undef HAVE_XDR_MNTREQUEST */
+/* Has authenticator */
+/* #undef MNT2_NFS_OPT_HASAUTH */
 
-/* Define if you have the xdr_mntres function.  */
-/* #undef HAVE_XDR_MNTRES */
+/* set hostname for error printf */
+/* #undef MNT2_NFS_OPT_HOSTNAME */
 
-/* Define if you have the xdr_mountbody function.  */
-#define HAVE_XDR_MOUNTBODY 1
+/* ignore mount point */
+/* #undef MNT2_NFS_OPT_IGNORE */
 
-/* Define if you have the xdr_mountlist function.  */
-#define HAVE_XDR_MOUNTLIST 1
+/* allow interrupts on hard mount */
+#define MNT2_NFS_OPT_INT 0x40
 
-/* Define if you have the xdr_mountres3 function.  */
-/* #undef HAVE_XDR_MOUNTRES3 */
+/* Bits set internally */
+/* #undef MNT2_NFS_OPT_INTERNAL */
 
-/* Define if you have the xdr_name function.  */
-#define HAVE_XDR_NAME 1
+/* allow interrupts on hard mount */
+/* #undef MNT2_NFS_OPT_INTR */
 
-/* Define if you have the xdr_nfs_fh function.  */
-#define HAVE_XDR_NFS_FH 1
+/* Use Kerberos authentication */
+/* #undef MNT2_NFS_OPT_KERB */
 
-/* Define if you have the xdr_nfscookie function.  */
-#define HAVE_XDR_NFSCOOKIE 1
+/* use kerberos credentials */
+/* #undef MNT2_NFS_OPT_KERBEROS */
 
-/* Define if you have the xdr_nfspath function.  */
-#define HAVE_XDR_NFSPATH 1
+/* transport's knetconfig structure */
+/* #undef MNT2_NFS_OPT_KNCONF */
 
-/* Define if you have the xdr_nfsstat function.  */
-#define HAVE_XDR_NFSSTAT 1
+/* set lease term (nqnfs) */
+/* #undef MNT2_NFS_OPT_LEASETERM */
 
-/* Define if you have the xdr_nfstime function.  */
-#define HAVE_XDR_NFSTIME 1
+/* Local locking (no lock manager) */
+/* #undef MNT2_NFS_OPT_LLOCK */
 
-/* Define if you have the xdr_pointer function.  */
-#define HAVE_XDR_POINTER 1
+/* set maximum grouplist size */
+#define MNT2_NFS_OPT_MAXGRPS 0x20
 
-/* Define if you have the xdr_readargs function.  */
-#define HAVE_XDR_READARGS 1
+/* Mnt server for mnt point */
+/* #undef MNT2_NFS_OPT_MNTD */
 
-/* Define if you have the xdr_readdirargs function.  */
-#define HAVE_XDR_READDIRARGS 1
+/* Assume writes were mine */
+/* #undef MNT2_NFS_OPT_MYWRITE */
 
-/* Define if you have the xdr_readdirres function.  */
-#define HAVE_XDR_READDIRRES 1
+/* mount NFS Version 3 */
+#define MNT2_NFS_OPT_NFSV3 0x200
 
-/* Define if you have the xdr_readlinkres function.  */
-#define HAVE_XDR_READLINKRES 1
+/* don't cache attributes */
+/* #undef MNT2_NFS_OPT_NOAC */
 
-/* Define if you have the xdr_readokres function.  */
-#define HAVE_XDR_READOKRES 1
+/* Don't Connect the socket */
+#define MNT2_NFS_OPT_NOCONN 0x80
 
-/* Define if you have the xdr_readres function.  */
-#define HAVE_XDR_READRES 1
+/* no close-to-open consistency */
+/* #undef MNT2_NFS_OPT_NOCTO */
 
-/* Define if you have the xdr_renameargs function.  */
-#define HAVE_XDR_RENAMEARGS 1
+/* disallow interrupts on hard mounts */
+/* #undef MNT2_NFS_OPT_NOINT */
 
-/* Define if you have the xdr_sattr function.  */
-#define HAVE_XDR_SATTR 1
+/* Don't use locking */
+/* #undef MNT2_NFS_OPT_NONLM */
 
-/* Define if you have the xdr_sattrargs function.  */
-#define HAVE_XDR_SATTRARGS 1
+/* Get lease for lookup */
+/* #undef MNT2_NFS_OPT_NQLOOKLEASE */
 
-/* Define if you have the xdr_statfsokres function.  */
-#define HAVE_XDR_STATFSOKRES 1
+/* Use Nqnfs protocol */
+/* #undef MNT2_NFS_OPT_NQNFS */
 
-/* Define if you have the xdr_statfsres function.  */
-#define HAVE_XDR_STATFSRES 1
+/* paging threshold */
+/* #undef MNT2_NFS_OPT_PGTHRESH */
 
-/* Define if you have the xdr_symlinkargs function.  */
-#define HAVE_XDR_SYMLINKARGS 1
+/* static pathconf kludge info */
+/* #undef MNT2_NFS_OPT_POSIX */
 
-/* Define if you have the xdr_umntrequest function.  */
-/* #undef HAVE_XDR_UMNTREQUEST */
+/* Use local locking */
+/* #undef MNT2_NFS_OPT_PRIVATE */
 
-/* Define if you have the xdr_umntres function.  */
-/* #undef HAVE_XDR_UMNTRES */
+/* allow property list operations (ACLs over NFS) */
+/* #undef MNT2_NFS_OPT_PROPLIST */
 
-/* Define if you have the xdr_writeargs function.  */
-#define HAVE_XDR_WRITEARGS 1
+/* Rcv socket lock */
+/* #undef MNT2_NFS_OPT_RCVLOCK */
 
-/* Define if you have the yp_all function.  */
-/* #undef HAVE_YP_ALL */
+/* Do lookup with readdir (nqnfs) */
+/* #undef MNT2_NFS_OPT_RDIRALOOK */
 
-/* Define if you have the yp_get_default_domain function.  */
-#define HAVE_YP_GET_DEFAULT_DOMAIN 1
+/* Use Readdirplus for NFSv3 */
+#define MNT2_NFS_OPT_RDIRPLUS 0x10000
 
-/* Define if you have the <arpa/inet.h> header file.  */
-#define HAVE_ARPA_INET_H 1
+/* set read ahead */
+#define MNT2_NFS_OPT_READAHEAD 0x2000
 
-/* Define if you have the <arpa/nameser.h> header file.  */
-#define HAVE_ARPA_NAMESER_H 1
+/* Set readdir size */
+#define MNT2_NFS_OPT_READDIRSIZE 0x20000
 
-/* Define if you have the <assert.h> header file.  */
-#define HAVE_ASSERT_H 1
+/* Allocate a reserved port */
+#define MNT2_NFS_OPT_RESVPORT 0x8000
 
-/* Define if you have the <bsd/rpc/rpc.h> header file.  */
-/* #undef HAVE_BSD_RPC_RPC_H */
+/* set number of request retries */
+#define MNT2_NFS_OPT_RETRANS 0x10
 
-/* Define if you have the <cdfs/cdfs_mount.h> header file.  */
-/* #undef HAVE_CDFS_CDFS_MOUNT_H */
+/* read only */
+/* #undef MNT2_NFS_OPT_RONLY */
 
-/* Define if you have the <cdfs/cdfsmount.h> header file.  */
-/* #undef HAVE_CDFS_CDFSMOUNT_H */
+/* use RPC to do secure NFS time sync */
+/* #undef MNT2_NFS_OPT_RPCTIMESYNC */
 
-/* Define if you have the <cluster.h> header file.  */
-/* #undef HAVE_CLUSTER_H */
+/* set read size */
+#define MNT2_NFS_OPT_RSIZE 0x4
 
-/* Define if you have the <ctype.h> header file.  */
-#define HAVE_CTYPE_H 1
+/* secure mount */
+/* #undef MNT2_NFS_OPT_SECURE */
 
-/* Define if you have the <db1/ndbm.h> header file.  */
-/* #undef HAVE_DB1_NDBM_H */
+/* Send socket lock */
+/* #undef MNT2_NFS_OPT_SNDLOCK */
 
-/* Define if you have the <dirent.h> header file.  */
-#define HAVE_DIRENT_H 1
+/* soft mount (hard is default) */
+#define MNT2_NFS_OPT_SOFT 0x1
 
-/* Define if you have the <errno.h> header file.  */
-#define HAVE_ERRNO_H 1
+/* spongy mount */
+/* #undef MNT2_NFS_OPT_SPONGY */
 
-/* Define if you have the <fcntl.h> header file.  */
-#define HAVE_FCNTL_H 1
+/* set symlink cache time-to-live */
+/* #undef MNT2_NFS_OPT_SYMTTL */
 
-/* Define if you have the <grp.h> header file.  */
-#define HAVE_GRP_H 1
+/* use TCP for mounts */
+/* #undef MNT2_NFS_OPT_TCP */
 
-/* Define if you have the <hesiod.h> header file.  */
-/* #undef HAVE_HESIOD_H */
+/* set initial timeout */
+#define MNT2_NFS_OPT_TIMEO 0x8
 
-/* Define if you have the <hsfs/hsfs.h> header file.  */
-/* #undef HAVE_HSFS_HSFS_H */
+/* linux NFSv3 */
+/* #undef MNT2_NFS_OPT_VER3 */
 
-/* Define if you have the <ifaddrs.h> header file.  */
-/* #undef HAVE_IFADDRS_H */
+/* Wait for authentication */
+/* #undef MNT2_NFS_OPT_WAITAUTH */
 
-/* Define if you have the <irs.h> header file.  */
-/* #undef HAVE_IRS_H */
+/* Wants an authenticator */
+/* #undef MNT2_NFS_OPT_WANTAUTH */
 
-/* Define if you have the <isofs/cd9660/cd9660_mount.h> header file.  */
-#define HAVE_ISOFS_CD9660_CD9660_MOUNT_H 1
+/* Want receive socket lock */
+/* #undef MNT2_NFS_OPT_WANTRCV */
 
-/* Define if you have the <lber.h> header file.  */
-/* #undef HAVE_LBER_H */
+/* Want send socket lock */
+/* #undef MNT2_NFS_OPT_WANTSND */
 
-/* Define if you have the <ldap.h> header file.  */
-/* #undef HAVE_LDAP_H */
+/* set write size */
+#define MNT2_NFS_OPT_WSIZE 0x2
 
-/* Define if you have the <libgen.h> header file.  */
-/* #undef HAVE_LIBGEN_H */
+/* 32<->64 dir cookie translation */
+/* #undef MNT2_NFS_OPT_XLATECOOKIE */
 
-/* Define if you have the <linux/auto_fs.h> header file.  */
-/* #undef HAVE_LINUX_AUTO_FS_H */
+/* Force Win95 long names */
+#define MNT2_PCFS_OPT_LONGNAME 0x2
 
-/* Define if you have the <linux/fs.h> header file.  */
-/* #undef HAVE_LINUX_FS_H */
+/* Completely ignore Win95 entries */
+#define MNT2_PCFS_OPT_NOWIN95 0x4
 
-/* Define if you have the <linux/nfs.h> header file.  */
-/* #undef HAVE_LINUX_NFS_H */
+/* Force old DOS short names only */
+#define MNT2_PCFS_OPT_SHORTNAME 0x1
 
-/* Define if you have the <linux/nfs_mount.h> header file.  */
-/* #undef HAVE_LINUX_NFS_MOUNT_H */
+/* Name of mount table file name */
+/* #undef MNTTAB_FILE_NAME */
 
-/* Define if you have the <linux/posix_types.h> header file.  */
-/* #undef HAVE_LINUX_POSIX_TYPES_H */
+/* Mount Table option string: Max attr cache timeout (dirs) */
+/* #undef MNTTAB_OPT_ACDIRMAX */
 
-/* Define if you have the <machine/endian.h> header file.  */
-#define HAVE_MACHINE_ENDIAN_H 1
+/* Mount Table option string: Min attr cache timeout (dirs) */
+/* #undef MNTTAB_OPT_ACDIRMIN */
 
-/* Define if you have the <malloc.h> header file.  */
-/* #undef HAVE_MALLOC_H */
+/* Mount Table option string: Max attr cache timeout (files) */
+/* #undef MNTTAB_OPT_ACREGMAX */
 
-/* Define if you have the <memory.h> header file.  */
-#define HAVE_MEMORY_H 1
+/* Mount Table option string: Min attr cache timeout (files) */
+/* #undef MNTTAB_OPT_ACREGMIN */
 
-/* Define if you have the <mntent.h> header file.  */
-/* #undef HAVE_MNTENT_H */
+/* Mount Table option string: Attr cache timeout (sec) */
+/* #undef MNTTAB_OPT_ACTIMEO */
 
-/* Define if you have the <mnttab.h> header file.  */
-/* #undef HAVE_MNTTAB_H */
+/* Mount Table option string: Do mount retries in background */
+/* #undef MNTTAB_OPT_BG */
 
-/* Define if you have the <mount.h> header file.  */
-/* #undef HAVE_MOUNT_H */
+/* Mount Table option string: compress */
+/* #undef MNTTAB_OPT_COMPRESS */
 
-/* Define if you have the <msdosfs/msdosfsmount.h> header file.  */
-#define HAVE_MSDOSFS_MSDOSFSMOUNT_H 1
+/* Mount Table option string: Device id of mounted fs */
+/* #undef MNTTAB_OPT_DEV */
 
-/* Define if you have the <ndbm.h> header file.  */
-#define HAVE_NDBM_H 1
+/* Mount Table option string: Automount direct map mount */
+/* #undef MNTTAB_OPT_DIRECT */
 
-/* Define if you have the <ndir.h> header file.  */
-/* #undef HAVE_NDIR_H */
+/* Mount Table option string: Do mount retries in foreground */
+/* #undef MNTTAB_OPT_FG */
 
-/* Define if you have the <net/errno.h> header file.  */
-/* #undef HAVE_NET_ERRNO_H */
+/* Mount Table option string: Filesystem id of mounted fs */
+/* #undef MNTTAB_OPT_FSID */
 
-/* Define if you have the <net/if.h> header file.  */
-#define HAVE_NET_IF_H 1
+/* Mount Table option string: SysV-compatible gid on create */
+/* #undef MNTTAB_OPT_GRPID */
 
-/* Define if you have the <net/if_var.h> header file.  */
-#define HAVE_NET_IF_VAR_H 1
+/* Mount Table option string: Hard mount */
+/* #undef MNTTAB_OPT_HARD */
 
-/* Define if you have the <net/route.h> header file.  */
-#define HAVE_NET_ROUTE_H 1
+/* Mount Table option string: Ignore this entry */
+/* #undef MNTTAB_OPT_IGNORE */
 
-/* Define if you have the <netconfig.h> header file.  */
-/* #undef HAVE_NETCONFIG_H */
+/* Mount Table option string: Automount indirect map mount */
+/* #undef MNTTAB_OPT_INDIRECT */
 
-/* Define if you have the <netdb.h> header file.  */
-#define HAVE_NETDB_H 1
+/* Mount Table option string: Allow NFS ops to be interrupted */
+/* #undef MNTTAB_OPT_INTR */
 
-/* Define if you have the <netdir.h> header file.  */
-/* #undef HAVE_NETDIR_H */
+/* Mount Table option string: Secure (AUTH_Kerb) mounting */
+/* #undef MNTTAB_OPT_KERB */
 
-/* Define if you have the <netinet/if_ether.h> header file.  */
-#define HAVE_NETINET_IF_ETHER_H 1
+/* Mount Table option string: Local locking (no lock manager) */
+/* #undef MNTTAB_OPT_LLOCK */
 
-/* Define if you have the <netinet/in.h> header file.  */
-#define HAVE_NETINET_IN_H 1
+/* Force Win95 long names */
+/* #undef MNTTAB_OPT_LONGNAME */
 
-/* Define if you have the <nfs/export.h> header file.  */
-/* #undef HAVE_NFS_EXPORT_H */
+/* Mount Table option string: Automount map */
+/* #undef MNTTAB_OPT_MAP */
 
-/* Define if you have the <nfs/mount.h> header file.  */
-/* #undef HAVE_NFS_MOUNT_H */
+/* Mount Table option string: max groups */
+/* #undef MNTTAB_OPT_MAXGROUPS */
 
-/* Define if you have the <nfs/nfs.h> header file.  */
-#define HAVE_NFS_NFS_H 1
+/* Mount Table option string: Do multi-component lookup */
+/* #undef MNTTAB_OPT_MULTI */
 
-/* Define if you have the <nfs/nfs_clnt.h> header file.  */
-/* #undef HAVE_NFS_NFS_CLNT_H */
+/* Mount Table option string: Don't cache attributes at all */
+/* #undef MNTTAB_OPT_NOAC */
 
-/* Define if you have the <nfs/nfs_gfs.h> header file.  */
-/* #undef HAVE_NFS_NFS_GFS_H */
+/* Mount Table option string: No auto (what?) */
+/* #undef MNTTAB_OPT_NOAUTO */
 
-/* Define if you have the <nfs/nfs_mount.h> header file.  */
-/* #undef HAVE_NFS_NFS_MOUNT_H */
+/* Mount Table option string: No connection */
+/* #undef MNTTAB_OPT_NOCONN */
 
-/* Define if you have the <nfs/nfsmount.h> header file.  */
-#define HAVE_NFS_NFSMOUNT_H 1
+/* Mount Table option string: No close-to-open consistency */
+/* #undef MNTTAB_OPT_NOCTO */
 
-/* Define if you have the <nfs/nfsproto.h> header file.  */
-#define HAVE_NFS_NFSPROTO_H 1
+/* Mount Table option string: Don't allow interrupted ops */
+/* #undef MNTTAB_OPT_NOINTR */
 
-/* Define if you have the <nfs/nfsv2.h> header file.  */
-#define HAVE_NFS_NFSV2_H 1
+/* Mount Table option string: Don't check quotas */
+/* #undef MNTTAB_OPT_NOQUOTA */
 
-/* Define if you have the <nfs/pathconf.h> header file.  */
-/* #undef HAVE_NFS_PATHCONF_H */
+/* Mount Table option string: Do no allow setting sec attrs */
+/* #undef MNTTAB_OPT_NOSETSEC */
 
-/* Define if you have the <nfs/rpcv2.h> header file.  */
-#define HAVE_NFS_RPCV2_H 1
+/* Mount Table option string: Disallow mounts on subdirs */
+/* #undef MNTTAB_OPT_NOSUB */
 
-/* Define if you have the <nsswitch.h> header file.  */
-/* #undef HAVE_NSSWITCH_H */
+/* Mount Table option string: Set uid not allowed */
+/* #undef MNTTAB_OPT_NOSUID */
 
-/* Define if you have the <pwd.h> header file.  */
-#define HAVE_PWD_H 1
+/* Completely ignore Win95 entries */
+/* #undef MNTTAB_OPT_NOWIN95 */
 
-/* Define if you have the <regex.h> header file.  */
-#define HAVE_REGEX_H 1
+/* Mount Table option string: action to taken on error */
+/* #undef MNTTAB_OPT_ONERROR */
 
-/* Define if you have the <resolv.h> header file.  */
-#define HAVE_RESOLV_H 1
+/* Mount Table option string: paging threshold */
+/* #undef MNTTAB_OPT_PGTHRESH */
 
-/* Define if you have the <rpc/auth_des.h> header file.  */
-#define HAVE_RPC_AUTH_DES_H 1
+/* Mount Table option string: NFS server IP port number */
+/* #undef MNTTAB_OPT_PORT */
 
-/* Define if you have the <rpc/pmap_clnt.h> header file.  */
-#define HAVE_RPC_PMAP_CLNT_H 1
+/* Mount Table option string: Get static pathconf for mount */
+/* #undef MNTTAB_OPT_POSIX */
 
-/* Define if you have the <rpc/pmap_prot.h> header file.  */
-#define HAVE_RPC_PMAP_PROT_H 1
+/* Mount Table option string: Use local locking */
+/* #undef MNTTAB_OPT_PRIVATE */
 
-/* Define if you have the <rpc/rpc.h> header file.  */
-#define HAVE_RPC_RPC_H 1
+/* Mount Table option string: support property lists (ACLs) */
+/* #undef MNTTAB_OPT_PROPLIST */
 
-/* Define if you have the <rpc/types.h> header file.  */
-#define HAVE_RPC_TYPES_H 1
+/* Mount Table option string: protocol network_id indicator */
+/* #undef MNTTAB_OPT_PROTO */
 
-/* Define if you have the <rpc/xdr.h> header file.  */
-#define HAVE_RPC_XDR_H 1
+/* Mount Table option string: Check quotas */
+/* #undef MNTTAB_OPT_QUOTA */
 
-/* Define if you have the <rpcsvc/mount.h> header file.  */
-#define HAVE_RPCSVC_MOUNT_H 1
+/* Mount Table option string: Change mount options */
+/* #undef MNTTAB_OPT_REMOUNT */
 
-/* Define if you have the <rpcsvc/mountv3.h> header file.  */
-/* #undef HAVE_RPCSVC_MOUNTV3_H */
+/* Mount Table option string: Max retransmissions (soft mnts) */
+/* #undef MNTTAB_OPT_RETRANS */
 
-/* Define if you have the <rpcsvc/nfs_prot.h> header file.  */
-#define HAVE_RPCSVC_NFS_PROT_H 1
+/* Mount Table option string: Number of mount retries */
+/* #undef MNTTAB_OPT_RETRY */
 
-/* Define if you have the <rpcsvc/nis.h> header file.  */
-#define HAVE_RPCSVC_NIS_H 1
+/* Mount Table option string: Read only */
+/* #undef MNTTAB_OPT_RO */
 
-/* Define if you have the <rpcsvc/yp_prot.h> header file.  */
-#define HAVE_RPCSVC_YP_PROT_H 1
+/* Mount Table option string: Read/write with quotas */
+/* #undef MNTTAB_OPT_RQ */
 
-/* Define if you have the <rpcsvc/ypclnt.h> header file.  */
-#define HAVE_RPCSVC_YPCLNT_H 1
+/* Mount Table option string: Max NFS read size (bytes) */
+/* #undef MNTTAB_OPT_RSIZE */
 
-/* Define if you have the <setjmp.h> header file.  */
-#define HAVE_SETJMP_H 1
+/* Mount Table option string: Read/write */
+/* #undef MNTTAB_OPT_RW */
 
-/* Define if you have the <signal.h> header file.  */
-#define HAVE_SIGNAL_H 1
+/* Mount Table option string: Secure (AUTH_DES) mounting */
+/* #undef MNTTAB_OPT_SECURE */
 
-/* Define if you have the <socketbits.h> header file.  */
-/* #undef HAVE_SOCKETBITS_H */
+/* Force old DOS short names only */
+/* #undef MNTTAB_OPT_SHORTNAME */
 
-/* Define if you have the <statbuf.h> header file.  */
-/* #undef HAVE_STATBUF_H */
+/* Mount Table option string: Soft mount */
+/* #undef MNTTAB_OPT_SOFT */
 
-/* Define if you have the <stdarg.h> header file.  */
-#define HAVE_STDARG_H 1
+/* Mount Table option string: spongy mount */
+/* #undef MNTTAB_OPT_SPONGY */
 
-/* Define if you have the <stdio.h> header file.  */
-#define HAVE_STDIO_H 1
+/* Mount Table option string: Set uid allowed */
+/* #undef MNTTAB_OPT_SUID */
 
-/* Define if you have the <stdlib.h> header file.  */
-#define HAVE_STDLIB_H 1
+/* Mount Table option string: set symlink cache time-to-live */
+/* #undef MNTTAB_OPT_SYMTTL */
 
-/* Define if you have the <string.h> header file.  */
-#define HAVE_STRING_H 1
+/* Mount Table option string: Synchronous local directory ops */
+/* #undef MNTTAB_OPT_SYNCDIR */
 
-/* Define if you have the <strings.h> header file.  */
-#define HAVE_STRINGS_H 1
+/* Mount Table option string: NFS timeout (1/10 sec) */
+/* #undef MNTTAB_OPT_TIMEO */
 
-/* Define if you have the <sys/config.h> header file.  */
-/* #undef HAVE_SYS_CONFIG_H */
+/* Mount Table option string: min. time between inconsistencies */
+/* #undef MNTTAB_OPT_TOOSOON */
 
-/* Define if you have the <sys/dg_mount.h> header file.  */
-/* #undef HAVE_SYS_DG_MOUNT_H */
+/* Mount Table option string: protocol version number indicator */
+/* #undef MNTTAB_OPT_VERS */
 
-/* Define if you have the <sys/dir.h> header file.  */
-/* #undef HAVE_SYS_DIR_H */
+/* Mount Table option string: Max NFS write size (bytes) */
+/* #undef MNTTAB_OPT_WSIZE */
 
-/* Define if you have the <sys/errno.h> header file.  */
-#define HAVE_SYS_ERRNO_H 1
+/* Mount-table entry name for AUTOFS filesystem */
+/* #undef MNTTAB_TYPE_AUTOFS */
 
-/* Define if you have the <sys/file.h> header file.  */
-#define HAVE_SYS_FILE_H 1
+/* Mount-table entry name for CACHEFS filesystem */
+/* #undef MNTTAB_TYPE_CACHEFS */
 
-/* Define if you have the <sys/fs/autofs.h> header file.  */
-/* #undef HAVE_SYS_FS_AUTOFS_H */
+/* Mount-table entry name for CDFS filesystem */
+#define MNTTAB_TYPE_CDFS "cd9660"
 
-/* Define if you have the <sys/fs/autofs_prot.h> header file.  */
-/* #undef HAVE_SYS_FS_AUTOFS_PROT_H */
+/* Mount-table entry name for CFS (crypto) filesystem */
+/* #undef MNTTAB_TYPE_CFS */
 
-/* Define if you have the <sys/fs/cachefs_fs.h> header file.  */
-/* #undef HAVE_SYS_FS_CACHEFS_FS_H */
+/* Mount-table entry name for EFS filesystem (irix) */
+/* #undef MNTTAB_TYPE_EFS */
 
-/* Define if you have the <sys/fs/efs_clnt.h> header file.  */
-/* #undef HAVE_SYS_FS_EFS_CLNT_H */
+/* Mount-table entry name for FFS filesystem */
+/* #undef MNTTAB_TYPE_FFS */
 
-/* Define if you have the <sys/fs/nfs.h> header file.  */
-/* #undef HAVE_SYS_FS_NFS_H */
+/* Mount-table entry name for LOFS filesystem */
+/* #undef MNTTAB_TYPE_LOFS */
 
-/* Define if you have the <sys/fs/nfs/mount.h> header file.  */
-/* #undef HAVE_SYS_FS_NFS_MOUNT_H */
+/* Mount-table entry name for MFS filesystem */
+/* #undef MNTTAB_TYPE_MFS */
 
-/* Define if you have the <sys/fs/nfs/nfs_clnt.h> header file.  */
-/* #undef HAVE_SYS_FS_NFS_NFS_CLNT_H */
+/* Mount-table entry name for NFS filesystem */
+#define MNTTAB_TYPE_NFS "nfs"
 
-/* Define if you have the <sys/fs/nfs_clnt.h> header file.  */
-/* #undef HAVE_SYS_FS_NFS_CLNT_H */
+/* Mount-table entry name for NFS3 filesystem */
+#define MNTTAB_TYPE_NFS3 "nfs3"
 
-/* Define if you have the <sys/fs/pc_fs.h> header file.  */
-/* #undef HAVE_SYS_FS_PC_FS_H */
+/* Mount-table entry name for NULLFS (loopback on bsd44) filesystem */
+#define MNTTAB_TYPE_NULLFS "nullfs"
 
-/* Define if you have the <sys/fs/tmp.h> header file.  */
-/* #undef HAVE_SYS_FS_TMP_H */
+/* Mount-table entry name for PCFS filesystem */
+#define MNTTAB_TYPE_PCFS "msdosfs"
 
-/* Define if you have the <sys/fs/ufs_mount.h> header file.  */
-/* #undef HAVE_SYS_FS_UFS_MOUNT_H */
+/* Mount-table entry name for TFS filesystem */
+/* #undef MNTTAB_TYPE_TFS */
 
-/* Define if you have the <sys/fs/xfs_clnt.h> header file.  */
-/* #undef HAVE_SYS_FS_XFS_CLNT_H */
+/* Mount-table entry name for TMPFS filesystem */
+/* #undef MNTTAB_TYPE_TMPFS */
 
-/* Define if you have the <sys/fs_types.h> header file.  */
-/* #undef HAVE_SYS_FS_TYPES_H */
+/* Mount-table entry name for UFS filesystem */
+#define MNTTAB_TYPE_UFS "ufs"
 
-/* Define if you have the <sys/fsid.h> header file.  */
-/* #undef HAVE_SYS_FSID_H */
+/* Mount-table entry name for UMAPFS (uid/gid mapping) filesystem */
+/* #undef MNTTAB_TYPE_UMAPFS */
 
-/* Define if you have the <sys/fstyp.h> header file.  */
-/* #undef HAVE_SYS_FSTYP_H */
+/* Mount-table entry name for UNIONFS filesystem */
+#define MNTTAB_TYPE_UNIONFS "unionfs"
 
-/* Define if you have the <sys/ioctl.h> header file.  */
-#define HAVE_SYS_IOCTL_H 1
+/* Mount-table entry name for XFS filesystem (irix) */
+/* #undef MNTTAB_TYPE_XFS */
 
-/* Define if you have the <sys/lock.h> header file.  */
-#define HAVE_SYS_LOCK_H 1
+/* Define if mount table is on file, undefine if in kernel */
+/* #undef MOUNT_TABLE_ON_FILE */
 
-/* Define if you have the <sys/machine.h> header file.  */
-/* #undef HAVE_SYS_MACHINE_H */
+/* Mount(2) type/name for AUTOFS filesystem */
+/* #undef MOUNT_TYPE_AUTOFS */
 
-/* Define if you have the <sys/mbuf.h> header file.  */
-#define HAVE_SYS_MBUF_H 1
+/* Mount(2) type/name for CACHEFS filesystem */
+/* #undef MOUNT_TYPE_CACHEFS */
 
-/* Define if you have the <sys/mntctl.h> header file.  */
-/* #undef HAVE_SYS_MNTCTL_H */
+/* Mount(2) type/name for CDFS filesystem */
+#define MOUNT_TYPE_CDFS "cd9660"
 
-/* Define if you have the <sys/mntent.h> header file.  */
-/* #undef HAVE_SYS_MNTENT_H */
+/* Mount(2) type/name for CFS (crypto) filesystem */
+/* #undef MOUNT_TYPE_CFS */
 
-/* Define if you have the <sys/mnttab.h> header file.  */
-/* #undef HAVE_SYS_MNTTAB_H */
+/* Mount(2) type/name for EFS filesystem (irix) */
+/* #undef MOUNT_TYPE_EFS */
 
-/* Define if you have the <sys/mount.h> header file.  */
-#define HAVE_SYS_MOUNT_H 1
+/* Mount(2) type/name for FFS filesystem */
+/* #undef MOUNT_TYPE_FFS */
 
-/* Define if you have the <sys/ndir.h> header file.  */
-/* #undef HAVE_SYS_NDIR_H */
+/* Mount(2) type/name for IGNORE filesystem (not real just ignore for df) */
+#define MOUNT_TYPE_IGNORE MNT_IGNORE
 
-/* Define if you have the <sys/netconfig.h> header file.  */
-/* #undef HAVE_SYS_NETCONFIG_H */
+/* Mount(2) type/name for LOFS filesystem */
+/* #undef MOUNT_TYPE_LOFS */
 
-/* Define if you have the <sys/param.h> header file.  */
-#define HAVE_SYS_PARAM_H 1
+/* Mount(2) type/name for MFS filesystem */
+/* #undef MOUNT_TYPE_MFS */
 
-/* Define if you have the <sys/pathconf.h> header file.  */
-/* #undef HAVE_SYS_PATHCONF_H */
+/* Mount(2) type/name for NFS filesystem */
+#define MOUNT_TYPE_NFS "nfs"
 
-/* Define if you have the <sys/proc.h> header file.  */
-#define HAVE_SYS_PROC_H 1
+/* Mount(2) type/name for NFS3 filesystem */
+#define MOUNT_TYPE_NFS3 MOUNT_NFS3
 
-/* Define if you have the <sys/resource.h> header file.  */
-#define HAVE_SYS_RESOURCE_H 1
+/* Mount(2) type/name for NULLFS (loopback on bsd44) filesystem */
+#define MOUNT_TYPE_NULLFS "nullfs"
 
-/* Define if you have the <sys/sema.h> header file.  */
-/* #undef HAVE_SYS_SEMA_H */
+/* Mount(2) type/name for PCFS filesystem. XXX: conf/trap/trap_hpux.h may
+   override this definition for HPUX 9.0 */
+#define MOUNT_TYPE_PCFS "msdosfs"
 
-/* Define if you have the <sys/signal.h> header file.  */
-#define HAVE_SYS_SIGNAL_H 1
+/* Mount(2) type/name for TFS filesystem */
+/* #undef MOUNT_TYPE_TFS */
 
-/* Define if you have the <sys/socket.h> header file.  */
-#define HAVE_SYS_SOCKET_H 1
+/* Mount(2) type/name for TMPFS filesystem */
+/* #undef MOUNT_TYPE_TMPFS */
 
-/* Define if you have the <sys/sockio.h> header file.  */
-#define HAVE_SYS_SOCKIO_H 1
+/* Mount(2) type/name for UFS filesystem */
+#define MOUNT_TYPE_UFS "ufs"
 
-/* Define if you have the <sys/stat.h> header file.  */
-#define HAVE_SYS_STAT_H 1
+/* Mount(2) type/name for UMAPFS (uid/gid mapping) filesystem */
+/* #undef MOUNT_TYPE_UMAPFS */
 
-/* Define if you have the <sys/statfs.h> header file.  */
-/* #undef HAVE_SYS_STATFS_H */
+/* Mount(2) type/name for UNIONFS filesystem */
+#define MOUNT_TYPE_UNIONFS MNT_UNION
 
-/* Define if you have the <sys/syscall.h> header file.  */
-#define HAVE_SYS_SYSCALL_H 1
+/* Mount(2) type/name for XFS filesystem (irix) */
+/* #undef MOUNT_TYPE_XFS */
 
-/* Define if you have the <sys/syslimits.h> header file.  */
-#define HAVE_SYS_SYSLIMITS_H 1
+/* The string used in printf to print the mount-type field of mount(2) */
+#define MTYPE_PRINTF_TYPE "%s"
 
-/* Define if you have the <sys/syslog.h> header file.  */
-#define HAVE_SYS_SYSLOG_H 1
+/* Type of the mount-type field in the mount() system call */
+#define MTYPE_TYPE char *
 
-/* Define if you have the <sys/time.h> header file.  */
-#define HAVE_SYS_TIME_H 1
+/* does libwrap expect caller to define the variables allow_severity and
+   deny_severity */
+/* #undef NEED_LIBWRAP_SEVERITY_VARIABLES */
 
-/* Define if you have the <sys/tiuser.h> header file.  */
-/* #undef HAVE_SYS_TIUSER_H */
+/* Defined to the header file containing ndbm-compatible definitions */
+#define NEW_DBM_H <ndbm.h>
 
-/* Define if you have the <sys/types.h> header file.  */
-#define HAVE_SYS_TYPES_H 1
+/* Define the field name for the filehandle within nfs_args_t */
+#define NFS_FH_FIELD fh
 
-/* Define if you have the <sys/ucred.h> header file.  */
-#define HAVE_SYS_UCRED_H 1
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
 
-/* Define if you have the <sys/uio.h> header file.  */
-#define HAVE_SYS_UIO_H 1
+/* Name of package */
+#define PACKAGE "am-utils"
 
-/* Define if you have the <sys/utsname.h> header file.  */
-#define HAVE_SYS_UTSNAME_H 1
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "https://bugzilla.am-utils.org/ or am-utils@am-utils.org"
 
-/* Define if you have the <sys/vfs.h> header file.  */
-/* #undef HAVE_SYS_VFS_H */
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "am-utils"
 
-/* Define if you have the <sys/vmount.h> header file.  */
-/* #undef HAVE_SYS_VMOUNT_H */
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "am-utils 6.1.5"
 
-/* Define if you have the <sys/vnode.h> header file.  */
-#define HAVE_SYS_VNODE_H 1
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "am-utils"
 
-/* Define if you have the <syslog.h> header file.  */
-#define HAVE_SYSLOG_H 1
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "6.1.5"
 
-/* Define if you have the <time.h> header file.  */
-#define HAVE_TIME_H 1
+/* Type of the 6th argument to recvfrom() */
+#define RECVFROM_FROMLEN_TYPE int
 
-/* Define if you have the <tiuser.h> header file.  */
-/* #undef HAVE_TIUSER_H */
+/* should signal handlers be reinstalled? */
+/* #undef REINSTALL_SIGNAL_HANDLER */
 
-/* Define if you have the <tmpfs/tmp.h> header file.  */
-/* #undef HAVE_TMPFS_TMP_H */
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
 
-/* Define if you have the <vfs/ufs/ufsmount.h> header file.  */
-#define HAVE_UFS_UFS_UFSMOUNT_H 1
+/* Define to 1 if the `setpgrp' function takes no argument. */
+/* #undef SETPGRP_VOID */
 
-/* Define if you have the <vfs/ufs_mount.h> header file.  */
-#define HAVE_UFS_UFS_MOUNT_H 1
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
 
-/* Define if you have the <unistd.h> header file.  */
-#define HAVE_UNISTD_H 1
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
 
-/* Define if you have the <varargs.h> header file.  */
-#define HAVE_VARARGS_H 1
+/* Define the type of the 3rd argument ('in') to svc_getargs() */
+#define SVC_IN_ARG_TYPE caddr_t
 
-/* Define if you have the <vfork.h> header file.  */
-/* #undef HAVE_VFORK_H */
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
 
-/* Define if you have the gdbm library (-lgdbm).  */
-/* #undef HAVE_LIBGDBM */
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
 
-/* Define if you have the malloc library (-lmalloc).  */
-/* #undef HAVE_LIBMALLOC */
+/* Define user name */
+/* #define USER_NAME "obrien" */
 
-/* Define if you have the mapmalloc library (-lmapmalloc).  */
-/* #undef HAVE_LIBMAPMALLOC */
+/* define if must NOT use NFS "noconn" option */
+#define USE_CONNECTED_NFS_SOCKETS 1
 
-/* Define if you have the nsl library (-lnsl).  */
-/* #undef HAVE_LIBNSL */
+/* define if must use NFS "noconn" option */
+/* #undef USE_UNCONNECTED_NFS_SOCKETS */
 
-/* Define if you have the rpc library (-lrpc).  */
-/* #undef HAVE_LIBRPC */
+/* Version number of package */
+#define VERSION "6.1.5"
 
-/* Define if you have the rpcsvc library (-lrpcsvc).  */
-#define HAVE_LIBRPCSVC 1
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
 
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef pid_t */
+/* Define to the type of xdr procedure type */
+#define XDRPROC_T_TYPE xdrproc_t
 
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef mode_t */
+/* Type of the 3rd argument to yp_order() */
+#define YP_ORDER_OUTORDER_TYPE int
 
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef pid_t */
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#define YYTEXT_POINTER 1
 
-/* Define to `unsigned' if <sys/types.h> does not define. */
-/* #undef size_t */
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* # undef _ALL_SOURCE */
+#endif
 
-/* Define to `long' if <sys/types.h> does not define. */
-/* #undef time_t */
+/* Define a type/structure for an NFS V2 filehandle */
+#define am_nfs_fh nfs_fh
 
+/* Define a type/structure for an NFS V3 filehandle */
+#define am_nfs_fh3 nfs_fh3_freebsd3
 
-/**************************************************************************/
-/*** Everything below this line is part of the "BOTTOM" of acconfig.h.	***/
-/**************************************************************************/
+/* Define a type for the autofs_args structure */
+/* #undef autofs_args_t */
 
-/*
- * Existence of external definitions.
- */
+/* Define a type for the cachefs_args structure */
+/* #undef cachefs_args_t */
 
-/* does extern definition for sys_errlist[] exist? */
-#define HAVE_EXTERN_SYS_ERRLIST 1
+/* Define a type for the cdfs_args structure */
+#define cdfs_args_t struct iso_args
 
-/* does extern definition for optarg exist? */
-#define HAVE_EXTERN_OPTARG 1
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
 
-/* does extern definition for clnt_spcreateerror() exist? */
-#define HAVE_EXTERN_CLNT_SPCREATEERROR 1
+/* Define a type for the efs_args structure */
+/* #undef efs_args_t */
 
-/* does extern definition for clnt_sperrno() exist? */
-#define HAVE_EXTERN_CLNT_SPERRNO 1
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
 
-/* does extern definition for free() exist? */
-#define HAVE_EXTERN_FREE 1
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
 
-/* does extern definition for get_myaddress() exist? */
-#define HAVE_EXTERN_GET_MYADDRESS 1
+/* Define a type for the lofs_args structure */
+/* #undef lofs_args_t */
 
-/* does extern definition for getccent() (hpux) exist? */
-/* #undef HAVE_EXTERN_GETCCENT */
+/* Define a type for the mfs_args structure */
+/* #undef mfs_args_t */
 
-/* does extern definition for getdomainname() exist? */
-#define HAVE_EXTERN_GETDOMAINNAME 1
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef mode_t */
 
-/* does extern definition for gethostname() exist? */
-#define HAVE_EXTERN_GETHOSTNAME 1
+/* Define a type for the nfs_args structure */
+#define nfs_args_t struct nfs_args
 
-/* does extern definition for getlogin() exist? */
-#define HAVE_EXTERN_GETLOGIN 1
+/* Define a type for the pcfs_args structure */
+#define pcfs_args_t struct msdosfs_args
 
-/* does extern definition for gettablesize() exist? */
-/* #undef HAVE_EXTERN_GETTABLESIZE */
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
 
-/* does extern definition for getpagesize() exist? */
-#define HAVE_EXTERN_GETPAGESIZE 1
+/* Check if pte_t is defined in <sys/immu.h> */
+/* #undef pte_t */
 
-/* does extern definition for innetgr() exist? */
-#define HAVE_EXTERN_INNETGR
+/* Define a type for the rfs_args structure */
+/* #undef rfs_args_t */
 
-/* does extern definition for mkstemp() exist? */
-#define HAVE_EXTERN_MKSTEMP 1
+/* Check if rpcvers_t is defined in <rpc/types.h> */
+/* #undef rpcvers_t */
 
-/* does extern definition for sbrk() exist? */
-#define HAVE_EXTERN_SBRK 1
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
 
-/* does extern definition for seteuid() exist? */
-#define HAVE_EXTERN_SETEUID 1
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef time_t */
 
-/* does extern definition for setitimer() exist? */
-#define HAVE_EXTERN_SETITIMER 1
+/* Define a type for the tmpfs_args structure */
+/* #undef tmpfs_args_t */
 
-/* does extern definition for strcasecmp() exist? */
-#define HAVE_EXTERN_STRCASECMP 1
+/* Define a type for the ufs_args structure */
+#define ufs_args_t struct ufs_args
 
-/* does extern definition for strdup() exist? */
-#define HAVE_EXTERN_STRDUP 1
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
 
-/* does extern definition for strstr() exist? */
-#define HAVE_EXTERN_STRSTR 1
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
 
-/* does extern definition for usleep() exist? */
-#define HAVE_EXTERN_USLEEP 1
+/* Define to "void *" if compiler can handle, otherwise "char *" */
+#define voidp void *
 
-/* does extern definition for wait3() exist? */
-#define HAVE_EXTERN_WAIT3 1
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+   code using `volatile' can become incorrect without. Disable with care. */
+/* #undef volatile */
 
-/* does extern definition for vsnprintf() exist? */
-#define HAVE_EXTERN_VSNPRINTF 1
+/* Define a type for the xfs_args structure */
+/* #undef xfs_args_t */
 
-/* does extern definition for xdr_opaque_auth() exist? */
-#define HAVE_EXTERN_XDR_OPAQUE_AUTH 1
 
 /****************************************************************************/
 /*** INCLUDE localconfig.h if it exists, to allow users to make some      ***/
diff --git a/usr.sbin/amd/include/newvers.sh b/usr.sbin/amd/include/newvers.sh
index f6e6a8e..cfe5e49 100644
--- a/usr.sbin/amd/include/newvers.sh
+++ b/usr.sbin/amd/include/newvers.sh
@@ -1,34 +1,43 @@
 #	$NetBSD: mkconf,v 1.1.1.1 1997/07/24 21:20:12 christos Exp $
-# $FreeBSD: src/usr.sbin/amd/include/newvers.sh,v 1.3 1999/08/28 01:15:16 peter Exp $
-# $DragonFly: src/usr.sbin/amd/include/newvers.sh,v 1.2 2003/06/17 04:29:52 dillon Exp $
+# $FreeBSD: src/usr.sbin/amd/include/newvers.sh,v 1.11 2012/11/17 01:54:36 svnexp Exp $
 # mkconf
 # Generate local configuration parameters for amd
 #
-cat << __EOF
-
-/* Define name of host machine's cpu (eg. sparc) */
-/* #define HOST_CPU "`uname -p`" */
-#define HOST_CPU "`uname -m`"
 
-/* Define name of host machine's architecture (eg. sun4) */
-#define HOST_ARCH "`uname -m`"
+if [ -e $1 ]; then
+	eval `LC_ALL=C egrep '^[A-Z]+=' $1 | grep -v COPYRIGHT`
+	OS=`echo ${TYPE} | LC_ALL=C tr 'A-Z' 'a-z'`
+	echo '/* Define name and version of host machine (eg. solaris2.5.1) */'
+	echo "#define HOST_OS \"${OS}${REVISION}\""
+	echo '/* Define only name of host machine OS (eg. solaris2) */'
+	echo "#define HOST_OS_NAME \"${OS}${REVISION}\"" \
+		| sed -e 's/\.[-._0-9]*//'
+	echo '/* Define only version of host machine (eg. 2.5.1) */'
+	echo "#define HOST_OS_VERSION \"${REVISION}\""
+else
+cat << __NO_newvers_sh
 
 /* Define name and version of host machine (eg. solaris2.5.1) */
-#define HOST_OS "`uname -s | tr '[A-Z]' '[a-z]'``uname -r`"
+#define HOST_OS "`uname -s | LC_ALL=C tr 'A-Z' 'a-z'``uname -r`"
 
 /* Define only name of host machine OS (eg. solaris2) */
-#define HOST_OS_NAME "`uname -s | tr '[A-Z]' '[a-z]'``uname -r | sed -e 's/\..*$//'`"
+#define HOST_OS_NAME "`uname -s | LC_ALL=C tr 'A-Z' 'a-z'``uname -r | sed -e 's/\..*$//'`"
 
 /* Define only version of host machine (eg. 2.5.1) */
-#define HOST_OS_VERSION "`uname -r`"
+#define HOST_OS_VERSION "`uname -r | sed -e 's/[-([:alpha:]].*//'`"
+
+__NO_newvers_sh
+fi
+
+cat << __EOF
 
 /* Define name of host */
-#define HOST_NAME "`hostname`"
+#define BUILD_HOST "`hostname`"
 
 /* Define user name */
-#define USER_NAME "`whoami`"
+#define BUILD_USER "`whoami`"
 
 /* Define configuration date */
-#define CONFIG_DATE "`date`"
+#define BUILD_DATE "`LC_ALL=C date`"
 
 __EOF
diff --git a/usr.sbin/amd/libamu/Makefile b/usr.sbin/amd/libamu/Makefile
index ff7d5eb..2caa4d5 100644
--- a/usr.sbin/amd/libamu/Makefile
+++ b/usr.sbin/amd/libamu/Makefile
@@ -3,30 +3,34 @@
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998
 #
-# $FreeBSD: src/usr.sbin/amd/libamu/Makefile,v 1.4.2.1 2002/07/19 18:46:29 ru Exp $
-# $DragonFly: src/usr.sbin/amd/libamu/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
+# $FreeBSD: src/usr.sbin/amd/libamu/Makefile,v 1.10 2012/11/17 01:54:36 svnexp Exp $
 
-.PATH:		${.CURDIR}/../../../contrib/amd/libamu \
-		${.CURDIR}/../../../contrib/amd/conf/transp \
-		${.CURDIR}/../../../contrib/amd/conf/mtab \
-		${.CURDIR}/../../../contrib/amd/conf/umount
+.PATH: ${.CURDIR}/../../../contrib/amd/libamu \
+       ${.CURDIR}/../../../contrib/amd/conf/transp \
+       ${.CURDIR}/../../../contrib/amd/conf/mtab \
+       ${.CURDIR}/../../../contrib/amd/conf/umount
 
-LIB=		amu
-INTERNALLIB=	YES
+LIB=	amu
+INTERNALLIB=
+SRCS=	hasmntopt.c misc_rpc.c mount_fs.c mtab.c nfs_prot_xdr.c \
+	strutil.c wire.c xutil.c
 
-SRCS=		hasmntopt.c misc_rpc.c mount_fs.c mtab.c nfs_prot_xdr.c \
-		util.c wire.c xutil.c
-
-#		These would be links created by the GNU-style configure
-SRCS+=		transp_sockets.c mtab_bsd.c umount_bsd44.c
-
-CFLAGS+=	-I${.CURDIR}/../../../contrib/amd/libamu
+#	These would be links created by the GNU-style configure
+SRCS+=	transp_sockets.c mtab_bsd.c umount_bsd44.c
 
 #		Generated at compile time (replaces supplied xdr_func.c)
-SRCS+=		nfs_prot_x.c
-CLEANFILES+=	nfs_prot_x.c
+SRCS+=		nfs_prot_x.c xdr_func_%undef.c
+CLEANFILES+=	nfs_prot_x.c xdr_func_%undef.c
+
+CFLAGS+= -I${.CURDIR}/../../../contrib/amd/libamu \
+	 -I${DESTDIR}/usr/include/rpcsvc
 
 nfs_prot_x.c: ${NFS_PROT_X}
-	${RPCCOM} -c -DWANT_NFS3 ${NFS_PROT_X} -o ${.TARGET}
+	${RPCCOM} -c -C -DWANT_NFS3 ${NFS_PROT_X} -o ${.TARGET}
+
+XDRDEFS!= grep 'ifndef.*HAVE_XDR' ${.CURDIR}/../../../contrib/amd/libamu/xdr_func.c | awk '{print "-D"$$2}'
+
+xdr_func_%undef.c: xdr_func.c
+	-unifdef ${XDRDEFS} < ${.ALLSRC} > ${.TARGET}
 
 .include <bsd.lib.mk>
diff --git a/usr.sbin/amd/mk-amd-map/Makefile b/usr.sbin/amd/mk-amd-map/Makefile
index 8546298..0a4da58 100644
--- a/usr.sbin/amd/mk-amd-map/Makefile
+++ b/usr.sbin/amd/mk-amd-map/Makefile
@@ -3,13 +3,14 @@
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998
 #
-# $FreeBSD: src/usr.sbin/amd/mk-amd-map/Makefile,v 1.10.2.1 2001/04/25 12:09:15 ru Exp $
-# $DragonFly: src/usr.sbin/amd/mk-amd-map/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
-#
+# $FreeBSD: src/usr.sbin/amd/mk-amd-map/Makefile,v 1.17 2012/11/17 01:54:36 svnexp Exp $
+
+.PATH: ${.CURDIR}/../../../contrib/amd/mk-amd-map
 
-.PATH:		${.CURDIR}/../../../contrib/amd/mk-amd-map
+PROG=	mk-amd-map
+MAN=	mk-amd-map.8
 
-PROG=		mk-amd-map
-MAN=		mk-amd-map.8
+DPADD=	${LIBAMU}
+LDADD=	${LIBAMU}
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/amd/pawd/Makefile b/usr.sbin/amd/pawd/Makefile
index df134d9..e9cc2b6 100644
--- a/usr.sbin/amd/pawd/Makefile
+++ b/usr.sbin/amd/pawd/Makefile
@@ -3,20 +3,18 @@
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998
 #
-# $FreeBSD: src/usr.sbin/amd/pawd/Makefile,v 1.3.2.1 2001/04/25 12:09:15 ru Exp $
-# $DragonFly: src/usr.sbin/amd/pawd/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
-#
+# $FreeBSD: src/usr.sbin/amd/pawd/Makefile,v 1.6 2012/11/17 01:54:36 svnexp Exp $
 
-.PATH:		${.CURDIR}/../../../contrib/amd/amq
+.PATH: ${.CURDIR}/../../../contrib/amd/amq
 
-BINDIR=		/usr/bin
+BINDIR=	/usr/bin
 
-PROG=		pawd
-SRCS=		pawd.c amq_clnt.c amq_xdr.c
+PROG=	pawd
+SRCS=	pawd.c amq_clnt.c amq_xdr.c
 
-CFLAGS+=	-I${.CURDIR}/../../../contrib/amd/amq
+CFLAGS+= -I${.CURDIR}/../../../contrib/amd/amq
 
-DPADD+=		${LIBAMU}
-LDADD+=		${LIBAMU}
+DPADD=	${LIBAMU}
+LDADD=	${LIBAMU}
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/amd/scripts/Makefile b/usr.sbin/amd/scripts/Makefile
index ad56eb3..9a22c57 100644
--- a/usr.sbin/amd/scripts/Makefile
+++ b/usr.sbin/amd/scripts/Makefile
@@ -1,8 +1,7 @@
-# $FreeBSD: src/usr.sbin/amd/scripts/Makefile,v 1.2.2.1 2001/04/25 12:09:16 ru Exp $
-# $DragonFly: src/usr.sbin/amd/scripts/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
+# $FreeBSD: src/usr.sbin/amd/scripts/Makefile,v 1.5 2012/11/17 01:54:36 svnexp Exp $
 
-.PATH:		${.CURDIR}/../../../contrib/amd/scripts
+.PATH: ${.CURDIR}/../../../contrib/amd/scripts
 
-MAN=		amd.conf.5
+MAN=	amd.conf.5
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/amd/wire-test/Makefile b/usr.sbin/amd/wire-test/Makefile
index 63d1d62..1d4908f 100644
--- a/usr.sbin/amd/wire-test/Makefile
+++ b/usr.sbin/amd/wire-test/Makefile
@@ -3,16 +3,14 @@
 # Makefile for amd
 # 	This file is under a "BSD" copyright (c) by David O'Brien 1998
 #
-# $FreeBSD: src/usr.sbin/amd/wire-test/Makefile,v 1.3.2.1 2001/04/25 12:09:16 ru Exp $
-# $DragonFly: src/usr.sbin/amd/wire-test/Makefile,v 1.2 2003/06/17 04:29:52 dillon Exp $
-#
+# $FreeBSD: src/usr.sbin/amd/wire-test/Makefile,v 1.9 2012/11/17 01:54:36 svnexp Exp $
 
-.PATH:		${.CURDIR}/../../../contrib/amd/wire-test
+.PATH: ${.CURDIR}/../../../contrib/amd/wire-test
 
-PROG=		wire-test
-MAN=		wire-test.8
+PROG=	wire-test
+MAN=	wire-test.8
 
-DPADD+=		${LIBAMU}
-LDADD+=		${LIBAMU}
+DPADD=	${LIBAMU}
+LDADD=	${LIBAMU}
 
 .include <bsd.prog.mk>
-- 
1.7.7.2

