[Midnightbsd-cvs] src [11011] trunk/contrib/amd: sync with freebsd

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri Jun 15 18:31:16 EDT 2018


Revision: 11011
          http://svnweb.midnightbsd.org/src/?rev=11011
Author:   laffer1
Date:     2018-06-15 18:31:15 -0400 (Fri, 15 Jun 2018)
Log Message:
-----------
sync with freebsd

Modified Paths:
--------------
    trunk/contrib/amd/AUTHORS
    trunk/contrib/amd/BUGS
    trunk/contrib/amd/COPYING
    trunk/contrib/amd/ChangeLog
    trunk/contrib/amd/FAQ
    trunk/contrib/amd/FREEBSD-Xlist
    trunk/contrib/amd/FREEBSD-upgrade
    trunk/contrib/amd/INSTALL
    trunk/contrib/amd/MIRRORS.html
    trunk/contrib/amd/MIRRORS.txt
    trunk/contrib/amd/NEWS
    trunk/contrib/amd/README
    trunk/contrib/amd/README.attrcache
    trunk/contrib/amd/README.ldap
    trunk/contrib/amd/README.y2k
    trunk/contrib/amd/amd/am_ops.c
    trunk/contrib/amd/amd/amd.8
    trunk/contrib/amd/amd/amd.c
    trunk/contrib/amd/amd/amd.h
    trunk/contrib/amd/amd/amfs_auto.c
    trunk/contrib/amd/amd/amfs_direct.c
    trunk/contrib/amd/amd/amfs_error.c
    trunk/contrib/amd/amd/amfs_generic.c
    trunk/contrib/amd/amd/amfs_host.c
    trunk/contrib/amd/amd/amfs_link.c
    trunk/contrib/amd/amd/amfs_linkx.c
    trunk/contrib/amd/amd/amfs_nfsl.c
    trunk/contrib/amd/amd/amfs_nfsx.c
    trunk/contrib/amd/amd/amfs_program.c
    trunk/contrib/amd/amd/amfs_root.c
    trunk/contrib/amd/amd/amfs_toplvl.c
    trunk/contrib/amd/amd/amfs_union.c
    trunk/contrib/amd/amd/amq_subr.c
    trunk/contrib/amd/amd/amq_svc.c
    trunk/contrib/amd/amd/autil.c
    trunk/contrib/amd/amd/clock.c
    trunk/contrib/amd/amd/conf.c
    trunk/contrib/amd/amd/conf_parse.y
    trunk/contrib/amd/amd/conf_tok.l
    trunk/contrib/amd/amd/get_args.c
    trunk/contrib/amd/amd/info_exec.c
    trunk/contrib/amd/amd/info_file.c
    trunk/contrib/amd/amd/info_hesiod.c
    trunk/contrib/amd/amd/info_ldap.c
    trunk/contrib/amd/amd/info_ndbm.c
    trunk/contrib/amd/amd/info_nis.c
    trunk/contrib/amd/amd/info_nisplus.c
    trunk/contrib/amd/amd/info_passwd.c
    trunk/contrib/amd/amd/info_union.c
    trunk/contrib/amd/amd/map.c
    trunk/contrib/amd/amd/mapc.c
    trunk/contrib/amd/amd/mntfs.c
    trunk/contrib/amd/amd/nfs_prot_svc.c
    trunk/contrib/amd/amd/nfs_start.c
    trunk/contrib/amd/amd/nfs_subr.c
    trunk/contrib/amd/amd/ops_TEMPLATE.c
    trunk/contrib/amd/amd/ops_cachefs.c
    trunk/contrib/amd/amd/ops_cdfs.c
    trunk/contrib/amd/amd/ops_efs.c
    trunk/contrib/amd/amd/ops_lofs.c
    trunk/contrib/amd/amd/ops_mfs.c
    trunk/contrib/amd/amd/ops_nfs.c
    trunk/contrib/amd/amd/ops_nfs3.c
    trunk/contrib/amd/amd/ops_nullfs.c
    trunk/contrib/amd/amd/ops_pcfs.c
    trunk/contrib/amd/amd/ops_tfs.c
    trunk/contrib/amd/amd/ops_tmpfs.c
    trunk/contrib/amd/amd/ops_ufs.c
    trunk/contrib/amd/amd/ops_umapfs.c
    trunk/contrib/amd/amd/ops_unionfs.c
    trunk/contrib/amd/amd/ops_xfs.c
    trunk/contrib/amd/amd/opts.c
    trunk/contrib/amd/amd/readdir.c
    trunk/contrib/amd/amd/restart.c
    trunk/contrib/amd/amd/rpc_fwd.c
    trunk/contrib/amd/amd/sched.c
    trunk/contrib/amd/amd/srvr_amfs_auto.c
    trunk/contrib/amd/amd/srvr_nfs.c
    trunk/contrib/amd/amq/amq.8
    trunk/contrib/amd/amq/amq.c
    trunk/contrib/amd/amq/amq.h
    trunk/contrib/amd/amq/amq_clnt.c
    trunk/contrib/amd/amq/amq_xdr.c
    trunk/contrib/amd/amq/pawd.1
    trunk/contrib/amd/amq/pawd.c
    trunk/contrib/amd/bootstrap
    trunk/contrib/amd/conf/checkmount/checkmount_bsd44.c
    trunk/contrib/amd/conf/mtab/mtab_bsd.c
    trunk/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h
    trunk/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h
    trunk/contrib/amd/conf/transp/transp_sockets.c
    trunk/contrib/amd/conf/trap/trap_default.h
    trunk/contrib/amd/conf/umount/umount_bsd44.c
    trunk/contrib/amd/doc/am-utils.texi
    trunk/contrib/amd/doc/stamp-vti
    trunk/contrib/amd/doc/texinfo.tex
    trunk/contrib/amd/doc/version.texi
    trunk/contrib/amd/fixmount/fixmount.8
    trunk/contrib/amd/fixmount/fixmount.c
    trunk/contrib/amd/fsinfo/fsi_analyze.c
    trunk/contrib/amd/fsinfo/fsi_data.h
    trunk/contrib/amd/fsinfo/fsi_dict.c
    trunk/contrib/amd/fsinfo/fsi_gram.y
    trunk/contrib/amd/fsinfo/fsi_lex.l
    trunk/contrib/amd/fsinfo/fsi_util.c
    trunk/contrib/amd/fsinfo/fsinfo.8
    trunk/contrib/amd/fsinfo/fsinfo.c
    trunk/contrib/amd/fsinfo/fsinfo.h
    trunk/contrib/amd/fsinfo/wr_atab.c
    trunk/contrib/amd/fsinfo/wr_bparam.c
    trunk/contrib/amd/fsinfo/wr_dumpset.c
    trunk/contrib/amd/fsinfo/wr_exportfs.c
    trunk/contrib/amd/fsinfo/wr_fstab.c
    trunk/contrib/amd/hlfsd/hlfsd.8
    trunk/contrib/amd/hlfsd/hlfsd.c
    trunk/contrib/amd/hlfsd/hlfsd.h
    trunk/contrib/amd/hlfsd/homedir.c
    trunk/contrib/amd/hlfsd/nfs_prot_svc.c
    trunk/contrib/amd/hlfsd/stubs.c
    trunk/contrib/amd/include/am_compat.h
    trunk/contrib/amd/include/am_defs.h
    trunk/contrib/amd/include/am_utils.h
    trunk/contrib/amd/include/am_xdr_func.h
    trunk/contrib/amd/include/amq_defs.h
    trunk/contrib/amd/include/mount_headers1.h
    trunk/contrib/amd/include/mount_headers2.h
    trunk/contrib/amd/ldap-id.ms
    trunk/contrib/amd/ldap-id.txt
    trunk/contrib/amd/libamu/amu.h
    trunk/contrib/amd/libamu/hasmntopt.c
    trunk/contrib/amd/libamu/misc_rpc.c
    trunk/contrib/amd/libamu/mount_fs.c
    trunk/contrib/amd/libamu/mtab.c
    trunk/contrib/amd/libamu/nfs_prot_xdr.c
    trunk/contrib/amd/libamu/strerror.c
    trunk/contrib/amd/libamu/strutil.c
    trunk/contrib/amd/libamu/wire.c
    trunk/contrib/amd/libamu/xdr_func.c
    trunk/contrib/amd/libamu/xutil.c
    trunk/contrib/amd/mk-amd-map/mk-amd-map.8
    trunk/contrib/amd/mk-amd-map/mk-amd-map.c
    trunk/contrib/amd/scripts/amd.conf-sample
    trunk/contrib/amd/scripts/amd.conf.5
    trunk/contrib/amd/scripts/automount2amd.8
    trunk/contrib/amd/scripts/automount2amd.in
    trunk/contrib/amd/scripts/expn.1
    trunk/contrib/amd/scripts/expn.in
    trunk/contrib/amd/scripts/fixrmtab.in
    trunk/contrib/amd/vers.m4
    trunk/contrib/amd/wire-test/wire-test.8
    trunk/contrib/amd/wire-test/wire-test.c

Modified: trunk/contrib/amd/AUTHORS
===================================================================
--- trunk/contrib/amd/AUTHORS	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/AUTHORS	2018-06-15 22:31:15 UTC (rev 11011)
@@ -6,22 +6,22 @@
 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 at cs.sunysb.edu>
+* Erez Zadok <ezk AT 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.
 
-* Ion Badulescu <ion at cs.columbia.edu>
+* Ion Badulescu <ion AT 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 at glue.umd.edu>
+* Randall S. Winchester <rsw AT glue.umd.edu>
 
 May 7, 1997: contributed a special version of upl102 that included NFS V.3
 support.  Some of the code was contributed by Christos Zoulas
-<christos at deshaw.com>.  I (Erez) ported these changes to am-utils.
+<christos AT deshaw.com>.  I (Erez) ported these changes to am-utils.
 
 September 12, 1997: lots of small prototype cleanups and fixes to numerous
 files.
@@ -35,12 +35,12 @@
 
 September 4, 1999: assorted fixes for NetBSD 1.4+.
 
-* Hannes Reinecke <hare at MathI.UNI-Heidelberg.DE>
+* Hannes Reinecke <hare AT MathI.UNI-Heidelberg.DE>
 
 Back in 1995, contributed code for linux.  A new parser for file system
 specific options that only exist under linux.
 
-* Leif Johansson <leifj at matematik.su.se>
+* Leif Johansson <leifj AT matematik.su.se>
 
 June 22, 1997: minor patch to ensure that systems without an RE library work.
 
@@ -52,7 +52,7 @@
 August 4, 1997: info_ldap.c fixes and adding two new amd.conf ldap
 variables: ldap_cache_seconds and ldap_cache_maxmem.
 
-* Andreas Stolcke <stolcke at speech.sri.com>
+* Andreas Stolcke <stolcke AT speech.sri.com>
 
 June 22, 1997: patches to ensure that proto= and vers= options work
 properly in mount tables and can be overridden.  Later on, more code
@@ -68,11 +68,11 @@
 December 19, 1997: detected an FMR (Free Memory Read) in amd/mntfs.c,
 uninit_mntfs().
 
-* Danny Braniss <danny at cs.huji.ac.il>
+* Danny Braniss <danny AT cs.huji.ac.il>
 
 July, 6 1997: contributed patches to hesiod on bsdi3.
 
-* Tom Schmidt <tschmidt at micron.com>
+* Tom Schmidt <tschmidt AT micron.com>
 
 July 10, 1997: Recommdation to include libgdbm if libc has no dbm_open.
 Patches for netgrp(host) command.  Mods to aux/config.guess to recognize
@@ -86,7 +86,7 @@
 
 May 30, 2000: correct logging types for addopts/mergeopts messages.
 
-* Daniel S. Riley  <dsr at mail.lns.cornell.edu>
+* Daniel S. Riley  <dsr AT mail.lns.cornell.edu>
 
 July 11, 1997: fixes to DU-4.0 to support string POSIX.1 signals, and struct
 sockaddr with sa_len field.
@@ -99,15 +99,15 @@
 August 15, 1998: fix memory leak in processing of /defaults, and avoid
 accessing uninitialized memory in osf1.
 
-* Roman Hodek <Roman.Hodek at informatik.uni-erlangen.de>
+* Roman Hodek <Roman.Hodek AT informatik.uni-erlangen.de>
 
 July 23, 1997: Got lots of patches from the Debian Linux folks, who fixed
 several generic bugs, and one serious one for Linux.  The latter involved
 using connected sockets for NFS mounts on kernels 1.3.10 and older.  Roman's
-work is baed on amd-upl102, and work from Ian Murdock <imurdock at debian.org>
-and Dominik Kubla <dominik at debian.org>.
+work is baed on amd-upl102, and work from Ian Murdock <imurdock AT debian.org>
+and Dominik Kubla <dominik AT debian.org>.
 
-* Rainer Orth <ro at TechFak.Uni-Bielefeld.DE>
+* Rainer Orth <ro AT TechFak.Uni-Bielefeld.DE>
 
 August 6, 1997: assorted fixes to support hesiod-1.3, solaris 2.4 (which I
 already fixed but did not release yet), and support for $LDFLAGS at
@@ -132,34 +132,34 @@
 February 9, 2000: new debug options hrtime (hi-res timer) and xdrtrace.  bug
 fixes.
 
-* Jason Thorpe <thorpej at nas.nasa.gov>
+* Jason Thorpe <thorpej AT nas.nasa.gov>
 
 August 25, 1997: make amd work when talking to NIS+ servers in NIS
 compatibility mode.  Fix originally came from Matthieu Herrb
-<matthieu at laas.fr>.
+<matthieu AT laas.fr>.
 
-* Chris Metcalf <metcalf at catfish.lcs.mit.edu>
+* Chris Metcalf <metcalf AT catfish.lcs.mit.edu>
 
 August 29, 1997: patch to make amd use FQHN for NFS/RPC authentication,
 useful esp. for cross-domain NFS mounts.
 September 2, 1997: if plock() succeeded, don't display errno string.
 
-* Enami Tsugutomo <enami at cv.sony.co.jp>
+* Enami Tsugutomo <enami AT cv.sony.co.jp>
 
 September 4, 1997: don't ping remote servers with NFS V.3 always, but V.2,
 regardless of client's NFS version. (conf/transp/transp_sockets.c)
 
-* Dan Riley <dsr at mail.lns.cornell.edu>
+* Dan Riley <dsr AT mail.lns.cornell.edu>
 
 September 19, 1997: make sure that amd works with more secure portmappers
 that do not allow forwarding of RPC messages to other services.
 
-* Wolfgang Rupprecht <wolfgang at wsrcc.com>
+* Wolfgang Rupprecht <wolfgang AT wsrcc.com>
 
 August 10, 1997: netbsd and other bsd systems have a mask flag for
 pcfs_args (msdos mount).
 
-* Christos Zoulas <christos at zoulas.com>
+* Christos Zoulas <christos AT zoulas.com>
 
 September 25, 1997: fix to initialize uid/gid fields of pcfs_args_t on
 netbsd.
@@ -181,7 +181,7 @@
 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 at ctr.columbia.edu>
+* Bill Paul <wpaul AT ctr.columbia.edu>
 
 November 5, 1997: NFS v.3 support for AIX 4.2.1, which does *not* include
 headers for this.  Bill had to guess at the right structures, field names,
@@ -189,26 +189,26 @@
 
 January 15, 1999: small ldap bug fixes.
 
-* Stefan Vogel <vogel at physik-rzu.unizh.ch>
+* Stefan Vogel <vogel AT physik-rzu.unizh.ch>
 
 November 14, 1997: typo in the subscription instructions to amd-dev.
 
-* Guntram Wolski <gwolsk at sei.com>
+* Guntram Wolski <gwolsk AT sei.com>
 
 November 15, 1997: pointed out mismatching documentation for the -o option.
 
-* Michael Hucka <hucka at eecs.umich.edu>
+* Michael Hucka <hucka AT eecs.umich.edu>
 
 January 11, 1997: pointed out reversed definition of NFS mount options vers
 and proto.
 
-* Albert Chin <china at pprd.abbott.com>
+* Albert Chin <china AT pprd.abbott.com>
 
 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 at chemie.fu-berlin.de>
+* Thomas Richter <richter AT chemie.fu-berlin.de>
 
 January 13, 1998: use case insensitive comparisons for variables that need
 it (such as all hostname related ones, and more).
@@ -216,11 +216,11 @@
 July 20, 1998: don't leak memory in the private version of yp_all (when
 vendor yp_all is bad).
 
-* Fred Korz <korz at smarts.com>
+* Fred Korz <korz AT smarts.com>
 
 January 30, 1998: minor typo fixed to tftp example in am-utils.texi.
 
-* Donald Buczek <buczek at MPIMG-Berlin-Dahlem.MPG.DE>
+* Donald Buczek <buczek AT MPIMG-Berlin-Dahlem.MPG.DE>
 
 March 6, 1998: correctly inherit existing NFS V.3 mounts upon restart.
 
@@ -230,11 +230,11 @@
 allow startup script to redirect it.  Set a temporary secure umask(0022)
 before writing log file and restore it afterwards.
 
-* Matthew Crosby <mcrosby at ms.com>
+* Matthew Crosby <mcrosby AT ms.com>
 
 April 20, 1998: allow arbitrary number of interfaces in wire listing.
 
-* David O'Brien <obrien at NUXI.com>
+* David O'Brien <obrien AT NUXI.com>
 
 September 4, 1998: bug fix to avoid overrunning hostname buffer, and minor
 amd.conf man page typo correction.
@@ -241,25 +241,25 @@
 
 September 22, 1999: use more secure vsnprintf in real_plog().
 
-* Danny Rathjens <dkr at cs.fiu.edu>
+* Danny Rathjens <dkr AT cs.fiu.edu>
 
 October 29, 1998: swap arguments to kill(2) in amd.c.
 
-* Mike Mitchell <mcm at unx.sas.com>
+* Mike Mitchell <mcm AT unx.sas.com>
 
 November 3, 1998: 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.
 
-* Douglas K. Rand" <rand at aero.und.edu>
+* Douglas K. Rand" <rand AT aero.und.edu>
 
 December 3, 1998: case insensitive host name match for nfsl.
 
-* David Wolfskill <dhw at whistle.com>
+* David Wolfskill <dhw AT whistle.com>
 January 28, 1999: don't turn on/off noconn option if it was already in that
 state.
 
-* Jeffrey C Honig <jch at BSDI.COM>
+* Jeffrey C Honig <jch AT BSDI.COM>
 March 14, 1999: clean up more autogenerated files upon "make distclean".
 
 March 15, 1999: avoid overly verbose NIS warning even on systems that don't
@@ -271,30 +271,30 @@
 
 September 17, 1999: fixes to expn.
 
-* Paul Balyoz <pbalyoz at sedona.ch.intel.com>
+* Paul Balyoz <pbalyoz AT sedona.ch.intel.com>
 March 26, 1999: ensure lostaltmail displays Y2K compliant dates.
 
-* Jon Peatfield <J.S.Peatfield at damtp.cam.ac.uk>
+* Jon Peatfield <J.S.Peatfield AT damtp.cam.ac.uk>
 March 30, 1999: turn off incomplete NFS V.3 support in HPUX 10.20.
 
 September 22, 1999: safe reloading of maps without first clearing old
 copies, and using cached copies if map failed to reload.
 
-* Peter Breitenlohner <peb at mppmu.mpg.de>
+* Peter Breitenlohner <peb AT 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 at quest.cc.purdue.edu>
+* Dale Talcott <aeh AT quest.cc.purdue.edu>
 July 26, 1999: added NFS3 support for AIX mounting.
 
-* Christophe Kalt <Christophe-Kalt at deshaw.com>
+* Christophe Kalt <Christophe-Kalt AT deshaw.com>
 July 14, 1999: add netgrpd() syntax function which uses FQHN.
 
-* Andrew J. Korty <ajk at purdue.edu>
+* Andrew J. Korty <ajk AT purdue.edu>
 September 5, 1999: pawd works for type:=nfsl.
 
-* Nick Williams <njw at ms.com>
+* Nick Williams <njw AT ms.com>
 September 1, 1999: bug fix for incorrect symlinks when two locations are
 requested simultaneously.
 
@@ -306,20 +306,20 @@
 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 at germany.agfa.com>
+* Johann Pfefferl <johann.pfefferl.jp AT germany.agfa.com>
 November 16, 1999: fix to ldap code so repeated calls to string2he don't
 corrupt the string passed.
 
-* Amitha Perera <perera at cs.rpi.edu>
+* Amitha Perera <perera AT cs.rpi.edu>
 December 9, 1999: detect all wire() interfaces correctly.
 
-* Steven Danz <sdanz at awc.kc.noaa.gov>
+* Steven Danz <sdanz AT awc.kc.noaa.gov>
 January 25, 2000: allow browsable auto maps.
 
-* Wolfram Klaus	<klaus at physik.fu-berlin.de>.
+* Wolfram Klaus	<klaus AT physik.fu-berlin.de>.
 November 21, 2000: recognize proplist mnttab flag.
 
-* Thomas Klausner <tk at giga.or.at>
+* Thomas Klausner <tk AT 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.
@@ -326,18 +326,18 @@
 
 November 28, 2004: small fixes to typos in amd.conf(5) man page.
 
-* Olaf Kirch <okir at caldera.de>
+* Olaf Kirch <okir AT caldera.de>
 February 1, 2001: important Linux NFS error number mapping fixed
 
-* Ahmon Dancy <dancy at franz.com>
+* Ahmon Dancy <dancy AT franz.com>
 February 9, 2001: Apple Rhapsody/Darwin/OS X port
 
-* Sebastien Bahloul <sebastien.bahloul at mangoosta.fr>
+* Sebastien Bahloul <sebastien.bahloul AT 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 at fifi.org>
+* Philippe Troin <phil AT 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.
@@ -348,51 +348,51 @@
 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 at fys.uio.no>
+* Trond Myklebust <trond.myklebust AT 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 at dcs.ed.ac.uk>
+* George Ross <gdmr AT 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 at inf.ed.ac.uk>).
+protocol version parameter (with Tim Colles <timc AT inf.ed.ac.uk>).
 
-* Matthias Scheler <tron at zhadum.de>
+* Matthias Scheler <tron AT zhadum.de>
 June 14, 2002: patch to use "xlatecookie" NFS mount option.
 
-* Jun-ichiro itojun Hagino <itojun at iijlab.net>.
+* Jun-ichiro itojun Hagino <itojun AT iijlab.net>.
 June 11, 2002: minor fixes to support NetBSD 1.6A.
 
-* Sean Fagan <sef at apple.com>
+* Sean Fagan <sef AT apple.com>
 March 14, 2003: detect and use the MNT2_GEN_OPT_AUTOMNTFS mount flag
 on OS X / Darwin.
 
-* Hendrik Scholz <hscholz at raisdorf.net>
+* Hendrik Scholz <hscholz AT raisdorf.net>
 June 9, 2003: mk-amd-map should open temp db file using O_EXCL.
 
-* Mark Davies <mark at mcs.vuw.ac.nz>
+* Mark Davies <mark AT 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 at thyrsus.com>
+* Eric S. Raymond <esr AT thyrsus.com>
 December 9, 2003: fix unbalanced [] typo in fsinfo man page.
 
-* Martin Blapp <mb at imp.ch>
+* Martin Blapp <mb AT imp.ch>
 July 6, 2004: recognize fields in pcfs_args_t in FreeBSD 5.
 
-* Dan Nelson <dnelson at allantgroup.com>
+* Dan Nelson <dnelson AT allantgroup.com>
 August 2, 2004: pawd to recognize "host" type mounts.
 
-* Hauke Fath <hauke at Espresso.Rhein-Neckar.DE>
+* Hauke Fath <hauke AT Espresso.Rhein-Neckar.DE>
 August 3, 2004: pawd to recognize "linkx" type mounts.
 
-* Michael van Elst <M.van.Elst at science-computing.de>
+* Michael van Elst <M.van.Elst AT science-computing.de>
 September 1, 2004: bug fix to avoid race condition in calls to mntctl on
 AIX.
 
-* Jonathan Chen <jon+amd at spock.org>
+* Jonathan Chen <jon+amd AT 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.
@@ -399,14 +399,14 @@
 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 at ucl.ac.uk>
+* David Rage <rage AT 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 at franz.com>
+* Kevin Layer <layer AT franz.com>
 January 28, 2005: basic instructions how to setup Amd on Mac OS-X.
 
-* Dan Ottavio <dottavio at ic.sunysb.edu>
+* Dan Ottavio <dottavio AT 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
@@ -415,7 +415,7 @@
 * Erik Kline <ekline at ekline dot com>
 January 3, 2005: implementation of executable maps for Amd.
 
-* Jim Zajkowski <jim.zajkowski at gmail.com>
+* Jim Zajkowski <jim.zajkowski AT gmail.com>
 March 14, 2005: small patch to amd2ldif.
 
 * Adam Morley <adam at gmi dot com>
@@ -422,9 +422,6 @@
 January 27, 2005: synchronize what amd2ldif does vs. what the ldap.schema
 expects.
 
-* Graeme Wilford <G.Wilford at surrey.ac.uk>
+* Graeme Wilford <G.Wilford AT surrey.ac.uk>
 July 4, 2005: buffer overflow in pawd.
 
-* Steve Plite <splite-amutils at sigint.cs.purdue.edu>
-September 22, 2005: repair reversed meaning of D_AMQ, so amq will unregister
-on exit.

Modified: trunk/contrib/amd/BUGS
===================================================================
--- trunk/contrib/amd/BUGS	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/BUGS	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,7 +1,7 @@
 	    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 at am-utils.org mailing list.
+by email to the am-utils mailing list (see www.am-utils.org).
 
 
 (1) mips-sgi-irix*
@@ -98,11 +98,11 @@
 
 (4) powerpc-ibm-aix4.2.1.0
 
-[4A] "Randall S. Winchester" <rsw at Glue.umd.edu> reports that for amd to
+[4A] "Randall S. Winchester" <rsw AT Glue.umd.edu> reports that for amd to
 start, you need to kill and restart rpc.mountd and possibly also make sure
 that nfsd is running.  Normally these are not required.
 
-[4B] "Stefan Vogel" <vogel at physik.unizh.ch> reports that if your amq
+[4B] "Stefan Vogel" <vogel AT physik.unizh.ch> reports that if your amq
 executable dump core unexpectedly, then it may be a bug in gcc 2.7.x.
 Upgrade to gcc 2.8.x or use IBM's xlC compiler.
 
@@ -123,7 +123,7 @@
 
 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 am-utils at am-utils.org know if you know of a fix.)
+time.  (Please let us know if you have a fix; see www.am-utils.org.)
 
 
 (7) *-aix4.3.2.0

Modified: trunk/contrib/amd/COPYING
===================================================================
--- trunk/contrib/amd/COPYING	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/COPYING	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,4 +1,4 @@
-Copyright (c) 1997-2006 Erez Zadok
+Copyright (c) 1997-2014 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.
@@ -15,12 +15,7 @@
 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, as well as the Trustees of
-     Columbia University.
-4. Neither the name of the University nor the names of its contributors
+3. 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.
 

Modified: trunk/contrib/amd/ChangeLog
===================================================================
--- trunk/contrib/amd/ChangeLog	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/ChangeLog	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,14 +1,564 @@
-2006-05-11  Erez Zadok  <ezk at cs.sunysb.edu>
+2014-10-28  Christos Zoulas <christos at zoulas.com>
 
 	*******************************************************************
-	*** Released am-utils-6.1.5					***
+	*** Released am-utils-6.2					***
 	*******************************************************************
 
-2006-05-10  Erez Zadok  <ezk at cs.sunysb.edu>
+	* add ylwrap.amd, sick and tired of patching broken ylwrap.
 
-	* Minor new ports: i386-unknown-freebsd6.1 (RELEASE)
+2014-09-05  Christos Zoulas <christos at zoulas.com>
+
+	* factor out the size check for both readdir methods
+	  (raven at themaw.net)
+
+2014-09-03  Christos Zoulas <christos at zoulas.com>
+
+	* configure test for 64 bit xdr function (raven at themaw.net)
+
+2014-09-01  Christos Zoulas <christos at zoulas.com>
+
+	* bug fix from raven at themaw.net to prevent writing v3 handle
+	  to a v2 structure.
+
+2014-07-21  Christos Zoulas <christos at zoulas.com>
+
+	* fix permission problems with access
+	* auto_nfs_version = 3 now works for me.
+
+2014-07-20  Christos Zoulas <christos at zoulas.com>
+
+	* refresh some autoconf files
+	* force autoconf version since earlier versions don't work
+	* changes from raven at themaw.net to support NFSv3 for automounted
+	  toplevel filesystems presented to the list in May. A few bug fixes
+	  and integration changes by me. The code now works well enough to
+	  mount the filesystem with NFSv3 and automount children but readdir
+	  does not work yet (so no listing of automounted filesystems).
+	  The new code is not enabled by default. To enable use
+		auto_nfs_version = 3
+	  in your configuration file.
+
+2014-03-26  Christos Zoulas <christos at zoulas.com>
+
+	From Ian Kent <ikent at redhat.com>
+
+	* use mktemp in scripts/fixrmtab
+	* fix documentatio nits
+	* [linux] Add ext2, ext3, ext4 specific mount options
+	* fix tcpwrappers (hosts.{allow,deny} problems for specific host
+	  entries
+
+2014-03-20  Christos Zoulas <christos at zoulas.com>
+
+
+	* don't background autofs umount
+	* avoid fh NULL dereference on umount
+	* handle ENOENT umount return for autofs mounts
+	* fix error message in get_nfs_version
+	* fix debug log deadlock
+	* [linux] retry umount on EBUSY
+	* handle failed umount on exit
+
+2014-03-09  Christos Zoulas <christos at zoulas.com>
+
+	* Remove BSD advertising clause.
+	* Remove expn program which is not used by anything
+
+2013-12-05  Christos Zoulas <christos at zoulas.com>
+
+	* Change the way we handle multiple lex scanners and yacc parsers
+	  in a single program. Our old patch to ylwrap does not work anymore
+	  because the bison parsers need shared symbols that start with yy
+	  and we can't easily select which ones work. So now we use -P and
+	  -p to let lex and yacc do the work for us. This requires a patch
+	  to ylwrap, but it is smaller.
+
+
+2013-12-05  Christos Zoulas <christos at zoulas.com>
+
+	* Change the way we handle multiple lex scanners and yacc parsers
+	  in a single program. Our old patch to ylwrap does not work anymore
+	  because the bison parsers need shared symbols that start with yy
+	  and we can't easily select which ones work. So now we use -P and
+	  -p to let lex and yacc do the work for us. This requires a patch
+	  to ylwrap, but it is smaller.
+
+2013-05-14  Christos Zoulas <christos at zoulas.com>
+
+	* update to handle new autoconf and regen files
+
+2012-11-23  Christos Zoulas <christos at zoulas.com>
+
+	* recognize mountport=, noacl options
+	* simplify the bootstrap process, by forcing
+	  all the files to be rebuild with autoreconf -f - i
+
+2012-10-03  Christos Zoulas <christos at zoulas.com>
+
+	* add missing ops_nfs4.c to the Makefile.am
+
+2012-09-14  Christos Zoulas <christos at zoulas.com>
+
+	* add locking option handling for lustre
+	* fix noatime, nodiratime, mandlock for linux
+
+2012-07-25  Christos Zoulas <christos at zoulas.com>
+
+	* bug fixes for lustre rhost parsing
+
+2012-06-27  Christos Zoulas <christos at zoulas.com>
+
+	* Disable 1/2-baked sun map support to avoid SIGSEGV
+
+2012-06-16  Christos Zoulas <christos at zoulas.com>
+
+	*******************************************************************
+	*** Released am-utils-6.2-rc1					***
+	*******************************************************************
+
+	* Fix libtool.m4 to work with later versions of autoconf.
+	* In buildall, use eval so that quoted strings work
+	* Centralize nfs version checking function, and introduce
+	  new configuration variable nfs_vers_ping, which is the
+	  max version we ping for. This is not documented yet, because
+	  there might be a better way separate the max version we can
+	  use vs the max version we ping for.
+
+2012-06-09  Christos Zoulas <christos at zoulas.com>
+
+	* fix issue with parsing nfsv4 security option strings
+
+2012-05-01  Christos Zoulas <christos at zoulas.com>
+
+	* Handle EPERM return from v4 file handles
+	  in old linux kernels
+
+2012-03-09  Christos Zoulas <christos at zoulas.com>
+
+	* fix linux autofs detection
+	* fix wrong types in new amq mount xdr processing
+
+2012-01-25  Christos Zoulas <christos at zoulas.com>
+
+	* FreeBSD portability fixes
+
+2012-01-23  Christos Zoulas <christos at zoulas.com>
+
+	* Avoid type punned warnings
+
+2011-12-29  Christos Zoulas <christos at zoulas.com>
+
+	* fix bug I introduced in get_nfs_version that caused it to return 0
+	* add direct support for ext{2,3,4}
+
+2011-12-15  Christos Zoulas <christos at zoulas.com>
+
+	* Include <linux/fs.h> on linux, to grab extra mount flags
+	* Add support for lustre
+
+2011-11-28  Christos Zoulas <christos at zoulas.com>
+
+	* For nfsl mounts, match against either the short local
+	  host name or the fqdn name.
+
+2011-10-06  Christos Zoulas <christos at zoulas.com>
+
+	* Add NFSv4 support (loosely based on Ramya's code).
+	  Currently if the NFSv4 mount fails with ENOENT we fail
+	  back to NFSv3, unless -DNO_FALLBACK.
+	* Replace strdup with xstrdup. It is not nice to replace
+	  system functions with ones that behave differently.
+	* Add various consistency checks (caller function checks
+	  variable for NULL, but callee does not).
+	* Fix error handling in various paths.
+	* Don't check before using XFREE(). free(NULL) works.
+
+2011-09-15  Christos Zoulas <christos at zoulas.com>
+
+	* amq -i addition (prints info about the map files)
+
+2011-09-14  Christos Zoulas <christos at zoulas.com>
+
+	* Solaris OS and compiler fixes from:
+		Hofmann, Frank <Frank.Hofmann at morganstanley.com>
+		Sayle, Alex <Alex.Sayle at morganstanley.com>
+	  - (void)&var generates warnings, removed
+	  - __inline is invalid, changed with inline
+	  - <sys/socket.h> and other headers have extra dependendcies
+			`
+2011-08-11  Christos Zoulas <christos at zoulas.com>
+
+	* fix potential buffer overflow in expand_error()
+	  (Richard Kettlewell). Does not seem to be exploitable.
+
+	* simplify %option parsing to appease ancient flex.
+
+2011-06-21  Christos Zoulas <christos at zoulas.com>
+
+	* add support for linux autofs version 5 (untested)
+
+2011-06-18  Christos Zoulas <christos at zoulas.com>
+
+	* roll back to an older version of libtool that works
+
+	* newer versions of config.guess and config.sub
+
+	* minor fixes to buildall
+
+2011-05-19  Christos Zoulas <christos at zoulas.com>
+
+	* m4/macros/libtool.m4: for AIX AC_LANG_PROGRAM is incorrectly
+	  used and the latest autoconf gives an error. For now just
+	  quote it.
+
+	* configure.in: Fedora Core 15 and RedHat 6 now don't define
+	  af_family_t in <linux/socket.h>, but in <bits/sockaddr.h>.
+	  Include <sys/socket.h> so that we get <bits/sockaddr.h>
+	  indirectly. This caused the <linux/nfs_mount.h> detection
+	  test to fail.
+
+2010-11-24  Erez Zadok  <ezk at fsl.cs.sunysb.edu>
+
+	* m4/macros/os_cflags.m4: for linux, define _GNU_SOURCE (to get
+	definitions for O_LARGEFILE and more).
+
+2010-11-20  Christos Zoulas <christos at zoulas.com>
+
+	* Update news items, add release readme, mark as rc1
+
+	* Fix addopts code to work with options that are key=value
+	  when the built-in hasmntopt() code is not used. The problem
+	  was that the code passed "key=" to hasmntopt not "key".
+
+2009-12-10  Christos Zoulas <christos at zoulas.com>
+
+	* Copy all fields of the am_opts structure
+	  When we introduced am_loc we also added a function to
+	  create a duplicate of an am_opts structure. As it turns
+	  out, that only made a partial copy of the struct and some
+	  fields (e.g. opt_cache) was left blank in the new structure.
+	  Unfortunately any code that was checking the options
+	  through the mntfs structure was mislead by the partial
+	  copy: caching was disabled completely, for example, and
+	  since browsing relies on caching being enabled it wasn't
+	  working either.
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* Initialize RPC authentication flavor to AUTH_UNIX instead
+	  of zero. RHEL 5 uses version 6 of the mount_arg structure
+	  that includes the desired RPC authorization flavour.
+	  Unfortunately amd initializes that value to zero, meaning
+	  AUTH_NULL, resulting in all NFS servers denying operations.
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* Make sure to remove nodes in the proper order when going
+	  down. Depending on what order the nodes got created it's
+	  possible that the parent of a node has a bigger am_mapno
+	  (index in exported_ap[]) so that it gets freed before
+	  its child while the child's am_parent pointer is still
+	  pointing to the already freed block of memory.
+	  This change makes sure that umount_exported() cleans up
+	  all children of a node first before freeing the node.
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* Fix Linux-specific stuff in ops_tmpfs.c
+	  AUTOFS_TMPFS_FS_FLAGS is defined only in the Linux-specific
+	  conf_linux.c file, so it cannot be built on Solaris.
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+        * Add missing parenthesis to fix defined(XXX
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* In the previous commit we've already made a change that
+	  makes this code unnecessary since the node is returned
+	  even if the backing file server is known to be down.
+	  Since the code path is unused it should be removed.
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* amfs_generic_lookup_child() tries to find an alternate
+	  file server if it detects that the current one is down.
+	  However, in the comparison used to decide if a possible
+	  mount is the same as the current one it compares the am_loc
+	  pointers instead of the actual mntfs pointers. Since
+	  amfs_lookup_one_location() creates a brand new am_loc
+	  structure for the returned mntfs structure the am_loc
+	  pointer will be different even if the mntfs it's pointing
+	  to is the same.
+	  This tricks amfs_generic_lookup_child() think it has
+	  found an alternate file server while it hasn't and thus
+	  starts multiple racing mounts for the very same node and
+	  mntfs.
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* In the new am_loc scheme mounted mntfs structures still
+	  have their mf_fo structure left intact. So when restart
+	  creates a fake mntfs for an already mounted filesystem it
+	  should not free mf_fo right away.
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* Setting the error flag of the mntfs for which the share
+	  is already mounted results in the mount point not being
+	  removed when it times out. (Amd considers it an error
+	  mntfs and thus umount becomse a no-op.)
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* Right now AMD sets all timeout values to their defaults
+	  even if you explicitly set them to zero. This patch
+	  introduces separate flags that store if the respective
+	  values have been set and the code path setting default
+	  values checks these flags instead of testing the values
+	  for zero. [Linux only]
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* Fix mntfs related lookup/(un)mount race conditions, by
+	  introducing a new structure linking an mntfs to a node.
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* We have to free the buffers allocated by the XDR routines when
+	  decoding the mount response after copying them to their final place.
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+2009-12-09  Christos Zoulas <christos at zoulas.com>
+
+	* Free continuation in amfs_retry() if we don't call amfs_bgmount()
+	  Normally it's amfs_bgmount() which frees the continuation. However, if
+	  the mount is already in progress and we're in amfs_retry() for another
+	  node we don't try mounting the filesystem once again. Still, we have
+	  to free the continuation as we won't get called again and thus would
+	  leak the continuation structure and our am_loc references.
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+	* Fix use-after-free and double free of mntfs private data
+	  ops_nfs.c(nfs_init) does not clear private data pointer after free().
+	  This leads to use-after-free and double free in case mount() fails.
+	  (found by valgrind)
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+2009-11-23  Christos Zoulas <christos at zoulas.com>
+
+	* The temporary filename buffer was leaked in lock_mtab().
+	  From: Krisztian Kovacs <Kris.Kovacs at morganstanley.com>
+
+2009-10-27  Christos Zoulas <christos at zoulas.com>
+
+	* Deal with errno.h->sys/errno.h better
+
+2009-10-26  Christos Zoulas <christos at zoulas.com>
+
+	* Fix issue with autoconf 2.63
+
+	* Fix compile warnings for gcc-4.4.x
+
+2009-04-15  Christos Zoulas <christos at zoulas.com>
+
+	* Share the LDAP connection between different maps to save resources
+	  on the LDAP server. (Olaf Flebbe <o.flebbe at science-computing.de>)
+
+2009-03-20  Christos Zoulas <christos at zoulas.com>
+
+	* Fix largefile re-definitions
+
+	* Fix compilation error caused in previous patch
+
+2009-02-19  Christos Zoulas <christos at zoulas.com>
+
+	* Add a synchronous unmount amq rpc that will wait for the remote
+	  filesystem to be unmounted, or return an error. Enabled by amq -uu
+
+2009-01-11  Erez Zadok  <ezk at fsl.cs.sunysb.edu>
+
+	* amd/ops_udf.c: don't define functions/variables which may not be
+	used.
+
+	* amd/ops_tmpfs.c (mount_tmpfs): force gcc not to complain about
+	unused variables.
+
+	* config.guess.long: properly support Fedora Core.
+
+2009-01-09  Christos Zoulas <christos at zoulas.com>
+
+	* Fix nfs mounts on linux 2.6.26 by explicitly initializing context.
+
+	* Treat an empty sublink as an unset sublink; this allows us to
+	  say sublink:=; in a spec to override the default. (This produces
+	  Bad selector error, but it works. XXX: We need to decide how to
+	  unset a selector. I proposed an unset keyword a while ago).
+
+2009-01-06  Christos Zoulas <christos at zoulas.com>
+
+	* re-renerate all generated files with newer versions of the
+	  auto-tools.
+
+	* move INSTALL to INSTALL.am-utils to avoid conflicts
+
+	* fix incompatibilities with new m4 and new autoconf.
+
+	* add UDF filesystem support.
+
+	* fix NetBSD nfs file handle detection.
+	
+2009-01-02  Christos Zoulas <christos at zoulas.com>
+
+	* add nocasetrans, nojoliet, rrcaseins for cd9660 filesystems
+
+2008-12-03  Christos Zoulas <christos at zoulas.com>
+
+	* allow ldap queries try a comma-separated list of servers given as:
+
+		ldap_hostports = host1:port1,host2,host3:port3
+
+	  original patch from Florian Geyer
+
+2008-09-19  Christos Zoulas <christos at zoulas.com>
+
+	* the auth_create gid on NetBSD is int
+
+	* deal with lossage from flex -P
+
+	* fix missing/incorrect prototypes
+
+2008-09-17  Christos Zoulas <christos at zoulas.com>
+
+	* fix manual page section issues (sorting, non-existant)
+
+	* add missing forward declarations
+
+	* avoid null pointer derefs (coverity)
+
+	* more portable endian detection support
+
+	* implement tmpfs support
+
+	* use sizeof var instead of constant
+
+	* fix yyerror declaration and definition
+
+	* fix yy function renaming, and correct some renaming issues.
+
+	* work around automake < 1.9 issue where ylwrap is not being run
+	  for a single yacc or lex file.
+
+	* NetBSD
+	  - handle headers that need other headers to compile
+	  - add exfs and tmpfs specific glue
+	  - add options log, noatime, nocoredump, nodevmtime, softdep,
+	    symperm, union
+	  - NetBSD's new mount system call needs the size of the opaque
+	    filesystem specific structure, but passing 0 for now works.
+	    We would need to change a lot more code to pass the size from
+	    the fs-specific calls, so for now punt.
+	  - recvfrom takes socklen_t * on NetBSD
+	  - handle newer NetBSD using statvfs
+	  - NetBSD calls its ufs ffs
+
+	* Linux
+	  - Most recent kernels have trouble with trying to parse the pid
+	    hostname and do locking. What before was a silent failure, now
+	    there is a warning printed and the mount is rejected. This is
+	    the simplest fix:
+	    (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=479884)
+
+2007-04-13  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* amd/sun_map.c (sun_append_str): When translating '&' from Sun
+	automounter maps, replace it with "${key}" in the Amd map, not
+	with the value of the key at the time.  This way '*' maps work
+	too.
+
+	* config.guess.long: don't use -q option to grep because some
+	systems don't support it.  Bug fix for solaris.
+
+2007-03-11  Christos Zoulas  <christos at zoulas.com>
+
+	* amd/opts.c (expand_op): Don't call xstrlcpy() to truncate a
+	string.  It causes spurious xstrlcpy() syslog() errors.  Use
+	memcpy() and explicitly terminate the string.
+
+2007-01-20  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* updated copyright year to 2007 on all files.
+
+2006-12-27  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* minor new port: ia64-hp-hpux11.23
+
+	* m4/macros/check_libwrap_severity.m4 (LIBS): also test if caller
+	needs to define rfc931_timeout.
+
+	* amd/sun2amd.c: define rfc931_timeout and allow/deny_severity for
+	libwrap.
+
+	* amd/amq_svc.c: some versions of libwrap require the caller to
+	define rfc931_timeout in addition to allow/deny_severity.
+
+	* amd/amfs_toplvl.c (amfs_toplvl_init): properly detect when
+	forced unmount functionality exists for all systems.
+
+	* libamu/mount_fs.c (compute_nfs_args): reset nfs_args_t->pathconf
+	only if field exists.
+
+	* conf/nfs_prot/nfs_prot_hpux11.h: prevent HPUX 11.23 from
+	including <tiuser> or <sys/tiuser> (TLI definitions are already
+	included from elsewhere).
+
+	* configure.in: detect nfs_args_t->pathconf field.
+
+2006-11-27  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* doc/Makefile.am: properly publish html files using newer
+	text2html.
+
+2006-11-27  Erez Zadok  <ezk at shekel.local>
+
+        * doc/Makefile.am: obfuscate emails in ChangeLog before it is
+        published on web site.
+
+	* obfuscate many more emails in the distro, esp. of files which get
+        posted on the am-utils web site.
+
+2006-11-26  Erez Zadok  <ezk at shekel.local>
+
+	* minor new port: i386-apple-darwin8.8.1.
+
+        * doc/am-utils.texi: remove obvious URLs used by spammers, and
+        replace them with links to the am-utils web site, which uses PNG
+        images to obfuscate the actual email/mailman URLs.
+
+2006-10-30  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* doc/am-utils.texi (Password maps): minor typo reported by
+	Christoph P. Kukulies.
+
+2006-10-26  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* minor new port: i386-pc-linux-fc6.
+
+	* m4/macros/linux_headers.m4: handle newer Linux kernels which
+	removed UTS_RELEASE from <linux/version.h>.
+
+2006-10-25  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* minor new ports: i386-pc-linux-centos4.4 and
+	powerpc-apple-darwin8.7.0.
+
+	* config.guess.long: recognize CentOS Linux.
+
+2006-06-20  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* minor new port: i386-pc-solaris2.11-nexentaos (GNU/OpenSolaris).
+
+	* config.guess.long: recognize NexentaOS (GNU/OpenSolaris)
+
+	* config.guess, config.sub: updates from latest official GNU
+	distributions.
+
+2006-05-11  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* Minor new ports: i386-unknown-freebsd6.1 (RELEASE),
 	powerpc-apple-darwin8.6.0, and i386-unknown-openbsd3.9.
 
+2006-05-10  Erez Zadok  <ezk at cs.sunysb.edu>
+
 	* libamu/mount_fs.c (compute_nfs_attrcache_flags): fix signedness
 	problems on IRIX-6.5.
 
@@ -188,12 +738,15 @@
 	same $ac_cv_* variable name).  Some systems support one header or
 	another.  Patch inspired by work Debian did.
 
-2006-02-10  Erez Zadok  <ezk at cs.sunysb.edu>
+2006-02-16  Daniel P. Ottavio  <ottavio at vm.fsl.cs.sunysb.edu>
 
-	*******************************************************************
-	*** Released am-utils-6.1.4					***
-	*******************************************************************
+	* amd/sum_map_tok.l: Fixed a bug in a regular expression that
+	prevented dashes in hostnames.  This was posted in BZ by Thomas
+	A. Fine.
 
+	* README.sun2amd: Fixed a typo.  Sentence mentions use of autofs
+	type when it should be host type.
+
 2006-01-04  Erez Zadok  <ezk at cs.sunysb.edu>
 
 	* doc/am-utils.texi (auto_attrcache Parameter): revise discussion
@@ -302,9 +855,31 @@
 2005-10-10  Erez Zadok  <ezk at cs.sunysb.edu>
 
 	*******************************************************************
-	*** Released am-utils-6.1.3					***
+	*** Released am-utils-6.1a1					***
 	*******************************************************************
 
+	* README.sun2amd: revised.
+
+2005-10-09  Daniel P. Ottavio  <dottavio at ic.sunysb.edu>
+
+	* amd/info_nis.c (nis_search): Bug fix for bugzilla #428; make
+	sure that sun_entry2amd() is not called when yp_match() returns an
+	error, this is done by checking that 'res' is 0.  Bug fix (same
+	BZ#); free the output allocated by yp_match() instead of freeing
+	the return value of sun_entry2amd().
+
+	* amd/sun_map.c (sun_entry2amd): Fix a comment.
+
+	* README.sun2amd: Made a first pass at describing the status of
+	the sun2amd feature.
+	Moved the date.
+
+2005-10-09  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* README.sun2amd: place holder.
+
+	* Makefile.am (EXTRA_DIST): distribute new README.sun2amd file.
+
 2005-10-07  Erez Zadok  <ezk at cs.sunysb.edu>
 
 	* m4/macros/check_mnttab_type.m4: move the test for MOUNT_* to the
@@ -343,6 +918,10 @@
 	* amd/info_exec.c (exec_map_open): break assignment from inside
 	conditional, to work around an IRIX-6.5 cc bug.
 
+	* amd/Makefile.am (amd_LDADD, sun2amd_LDADD): put libaminfo.a
+	before libamu.la.  Some linkers (e.g., IRIX-6.5) incorrectly
+	complain about undefined symbols.
+
 	* 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.
@@ -479,15 +1058,10 @@
 
 2005-10-02  Erez Zadok  <ezk at cs.sunysb.edu>
 
-	* include/am_utils.h: extern for xvsnprintf().
-
-	* amd/autil.c: move strsplit() to libamu/strutil.c.
-
 	* libamu/Makefile.am: use strutil.c, not util.c.
 
 	* 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.
+	of file.  Move xvsnprintf and xsnprintf from xutil.c to this file.
 
 	* libamu/xutil.c: explain purpose of file.  Move mkdirs/rmdirs
 	code from old util.c.
@@ -555,10 +1129,6 @@
 
 2005-09-26  Erez Zadok  <ezk at cs.sunysb.edu>
 
-	* 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>.
-
 	* 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.
@@ -565,13 +1135,8 @@
 
 2005-09-18  Erez Zadok  <ezk at cs.sunysb.edu>
 
-	*******************************************************************
-	*** Released am-utils-6.1.2.1					***
-	*******************************************************************
+	* README.attrcache: document netbsd's patchs to support noac.
 
-	* README.attrcache: Update status of freebsd and openbsd.
-	Document netbsd's patchs to support noac.
-
 	* 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.
@@ -578,13 +1143,10 @@
 
 	* configure.in: check for nfs_args fields acregmax and acdirmax.
 
-	*******************************************************************
-	*** Released am-utils-6.1.2					***
-	*******************************************************************
-
 	* README.attrcache: new file documenting in detail OS bugs
 	relating to attribute caching, which can affect Amd's reliability
 	under heavy load.
+	Update status of freebsd and openbsd.
 
 	* doc/Makefile.am: install README.attrcache file as attrache.txt
 	file on am-utils Web site.
@@ -665,6 +1227,54 @@
 	amfs_bgmount, amfs_generic_mount_child), amd/amd.c (main): pass
 	NULL to clocktime().
 
+2005-09-15  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* amd/nfs_subr.c (nfsproc_getattr_2_svc): initialize 'retry', just
+	in case.
+	(fh_to_mp3): increment amd_stats.d_stale counter only if we are
+	actually returning ESTALE.
+
+	* amd/info_exec.c (exec_parse_qanswer), amd/info_file.c
+	(file_search_or_reload), amd/info_hesiod.c (hesiod_search),
+	amd/info_ldap.c (amu_ldap_search), amd/info_ndbm.c (search_ndbm),
+	amd/info_nis.c (nis_search), amd/info_nisplus.c (nisplus_search,
+	nisplus_search): don't dereference mnt_map->cfm which may be null
+	if we're not using an amd.conf file.
+
+2005-09-14  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* libamu/xutil.c (unregister_amq): if failed to de-register Amd
+	from portmapper, report it under dlog (debugging), not as an
+	annoying plog that always shows up.
+
+2005-09-13  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* mk-amd-map/mk-amd-map.c (read_file_file), libamu/util.c
+	(strsplit), libamu/hasmntopt.c (nextmntopt), amd/sun_map.c
+	(sun_entry2amd), amd/sun2amd.c (sun2amd_convert_convert),
+	amd/mapc.c (mapc_add_kv), amd/info_file.c (file_search_or_reload),
+	amd/info_exec.c (exec_parse_qanswer): cast isspace() and isascii()
+	arg to unsigned char, which is safer as per Christos.
+
+	* amd/sun_map.c (sun_entry2amd): isspace takes an int, not a char.
+
+	* configure.in: keep a dummy unused AM_PROG_LEX, because old
+	Automake (1.6.3) looks for it if you refer to LEX in your
+	Makefile.am files.  Silly thing, fixed in newer versions of
+	Automake (1.9.2).
+
+2005-09-11  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* Makefile.am (EXTRA_DIST_M4): add prog_{lex,yacc}.m4 to distro.
+
+	* configure.in: use new macros AMU_PROG_YACC and AMU_PROG_LEX.
+
+	* m4/macros/prog_yacc.m4: new macro to check if bison/yacc/byacc
+	exist, but exist with an error if none found.
+
+	* m4/macros/prog_lex.m4: new macro to check if f/lex exist, but
+	exit with an error if not found (am-utils requires f/lex).
+
 2005-09-07  Erez Zadok  <ezk at cs.sunysb.edu>
 
 	* minor new port: powerpc-apple-darwin8.2.0.
@@ -683,8 +1293,48 @@
 	file system on this system (probably because /proc isn't mounted),
 	then provide some default definition for this file to compile.
 
+2005-08-28  Daniel P. Ottavio  <dottavio at ic.sunysb.edu>
+
+	* amd/sun_map.c (sun_entry2amd) : Wipe out any trailing white
+	spaces or '\n' before passing strings to the parser.
+
+	* amd/amd.h : oops, reverting bad changes
+
+	* amd/info_file.c : oops, reverting bad changes
+
+	* amd/mapc.c : oops, reverting bad changes
+
+	* amd/sun_map_parse.y : oops, reverting bad changes
+
 2005-08-27  Erez Zadok  <ezk at cs.sunysb.edu>
 
+	* libamu/xutil.c: amd_program_number is a u_long now.
+	(unregister_amq): if pmap_unset failed to de-register Amd from the
+	portmapper, print an error message.
+	(get_amd_program_number): returns a u_long now.
+	(set_amd_program_number): take a u_long now.
+
+	* include/am_utils.h: get_amd_program_number() returns u_long now.
+	set_amd_program_number() takes a u_long now.
+
+	* amq/amq.c: amd_program_number is a u_long, not int.
+
+	* amd/nfs_start.c (mount_automounter): when registering Amd with
+	the portmapper (for Amq service), don't fail if just one of TCP or
+	UDP failed to register, but only if both transports failed.  That
+	way Amq can still contact Amd using the transport that did
+	register correctly.  However, now, if both transports failed to
+	register, then set amd_state to "Done" so it would shutdown
+	cleanly.
+
+	* conf/transp/transp_{sockets,tli{}.c (amu_svc_register): better
+	comments.
+
+	* libamu/xutil.c: debug_flags should always be initialized to
+	D_CONTROL (amq,daemon,fork).
+	(debug_option): allow setting initial immutable debug_flags via
+	amd.conf; afterward, prevent it (i.e., one tries it via "amq -D").
+
 	* 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".
@@ -692,13 +1342,199 @@
 	* amd/Makefile.am (DISTCLEANFILES): also remove ops_autofs.c on
 	"make distclean".
 
+2005-08-27  Daniel P. Ottavio  <dottavio at ic.sunysb.edu>
+
+	* amd/info_file.c (file_search_or_reload): Changed the key
+	variable that is passed to the sun_entry2amd.
+
+	* amd/mapc.c (mapc_add_kv): Add support for multiple entries
+	packed into one line.  This is a workaround for handling Sun style
+	mounts that contains multiple entries on one line: "multi-mount
+	entries".  The sun2amd conversion tools will convert such entries
+	into type:=auto and pack each of the auto-entries into one line
+	separated by '\n'.  The mapc_add_kv function will now recognize
+	such entries and add then.
+
+	* amd/sun2amd.c (sun2amd_convert): Add print statement that
+	includes the line number during a parser failure.
+
+	* sun_map.c: Fix the AMD_MAP_PREF_KW definition.  Fix spelling.
+	(sun_mountpts2amd): removed this function
+	(sun_hsfs2amd): added some more comments
+	(sun_nfs2amd): moved support for multi-mount entries from this
+	function to sun_multi2amd().
+	(sun_multi2amd): New function to handle multi-mount entries.  This
+	function will convert the Sun version to an Amd type:=auto.  Each
+	extra auto entry will be appended to the same line separated by a
+	'\n'.
+	(sun_entry2amd): Fixed a bug if-statement.  This function now
+	checks for multi-mount entries.
+
+	* amd/sun_map.h: Add a fstype member to the sun_mountpt struct.
+
+	* amd/sun_map_parse.y: Parser now supports fstype for multi-mount
+	entries.
+
+	* amd/sun_map_tok.l: No longer print the line and column number
+	when parsing.  This is because the parser is handed strings not
+	files.  Therefore, the line number will always be 1.  It is now up
+	to the higher level tools to echo line information during error
+	when they feed the parser.
+
 2005-08-24  Erez Zadok  <ezk at cs.sunysb.edu>
 
 	* configure.in: wrap all LDAP and HESIOD tests in test whether
 	--with-OPT was used.
 
+2005-08-20  Daniel P. Ottavio  <dottavio at ic.sunysb.edu>
+
+	* amd/sun_map.c: Clean up #defines
+	(sun_entry2amd) : Verify that the key and entry values passed are
+	not NULL.  Free the Sun entry struct when done.
+
+	* amd/sun_map.h: Add some "not implemented yet" comments to the
+	map and mmap structures.
+
+	* amd/sun_map_parse.y: Removed automap include functionality, it
+	will need to be re-implemented using a pre-processor.
+	Clean up function calls.
+
+2005-08-16  Daniel P. Ottavio  <dottavio at ic.sunysb.edu>
+
+	* amd/sun2amd.c (sun2amd_convert): If the input line is too long
+	don't return an error just null terminate and continue.  Fix bug:
+	the map key was not written.
+
+	* amd/sun_map.c: Add a new Amd device, and cdfs constant.
+	(sun_locations2amd): Write the NFS type keyword
+	for each host of the mount entry.  Add a space between each mount
+	location.
+	(sun_hsfs2amd): New function to support hsfs to
+	cdfs.
+	(sun_nfs2amd): Don't write the nfs type here.  Fix
+	comments.
+	(sun_entry2amd): Change function parameter var for
+	clarity.  Add support for hsfs.
+
+	* amd/sun_map_parse.y (sun_map_parse_read): Reset the entry list
+	after it has been returned.
+
 2005-08-16  Erez Zadok  <ezk at cs.sunysb.edu>
 
+	* amd/get_args.c (get_args): initialize debug_flags if they've
+	never been set.
+
+2005-08-15  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* amd/mapc.c (mapc_create): mapc find takes 4th arg, the mount
+	point.  Now, we can properly initialize the cfm structure of the
+	mnt_map, so we can have access to the flags (e.g., SUN_MAP_SYNTAX)
+	inside each info_*.c file.
+	(mapc_find): takes 4rd arg (mntpt) and passes it to calls to
+	mapc_create.
+	(root_newmap): pass NULL as 4th arg (mntpt).
+
+	* amd/amfs_generic.c (amfs_parse_defaults): remove ugly hack to
+	initialize map cfm structure (including flags) so late.
+
+	* amd/autil.c (amfs_mkcacheref): pass mount point as 4th arg to
+	mapc_find.
+
+	* amd/amfs_root.c (amfs_root_mount): pass NULL as new 4th arg to
+	mapc_find.
+
+	* amd/amd.h: extern for mapc_find changed to pass the mount point.
+
+	* libamu/xutil.c: debug_flags should be unsigned.
+	(dbg_opt): fix comments for updated debug_flags, add "defaults".
+	(debug_option): Don't allow "immutable" (D_IMMUTABLE) flags to be
+	changed, because they could mess Amd's state and only make sense
+	to be set once when Amd starts.  Currently these immutable flags
+	are "daemon," "fork," "amq," and "mtab."  If Amd not compiled with
+	debugging, set default "control" options (daemon,fork,amq).
+	(unregister_amq): proper use of D_AMQ.
+
+	* include/am_utils.h: define new D_BASIC, D_CONTROL, D_DEFAULT,
+	D_IMMUTABLE, and D_MASK.  Updated definitions of D_ALL and D_TEST.
+	debug_flags extern should be unsigned.
+
+	* scripts/amd.conf-sample (debug_options): mention new "defaults"
+	option.
+
+	* scripts/amd.conf.5,doc/am-utils.texi: document new debug option
+	"defaults" and properly explain the corrected meanings of
+	"daemon," "fork," "amq," and their "no" inversions.  Better
+	explain "all" and "test" too.  Correct default debug_mtab file to
+	/tmp/mtab.
+
+	* hlfsd/stubs.c (nfsproc_readlink_2_svc): proper use of D_FORK.
+
+	* hlfsd/homedir.c (homedir): proper use of D_FORK.
+
+	* hlfsd/hlfsd.c (main, hlfsd_init, cleanup): proper use of
+	D_DAEMON.
+
+	* amd/nfs_start.c (mount_automounter): proper use of D_AMQ.
+
+	* amd/amd.h (DEBUG_MNTTAB_FILE): change default to /tmp/mtab,
+	which is more common on more systems (instead of /tmp/mnttab).
+
+	* amd/amd.c (main): properly use D_DAEMON.
+
+2005-08-14  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* libamu/xutil.c (xlog_opt): define new pseudo log_option named
+	"defaults", which is an alias for "fatal,error,user,warning,info".
+
+	* scripts/amd.conf.5, doc/am-utils.texi, amd/amd.8: document new
+	log_option "defaults".
+
+	* amq/amq.8: typo.  Arg name for -D is "debug_options" not
+	"log_options".
+
+	* libamu/xutil.c: make xlog_level static, and initialize it to
+	XLOG_DEFAULT.
+	(cmdoption): take unsigned int as flags argument, and print any
+	errors as XLOG_ERROR (which cannot be turned off).
+	(switch_option): remove old code which disallowed you from turning
+	off flags that were set when Amd started up.  Now, you can turn
+	any log option on/off at start time or later on (via amq -x),
+	other than the two mandatory options (fatal+error).
+
+	* include/am_utils.h (XLOG_*): remove unused XLOG_DEFSTR.  Define
+	XLOG_MASK to mask out unused flag bits.  Define XLOG_DEFAULT to be
+	what it was before (fatal + error + user + warning + info), but
+	use the new mask.  Remove extern's for xlog_level and
+	xlog_level_init.  Change extern for cmdoption() to take an
+	unsigned flags argument.
+
+	* doc/am-utils.texi, amq/amq.8, scripts/amd.conf.5, amd/amd.8:
+	document mandatory log options
+	(fatal+error) which cannot be turned off and are always on by
+	default.  They must be on so that Amd can report crucial errors,
+	including those related to setting flags on/off.
+
+	* hlfsd/hlfsd.c (main): remove hack to initialize log_options.
+
+	* wire-test/wire-test.c: remove reference to unused xlog_level.
+
+	* amd/mapc.c (mapc_create): 'alloc' flags variable should be
+	unsigned.
+
+	* amd/get_args.c (get_args): no need for hack using
+	xlog_level_init.
+
+	* amd/Makefile.am: separate sources common to amd and sun2amd into
+	a special, locally-built only, static library called libaminfo.a.
+
+	* libamu/xutil.c (real_plog, xsnprintf): call new xvsnprintf()
+	wrapper function.
+	(xvsnprintf): new function which already gets a va_list.  This was
+	needed to avoid nesting va_list's (which apparently isn't
+	allowed).
+
+	* include/am_utils.h: prototype for new xvsnprintf wrapper.
+
 	* configure.in: sinclude([vers.m4]) version number file.
 
 	* vers.m4: new file to separate version number out of
@@ -707,18 +1543,236 @@
 
 	* Makefile.am (EXTRA_DIST_M4): include vers.m4 in distro.
 
+2005-08-14  Daniel P. Ottavio  <dottavio at ic.sunysb.edu>
+
+	* amd/info_file.c: add key to sun_entry2amd()'s parameters
+
+	* amd/info_hesiod.c: add key to sun_entry2amd()'s parameters
+
+	* amd/info_ldap.c: add key to sun_entry2amd()'s parameters
+
+	* amd/info_ndbm.c: add key to sun_entry2amd()'s parameters
+
+	* amd/info_nis.c: add key to sun_entry2amd()'s parameters
+
+	* amd/info_nisplus.c: add key to sun_entry2amd()'s parameters
+
+	* amd/sun_map.c: New functions to support sun translation to amd.
+	The function sun_entry2amd's parameters were expanded to include
+	the key value.  sun_entry_2amd() now returns NULL on error.
+
+	* amd/sun_map.h: Expand sun_entry2amd's parameters to include key
+	value.
+
+	* amd/sun_map_parse.y: Change how file system types are parsed out
+	of the list of options for each entry.  The previous way was not
+	working properly so now we just look for the 'fstype' keyword in
+	each option.  If it exists we copy its key value.
+	Added some comments to sun_map_parse_read().
+
+	* amd/amd.h: Added an extern from info_file.c called
+	file_read_line().  Previously this function was static but is now
+	used in sun2amd.c.
+
+	* amd/info_file.c: Changed the static function read_line() to a
+	public function called file_read_line().  This function is now
+	used in sun2amd.c
+
+	* amd/sun2amd.8: Filled in the contents of this man page.  This is
+	a conversion utility that converts Sun maps to Amd maps.
+
+	* amd/sun2amd.c: Implemented a working version of this utility.
+
 2005-08-11  Erez Zadok  <ezk at cs.sunysb.edu>
 
+	* amd/sun_map_parse.y: instead of using a custom FOO_alloc()
+	function, use Amd's CALLOC(struct FOO) macro.
+
+	* amd/sun_map.h: remove extern definitions to functions no longer
+	needed.
+
+	* amd/sun_map.c: removed superfluous *_alloc() functions, some of
+	which caused conflicts with same-named symbols in the parser
+	(since we rename 'yyalloc' to 'sun_map_alloc').
+
 	* configure.in: keep AC_INIT on same line, for nightly snapshot
 	build script.
 
+	* amd/Makefile.am: f/lex libraries are incompatible with multiple
+	scanners, so don't link Amd with libl.a/libfl.a.
+
+2005-08-10  Daniel P. Ottavio  <dottavio at ic.sunysb.edu>
+
+	* amd/sun_map_tok.l: Clean up regular expression so HPUX stops
+	whining.
+
+2005-08-09  Daniel P. Ottavio  <dottavio at ic.sunysb.edu>
+
+	* amd/sun_map_parse.y: Moved license below special yacc bracket to
+	be portable with HPUX's yacc.  Clean up externs.
+
+	* amd/sun_map_tok.l: Moved license below special lex bracket to be
+	portable with HPUX's lex.  Fixed definitions to allow for a
+	non-flex lex to parse strings instead of files.  Added some casts
+	to strlcpy usage to silence warnings.  Moved the % options because
+	HPUX was complaining,
+
+2005-08-08  Daniel P. Ottavio  <dottavio at ic.sunysb.edu>
+
+	* amd/sun_map_tok.l: Applied some definition goop to handle the
+	ECHO symbol that lex defines.  This symbol causes problems on
+	RedHat-EL-powerPC platforms.  Replaced strncpy with strlcpy.
+	Renamed the function sun_map_yyinput to sun_map_input.  This
+	function is a utility function that is not generated by lex.
+	Therefore, the 'yy' may cause confusion.
+
+2005-08-08  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* amd/sun_map_tok.l: allocate more output slots so lex scanners
+	don't run out of memory.
+
+	* amd/sun_map_parse.y: declare extern for sun_map_parse().
+
+	* libamu/xutil.c (xsnprintf): ensure proper comparisons between
+	signed and unsigned quantities.
+
 2005-08-06  Erez Zadok  <ezk at cs.sunysb.edu>
 
+	* libamu/util.c, amd/autil.c (strsplit): moved strsplit() function
+	from Amd code to to libamu, so sun2amd could use it.
+
+	* amd/Makefile.am (sbin_PROGRAMS): build sun2amd binary and man
+	page.
+	(EXTRA_sun2amd_OBJECTS): sun2amd needs to link with all info_*.c files
+
+	* amd/sun2amd.8: placeholder for man page.
+
+	* amd/sun2amd.c: placeholder for C version of translator from Sun
+	syntax maps to Amd maps.
+
+	* */*.[0-9]: include file name in nroff source comment.
+
+	* ALL: use '0' properly when assigning or passing it to functions.
+	If in the context pointer, use NULL.  If in the context of a
+	single char (say within a string), the use '\0'.  This is just to
+	make the code clearer.
+
+	* m4/macros/header_templates.m4: template for HAVE_MAP_SUN.
+
+	* amd/mapc.c (maptypes): add placeholder for Sun-syntax map
+	methods.
+
+	* amd/Makefile.am (EXTRA_amd_SOURCES): compile info_sun.c
+
+	* amd/info_sun.c: placeholder for meta info parser to get info
+	from Sun automount-style /etc/auto_master, possibly following
+	into multiple info services (via /etc/nsswitch.conf).
+
+	* libamu/xutil.c (xsnprintf): if vsnprintf truncated the output
+	string to avoid an overflow, print an error.  Include some code to
+	break out any possible infinite loop between plog() and
+	xsnprintf().
+	(real_plog): now we can use (carefully) xsnprintf() directly.
+
+	* amd/sun_map.[hc]: cleanup and formatting.
+
+	* amd/sun_map_parse.y: to match the literal string "fstype=" use
+	double quotes, not single quotes.
+
+	* amd/get_args.c (get_args): call conf_parse() using conf_in.
+
+	* amd/amd.h: use renamed parser symbols (yyparse -> conf_parse;
+	yyin -> conf_in).
+
+	* ylwrap: Enhance wrapper to avoid the #define hacks done by Gdb,
+	and suggested by the Automake manual.  This enhanced parser will
+	prefix each conflicting yacc/lex symbol with a unique name
+	produced from INPUT.  For example, if INPUT is foo_parse.y, then
+	yyparse() becomes foo_parse().  This requires that both your .l
+	and corresponding .y files have the same prefix (e.g., foo_parse.y
+	and foo_tok.l).
+
+	* amd/Makefile.am (BUILT_SOURCES): define which yacc/lex .h/.c
+	source files are built automatically, and therefore should not be
+	in the distro (IMHO), and should be cleaned upon "make clean".
+	(amd_SOURCES): include new sun_map_parse.y and sun_map_tok.l files.
+
+	* ylwrap: new file needed because we have two parsers now.
+
+	* amd/sun_map_{parse.y,tok.l}: cleanup and formatting.
+
+2005-08-06  Daniel P. Ottavio  <dottavio at ic.sunysb.edu>
+
+	* amd/Makefile.am: Added new files sun_map.h, sun_map.c,
+	sun_map_parse.y, and sun_map_tok.l.  These files add support for
+	parsing Sun style maps.  The yacc/lex files needed custom rules so
+	they don't cause symbol conflicts with each other.
+
+	* amd/amd.h: Added "#define INFO_MAX_LINE_LEN" that specifies the
+	line limit for info services.
+
+	* amd/info_exec.c: Replaced MAX_LINE_LEN with INFO_MAX_LINE_LEN
+
+	* amd/info_file.c: Replaced MAX_LINE_LEN with INFO_MAX_LINE_LEN,
+	added support for parsing Sun style maps.  The support for Sun
+	maps is done using the sun_entry2amd() function.  This function is
+	called for each entry line that is read only when Sun parsing is
+	enabled.  For each entry line that is passed to the function a
+	copy of the Amd equivalent is returned.
+
+	* amd/sun_map.h: new header file for Sun style map support
+
+	* amd/sun_map.c: new source file for Sun style map support, clean
+	up comments, additional sun2amd conversion routines
+
+	* amd/sun_map_parse.y: new yacc file for parsing Sun style maps,
+	fix copyright notice, put filename below license.
+
+	* amd/sun_map_tok.l: new lex file for parsing Sun style maps, fix
+	copyright notice, put filename below license.
+
+	* amd/get_args.c: replace usage of strlcat with xstrlcat
+
+	* include/am_utils.h: added 'extern void xstrlcat()'
+
+	* libamu/util.c: Added a xstrlcat() function that wraps the
+	syscall strlcat() so that string truncations can be logged.
+
+2005-08-06  Erez Zadok  <ezk at cs.sunysb.edu>
+
+	* amd/info_file.c (file_search, file_reload): pass mnt_map to
+	file_search_or_reload.
+	(file_search_or_reload): ensure that mnt_map is never NULL.
+
+	* amd/info_nis.c (nis_search): call sun_entry2amd() if
+	sun_map_syntax=yes.
+
+	* amd/info_ldap.c (amu_ldap_search): call sun_entry2amd() if
+	sun_map_syntax=yes.
+
+	* amd/info_hesiod.c (hesiod_search): call sun_entry2amd() if
+	sun_map_syntax=yes.
+
+	* amd/info_ndbm.c (ndbm_search): pass mnt_map to search_ndbm.
+	(search_ndbm): call sun_entry2amd() if sun_map_syntax=yes.
+
+	* amd/info_nisplus.c (nisplus_search): call sun_entry2amd() if
+	sun_map_syntax=yes.
+
+	* amd/info_exec.c (exec_search): pass mnt_map to
+	exec_parse_qanswer.
+	(exec_parse_qanswer): call sun_entry2amd() if sun_map_syntax=yes.
+
+	* doc/am-utils.texi (sun_map_syntax Parameter): document new
+	common parameter.
+
 	* scripts/amd.conf.5: selectors_in_defaults is a common parameter,
 	not just [global].  Use consistent capitalization of Amd/Amq.
+	Document new sun_map_syntax parameter.
 
 	* scripts/amd.conf-sample: properly list all of the parameters
 	which are common to both the [global] and the per-map sections.
+	(sun_map_syntax): example of new parameter.
 
 	* doc/am-utils.texi (Common Parameters): selectors_in_defaults is
 	a common parameter, not just [global].
@@ -725,6 +1779,12 @@
 
 	* scripts/amd.conf-sample (sun_map_syntax): example of new flag.
 
+	* amd/conf.c ({ropt,gopt}_sun_map_syntax): new function to parse
+	sun_map_syntax flag (global or per map).
+
+	* amd/amd.h (CFM_SUN_MAP_SYNTAX): new flag for users to say if the
+	map uses Sun automounter syntax.
+
 	* cvs-server.txt: update instructions after branching 6.1-stable.
 
 2005-08-02  Erez Zadok  <ezk at cs.sunysb.edu>

Modified: trunk/contrib/amd/FAQ
===================================================================
--- trunk/contrib/amd/FAQ	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/FAQ	2018-06-15 22:31:15 UTC (rev 11011)
@@ -26,7 +26,7 @@
    listed in bugzilla in https://bugzilla.am-utils.org/
 
 If you have additions to this FAQ, please let us know at
-am-utils at am-utils.org.
+the am-utils list (see www.am-utils.org).
 
 Thank you,
 The Am-utils development team.

Modified: trunk/contrib/amd/FREEBSD-Xlist
===================================================================
--- trunk/contrib/amd/FREEBSD-Xlist	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/FREEBSD-Xlist	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,4 +1,4 @@
-$FreeBSD$
+$FreeBSD: stable/10/contrib/amd/FREEBSD-Xlist 174537 2007-12-11 19:16:51Z obrien $
 *LSM.am-utils
 *Makefile.*
 *README.autofs

Modified: trunk/contrib/amd/FREEBSD-upgrade
===================================================================
--- trunk/contrib/amd/FREEBSD-upgrade	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/FREEBSD-upgrade	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 # ex:ts=8
-$FreeBSD$
+$FreeBSD: stable/10/contrib/amd/FREEBSD-upgrade 174537 2007-12-11 19:16:51Z obrien $
 
 AMD (am-utils) 6.1.5
     originals can be found at: ftp://ftp.am-utils.org/pub/am-utils/

Modified: trunk/contrib/amd/INSTALL
===================================================================
--- trunk/contrib/amd/INSTALL	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/INSTALL	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,124 +1,370 @@
-		      am-utils 6.1 compatibility list
+Installation Instructions
+*************************
 
-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 'X' means verified broken or nonexistent (static library).
+Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
+Inc.
 
-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
+   Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.  This file is offered as-is,
+without warranty of any kind.
 
+Basic Installation
+==================
 
-EMAIL ID LEGEND:
+   Briefly, the shell command `./configure && make && make install'
+should configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.  Some packages provide this
+`INSTALL' file but do not implement all of the features documented
+below.  The lack of an optional feature in a given package is not
+necessarily a bug.  More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
 
-bking:	Bevis R W King <B.King at ee.surrey.ac.uk>
-dsr:	Dan Riley <dsr at mail.lns.cornell.edu>
-ezk:	Erez Zadok <ezk at cs.columbia.edu>
-finkel:	Raphael Finkel <raphael at cs.uky.edu>
-ion:	Ion Badulescu <ion at cs.columbia.edu>
-jose:	Jose Nazario <jose at biocserver.BIOC.CWRU.Edu>
-nrh:	Nick Hall <nrh at dcs.ed.ac.uk>
-ro:	Rainer Orth <ro at TechFak.Uni-Bielefeld.DE>
-stolke:	Andreas Stolcke <stolcke at speech.sri.com>
-wpaul:	Bill Paul <wpaul at ctr.columbia.edu>
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
 
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
 
-FOOTNOTES:
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
 
-[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.
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
 
-[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.
+   The simplest way to compile this package is:
 
-[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.
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
 
-Erez & Ion
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package, generally using the just-built uninstalled binaries.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.  When installing into a prefix owned by root, it is
+     recommended that the package be configured and built as a regular
+     user, and only the `make install' phase executed with root
+     privileges.
+
+  5. Optionally, type `make installcheck' to repeat any self-tests, but
+     this time using the binaries in their final installed location.
+     This target does not install anything.  Running this target as a
+     regular user, particularly if the prior `make install' required
+     root privileges, verifies that the installation completed
+     correctly.
+
+  6. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  7. Often, you can also type `make uninstall' to remove the installed
+     files again.  In practice, not all packages have tested that
+     uninstallation works correctly, even though it is required by the
+     GNU Coding Standards.
+
+  8. Some packages, particularly those that use Automake, provide `make
+     distcheck', which can by used by developers to test that all other
+     targets like `make install' and `make uninstall' work correctly.
+     This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.  This
+is known as a "VPATH" build.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+   On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor.  Like
+this:
+
+     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CPP="gcc -E" CXXCPP="g++ -E"
+
+   This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+   By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.  In general, the
+default for these options is expressed in terms of `${prefix}', so that
+specifying just `--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+   The most portable way to affect installation locations is to pass the
+correct locations to `configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+`make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+   The first method involves providing an override variable for each
+affected directory.  For example, `make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+`${prefix}'.  Any directories that were specified during `configure',
+but not in terms of `${prefix}', must each be overridden at install
+time for the entire installation to be relocated.  The approach of
+makefile variable overrides for each directory variable is required by
+the GNU Coding Standards, and ideally causes no recompilation.
+However, some platforms have known limitations with the semantics of
+shared libraries that end up requiring recompilation when using this
+method, particularly noticeable in packages that use GNU Libtool.
+
+   The second method involves providing the `DESTDIR' variable.  For
+example, `make install DESTDIR=/alternate/directory' will prepend
+`/alternate/directory' before all installation names.  The approach of
+`DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters.  On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of `${prefix}'
+at `configure' time.
+
+Optional Features
+=================
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+   Some packages offer the ability to configure how verbose the
+execution of `make' will be.  For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with `make V=0'.
+
+Particular systems
+==================
+
+   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+     ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+   HP-UX `make' updates targets which have the same time stamps as
+their prerequisites, which makes it generally unusable when shipped
+generated files such as `configure' are involved.  Use GNU `make'
+instead.
+
+   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
+a workaround.  If GNU CC is not installed, it is therefore recommended
+to try
+
+     ./configure CC="cc"
+
+and if that doesn't work, try
+
+     ./configure CC="cc -nodtk"
+
+   On Solaris, don't put `/usr/ucb' early in your `PATH'.  This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'.  So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+   On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'.  It is recommended to use the following options:
+
+     ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS
+     KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf limitation.  Until the limitation is lifted, you can use
+this workaround:
+
+     CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+     Print a summary of the options unique to this package's
+     `configure', and exit.  The `short' variant lists options used
+     only in the top level, while the `recursive' variant lists options
+     also present in any nested packages.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+     Use DIR as the installation prefix.  *note Installation Names::
+     for more details, including other options available for fine-tuning
+     the installation locations.
+
+`--no-create'
+`-n'
+     Run the configure checks, but stop before creating any output
+     files.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.

Modified: trunk/contrib/amd/MIRRORS.html
===================================================================
--- trunk/contrib/amd/MIRRORS.html	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/MIRRORS.html	2018-06-15 22:31:15 UTC (rev 11011)
@@ -11,8 +11,8 @@
 
 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 at am-utils.org">am-utils-developers at am-utils.org</A> with the
+official mirror list, please send mail to
+"am-utils-developers AT am-utils.org" with the
 full URL, maintainer's email, and geographical location.
 
 <P>
@@ -24,8 +24,8 @@
  <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 at am-utils.org">am-utils-developers at am-utils.org</A>.
+ Contact person in case of problems
+"am-utils-developers AT am-utils.org".
  </LI>
  </UL>
 
@@ -33,7 +33,7 @@
  <UL>
  <LI> FTP: <A
  HREF="ftp://ftp.cs.umn.edu/pub/am-utils">ftp.cs.umn.edu</A>.
- Maintainer <A HREF="mailto:dokas at cs.umn.edu">dokas at cs.umn.edu</A>.
+ Maintainer <A HREF="mailto:dokas AT cs.umn.edu">dokas AT cs.umn.edu</A>.
  </LI>
  </UL>
 
@@ -40,7 +40,7 @@
 <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 at cise.ufl.edu">mirror at cise.ufl.edu</A>.
+  Maintainer <A HREF="mailto:mirror AT cise.ufl.edu">mirror AT cise.ufl.edu</A>.
  </LI>
  </UL>
 
@@ -52,10 +52,10 @@
 <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 at ftp.fu-berlin.de">ftp-adm at ftp.fu-berlin.de</A>.
+  Maintainer <A HREF="mailto:ftp-adm AT ftp.fu-berlin.de">ftp-adm AT 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 at ftp.tu-darmstadt.de">networking at ftp.tu-darmstadt.de</A>.
+  Maintainer <A HREF="mailto:networking AT ftp.tu-darmstadt.de">networking AT ftp.tu-darmstadt.de</A>.
  </LI>
  </UL>
 
@@ -62,7 +62,7 @@
 <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 at ftp.sunet.se">archive at ftp.sunet.se</A>.
+ Maintainer <A HREF="mailto:archive AT ftp.sunet.se">archive AT ftp.sunet.se</A>.
  </LI>
  </UL>
 
@@ -69,7 +69,7 @@
 <LI> UK
  <UL>
  <LI> FTP: <A HREF="ftp://sunsite.org.uk/package/am-utils">sunsite.org.uk</A>.
- Maintainer <A HREF="mailto:lmjm at icparc.ic.ac.uk">lmjm at icparc.ic.ac.uk</A>.
+ Maintainer <A HREF="mailto:lmjm AT icparc.ic.ac.uk">lmjm AT icparc.ic.ac.uk</A>.
  </LI>
  </UL>
 
@@ -81,21 +81,21 @@
 <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 at u-aizu.ac.jp">ftp-admin at u-aizu.ac.jp</A>.
+  Maintainer <A HREF="mailto:ftp-admin AT u-aizu.ac.jp">ftp-admin AT 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 at ring.gr.jp">ftpadmin at ring.gr.jp</A>.
+  Maintainer <A HREF="mailto:ftpadmin AT ring.gr.jp">ftpadmin AT 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 at ring.gr.jp">ftpadmin at ring.gr.jp</A>.
+  Maintainer <A HREF="mailto:ftpadmin AT ring.gr.jp">ftpadmin AT ring.gr.jp</A>.
  </LI>
  </UL>
 </UL>
 
 <HR>
-<I> Last updated: Jan 5, 2004</I>
+<I> Last updated: 2006-11-27</I>
 
 </BODY>
 </HTML>

Modified: trunk/contrib/amd/MIRRORS.txt
===================================================================
--- trunk/contrib/amd/MIRRORS.txt	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/MIRRORS.txt	2018-06-15 22:31:15 UTC (rev 11011)
@@ -2,59 +2,59 @@
 
 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 at am-utils.org
+official mirror list, please send mail to am-utils-developers AT 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 at am-utils.org
+		Maintainer: ezk AT am-utils.org
 	Minnesota:
 		ftp://ftp.cs.umn.edu/pub/am-utils
-		Maintainer: dokas at cs.umn.edu
+		Maintainer: dokas AT cs.umn.edu
 #Avoid for now: empty directory
 # 	Virginia (Newport News):
 # 		ftp://ftp.ferginc.com/pub/unix/am-utils
-# 		Maintainer: Branson.Matheson at FergInc.com
+# 		Maintainer: Branson.Matheson AT FergInc.com
 #server gone? (Jan 5, 2004)
 # 	Ohio (Kent State University):
 # 		ftp://info.mcs.kent.edu/pub/am-utils
-# 		Maintainer: root at mcs.kent.edu
+# 		Maintainer: root AT mcs.kent.edu
 	Florida (University of Florida)
 		ftp://ftp.cise.ufl.edu/pub/mirrors/am-utils
-		Maintainer: mirror at cise.ufl.edu
+		Maintainer: mirror AT cise.ufl.edu
 
 Europe:
 	Germany:
 		ftp://ftp.fu-berlin.de/unix/network/am-utils
-		Maintainer: ftp-adm at ftp.fu-berlin.de
+		Maintainer: ftp-adm AT ftp.fu-berlin.de
 	Germany:
 		ftp://ftp.tu-darmstadt.de/pub/networking/filesystems/am-utils/
-		Maintainer: networking at ftp.tu-darmstadt.de
+		Maintainer: networking AT ftp.tu-darmstadt.de
 	Sweden:
 		ftp://ftp.sunet.se/pub/unix/admin/am-utils
-		Maintainer: archive at ftp.sunet.se
+		Maintainer: archive AT ftp.sunet.se
 # not responding (Jan 5, 2004)
 # 	Sweden (Stockholm University, Math Depat):
 # 		ftp://mirror.matematik.su.se/pub/am-utils
-# 		Maintainer: leifj at matematik.su.se
+# 		Maintainer: leifj AT matematik.su.se
 	UK:
 		ftp://sunsite.org.uk/package/am-utils
-		Maintainer: lmjm at icparc.ic.ac.uk
+		Maintainer: lmjm AT icparc.ic.ac.uk
 
 Asia:
 	Japan:
 		ftp://ftp.u-aizu.ac.jp/pub/net/amd/am-utils
-		Maintainer: ftp-admin at u-aizu.ac.jp
+		Maintainer: ftp-admin AT u-aizu.ac.jp
 	Japan:
 		ftp://core.ring.gr.jp/pub/net/am-utils/
-		Maintainer: ftpadmin at ring.gr.jp
+		Maintainer: ftpadmin AT ring.gr.jp
 	Japan:
 		ftp://ftp.ring.gr.jp/pub/net/am-utils/
-		Maintainer: ftpadmin at ring.gr.jp
+		Maintainer: ftpadmin AT ring.gr.jp
 
 # gone? (Jan 5, 2004)
 # Australia:
 # 	Melbourne:
 # 		ftp://ftp.sage-au.org.au/pub/network/filesystem/am-utils
-# 		Maintainer: mirror at ftp.sage-au.org.au
+# 		Maintainer: mirror AT ftp.sage-au.org.au

Modified: trunk/contrib/amd/NEWS
===================================================================
--- trunk/contrib/amd/NEWS	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/NEWS	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,45 @@
-*** Notes specific to am-utils version 6.1.5
+*** Notes specific to am-utils version 6.2
 
+    - Removed license advertising clause
+    - Removed expn program
+
+*** Notes specific to am-utils version 6.2-rc1
+
+Filesystem Support:
+    - Add support for NFSv4
+    - Add support for Lustre
+    - Add support for ext{2,3,4}
+    - Add support for linux autofs version 5
+    - Add support for TMPFS and UDF
+New features:
+    - Add amq -i (prints information about maps)
+    - Add synchronous unmount code for amq -uu
+    - Allow a comma-separated list of LDAP servers for failover
+Changes in behavior:
+    - Empty variable assignments, now unset the variable value.
+    - Share LDAP connections between different maps to save resources
+Portability fixes:
+    - Changes to work with Linux-2.6.x, Linux-3.x and NetBSD-5.x, NetBSD-6.x,
+      FreeBSD 7.x, Solaris
+Bug fixes:
+    - Many bug fixes, see ChangeLog
+
+*** Notes specific to am-utils version 6.2a3
+
+- minor new ports:
+	i386-apple-darwin8.8.1
+	i386-pc-linux-centos4.4 (RHEL4 clone)
+	i386-pc-linux-fc6 (Fedora Core 6)
+	i386-pc-solaris2.11-nexentaos (GNU/OpenSolaris)
+	ia64-hp-hpux11.23 (gcc and cc)
+	powerpc-apple-darwin8.7.0
+
+- Bugs fixed:
+	* reduce annoying warnings from xstrlcpy when expanding options.
+	* translate '*' Sun maps correctly with "${key}"
+
+*** Notes specific to am-utils version 6.2a2
+
 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
@@ -11,21 +51,6 @@
 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.
 
@@ -41,10 +66,13 @@
 	i386-pc-linux-fc5 (Fedora Core 5)
 	i386-pc-linux-suse10.1 (beta 8)
 	i386-unknown-freebsd6.0 (RELEASE)
+	i386-unknown-freebsd6.1 (RELEASE)
 	i386-unknown-netbsdelf2.1
 	i386-unknown-netbsdelf3.0 (RELEASE)
 	i386-unknown-openbsd3.8
+	i386-unknown-openbsd3.9
 	powerpc-apple-darwin8.5.0
+	powerpc-apple-darwin8.6.0
 
 - Bugs fixed:
 	* one serious memory leak in amfs_generic (caught by Coverity)
@@ -51,35 +79,16 @@
 	* 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
+	* handle old-style filehandles correctly (for mount points longer
+	  than 28 chars)
 	* use-after-free bug in amfs_lookup_mntfs (Coverity)
+	* 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)
 
-*** Notes specific to am-utils version 6.1.3
+*** Notes specific to am-utils version 6.2a1
 
-- 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,
@@ -114,13 +123,82 @@
 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.
 
+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.
+
+Changed slightly how Amd behaves when you try to change log_options after
+Amd started (options can be turned on/off via "amq -x ARG").  It used to be
+that Amd won't let you turn off options which were on when Amd started.
+That limited users' ability to reduce Amd's logging levels to a minimum.
+Now, Amd will allow you to turn on/off any option, other than the two
+options "fatal" and "error."  Both are on by default and considered
+mandatory.  These two don't produce a lot of log messages, so your logs will
+remain small, but they are important to keep on, so Amd can report serious
+problems (including errors relating to incorrectly setting other log
+options).
+
+Amd now understands a new log_option called "defaults" which is synonymous
+with "fatal,error,user,warning,info" (and is also what logging happens by
+default).
+
+Amd now understands a new debug_option called "defaults" which is synonymous
+with "all,nohrtime,nomtab,noxdrtrace".
+
+Changed the misleading inverted logic of certain debug_options:
+
+1. "xdrtrace" is included in "all" because "all" (as the name implies),
+   should be *all* options, not just a subset.  If you want the old behavior
+   of "all" then use "defaults" (all only adds "xdrtrace" which can be
+   chatty on some systems).
+
+2. Certain debug options are hereby declared immutable: they may not be
+   changed by "amq -D" after Amd starts, because it doesn't make much sense
+   to change them after Amd starts, and it could really mess up Amd.  These
+   immutable flags are currently "daemon," "fork," "amq," and "mtab."
+
+3. the debug option "daemon" *will* cause Amd to daemonize.  Before, it was
+   causing Amd NOT to daemonize.  This was greatly confusing, especially
+   since the code, documentation, and comments often conflicted with each
+   other.  If you don't want Amd to daemonize, which is useful for debugging
+   it, then use the debug option "nodaemon" -- it makes a lot more sense.
+
+4. Similarly, the "fork" option *will* cause Hlfsd to fork.  Use "nofork" if
+   you don't want Hlfsd to fork.  This option is only applicable to Hlfsd.
+
+5. Similarly, the "amq" option, which is now on by default, will cause Amd
+   to register itself with the RPC portmapper (for Amq), as is done
+   normally.  If you don't want Amd to register with the portmapper, use
+   "noamq" -- this naming convention makes more sense.  This was also
+   confusingly documented and coded in places.
+
+   Note: unfortunately, these changes to the "daemon," "fork," and "amq"
+   debug options may be incompatible with people's previous use of Amd.
+   Some of you may have to update your amd.conf slightly or your startup
+   options (if they're hard-coded in your amd startup script).  Sorry, but
+   we have to fix those old problems sooner or later.  However, if you never
+   set any debug_options, or you used to "all," then you won't be affected
+   by the change in meaning of these three flags.
+
 - minor new ports:
 	i386-pc-linux-deb3.1
-	i386-unknown-netbsdelf3.0
+	i386-unknown-netbsdelf3.0 (BETA)
 	powerpc-apple-darwin8.2.0
 
-- bugs fixed:
-	* minor documentation corrections
+- Bugs fixed:
+	* abort with an error if yacc/lex programs not found
+	* 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
+	* 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
 
 *** Notes specific to am-utils version 6.1.1
 
@@ -328,7 +406,7 @@
   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".
+  file during debug-mtab mode.  The default path is "/tmp/mtab".
 
 - 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

Modified: trunk/contrib/amd/README
===================================================================
--- trunk/contrib/amd/README	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/README	2018-06-15 22:31:15 UTC (rev 11011)
@@ -81,7 +81,7 @@
 	./buildall -K
 
 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
+autoconf-2.68, automake-1.11.1, and libtool 2.2.6b 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.
@@ -94,9 +94,9 @@
 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 am-utils at am-utils.org.  Avoid reporting to my
-personal email address.  It is important to involve the whole list in bug
-fixes etc.
+[E] Report all bugs via Bugzilla or the am-utils list (see
+www.am-utils.org).  Avoid reporting to my personal email address.  It is
+important to involve the whole list in bug fixes etc.
 
 Good luck.
 

Modified: trunk/contrib/amd/README.attrcache
===================================================================
--- trunk/contrib/amd/README.attrcache	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/README.attrcache	2018-06-15 22:31:15 UTC (rev 11011)
@@ -122,8 +122,8 @@
 # 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 at am-utils.org, so we can record it in
-this file.
+above), please report it to us via Bugzilla or the am-utils mailing list
+(see www.am-utils.org), so we can record it in this file.
 
 Sincerely,
 Erez.

Modified: trunk/contrib/amd/README.ldap
===================================================================
--- trunk/contrib/amd/README.ldap	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/README.ldap	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 LDAP support for am-utils was originally done by Leif Johansson
-<leifj at it.su.se>.  He no longer maintains it.
+<leifj AT 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.
@@ -6,7 +6,7 @@
 
 The IANA has assigned the following Private Enterprise Number to:
 
-	10180  Am-utils Organization   Erez Zadok	ezk at am-utils.org
+	10180  Am-utils Organization   Erez Zadok	ezk AT am-utils.org
 
 There are three files in this directory that relate to LDAP:
 
@@ -33,8 +33,8 @@
 
 ------- Forwarded Message
 
-From: "IANA Private Enterprise Number" <iana-pen at icann.org>
-To: "Erez Zadok" <ezk at cs.columbia.edu>
+From: "IANA Private Enterprise Number" <iana-pen AT icann.org>
+To: "Erez Zadok" <ezk AT cs.columbia.edu>
 Subject: RE: Application for Enterprise-number (10180)
 Date: Sun, 15 Jul 2001 14:43:45 -0700
 
@@ -43,7 +43,7 @@
 The IANA has assigned the following Private Enterprise
 Number to:
 
-10180  Am-utils Organization   Erez Zadok                 ezk at am-utils.org
+10180  Am-utils Organization   Erez Zadok                 ezk AT am-utils.org
 
 Please notify the IANA if there is a change in your contact
 or company information.

Modified: trunk/contrib/amd/README.y2k
===================================================================
--- trunk/contrib/amd/README.y2k	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/README.y2k	2018-06-15 22:31:15 UTC (rev 11011)
@@ -8,10 +8,10 @@
 the log file, in whatever format is provided by your os/libc --- especially
 the ctime(3) call.
 
-However, on Friday, September 18th 1998, Matthew Crosby <mcrosby at ms.com>
+However, on Friday, September 18th 1998, Matthew Crosby <mcrosby AT ms.com>
 reported that they evaluated 6.0a16 and found it to be compliant.
 
-On March 26, 1999, Paul Balyoz <pbalyoz at sedona.ch.intel.com> submitted a
+On March 26, 1999, Paul Balyoz <pbalyoz AT sedona.ch.intel.com> submitted a
 patch to lostaltmail which makes it print Y2K compliant dates.  He used a
 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.
@@ -23,5 +23,4 @@
 ---
 Erez Zadok.
 Maintainer, am-utils package and am-utils list.
-Email: am-utils at am-utils.org
 WWW:   http://www.am-utils.org

Modified: trunk/contrib/amd/amd/am_ops.c
===================================================================
--- trunk/contrib/amd/amd/am_ops.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/am_ops.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -96,6 +92,11 @@
 #ifdef HAVE_FS_XFS
   &xfs_ops,			/* Unix (irix) F/S */
 #endif /* HAVE_FS_XFS */
+#ifdef HAVE_FS_EXT
+  &ext2_ops,			/* Unix (linux) F/S */
+  &ext3_ops,			/* Unix (linux) F/S */
+  &ext4_ops,			/* Unix (linux) F/S */
+#endif /* HAVE_FS_EXT */
 #ifdef HAVE_FS_EFS
   &efs_ops,			/* Unix (irix) F/S */
 #endif /* HAVE_FS_EFS */
@@ -111,6 +112,9 @@
 #ifdef HAVE_FS_CACHEFS
   &cachefs_ops,			/* caching F/S */
 #endif /* HAVE_FS_CACHEFS */
+#ifdef HAVE_FS_TMPFS
+  &tmpfs_ops,			/* /tmp (in memory) F/S */
+#endif /* HAVE_FS_TMPFS */
 #ifdef HAVE_FS_NULLFS
 /* FILL IN */			/* null (loopback) F/S */
 #endif /* HAVE_FS_NULLFS */
@@ -120,6 +124,12 @@
 #ifdef HAVE_FS_UMAPFS
 /* FILL IN */			/* uid/gid mapping F/S */
 #endif /* HAVE_FS_UMAPFS */
+#ifdef HAVE_FS_UDF
+  &udf_ops,			/* UDF F/S */
+#endif /* HAVE_FS_UDF */
+#ifdef HAVE_FS_LUSTRE
+  &lustre_ops,			/* Lustre */
+#endif /* HAVE_FS_LUSTRE */
 
   /*
    * These 4 should be last, in the order:
@@ -316,7 +326,7 @@
   char oneopt[80];		/* one option w/o value if any */
   char *revoneopt;		/* reverse of oneopt */
   size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */
-  char *s1 = strdup(opts1);	/* copy of opts1 to munge */
+  char *s1 = xstrdup(opts1);	/* copy of opts1 to munge */
 
   /* initialization */
   mnt2.mnt_opts = (char *) opts2;
@@ -327,13 +337,13 @@
        tmpstr;
        tmpstr = strtok(NULL, ",")) {
     /* copy option to temp buffer */
-    xstrlcpy(oneopt, tmpstr, 80);
+    xstrlcpy(oneopt, tmpstr, sizeof(oneopt));
     /* if option has a value such as rsize=1024, chop the value part */
-    if ((eq = haseq(oneopt)))
+    if ((eq = strchr(oneopt, '=')))
       *eq = '\0';
     /* find reverse option of oneopt */
     revoneopt = reverse_option(oneopt);
-    /* if option orits reverse exist in opts2, ignore it */
+    /* if option or its reverse exist in opts2, ignore it */
     if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt))
       continue;
     /* add option to returned string */
@@ -362,7 +372,7 @@
 ops_search(char *type)
 {
   am_ops **vp;
-  am_ops *rop = 0;
+  am_ops *rop = NULL;
   for (vp = vops; (rop = *vp); vp++)
     if (STREQ(rop->fs_type, type))
       break;
@@ -373,7 +383,7 @@
 am_ops *
 ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map)
 {
-  am_ops *rop = 0;
+  am_ops *rop = NULL;
   char *link_dir;
 
   /*
@@ -400,7 +410,7 @@
    * Otherwise skip past any leading '-'.
    */
   if (fo->opt_opts == 0)
-    fo->opt_opts = strdup("rw,defaults");
+    fo->opt_opts = xstrdup("rw,defaults");
   else if (*fo->opt_opts == '-') {
     /*
      * We cannot simply do fo->opt_opts++ here since the opts
@@ -408,7 +418,7 @@
      * So just reallocate the thing -- stolcke 11/11/94
      */
     char *old = fo->opt_opts;
-    fo->opt_opts = strdup(old + 1);
+    fo->opt_opts = xstrdup(old + 1);
     XFREE(old);
   }
 
@@ -426,7 +436,7 @@
       XFREE(fo->opt_opts);
       XFREE(fo->opt_remopts);
       fo->opt_opts = mergedstr;
-      fo->opt_remopts = strdup(mergedstr);
+      fo->opt_remopts = xstrdup(mergedstr);
     } else {
       char *mergedstr, *remmergedstr;
       mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts);
@@ -451,7 +461,7 @@
   /* 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);
+    link_dir = str3cat((char *) NULL, fo->opt_fs, "/", link_dir);
     normalize_slash(link_dir);
     XFREE(fo->opt_sublink);
     fo->opt_sublink = link_dir;
@@ -460,8 +470,7 @@
   /*
    * Check the filesystem is happy
    */
-  if (fo->fs_mtab)
-    XFREE(fo->fs_mtab);
+  XFREE(fo->fs_mtab);
 
   fo->fs_mtab = rop->fs_match(fo);
   if (fo->fs_mtab)

Modified: trunk/contrib/amd/amd/amd.8
===================================================================
--- trunk/contrib/amd/amd/amd.8	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amd.8	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
 .\" 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
+.\" 3. 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.
 .\"
@@ -36,10 +32,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: amd.8,v 1.1.1.4 2012-07-21 14:53:13 laffer1 Exp $
-.\" $FreeBSD$
+.\" File: am-utils/amd/amd.8
+.\" $FreeBSD: stable/10/contrib/amd/amd/amd.8 310490 2016-12-23 22:42:14Z cy $
 .\"
 .Dd January 2, 2006
 .Dt AMD 8
@@ -225,11 +220,13 @@
 in seconds, between attempts to dismount
 file systems that have exceeded their cached times.
 The default is 2 minutes.
+.TP
 .It Fl x Ar options
-Specify run-time logging options.
-The options are a comma separated
+Specify run-time logging options.  The options are a comma separated
 list chosen from:
-.Li fatal , error , user , warn , info , map , stats , all .
+.Li fatal, error, user, warn, info, map, stats, defaults, all .
+Note that "fatal" and "error" are mandatory and cannot be turned off.
+.TP
 .It Fl y Ar domain
 Specify an alternative
 .Tn NIS
@@ -236,9 +233,7 @@
 domain from which to fetch the
 .Tn NIS
 maps.
-The default is the system domain name.
-This option is ignored if
-.Tn NIS
+The default is the system domain name.  This option is ignored if NIS
 support is not available.
 .It Fl A Ar arch
 Specifies the OS architecture.
@@ -360,14 +355,15 @@
 A weird imagination is most useful to gain full advantage of all
 the features.
 .Sh SEE ALSO
-.Xr domainname 1 ,
-.Xr hostname 1 ,
-.Xr syslog 3 ,
-.Xr amd.conf 5 ,
-.Xr mtab 5 ,
-.Xr amq 8 ,
-.Xr mount 8 ,
-.Xr umount 8
+.Xr domainname 1,
+.Xr hostname 1,
+.Xr syslog 3.
+.Xr amd.conf 5,
+.Xr mtab 5,
+.Xr amq 8,
+.Xr automount 8,
+.Xr mount 8,
+.Xr umount 8,
 .Pp
 .Dq am-utils
 .Xr info 1

Modified: trunk/contrib/amd/amd/amd.c
===================================================================
--- trunk/contrib/amd/amd/amd.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amd.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -37,13 +33,13 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: amd.c,v 1.1.1.3 2012-07-21 14:53:13 laffer1 Exp $
+ * $Id: amd.c,v 1.8.2.6 2004/01/06 03:15:16 ezk Exp $
  * File: am-utils/amd/amd.c
  *
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: stable/10/contrib/amd/amd/amd.c 310490 2016-12-23 22:42:14Z cy $");
 
 /*
  * Automounter
@@ -379,7 +375,7 @@
 #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 */
+    madvise(NULL, 0, MADV_PROTECT); /* may be redundant of the above worked out */
 #endif /* defined(HAVE_MADVISE) && defined(MADV_PROTECT) */
 }
 
@@ -431,6 +427,7 @@
   if (gethostname(hostname, sizeof(hostname)) < 0) {
     plog(XLOG_FATAL, "gethostname: %m");
     going_down(1);
+    return 1;
   }
   hostname[sizeof(hostname) - 1] = '\0';
 
@@ -440,6 +437,7 @@
   if (!*hostname) {
     plog(XLOG_FATAL, "host name is not set");
     going_down(1);
+    return 1;
   }
 
   /*
@@ -498,7 +496,8 @@
   getwire(&PrimNetName, &PrimNetNum);
 
   /*
-   * Determine command-line arguments
+   * Determine command-line arguments.
+   * (Also initialize amd.conf parameters, maps, and more.)
    */
   get_args(argc, argv);
 
@@ -532,6 +531,7 @@
   if (geteuid() != 0) {
     plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %ld)", (long) geteuid());
     going_down(1);
+    return 1;
   }
 
 #ifdef HAVE_MAP_NIS
@@ -543,10 +543,11 @@
   if (gopt.nis_domain && yp_bind(gopt.nis_domain)) {
     plog(XLOG_FATAL, "Can't bind to NIS domain \"%s\"", gopt.nis_domain);
     going_down(1);
+    return 1;
   }
 #endif /* HAVE_MAP_NIS */
 
-  if (!amuDebug(D_DAEMON))
+  if (amuDebug(D_DAEMON))
     ppid = daemon_mode();
 
   /*

Modified: trunk/contrib/amd/amd/amd.h
===================================================================
--- trunk/contrib/amd/amd/amd.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amd.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -54,9 +50,12 @@
  * that support mtab on file.
  */
 #ifdef MOUNT_TABLE_ON_FILE
-# define DEBUG_MNTTAB_FILE               "/tmp/mnttab"
+# define DEBUG_MNTTAB_FILE		"/tmp/mtab"
 #endif /* MOUNT_TABLE_ON_FILE */
 
+/* Max line length that info services can handle */
+#define INFO_MAX_LINE_LEN		1500
+
 /* options for amd.conf */
 #define CFM_BROWSABLE_DIRS		0x00000001
 #define CFM_MOUNT_TYPE_AUTOFS		0x00000002 /* use kernel autofs support */
@@ -76,10 +75,7 @@
 #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 */
@@ -212,6 +208,7 @@
 typedef struct kv kv;
 typedef struct am_node am_node;
 typedef struct mntfs mntfs;
+typedef struct am_loc am_loc;
 typedef struct am_opts am_opts;
 typedef struct am_ops am_ops;
 typedef struct am_stats am_stats;
@@ -245,7 +242,7 @@
 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 int (*vreaddir) (am_node *, voidp, voidp, voidp, u_int);
 typedef am_node *(*vreadlink) (am_node *, int *);
 typedef void (*vmounted) (mntfs *);
 typedef void (*vumounted) (mntfs *);
@@ -252,6 +249,10 @@
 typedef fserver *(*vffserver) (mntfs *);
 typedef wchan_t (*vget_wchan) (mntfs *);
 
+/*
+ * NFS progran dispatcher
+ */
+typedef void (*dispatcher_t)(struct svc_req *rqstp, SVCXPRT *transp);
 
 
 /*
@@ -314,6 +315,7 @@
 #endif /* HAVE_MAP_NIS */
   char *nfs_proto;		/* NFS protocol (NULL, udp, tcp) */
   int nfs_vers;			/* NFS version (0, 2, 3, 4) */
+  int nfs_vers_ping;		/* NFS rpc ping version (0, 2, 3, 4) */
   u_int exec_map_timeout;	/* timeout (seconds) for executable maps */
 };
 
@@ -349,6 +351,7 @@
   short alloc;                  /* Allocation mode */
   time_t modify;                /* Modify time of map */
   u_int reloads;		/* Number of times map was reloaded */
+  u_int nentries;		/* Number of entries in the map */
   char *map_name;               /* Name of this map */
   char *wildcard;               /* Wildcard value */
   reload_fn *reload;            /* Function to be used for reloads */
@@ -420,7 +423,7 @@
   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_auto;		/* Mount info */
   char *mf_mopts;		/* FS mount opts */
   char *mf_remopts;		/* Remote FS mount opts */
   char *mf_loopdev;		/* loop device name for /dev/loop mounts */
@@ -435,6 +438,16 @@
 };
 
 /*
+ * Locations: bindings between keys and mntfs
+ */
+struct am_loc {
+  am_opts *al_fo;
+  mntfs *al_mnt;
+  int al_refc;
+};
+
+
+/*
  * List of fileservers
  */
 struct fserver {
@@ -463,6 +476,8 @@
   int s_readdir;		/* Count of readdirs */
   int s_readlink;		/* Count of readlinks */
   int s_statfs;			/* Count of statfs */
+  int s_fsinfo;			/* Count of fsinfo */
+  int s_pathconf;		/* Count of pathconf */
 };
 
 /*
@@ -482,8 +497,8 @@
  */
 struct am_node {
   int am_mapno;		/* Map number */
-  mntfs *am_mnt;	/* Mounted filesystem */
-  mntfs **am_mfarray;	/* Filesystem sources to try to mount */
+  am_loc *am_al;	/* Mounted filesystem */
+  am_loc **am_alarray;	/* 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 */
@@ -508,6 +523,7 @@
   autofs_fh_t *am_autofs_fh;
   time_t am_autofs_ttl;	/* Time to expire autofs nodes */
 #endif /* HAVE_FS_AUTOFS */
+  int am_fd[2];		/* parent child pipe fd's for sync umount */
 };
 
 /*
@@ -527,13 +543,18 @@
 extern int *amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp);
 extern int *amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp);
 extern voidp amqproc_null_1_svc(voidp argp, struct svc_req *rqstp);
-extern voidp amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp);
+extern int *amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp);
+extern int *amqproc_sync_umnt_1_svc_parent(voidp argp, struct svc_req *rqstp);
+extern amq_sync_umnt *amqproc_sync_umnt_1_svc_child(voidp argp, struct svc_req *rqstp);
+extern amq_sync_umnt *amqproc_sync_umnt_1_svc_async(voidp argp, struct svc_req *rqstp);
+extern amq_map_info_list *amqproc_getmapinfo_1_svc(voidp argp, struct svc_req *rqstp);
 
 /* other external definitions */
-extern am_nfs_fh *get_root_nfs_fh(char *dir);
+extern am_nfs_handle_t *get_root_nfs_fh(char *dir, am_nfs_handle_t *nfh);
 extern am_node *find_ap(char *);
 extern am_node *get_ap_child(am_node *, char *);
 extern bool_t xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead);
+extern bool_t xdr_amq_map_info_qelem(XDR *xdrs, qelem *qhead);
 extern fserver *find_nfs_srvr(mntfs *mf);
 extern int mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf);
 extern int process_all_regular_maps(void);
@@ -541,7 +562,8 @@
 extern int set_conf_kv(const char *section, const char *k, const char *v);
 extern int mount_node(opaque_t arg);
 extern int unmount_mp(am_node *mp);
-extern int yyparse (void);
+extern int conf_parse(void);	/* "yyparse" renamed */
+extern FILE *conf_in;		/* "yyin" renamed */
 
 extern void amfs_mkcacheref(mntfs *mf);
 extern int amfs_mount(am_node *mp, mntfs *mf, char *opts);
@@ -566,12 +588,15 @@
 extern void flush_nfs_fhandle_cache(fserver *);
 
 extern mntfs *dup_mntfs(mntfs *);
+extern am_loc *dup_loc(am_loc *);
 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 am_loc *new_loc(void);
 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 free_loc(voidp);
 
 
 extern void amq_program_1(struct svc_req *rqstp, SVCXPRT *transp);
@@ -579,9 +604,11 @@
 extern void deslashify(char *);
 extern void do_task_notify(void);
 extern int  eval_fs_opts(am_opts *, char *, char *, char *, char *, char *);
+extern int  file_read_line(char *, int, FILE *);
 extern void forcibly_timeout_mp(am_node *);
 extern void free_map(am_node *);
 extern void free_opts(am_opts *);
+extern am_opts *copy_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 *);
@@ -596,7 +623,7 @@
 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 mnt_map *mapc_find(char *, char *, const char *, const char *);
 extern void mapc_free(opaque_t);
 extern int  mapc_keyiter(mnt_map *, key_fun, opaque_t);
 extern void mapc_reload(void);
@@ -608,9 +635,11 @@
 extern int  mount_automounter(int);
 extern int  mount_exported(void);
 extern void mp_to_fh(am_node *, am_nfs_fh *);
+extern void mp_to_fh3(am_node *mp, am_nfs_fh3 *fhp);
 extern void new_ttl(am_node *);
 extern void nfs_quick_reply(am_node *mp, int error);
 extern void normalize_slash(char *);
+extern void notify_child(am_node *, au_etype, int, int);
 extern void ops_showamfstypes(char *buf, size_t l);
 extern void ops_showfstypes(char *outbuf, size_t l);
 extern void rem_que(qelem *);
@@ -639,8 +668,8 @@
 /*
  * Global variables.
  */
-extern FILE *yyin;
 extern SVCXPRT *current_transp; /* For nfs_quick_reply() */
+extern dispatcher_t nfs_dispatcher;
 extern char *conf_tag;
 #define SIZEOF_UID_STR	12
 #define SIZEOF_GID_STR	12
@@ -724,6 +753,19 @@
 #endif /* HAVE_FS_PCFS */
 
 /*
+ * UDF File System
+ * Many systems can't support this, and in any case most of the
+ * functionality is available with program FS.
+ */
+#ifdef HAVE_FS_UDF
+extern am_ops udf_ops;
+#endif /* HAVE_FS_UDF */
+
+#ifdef HAVE_FS_LUSTRE
+extern am_ops lustre_ops;
+#endif /* HAVE_FS_LUSTRE */
+
+/*
  * Caching File System (Solaris)
  */
 #ifdef HAVE_FS_CACHEFS
@@ -731,6 +773,12 @@
 #endif /* HAVE_FS_CACHEFS */
 
 /*
+ * In memory /tmp filesystem (Linux, NetBSD)
+ */
+#ifdef HAVE_FS_TMPFS
+extern am_ops tmpfs_ops;
+#endif /* HAVE_FS_TMPFS */
+/*
  * Network File System
  * Good, slow, NFS V.2.
  */
@@ -753,6 +801,13 @@
 extern am_ops xfs_ops;		/* Un*x file system */
 #endif /* HAVE_FS_XFS */
 
+/* Unix file system (ext*) */
+#ifdef HAVE_FS_EXT
+extern am_ops ext2_ops;		/* Un*x file system */
+extern am_ops ext3_ops;		/* Un*x file system */
+extern am_ops ext4_ops;		/* Un*x file system */
+#endif /* HAVE_FS_EXT */
+
 /* Unix file system (irix) */
 #ifdef HAVE_FS_EFS
 extern am_ops efs_ops;		/* Un*x file system */
@@ -772,7 +827,7 @@
  */
 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_readdir(am_node *mp, voidp cookie, voidp dp, voidp 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);
@@ -808,7 +863,8 @@
 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);
+extern int amfs_error_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count);
+
 #endif /* HAVE_AMU_FS_ERROR */
 
 /*

Modified: trunk/contrib/amd/amd/amfs_auto.c
===================================================================
--- trunk/contrib/amd/amd/amfs_auto.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_auto.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -101,6 +97,8 @@
 static int
 amfs_auto_mount(am_node *mp, mntfs *mf)
 {
+  if (mp->am_parent == NULL)
+    return EINVAL;
   /*
    * Pseudo-directories are used to provide some structure
    * to the automounted directories instead
@@ -115,7 +113,7 @@
    * Historical - not documented.
    */
   if (mf->mf_info[0] == '.' && mf->mf_info[1] == '\0')
-    mf->mf_info = strealloc(mf->mf_info, mp->am_parent->am_mnt->mf_info);
+    mf->mf_info = strealloc(mf->mf_info, mp->am_parent->am_al->al_mnt->mf_info);
 
   /*
    * Compute prefix:
@@ -131,12 +129,12 @@
   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 = strdup("");
+      mp->am_pref = xstrdup("");
     } else {
       /*
        * the prefix specified as an option
        */
-      mp->am_pref = strdup(mf->mf_fo->opt_pref);
+      mp->am_pref = xstrdup(mf->mf_fo->opt_pref);
     }
   } else {
     /*
@@ -147,7 +145,7 @@
     char *ppref = mp->am_parent->am_pref;
     if (ppref == 0)
       ppref = "";
-    mp->am_pref = str3cat((char *) 0, ppref, mp->am_name, "/");
+    mp->am_pref = str3cat((char *) NULL, ppref, mp->am_name, "/");
   }
 
 #ifdef HAVE_FS_AUTOFS

Modified: trunk/contrib/amd/amd/amfs_direct.c
===================================================================
--- trunk/contrib/amd/amd/amfs_direct.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_direct.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -93,8 +89,8 @@
 
   xp = next_nonerror_node(mp->am_child);
   if (!xp) {
-    if (!mp->am_mnt->mf_private)
-      amfs_mkcacheref(mp->am_mnt);	/* XXX */
+    if (!mp->am_al->al_mnt->mf_private)
+      amfs_mkcacheref(mp->am_al->al_mnt);
     xp = amfs_generic_lookup_child(mp, mp->am_path + 1, &rc, VLOOK_CREATE);
     if (xp && rc < 0)
       xp = amfs_generic_mount_child(xp, &rc);

Modified: trunk/contrib/amd/amd/amfs_error.c
===================================================================
--- trunk/contrib/amd/amd/amfs_error.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_error.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -92,7 +88,7 @@
 static char *
 amfs_error_match(am_opts *fo)
 {
-  return strdup("(error-hook)");
+  return xstrdup("(error-hook)");
 }
 
 
@@ -145,7 +141,7 @@
  * If we do then just give an error.
  */
 int
-amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
+amfs_error_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count)
 {
   return ESTALE;
 }

Modified: trunk/contrib/amd/amd/amfs_generic.c
===================================================================
--- trunk/contrib/amd/amd/amfs_generic.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_generic.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -55,7 +51,7 @@
 /****************************************************************************
  *** MACROS                                                               ***
  ****************************************************************************/
-#define	IN_PROGRESS(cp) ((cp)->mp->am_mnt->mf_flags & MFF_MOUNTING)
+#define	IN_PROGRESS(cp) ((cp)->mp->am_al->al_mnt->mf_flags & MFF_MOUNTING)
 
 
 /****************************************************************************
@@ -80,7 +76,7 @@
   int retry;			/* Try again? */
   time_t start;			/* Time we started this mount */
   int callout;			/* Callout identifier */
-  mntfs **mf;			/* Current mntfs */
+  am_loc **al;			/* Current location */
 };
 
 
@@ -88,9 +84,9 @@
  *** 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,
+static am_loc *amfs_lookup_one_location(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 am_loc **amfs_lookup_loc(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);
@@ -108,7 +104,7 @@
   int error = 0;		/* Error so far */
   int in_progress = 0;		/* # of (un)mount in progress */
   mntfs *mf;
-  char *expanded_fname = 0;
+  char *expanded_fname = NULL;
 
   dlog("in amfs_lookup_node");
 
@@ -118,7 +114,7 @@
    * about the mount point.
    */
   if (amd_state == Finishing) {
-    if (mp->am_mnt == 0 || mp->am_mnt->mf_fsflags & FS_DIRECT) {
+    if (mp->am_al == NULL || mp->am_al->al_mnt == NULL || mp->am_al->al_mnt->mf_fsflags & FS_DIRECT) {
       dlog("%s mount ignored - going down", fname);
     } else {
       dlog("%s/%s mount ignored - going down", mp->am_path, fname);
@@ -170,7 +166,7 @@
        * If the error code is undefined then it must be
        * in progress.
        */
-      mf = new_mp->am_mnt;
+      mf = new_mp->am_al->al_mnt;
       if (mf->mf_error < 0)
 	goto in_progrss;
 
@@ -240,7 +236,7 @@
    */
   new_mp = get_ap_child(mp, expanded_fname);
   XFREE(expanded_fname);
-  if (new_mp == 0)
+  if (new_mp == NULL)
     ereturn(ENOSPC);
 
   *error_return = -1;
@@ -249,19 +245,25 @@
 
 
 
-static mntfs *
-amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec,
-		      char *def_opts, char *pfname)
+static am_loc *
+amfs_lookup_one_location(am_node *new_mp, mntfs *mf, char *ivec,
+			char *def_opts, char *pfname)
 {
   am_ops *p;
   am_opts *fs_opts;
+  am_loc *new_al;
   mntfs *new_mf;
-  char *mp_dir = 0;
+  char *mp_dir = NULL;
 #ifdef HAVE_FS_AUTOFS
   int on_autofs = 1;
 #endif /* HAVE_FS_AUTOFS */
 
   /* match the operators */
+  /*
+   * although we alloc the fs_opts here, the pointer is 'owned' by the am_loc and will
+   * be free'd on destruction of the am_loc. If we don't allocate a loc, then we need
+   * to free this.
+   */
   fs_opts = CALLOC(am_opts);
   p = ops_match(fs_opts, ivec, def_opts, new_mp->am_path,
 		pfname, mf->mf_info);
@@ -269,7 +271,7 @@
   /* 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) {
+    if (fs_opts->opt_sublink && fs_opts->opt_sublink[0]) {
       /*
        * For sublinks we need to use a hack with autofs:
        * mount the filesystem on the original opt_fs (which is NOT an
@@ -292,6 +294,9 @@
 
   /*
    * Find or allocate a filesystem for this node.
+   * we search for a matching backend share, since
+   * we will construct our own al_loc to handle
+   * any customisations for this usage.
    */
   new_mf = find_mntfs(p, fs_opts,
 		      mp_dir,
@@ -300,6 +305,7 @@
 		      fs_opts->opt_opts,
 		      fs_opts->opt_remopts);
 
+
   /*
    * See whether this is a real filesystem
    */
@@ -307,10 +313,16 @@
   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);
+    free_opts(fs_opts);
+    XFREE(fs_opts);
     return NULL;
   }
 
   dlog("Got a hit with %s", p->fs_type);
+  new_al = new_loc();
+  free_mntfs(new_al->al_mnt);
+  new_al->al_mnt = new_mf;
+  new_al->al_fo = fs_opts; /* now the loc is in charge of free'ing this mem */
 
 #ifdef HAVE_FS_AUTOFS
   if (new_mp->am_flags & AMF_AUTOFS && on_autofs) {
@@ -332,12 +344,12 @@
     new_mf->mf_flags |= MFF_IS_AUTOFS;
 #endif /* HAVE_FS_AUTOFS */
 
-  return new_mf;
+  return new_al;
 }
 
 
-static mntfs **
-amfs_lookup_mntfs(am_node *new_mp, int *error_return)
+static am_loc **
+amfs_lookup_loc(am_node *new_mp, int *error_return)
 {
   am_node *mp;
   char *info;			/* Mount info - where to get the file system */
@@ -348,10 +360,11 @@
   int error = 0;		/* Error so far */
   char path_name[MAXPATHLEN];	/* General path name buffer */
   char *pfname;			/* Path for database lookup */
-  mntfs *mf, **mf_array;
+  mntfs* mf;			/* The mntfs for the map of our parent */
+  am_loc **al_array;		/* the generated list of locations */
   int count;
 
-  dlog("in amfs_lookup_mntfs");
+  dlog("in amfs_lookup_loc");
 
   mp = new_mp->am_parent;
 
@@ -369,7 +382,7 @@
     pfname = new_mp->am_name;
   }
 
-  mf = mp->am_mnt;
+  mf = mp->am_al->al_mnt;
 
   dlog("will search map info in %s to find %s", mf->mf_info, pfname);
   /*
@@ -404,8 +417,8 @@
   else
     def_opts = "";
 
-  orig_def_opts = amfs_parse_defaults(mp, mf, strdup(def_opts));
-  def_opts = strdup(orig_def_opts);
+  orig_def_opts = amfs_parse_defaults(mp, mf, xstrdup(def_opts));
+  def_opts = xstrdup(orig_def_opts);
 
   /* first build our defaults */
   num_ivecs = 0;
@@ -423,11 +436,11 @@
       num_ivecs++;
   }
 
-  mf_array = calloc(num_ivecs + 1, sizeof(mntfs *));
+  al_array = calloc(num_ivecs + 1, sizeof(am_loc *));
 
-  /* construct the array of struct mntfs for this mount point */
+  /* construct the array of struct locations for this key */
   for (count = 0, cur_ivec = ivecs; *cur_ivec; cur_ivec++) {
-    mntfs *new_mf;
+    am_loc *new_al;
 
     if (**cur_ivec == '-') {
       XFREE(def_opts);
@@ -436,11 +449,11 @@
 	 * If we have a single dash '-' than we need to reset the
 	 * default options.
 	 */
-	def_opts = strdup(orig_def_opts);
+	def_opts = xstrdup(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);
+	def_opts = str3cat((char *) NULL, orig_def_opts, ";", *cur_ivec + 1);
 	dlog("Resetting def_opts to \"%s\"", def_opts);
       }
       continue;
@@ -447,7 +460,7 @@
     }
 
     /*
-     * If a mntfs has already been found, and we find
+     * If a loc 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 "||".
@@ -455,16 +468,16 @@
      */
     if (STREQ(*cur_ivec, "/") || STREQ(*cur_ivec, "||")) {
       if (count > 0) {
-	dlog("Cut: not trying any more locations for %s", mp->am_path);
+	dlog("Cut: not trying any more locations for %s", pfname);
 	break;
       }
       continue;
     }
 
-    new_mf = amfs_lookup_one_mntfs(new_mp, mf, *cur_ivec, def_opts, pfname);
-    if (new_mf == NULL)
+    new_al = amfs_lookup_one_location(new_mp, mf, *cur_ivec, def_opts, pfname);
+    if (new_al == NULL)
       continue;
-    mf_array[count++] = new_mf;
+    al_array[count++] = new_al;
   }
 
   /* We're done with ivecs */
@@ -473,11 +486,11 @@
   XFREE(orig_def_opts);
   XFREE(def_opts);
   if (count == 0) {			/* no match */
-    XFREE(mf_array);
+    XFREE(al_array);
     ereturn(ENOENT);
   }
 
-  return mf_array;
+  return al_array;
 }
 
 
@@ -491,7 +504,7 @@
 {
   struct continuation *cp = (struct continuation *) arg;
   am_node *mp = cp->mp;
-  mntfs *mf = mp->am_mnt;
+  mntfs *mf = mp->am_al->al_mnt;
 
   dlog("amfs_cont: '%s'", mp->am_path);
 
@@ -556,7 +569,7 @@
 	mf->mf_error = rc;
 	mf->mf_flags |= MFF_ERROR;
 	errno = rc;		/* XXX */
-	if (!STREQ(mp->am_mnt->mf_ops->fs_type, "linkx"))
+	if (!STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "linkx"))
 	  plog(XLOG_ERROR, "%s: mount (amfs_cont): %m", mp->am_path);
       }
     }
@@ -568,7 +581,7 @@
        * call the background mount routine again
        */
       amd_stats.d_merr++;
-      cp->mf++;
+      cp->al++;
     }
     amfs_bgmount(cp);
     if (mp->am_error > 0)
@@ -608,13 +621,21 @@
      */
     plog(XLOG_INFO, "mount of \"%s\" has timed out", mp->am_path);
     error = ETIMEDOUT;
-    while (*cp->mf)
-      cp->mf++;
+    while (*cp->al)
+      cp->al++;
     /* explicitly forbid further retries after timeout */
     cp->retry = FALSE;
   }
   if (error || !IN_PROGRESS(cp))
     error = amfs_bgmount(cp);
+  else
+    /* Normally it's amfs_bgmount() which frees the continuation. However, if
+     * the mount is already in progress and we're in amfs_retry() for another
+     * node we don't try mounting the filesystem once again. Still, we have
+     * to free the continuation as we won't get called again and thus would
+     * leak the continuation structure and our am_loc references.
+     */
+    free_continuation(cp);
 
   reschedule_timeout_mp();
 }
@@ -626,7 +647,7 @@
 static void
 free_continuation(struct continuation *cp)
 {
-  mntfs **mfp;
+  am_loc **alp;
 
   dlog("free_continuation");
   if (cp->callout)
@@ -634,13 +655,12 @@
   /*
    * 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);
+  for (alp = cp->mp->am_alarray; *alp; alp++) {
+    free_loc(*alp);
   }
-  XFREE(cp->mp->am_mfarray);
-  cp->mp->am_mfarray = 0;
+  XFREE(cp->mp->am_alarray);
+  cp->mp->am_alarray = 0;
   XFREE(cp);
 }
 
@@ -690,12 +710,13 @@
 amfs_bgmount(struct continuation *cp)
 {
   am_node *mp = cp->mp;
-  mntfs *mf;			/* Current mntfs */
+  am_loc *loc;
+  mntfs *mf;
   int this_error = -1;		/* Per-mount error */
   int hard_error = -1;		/* Cumulative per-node error */
 
-  if (mp->am_mnt)
-    free_mntfs(mp->am_mnt);
+  if (mp->am_al)
+    free_loc(mp->am_al);
 
   /*
    * Try to mount each location.
@@ -704,10 +725,11 @@
    * 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) {
+  for (mp->am_al = *cp->al; *cp->al; cp->al++, mp->am_al = *cp->al) {
     am_ops *p;
 
-    mf = dup_mntfs(mp->am_mnt);
+    loc = dup_loc(mp->am_al);
+    mf = loc->al_mnt;
     p = mf->mf_ops;
 
     if (hard_error < 0)
@@ -737,13 +759,12 @@
       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);
+    XFREE(mp->am_link);
+    mp->am_link = NULL;
 
+    if (loc->al_fo && loc->al_fo->opt_sublink && loc->al_fo->opt_sublink[0])
+      mp->am_link = xstrdup(loc->al_fo->opt_sublink);
+
     /*
      * Will usually need to play around with the mount nodes
      * file attribute structure.  This must be done here.
@@ -784,13 +805,13 @@
     if (this_error < 0)
       goto retry;
 
-    if (mf->mf_fo && mf->mf_fo->opt_delay) {
+    if (loc->al_fo && loc->al_fo->opt_delay) {
       /*
-       * If there is a delay timer on the mount
+       * If there is a delay timer on the location
        * then don't try to mount if the timer
        * has not expired.
        */
-      int i = atoi(mf->mf_fo->opt_delay);
+      int i = atoi(loc->al_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));
@@ -866,22 +887,25 @@
     return -1;
 
   failed:
-    amd_stats.d_merr++;
-    mf->mf_error = this_error;
-    mf->mf_flags |= MFF_ERROR;
+    if (!FSRV_ISDOWN(mf->mf_server)) {
+      /* mark the mount as failed unless the server is down */
+      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);
+      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;
+      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);
+    free_loc(loc);
     /* continue */
   }
 
@@ -890,7 +914,10 @@
    * there is no more mount information available.
    */
   if (this_error) {
-    mp->am_mnt = mf = new_mntfs();
+    if (mp->am_al)
+      free_loc(mp->am_al);
+    mp->am_al = loc = new_loc();
+    mf = loc->al_mnt;
 
 #ifdef HAVE_FS_AUTOFS
     if (mp->am_flags & AMF_AUTOFS)
@@ -920,7 +947,7 @@
     }
     new_ttl(mp);
   } else {
-    mf = mp->am_mnt;
+    mf = loc->al_mnt;
     /*
      * Wakeup anything waiting for this mount
      */
@@ -959,19 +986,10 @@
 
   /*
    * 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);
+    dflts = xstrdup(mm->cfm->cfm_defaults);
   } else if (mapc_search(mm, "/defaults", &dflts) == 0) {
     dlog("/defaults gave %s", dflts);
   } else {
@@ -1009,7 +1027,7 @@
 	 * get expanded to "/defaults"
 	 */
 	pt = ops_match(&ap, *sp, "", mp->am_path, "/defaults",
-		       mp->am_parent->am_mnt->mf_info);
+		       mp->am_parent->am_al->al_mnt->mf_info);
 	free_opts(&ap);	/* don't leak */
 	if (pt == &amfs_error_ops) {
 	  plog(XLOG_MAP, "did not match defaults for \"%s\"", *sp);
@@ -1076,8 +1094,9 @@
   *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;
+  if (new_mp->am_al)
+    free_loc(new_mp->am_al);
+  new_mp->am_al = NULL;
 
   /*
    * Construct a continuation
@@ -1087,7 +1106,7 @@
   cp->mp = new_mp;
   cp->retry = TRUE;
   cp->start = clocktime(NULL);
-  cp->mf = new_mp->am_mfarray;
+  cp->al = new_mp->am_alarray;
 
   /*
    * Try and mount the file system.  If this succeeds immediately (possible
@@ -1101,7 +1120,7 @@
 
   /*
    * 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
+   * transp that's been passed down from nfs_dispatcher() 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
@@ -1113,7 +1132,8 @@
     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))
+  if (error && new_mp->am_al && new_mp->am_al->al_mnt &&
+      (new_mp->am_al->al_mnt->mf_ops == &amfs_error_ops))
     new_mp->am_error = error;
 
   if (new_mp->am_error > 0)
@@ -1132,7 +1152,7 @@
 amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op)
 {
   am_node *new_mp;
-  mntfs **mf_array;
+  am_loc **al_array;
   int mp_error;
 
   dlog("in amfs_generic_lookup_child");
@@ -1145,7 +1165,7 @@
     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))
+  if (*error_return == 0 && FSRV_ISUP(new_mp->am_al->al_mnt->mf_server))
     return new_mp;
 
   switch (op) {
@@ -1161,42 +1181,15 @@
   /* 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;
+  al_array = amfs_lookup_loc(new_mp, error_return);
+  if (!al_array) {
+    new_mp->am_error = new_mp->am_al->al_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;
+  new_mp->am_alarray = al_array;
 
   /*
    * Note: while it might seem like a good idea to prioritize
@@ -1258,5 +1251,5 @@
   /*
    * mtab entry turns out to be the name of the mount map
    */
-  return strdup(fo->opt_rfs ? fo->opt_rfs : ".");
+  return xstrdup(fo->opt_rfs ? fo->opt_rfs : ".");
 }

Modified: trunk/contrib/amd/amd/amfs_host.c
===================================================================
--- trunk/contrib/amd/amd/amfs_host.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_host.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -227,7 +223,14 @@
 
   plog(XLOG_INFO, "fetch_fhandle: NFS version %d", (int) nfs_version);
 #ifdef HAVE_FS_NFS3
-  if (nfs_version == NFS_VERSION3) {
+  if (nfs_version == NFS_VERSION3
+#ifdef HAVE_FS_NFS4
+#ifndef NO_FALLBACK
+      || nfs_version == NFS_VERSION4
+#endif /* NO_FALLBACK */
+#endif /* HAVE_FS_NFS4 */
+    ) {
+
     memset((char *) &res3, 0, sizeof(res3));
     clnt_stat = clnt_call(client,
 			  MOUNTPROC_MNT,
@@ -303,8 +306,8 @@
   int n_export;
   int j, k;
   exports exlist = 0, ex;
-  exports *ep = 0;
-  am_nfs_handle_t *fp = 0;
+  exports *ep = NULL;
+  am_nfs_handle_t *fp = NULL;
   char *host;
   int error = 0;
   struct sockaddr_in sin;
@@ -449,13 +452,13 @@
     /* Check and avoid a duplicated export entry */
     if (j > k && ep[k] && STREQ(ep[j]->ex_dir, ep[k]->ex_dir)) {
       dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir);
-      ep[j] = 0;
+      ep[j] = NULL;
     } else {
       k = j;
       error = fetch_fhandle(client, ep[j]->ex_dir, &fp[j],
 			    mf->mf_server->fs_version);
       if (error)
-	ep[j] = 0;
+	ep[j] = NULL;
     }
   }
 
@@ -465,8 +468,8 @@
    * error code 0 at the end.  If they all fail then return
    * the last error code.
    */
-  xstrlcpy(fs_name, mf->mf_info, MAXPATHLEN);
-  if ((rfs_dir = strchr(fs_name, ':')) == (char *) 0) {
+  xstrlcpy(fs_name, mf->mf_info, sizeof(fs_name));
+  if ((rfs_dir = strchr(fs_name, ':')) == (char *) NULL) {
     plog(XLOG_FATAL, "amfs_host_mount: mf_info has no colon");
     error = EINVAL;
     goto out;
@@ -493,10 +496,8 @@
    */
 out:
   discard_mntlist(mlist);
-  if (ep)
-    XFREE(ep);
-  if (fp)
-    XFREE(fp);
+  XFREE(ep);
+  XFREE(fp);
   if (sock != RPC_ANYSOCK)
     (void) amu_close(sock);
   if (client)
@@ -554,7 +555,7 @@
    * Reverse list...
    */
   ml = mlist;
-  mprev = 0;
+  mprev = NULL;
   while (ml) {
     mntlist *ml2 = ml->mnext;
     ml->mnext = mprev;

Modified: trunk/contrib/amd/amd/amfs_link.c
===================================================================
--- trunk/contrib/amd/amd/amfs_link.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_link.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -109,13 +105,13 @@
    */
   if (fo->opt_fs[0] == '/') {
     char *link_hack = str3cat(NULL, ".", fo->opt_fs, "");
-    if (!fo->opt_sublink)
-      fo->opt_sublink = strdup(fo->opt_fs);
+    if (fo->opt_sublink == NULL || fo->opt_sublink[0] == '\0')
+      fo->opt_sublink = xstrdup(fo->opt_fs);
     XFREE(fo->opt_fs);
     fo->opt_fs = link_hack;
   }
 
-  return strdup(fo->opt_fs);
+  return xstrdup(fo->opt_fs);
 }
 
 

Modified: trunk/contrib/amd/amd/amfs_linkx.c
===================================================================
--- trunk/contrib/amd/amd/amfs_linkx.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_linkx.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/amd/amfs_nfsl.c
===================================================================
--- trunk/contrib/amd/amd/amfs_nfsl.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_nfsl.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -101,7 +97,7 @@
   char *retval;
   struct stat stb;
 
-  if (fo->opt_sublink)
+  if (fo->opt_sublink && fo->opt_sublink[0])
     cp = fo->opt_sublink;
   else
     cp = fo->opt_fs;
@@ -116,8 +112,9 @@
    * 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);
+  if (!STRCEQ(ho, am_get_hostname()) && !STRCEQ(ho, hostd)) {
+    plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not the local host \"%s\", "
+	"or \"%s\" using type:=nfs", ho, am_get_hostname(), hostd);
     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);
@@ -213,11 +210,16 @@
 static fserver *
 amfs_nfsl_ffserver(mntfs *mf)
 {
-  char *cp;
-  char *ho = mf->mf_fo->opt_rhost;
+  char *cp, *ho;
   struct stat stb;
 
-  if (mf->mf_fo->opt_sublink)
+  if (mf->mf_fo == NULL) {
+    plog(XLOG_ERROR, "%s: NULL mf_fo", __func__);
+    return NULL;
+  }
+  ho = mf->mf_fo->opt_rhost;
+
+  if (mf->mf_fo->opt_sublink && mf->mf_fo->opt_sublink[0])
     cp = mf->mf_fo->opt_sublink;
   else
     cp = mf->mf_fo->opt_fs;
@@ -227,7 +229,8 @@
    * 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) {
+  if ((!STRCEQ(ho, am_get_hostname()) &&
+       !STRCEQ(ho, hostd)) || lstat(cp, &stb) < 0) {
     return nfs_ops.ffserver(mf);
   } else {
     mf->mf_flags |= MFF_NFSLINK;

Modified: trunk/contrib/amd/amd/amfs_nfsx.c
===================================================================
--- trunk/contrib/amd/amd/amfs_nfsx.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_nfsx.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -118,7 +114,7 @@
   }
 
   /* set default sublink */
-  if (fo->opt_sublink == 0) {
+  if (fo->opt_sublink == NULL || fo->opt_sublink[0] == '\0') {
     ptr = strchr(fo->opt_rfs, ',');
     if (ptr && ptr > (fo->opt_rfs + 1))
       fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1);
@@ -149,7 +145,7 @@
   /*
    * Determine magic cookie to put in mtab
    */
-  xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs);
+  xmtab = str3cat((char *) NULL, fo->opt_rhost, ":", fo->opt_rfs);
   dlog("NFSX: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
        fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
 
@@ -190,12 +186,15 @@
 
   if (nx == 0) {
     char **ivec;
-    char *info = 0;
+    char *info = NULL;
     char *host;
     char *pref;
     int error = 0;
 
-    info = strdup(mf->mf_info);
+    info = xstrdup(mf->mf_info);
+    if (info == NULL)
+      return errno;
+
     host = strchr(info, ':');
     if (!host) {
       error = EINVAL;
@@ -221,12 +220,12 @@
 
     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;
+    nx->nx_mp = NULL;
     {
-      char *mp = 0;
-      char *xinfo = 0;
+      char *mp = NULL;
+      char *xinfo = NULL;
       char *fs = mf->mf_fo->opt_fs;
-      char *rfs = 0;
+      char *rfs = NULL;
       for (i = 0; i < nx->nx_c; i++) {
 	char *path = ivec[i + 1];
 	rfs = str3cat(rfs, pref, "/", path);
@@ -251,18 +250,14 @@
 	/* propagate the on_autofs flag */
 	nx->nx_v[i].n_mnt->mf_flags |= mf->mf_flags & MFF_ON_AUTOFS;
       }
-      if (rfs)
-	XFREE(rfs);
-      if (mp)
-	XFREE(mp);
-      if (xinfo)
-	XFREE(xinfo);
+      XFREE(rfs);
+      XFREE(mp);
+      XFREE(xinfo);
     }
 
     XFREE(ivec);
   errexit:
-    if (info)
-      XFREE(info);
+    XFREE(info);
     if (error)
       return error;
   }
@@ -503,7 +498,7 @@
 	}
       }
       free_mntfs(m);
-      n->n_mnt = 0;
+      n->n_mnt = NULL;
       n->n_error = -1;
     }
   }

Modified: trunk/contrib/amd/amd/amfs_program.c
===================================================================
--- trunk/contrib/amd/amd/amfs_program.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_program.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -105,7 +101,7 @@
   }
   prog = strchr(fo->opt_mount, ' ');
 
-  return strdup(prog ? prog + 1 : fo->opt_mount);
+  return xstrdup(prog ? prog + 1 : fo->opt_mount);
 }
 
 
@@ -116,11 +112,14 @@
   if (mf->mf_private != NULL)
     return 0;
 
+  if (mf->mf_fo == 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);
+    mf->mf_private = (opaque_t) xstrdup(mf->mf_fo->opt_unmount);
   else
-    mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_umount);
+    mf->mf_private = (opaque_t) xstrdup(mf->mf_fo->opt_umount);
   mf->mf_prfree = (void (*)(opaque_t)) free;
 
   return 0;
@@ -136,9 +135,7 @@
   /*
    * Split copy of command info string
    */
-  info = strdup(info);
-  if (info == 0)
-    return ENOBUFS;
+  info = xstrdup(info);
   xivec = strsplit(info, ' ', '\'');
 
   /*
@@ -147,10 +144,12 @@
   (void) fclose(stdout);
   if (!logfp)
     logfp = stderr;		/* initialize before possible first use */
-  (void) dup(fileno(logfp));
+    if (dup(fileno(logfp)) == -1)
+      goto out;
   if (fileno(logfp) != fileno(stderr)) {
     (void) fclose(stderr);
-    (void) dup(fileno(logfp));
+    if (dup(fileno(logfp)) == -1)
+      goto out;
   }
 
   /*
@@ -170,13 +169,16 @@
     plog(XLOG_USER, "1st/2nd args missing to (un)mount program");
   } else {
     (void) execv(xivec[0], xivec + 1);
+    error = errno;
+    plog(XLOG_ERROR, "exec failed: %m");
+    errno = error;
   }
 
+out:
   /*
    * Save error number
    */
   error = errno;
-  plog(XLOG_ERROR, "exec failed: %m");
 
   /*
    * Free allocate memory

Modified: trunk/contrib/amd/amd/amfs_root.c
===================================================================
--- trunk/contrib/amd/amd/amfs_root.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_root.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -92,7 +88,7 @@
 amfs_root_mount(am_node *mp, mntfs *mf)
 {
   mf->mf_mount = strealloc(mf->mf_mount, pid_fsname);
-  mf->mf_private = (opaque_t) mapc_find(mf->mf_info, "", NULL);
+  mf->mf_private = (opaque_t) mapc_find(mf->mf_info, "", NULL, NULL);
   mf->mf_prfree = mapc_free;
 
   return 0;

Modified: trunk/contrib/amd/amd/amfs_toplvl.c
===================================================================
--- trunk/contrib/amd/amd/amfs_toplvl.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_toplvl.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -148,7 +144,7 @@
 {
   int error = 0;
 
-#if defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)
+#if (defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)) && (defined(HAVE_UVMOUNT) || defined(HAVE_UMOUNT2))
   if (gopt.flags & CFM_FORCED_UNMOUNTS) {
     plog(XLOG_INFO, "amfs_toplvl_init: trying forced/lazy unmount of %s",
 	 mf->mf_mount);
@@ -158,7 +154,7 @@
     else
       dlog("amfs_toplvl_init: forced/lazy unmount succeeded");
   }
-#endif /* MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH */
+#endif /* (MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH) && (HAVE_UVMOUNT || HAVE_UMOUNT2) */
   return error;
 }
 
@@ -227,6 +223,11 @@
       xstrlcat(opts, toplvl_opts, sizeof(opts));
     }
 
+#ifdef MNTTAB_OPT_NOLOCK
+    xstrlcat(opts, ",", sizeof(opts));
+    xstrlcat(opts, MNTTAB_OPT_NOLOCK, sizeof(opts));
+#endif /* MNTTAB_OPT_NOLOCK */
+
 #ifdef MNTTAB_OPT_NOAC
     if (gopt.auto_attrcache == 0) {
       xstrlcat(opts, ",", sizeof(opts));

Modified: trunk/contrib/amd/amd/amfs_union.c
===================================================================
--- trunk/contrib/amd/amd/amfs_union.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amfs_union.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -95,7 +91,7 @@
     am_node *am;
     am = amfs_generic_lookup_child(arg, dir, &error, VLOOK_CREATE);
     if (am && error < 0)
-      am = amfs_generic_mount_child(am, &error);
+      (void)amfs_generic_mount_child(am, &error);
     if (error > 0) {
       errno = error;		/* XXX */
       plog(XLOG_ERROR, "unionfs: could not mount %s: %m", dir);
@@ -121,9 +117,9 @@
   for (mp = get_first_exported_ap(&index);
        mp;
        mp = get_next_exported_ap(&index)) {
-    if (mp->am_mnt == mf) {
+    if (mp->am_al->al_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) mapc_keyiter((mnt_map *) mp->am_al->al_mnt->mf_private,
 			  create_amfs_union_node,
 			  mp);
       break;

Modified: trunk/contrib/amd/amd/amq_subr.c
===================================================================
--- trunk/contrib/amd/amd/amq_subr.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amq_subr.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -80,20 +76,72 @@
 /*
  * Unmount a single node
  */
-voidp
+int *
 amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp)
 {
-  static char res;
+  static int res = AMQ_UMNT_OK;
   am_node *mp = find_ap(*(char **) argp);
 
   if (mp)
     forcibly_timeout_mp(mp);
 
-  return (voidp) &res;
+  return &res;
 }
 
 
 /*
+ * Synchronously unmount a single node - parent side.
+ */
+int *
+amqproc_sync_umnt_1_svc_parent(voidp argp, struct svc_req *rqstp)
+{
+  amqproc_umnt_1_svc(argp, rqstp);
+  return NULL;
+}
+
+
+/*
+ * Synchronously unmount a single node - child side.
+ */
+amq_sync_umnt *
+amqproc_sync_umnt_1_svc_child(voidp argp, struct svc_req *rqstp)
+{
+  static amq_sync_umnt rv;
+  amq_sync_umnt buf;
+  ssize_t n;
+
+  am_node *mp = find_ap(*(char **) argp);
+
+  memset(&rv, 0, sizeof(rv));
+  rv.au_etype = AMQ_UMNT_READ;
+  if (mp && mp->am_fd[0] >= 0) {
+    n = read(mp->am_fd[0], &buf, sizeof(buf));
+    if (n == sizeof(buf))
+      rv = buf;
+  }
+  return &rv;
+}
+
+
+/*
+ * Synchronously unmount a single node - use if we can't fork (asynchronous).
+ */
+amq_sync_umnt *
+amqproc_sync_umnt_1_svc_async(voidp argp, struct svc_req *rqstp)
+{
+  static amq_sync_umnt rv;
+
+  memset(&rv, 0, sizeof(rv));
+  rv.au_etype = AMQ_UMNT_FORK;
+  rv.au_errno = errno;
+
+  amqproc_umnt_1_svc(argp, rqstp);
+
+  return &rv;
+}
+
+
+/*
  * Return global statistics
  */
 amq_mount_stats *
@@ -170,6 +218,12 @@
   return (amq_mount_info_list *) ((void *)&mfhead);	/* XXX */
 }
 
+extern qelem map_list_head;
+amq_map_info_list *
+amqproc_getmapinfo_1_svc(voidp argp, struct svc_req *rqstp)
+{
+  return (amq_map_info_list *) ((void *)&map_list_head);	/* XXX */
+}
 
 amq_string *
 amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp)
@@ -218,11 +272,11 @@
     for (mp = get_first_exported_ap(&index);
 	 mp;
 	 mp = get_next_exported_ap(&index)) {
-      if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl"))
+      if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "toplvl"))
 	continue;
-      if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto"))
+      if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "auto"))
 	continue;
-      mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
+      mountpoint = (mp->am_link ? mp->am_link : mp->am_al->al_mnt->mf_mount);
       len = strlen(mountpoint);
       if (len == 0)
 	continue;
@@ -277,16 +331,16 @@
   am_node *mp = (am_node *) objp;
   long mtime;
 
-  if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_info)) {
+  if (!xdr_amq_string(xdrs, &mp->am_al->al_mnt->mf_info)) {
     return (FALSE);
   }
   if (!xdr_amq_string(xdrs, &mp->am_path)) {
     return (FALSE);
   }
-  if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_mnt->mf_mount)) {
+  if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_al->al_mnt->mf_mount)) {
     return (FALSE);
   }
-  if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_ops->fs_type)) {
+  if (!xdr_amq_string(xdrs, &mp->am_al->al_mnt->mf_ops->fs_type)) {
     return (FALSE);
   }
   mtime = mp->am_stats.s_mtime;
@@ -412,10 +466,6 @@
 }
 
 
-
-/*
- * Compute length of list
- */
 bool_t
 xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead)
 {
@@ -422,6 +472,9 @@
   mntfs *mf;
   u_int len = 0;
 
+  /*
+   * Compute length of list
+   */
   for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) {
     if (!(mf->mf_fsflags & FS_AMQINFO))
       continue;
@@ -468,7 +521,71 @@
   return (TRUE);
 }
 
+bool_t
+xdr_amq_map_info_qelem(XDR *xdrs, qelem *qhead)
+{
+  mnt_map *m;
+  u_int len = 0;
+  int x;
+  char *n;
 
+  /*
+   * Compute length of list
+   */
+  ITER(m, mnt_map, qhead) {
+     len++;
+  }
+
+  if (!xdr_u_int(xdrs, &len))
+      return (FALSE);
+
+  /*
+   * Send individual data items
+   */
+  ITER(m, mnt_map, qhead) {
+    if (!xdr_amq_string(xdrs, &m->map_name)) {
+      return (FALSE);
+    }
+
+    n = m->wildcard ? m->wildcard : "";
+    if (!xdr_amq_string(xdrs, &n)) {
+      return (FALSE);
+    }
+
+    if (!xdr_long(xdrs, (long *) &m->modify)) {
+      return (FALSE);
+    }
+
+    x = m->flags;
+    if (!xdr_int(xdrs, &x)) {
+      return (FALSE);
+    }
+
+    x = m->nentries;
+    if (!xdr_int(xdrs, &x)) {
+      return (FALSE);
+    }
+
+    x = m->reloads;
+    if (!xdr_int(xdrs, &x)) {
+      return (FALSE);
+    }
+
+    if (!xdr_int(xdrs, &m->refc)) {
+      return (FALSE);
+    }
+
+    if (m->isup)
+      x = (*m->isup)(m, m->map_name);
+    else
+      x = -1;
+    if (!xdr_int(xdrs, &x)) {
+      return (FALSE);
+    }
+  }
+  return (TRUE);
+}
+
 bool_t
 xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr)
 {

Modified: trunk/contrib/amd/amd/amq_svc.c
===================================================================
--- trunk/contrib/amd/amd/amq_svc.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/amq_svc.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -57,7 +53,7 @@
  * 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;
+int allow_severity=0, deny_severity=0, rfc931_timeout=0;
 # endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */
 
 /*
@@ -65,49 +61,88 @@
  * Returns: 1=allowed, 0=denied.
  */
 static int
-amqsvc_is_client_allowed(const struct sockaddr_in *addr, char *remote)
+amqsvc_is_client_allowed(const struct sockaddr_in *addr)
 {
-  struct hostent *h;
-  char *name = NULL, **ad;
-  int ret = 0;			/* default is 0==denied */
+  struct request_info req;
 
-  /* Check IP address */
-  if (hosts_ctl(AMD_SERVICE_NAME, "", remote, "")) {
-    ret = 1;
-    goto out;
+  request_init(&req, RQ_DAEMON, AMD_SERVICE_NAME, RQ_CLIENT_SIN, addr, 0);
+  sock_methods(&req);
+
+  if (hosts_access(&req))
+         return 1;
+
+  return 0;
+}
+#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
+
+
+/*
+ * Prepare the parent and child:
+ * 1) Setup IPC pipe.
+ * 2) Set signal masks.
+ * 3) Fork by calling background() so that NumChildren is updated.
+ */
+static int
+amq_fork(opaque_t argp)
+{
+#ifdef HAVE_SIGACTION
+  sigset_t new, mask;
+#else /* not HAVE_SIGACTION */
+  int mask;
+#endif /* not HAVE_SIGACTION */
+  am_node *mp;
+  pid_t pid;
+
+  mp = find_ap(*(char **) argp);
+  if (mp == NULL) {
+    errno = 0;
+    return -1;
   }
-  /* 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;
+
+  if (pipe(mp->am_fd) == -1) {
+    mp->am_fd[0] = -1;
+    mp->am_fd[1] = -1;
+    return -1;
   }
-  /* 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;
+#ifdef HAVE_SIGACTION
+  sigemptyset(&new);		/* initialize signal set we wish to block */
+  sigaddset(&new, SIGHUP);
+  sigaddset(&new, SIGINT);
+  sigaddset(&new, SIGQUIT);
+  sigaddset(&new, SIGCHLD);
+  sigprocmask(SIG_BLOCK, &new, &mask);
+#else /* not HAVE_SIGACTION */
+  mask =
+      sigmask(SIGHUP) |
+      sigmask(SIGINT) |
+      sigmask(SIGQUIT) |
+      sigmask(SIGCHLD);
+  mask = sigblock(mask);
+#endif /* not HAVE_SIGACTION */
+
+  switch ((pid = background())) {
+  case -1:	/* error */
+    dlog("amq_fork failed");
+    return -1;
+
+  case 0:	/* child */
+    close(mp->am_fd[1]);	/* close output end of pipe */
+    mp->am_fd[1] = -1;
+    return 0;
+
+  default:	/* parent */
+    close(mp->am_fd[0]);	/* close input end of pipe */
+    mp->am_fd[0] = -1;
+
+#ifdef HAVE_SIGACTION
+    sigprocmask(SIG_SETMASK, &mask, NULL);
+#else /* not HAVE_SIGACTION */
+    sigsetmask(mask);
+#endif /* not HAVE_SIGACTION */
+    return pid;
+  }
 }
-#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
 
 
 void
@@ -121,6 +156,9 @@
   char *result;
   xdrproc_t xdr_argument, xdr_result;
   amqsvcproc_t local;
+  amqsvcproc_t child;
+  amqsvcproc_t parent;
+  pid_t pid;
 
 #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP)
   if (gopt.flags & CFM_USE_TCPWRAPPERS) {
@@ -127,7 +165,7 @@
     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)) {
+    if (!amqsvc_is_client_allowed(remote_addr)) {
       plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname);
       svcerr_auth(transp, AUTH_FAILED);
       return;
@@ -137,6 +175,10 @@
   }
 #endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */
 
+  local = NULL;
+  child = NULL;
+  parent = NULL;
+
   switch (rqstp->rq_proc) {
 
   case AMQPROC_NULL:
@@ -199,6 +241,21 @@
     local = (amqsvcproc_t) amqproc_pawd_1_svc;
     break;
 
+  case AMQPROC_SYNC_UMNT:
+    xdr_argument = (xdrproc_t) xdr_amq_string;
+    xdr_result = (xdrproc_t) xdr_amq_sync_umnt;
+    parent = (amqsvcproc_t) amqproc_sync_umnt_1_svc_parent;
+    child = (amqsvcproc_t) amqproc_sync_umnt_1_svc_child;
+    /* used if fork fails */
+    local = (amqsvcproc_t) amqproc_sync_umnt_1_svc_async;
+    break;
+
+  case AMQPROC_GETMAPINFO:
+    xdr_argument = (xdrproc_t) xdr_void;
+    xdr_result = (xdrproc_t) xdr_amq_map_info_qelem;
+    local = (amqsvcproc_t) amqproc_getmapinfo_1_svc;
+    break;
+
   default:
     svcerr_noproc(transp);
     return;
@@ -212,8 +269,29 @@
     return;
   }
 
-  result = (*local) (&argument, rqstp);
+  pid = -1;
+  result = NULL;
 
+  if (child) {
+    switch ((pid = amq_fork(&argument))) {
+    case -1:	/* error */
+      break;
+
+    case 0:	/* child */
+      result = (*child) (&argument, rqstp);
+      local = NULL;
+      break;
+
+    default:	/* parent */
+      result = (*parent) (&argument, rqstp);
+      local = NULL;
+      break;
+    }
+  }
+
+  if (local)
+    result = (*local) (&argument, rqstp);
+
   if (result != NULL && !svc_sendreply(transp,
 				       (XDRPROC_T_TYPE) xdr_result,
 				       result)) {
@@ -226,4 +304,7 @@
     plog(XLOG_FATAL, "unable to free rpc arguments in amqprog_1");
     going_down(1);
   }
+
+  if (pid == 0)
+    exit(0);	/* the child is done! */
 }

Modified: trunk/contrib/amd/amd/autil.c
===================================================================
--- trunk/contrib/amd/amd/autil.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/autil.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -160,16 +156,23 @@
 void
 forcibly_timeout_mp(am_node *mp)
 {
-  mntfs *mf = mp->am_mnt;
+  mntfs *mf = mp->am_al->al_mnt;
   /*
    * Arrange to timeout this node
    */
   if (mf && ((mp->am_flags & AMF_ROOT) ||
 	     (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)))) {
+    /*
+     * We aren't going to schedule a timeout, so we need to notify the
+     * child here unless we are already unmounting, in which case that
+     * process is responsible for notifying the child.
+     */
     if (mf->mf_flags & MFF_UNMOUNTING)
       plog(XLOG_WARNING, "node %s is currently being unmounted, ignoring timeout request", mp->am_path);
-    else
+    else {
       plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path);
+      notify_child(mp, AMQ_UMNT_FAILED, EBUSY, 0);
+    }
   } else {
     plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
     mp->am_flags &= ~AMF_NOTIMEOUT;
@@ -207,24 +210,11 @@
       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).
+     * We used to free the mf_mo (options) here, however they're now stored
+     * and managed with the mntfs and do not need to be free'd here (this ensures
+     * that we use the same options to monitor/unmount the system as we used
+     * to mount it).
      */
-    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;
-    }
   }
 
   if (mf->mf_flags & MFF_RESTART) {
@@ -249,7 +239,7 @@
 am_mounted(am_node *mp)
 {
   int notimeout = 0;		/* assume normal timeouts initially */
-  mntfs *mf = mp->am_mnt;
+  mntfs *mf = mp->am_al->al_mnt;
 
   /*
    * This is the parent mntfs which does the mf->mf_fo (am_opts type), and
@@ -266,7 +256,7 @@
   /*
    * Patch up path for direct mounts
    */
-  if (mp->am_parent && mp->am_parent->am_mnt->mf_fsflags & FS_DIRECT)
+  if (mp->am_parent && mp->am_parent->am_al->al_mnt->mf_fsflags & FS_DIRECT)
     mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
 
   /*
@@ -277,6 +267,7 @@
   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;
@@ -321,7 +312,7 @@
   /*
    * Update mtime of parent node (copying "struct nfstime" in '=' below)
    */
-  if (mp->am_parent && mp->am_parent->am_mnt)
+  if (mp->am_parent && mp->am_parent->am_al->al_mnt)
     mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime;
 
   /*
@@ -360,21 +351,27 @@
 {
   int error;
   dlog("assign_error_mntfs");
+
+  if (mp->am_al == NULL) {
+    plog(XLOG_ERROR, "%s: Can't assign error", __func__);
+    return;
+  }
   /*
    * Save the old error code
    */
   error = mp->am_error;
   if (error <= 0)
-    error = mp->am_mnt->mf_error;
+    error = mp->am_al->al_mnt->mf_error;
   /*
    * Allocate a new error reference
    */
-  mp->am_mnt = new_mntfs();
+  free_loc(mp->am_al);
+  mp->am_al = new_loc();
   /*
    * Put back the error code
    */
-  mp->am_mnt->mf_error = error;
-  mp->am_mnt->mf_flags |= MFF_ERROR;
+  mp->am_al->al_mnt->mf_error = error;
+  mp->am_al->al_mnt->mf_flags |= MFF_ERROR;
   /*
    * Zero the error in the mount point
    */
@@ -397,7 +394,8 @@
     cache = "none";
   mf->mf_private = (opaque_t) mapc_find(mf->mf_info,
 					cache,
-					(mf->mf_fo ? mf->mf_fo->opt_maptype : NULL));
+					(mf->mf_fo ? mf->mf_fo->opt_maptype : NULL),
+					mf->mf_mount);
   mf->mf_prfree = mapc_free;
 }
 
@@ -418,7 +416,7 @@
    * containing hung automounts.
    */
   while (xp &&
-	 (!(mf = xp->am_mnt) ||	/* No mounted filesystem */
+	 (!(mf = xp->am_al->al_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 */
@@ -453,8 +451,9 @@
   mntent_t mnt;
   MTYPE_TYPE type;
   int forced_unmount = 0;	/* are we using forced unmounts? */
+  u_long nfs_version = get_nfs_dispatcher_version(nfs_dispatcher);
 
-  memset((voidp) &mnt, 0, sizeof(mnt));
+  memset(&mnt, 0, sizeof(mnt));
   mnt.mnt_dir = dir;
   mnt.mnt_fsname = pid_fsname;
   mnt.mnt_opts = opts;
@@ -525,8 +524,7 @@
 again:
   if (!(mf->mf_flags & MFF_IS_AUTOFS)) {
     nfs_args_t nfs_args;
-    am_nfs_fh *fhp;
-    am_nfs_handle_t anh;
+    am_nfs_handle_t *fhp, anh;
 #ifndef HAVE_TRANSPORT_TYPE_TLI
     u_short port;
     struct sockaddr_in sin;
@@ -535,7 +533,7 @@
     /*
      * get fhandle of remote path for automount point
      */
-    fhp = get_root_nfs_fh(dir);
+    fhp = get_root_nfs_fh(dir, &anh);
     if (!fhp) {
       plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
       return EINVAL;
@@ -545,7 +543,7 @@
     /*
      * Create sockaddr to point to the local machine.
      */
-    memset((voidp) &sin, 0, sizeof(sin));
+    memset(&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;
@@ -559,7 +557,6 @@
 #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,
@@ -566,9 +563,9 @@
 		     genflags,
 		     nfsncp,
 		     NULL,	/* remote host IP addr is set below */
-		     NFS_VERSION,	/* version 2 */
+		     nfs_version,
 		     "udp",
-		     &anh,
+		     fhp,
 		     fs_hostname,
 		     pid_fsname);
     /*
@@ -587,9 +584,9 @@
 		     genflags,
 		     NULL,
 		     &sin,
-		     NFS_VERSION,	/* version 2 */
+		     nfs_version,
 		     "udp",
-		     &anh,
+		     fhp,
 		     fs_hostname,
 		     pid_fsname);
 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
@@ -656,10 +653,17 @@
 void
 am_unmounted(am_node *mp)
 {
-  mntfs *mf = mp->am_mnt;
+  mntfs *mf = mp->am_al->al_mnt;
 
-  if (!foreground)		/* firewall - should never happen */
+  if (!foreground) {		/* firewall - should never happen */
+    /*
+     * This is a coding error.  Make sure we hear about it!
+     */
+    plog(XLOG_FATAL, "am_unmounted: illegal use in background (%s)",
+	mp->am_name);
+    notify_child(mp, AMQ_UMNT_OK, 0, 0);	/* XXX - be safe? */
     return;
+  }
 
   /*
    * Do unmounted callback
@@ -707,26 +711,37 @@
   /*
    * Update mtime of parent node
    */
-  if (mp->am_parent && mp->am_parent->am_mnt)
+  if (mp->am_parent && mp->am_parent->am_al->al_mnt)
     clocktime(&mp->am_parent->am_fattr.na_mtime);
 
   if (mp->am_parent && (mp->am_flags & AMF_REMOUNT)) {
-    char *fname = strdup(mp->am_name);
+    char *fname = xstrdup(mp->am_name);
     am_node *mp_parent = mp->am_parent;
-    mntfs *mf_parent = mp_parent->am_mnt;
+    mntfs *mf_parent = mp_parent->am_al->al_mnt;
+    am_node fake_mp;
     int error = 0;
 
+    /*
+     * We need to use notify_child() after free_map(), so save enough
+     * to do that in fake_mp.
+     */
+    fake_mp.am_fd[1] = mp->am_fd[1];
+    mp->am_fd[1] = -1;
+
     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);
+      (void)mf_parent->mf_ops->mount_child(mp, &error);
     if (error > 0) {
       errno = error;
       plog(XLOG_ERROR, "am_unmounted: could not remount %s: %m", fname);
+      notify_child(&fake_mp, AMQ_UMNT_OK, 0, 0);
+    } else {
+      notify_child(&fake_mp, AMQ_UMNT_FAILED, EBUSY, 0);
     }
     XFREE(fname);
-  } else
+  } else {
     /*
      * We have a race here.
      * If this node has a pending mount and amd is going down (unmounting
@@ -734,10 +749,12 @@
      * 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).
+     * pending mounts (defined as having a non-NULL am_alarray).
      */
-    if (!mp->am_mfarray)
+    notify_child(mp, AMQ_UMNT_OK, 0, 0);	/* do this regardless */
+    if (!mp->am_alarray)
       free_map(mp);
+  }
 }
 
 

Modified: trunk/contrib/amd/amd/clock.c
===================================================================
--- trunk/contrib/amd/amd/clock.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/clock.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/amd/conf.c
===================================================================
--- trunk/contrib/amd/amd/conf.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/conf.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -77,6 +73,7 @@
 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_auto_nfs_version(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);
@@ -120,6 +117,7 @@
 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_nfs_vers_ping(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);
@@ -132,6 +130,7 @@
 static int gopt_search_path(const char *val);
 static int gopt_selectors_in_defaults(const char *val);
 static int gopt_show_statfs_entries(const char *val);
+static int gopt_sun_map_syntax(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);
@@ -146,6 +145,7 @@
 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_sun_map_syntax(const char *val, cf_map_t *cfm);
 static int ropt_tag(const char *val, cf_map_t *cfm);
 static void init_cf_map(cf_map_t *cfm);
 
@@ -159,6 +159,7 @@
   {"arch",			gopt_arch},
   {"auto_attrcache",		gopt_auto_attrcache},
   {"auto_dir",			gopt_auto_dir},
+  {"auto_nfs_version",		gopt_auto_nfs_version},
   {"autofs_use_lofs",		gopt_autofs_use_lofs},
   {"browsable_dirs",		gopt_browsable_dirs},
   {"cache_duration",		gopt_cache_duration},
@@ -202,6 +203,7 @@
   {"nfs_retry_interval_tcp",	gopt_nfs_retry_interval_tcp},
   {"nfs_retry_interval_toplvl",	gopt_nfs_retry_interval_toplvl},
   {"nfs_vers",			gopt_nfs_vers},
+  {"nfs_vers_ping",		gopt_nfs_vers_ping},
   {"nis_domain",		gopt_nis_domain},
   {"normalize_hostnames",	gopt_normalize_hostnames},
   {"normalize_slashes",		gopt_normalize_slashes},
@@ -215,6 +217,7 @@
   {"selectors_on_default",	gopt_selectors_in_defaults},
   {"selectors_in_defaults",	gopt_selectors_in_defaults},
   {"show_statfs_entries",	gopt_show_statfs_entries},
+  {"sun_map_syntax",		gopt_sun_map_syntax},
   {"truncate_log",		gopt_truncate_log},
   {"unmount_on_exit",		gopt_unmount_on_exit},
   {"use_tcpwrappers",		gopt_use_tcpwrappers},
@@ -255,12 +258,14 @@
   cfm->cfm_search_path = gopt.search_path;
 
   /*
-   * Initialize flags that are common both to [global] and a local map.
+   * Initialize flags that are common both to [global] and a local map
+   * (that is, they could be inherited from the global section).
    */
   cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS |
 				 CFM_BROWSABLE_DIRS_FULL |
 				 CFM_MOUNT_TYPE_AUTOFS |
-				 CFM_SELECTORS_IN_DEFAULTS);
+				 CFM_SELECTORS_IN_DEFAULTS |
+				 CFM_SUN_MAP_SYNTAX );
 }
 
 
@@ -366,7 +371,7 @@
 static int
 gopt_arch(const char *val)
 {
-  gopt.arch = strdup((char *)val);
+  gopt.arch = xstrdup(val);
   return 0;
 }
 
@@ -386,10 +391,23 @@
 static int
 gopt_auto_dir(const char *val)
 {
-  gopt.auto_dir = strdup((char *)val);
+  gopt.auto_dir = xstrdup(val);
   return 0;
 }
 
+static int
+gopt_auto_nfs_version(const char *val)
+{
+  if (strcmp(val, "2") == 0)
+    nfs_dispatcher = nfs_program_2;
+  else if (strcmp(val, "3") == 0)
+    nfs_dispatcher = nfs_program_3;
+  else {
+    fprintf(stderr, "conf: bad auto nfs version : \"%s\"\n", val);
+    return 1;
+  }
+  return 0;
+}
 
 static int
 gopt_autofs_use_lofs(const char *val)
@@ -439,7 +457,7 @@
 static int
 gopt_cluster(const char *val)
 {
-  gopt.cluster = strdup((char *)val);
+  gopt.cluster = xstrdup(val);
   return 0;
 }
 
@@ -447,7 +465,7 @@
 static int
 gopt_debug_mtab_file(const char *val)
 {
-  gopt.debug_mtab_file = strdup((char*)val);
+  gopt.debug_mtab_file = xstrdup(val);
   return 0;
 }
 
@@ -547,7 +565,7 @@
 static int
 gopt_full_os(const char *val)
 {
-  gopt.op_sys_full = strdup((char *)val);
+  gopt.op_sys_full = xstrdup(val);
   return 0;
 }
 
@@ -572,7 +590,7 @@
 gopt_hesiod_base(const char *val)
 {
 #ifdef HAVE_MAP_HESIOD
-  gopt.hesiod_base = strdup((char *)val);
+  gopt.hesiod_base = xstrdup(val);
   return 0;
 #else /* not HAVE_MAP_HESIOD */
   fprintf(stderr, "conf: hesiod_base option ignored.  No Hesiod support available.\n");
@@ -584,7 +602,7 @@
 static int
 gopt_karch(const char *val)
 {
-  gopt.karch = strdup((char *)val);
+  gopt.karch = xstrdup(val);
   return 0;
 }
 
@@ -592,7 +610,7 @@
 static int
 gopt_pid_file(const char *val)
 {
-  gopt.pid_file = strdup((char *)val);
+  gopt.pid_file = xstrdup(val);
   return 0;
 }
 
@@ -600,7 +618,7 @@
 static int
 gopt_local_domain(const char *val)
 {
-  gopt.sub_domain = strdup((char *)val);
+  gopt.sub_domain = xstrdup(val);
   return 0;
 }
 
@@ -608,7 +626,7 @@
 static int
 gopt_localhost_address(const char *val)
 {
-  gopt.localhost_address = strdup((char *)val);
+  gopt.localhost_address = xstrdup(val);
   return 0;
 }
 
@@ -617,7 +635,7 @@
 gopt_ldap_base(const char *val)
 {
 #ifdef HAVE_MAP_LDAP
-  gopt.ldap_base = strdup((char *)val);
+  gopt.ldap_base = xstrdup(val);
   return 0;
 #else /* not HAVE_MAP_LDAP */
   fprintf(stderr, "conf: ldap_base option ignored.  No LDAP support available.\n");
@@ -668,7 +686,7 @@
 gopt_ldap_hostports(const char *val)
 {
 #ifdef HAVE_MAP_LDAP
-  gopt.ldap_hostports = strdup((char *)val);
+  gopt.ldap_hostports = xstrdup(val);
   return 0;
 #else /* not HAVE_MAP_LDAP */
   fprintf(stderr, "conf: ldap_hostports option ignored.  No LDAP support available.\n");
@@ -719,7 +737,7 @@
 static int
 gopt_log_file(const char *val)
 {
-  gopt.logfile = strdup((char *)val);
+  gopt.logfile = xstrdup(val);
   return 0;
 }
 
@@ -735,7 +753,7 @@
 static int
 gopt_map_defaults(const char *val)
 {
-  gopt.map_defaults = strdup((char *)val);
+  gopt.map_defaults = xstrdup(val);
   return 0;
 }
 
@@ -743,7 +761,7 @@
 static int
 gopt_map_options(const char *val)
 {
-  gopt.map_options = strdup((char *)val);
+  gopt.map_options = xstrdup(val);
   return 0;
 }
 
@@ -766,7 +784,7 @@
     fprintf(stderr, "conf: no such map type \"%s\"\n", val);
     return 1;
   }
-  gopt.map_type = strdup((char *)val);
+  gopt.map_type = xstrdup(val);
   return 0;
 }
 
@@ -863,7 +881,7 @@
 gopt_nfs_proto(const char *val)
 {
   if (STREQ(val, "udp") || STREQ(val, "tcp")) {
-    gopt.nfs_proto = strdup((char *)val);
+    gopt.nfs_proto = xstrdup(val);
     return 0;
   }
   fprintf(stderr, "conf: illegal nfs_proto \"%s\"\n", val);
@@ -946,7 +964,7 @@
 {
   int i = atoi(val);
 
-  if (i == 2 || i == 3) {
+  if (i == 2 || i == 3 || i == 4) {
     gopt.nfs_vers = i;
     return 0;
   }
@@ -956,10 +974,23 @@
 
 
 static int
+gopt_nfs_vers_ping(const char *val)
+{
+  int i = atoi(val);
+
+  if (i == 2 || i == 3 || i == 4) {
+    gopt.nfs_vers_ping = i;
+    return 0;
+  }
+  fprintf(stderr, "conf: illegal nfs_vers_ping \"%s\"\n", val);
+  return 1;
+}
+
+static int
 gopt_nis_domain(const char *val)
 {
 #ifdef HAVE_MAP_NIS
-  gopt.nis_domain = strdup((char *)val);
+  gopt.nis_domain = xstrdup(val);
   return 0;
 #else /* not HAVE_MAP_NIS */
   fprintf(stderr, "conf: nis_domain option ignored.  No NIS support available.\n");
@@ -1003,7 +1034,7 @@
 static int
 gopt_os(const char *val)
 {
-  gopt.op_sys = strdup((char *)val);
+  gopt.op_sys = xstrdup(val);
   return 0;
 }
 
@@ -1011,7 +1042,7 @@
 static int
 gopt_osver(const char *val)
 {
-  gopt.op_sys_ver = strdup((char *)val);
+  gopt.op_sys_ver = xstrdup(val);
   return 0;
 }
 
@@ -1084,7 +1115,7 @@
 static int
 gopt_search_path(const char *val)
 {
-  gopt.search_path = strdup((char *)val);
+  gopt.search_path = xstrdup(val);
   return 0;
 }
 
@@ -1122,6 +1153,22 @@
 
 
 static int
+gopt_sun_map_syntax(const char *val)
+{
+  if (STREQ(val, "yes")) {
+    gopt.flags |= CFM_SUN_MAP_SYNTAX;
+    return 0;
+  } else if (STREQ(val, "no")) {
+    gopt.flags &= ~CFM_SUN_MAP_SYNTAX;
+    return 0;
+  }
+
+  fprintf(stderr, "conf: unknown value to sun_map_syntax \"%s\"\n", val);
+  return 1;			/* unknown value */
+}
+
+
+static int
 gopt_truncate_log(const char *val)
 {
   if (STREQ(val, "yes")) {
@@ -1177,7 +1224,7 @@
 static int
 gopt_vendor(const char *val)
 {
-  gopt.op_sys_vendor = strdup((char *)val);
+  gopt.op_sys_vendor = xstrdup(val);
   return 0;
 }
 
@@ -1199,7 +1246,7 @@
 
   /* check if initializing a new map */
   if (!cfm->cfm_dir)
-    cfm->cfm_dir = strdup((char *)section);
+    cfm->cfm_dir = xstrdup(section);
 
   /* check for each possible field */
   if (STREQ(key, "browsable_dirs"))
@@ -1223,6 +1270,9 @@
   if (STREQ(key, "search_path"))
     return ropt_search_path(val, cfm);
 
+  if (STREQ(key, "sun_map_syntax"))
+    return ropt_sun_map_syntax(val, cfm);
+
   if (STREQ(key, "tag"))
     return ropt_tag(val, cfm);
 
@@ -1254,7 +1304,7 @@
 static int
 ropt_map_name(const char *val, cf_map_t *cfm)
 {
-  cfm->cfm_name = strdup((char *)val);
+  cfm->cfm_name = xstrdup(val);
   return 0;
 }
 
@@ -1262,7 +1312,7 @@
 static int
 ropt_map_defaults(const char *val, cf_map_t *cfm)
 {
-  cfm->cfm_defaults = strdup((char *)val);
+  cfm->cfm_defaults = xstrdup(val);
   return 0;
 }
 
@@ -1270,7 +1320,7 @@
 static int
 ropt_map_options(const char *val, cf_map_t *cfm)
 {
-  cfm->cfm_opts = strdup((char *)val);
+  cfm->cfm_opts = xstrdup(val);
   return 0;
 }
 
@@ -1283,7 +1333,7 @@
     fprintf(stderr, "conf: no such map type \"%s\"\n", val);
     return 1;
   }
-  cfm->cfm_type = strdup((char *)val);
+  cfm->cfm_type = xstrdup(val);
   return 0;
 }
 
@@ -1313,15 +1363,32 @@
 static int
 ropt_search_path(const char *val, cf_map_t *cfm)
 {
-  cfm->cfm_search_path = strdup((char *)val);
+  cfm->cfm_search_path = xstrdup(val);
   return 0;
 }
 
 
 static int
+ropt_sun_map_syntax(const char *val, cf_map_t *cfm)
+{
+  if (STREQ(val, "yes")) {
+    cfm->cfm_flags |= CFM_SUN_MAP_SYNTAX;
+    return 0;
+
+  } else if (STREQ(val, "no")) {
+    cfm->cfm_flags &= ~CFM_SUN_MAP_SYNTAX;
+    return 0;
+  }
+
+  fprintf(stderr, "conf: unknown value to sun_map_syntax \"%s\"\n", val);
+  return 1;			/* unknown value */
+}
+
+
+static int
 ropt_tag(const char *val, cf_map_t *cfm)
 {
-  cfm->cfm_tag = strdup((char *)val);
+  cfm->cfm_tag = xstrdup(val);
   return 0;
 }
 
@@ -1397,7 +1464,7 @@
     return NULL;
 
   while (tmp_map) {
-    if (STREQ(tmp_map->cfm_dir,name)) {
+    if (STREQ(tmp_map->cfm_dir, name)) {
       return tmp_map;
     }
     tmp_map = tmp_map->cfm_next;

Modified: trunk/contrib/amd/amd/conf_parse.y
===================================================================
--- trunk/contrib/amd/amd/conf_parse.y	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/conf_parse.y	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/amd/conf_tok.l
===================================================================
--- trunk/contrib/amd/amd/conf_tok.l	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/conf_tok.l	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,6 +1,6 @@
 %{
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -17,11 +17,7 @@
  * 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
+ * 3. 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.
  *
@@ -74,7 +70,7 @@
  */
 #ifdef FLEX_SCANNER
 # ifndef ECHO
-#  define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#  define ECHO __IGNORE(fwrite( yytext, yyleng, 1, yyout ))
 # endif /* not ECHO */
 #endif /* FLEX_SCANNER */
 
@@ -86,9 +82,9 @@
  * which automatically generates yywrap macros and symbols.  So I must
  * distinguish between them and when yywrap is actually needed.
  */
-#ifndef yywrap
+#if !defined(yywrap) || defined(yylex)
 int yywrap(void);
-#endif /* not yywrap */
+#endif /* not yywrap or yylex */
 
 #define TOK_DEBUG 0
 
@@ -108,6 +104,7 @@
 /* This option causes Solaris lex to fail.  Use flex.  See BUGS file */
 /* no need to use yyunput() */
 %option nounput
+%option noinput
 
 /* allocate more output slots so lex scanners don't run out of mem */
 %o 1024
@@ -131,19 +128,19 @@
 
 \[			{
 			dprintf("%8d: Left bracket \"%s\"\n", yytext);
-			yylval.strtype = strdup((char *)yytext);
+			conf_lval.strtype = xstrdup(yytext);
 			amu_return(LEFT_BRACKET);
 			}
 
 \]			{
 			dprintf("%8d: Right bracket \"%s\"\n", yytext);
-			yylval.strtype = strdup((char *)yytext);
+			conf_lval.strtype = xstrdup(yytext);
 			amu_return(RIGHT_BRACKET);
 			}
 
 =			{
 			dprintf("%8d: Equal \"%s\"\n", yytext);
-			yylval.strtype = strdup((char *)yytext);
+			conf_lval.strtype = xstrdup(yytext);
 			amu_return(EQUAL);
 			}
 
@@ -159,7 +156,7 @@
 
 {NONWSCHAR}{NONWSCHAR}*	{
 			dprintf("%8d: Non-WS string \"%s\"\n", yytext);
-			yylval.strtype = strdup((char *)yytext);
+			conf_lval.strtype = xstrdup(yytext);
 			amu_return(NONWS_STRING);
 			}
 
@@ -167,13 +164,13 @@
 			dprintf("%8d: QUOTED-Non-WS-EQ string \"%s\"\n", yytext);
 			/* must strip quotes */
 			yytext[strlen((char *)yytext)-1] = '\0';
-			yylval.strtype = strdup((char *)&yytext[1]);
+			conf_lval.strtype = xstrdup(&yytext[1]);
 			amu_return(QUOTED_NONWSEQ_STRING);
 			}
 
 {NONWSEQCHAR}{NONWSEQCHAR}*	{
 			dprintf("%8d: Non-WS-EQ string \"%s\"\n", yytext);
-			yylval.strtype = strdup((char *)yytext);
+			conf_lval.strtype = xstrdup(yytext);
 			amu_return(NONWSEQ_STRING);
 			}
 
@@ -184,9 +181,9 @@
  * which automatically generates yywrap macros and symbols.  So I must
  * distinguish between them and when yywrap is actually needed.
  */
-#ifndef yywrap
+#if !defined(yywrap) || defined(yylex)
 int yywrap(void)
 {
   return 1;
 }
-#endif /* not yywrap */
+#endif /* not yywrap or yylex */

Modified: trunk/contrib/amd/amd/get_args.c
===================================================================
--- trunk/contrib/amd/amd/get_args.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/get_args.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -84,17 +80,31 @@
   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) 1997-2014 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);
+  xstrlcat(vers, tmpbuf, len);
   xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT);
-  strlcat(vers, tmpbuf, len);
+  xstrlcat(vers, tmpbuf, len);
+#if 0
+  /*
+   * XXX  This block (between from the #if 0 to #endif was in the
+   * XXX  original was in the original merge however in the interest
+   * XXX  of reproduceable builds and the fact that this is redundant
+   * XXX  information, it is effectively removed.
+   */
   xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n",
 	    USER_NAME, HOST_NAME, CONFIG_DATE);
+  xstrlcat(vers, tmpbuf, len);
+  xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s on date %s.\n",
+	    BUILD_USER, BUILD_HOST, BUILD_DATE);
+  xstrlcat(vers, tmpbuf, len);
+#endif
+  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);
@@ -101,27 +111,27 @@
   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);
+  xstrlcat(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);
+  xstrlcat(vers, tmpbuf, len);
   xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n",
 	    hostdomain, am_get_hostname(), hostd);
-  strlcat(vers, tmpbuf, len);
+  xstrlcat(vers, tmpbuf, len);
 
-  strlcat(vers, "Map support for: ", len);
+  xstrlcat(vers, "Map support for: ", len);
   mapc_showtypes(tmpbuf, sizeof(tmpbuf));
-  strlcat(vers, tmpbuf, len);
-  strlcat(vers, ".\nAMFS: ", len);
+  xstrlcat(vers, tmpbuf, len);
+  xstrlcat(vers, ".\nAMFS: ", len);
   ops_showamfstypes(tmpbuf, sizeof(tmpbuf));
-  strlcat(vers, tmpbuf, len);
-  strlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
+  xstrlcat(vers, tmpbuf, len);
+  xstrlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */
   ops_showfstypes(tmpbuf, sizeof(tmpbuf));
-  strlcat(vers, tmpbuf, len);
+  xstrlcat(vers, tmpbuf, len);
 
   /* append list of networks if available */
   if (wire_buf) {
-    strlcat(vers, wire_buf, len);
+    xstrlcat(vers, wire_buf, len);
     XFREE(wire_buf);
   }
 
@@ -331,19 +341,18 @@
       perror(buf);
       exit(1);
     }
-    yyin = fp;
-    yyparse();
+    conf_in = fp;
+    conf_parse();
     fclose(fp);
     if (process_all_regular_maps() != 0)
       exit(1);
   }
 
-  /* make sure there are some default options defined */
-  if (xlog_level_init == ~0) {
-    switch_option("");
-  }
 #ifdef DEBUG
   usage += switch_option("debug");
+  /* initialize debug options */
+  if (!debug_flags)
+    debug_flags = D_CONTROL;	/* CONTROL = "daemon,amq,fork" */
 #endif /* DEBUG */
 
   /* log information regarding amd.conf file */

Modified: trunk/contrib/amd/amd/info_exec.c
===================================================================
--- trunk/contrib/amd/amd/info_exec.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/info_exec.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -52,8 +48,8 @@
 #endif /* HAVE_CONFIG_H */
 #include <am_defs.h>
 #include <amd.h>
+#include <sun_map.h>
 
-#define	MAX_LINE_LEN		1500
 
 /* forward declarations */
 int exec_init(mnt_map *m, char *map, time_t *tp);
@@ -74,13 +70,13 @@
   if (!s || size < 0 || rdfd < 0)
     return 0;
 
-  s[0] = 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' */
+    s[i+1] = '\0'; /* places the requisite trailing '\0' */
 
     /* ready for reading */
     rval = read(rdfd, (void *)(s+i), 1);
@@ -114,7 +110,7 @@
     FD_ZERO(&fds);
     FD_SET(rdfd, &fds);
 
-    rval = select(rdfd+1, &fds, 0, 0, &timeo);
+    rval = select(rdfd+1, &fds, NULL, NULL, &timeo);
     if (rval < 0) {
       /* error selecting */
       plog(XLOG_WARNING, "fgets_timed select error: %m");
@@ -165,9 +161,9 @@
  * 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)
+exec_parse_qanswer(mnt_map *m, int fd, char *map, char *key, char **pval, time_t *tp)
 {
-  char qanswer[MAX_LINE_LEN], *dc = 0;
+  char qanswer[INFO_MAX_LINE_LEN], *dc = NULL;
   int chuck = 0;
   int line_no = 0;
 
@@ -197,7 +193,7 @@
     /*
      * Find beginning of value (query answer)
      */
-    for (cp = qanswer; *cp && !isascii((int)*cp) && !isspace((int)*cp); cp++)
+    for (cp = qanswer; *cp && !isascii((unsigned char)*cp) && !isspace((unsigned char)*cp); cp++)
       ;;
 
     /* Ignore blank lines */
@@ -207,7 +203,10 @@
     /*
      * Return a copy of the data
      */
-    dc = strdup(cp);
+    if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
+      dc = sun_entry2amd(key, cp);
+    else
+      dc = xstrdup(cp);
     *pval = dc;
     dlog("%s returns %s", key, dc);
 
@@ -324,7 +323,7 @@
   close(pdes[1]);
 
   /* anti-zombie insurance */
-  while (waitpid(p1,0,0) < 0)
+  while (waitpid(p1, 0, 0) < 0)
     if (errno != EINTR)
       exit(errno);
 
@@ -416,7 +415,7 @@
     if (tp)
       *tp = clocktime(NULL);
 
-    return exec_parse_qanswer(mapfd, map, key, pval, tp);
+    return exec_parse_qanswer(m, mapfd, map, key, pval, tp);
   }
 
   return errno;

Modified: trunk/contrib/amd/amd/info_file.c
===================================================================
--- trunk/contrib/amd/amd/info_file.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/info_file.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -50,8 +46,8 @@
 #endif /* HAVE_CONFIG_H */
 #include <am_defs.h>
 #include <amd.h>
+#include <sun_map.h>
 
-#define	MAX_LINE_LEN	1500
 
 /* forward declarations */
 int file_init_or_mtime(mnt_map *m, char *map, time_t *tp);
@@ -59,8 +55,8 @@
 int file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
 
 
-static int
-read_line(char *buf, int size, FILE *fp)
+int
+file_read_line(char *buf, int size, FILE *fp)
 {
   int done = 0;
 
@@ -79,7 +75,7 @@
 	 * Skip leading white space on next line
 	 */
 	while ((ch = getc(fp)) != EOF &&
-	       isascii(ch) && isspace(ch)) ;
+	       isascii((unsigned char)ch) && isspace((unsigned char)ch)) ;
 	(void) ungetc(ch, fp);
       } else {
 	return done;
@@ -95,18 +91,18 @@
  * Try to locate a key in a file
  */
 static int
-file_search_or_reload(FILE *fp,
+file_search_or_reload(mnt_map *m,
+		      FILE *fp,
 		      char *map,
 		      char *key,
 		      char **val,
-		      mnt_map *m,
 		      void (*fn) (mnt_map *m, char *, char *))
 {
-  char key_val[MAX_LINE_LEN];
+  char key_val[INFO_MAX_LINE_LEN];
   int chuck = 0;
   int line_no = 0;
 
-  while (read_line(key_val, sizeof(key_val), fp)) {
+  while (file_read_line(key_val, sizeof(key_val), fp)) {
     char *kp;
     char *cp;
     char *hash;
@@ -133,7 +129,7 @@
     /*
      * Find start of key
      */
-    for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ;
+    for (kp = key_val; *kp && isascii((unsigned char)*kp) && isspace((unsigned char)*kp); kp++) ;
 
     /*
      * Ignore blank lines
@@ -144,7 +140,7 @@
     /*
      * Find end of key
      */
-    for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ;
+    for (cp = kp; *cp && (!isascii((unsigned char)*cp) || !isspace((unsigned char)*cp)); cp++) ;
 
     /*
      * Check whether key matches
@@ -153,15 +149,20 @@
       *cp++ = '\0';
 
     if (fn || (*key == *kp && STREQ(key, kp))) {
-      while (*cp && isascii(*cp) && isspace((int)*cp))
+      while (*cp && isascii((unsigned char)*cp) && isspace((unsigned char)*cp))
 	cp++;
       if (*cp) {
 	/*
 	 * Return a copy of the data
 	 */
-	char *dc = strdup(cp);
+	char *dc;
+	/* if m->cfm == NULL, not using amd.conf file */
+	if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
+	  dc = sun_entry2amd(kp, cp);
+	else
+	  dc = xstrdup(cp);
 	if (fn) {
-	  (*fn) (m, strdup(kp), dc);
+	  (*fn) (m, xstrdup(kp), dc);
 	} else {
 	  *val = dc;
 	  dlog("%s returns %s", key, dc);
@@ -221,10 +222,10 @@
 int
 file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
 {
-  FILE *mapf = file_open(map, (time_t *) 0);
+  FILE *mapf = file_open(map, (time_t *) NULL);
 
   if (mapf) {
-    int error = file_search_or_reload(mapf, map, 0, 0, m, fn);
+    int error = file_search_or_reload(m, mapf, map, NULL, NULL, fn);
     (void) fclose(mapf);
     return error;
   }
@@ -244,7 +245,7 @@
       *tp = t;
       error = -1;
     } else {
-      error = file_search_or_reload(mapf, map, key, pval, 0, 0);
+      error = file_search_or_reload(m, mapf, map, key, pval, NULL);
     }
     (void) fclose(mapf);
     return error;

Modified: trunk/contrib/amd/amd/info_hesiod.c
===================================================================
--- trunk/contrib/amd/amd/info_hesiod.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/info_hesiod.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -50,6 +46,7 @@
 #endif /* HAVE_CONFIG_H */
 #include <am_defs.h>
 #include <amd.h>
+#include <sun_map.h>
 
 #define	HES_PREFIX	"hesiod."
 #define	HES_PREFLEN	7
@@ -127,7 +124,11 @@
    * it (and free subsequent replies)
    */
   if (rvec && *rvec) {
-    *pval = *rvec;
+    if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) {
+      *pval = sun_entry2amd(key, *rvec);
+      XFREE(*rvec);
+    } else
+      *pval = *rvec;
     while (*++rvec)
       XFREE(*rvec);
     return 0;

Modified: trunk/contrib/amd/amd/info_ldap.c
===================================================================
--- trunk/contrib/amd/amd/info_ldap.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/info_ldap.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -66,6 +62,7 @@
 #endif /* HAVE_CONFIG_H */
 #include <am_defs.h>
 #include <amd.h>
+#include <sun_map.h>
 
 
 /*
@@ -118,6 +115,8 @@
   struct he_ent *next;
 };
 
+static ALD *ldap_connection;
+
 /*
  * FORWARD DECLARATIONS:
  */
@@ -124,6 +123,9 @@
 static int amu_ldap_rebind(ALD *a);
 static int get_ldap_timestamp(ALD *a, char *map, time_t *ts);
 
+int amu_ldap_init(mnt_map *m, char *map, time_t *tsu);
+int amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts);
+int amu_ldap_mtime(mnt_map *m, char *map, time_t *ts);
 
 /*
  * FUNCTIONS:
@@ -144,30 +146,33 @@
 {
   char *c, *p;
   char *s;
-  HE_ENT *new, *old = NULL;
+  HE_ENT *first = NULL, *cur = NULL;
 
-  if (NULL == s_orig || NULL == (s = strdup(s_orig)))
+  if (NULL == s_orig)
     return NULL;
-  for (p = s; p; p = strchr(p, ',')) {
-    if (old != NULL) {
-      new = ALLOC(HE_ENT);
-      old->next = new;
-      old = new;
-    } else {
-      old = ALLOC(HE_ENT);
-      old->next = NULL;
-    }
+  s = xstrdup(s_orig);
+  for (p = strtok(s, ","); p; p = strtok(NULL, ",")) {
+    if (cur != NULL) {
+      cur->next = ALLOC(HE_ENT);
+      cur = cur->next;
+    } else
+      first = cur = ALLOC(HE_ENT);
+
+    cur->next = NULL;
     c = strchr(p, ':');
     if (c) {            /* Host and port */
       *c++ = '\0';
-      old->host = strdup(p);
-      old->port = atoi(c);
-    } else
-      old->host = strdup(p);
-
+      cur->host = xstrdup(p);
+      cur->port = atoi(c);
+    } else {
+      cur->host = xstrdup(p);
+      cur->port = LDAP_PORT;
+    }
+    plog(XLOG_USER, "Adding ldap server %s:%d",
+      cur->host, cur->port);
   }
   XFREE(s);
-  return (old);
+  return first;
 }
 
 
@@ -248,10 +253,18 @@
   if (!gopt.map_type || !STREQ(gopt.map_type, AMD_LDAP_TYPE)) {
     dlog("amu_ldap_init called with map_type <%s>\n",
 	 (gopt.map_type ? gopt.map_type : "null"));
+    return ENOENT;
   } else {
     dlog("Map %s is ldap\n", map);
   }
 
+#ifndef LDAP_CONNECTION_PER_MAP
+  if (ldap_connection != NULL) {
+    m->map_data = (void *) ldap_connection;
+    return 0;
+  }
+#endif
+
   aldh = ALLOC(ALD);
   creds = ALLOC(CR);
   aldh->ldap = NULL;
@@ -274,11 +287,14 @@
     ald_free(aldh);
     return (ENOENT);
   }
-  m->map_data = (void *) aldh;
   dlog("Bound to %s:%d\n", aldh->hostent->host, aldh->hostent->port);
-  if (get_ldap_timestamp(aldh, map, ts))
+  if (get_ldap_timestamp(aldh, map, ts)) {
+    ald_free(aldh);
     return (ENOENT);
+  }
   dlog("Got timestamp for map %s: %ld\n", map, (u_long) *ts);
+  ldap_connection = aldh;
+  m->map_data = (void *) ldap_connection;
 
   return (0);
 }
@@ -312,7 +328,7 @@
     for (h = a->hostent; h != NULL; h = h->next) {
       if ((ld = ldap_open(h->host, h->port)) == NULL) {
 	plog(XLOG_WARNING, "Unable to ldap_open to %s:%d\n", h->host, h->port);
-	break;
+	continue;
       }
 #if LDAP_VERSION_MAX > LDAP_VERSION2
       /* handle LDAPv3 and heigher, if available and amd.conf-igured */
@@ -321,9 +337,9 @@
           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;
+          plog(XLOG_WARNING, "Unable to set ldap protocol version to %ld for "
+	       "%s:%d\n", gopt.ldap_proto_version, h->host, h->port);
+	  continue;
         }
       }
 #endif /* LDAP_VERSION_MAX > LDAP_VERSION2 */
@@ -330,7 +346,7 @@
       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;
+	continue;
       }
       if (gopt.ldap_cache_seconds > 0) {
 #if defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE)
@@ -541,7 +557,10 @@
   }
   dlog("Map %s, %s => %s\n", map, key, vals[0]);
   if (vals[0]) {
-    *pval = strdup(vals[0]);
+    if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
+      *pval = sun_entry2amd(key, vals[0]);
+    else
+      *pval = xstrdup(vals[0]);
     err = 0;
   } else {
     plog(XLOG_USER, "Empty value for %s in map %s\n", key, map);

Modified: trunk/contrib/amd/amd/info_ndbm.c
===================================================================
--- trunk/contrib/amd/amd/info_ndbm.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/info_ndbm.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -50,6 +46,7 @@
 #endif /* HAVE_CONFIG_H */
 #include <am_defs.h>
 #include <amd.h>
+#include <sun_map.h>
 
 /* forward declarations */
 int ndbm_init(mnt_map *m, char *map, time_t *tp);
@@ -58,7 +55,7 @@
 
 
 static int
-search_ndbm(DBM *db, char *key, char **val)
+search_ndbm(mnt_map *m, DBM *db, char *key, char **val)
 {
   datum k, v;
 
@@ -66,7 +63,10 @@
   k.dsize = strlen(key) + 1;
   v = dbm_fetch(db, k);
   if (v.dptr) {
-    *val = strdup(v.dptr);
+    if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX))
+      *val = sun_entry2amd(key, v.dptr);
+    else
+      *val = xstrdup(v.dptr);
     return 0;
   }
   return ENOENT;
@@ -95,7 +95,7 @@
       *tp = stb.st_mtime;
       error = -1;
     } else {
-      error = search_ndbm(db, key, pval);
+      error = search_ndbm(m, db, key, pval);
     }
     (void) dbm_close(db);
     return error;

Modified: trunk/contrib/amd/amd/info_nis.c
===================================================================
--- trunk/contrib/amd/amd/info_nis.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/info_nis.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -50,6 +46,7 @@
 #endif /* HAVE_CONFIG_H */
 #include <am_defs.h>
 #include <amd.h>
+#include <sun_map.h>
 
 
 /*
@@ -109,7 +106,7 @@
     plog(XLOG_WARNING, "NIS domain name is not set.  NIS ignored.");
     return ENOENT;
   }
-  gopt.nis_domain = strdup(default_domain);
+  gopt.nis_domain = xstrdup(default_domain);
 
   return 0;
 }
@@ -167,6 +164,7 @@
   cbinfo.data = (voidp) &data;
   cbinfo.foreach = (ypall_callback_fxn_t) callback;
 
+  plog(XLOG_INFO, "NIS map %s reloading using yp_all", map);
   /*
    * If you are using NIS and your yp_all function is "broken", you have to
    * get it fixed.  The bug in yp_all() is that it does not close a TCP
@@ -247,7 +245,7 @@
  * Try to locate a key using NIS.
  */
 int
-nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
+nis_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
 {
   int outlen;
   int res;
@@ -301,7 +299,15 @@
   /*
    * Lookup key
    */
-  res = yp_match(gopt.nis_domain, map, key, strlen(key), val, &outlen);
+  res = yp_match(gopt.nis_domain, map, key, strlen(key), pval, &outlen);
+  if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX) && res == 0) {
+    char *oldval = *pval;
+    *pval = sun_entry2amd(key, oldval);
+    /* We always need to free the output of the yp_match call. */
+    XFREE(oldval);
+    if (*pval == NULL)
+      return -1;		/* sun2amd parser error */
+  }
 
   /*
    * Do something interesting with the return code

Modified: trunk/contrib/amd/amd/info_nisplus.c
===================================================================
--- trunk/contrib/amd/amd/info_nisplus.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/info_nisplus.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -50,6 +46,7 @@
 #endif /* HAVE_CONFIG_H */
 #include <am_defs.h>
 #include <amd.h>
+#include <sun_map.h>
 
 #define NISPLUS_KEY "key="
 #define NISPLUS_ORGDIR ".org_dir"
@@ -221,8 +218,13 @@
       if (value != NULL)
 	data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
     }
-    *val = data.value;
 
+    if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) {
+      *val = sun_entry2amd(key, data.value);
+      XFREE(data.value);	/* strnsave malloc'ed it above */
+    } else
+      *val = data.value;
+
     if (*val) {
       error = 0;
       dlog("NISplus search found %s", *val);

Modified: trunk/contrib/amd/amd/info_passwd.c
===================================================================
--- trunk/contrib/amd/amd/info_passwd.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/info_passwd.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -94,11 +90,11 @@
 int
 passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
 {
-  char *dir = 0;
+  char *dir = NULL;
   struct passwd *pw;
 
   if (STREQ(key, "/defaults")) {
-    *pval = strdup("type:=nfs");
+    *pval = xstrdup("type:=nfs");
     return 0;
   }
   pw = getpwnam(key);
@@ -123,7 +119,7 @@
     char *p, *q;
     char val[MAXPATHLEN];
     char rhost[MAXHOSTNAMELEN];
-    dir = strdup(pw->pw_dir);
+    dir = xstrdup(pw->pw_dir);
 
     /*
      * Find user name.  If no / then Invalid...
@@ -180,13 +176,12 @@
     dlog("passwd_search: map=%s key=%s -> %s", map, key, val);
     if (q)
       *q = '.';
-    *pval = strdup(val);
+    *pval = xstrdup(val);
     return 0;
   }
 
 enoent:
-  if (dir)
-    XFREE(dir);
+  XFREE(dir);
 
   return ENOENT;
 }

Modified: trunk/contrib/amd/amd/info_union.c
===================================================================
--- trunk/contrib/amd/amd/info_union.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/info_union.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -77,7 +73,7 @@
 int
 union_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
 {
-  char *mapd = strdup(map + UNION_PREFLEN);
+  char *mapd = xstrdup(map + UNION_PREFLEN);
   char **v = strsplit(mapd, ':', '\"');
   char **p;
   size_t l;
@@ -95,7 +91,8 @@
 int
 union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
 {
-  char *mapd = strdup(map + UNION_PREFLEN);
+  static const char fseq[] = "fs:=";
+  char *mapd = xstrdup(map + UNION_PREFLEN);
   char **v = strsplit(mapd, ':', '\"');
   char **dir;
 
@@ -102,7 +99,7 @@
   /*
    * Add fake /defaults entry
    */
-  (*fn) (m, strdup("/defaults"), strdup("type:=link;opts:=nounmount;sublink:=${key}"));
+  (*fn) (m, xstrdup("/defaults"), xstrdup("type:=link;opts:=nounmount;sublink:=${key}"));
 
   for (dir = v; *dir; dir++) {
     size_t l;
@@ -113,7 +110,7 @@
       plog(XLOG_USER, "Cannot read directory %s: %m", *dir);
       continue;
     }
-    l = strlen(*dir) + 5;
+    l = strlen(*dir) + sizeof(fseq);
 
     dlog("Reading directory %s...", *dir);
     while ((dp = readdir(dirp))) {
@@ -125,8 +122,8 @@
 
       dlog("... gives %s", dp->d_name);
       val = xmalloc(l);
-      xsnprintf(val, l + 5, "fs:=%s", *dir);
-      (*fn) (m, strdup(dp->d_name), val);
+      xsnprintf(val, l, "%s%s", fseq, *dir);
+      (*fn) (m, xstrdup(dp->d_name), val);
     }
     closedir(dirp);
   }
@@ -135,11 +132,11 @@
    * Add wildcard entry
    */
   {
-    size_t l = strlen(*(dir-1)) + 5;
+    size_t l = strlen(*(dir-1)) + sizeof(fseq);
     char *val = xmalloc(l);
 
-    xsnprintf(val, l, "fs:=%s", *(dir-1));
-    (*fn) (m, strdup("*"), val);
+    xsnprintf(val, l, "%s%s", fseq, *(dir-1));
+    (*fn) (m, xstrdup("*"), val);
   }
   XFREE(mapd);
   XFREE(v);

Modified: trunk/contrib/amd/amd/map.c
===================================================================
--- trunk/contrib/amd/amd/map.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/map.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -69,7 +65,7 @@
 static int timeout_mp_id;	/* Id from last call to timeout */
 
 static am_node *root_node;	/* The root of the mount tree */
-static am_node **exported_ap = (am_node **) 0;
+static am_node **exported_ap = (am_node **) NULL;
 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 */
@@ -190,7 +186,7 @@
 get_ap_child(am_node *mp, char *fname)
 {
   am_node *new_mp;
-  mntfs *mf = mp->am_mnt;
+  mntfs *mf = mp->am_al->al_mnt;
 
   /*
    * Allocate a new map
@@ -280,7 +276,7 @@
   /*
    * Zero the slot pointer to avoid double free's
    */
-  exported_ap[mp->am_mapno] = 0;
+  exported_ap[mp->am_mapno] = NULL;
 
   /*
    * Update the free and last_used indices
@@ -325,7 +321,7 @@
     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)
+  if (p_mp->am_al->al_mnt->mf_flags & MFF_IS_AUTOFS)
     mp->am_flags |= AMF_AUTOFS;
 #endif /* HAVE_FS_AUTOFS */
 }
@@ -408,13 +404,14 @@
    * mp->am_mapno is initialized by exported_ap_alloc
    * 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_al = new_loc();
+  mp->am_alarray = NULL;
+  mp->am_name = xstrdup(dir);
+  mp->am_path = xstrdup(dir);
   mp->am_gen = new_gen();
 #ifdef HAVE_FS_AUTOFS
-  mp->am_autofs_fh = 0;
+  mp->am_autofs_fh = NULL;
 #endif /* HAVE_FS_AUTOFS */
 
   mp->am_timeo = gopt.am_timeo;
@@ -430,9 +427,33 @@
   mp->am_stats.s_mtime = mp->am_fattr.na_atime.nt_seconds;
   mp->am_dev = -1;
   mp->am_rdev = -1;
+  mp->am_fd[0] = -1;
+  mp->am_fd[1] = -1;
 }
 
 
+void
+notify_child(am_node *mp, au_etype au_etype, int au_errno, int au_signal)
+{
+  amq_sync_umnt rv;
+  int err;
+
+  if (mp->am_fd[1] >= 0) {	/* we have a child process */
+    rv.au_etype = au_etype;
+    rv.au_signal = au_signal;
+    rv.au_errno = au_errno;
+
+    err = write(mp->am_fd[1], &rv, sizeof(rv));
+    /* XXX: do something else on err? */
+    if (err < sizeof(rv))
+      plog(XLOG_INFO, "notify_child: write returned %d instead of %d.",
+	   err, (int) sizeof(rv));
+    close(mp->am_fd[1]);
+    mp->am_fd[1] = -1;
+  }
+}
+
+
 /*
  * Free a mount node.
  * The node must be already unmounted.
@@ -442,25 +463,24 @@
 {
   remove_am(mp);
 
-  if (mp->am_link)
-    XFREE(mp->am_link);
-  if (mp->am_name)
-    XFREE(mp->am_name);
-  if (mp->am_path)
-    XFREE(mp->am_path);
-  if (mp->am_pref)
-    XFREE(mp->am_pref);
-  if (mp->am_transp)
-    XFREE(mp->am_transp);
+  if (mp->am_fd[1] != -1)
+    plog(XLOG_FATAL, "free_map: called prior to notifying the child for %s.",
+	mp->am_path);
 
-  if (mp->am_mnt)
-    free_mntfs(mp->am_mnt);
+  XFREE(mp->am_link);
+  XFREE(mp->am_name);
+  XFREE(mp->am_path);
+  XFREE(mp->am_pref);
+  XFREE(mp->am_transp);
 
-  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);
+  if (mp->am_al)
+    free_loc(mp->am_al);
+
+  if (mp->am_alarray) {
+    am_loc **temp_al;
+    for (temp_al = mp->am_alarray; *temp_al; temp_al++)
+      free_loc(*temp_al);
+    XFREE(mp->am_alarray);
   }
 
 #ifdef HAVE_FS_AUTOFS
@@ -480,8 +500,8 @@
     if (STREQ(mp->am_path, dir))
       return mp;
 
-    if ((mp->am_mnt->mf_flags & MFF_MOUNTED) &&
-	STREQ(mp->am_mnt->mf_mount, dir))
+    if ((mp->am_al->al_mnt->mf_flags & MFF_MOUNTED) &&
+	STREQ(mp->am_al->al_mnt->mf_mount, dir))
       return mp;
 
     mp2 = find_ap_recursive(dir, mp->am_osib);
@@ -518,37 +538,20 @@
 
 
 /*
- * Find the mount node corresponding
- * to the mntfs structure.
- */
-am_node *
-find_mf(mntfs *mf)
-{
-  int i;
-
-  for (i = last_used_map; i >= 0; --i) {
-    am_node *mp = exported_ap[i];
-    if (mp && mp->am_mnt == mf)
-      return mp;
-  }
-
-  return 0;
-}
-
-
-/*
  * Get the filehandle for a particular named directory.
  * This is used during the bootstrap to tell the kernel
  * the filehandles of the initial automount points.
  */
-am_nfs_fh *
-get_root_nfs_fh(char *dir)
+am_nfs_handle_t *
+get_root_nfs_fh(char *dir, am_nfs_handle_t *nfh)
 {
-  static am_nfs_fh nfh;
   am_node *mp = get_root_ap(dir);
   if (mp) {
-    mp_to_fh(mp, &nfh);
-    return &nfh;
+    if (nfs_dispatcher == nfs_program_2)
+      mp_to_fh(mp, &nfh->v2);
+    else
+      mp_to_fh3(mp, &nfh->v3);
+    return nfh;
   }
 
   /*
@@ -584,7 +587,8 @@
 
   for (i = last_used_map; i >= 0; --i) {
     am_node *mp = exported_ap[i];
-    if (mp && mp->am_mnt && mp->am_mnt->mf_server == fs) {
+
+    if (mp && mp->am_al->al_mnt && mp->am_al->al_mnt->mf_server == fs) {
       plog(XLOG_INFO, "Flushed %s; dependent on %s", mp->am_path, fs->fs_host);
       mp->am_ttl = clocktime(NULL);
       done = 1;
@@ -608,7 +612,7 @@
   am_node *mp = (am_node *) arg;
   am_node *new_mp;
 
-  new_mp = mp->am_mnt->mf_ops->lookup_child(mp, dir, &error, VLOOK_CREATE);
+  new_mp = mp->am_al->al_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.
@@ -616,7 +620,7 @@
      */
     new_mp->am_gen = new_mp->am_fattr.na_fileid = 1;
 
-    new_mp = mp->am_mnt->mf_ops->mount_child(new_mp, &error);
+    (void) mp->am_al->al_mnt->mf_ops->mount_child(new_mp, &error);
   }
 
   if (error > 0) {
@@ -647,7 +651,7 @@
 void
 make_root_node(void)
 {
-  mntfs *root_mnt;
+  mntfs *root_mf;
   char *rootmap = ROOT_MAP;
   root_node = exported_ap_alloc();
 
@@ -659,24 +663,24 @@
   /*
    * Allocate a new mounted filesystem
    */
-  root_mnt = find_mntfs(&amfs_root_ops, (am_opts *) 0, "", rootmap, "", "", "");
+  root_mf = find_mntfs(&amfs_root_ops, (am_opts *) NULL, "", rootmap, "", "", "");
 
   /*
    * Replace the initial null reference
    */
-  free_mntfs(root_node->am_mnt);
-  root_node->am_mnt = root_mnt;
+  free_mntfs(root_node->am_al->al_mnt);
+  root_node->am_al->al_mnt = root_mf;
 
   /*
    * Initialize the root
    */
-  if (root_mnt->mf_ops->fs_init)
-    (*root_mnt->mf_ops->fs_init) (root_mnt);
+  if (root_mf->mf_ops->fs_init)
+    (*root_mf->mf_ops->fs_init) (root_mf);
 
   /*
    * Mount the root
    */
-  root_mnt->mf_error = root_mnt->mf_ops->mount_fs(root_node, root_mnt);
+  root_mf->mf_error = root_mf->mf_ops->mount_fs(root_node, root_mf);
 }
 
 
@@ -687,68 +691,81 @@
 void
 umount_exported(void)
 {
-  int i;
+  int i, work_done;
 
-  for (i = last_used_map; i >= 0; --i) {
-    am_node *mp = exported_ap[i];
-    mntfs *mf;
+  do {
+    work_done = 0;
 
-    if (!mp)
-      continue;
+    for (i = last_used_map; i >= 0; --i) {
+      am_node *mp = exported_ap[i];
+      mntfs *mf;
 
-    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_fsflags & FS_DIRECTORY))
       /*
-       * When shutting down this had better
-       * look like a directory, otherwise it
-       * can't be unmounted!
+       * Wait for children to be removed first
        */
-      mk_fattr(&mp->am_fattr, NFDIR);
+      if (mp->am_child)
+	continue;
 
-    if ((--immediate_abort < 0 &&
-	 !(mp->am_flags & AMF_ROOT) && mp->am_parent) ||
-	(mf->mf_flags & MFF_RESTART)) {
+      mf = mp->am_al->al_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;
+      }
 
-      /*
-       * 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);
+      if (!(mf->mf_fsflags & FS_DIRECTORY))
 	/*
-	 * use unmount_mp, not unmount_node, so that unmounts be
-	 * backgrounded as needed.
+	 * When shutting down this had better
+	 * look like a directory, otherwise it
+	 * can't be unmounted!
 	 */
-	unmount_mp((opaque_t) mp);
+	mk_fattr(&mp->am_fattr, NFDIR);
+
+      if ((--immediate_abort < 0 &&
+	   !(mp->am_flags & AMF_ROOT) && mp->am_parent) ||
+	  (mf->mf_flags & MFF_RESTART)) {
+
+	work_done++;
+
+	/*
+	 * 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);
+	  /*
+	   * use unmount_mp, not unmount_node, so that unmounts be
+	   * backgrounded as needed.
+	   */
+	  unmount_mp((opaque_t) mp);
+	} else {
+	  am_unmounted(mp);
+	}
+	if (!(mf->mf_flags & (MFF_UNMOUNTING|MFF_MOUNTED)))
+	  exported_ap[i] = NULL;
       } else {
-	am_unmounted(mp);
+	/*
+	 * Any other node gets forcibly timed out.
+	 */
+	mp->am_flags &= ~AMF_NOTIMEOUT;
+	mp->am_al->al_mnt->mf_flags &= ~MFF_RSTKEEP;
+	mp->am_ttl = 0;
+	mp->am_timeo = 1;
+	mp->am_timeo_w = 0;
       }
-      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;
     }
-  }
+  } while (work_done);
 }
 
 
@@ -762,7 +779,7 @@
 mount_node(opaque_t arg)
 {
   am_node *mp = (am_node *) arg;
-  mntfs *mf = mp->am_mnt;
+  mntfs *mf = mp->am_al->al_mnt;
   int error = 0;
 
 #ifdef HAVE_FS_AUTOFS
@@ -784,7 +801,7 @@
 unmount_node(opaque_t arg)
 {
   am_node *mp = (am_node *) arg;
-  mntfs *mf = mp->am_mnt;
+  mntfs *mf = mp->am_al->al_mnt;
   int error = 0;
 
   if (mf->mf_flags & MFF_ERROR) {
@@ -805,7 +822,7 @@
   }
 
   /* do this again, it might have changed */
-  mf = mp->am_mnt;
+  mf = mp->am_al->al_mnt;
   if (error) {
     errno = error;		/* XXX */
     dlog("%s: unmount: %m", mf->mf_mount);
@@ -819,7 +836,7 @@
 free_map_if_success(int rc, int term, opaque_t arg)
 {
   am_node *mp = (am_node *) arg;
-  mntfs *mf = mp->am_mnt;
+  mntfs *mf = mp->am_al->al_mnt;
   wchan_t wchan = get_mntfs_wchan(mf);
 
   /*
@@ -836,6 +853,7 @@
     reschedule_timeout_mp();
   }
   if (term) {
+    notify_child(mp, AMQ_UMNT_SIGNAL, 0, term);
     plog(XLOG_ERROR, "unmount for %s got signal %d", mp->am_path, term);
 #if defined(DEBUG) && defined(SIGTRAP)
     /*
@@ -852,18 +870,24 @@
 #endif /* HAVE_FS_AUTOFS */
     amd_stats.d_uerr++;
   } else if (rc) {
+    notify_child(mp, AMQ_UMNT_FAILED, rc, 0);
     if (mf->mf_ops == &amfs_program_ops || rc == EBUSY)
       plog(XLOG_STATS, "\"%s\" on %s still active", mp->am_path, mf->mf_mount);
     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);
+    if (rc != ENOENT) {
+      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() will call notify_child() appropriately.
+     */
     am_unmounted(mp);
   }
 
@@ -878,11 +902,11 @@
 unmount_mp(am_node *mp)
 {
   int was_backgrounded = 0;
-  mntfs *mf = mp->am_mnt;
+  mntfs *mf = mp->am_al->al_mnt;
 
 #ifdef notdef
   plog(XLOG_INFO, "\"%s\" on %s timed out (flags 0x%x)",
-       mp->am_path, mp->am_mnt->mf_mount, (int) mf->mf_flags);
+       mp->am_path, mf->mf_mount, (int) mf->mf_flags);
 #endif /* notdef */
 
 #ifndef MNT2_NFS_OPT_SYMTTL
@@ -914,10 +938,11 @@
       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;
     }
+    notify_child(mp, AMQ_UMNT_SERVER, 0, 0);
     return 0;
   }
 
-  dlog("\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount);
+  dlog("\"%s\" on %s timed out", mp->am_path, mf->mf_mount);
   mf->mf_flags |= MFF_UNMOUNTING;
 
 #ifdef HAVE_FS_AUTOFS
@@ -926,7 +951,8 @@
 #endif /* HAVE_FS_AUTOFS */
 
   if ((mf->mf_fsflags & FS_UBACKGROUND) &&
-      (mf->mf_flags & MFF_MOUNTED)) {
+      (mf->mf_flags & MFF_MOUNTED) &&
+     !(mf->mf_flags & MFF_ON_AUTOFS)) {
     dlog("Trying unmount in background");
     run_task(unmount_node, (opaque_t) mp,
 	     free_map_if_success, (opaque_t) mp);
@@ -964,7 +990,7 @@
     /*
      * Pick up mounted filesystem
      */
-    mf = mp->am_mnt;
+    mf = mp->am_al->al_mnt;
     if (!mf)
       continue;
 
@@ -1056,7 +1082,7 @@
     t = now + 1;
   dlog("Next mount timeout in %lds", (long) (t - now));
 
-  timeout_mp_id = timeout(t - now, timeout_mp, 0);
+  timeout_mp_id = timeout(t - now, timeout_mp, NULL);
 }
 
 
@@ -1068,5 +1094,5 @@
 {
   if (timeout_mp_id)
     untimeout(timeout_mp_id);
-  timeout_mp_id = timeout(0, timeout_mp, 0);
+  timeout_mp_id = timeout(0, timeout_mp, NULL);
 }

Modified: trunk/contrib/amd/amd/mapc.c
===================================================================
--- trunk/contrib/amd/amd/mapc.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/mapc.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -96,7 +92,7 @@
   {"regexp", MAPC_RE},
 #endif /* HAVE_REGEXEC */
   {"sync", MAPC_SYNC},
-  {0, 0}
+  {NULL, 0}
 };
 
 /*
@@ -137,6 +133,7 @@
 static int mapc_meta_search(mnt_map *, char *, char **, int);
 static void mapc_sync(mnt_map *);
 static void mapc_clear(mnt_map *);
+static void mapc_clear_kvhash(kv **);
 
 /* ROOT MAP */
 static int root_init(mnt_map *, char *, time_t *);
@@ -198,12 +195,6 @@
 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_or_mtime(mnt_map *, char *, time_t *);
@@ -211,7 +202,17 @@
 extern int file_search(mnt_map *, char *, char *, char **, time_t *);
 #endif /* HAVE_MAP_FILE */
 
+/* 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 */
 
+/* Sun-syntax MAPS */
+#ifdef HAVE_MAP_SUN
+/* XXX: fill in */
+#endif /* HAVE_MAP_SUN */
+
 /* note that the choice of MAPC_{INC,ALL} will affect browsable_dirs */
 static map_type maptypes[] =
 {
@@ -323,7 +324,21 @@
     MAPC_INC
   },
 #endif /* HAVE_MAP_EXEC */
+#ifdef notyet /* probe function needs to be there or SEGV */
+#ifdef HAVE_MAP_SUN
   {
+    /* XXX: fill in */
+    "sun",
+    NULL,
+    NULL,
+    NULL,			/* isup function */
+    NULL,
+    NULL,
+    0
+  },
+#endif /* HAVE_MAP_SUN */
+#endif
+  {
     "error",
     error_init,
     error_reload,
@@ -412,6 +427,44 @@
 
   dlog("add_kv: %s -> %s", key, val);
 
+  if (val != NULL && strchr(val, '\n') != NULL) {
+    /*
+     * If the entry value contains multiple lines we need to break
+     * them up and add them recursively.  This is a workaround to
+     * support Sun style multi-mounts.  Amd converts Sun style
+     * mulit-mounts to type:=auto.  The problem is that Sun packs all
+     * the entries on one line.  When Amd does the conversion it puts
+     * each type:=auto entry on the same line separated by '\n'.
+     */
+    char *entry, *tok;
+
+    /*
+     * The first line should contain the first entry.  The key for
+     * this entry is the key passed into this function.
+     */
+    if ((tok = strtok(val, "\n")) != NULL) {
+      mapc_add_kv(m, key, xstrdup(tok));
+    }
+
+    /*
+     * For the rest of the entries we need to tokenize them by '\n'
+     * and separate the keys from there entries.
+     */
+    while ((tok = strtok(NULL, "\n")) != NULL) {
+      key = tok;
+      /* find the entry */
+      for (entry = key; *entry && !isspace((unsigned char)*entry); entry++);
+      if (*entry) {
+	*entry++ = '\0';
+      }
+
+      mapc_add_kv(m, xstrdup(key), xstrdup(entry));
+    }
+
+    XFREE(val);
+    return;
+  }
+
 #ifdef HAVE_REGEXEC
   if (MAPC_ISRE(m)) {
     char pattern[MAXPATHLEN];
@@ -431,7 +484,8 @@
       plog(XLOG_USER, "error compiling RE \"%s\": %s", pattern, errstr);
       return;
     }
-  }
+  } else
+    memset(&re, 0, sizeof(re));
 #endif /* HAVE_REGEXEC */
 
   h = &m->kvhash[hash];
@@ -443,6 +497,7 @@
   n->val = val;
   n->next = *h;
   *h = n;
+  m->nentries++;
 }
 
 
@@ -506,7 +561,7 @@
   int rc = search_map(m, wildcard, &m->wildcard);
 
   if (rc != 0)
-    m->wildcard = 0;
+    m->wildcard = NULL;
 }
 
 
@@ -520,7 +575,7 @@
 mapc_reload_map(mnt_map *m)
 {
   int error, ret = 0;
-  kv *maphash[NKVHASH], *tmphash[NKVHASH];
+  kv *maphash[NKVHASH];
   time_t t;
 
   error = (*m->mtime) (m, m->map_name, &t);
@@ -546,6 +601,7 @@
   memset((voidp) m->kvhash, 0, sizeof(m->kvhash));
 
   dlog("calling map reload on %s", m->map_name);
+  m->nentries = 0;
   error = (*m->reload) (m, m->map_name, mapc_add_kv);
   if (error) {
     if (m->reloads == 0)
@@ -561,19 +617,19 @@
     else
       plog(XLOG_INFO, "reload #%d of map %s succeeded",
 	   m->reloads, m->map_name);
-    memcpy((voidp) tmphash, (voidp) m->kvhash, sizeof(m->kvhash));
-    memcpy((voidp) m->kvhash, (voidp) maphash, sizeof(m->kvhash));
-    mapc_clear(m);
-    memcpy((voidp) m->kvhash, (voidp) tmphash, sizeof(m->kvhash));
+    mapc_clear_kvhash(maphash);
+    if (m->wildcard) {
+       XFREE(m->wildcard);
+       m->wildcard = NULL;
+    }
     m->modify = t;
     ret = 1;
   }
-  m->wildcard = 0;
 
   dlog("calling mapc_search for wildcard");
   error = mapc_search(m, wildcard, &m->wildcard);
   if (error)
-    m->wildcard = 0;
+    m->wildcard = NULL;
   return ret;
 }
 
@@ -582,12 +638,12 @@
  * Create a new map
  */
 static mnt_map *
-mapc_create(char *map, char *opt, const char *type)
+mapc_create(char *map, char *opt, const char *type, const char *mntpt)
 {
   mnt_map *m = ALLOC(struct mnt_map);
   map_type *mt;
   time_t modify = 0;
-  int alloc = 0;
+  u_int alloc = 0;
 
   cmdoption(opt, mapc_opt, &alloc);
 
@@ -632,6 +688,7 @@
   /* assert: mt in maptypes */
 
   m->flags = alloc & ~MAPC_CACHE_MASK;
+  m->nentries = 0;
   alloc &= MAPC_CACHE_MASK;
 
   if (alloc == MAPC_DFLT)
@@ -678,12 +735,12 @@
   m->search = alloc >= MAPC_ALL ? error_search : mt->search;
   m->mtime = mt->mtime;
   memset((voidp) m->kvhash, 0, sizeof(m->kvhash));
-  m->map_name = strdup(map);
+  m->map_name = xstrdup(map);
   m->refc = 1;
-  m->wildcard = 0;
+  m->wildcard = NULL;
   m->reloads = 0;
-  /* Unfortunately with current code structure, this cannot be initialized here */
-  m->cfm = NULL;
+  /* initialize per-map information (flags, etc.) */
+  m->cfm = find_cf_map(mntpt);
 
   /*
    * synchronize cache with reality
@@ -695,10 +752,10 @@
 
 
 /*
- * Free the cached data in a map
+ * Free the cached data in a map hash
  */
 static void
-mapc_clear(mnt_map *m)
+mapc_clear_kvhash(kv **kvhash)
 {
   int i;
 
@@ -707,17 +764,26 @@
    * along free'ing the data.
    */
   for (i = 0; i < NKVHASH; i++) {
-    kv *k = m->kvhash[i];
+    kv *k = kvhash[i];
     while (k) {
       kv *n = k->next;
       XFREE(k->key);
-      if (k->val)
-	XFREE(k->val);
+      XFREE(k->val);
       XFREE(k);
       k = n;
     }
   }
+}
 
+
+/*
+ * Free the cached data in a map
+ */
+static void
+mapc_clear(mnt_map *m)
+{
+  mapc_clear_kvhash(m->kvhash);
+
   /*
    * Zero the hash slots
    */
@@ -726,10 +792,10 @@
   /*
    * Free the wildcard if it exists
    */
-  if (m->wildcard) {
-    XFREE(m->wildcard);
-    m->wildcard = 0;
-  }
+  XFREE(m->wildcard);
+  m->wildcard = NULL;
+
+  m->nentries = 0;
 }
 
 
@@ -737,7 +803,7 @@
  * Find a map, or create one if it does not exist
  */
 mnt_map *
-mapc_find(char *map, char *opt, const char *maptype)
+mapc_find(char *map, char *opt, const char *maptype, const char *mntpt)
 {
   mnt_map *m;
 
@@ -751,7 +817,7 @@
   ITER(m, mnt_map, &map_list_head)
     if (STREQ(m->map_name, map))
       return mapc_dup(m);
-  m = mapc_create(map, opt, maptype);
+  m = mapc_create(map, opt, maptype, mntpt);
   ins_que(&m->hdr, &map_list_head);
 
   return m;
@@ -788,7 +854,7 @@
 mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
 {
   int error = 0;
-  kv *k = 0;
+  kv *k = NULL;
 
   /*
    * Firewall
@@ -839,7 +905,7 @@
 	int retval;
 
 	/* XXX: this code was recently ported, and must be tested -Erez */
-	retval = regexec(&k->re, key, 0, 0, 0);
+	retval = regexec(&k->re, key, 0, NULL, 0);
 	if (retval == 0) {	/* succeeded */
 	  break;
 	} else {		/* failed to match, log error */
@@ -863,7 +929,7 @@
    */
   if (k) {
     if (k->val)
-      *pval = strdup(k->val);
+      *pval = xstrdup(k->val);
     else
       error = ENOENT;
   } else if (m->alloc >= MAPC_ALL) {
@@ -880,7 +946,7 @@
      */
     error = search_map(m, key, pval);
     if (!error && m->alloc == MAPC_INC)
-      mapc_add_kv(m, strdup(key), strdup(*pval));
+      mapc_add_kv(m, xstrdup(key), xstrdup(*pval));
   }
 
   /*
@@ -911,11 +977,11 @@
 	dlog("mapc recurses on %s", wildname);
 	error = mapc_meta_search(m, wildname, pval, MREC_PART);
 	if (error)
-	  *subp = 0;
+	  *subp = '\0';
       }
 
       if (error > 0 && m->wildcard) {
-	*pval = strdup(m->wildcard);
+	*pval = xstrdup(m->wildcard);
 	error = 0;
       }
     }
@@ -1031,7 +1097,7 @@
    * First make sure we have a root map to talk about...
    */
   if (!root_map)
-    root_map = mapc_find(ROOT_MAP, "mapdefault", NULL);
+    root_map = mapc_find(ROOT_MAP, "mapdefault", NULL, NULL);
 
   /*
    * Then add the entry...
@@ -1071,7 +1137,7 @@
     else
       xstrlcpy(str, opts, sizeof(str));
   }
-  mapc_repl_kv(root_map, strdup((char *)dir), strdup(str));
+  mapc_repl_kv(root_map, xstrdup(dir), xstrdup(str));
 }
 
 

Modified: trunk/contrib/amd/amd/mntfs.c
===================================================================
--- trunk/contrib/amd/amd/mntfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/mntfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -52,6 +48,16 @@
 int mntfs_allocated;
 
 
+am_loc *
+dup_loc(am_loc *loc)
+{
+  loc->al_refc++;
+  if (loc->al_mnt) {
+    dup_mntfs(loc->al_mnt);
+  }
+  return loc;
+}
+
 mntfs *
 dup_mntfs(mntfs *mf)
 {
@@ -71,24 +77,27 @@
 {
   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_fo = 0;
+  if (mo)
+    mf->mf_fo = copy_opts(mo);
+
+  mf->mf_mount = xstrdup(mp);
+  mf->mf_info = xstrdup(info);
+  mf->mf_auto = xstrdup(auto_opts);
+  mf->mf_mopts = xstrdup(mopts);
+  mf->mf_remopts = xstrdup(remopts);
   mf->mf_loopdev = NULL;
   mf->mf_refc = 1;
   mf->mf_flags = 0;
   mf->mf_error = -1;
   mf->mf_cid = 0;
-  mf->mf_private = 0;
-  mf->mf_prfree = 0;
+  mf->mf_private = NULL;
+  mf->mf_prfree = NULL;
 
   if (ops->ffserver)
     mf->mf_server = (*ops->ffserver) (mf);
   else
-    mf->mf_server = 0;
+    mf->mf_server = NULL;
 }
 
 
@@ -138,7 +147,7 @@
       }
 
       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.
@@ -171,7 +180,7 @@
 
 	if (mf->mf_private && mf->mf_prfree) {
 	  mf->mf_prfree(mf->mf_private);
-	  mf->mf_private = 0;
+	  mf->mf_private = NULL;
 	}
 
 	fs = ops->ffserver ? (*ops->ffserver) (mf) : (fserver *) NULL;
@@ -202,26 +211,35 @@
 mntfs *
 new_mntfs(void)
 {
-  return alloc_mntfs(&amfs_error_ops, (am_opts *) 0, "//nil//", ".", "", "", "");
+  return alloc_mntfs(&amfs_error_ops, (am_opts *) NULL, "//nil//", ".", "", "", "");
 }
 
+am_loc *
+new_loc(void)
+{
+  am_loc *loc = CALLOC(struct am_loc);
+  loc->al_fo = 0;
+  loc->al_mnt = new_mntfs();
+  loc->al_refc = 1;
+  return loc;
+}
 
+
 static void
 uninit_mntfs(mntfs *mf)
 {
-  if (mf->mf_auto)
-    XFREE(mf->mf_auto);
-  if (mf->mf_mopts)
-    XFREE(mf->mf_mopts);
-  if (mf->mf_remopts)
-    XFREE(mf->mf_remopts);
-  if (mf->mf_info)
-    XFREE(mf->mf_info);
+  if (mf->mf_fo) {
+    free_opts(mf->mf_fo);
+    XFREE(mf->mf_fo);
+  }
+  XFREE(mf->mf_auto);
+  XFREE(mf->mf_mopts);
+  XFREE(mf->mf_remopts);
+  XFREE(mf->mf_info);
   if (mf->mf_private && mf->mf_prfree)
     (*mf->mf_prfree) (mf->mf_private);
 
-  if (mf->mf_mount)
-    XFREE(mf->mf_mount);
+  XFREE(mf->mf_mount);
 
   /*
    * Clean up the file server
@@ -255,6 +273,16 @@
   --mntfs_allocated;
 }
 
+static void
+discard_loc(voidp v)
+{
+  am_loc *loc = v;
+  if (loc->al_fo) {
+    free_opts(loc->al_fo);
+    XFREE(loc->al_fo);
+  }
+  XFREE(loc);
+}
 
 void
 flush_mntfs(void)
@@ -270,7 +298,24 @@
   }
 }
 
+void
+free_loc(opaque_t arg)
+{
+  am_loc *loc = (am_loc *) arg;
+  dlog("free_loc %p", loc);
 
+  if (loc->al_refc <= 0) {
+    plog(XLOG_ERROR, "IGNORING free_loc for 0x%p", loc);
+    return;
+  }
+
+  if (loc->al_mnt)
+    free_mntfs(loc->al_mnt);
+  if (--loc->al_refc == 0) {
+    discard_loc(loc);
+  }
+}
+
 void
 free_mntfs(opaque_t arg)
 {
@@ -356,7 +401,6 @@
   if (mf->mf_ops != &amfs_error_ops &&
       (mf->mf_flags & MFF_MOUNTED) &&
       !FSRV_ISDOWN(mf->mf_server)) {
-    mf->mf_fo = mo;
     return mf;
   }
 

Modified: trunk/contrib/amd/amd/nfs_prot_svc.c
===================================================================
--- trunk/contrib/amd/amd/nfs_prot_svc.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/nfs_prot_svc.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -69,6 +65,7 @@
 
 /* global variables */
 SVCXPRT *current_transp;
+dispatcher_t nfs_dispatcher = nfs_program_2;
 
 /* typedefs */
 typedef char *(*nfssvcproc_t)(voidp, struct svc_req *);
@@ -299,3 +296,193 @@
     going_down(1);
   }
 }
+
+void
+nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
+{
+  union {
+    am_GETATTR3args am_nfs3_getattr_3_arg;
+    am_SETATTR3args am_nfs3_setattr_3_arg;
+    am_LOOKUP3args am_nfs3_lookup_3_arg;
+    am_ACCESS3args am_nfs3_access_3_arg;
+    am_READLINK3args am_nfs3_readlink_3_arg;
+    am_READ3args am_nfs3_read_3_arg;
+    am_WRITE3args am_nfs3_write_3_arg;
+    am_CREATE3args am_nfs3_create_3_arg;
+    am_MKDIR3args am_nfs3_mkdir_3_arg;
+    am_SYMLINK3args am_nfs3_symlink_3_arg;
+    am_MKNOD3args am_nfs3_mknod_3_arg;
+    am_REMOVE3args am_nfs3_remove_3_arg;
+    am_RMDIR3args am_nfs3_rmdir_3_arg;
+    am_RENAME3args am_nfs3_rename_3_arg;
+    am_LINK3args am_nfs3_link_3_arg;
+    am_READDIR3args am_nfs3_readdir_3_arg;
+    am_READDIRPLUS3args am_nfs3_readdirplus_3_arg;
+    am_FSSTAT3args am_nfs3_fsstat_3_arg;
+    am_FSINFO3args am_nfs3_fsinfo_3_arg;
+    am_PATHCONF3args am_nfs3_pathconf_3_arg;
+    am_COMMIT3args am_nfs3_commit_3_arg;
+  } argument;
+  char *result;
+  xdrproc_t _xdr_argument, _xdr_result;
+  nfssvcproc_t local;
+
+  switch (rqstp->rq_proc) {
+  case AM_NFS3_NULL:
+    _xdr_argument = (xdrproc_t) xdr_void;
+    _xdr_result = (xdrproc_t) xdr_void;
+    local = (nfssvcproc_t) am_nfs3_null_3_svc;
+    break;
+
+  case AM_NFS3_GETATTR:
+    _xdr_argument = (xdrproc_t) xdr_am_GETATTR3args;
+    _xdr_result = (xdrproc_t) xdr_am_GETATTR3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_getattr_3_svc;
+    break;
+
+  case AM_NFS3_SETATTR:
+    _xdr_argument = (xdrproc_t) xdr_am_SETATTR3args;
+    _xdr_result = (xdrproc_t) xdr_am_SETATTR3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_setattr_3_svc;
+    break;
+
+  case AM_NFS3_LOOKUP:
+    _xdr_argument = (xdrproc_t) xdr_am_LOOKUP3args;
+    _xdr_result = (xdrproc_t) xdr_am_LOOKUP3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_lookup_3_svc;
+    break;
+
+  case AM_NFS3_ACCESS:
+    _xdr_argument = (xdrproc_t) xdr_am_ACCESS3args;
+    _xdr_result = (xdrproc_t) xdr_am_ACCESS3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_access_3_svc;
+    break;
+
+  case AM_NFS3_READLINK:
+    _xdr_argument = (xdrproc_t) xdr_am_READLINK3args;
+    _xdr_result = (xdrproc_t) xdr_am_READLINK3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readlink_3_svc;
+    break;
+
+  case AM_NFS3_READ:
+    _xdr_argument = (xdrproc_t) xdr_am_READ3args;
+    _xdr_result = (xdrproc_t) xdr_am_READ3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_read_3_svc;
+    break;
+
+  case AM_NFS3_WRITE:
+    _xdr_argument = (xdrproc_t) xdr_am_WRITE3args;
+    _xdr_result = (xdrproc_t) xdr_am_WRITE3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_write_3_svc;
+    break;
+
+  case AM_NFS3_CREATE:
+    _xdr_argument = (xdrproc_t) xdr_am_CREATE3args;
+    _xdr_result = (xdrproc_t) xdr_am_CREATE3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_create_3_svc;
+    break;
+
+  case AM_NFS3_MKDIR:
+    _xdr_argument = (xdrproc_t) xdr_am_MKDIR3args;
+    _xdr_result = (xdrproc_t) xdr_am_MKDIR3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_mkdir_3_svc;
+    break;
+
+  case AM_NFS3_SYMLINK:
+    _xdr_argument = (xdrproc_t) xdr_am_SYMLINK3args;
+    _xdr_result = (xdrproc_t) xdr_am_SYMLINK3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_symlink_3_svc;
+    break;
+
+  case AM_NFS3_MKNOD:
+    _xdr_argument = (xdrproc_t) xdr_am_MKNOD3args;
+    _xdr_result = (xdrproc_t) xdr_am_MKNOD3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_mknod_3_svc;
+    break;
+
+  case AM_NFS3_REMOVE:
+    _xdr_argument = (xdrproc_t) xdr_am_REMOVE3args;
+    _xdr_result = (xdrproc_t) xdr_am_REMOVE3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_remove_3_svc;
+    break;
+
+  case AM_NFS3_RMDIR:
+    _xdr_argument = (xdrproc_t) xdr_am_RMDIR3args;
+    _xdr_result = (xdrproc_t) xdr_am_RMDIR3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_rmdir_3_svc;
+    break;
+
+  case AM_NFS3_RENAME:
+    _xdr_argument = (xdrproc_t) xdr_am_RENAME3args;
+    _xdr_result = (xdrproc_t) xdr_am_RENAME3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_rename_3_svc;
+    break;
+
+  case AM_NFS3_LINK:
+    _xdr_argument = (xdrproc_t) xdr_am_LINK3args;
+    _xdr_result = (xdrproc_t) xdr_am_LINK3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_link_3_svc;
+    break;
+
+  case AM_NFS3_READDIR:
+    _xdr_argument = (xdrproc_t) xdr_am_READDIR3args;
+    _xdr_result = (xdrproc_t) xdr_am_READDIR3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readdir_3_svc;
+    break;
+
+  case AM_NFS3_READDIRPLUS:
+    _xdr_argument = (xdrproc_t) xdr_am_READDIRPLUS3args;
+    _xdr_result = (xdrproc_t) xdr_am_READDIRPLUS3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readdirplus_3_svc;
+    break;
+
+  case AM_NFS3_FSSTAT:
+    _xdr_argument = (xdrproc_t) xdr_am_FSSTAT3args;
+    _xdr_result = (xdrproc_t) xdr_am_FSSTAT3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_fsstat_3_svc;
+    break;
+
+  case AM_NFS3_FSINFO:
+    _xdr_argument = (xdrproc_t) xdr_am_FSINFO3args;
+    _xdr_result = (xdrproc_t) xdr_am_FSINFO3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_fsinfo_3_svc;
+    break;
+
+  case AM_NFS3_PATHCONF:
+    _xdr_argument = (xdrproc_t) xdr_am_PATHCONF3args;
+    _xdr_result = (xdrproc_t) xdr_am_PATHCONF3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_pathconf_3_svc;
+    break;
+
+  case AM_NFS3_COMMIT:
+    _xdr_argument = (xdrproc_t) xdr_am_COMMIT3args;
+    _xdr_result = (xdrproc_t) xdr_am_COMMIT3res;
+    local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_commit_3_svc;
+    break;
+
+  default:
+    svcerr_noproc (transp);
+    return;
+  }
+
+  memset ((char *)&argument, 0, sizeof (argument));
+
+  if (!svc_getargs(transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
+    plog(XLOG_ERROR,
+	 "NFS xdr decode failed for %d %d %d",
+	 (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
+    svcerr_decode(transp);
+    return;
+  }
+
+  result = (*local) (&argument, rqstp);
+  if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
+    svcerr_systemerr (transp);
+  }
+
+  if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
+    plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_3");
+    going_down(1);
+  }
+  return;
+}

Modified: trunk/contrib/amd/amd/nfs_start.c
===================================================================
--- trunk/contrib/amd/amd/nfs_start.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/nfs_start.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -65,12 +61,11 @@
 static void
 checkup(void)
 {
-
   static int max_fd = 0;
-  static char *max_mem = 0;
-
+  static char *max_mem = NULL;
   int next_fd = dup(0);
   caddr_t next_mem = sbrk(0);
+
   close(next_fd);
 
   if (max_fd < next_fd) {
@@ -135,8 +130,8 @@
     /*
      * Wait for input
      */
-    nsel = select(fds, fdp, (fd_set *) 0, (fd_set *) 0,
-		  tvp->tv_sec ? tvp : (struct timeval *) 0);
+    nsel = select(fds, fdp, (fd_set *) NULL, (fd_set *) NULL,
+		  tvp->tv_sec ? tvp : (struct timeval *) NULL);
   }
 
 #ifdef HAVE_SIGACTION
@@ -171,7 +166,7 @@
   FD_SET(fwd_sock, &readfds);
 
   tvv.tv_sec = tvv.tv_usec = 0;
-  nsel = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &tvv);
+  nsel = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &tvv);
   if (nsel < 1)
     return (0);
   if (FD_ISSET(fwd_sock, &readfds))
@@ -365,7 +360,8 @@
    * already created the service during restart_automounter_nodes().
    */
   if (nfs_port == 0) {
-    ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
+    ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_dispatcher,
+	get_nfs_dispatcher_version(nfs_dispatcher));
     if (ret != 0)
       return ret;
   }
@@ -372,8 +368,8 @@
   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)) {
+  /* security: if user sets -D noamq, don't even create listening socket */
+  if (amuDebug(D_AMQ)) {
     ret = create_amq_service(&udp_soAMQ,
 			     &udp_amqp,
 			     &udp_amqncp,
@@ -416,25 +412,33 @@
     return 0;
   }
 
-  if (!amuDebug(D_AMQ)) {
+  if (amuDebug(D_AMQ)) {
     /*
      * Complete registration of amq (first TCP service then UDP)
      */
-    unregister_amq();
+    int tcp_ok = 0, udp_ok = 0;
 
-    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());
+    unregister_amq();	 /* unregister leftover Amd, if any, just in case */
+
+    tcp_ok = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
+			      amq_program_1, IPPROTO_TCP, tcp_amqncp);
+    if (!tcp_ok)
+      plog(XLOG_FATAL,
+	   "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, tcp)",
+	   get_amd_program_number());
+
+    udp_ok = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
+			      amq_program_1, IPPROTO_UDP, udp_amqncp);
+    if (!udp_ok)
+      plog(XLOG_FATAL,
+	   "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, udp)",
+	   get_amd_program_number());
+
+    /* return error only if both failed */
+    if (!tcp_ok && !udp_ok) {
+      amd_state = Done;
       return 3;
     }
-
-    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;
-    }
   }
 
   /*

Modified: trunk/contrib/amd/amd/nfs_subr.c
===================================================================
--- trunk/contrib/amd/amd/nfs_subr.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/nfs_subr.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -78,6 +74,17 @@
   } u;
 };
 
+struct am_fh3 {
+  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[AM_FHSIZE3-sizeof(u_int)];	/* path to am_node */
+  } u;
+};
 
 /* forward declarations */
 /* converting am-filehandles to mount-points */
@@ -96,10 +103,10 @@
    * otherwise if a link exists use that,
    * otherwise use the mount point.
    */
-  if (mp->am_mnt->mf_ops->readlink) {
+  if (mp->am_al->al_mnt->mf_ops->readlink) {
     int retry = 0;
-    mp = (*mp->am_mnt->mf_ops->readlink) (mp, &retry);
-    if (mp == 0) {
+    mp = (*mp->am_al->al_mnt->mf_ops->readlink) (mp, &retry);
+    if (mp == NULL) {
       *error_return = retry;
       return 0;
     }
@@ -109,7 +116,7 @@
   if (mp->am_link) {
     ln = mp->am_link;
   } else {
-    ln = mp->am_mnt->mf_mount;
+    ln = mp->am_al->al_mnt->mf_mount;
   }
 
   return ln;
@@ -130,7 +137,7 @@
 {
   static nfsattrstat res;
   am_node *mp;
-  int retry;
+  int retry = 0;
   time_t now = clocktime(NULL);
 
   if (amuDebug(D_TRACE))
@@ -137,7 +144,7 @@
     plog(XLOG_DEBUG, "getattr:");
 
   mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
-  if (mp == 0) {
+  if (mp == NULL) {
     if (amuDebug(D_TRACE))
       plog(XLOG_DEBUG, "\tretry=%d", retry);
 
@@ -209,7 +216,7 @@
   xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) gid);
 
   mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_CREATE);
-  if (mp == 0) {
+  if (mp == NULL) {
     if (retry < 0) {
       amd_stats.d_drops++;
       return 0;
@@ -220,9 +227,9 @@
     am_node *ap;
     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);
+    ap = mp->am_al->al_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);
+      ap = mp->am_al->al_mnt->mf_ops->mount_child(ap, &error);
     if (ap == 0) {
       if (error < 0) {
 	amd_stats.d_drops++;
@@ -285,7 +292,7 @@
      * Free up transp.  It's only used for one reply.
      */
     XFREE(mp->am_transp);
-    dlog("Quick reply sent for %s", mp->am_mnt->mf_mount);
+    dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
   }
 }
 
@@ -301,7 +308,7 @@
     plog(XLOG_DEBUG, "readlink:");
 
   mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
-  if (mp == 0) {
+  if (mp == NULL) {
   readlink_retry:
     if (retry < 0) {
       amd_stats.d_drops++;
@@ -379,7 +386,7 @@
   int retry;
 
   am_node *mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_DELETE);
-  if (mp == 0) {
+  if (mp == NULL) {
     if (retry < 0) {
       amd_stats.d_drops++;
       return 0;
@@ -396,8 +403,8 @@
   if (amuDebug(D_TRACE))
     plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->da_name);
 
-  mp = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &retry, VLOOK_DELETE);
-  if (mp == 0) {
+  mp = mp->am_al->al_mnt->mf_ops->lookup_child(mp, argp->da_name, &retry, VLOOK_DELETE);
+  if (mp == NULL) {
     /*
      * Ignore retries...
      */
@@ -510,7 +517,7 @@
     plog(XLOG_DEBUG, "readdir:");
 
   mp = fh_to_mp3(&argp->rda_fhandle, &retry, VLOOK_CREATE);
-  if (mp == 0) {
+  if (mp == NULL) {
     if (retry < 0) {
       amd_stats.d_drops++;
       return 0;
@@ -519,7 +526,7 @@
   } else {
     if (amuDebug(D_TRACE))
       plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
-    res.rdr_status = nfs_error((*mp->am_mnt->mf_ops->readdir)
+    res.rdr_status = nfs_error((*mp->am_al->al_mnt->mf_ops->readdir)
 			   (mp, argp->rda_cookie,
 			    &res.rdr_u.rdr_reply_u, e_res, argp->rda_count));
     mp->am_stats.s_readdir++;
@@ -541,7 +548,7 @@
     plog(XLOG_DEBUG, "statfs:");
 
   mp = fh_to_mp3(argp, &retry, VLOOK_CREATE);
-  if (mp == 0) {
+  if (mp == NULL) {
     if (retry < 0) {
       amd_stats.d_drops++;
       return 0;
@@ -562,8 +569,8 @@
 
     /* check if map is browsable and show_statfs_entries=yes  */
     if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) &&
-	mp->am_mnt && mp->am_mnt->mf_mopts) {
-      mnt.mnt_opts = mp->am_mnt->mf_mopts;
+	mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) {
+      mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts;
       if (amu_hasmntopt(&mnt, "browsable")) {
 	count_map_entries(mp,
 			  &fp->sfrok_blocks,
@@ -599,7 +606,7 @@
   blocks = bfree = bavail = 0;
   if (!mp)
     goto out;
-  mf = mp->am_mnt;
+  mf = mp->am_al->al_mnt;
   if (!mf)
     goto out;
   mmp = (mnt_map *) mf->mf_private;
@@ -625,50 +632,10 @@
   *out_bavail = bavail;
 }
 
-
-/*
- * Convert from file handle to automount node.
- */
 static am_node *
-fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop)
+validate_ap(am_node *node, int *rp, u_int fhh_gen)
 {
-  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);
-  }
-
+  am_node *ap = node;
   /*
    * Check the generation number in the node
    * matches the one from the kernel.  If not
@@ -675,8 +642,8 @@
    * 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 (node != NULL && node->am_gen != fhh_gen)
+    ap = NULL;
 
   /*
    * If it doesn't exists then drop the request
@@ -690,12 +657,12 @@
    * for it.  This implements the replicated filesystem
    * retries.
    */
-  if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) {
+  if (ap->am_al->al_mnt && FSRV_ISDOWN(ap->am_al->al_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);
+    dlog("%s: %s (%s) is hung: lookup alternative file server", __func__,
+	 orig_ap->am_path, orig_ap->am_al->al_mnt->mf_info);
 
     /*
      * Update modify time of parent node.
@@ -712,11 +679,11 @@
      * 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);
+      ap = orig_ap->am_parent->am_al->al_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);
+	ap = orig_ap->am_parent->am_al->al_mnt->mf_ops->mount_child(ap, &error);
     } else {
-      ap = 0;
+      ap = NULL;
       error = ESTALE;
     }
     if (ap == 0) {
@@ -735,13 +702,13 @@
     new_ttl(orig_ap);
 
   }
-#endif
+#endif /* 0 */
 
   /*
    * Disallow references to objects being unmounted, unless
    * they are automount points.
    */
-  if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) &&
+  if (ap->am_al->al_mnt && (ap->am_al->al_mnt->mf_flags & MFF_UNMOUNTING) &&
       !(ap->am_flags & AMF_ROOT)) {
     if (amd_state == Finishing)
       *rp = ENOENT;
@@ -752,7 +719,7 @@
   new_ttl(ap);
 
 drop:
-  if (!ap || !ap->am_mnt) {
+  if (!ap || !ap->am_al->al_mnt) {
     /*
      * If we are shutting down then it is likely
      * that this node has disappeared because of
@@ -764,15 +731,61 @@
      */
     if (amd_state == Finishing)
       *rp = ENOENT;
-    else
+    else {
       *rp = ESTALE;
-    amd_stats.d_stale++;
+      amd_stats.d_stale++;
+    }
   }
 
   return ap;
 }
 
+/*
+ * 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 = NULL;
 
+  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("%s: new filehandle: %s", __func__, path);
+
+    ap = path_to_exported_ap(path);
+    XFREE(path);
+  } else {
+    dlog("%s: old filehandle: %d", __func__, 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("%s: wrong pid %ld != my pid %ld", __func__,
+	   (long) fp->u.s.fhh_pid, get_server_pid());
+      goto done;
+    }
+
+    /*
+     * Get hold of the supposed mount node
+     */
+    ap = get_exported_ap(fp->u.s.fhh_id);
+  }
+done:
+  return validate_ap(ap, rp, fp->fhh_gen);
+}
+
 static am_node *
 fh_to_mp(am_nfs_fh *fhp)
 {
@@ -781,7 +794,57 @@
   return fh_to_mp3(fhp, &dummy, VLOOK_CREATE);
 }
 
+static am_node *
+fh3_to_mp3(am_nfs_fh3 *fhp, int *rp, int vop)
+{
+  struct am_fh3 *fp = (struct am_fh3 *) fhp->am_fh3_data;
+  am_node *ap = NULL;
 
+  if (fp->u.s.fhh_type != 0) {
+    /* New filehandle type */
+    int len = sizeof(*fp) - 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("%s: new filehandle: %s", __func__, path);
+
+    ap = path_to_exported_ap(path);
+    XFREE(path);
+  } else {
+    dlog("%s: old filehandle: %d", __func__, 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("%s: wrong pid %ld != my pid %ld", __func__,
+	   (long) fp->u.s.fhh_pid, get_server_pid());
+      goto done;
+    }
+
+    /*
+     * Get hold of the supposed mount node
+     */
+    ap = get_exported_ap(fp->u.s.fhh_id);
+  }
+done:
+  return validate_ap(ap, rp, fp->fhh_gen);
+}
+
+static am_node *
+fh3_to_mp(am_nfs_fh3 *fhp)
+{
+  int dummy;
+
+  return fh3_to_mp3(fhp, &dummy, VLOOK_CREATE);
+}
+
 /*
  * Convert from automount node to file handle.
  */
@@ -826,3 +889,975 @@
     /* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */
   }
 }
+void
+mp_to_fh3(am_node *mp, am_nfs_fh3 *fhp)
+{
+  u_int pathlen;
+  struct am_fh3 *fp = (struct am_fh3 *) fhp->am_fh3_data;
+
+  memset((char *) fhp, 0, sizeof(am_nfs_fh3));
+  fhp->am_fh3_length = AM_FHSIZE3;
+
+  /* Store the generation number */
+  fp->fhh_gen = mp->am_gen;
+
+  pathlen = strlen(mp->am_path);
+  if (pathlen <= sizeof(*fp) - 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); */
+  }
+}
+
+#ifdef HAVE_FS_NFS3
+static am_ftype3 ftype_to_ftype3(nfsftype ftype)
+{
+  if (ftype == NFFIFO)
+    return AM_NF3FIFO;
+  else
+    return ftype;
+}
+
+static void nfstime_to_am_nfstime3(nfstime *time, am_nfstime3 *time3)
+{
+  time3->seconds = time->seconds;
+  time3->nseconds = time->useconds * 1000;
+}
+
+static void rdev_to_am_specdata3(u_int rdev, am_specdata3 *rdev3)
+{
+  /* No device node here */
+  rdev3->specdata1 = (u_int) -1;
+  rdev3->specdata2 = (u_int) -1;
+}
+
+static void fattr_to_fattr3(nfsfattr *fattr, am_fattr3 *fattr3)
+{
+  fattr3->type = ftype_to_ftype3(fattr->na_type);
+  fattr3->mode = (am_mode3) fattr->na_mode;
+  fattr3->nlink = fattr->na_nlink;
+  fattr3->uid = (am_uid3) fattr->na_uid;
+  fattr3->gid = (am_uid3) fattr->na_gid;
+  fattr3->size = (am_size3) fattr->na_size;
+  fattr3->used = (am_size3) fattr->na_size;
+  rdev_to_am_specdata3(fattr->na_rdev, &fattr3->rdev);
+  fattr3->fsid = (uint64) fattr->na_fsid;
+  fattr3->fileid = (uint64) fattr->na_fileid;
+  nfstime_to_am_nfstime3(&fattr->na_atime, &fattr3->atime);
+  nfstime_to_am_nfstime3(&fattr->na_mtime, &fattr3->mtime);
+  nfstime_to_am_nfstime3(&fattr->na_ctime, &fattr3->ctime);
+}
+
+static void fattr_to_wcc_attr(nfsfattr *fattr, am_wcc_attr *wcc_attr)
+{
+  wcc_attr->size = (am_size3) fattr->na_size;
+  nfstime_to_am_nfstime3(&fattr->na_mtime, &wcc_attr->mtime);
+  nfstime_to_am_nfstime3(&fattr->na_ctime, &wcc_attr->ctime);
+}
+
+static am_nfsstat3 return_estale_or_rofs(am_nfs_fh3 *fh,
+                                         am_pre_op_attr *pre_op,
+                                         am_post_op_attr *post_op)
+{
+  am_node *mp;
+
+  mp = fh3_to_mp(fh);
+  if (!mp) {
+    pre_op->attributes_follow = 0;
+    post_op->attributes_follow = 0;
+    return  nfs_error(ESTALE);
+  } else {
+    am_fattr3 *fattr3 = &post_op->am_post_op_attr_u.attributes;
+    am_wcc_attr *wcc_attr = &pre_op->am_pre_op_attr_u.attributes;
+    nfsfattr *fattr = &mp->am_fattr;
+    pre_op->attributes_follow = 1;
+    fattr_to_wcc_attr(fattr, wcc_attr);
+    post_op->attributes_follow = 1;
+    fattr_to_fattr3(fattr, fattr3);
+    return nfs_error(EROFS);
+  }
+}
+
+static am_nfsstat3 unlink3_or_rmdir3(am_diropargs3 *argp,
+                                     am_wcc_data *wcc_data, int unlinkp)
+{
+  static am_nfsstat3 res;
+  am_nfs_fh3 *dir = &argp->dir;
+  am_filename3 name = argp->name;
+  am_pre_op_attr *pre_op_dir = &wcc_data->before;
+  am_post_op_attr *post_op_dir = &wcc_data->after;
+  nfsfattr *fattr;
+  am_wcc_attr *wcc_attr;
+  am_node *mp, *ap;
+  int retry;
+
+  post_op_dir->attributes_follow = 0;
+
+  mp = fh3_to_mp3(dir, &retry, VLOOK_DELETE);
+  if (!mp) {
+    pre_op_dir->attributes_follow = 0;
+    if (retry < 0) {
+      amd_stats.d_drops++;
+      return 0;
+    }
+    res = nfs_error(retry);
+    goto out;
+  }
+
+  pre_op_dir->attributes_follow = 1;
+  fattr = &mp->am_fattr;
+  wcc_attr = &pre_op_dir->am_pre_op_attr_u.attributes;
+  fattr_to_wcc_attr(fattr, wcc_attr);
+
+  if (mp->am_fattr.na_type != NFDIR) {
+    res = nfs_error(ENOTDIR);
+    goto out;
+  }
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, name);
+
+  ap = mp->am_al->al_mnt->mf_ops->lookup_child(mp, name, &retry, VLOOK_DELETE);
+  if (!ap) {
+    /*
+     * Ignore retries...
+     */
+    if (retry < 0)
+      retry = 0;
+    /*
+     * Usual NFS workaround...
+     */
+    else if (retry == ENOENT)
+      retry = 0;
+    res = nfs_error(retry);
+  } else {
+    forcibly_timeout_mp(mp);
+    res = AM_NFS3_OK;
+  }
+
+out:
+  return res;
+}
+
+voidp
+am_nfs3_null_3_svc(voidp argp, struct svc_req *rqstp)
+{
+  static char * result;
+
+  return (voidp) &result;
+}
+
+am_GETATTR3res *
+am_nfs3_getattr_3_svc(am_GETATTR3args *argp, struct svc_req *rqstp)
+{
+  static am_GETATTR3res  result;
+  am_nfs_fh3 *fh = (am_nfs_fh3 *) &argp->object;
+  am_fattr3 *fattr3;
+  nfsfattr *fattr;
+  am_node *mp;
+  int retry = 0;
+  time_t now = clocktime(NULL);
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "getattr_3:");
+
+  mp = fh3_to_mp3(fh, &retry, VLOOK_CREATE);
+  if (!mp) {
+    if (amuDebug(D_TRACE))
+      plog(XLOG_DEBUG, "\tretry=%d", retry);
+
+    if (retry < 0) {
+      amd_stats.d_drops++;
+      return 0;
+    }
+    result.status = nfs_error(retry);
+    return &result;
+  }
+
+  fattr = &mp->am_fattr;
+  fattr3 = (am_fattr3 *) &result.res_u.ok.obj_attributes;
+  fattr_to_fattr3(fattr, fattr3);
+
+  result.status = AM_NFS3_OK;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "\tstat(%s), size = %lu, mtime=%d.%d",
+	 mp->am_path,
+	 (u_long) fattr3->size,
+	 (u_int) fattr3->mtime.seconds,
+	 (u_int) fattr3->mtime.nseconds);
+
+  /* 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 &result;
+}
+
+am_SETATTR3res *
+am_nfs3_setattr_3_svc(am_SETATTR3args *argp, struct svc_req *rqstp)
+{
+  static am_SETATTR3res  result;
+  am_nfs_fh3 *fh = (am_nfs_fh3 *) &argp->object;
+  am_pre_op_attr *pre_op_obj = &result.res_u.fail.obj_wcc.before;
+  am_post_op_attr *post_op_obj = &result.res_u.fail.obj_wcc.after;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "setattr_3:");
+
+  result.status = return_estale_or_rofs(fh, pre_op_obj, post_op_obj);
+
+  return &result;
+}
+
+am_LOOKUP3res *
+am_nfs3_lookup_3_svc(am_LOOKUP3args *argp, struct svc_req *rqstp)
+{
+  static am_LOOKUP3res  result;
+  am_nfs_fh3 *dir = &argp->what.dir;
+  am_post_op_attr *post_op_dir;
+  am_post_op_attr *post_op_obj;
+  am_node *mp;
+  int retry;
+  uid_t uid;
+  gid_t gid;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "lookup_3:");
+
+  /* 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 = fh3_to_mp3(dir, &retry, VLOOK_CREATE);
+  if (!mp) {
+    post_op_dir = &result.res_u.fail.dir_attributes;
+    post_op_dir->attributes_follow = 0;
+    if (retry < 0) {
+      amd_stats.d_drops++;
+      return 0;
+    }
+    result.status = nfs_error(retry);
+  } else {
+    post_op_dir = &result.res_u.ok.dir_attributes;
+    post_op_obj = &result.res_u.ok.obj_attributes;
+    am_filename3 name;
+    am_fattr3 *fattr3;
+    nfsfattr *fattr;
+    am_node *ap;
+    int error;
+
+    /* dir attributes */
+    post_op_dir->attributes_follow = 1;
+    fattr = &mp->am_fattr;
+    fattr3 = &post_op_dir->am_post_op_attr_u.attributes;
+    fattr_to_fattr3(fattr, fattr3);
+
+    post_op_obj->attributes_follow = 0;
+
+    name = argp->what.name;
+
+    if (amuDebug(D_TRACE))
+      plog(XLOG_DEBUG, "\tlookup_3(%s, %s)", mp->am_path, name);
+
+    ap = mp->am_al->al_mnt->mf_ops->lookup_child(mp, name, &error, VLOOK_CREATE);
+    if (ap && error < 0)
+      ap = mp->am_al->al_mnt->mf_ops->mount_child(ap, &error);
+    if (ap == 0) {
+      if (error < 0) {
+	amd_stats.d_drops++;
+	return 0;
+      }
+      result.status = nfs_error(error);
+    } else {
+      /*
+       * XXX: EXPERIMENTAL! Delay unmount of what was looked up.  This
+       * should reduce the chance for race condition between unmounting an
+       * entry synchronously, and re-mounting it asynchronously.
+       */
+      if (ap->am_ttl < mp->am_ttl)
+        ap->am_ttl = mp->am_ttl;
+
+      mp_to_fh3(ap, &result.res_u.ok.object);
+
+      /* mount attributes */
+      post_op_obj->attributes_follow = 1;
+      fattr = &ap->am_fattr;
+      fattr3 = &post_op_obj->am_post_op_attr_u.attributes;
+      fattr_to_fattr3(fattr, fattr3);
+
+      result.status = AM_NFS3_OK;
+    }
+    mp->am_stats.s_lookup++;
+  }
+  return &result;
+}
+
+am_ACCESS3res *
+am_nfs3_access_3_svc(am_ACCESS3args *argp, struct svc_req *rqstp)
+{
+  static am_ACCESS3res  result;
+
+  am_nfs_fh3 *obj = &argp->object;
+  u_int accessbits = argp->access;
+  u_int accessmask = AM_ACCESS3_LOOKUP|AM_ACCESS3_READ;
+  am_post_op_attr *post_op_obj;
+  am_node *mp;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "access_3:");
+
+  mp = fh3_to_mp(obj);
+  if (!mp) {
+    post_op_obj = &result.res_u.fail.obj_attributes;
+    post_op_obj->attributes_follow = 0;
+    result.status = nfs_error(ENOENT);
+    if (amuDebug(D_TRACE))
+      plog(XLOG_DEBUG, "access_3: ENOENT");
+  } else {
+    nfsfattr *fattr = &mp->am_fattr;
+    am_fattr3 *fattr3;
+    post_op_obj = &result.res_u.ok.obj_attributes;
+    fattr3 = &post_op_obj->am_post_op_attr_u.attributes;
+    post_op_obj->attributes_follow = 1;
+    fattr_to_fattr3(fattr, fattr3);
+
+    result.res_u.ok.access = accessbits & accessmask;
+    if (amuDebug(D_TRACE))
+      plog(XLOG_DEBUG, "access_3: b=%x m=%x", accessbits, accessmask);
+
+    result.status = AM_NFS3_OK;
+  }
+
+  return &result;
+}
+
+am_READLINK3res *
+am_nfs3_readlink_3_svc(am_READLINK3args *argp, struct svc_req *rqstp)
+{
+  static am_READLINK3res  result;
+
+  am_nfs_fh3 *symlink = (am_nfs_fh3 *) &argp->symlink;
+  am_post_op_attr *post_op_sym;
+  am_node *mp;
+  int retry = 0;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "readlink_3:");
+
+  mp = fh3_to_mp3(symlink, &retry, VLOOK_CREATE);
+  if (!mp) {
+  readlink_retry:
+    if (retry < 0) {
+      amd_stats.d_drops++;
+      return 0;
+    }
+    post_op_sym = &result.res_u.fail.symlink_attributes;
+    post_op_sym->attributes_follow = 0;
+    result.status = nfs_error(retry);
+  } else {
+    nfsfattr *fattr;
+    am_fattr3 *fattr3;
+    char *ln;
+
+    ln = do_readlink(mp, &retry);
+    if (!ln)
+      goto readlink_retry;
+
+    if (amuDebug(D_TRACE) && ln)
+      plog(XLOG_DEBUG, "\treadlink_3(%s) = %s", mp->am_path, ln);
+
+    result.res_u.ok.data = ln;
+
+    post_op_sym = &result.res_u.ok.symlink_attributes;
+    post_op_sym->attributes_follow = 1;
+    fattr = &mp->am_fattr;
+    fattr3 = &post_op_sym->am_post_op_attr_u.attributes;
+    fattr_to_fattr3(fattr, fattr3);
+
+    mp->am_stats.s_readlink++;
+    result.status = AM_NFS3_OK;
+  }
+
+  return &result;
+}
+
+am_READ3res *
+am_nfs3_read_3_svc(am_READ3args *argp, struct svc_req *rqstp)
+{
+  static am_READ3res  result;
+
+  am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file;
+  am_post_op_attr *post_op_file;
+  am_node *mp;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "read_3:");
+
+  post_op_file = &result.res_u.fail.file_attributes;
+  result.status = nfs_error(EACCES);
+
+  mp = fh3_to_mp(file);
+  if (!mp)
+    post_op_file->attributes_follow = 0;
+  else {
+    nfsfattr *fattr = &mp->am_fattr;
+    am_fattr3 *fattr3 = &post_op_file->am_post_op_attr_u.attributes;
+    post_op_file->attributes_follow = 1;
+    fattr_to_fattr3(fattr, fattr3);
+  }
+
+  return &result;
+}
+
+am_WRITE3res *
+am_nfs3_write_3_svc(am_WRITE3args *argp, struct svc_req *rqstp)
+{
+  static am_WRITE3res  result;
+
+  am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file;
+  am_pre_op_attr *pre_op_file = &result.res_u.fail.file_wcc.before;
+  am_post_op_attr *post_op_file = &result.res_u.fail.file_wcc.after;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "write_3:");
+
+  result.status = return_estale_or_rofs(file, pre_op_file, post_op_file);
+
+  return &result;
+}
+
+am_CREATE3res *
+am_nfs3_create_3_svc(am_CREATE3args *argp, struct svc_req *rqstp)
+{
+  static am_CREATE3res  result;
+
+  am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir;
+  am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before;
+  am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "create_3:");
+
+  result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir);
+
+  return &result;
+}
+
+am_MKDIR3res *
+am_nfs3_mkdir_3_svc(am_MKDIR3args *argp, struct svc_req *rqstp)
+{
+  static am_MKDIR3res  result;
+
+  am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir;
+  am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before;
+  am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "mkdir_3:");
+
+  result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir);
+
+  return &result;
+}
+
+am_SYMLINK3res *
+am_nfs3_symlink_3_svc(am_SYMLINK3args *argp, struct svc_req *rqstp)
+{
+  static am_SYMLINK3res  result;
+
+  am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir;
+  am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before;
+  am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "symlink_3:");
+
+  result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir);
+
+  return &result;
+}
+
+am_MKNOD3res *
+am_nfs3_mknod_3_svc(am_MKNOD3args *argp, struct svc_req *rqstp)
+{
+  static am_MKNOD3res  result;
+
+  am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir;
+  am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before;
+  am_post_op_attr *post_op_dir =  &result.res_u.fail.dir_wcc.after;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "mknod_3:");
+
+  result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir);
+  return &result;
+}
+
+am_REMOVE3res *
+am_nfs3_remove_3_svc(am_REMOVE3args *argp, struct svc_req *rqstp)
+{
+  static am_REMOVE3res  result;
+
+  am_diropargs3 *obj = &argp->object;
+  am_wcc_data dir_wcc;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "remove_3:");
+
+  result.status = unlink3_or_rmdir3(obj, &dir_wcc, TRUE);
+
+  result.res_u.ok.dir_wcc = dir_wcc;
+ 
+  return &result;
+}
+
+am_RMDIR3res *
+am_nfs3_rmdir_3_svc(am_RMDIR3args *argp, struct svc_req *rqstp)
+{
+  static am_RMDIR3res  result;
+
+  am_diropargs3 *obj = &argp->object;
+  am_wcc_data dir_wcc;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "rmdir_3:");
+
+  result.status = unlink3_or_rmdir3(obj, &dir_wcc, TRUE);
+
+  result.res_u.ok.dir_wcc = dir_wcc;
+ 
+  return &result;
+}
+
+am_RENAME3res *
+am_nfs3_rename_3_svc(am_RENAME3args *argp, struct svc_req *rqstp)
+{
+  static am_RENAME3res  result;
+
+  am_nfs_fh3 *fromdir = (am_nfs_fh3 *) &argp->from.dir;
+  am_nfs_fh3 *todir = (am_nfs_fh3 *) &argp->to.dir;
+  am_filename3 name = argp->to.name;
+  am_node *to_mp, *from_mp;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "rename_3:");
+
+  if (!(from_mp = fh3_to_mp(fromdir)) || !(to_mp = fh3_to_mp(todir)))
+    result.status = nfs_error(ESTALE);
+  /*
+   * If the kernel is doing clever things with referenced files
+   * then let it pretend...
+   */
+  else {
+    am_wcc_attr *wcc_attr;
+    am_fattr3 *fattr3;
+    am_wcc_data *to_wcc_data, *from_wcc_data;
+    am_pre_op_attr *pre_op_to, *pre_op_from;
+    am_post_op_attr *post_op_to, *post_op_from;
+    nfsfattr *fattr;
+
+    to_wcc_data = &result.res_u.ok.todir_wcc;
+
+    pre_op_to = &to_wcc_data->before;
+    post_op_to = &to_wcc_data->after;
+
+    pre_op_to->attributes_follow = 1;
+    fattr = &to_mp->am_fattr;
+    wcc_attr = &pre_op_to->am_pre_op_attr_u.attributes;
+    fattr_to_wcc_attr(fattr, wcc_attr);
+    post_op_to->attributes_follow = 1;
+    fattr3 = &post_op_to->am_post_op_attr_u.attributes;
+    fattr_to_fattr3(fattr, fattr3);
+
+    from_wcc_data = &result.res_u.ok.fromdir_wcc;
+
+    pre_op_from = &from_wcc_data->before;
+    post_op_from = &from_wcc_data->after;
+
+    pre_op_from->attributes_follow = 1;
+    fattr = &from_mp->am_fattr;
+    wcc_attr = &pre_op_from->am_pre_op_attr_u.attributes;
+    fattr_to_wcc_attr(fattr, wcc_attr);
+    post_op_from->attributes_follow = 1;
+    fattr3 = &post_op_from->am_post_op_attr_u.attributes;
+    fattr_to_fattr3(fattr, fattr3);
+
+    if (NSTREQ(name, ".nfs", 4))
+      result.status = AM_NFS3_OK;
+    /*
+     * otherwise a failure
+     */
+    else
+      result.status = nfs_error(EROFS);
+  }
+
+  return &result;
+}
+
+am_LINK3res *
+am_nfs3_link_3_svc(am_LINK3args *argp, struct svc_req *rqstp)
+{
+  static am_LINK3res  result;
+
+  am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file;
+  am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->link.dir;
+  am_post_op_attr *post_op_file;
+  am_pre_op_attr *pre_op_dir;
+  am_post_op_attr *post_op_dir;
+  am_node *mp_file, *mp_dir;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "link_3:");
+
+  post_op_file = &result.res_u.fail.file_attributes;
+  post_op_file->attributes_follow = 0;
+
+  mp_file = fh3_to_mp(file);
+  if (mp_file) {
+    nfsfattr *fattr = &mp_file->am_fattr;
+    am_fattr3 *fattr3 = &post_op_file->am_post_op_attr_u.attributes;
+    fattr_to_fattr3(fattr, fattr3);
+  }
+
+  pre_op_dir = &result.res_u.fail.linkdir_wcc.before;
+  pre_op_dir->attributes_follow = 0;
+  post_op_dir = &result.res_u.fail.linkdir_wcc.after;
+  post_op_dir->attributes_follow = 0;
+
+  mp_dir = fh3_to_mp(dir);
+  if (mp_dir) {
+    nfsfattr *fattr = &mp_dir->am_fattr;
+    am_fattr3 *fattr3 = &post_op_dir->am_post_op_attr_u.attributes;
+    am_wcc_attr *wcc_attr = &pre_op_dir->am_pre_op_attr_u.attributes;
+
+    pre_op_dir->attributes_follow = 1;
+    fattr_to_wcc_attr(fattr, wcc_attr);
+    post_op_dir->attributes_follow = 1;
+    fattr_to_fattr3(fattr, fattr3);
+  }
+
+  if (!mp_file || !mp_dir)
+    result.status = nfs_error(ESTALE);
+  else
+    result.status = nfs_error(EROFS);
+
+  return &result;
+}
+
+am_READDIR3res *
+am_nfs3_readdir_3_svc(am_READDIR3args *argp, struct svc_req *rqstp)
+{
+  static am_READDIR3res  result;
+  static am_entry3 entries[MAX_READDIR_ENTRIES];
+  am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->dir;
+  am_cookie3 cookie = argp->cookie;
+  am_cookieverf3 cookieverf;
+  am_count3 count = argp->count;
+  am_post_op_attr *post_op_dir;
+  am_node *mp;
+  int retry;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "readdir_3:");
+
+  memcpy(&cookieverf, &argp->cookieverf, sizeof(am_cookieverf3));
+
+  mp = fh3_to_mp3(dir, &retry, VLOOK_CREATE);
+  if (mp == NULL) {
+    if (retry < 0) {
+      amd_stats.d_drops++;
+      return 0;
+    }
+    post_op_dir = &result.res_u.fail.dir_attributes;
+    post_op_dir->attributes_follow = 0;
+    result.status = nfs_error(retry);
+  } else {
+    am_dirlist3 *list = &result.res_u.ok.reply;
+    am_nfsstat3 status;
+
+    if (amuDebug(D_TRACE))
+      plog(XLOG_DEBUG, "\treaddir_3(%s)", mp->am_path);
+
+    status = mp->am_al->al_mnt->mf_ops->readdir(mp,
+					(voidp)&cookie, list, entries, count);
+    if (status == 0) {
+      post_op_dir = &result.res_u.ok.dir_attributes;
+      nfsfattr *fattr;
+      am_fattr3 *fattr3;
+
+      fattr = &mp->am_fattr;
+      fattr3 = &post_op_dir->am_post_op_attr_u.attributes;
+      post_op_dir->attributes_follow = 1;
+      fattr_to_fattr3(fattr, fattr3);
+      result.status = AM_NFS3_OK;
+    } else {
+      post_op_dir = &result.res_u.fail.dir_attributes;
+      post_op_dir->attributes_follow = 0;
+      result.status = nfs_error(status);
+    }
+
+    mp->am_stats.s_readdir++;
+  }
+
+  return &result;
+}
+
+am_READDIRPLUS3res *
+am_nfs3_readdirplus_3_svc(am_READDIRPLUS3args *argp, struct svc_req *rqstp)
+{
+  static am_READDIRPLUS3res  result;
+  am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->dir;
+  am_post_op_attr *post_op_dir;
+  nfsfattr *fattr;
+  am_fattr3 *fattr3;
+  am_node *mp;
+  int retry;
+
+  mp = fh3_to_mp3(dir, &retry, VLOOK_CREATE);
+  if (mp == NULL) {
+    if (retry < 0) {
+      amd_stats.d_drops++;
+      return 0;
+    }
+    post_op_dir = &result.res_u.fail.dir_attributes;
+    post_op_dir->attributes_follow = 0;
+    result.status = nfs_error(retry);
+  } else {
+      post_op_dir = &result.res_u.ok.dir_attributes;
+      fattr = &mp->am_fattr;
+      fattr3 = &post_op_dir->am_post_op_attr_u.attributes;
+      post_op_dir->attributes_follow = 1;
+      fattr_to_fattr3(fattr, fattr3);
+      result.status = AM_NFS3ERR_NOTSUPP;
+  }
+
+  return &result;
+}
+
+am_FSSTAT3res *
+am_nfs3_fsstat_3_svc(am_FSSTAT3args *argp, struct svc_req *rqstp)
+{
+  static am_FSSTAT3res  result;
+
+  am_nfs_fh3 *fsroot = (am_nfs_fh3 *) &argp->fsroot;
+  am_post_op_attr *post_op_fsroot;
+  am_node *mp;
+  int retry;
+ 
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "fsstat_3:");
+
+  mp = fh3_to_mp3(fsroot, &retry, VLOOK_CREATE);
+  if (!mp) {
+    if (retry < 0) {
+      amd_stats.d_drops++;
+      return 0;
+    }
+    post_op_fsroot = &result.res_u.fail.obj_attributes;
+    post_op_fsroot->attributes_follow = 0;
+    result.status = nfs_error(retry);
+  } else {
+    am_FSSTAT3resok *ok = &result.res_u.ok;
+    u_int blocks, bfree, bavail;
+    nfsfattr *fattr;
+    am_fattr3 *fattr3;
+    mntent_t mnt;
+
+    if (amuDebug(D_TRACE))
+      plog(XLOG_DEBUG, "\tfsstat_3(%s)", mp->am_path);
+
+    fattr = &mp->am_fattr;
+    post_op_fsroot = &ok->obj_attributes;
+    post_op_fsroot->attributes_follow = 1;
+    fattr3 = &post_op_fsroot->am_post_op_attr_u.attributes;
+    fattr_to_fattr3(fattr, fattr3);
+
+    /*
+     * just return faked up file system information
+     */
+    ok->tbytes = 1024;
+    ok->invarsec = 0;
+
+    /* check if map is browsable and show_statfs_entries=yes  */
+    if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) &&
+	mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) {
+      mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts;
+      if (amu_hasmntopt(&mnt, "browsable")) {
+	count_map_entries(mp, &blocks, &bfree, &bavail);
+      }
+      ok->fbytes = bfree;
+      ok->abytes = bavail;
+      ok->ffiles = bfree;
+      ok->afiles = bavail;
+      ok->tfiles = blocks;
+    } else {
+      ok->fbytes = 0;
+      ok->abytes = 0;
+      ok->ffiles = 0;
+      ok->afiles = 0;
+      ok->tfiles = 0; /* set to 1 if you don't want empty automounts */
+    }
+
+    result.status = AM_NFS3_OK;
+    mp->am_stats.s_statfs++;
+  }
+
+  return &result;
+}
+
+#define FSF3_HOMOGENEOUS 0x0008
+
+am_FSINFO3res *
+am_nfs3_fsinfo_3_svc(am_FSINFO3args *argp, struct svc_req *rqstp)
+{
+  static am_FSINFO3res  result;
+
+  am_nfs_fh3 *fsroot = (am_nfs_fh3 *) &argp->fsroot;
+  am_post_op_attr *post_op_fsroot;
+  am_node *mp;
+  int retry;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "fsinfo_3:");
+
+  mp = fh3_to_mp3(fsroot, &retry, VLOOK_CREATE);
+  if (!mp) {
+    if (retry < 0) {
+      amd_stats.d_drops++;
+      return 0;
+    }
+    post_op_fsroot = &result.res_u.fail.obj_attributes;
+    post_op_fsroot->attributes_follow = 0;
+    result.status = nfs_error(retry);
+  } else {
+    am_FSINFO3resok *ok = &result.res_u.ok;
+    nfsfattr *fattr;
+    am_fattr3 *fattr3;
+
+    if (amuDebug(D_TRACE))
+      plog(XLOG_DEBUG, "\tfsinfo_3(%s)", mp->am_path);
+
+    fattr = &mp->am_fattr;
+    post_op_fsroot = &ok->obj_attributes;
+    post_op_fsroot->attributes_follow = 1;
+    fattr3 = &post_op_fsroot->am_post_op_attr_u.attributes;
+    fattr_to_fattr3(fattr, fattr3);
+
+    /*
+     * just return faked up file system information
+     */
+    ok->rtmax = 0;
+    ok->rtpref = 0;
+    ok->rtmult = 0;
+    ok->wtmax = 0;
+    ok->wtpref = 0;
+    ok->wtmult = 0;
+    ok->dtpref = 1024;
+    ok->maxfilesize = 0;
+    ok->time_delta.seconds = 1;
+    ok->time_delta.nseconds = 0;
+    ok->properties = FSF3_HOMOGENEOUS;
+
+    result.status = AM_NFS3_OK;
+    mp->am_stats.s_fsinfo++;
+  }
+
+  return &result;
+}
+
+am_PATHCONF3res *
+am_nfs3_pathconf_3_svc(am_PATHCONF3args *argp, struct svc_req *rqstp)
+{
+  static am_PATHCONF3res  result;
+
+  am_nfs_fh3 *obj = (am_nfs_fh3 *) &argp->object;
+  am_post_op_attr *post_op_obj;
+  am_node *mp;
+  int retry;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "pathconf_3:");
+
+  mp = fh3_to_mp3(obj, &retry, VLOOK_CREATE);
+  if (!mp) {
+    if (retry < 0) {
+      amd_stats.d_drops++;
+      return 0;
+    }
+    post_op_obj = &result.res_u.fail.obj_attributes;
+    post_op_obj->attributes_follow = 0;
+    result.status = nfs_error(retry);
+  } else {
+    am_PATHCONF3resok *ok = &result.res_u.ok;
+    nfsfattr *fattr;
+    am_fattr3 *fattr3;
+
+    if (amuDebug(D_TRACE))
+      plog(XLOG_DEBUG, "\tpathconf_3(%s)", mp->am_path);
+
+    fattr = &mp->am_fattr;
+    post_op_obj = &ok->obj_attributes;
+    post_op_obj->attributes_follow = 1;
+    fattr3 = &post_op_obj->am_post_op_attr_u.attributes;
+    fattr_to_fattr3(fattr, fattr3);
+
+    ok->linkmax = 0;
+    ok->name_max = NAME_MAX;
+    ok->no_trunc = 1;
+    ok->chown_restricted = 1;
+    ok->case_insensitive = 0;
+    ok->case_preserving = 1;
+
+    result.status = AM_NFS3_OK;
+    mp->am_stats.s_pathconf++;
+  }
+
+  return &result;
+}
+
+am_COMMIT3res *
+am_nfs3_commit_3_svc(am_COMMIT3args *argp, struct svc_req *rqstp)
+{
+  static am_COMMIT3res  result;
+
+  am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file;
+  am_pre_op_attr *pre_op_file = &result.res_u.fail.file_wcc.before;
+  am_post_op_attr *post_op_file = &result.res_u.fail.file_wcc.after;
+
+  if (amuDebug(D_TRACE))
+    plog(XLOG_DEBUG, "commit_3:");
+
+  result.status = return_estale_or_rofs(file, pre_op_file, post_op_file);
+
+  return &result;
+}
+#endif /* HAVE_FS_NFS3 */

Modified: trunk/contrib/amd/amd/ops_TEMPLATE.c
===================================================================
--- trunk/contrib/amd/amd/ops_TEMPLATE.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_TEMPLATE.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -64,7 +60,7 @@
 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 int foofs_readdir(am_node *mp, void cookie, voidp dp, voidp 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);
@@ -220,7 +216,7 @@
  * If OK, fills in ep with chain of directory entries.
  */
 static int
-foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
+foofs_readdir(am_node *mp, void cookie, voidp dp, voidp ep, u_int count)
 {
   int error = 0;
 

Modified: trunk/contrib/amd/amd/ops_cachefs.c
===================================================================
--- trunk/contrib/amd/amd/ops_cachefs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_cachefs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -99,7 +95,7 @@
   dlog("CACHEFS: using cache directory \"%s\"", fo->opt_cachedir);
 
   /* determine magic cookie to put in mtab */
-  return strdup(fo->opt_cachedir);
+  return xstrdup(fo->opt_cachedir);
 }
 
 
@@ -114,7 +110,7 @@
    * Save cache directory name
    */
   if (!mf->mf_private) {
-    mf->mf_private = (voidp) strdup(mf->mf_fo->opt_cachedir);
+    mf->mf_private = (voidp) xstrdup(mf->mf_fo->opt_cachedir);
     mf->mf_prfree = (void (*)(voidp)) free;
   }
 

Modified: trunk/contrib/amd/amd/ops_cdfs.c
===================================================================
--- trunk/contrib/amd/amd/ops_cdfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_cdfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -97,7 +93,7 @@
   /*
    * Determine magic cookie to put in mtab
    */
-  return strdup(fo->opt_dev);
+  return xstrdup(fo->opt_dev);
 }
 
 
@@ -148,6 +144,7 @@
   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 (amu_hasmntopt(&mnt, MNTTAB_OPT_NORRIP))
     cdfs_flags |= MNT2_CDFS_OPT_NORRIP;
@@ -157,11 +154,27 @@
   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 (amu_hasmntopt(&mnt, MNTTAB_OPT_EXTATT))
     cdfs_flags |= MNT2_CDFS_OPT_EXTATT;
 #endif /* defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) */
 
+#if defined(MNT2_CDFS_OPT_NOCASETRANS) && defined(MNTTAB_OPT_NOCASETRANS)
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOCASETRANS))
+    cdfs_flags |= MNT2_CDFS_OPT_NOCASETRANS;
+#endif /* defined(MNT2_CDFS_OPT_NOCASETRANS) && defined(MNTTAB_OPT_NOCASETRANS) */
+
+#if defined(MNT2_CDFS_OPT_NOJOLIET) && defined(MNTTAB_OPT_NOJOLIET)
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOJOLIET))
+    cdfs_flags |= MNT2_CDFS_OPT_NOJOLIET;
+#endif /* defined(MNT2_CDFS_OPT_NOJOLIET) && defined(MNTTAB_OPT_NOJOLIET) */
+
+#if defined(MNT2_CDFS_OPT_RRCASEINS) && defined(MNTTAB_OPT_RRCASEINS)
+  if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRCASEINS))
+    cdfs_flags |= MNT2_CDFS_OPT_RRCASEINS;
+#endif /* defined(MNT2_CDFS_OPT_RRCASEINS) && defined(MNTTAB_OPT_RRCASEINS) */
+
   genflags = compute_mount_flags(&mnt);
 #ifdef HAVE_FS_AUTOFS
   if (on_autofs)

Modified: trunk/contrib/amd/amd/ops_efs.c
===================================================================
--- trunk/contrib/amd/amd/ops_efs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_efs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -98,7 +94,7 @@
   /*
    * Determine magic cookie to put in mtab
    */
-  return strdup(fo->opt_dev);
+  return xstrdup(fo->opt_dev);
 }
 
 
@@ -137,6 +133,9 @@
 #ifdef HAVE_EFS_ARGS_T_FSPEC
   efs_args.fspec = fs_name;
 #endif /* HAVE_EFS_ARGS_T_FSPEC */
+#if defined(HAVE_EFS_ARGS_T_VERSION) && defined(EFS_MNT_VERSION)
+  efs_args.version = EFS_MNT_VERSION;
+#endif /* HAVE_EFS_ARGS_T_VERSION && EFS_MNT_VERSION */
 
   /*
    * Call generic mount routine

Modified: trunk/contrib/amd/amd/ops_lofs.c
===================================================================
--- trunk/contrib/amd/amd/ops_lofs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_lofs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -97,7 +93,7 @@
   /*
    * Determine magic cookie to put in mtab
    */
-  return strdup(fo->opt_rfs);
+  return xstrdup(fo->opt_rfs);
 }
 
 

Modified: trunk/contrib/amd/amd/ops_mfs.c
===================================================================
--- trunk/contrib/amd/amd/ops_mfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_mfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/amd/ops_nfs.c
===================================================================
--- trunk/contrib/amd/amd/ops_nfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_nfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -113,6 +109,13 @@
 static int webnfs_lookup(fh_cache *fp, fwd_fun f, wchan_t wchan);
 static int fh_id = 0;
 
+/*
+ * clamp the filehandle version to 3, so that we can fail back to nfsv3
+ * since nfsv4 does not have file handles
+ */
+#define SET_FH_VERSION(fs) \
+    (fs)->fs_version > NFS_VERSION3 ? NFS_VERSION3 : (fs)->fs_version;
+
 /* globals */
 AUTH *nfs_auth;
 qelem fh_head = {&fh_head, &fh_head};
@@ -145,7 +148,7 @@
 static fh_cache *
 find_nfs_fhandle_cache(opaque_t arg, int done)
 {
-  fh_cache *fp, *fp2 = 0;
+  fh_cache *fp, *fp2 = NULL;
   int id = (long) arg;		/* for 64-bit archs */
 
   ITER(fp, fh_cache, &fh_head) {
@@ -201,6 +204,10 @@
     memmove(fp->fh_nfs_handle.v3.am_fh3_data,
 	    res3.mountres3_u.mountinfo.fhandle.fhandle3_val,
 	    fp->fh_nfs_handle.v3.am_fh3_length);
+
+    XFREE(res3.mountres3_u.mountinfo.fhandle.fhandle3_val);
+    if (res3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val)
+      XFREE(res3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val);
   } else {
 #endif /* HAVE_FS_NFS3 */
     memset(&res, 0, sizeof(res));
@@ -326,8 +333,7 @@
     dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
     free_srvr(fp->fh_fs);
   }
-  if (fp->fh_path)
-    XFREE(fp->fh_path);
+  XFREE(fp->fh_path);
   XFREE(fp);
 }
 
@@ -338,7 +344,7 @@
 static int
 prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *mf)
 {
-  fh_cache *fp, *fp_save = 0;
+  fh_cache *fp, *fp_save = NULL;
   int error;
   int reuse_id = FALSE;
 
@@ -466,11 +472,11 @@
     fp->fh_sin = *fs->fs_ip;
     if (!(mf->mf_flags & MFF_WEBNFS))
 	fp->fh_sin.sin_port = 0;
-    fp->fh_nfs_version = fs->fs_version;
+    fp->fh_nfs_version = SET_FH_VERSION(fs);
   }
 
   fp->fh_fs = dup_srvr(fs);
-  fp->fh_path = strdup(path);
+  fp->fh_path = xstrdup(path);
 
   if (mf->mf_flags & MFF_WEBNFS)
     error = webnfs_lookup(fp, got_nfs_fh_webnfs, get_mntfs_wchan(mf));
@@ -544,7 +550,9 @@
     if (error)
       return error;
     fp->fh_sin.sin_port = mountd_port;
-  }
+    dlog("%s: New %d mountd port", __func__, fp->fh_sin.sin_port);
+  } else
+    dlog("%s: Already had %d mountd port", __func__, fp->fh_sin.sin_port);
 
   /* find the right version of the mount protocol */
 #ifdef HAVE_FS_NFS3
@@ -605,7 +613,7 @@
   nfsdiropargs args;
 #ifdef HAVE_FS_NFS3
   am_LOOKUP3args args3;
-#endif
+#endif /* HAVE_FS_NFS3 */
   char *wnfs_path;
   size_t l;
 
@@ -724,6 +732,17 @@
   am_nfs_handle_t fhs;
   char *colon;
 
+#ifdef NO_FALLBACK
+  /*
+   * We don't need file handles for NFS version 4, but we can fall back to
+   * version 3, so we allocate anyway
+   */
+#ifdef HAVE_FS_NFS4
+  if (mf->mf_server->fs_version == NFS_VERSION4)
+    return 0;
+#endif /* HAVE_FS_NFS4 */
+#endif /* NO_FALLBACK */
+
   if (mf->mf_private) {
     if (mf->mf_flags & MFF_NFS_SCALEDOWN) {
       fserver *fs;
@@ -732,6 +751,9 @@
       mf->mf_ops->umounted(mf);
 
       mf->mf_prfree(mf->mf_private);
+      mf->mf_private = NULL;
+      mf->mf_prfree = NULL;
+
       fs = mf->mf_ops->ffserver(mf);
       free_srvr(mf->mf_server);
       mf->mf_server = fs;
@@ -769,7 +791,11 @@
   int retry;
   int proto = AMU_TYPE_NONE;
   mntent_t mnt;
+  void *argsp;
   nfs_args_t nfs_args;
+#ifdef HAVE_FS_NFS4
+  nfs4_args_t nfs4_args;
+#endif /* HAVE_FS_NFS4 */
 
   /*
    * Extract HOST name to give to kernel.
@@ -829,10 +855,7 @@
   /*
    * Set mount types accordingly
    */
-#ifndef HAVE_FS_NFS3
-  type = MOUNT_TYPE_NFS;
-  mnt.mnt_type = MNTTAB_TYPE_NFS;
-#else /* HAVE_FS_NFS3 */
+#ifdef HAVE_FS_NFS3
   if (nfs_version == NFS_VERSION3) {
     type = MOUNT_TYPE_NFS3;
     /*
@@ -843,16 +866,25 @@
      * So on those systems, set it to "nfs".
      * Note: MNTTAB_OPT_VERS is always set for NFS3 (see am_compat.h).
      */
+    argsp = &nfs_args;
 # if defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE)
     mnt.mnt_type = MNTTAB_TYPE_NFS;
 # else /* defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE) */
     mnt.mnt_type = MNTTAB_TYPE_NFS3;
 # endif /* defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE) */
-  } else {
+# ifdef HAVE_FS_NFS4
+  } else if (nfs_version == NFS_VERSION4) {
+    argsp = &nfs4_args;
+    type = MOUNT_TYPE_NFS4;
+    mnt.mnt_type = MNTTAB_TYPE_NFS4;
+# endif /* HAVE_FS_NFS4 */
+  } else
+#endif /* HAVE_FS_NFS3 */
+  {
+    argsp = &nfs_args;
     type = MOUNT_TYPE_NFS;
     mnt.mnt_type = MNTTAB_TYPE_NFS;
   }
-#endif /* HAVE_FS_NFS3 */
   plog(XLOG_INFO, "mount_nfs_fh: NFS version %d", (int) nfs_version);
   plog(XLOG_INFO, "mount_nfs_fh: using NFS transport %s", nfs_proto);
 
@@ -866,32 +898,44 @@
     genflags |= autofs_compute_mount_flags(&mnt);
 #endif /* HAVE_FS_AUTOFS */
 
-  /* setup the many fields and flags within nfs_args */
-  compute_nfs_args(&nfs_args,
-		   &mnt,
-		   genflags,
-		   NULL,	/* struct netconfig *nfsncp */
-		   fs->fs_ip,
-		   nfs_version,
-		   nfs_proto,
-		   fhp,
-		   host,
-		   fs_name);
+   /* setup the many fields and flags within nfs_args */
+   compute_nfs_args(argsp,
+		    &mnt,
+		    genflags,
+		    NULL,	/* struct netconfig *nfsncp */
+		    fs->fs_ip,
+		    nfs_version,
+		    nfs_proto,
+		    fhp,
+		    host,
+		    fs_name);
 
   /* finally call the mounting function */
   if (amuDebug(D_TRACE)) {
-    print_nfs_args(&nfs_args, nfs_version);
+    print_nfs_args(argsp, nfs_version);
     plog(XLOG_DEBUG, "Generic mount flags 0x%x used for NFS mount", genflags);
   }
-  error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type,
-		    nfs_version, nfs_proto, mnttab_file_name, on_autofs);
-  XFREE(xopts);
+  error = mount_fs(&mnt, genflags, argsp, retry, type,
+		   nfs_version, nfs_proto, mnttab_file_name, on_autofs);
+  XFREE(mnt.mnt_opts);
+  discard_nfs_args(argsp, nfs_version);
 
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-  free_knetconfig(nfs_args.knconf);
-  if (nfs_args.addr)
-    XFREE(nfs_args.addr);	/* allocated in compute_nfs_args() */
-#endif /* HAVE_TRANSPORT_TYPE_TLI */
+#ifdef HAVE_FS_NFS4
+# ifndef NO_FALLBACK
+  /*
+   * If we are using a v4 file handle, we try a v3 if we get back:
+   * 	ENOENT: NFS v4 has a different export list than v3
+   * 	EPERM: Kernels <= 2.6.18 return that, instead of ENOENT
+   */
+  if ((error == ENOENT || error == EPERM) && nfs_version == NFS_VERSION4) {
+    plog(XLOG_DEBUG, "Could not find NFS 4 mount, trying again with NFS 3");
+    fs->fs_version = NFS_VERSION3;
+    error = mount_nfs_fh(fhp, mntdir, fs_name, mf);
+    if (error)
+      fs->fs_version = NFS_VERSION4;
+  }
+# endif /* NO_FALLBACK */
+#endif /* HAVE_FS_NFS4 */
 
   return error;
 }
@@ -903,11 +947,16 @@
   int error = 0;
   mntent_t mnt;
 
-  if (!mf->mf_private) {
+  if (!mf->mf_private && mf->mf_server->fs_version != 4) {
     plog(XLOG_ERROR, "Missing filehandle for %s", mf->mf_info);
     return EINVAL;
   }
 
+  if (mf->mf_mopts == NULL) {
+    plog(XLOG_ERROR, "Missing mount options for %s", mf->mf_info);
+    return EINVAL;
+  }
+
   mnt.mnt_opts = mf->mf_mopts;
   if (amu_hasmntopt(&mnt, "softlookup") ||
       (amu_hasmntopt(&mnt, "soft") && !amu_hasmntopt(&mnt, "nosoftlookup")))
@@ -932,6 +981,7 @@
 {
   int unmount_flags, new_unmount_flags, error;
 
+  dlog("attempting nfs umount");
   unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
   error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 
@@ -1031,12 +1081,12 @@
     f.fh_path = path;
     f.fh_sin = *fs->fs_ip;
     f.fh_sin.sin_port = (u_short) 0;
-    f.fh_nfs_version = fs->fs_version;
+    f.fh_nfs_version = SET_FH_VERSION(fs);
     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, mf);
-    call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun *) 0, (wchan_t) 0);
+    prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) NULL, mf);
+    call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun *) NULL, (wchan_t) NULL);
     *colon = ':';
   }
 }

Modified: trunk/contrib/amd/amd/ops_nfs3.c
===================================================================
--- trunk/contrib/amd/amd/ops_nfs3.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_nfs3.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/amd/ops_nullfs.c
===================================================================
--- trunk/contrib/amd/amd/ops_nullfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_nullfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/amd/ops_pcfs.c
===================================================================
--- trunk/contrib/amd/amd/ops_pcfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_pcfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -97,7 +93,7 @@
   /*
    * Determine magic cookie to put in mtab
    */
-  return strdup(fo->opt_dev);
+  return xstrdup(fo->opt_dev);
 }
 
 

Modified: trunk/contrib/amd/amd/ops_tfs.c
===================================================================
--- trunk/contrib/amd/amd/ops_tfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_tfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/amd/ops_tmpfs.c
===================================================================
--- trunk/contrib/amd/amd/ops_tmpfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_tmpfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -51,4 +47,146 @@
 #include <am_defs.h>
 #include <amd.h>
 
-/* FEEL FREE TO IMPLEMENT THIS... :-) */
+/* forward declarations */
+static char *tmpfs_match(am_opts *fo);
+static int tmpfs_mount(am_node *am, mntfs *mf);
+static int tmpfs_umount(am_node *am, mntfs *mf);
+
+/*
+ * Ops structure
+ */
+am_ops tmpfs_ops =
+{
+  "tmpfs",
+  tmpfs_match,
+  0,				/* tmpfs_init */
+  tmpfs_mount,
+  tmpfs_umount,
+  amfs_error_lookup_child,
+  amfs_error_mount_child,
+  amfs_error_readdir,
+  0,				/* tmpfs_readlink */
+  0,				/* tmpfs_mounted */
+  0,				/* tmpfs_umounted */
+  amfs_generic_find_srvr,
+  0,				/* tmpfs_get_wchan */
+  FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */
+#if defined(HAVE_FS_AUTOFS) && defined(AUTOFS_TMPFS_FS_FLAGS)
+  AUTOFS_TMPFS_FS_FLAGS,
+#endif /* HAVE_FS_AUTOFS */
+};
+
+
+/*
+ * EFS needs local filesystem and device.
+ */
+static char *
+tmpfs_match(am_opts *fo)
+{
+
+  if (!fo->opt_dev) {
+    plog(XLOG_USER, "tmpfs: no device specified");
+    return 0;
+  }
+
+  dlog("EFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
+
+  /*
+   * Determine magic cookie to put in mtab
+   */
+  return xstrdup(fo->opt_dev);
+}
+
+
+static int
+mount_tmpfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
+{
+  tmpfs_args_t tmpfs_args;
+  mntent_t mnt;
+  int flags;
+  const char *p;
+
+  /*
+   * Figure out the name of the file system type.
+   */
+  MTYPE_TYPE type = MOUNT_TYPE_TMPFS;
+
+  p = NULL;
+  memset((voidp) &tmpfs_args, 0, sizeof(tmpfs_args)); /* Paranoid */
+
+  /*
+   * Fill in the mount structure
+   */
+  memset((voidp) &mnt, 0, sizeof(mnt));
+  mnt.mnt_dir = mntdir;
+  mnt.mnt_fsname = fs_name;
+  mnt.mnt_type = MNTTAB_TYPE_TMPFS;
+  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 */
+
+#if defined(HAVE_TMPFS_ARGS_T_TA_VERSION) && defined(TMPFS_ARGS_VERSION)
+  tmpfs_args.ta_version = TMPFS_ARGS_VERSION;
+#endif /* HAVE_TMPFS_ARGS_T_TA_VERSION && TMPFS_ARGS_VERSION */
+#ifdef HAVE_TMPFS_ARGS_T_TA_NODES_MAX
+  if ((p = amu_hasmntopt(&mnt, "nodes")) == NULL)
+	p = "1000000";
+  tmpfs_args.ta_nodes_max = atoi(p);
+#endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */
+#ifdef HAVE_TMPFS_ARGS_T_TA_SIZE_MAX
+  if ((p = amu_hasmntopt(&mnt, "size")) == NULL)
+	p = "10000000";
+  tmpfs_args.ta_size_max = atoi(p);
+#endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */
+#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_UID
+  if ((p = amu_hasmntopt(&mnt, "uid")) == NULL)
+	p = "0";
+  tmpfs_args.ta_root_uid = atoi(p);
+#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_UID */
+#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_GID
+  if ((p = amu_hasmntopt(&mnt, "gid")) == NULL)
+	p = "0";
+  tmpfs_args.ta_root_gid = atoi(p);
+#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_GID */
+#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_MODE
+  if ((p = amu_hasmntopt(&mnt, "mode")) == NULL)
+	p = "01777";
+  tmpfs_args.ta_root_mode = strtol(p, NULL, 8);
+#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_MODE */
+
+  /*
+   * Call generic mount routine
+   */
+  return mount_fs(&mnt, flags, (caddr_t) &tmpfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
+}
+
+
+static int
+tmpfs_mount(am_node *am, mntfs *mf)
+{
+  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
+  int error;
+
+  error = mount_tmpfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
+  if (error) {
+    errno = error;
+    plog(XLOG_ERROR, "mount_tmpfs: %m");
+    return error;
+  }
+
+  return 0;
+}
+
+
+static int
+tmpfs_umount(am_node *am, mntfs *mf)
+{
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
+}
+

Modified: trunk/contrib/amd/amd/ops_ufs.c
===================================================================
--- trunk/contrib/amd/amd/ops_ufs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_ufs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -61,7 +57,11 @@
  */
 am_ops ufs_ops =
 {
+#ifndef __NetBSD__
   "ufs",
+#else
+  "ffs",
+#endif
   ufs_match,
   0,				/* ufs_init */
   ufs_mount,
@@ -98,7 +98,7 @@
   /*
    * Determine magic cookie to put in mtab
    */
-  return strdup(fo->opt_dev);
+  return xstrdup(fo->opt_dev);
 }
 
 

Modified: trunk/contrib/amd/amd/ops_umapfs.c
===================================================================
--- trunk/contrib/amd/amd/ops_umapfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_umapfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/amd/ops_unionfs.c
===================================================================
--- trunk/contrib/amd/amd/ops_unionfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_unionfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/amd/ops_xfs.c
===================================================================
--- trunk/contrib/amd/amd/ops_xfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/ops_xfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -98,7 +94,7 @@
   /*
    * Determine magic cookie to put in mtab
    */
-  return strdup(fo->opt_dev);
+  return xstrdup(fo->opt_dev);
 }
 
 

Modified: trunk/contrib/amd/amd/opts.c
===================================================================
--- trunk/contrib/amd/amd/opts.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/opts.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -539,7 +535,7 @@
   char *f;
   int ret = 0;
 
-  o = old_o = strdup(opts);
+  o = old_o = xstrdup(opts);
 
   /*
    * For each user-specified option
@@ -570,7 +566,7 @@
       /* null-terminate the argument  */
       *arg++ = '\0';
       fx = strchr(arg, ')');
-      if (!arg || fx == arg) {
+      if (fx == NULL || fx == arg) {
 	plog(XLOG_USER, "key %s: Malformed function in \"%s\"", mapkey, f);
 	continue;
       }
@@ -606,8 +602,10 @@
       }
     } else {
       if (eq[1] == '\0' || eq == f) {
-	/* misformed selector */
+#ifdef notdef
+	/* We allow empty assignments */
 	plog(XLOG_USER, "key %s: Bad selector \"%s\"", mapkey, f);
+#endif
 	continue;
       }
     }
@@ -968,9 +966,7 @@
 static void
 free_op(opt_apply *p, int b)
 {
-  if (*p->opt) {
-    XFREE(*p->opt);
-  }
+  XFREE(*p->opt);
 }
 
 
@@ -1016,7 +1012,7 @@
       /* assert(*f == 0 || *f == '/'); */
 
     } while (*f);
-    *t = 0;			/* derived from fix by Steven Glassman */
+    *t = '\0';			/* derived from fix by Steven Glassman */
   }
 }
 
@@ -1238,8 +1234,14 @@
 	    }
 
 	    if (BUFSPACE(ep, vlen+1)) {
-	      xstrlcpy(ep, vptr, vlen+1);
+	      /*
+	       * Don't call xstrlcpy() to truncate a string here.  It causes
+	       * spurious xstrlcpy() syslog() errors.  Use memcpy() and
+	       * explicitly terminate the string.
+	       */
+	      memcpy(ep, vptr, vlen+1);
 	      ep += vlen;
+	      *ep = '\0';
 	    } else {
 	      plog(XLOG_ERROR, EXPAND_ERROR, opt);
 	      goto out;
@@ -1292,7 +1294,7 @@
    * Handle common case - no expansion
    */
   if (cp == opt) {
-    opt = strdup(cp);
+    opt = xstrdup(cp);
   } else {
     /*
      * Finish off the expansion
@@ -1308,7 +1310,7 @@
     /*
      * Save the expansion
      */
-    opt = strdup(expbuf);
+    opt = xstrdup(expbuf);
   }
 
   normalize_slash(opt);
@@ -1372,7 +1374,46 @@
   apply_opts(free_op, to_free, FALSE);
 }
 
+am_opts *
+copy_opts(am_opts *old)
+{
+  am_opts *newopts;
+  newopts = CALLOC(struct am_opts);
 
+#define _AM_OPT_COPY(field) do { \
+    if (old->field) \
+      newopts->field = xstrdup(old->field); \
+  } while (0)
+
+  _AM_OPT_COPY(fs_glob);
+  _AM_OPT_COPY(fs_local);
+  _AM_OPT_COPY(fs_mtab);
+  _AM_OPT_COPY(opt_dev);
+  _AM_OPT_COPY(opt_delay);
+  _AM_OPT_COPY(opt_dir);
+  _AM_OPT_COPY(opt_fs);
+  _AM_OPT_COPY(opt_group);
+  _AM_OPT_COPY(opt_mount);
+  _AM_OPT_COPY(opt_opts);
+  _AM_OPT_COPY(opt_remopts);
+  _AM_OPT_COPY(opt_pref);
+  _AM_OPT_COPY(opt_cache);
+  _AM_OPT_COPY(opt_rfs);
+  _AM_OPT_COPY(opt_rhost);
+  _AM_OPT_COPY(opt_sublink);
+  _AM_OPT_COPY(opt_type);
+  _AM_OPT_COPY(opt_mount_type);
+  _AM_OPT_COPY(opt_unmount);
+  _AM_OPT_COPY(opt_umount);
+  _AM_OPT_COPY(opt_user);
+  _AM_OPT_COPY(opt_maptype);
+  _AM_OPT_COPY(opt_cachedir);
+  _AM_OPT_COPY(opt_addopts);
+
+  return newopts;
+}
+
+
 /*
  * Expand selectors (variables that cannot be assigned to or overridden)
  */

Modified: trunk/contrib/amd/amd/readdir.c
===================================================================
--- trunk/contrib/amd/amd/readdir.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/readdir.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -42,6 +38,7 @@
  */
 
 
+#include <stdint.h>
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif /* HAVE_CONFIG_H */
@@ -63,6 +60,7 @@
 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);
 
+static const u_int dotdotcookie = DOT_DOT_COOKIE;
 
 /****************************************************************************
  *** FUNCTIONS                                                             ***
@@ -108,14 +106,14 @@
     plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)");
     return retval;
   }
-  mf = mp->am_mnt;
+  mf = mp->am_al->al_mnt;
   if (!mf) {
-    plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt is (NULL)");
+    plog(XLOG_DEBUG, "make_entry_chain: mp->am_al->al_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)");
+    plog(XLOG_DEBUG, "make_entry_chain: mp->am_al->al_mnt->mf_private is (NULL)");
     return retval;
   }
 
@@ -170,7 +168,7 @@
 	/* 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;
+	  chain[num_entries - 1].ne_nextentry = NULL;
 	  retval = &chain[0];
 	}
 	return retval;
@@ -190,7 +188,7 @@
 
   /* terminate chain */
   if (num_entries > 0) {
-    chain[num_entries - 1].ne_nextentry = 0;
+    chain[num_entries - 1].ne_nextentry = NULL;
     retval = &chain[0];
   }
 
@@ -203,7 +201,7 @@
 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;
+  u_int gen = *(u_int *) (uintptr_t) cookie;
   int chain_length, i;
   static nfsentry *te, *te_next;
   static int j;
@@ -223,7 +221,7 @@
      * to be returned in a single packet.  If it isn't (which would be
      * fairly unbelievable) then tough.
      */
-    dlog("amfs_readdir_browsable: default search");
+    dlog("%s: default search", __func__);
     /*
      * Check for enough room.  This is extremely approximate but is more
      * than enough space.  Really need 2 times:
@@ -262,8 +260,8 @@
       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;
+    ep[1].ne_nextentry = NULL;
+    (void)memcpy(ep[1].ne_cookie, &dotdotcookie, sizeof(dotdotcookie));
 
     /*
      * If map is browsable, call a function make_entry_chain() to construct
@@ -308,12 +306,12 @@
     return 0;
   } /* end of "if (gen == 0)" statement */
 
-  dlog("amfs_readdir_browsable: real child");
+  dlog("%s: real child", __func__);
 
   if (gen == DOT_DOT_COOKIE) {
-    dlog("amfs_readdir_browsable: End of readdir in %s", mp->am_path);
+    dlog("%s: End of readdir in %s", __func__, mp->am_path);
     dp->dl_eof = TRUE;
-    dp->dl_entries = 0;
+    dp->dl_entries = NULL;
     return 0;
   }
 
@@ -327,7 +325,7 @@
 
   te = te_next;			/* reset 'te' from last saved te_next */
   if (!te) {			/* another indicator of end of readdir */
-    dp->dl_entries = 0;
+    dp->dl_entries = NULL;
     return 0;
   }
   /*
@@ -360,29 +358,14 @@
   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)
+static int
+amfs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count)
 {
-  u_int gen = *(u_int *) cookie;
+  u_int gen = *(u_int *) (uintptr_t) 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) {
     /*
@@ -393,7 +376,7 @@
      * to be returned in a single packet.  If it isn't (which would be
      * fairly unbelievable) then tough.
      */
-    dlog("amfs_generic_readdir: default search");
+    dlog("%s: default search", __func__);
     /*
      * Check for enough room.  This is extremely approximate but is more
      * than enough space.  Really need 2 times:
@@ -402,8 +385,11 @@
      *      4byte name length
      *      4byte name
      * plus the dirlist structure */
-    if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))))
+#define NEEDROOM (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp)))
+    if (count < NEEDROOM) {
+      dlog("%s: not enough room %u < %zu", __func__, count, NEEDROOM);
       return EINVAL;
+    }
 
     xp = next_nonerror_node(mp->am_child);
     dp->dl_entries = ep;
@@ -420,8 +406,9 @@
     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);
+    ep[1].ne_nextentry = NULL;
+    (void)memcpy(ep[1].ne_cookie, (xp ? &xp->am_gen : &dotdotcookie),
+      sizeof(dotdotcookie));
 
     if (!xp)
       dp->dl_eof = TRUE;	/* by default assume readdir done */
@@ -435,12 +422,12 @@
     }
     return 0;
   }
-  dlog("amfs_generic_readdir: real child");
+  dlog("%s: real child", __func__);
 
   if (gen == DOT_DOT_COOKIE) {
-    dlog("amfs_generic_readdir: End of readdir in %s", mp->am_path);
+    dlog("%s: End of readdir in %s", __func__, mp->am_path);
     dp->dl_eof = TRUE;
-    dp->dl_entries = 0;
+    dp->dl_entries = NULL;
     if (amuDebug(D_READDIR))
       plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n");
     return 0;
@@ -483,7 +470,7 @@
       }
     } while (todo > 0);
 
-    ep->ne_nextentry = 0;
+    ep->ne_nextentry = NULL;
 
     if (amuDebug(D_READDIR)) {
       nfsentry *ne;
@@ -496,3 +483,460 @@
   }
   return ESTALE;
 }
+
+/*
+ * Search a chain for an entry with some name.
+ */
+static int
+key_already_in_chain3(char *keyname, const am_entry3 *chain)
+{
+  const am_entry3 *tmpchain = chain;
+
+  while (tmpchain) {
+    if (keyname && tmpchain->name && STREQ(keyname, tmpchain->name))
+        return 1;
+    tmpchain = tmpchain->nextentry;
+  }
+
+  return 0;
+}
+
+/*
+ * Create a chain of entries which are not linked.
+ */
+static am_entry3 *
+make_entry_chain3(am_node *mp, const am_entry3 *current_chain, int fully_browsable)
+{
+  static uint64 last_cookie = (uint64) 2;	/* monotonically increasing */
+  static am_entry3 chain[MAX_CHAIN];
+  static int max_entries = MAX_CHAIN;
+  char *key;
+  int num_entries = 0, i;
+  u_int preflen = 0;
+  am_entry3 *retval = (am_entry3 *) NULL;
+  mntfs *mf;
+  mnt_map *mmp;
+
+  if (!mp) {
+    plog(XLOG_DEBUG, "make_entry_chain3: mp is (NULL)");
+    return retval;
+  }
+  mf = mp->am_al->al_mnt;
+  if (!mf) {
+    plog(XLOG_DEBUG, "make_entry_chain3: mp->am_al->al_mnt is (NULL)");
+    return retval;
+  }
+  mmp = (mnt_map *) mf->mf_private;
+  if (!mmp) {
+    plog(XLOG_DEBUG, "make_entry_chain3: mp->am_al->al_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_chain3(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_chain3: no more space in chain");
+	if (num_entries > 0) {
+	  chain[num_entries - 1].nextentry = NULL;
+	  retval = &chain[0];
+	}
+	return retval;
+      }
+
+      /* we have space.  put entry in next cell */
+      ++last_cookie;
+      chain[num_entries].fileid = last_cookie;
+      chain[num_entries].cookie = last_cookie;
+      chain[num_entries].name = key;
+      if (num_entries < max_entries - 1) {	/* link to next one */
+	chain[num_entries].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].nextentry = NULL;
+    retval = &chain[0];
+  }
+
+  return retval;
+}
+
+static size_t needroom3(void)
+{
+  /*
+   * Check for enough room.  This is extremely approximate but should
+   * be enough space.  Really need 2 times:
+   *      (8byte fileid
+   *      8byte cookie
+   *      8byte name pointer
+   *      8byte next entry addres) = sizeof(am_entry3)
+   *      2byte name + 1byte terminator
+   * plus the size of the am_dirlist3 structure */
+  return ((2 * ((sizeof(am_entry3) + sizeof("..") + 1))) + sizeof(am_dirlist3));
+}
+
+/* This one is called only if map is browsable */
+static int
+amfs_readdir3_browsable(am_node *mp, am_cookie3 cookie,
+			am_dirlist3 *dp, am_entry3 *ep, u_int count,
+			int fully_browsable)
+{
+  uint64 gen = *(uint64 *) (uintptr_t) cookie;
+  int chain_length, i;
+  static am_entry3 *te, *te_next;
+  static int j;
+
+  dp->eof = FALSE;		/* assume readdir not done */
+
+  if (amuDebug(D_READDIR))
+    plog(XLOG_DEBUG, "amfs_readdir3_browsable gen=%lu, count=%d", (long unsigned) gen, count);
+
+  if (gen == 0) {
+    size_t needed = needroom3();
+    /*
+     * 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("%s: default search", __func__);
+
+    if (count < needed) {
+      dlog("%s: not enough room %u < %zu", __func__, count, needed);
+      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->entries = ep;
+
+    /* construct "." */
+    ep[0].fileid = mp->am_gen;
+    ep[0].name = ".";
+    ep[0].nextentry = &ep[1];
+    ep[0].cookie = 0;
+
+    /* construct ".." */
+    if (mp->am_parent)
+      ep[1].fileid = mp->am_parent->am_gen;
+    else
+      ep[1].fileid = mp->am_gen;
+
+    ep[1].name = "..";
+    ep[1].nextentry = NULL;
+    ep[1].cookie = dotdotcookie;
+
+    /*
+     * 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_chain3(mp, dp->entries, fully_browsable);
+    if (!te)
+      return 0;
+    if (amuDebug(D_READDIR)) {
+      am_entry3 *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->nextentry;
+      if (!te_next)
+	break;
+    }
+    if (te_next) {
+      am_entry3 *te_saved = te_next->nextentry;
+      te_next->nextentry = NULL; /* terminate "te" chain */
+      te_next = te_saved;	 /* save rest of "te" for next iteration */
+      dp->eof = FALSE;		 /* tell readdir there's more */
+    } else {
+      dp->eof = TRUE;		 /* tell readdir that's it */
+    }
+    ep[1].nextentry = te;	 /* append this chunk of "te" chain */
+    if (amuDebug(D_READDIR)) {
+      am_entry3 *ne;
+      for (j = 0, ne = te; ne; ne = ne->ne_nextentry)
+	plog(XLOG_DEBUG, "gen2 key %4d \"%s\"", j++, ne->name);
+      for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) {
+	plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%lu ck=%lu",
+	     j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie);
+      }
+      plog(XLOG_DEBUG, "EOF is %d", dp->eof);
+    }
+    return 0;
+  } /* end of "if (gen == 0)" statement */
+
+  dlog("%s: real child", __func__);
+
+  if (gen == DOT_DOT_COOKIE) {
+    dlog("%s: End of readdir in %s", __func__, mp->am_path);
+    dp->eof = TRUE;
+    dp->entries = NULL;
+    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->eof = TRUE;
+  dp->entries = ep;
+
+  te = te_next;			/* reset 'te' from last saved te_next */
+  if (!te) {			/* another indicator of end of readdir */
+    dp->entries = NULL;
+    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->nextentry;
+    if (!te_next)
+      break;
+  }
+  if (te_next) {
+    am_entry3 *te_saved = te_next->nextentry;
+    te_next->nextentry = NULL; /* terminate "te" chain */
+    te_next = te_saved;		/* save rest of "te" for next iteration */
+    dp->eof = FALSE;		/* tell readdir there's more */
+  }
+  ep = te;			/* send next chunk of "te" chain */
+  dp->entries = ep;
+  if (amuDebug(D_READDIR)) {
+    am_entry3 *ne;
+    plog(XLOG_DEBUG,
+	 "entries=%p, te_next=%p, eof=%d", dp->entries, te_next, dp->eof);
+    for (ne = te; ne; ne = ne->nextentry)
+      plog(XLOG_DEBUG, "gen3 key %4d \"%s\"", j++, ne->name);
+  }
+  return 0;
+}
+
+static int
+amfs_readdir3(am_node *mp, am_cookie3 cookie,
+	      am_dirlist3 *dp, am_entry3 *ep, u_int count)
+{
+  uint64 gen = *(uint64 *) (uintptr_t) cookie;
+  am_node *xp;
+
+  if (amuDebug(D_READDIR))
+    plog(XLOG_DEBUG, "amfs_readdir3 gen=%lu, count=%d", (long unsigned) gen, count);
+
+  dp->eof = FALSE;		/* assume readdir not done */
+
+  /* when gen is 0, we start reading from the beginning of the directory */
+  if (gen == 0) {
+    size_t needed = needroom3();
+    /*
+     * 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("%s: default search", __func__);
+
+    if (count < needed) {
+      dlog("%s: not enough room %u < %zu", __func__, count, needed);
+      return EINVAL;
+    }
+
+    xp = next_nonerror_node(mp->am_child);
+    dp->entries = ep;
+
+    /* construct "." */
+    ep[0].fileid = mp->am_gen;
+    ep[0].name = ".";
+    ep[0].cookie = 0;
+    ep[0].nextentry = &ep[1];
+
+    /* construct ".." */
+    if (mp->am_parent)
+      ep[1].fileid = mp->am_parent->am_gen;
+    else
+      ep[1].fileid = mp->am_gen;
+    ep[1].name = "..";
+    ep[1].nextentry = NULL;
+    ep[1].cookie = (xp ? xp->am_gen : dotdotcookie);
+
+    if (!xp)
+      dp->eof = TRUE;	/* by default assume readdir done */
+
+    if (amuDebug(D_READDIR)) {
+      am_entry3 *ne;
+      int j;
+      for (j = 0, ne = ep; ne; ne = ne->nextentry) {
+	plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%lu ck=%lu",
+	     j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie);
+      }
+    }
+    return 0;
+  }
+  dlog("%s: real child", __func__);
+
+  if (gen == (uint64) DOT_DOT_COOKIE) {
+    dlog("%s: End of readdir in %s", __func__, mp->am_path);
+    dp->eof = TRUE;
+    dp->entries = NULL;
+    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->entries = ep;
+    do {
+      am_node *xp_next = next_nonerror_node(xp->am_osib);
+
+      if (xp_next) {
+        ep->cookie = xp_next->am_gen;
+      } else {
+	ep->cookie = (uint64) dotdotcookie;
+	dp->eof = TRUE;
+      }
+
+      ep->fileid = xp->am_gen;
+      ep->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->nextentry = ep + 1;
+	ep++;
+	--todo;
+      } else {
+	todo = 0;
+      }
+    } while (todo > 0);
+
+    ep->nextentry = NULL;
+
+    if (amuDebug(D_READDIR)) {
+      am_entry3 *ne;
+      int j;
+      for (j = 0, ne = ep; ne; ne = ne->nextentry) {
+	plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%lu ck=%lu",
+	     j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie);
+      }
+    }
+    return 0;
+  }
+  return ESTALE;
+}
+
+/*
+ * 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, voidp cookie, voidp dp, voidp ep, u_int count)
+{
+  int browsable, full;
+
+  /* check if map is browsable */
+  browsable = 0;
+  if (mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) {
+    mntent_t mnt;
+    mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts;
+    if (amu_hasmntopt(&mnt, "fullybrowsable"))
+      browsable = 2;
+    else if (amu_hasmntopt(&mnt, "browsable"))
+      browsable = 1;
+  }
+  full = (browsable == 2);
+
+  if (nfs_dispatcher == nfs_program_2) {
+    if (browsable)
+      return amfs_readdir_browsable(mp, cookie, dp, ep, count, full);
+    else
+      return amfs_readdir(mp, cookie, dp, ep, count);
+  } else {
+    if (browsable)
+      return amfs_readdir3_browsable(mp, (am_cookie3) (uintptr_t) cookie, dp, ep, count, full);
+    else
+      return amfs_readdir3(mp, (am_cookie3) (uintptr_t) cookie, dp, ep, count);
+  }
+}

Modified: trunk/contrib/amd/amd/restart.c
===================================================================
--- trunk/contrib/amd/amd/restart.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/restart.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -59,13 +55,13 @@
    * Partially fake up an opts structure
    */
   memset(&mo, 0, sizeof(mo));
-  mo.opt_rhost = 0;
-  mo.opt_rfs = 0;
+  mo.opt_rhost = NULL;
+  mo.opt_rfs = NULL;
   cp = strchr(me->mnt_fsname, ':');
   if (cp) {
     *cp = '\0';
-    mo.opt_rhost = strdup(me->mnt_fsname);
-    mo.opt_rfs = strdup(cp + 1);
+    mo.opt_rhost = xstrdup(me->mnt_fsname);
+    mo.opt_rfs = xstrdup(cp + 1);
     *cp = ':';
   } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
     /*
@@ -72,8 +68,8 @@
      * 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("/");
+    mo.opt_rhost = xstrdup(me->mnt_fsname);
+    mo.opt_rfs = xstrdup("/");
     me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
   }
   mo.opt_fs = me->mnt_dir;
@@ -87,7 +83,6 @@
   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
      */
@@ -110,10 +105,8 @@
   /*
    * Clean up mo
    */
-  if (mo.opt_rhost)
-    XFREE(mo.opt_rhost);
-  if (mo.opt_rfs)
-    XFREE(mo.opt_rfs);
+  XFREE(mo.opt_rhost);
+  XFREE(mo.opt_rfs);
 }
 
 
@@ -140,7 +133,7 @@
        mlp;
        mlp = mlp->mnext) {
     mntent_t *me = mlp->mnt;
-    am_ops *fs_ops = 0;
+    am_ops *fs_ops = NULL;
 
     if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
       /*
@@ -203,7 +196,7 @@
        mlp;
        mlp = mlp->mnext) {
     mntent_t *me = mlp->mnt;
-    am_ops *fs_ops = 0;
+    am_ops *fs_ops = NULL;
     char *colon;
     long pid;
     u_short port;
@@ -263,7 +256,8 @@
       if (old_ports[i] == 0) {
 	int soNFS;
 	SVCXPRT *nfsxprt;
-	if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_program_2) != 0) {
+	if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_dispatcher,
+	    get_nfs_dispatcher_version(nfs_dispatcher)) != 0) {
 	  plog(XLOG_WARNING, "Can't bind to port %u", port);
 	  goto give_up;
 	}

Modified: trunk/contrib/amd/amd/rpc_fwd.c
===================================================================
--- trunk/contrib/amd/amd/rpc_fwd.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/rpc_fwd.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -94,7 +90,7 @@
 fwd_alloc(void)
 {
   time_t now = clocktime(NULL);
-  rpc_forward *p = 0, *p2;
+  rpc_forward *p = NULL, *p2;
 
   /*
    * First search for an existing expired one.
@@ -183,7 +179,7 @@
   /*
    * Some things we talk to require a priv port - so make one here
    */
-  if (bind_resv_port(fwd_sock, (u_short *) 0) < 0)
+  if (bind_resv_port(fwd_sock, (u_short *) NULL) < 0)
     plog(XLOG_ERROR, "can't bind privileged port (rpc_fwd)");
 
   if (fcntl(fwd_sock, F_SETFL, FNDELAY) < 0

Modified: trunk/contrib/amd/amd/sched.c
===================================================================
--- trunk/contrib/amd/amd/sched.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/sched.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -262,7 +258,7 @@
 #ifdef HAVE_WAITPID
   while ((pid = waitpid((pid_t) -1,  &w, WNOHANG)) > 0) {
 #else /* not HAVE_WAITPID */
-  while ((pid = wait3( &w, WNOHANG, (struct rusage *) 0)) > 0) {
+  while ((pid = wait3( &w, WNOHANG, (struct rusage *) NULL)) > 0) {
 #endif /* not HAVE_WAITPID */
     pjob *p, *p2;
 

Modified: trunk/contrib/amd/amd/srvr_amfs_auto.c
===================================================================
--- trunk/contrib/amd/amd/srvr_amfs_auto.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/srvr_amfs_auto.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -69,14 +65,14 @@
   if (!fs) {
     fs = ALLOC(struct fserver);
     fs->fs_refc = 0;
-    fs->fs_host = strdup("localhost");
-    fs->fs_ip = 0;
+    fs->fs_host = xstrdup("localhost");
+    fs->fs_ip = NULL;
     fs->fs_cid = 0;
     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;
+    fs->fs_private = NULL;
+    fs->fs_prfree = NULL;
 
     ins_que(&fs->fs_q, &amfs_auto_srvr_list);
 
@@ -135,8 +131,7 @@
     /*
      * Free the net address
      */
-    if (fs->fs_ip)
-      XFREE(fs->fs_ip);
+    XFREE(fs->fs_ip);
 
     /*
      * Free the host name.

Modified: trunk/contrib/amd/amd/srvr_nfs.c
===================================================================
--- trunk/contrib/amd/amd/srvr_nfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amd/srvr_nfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -75,6 +71,7 @@
 typedef struct nfs_private {
   u_short np_mountd;		/* Mount daemon port number */
   char np_mountd_inval;		/* Port *may* be invalid */
+  				/* 'Y' invalid, 'N' valid, 'P' permanent */
   int np_ping;			/* Number of failed ping attempts */
   time_t np_ttl;		/* Time when server is thought dead */
   int np_xid;			/* RPC transaction id for pings */
@@ -88,7 +85,9 @@
 static int global_xid;		/* For NFS pings */
 #define	XID_ALLOC()		(++global_xid)
 
-#ifdef HAVE_FS_NFS3
+#if defined(HAVE_FS_NFS4)
+# define NUM_NFS_VERS 3
+#elif defined(HAVE_FS_NFS3)
 # define NUM_NFS_VERS 2
 #else  /* not HAVE_FS_NFS3 */
 # define NUM_NFS_VERS 1
@@ -124,8 +123,8 @@
   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;
+      if (np && np->np_mountd_inval != 'P') {
+	np->np_mountd_inval = 'Y';
 	np->np_error = -1;
       }
     }
@@ -147,9 +146,9 @@
    */
   if (nfs_version == 0) {
     nfs_version = NFS_VERSION;
-    plog(XLOG_WARNING, "create_ping_payload: nfs_version = 0, changed to 2");
+    plog(XLOG_WARNING, "%s: nfs_version = 0, changed to 2", __func__);
   } else
-    plog(XLOG_INFO, "create_ping_payload: nfs_version: %d", (int) nfs_version);
+    plog(XLOG_INFO, "%s: nfs_version: %d", __func__, (int) nfs_version);
 
   rpc_msg_init(&ping_msg, NFS_PROGRAM, nfs_version, NFSPROC_NULL);
 
@@ -164,6 +163,7 @@
   if (!xdr_callmsg(&ping_xdr, &ping_msg)) {
     plog(XLOG_ERROR, "Couldn't create ping RPC message");
     going_down(3);
+    return;
   }
   /*
    * Find out how long it is
@@ -184,7 +184,7 @@
 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;
+  fserver *fs = NULL;
 
   /*
    * Find which fileserver we are talking about
@@ -207,7 +207,7 @@
        * network ordering.
        */
       np->np_mountd = htons((u_short) port);
-      np->np_mountd_inval = FALSE;
+      np->np_mountd_inval = 'N';
       np->np_error = 0;
     } else {
       dlog("Error fetching port for mountd on %s", fs->fs_host);
@@ -291,9 +291,9 @@
   }
 
   if (fs->fs_version == 0)
-    plog(XLOG_WARNING, "recompute_portmap: nfs_version = 0 fixed");
+    plog(XLOG_WARNING, "%s: nfs_version = 0 fixed", __func__);
 
-  plog(XLOG_INFO, "recompute_portmap: NFS version %d on %s",
+  plog(XLOG_INFO, "%s: NFS version %d on %s", __func__,
        (int) fs->fs_version, fs->fs_host);
 #ifdef HAVE_FS_NFS3
   if (fs->fs_version == NFS_VERSION3)
@@ -311,6 +311,7 @@
 get_mountd_port(fserver *fs, u_short *port, wchan_t wchan)
 {
   int error = -1;
+
   if (FSRV_ISDOWN(fs))
     return EWOULDBLOCK;
 
@@ -329,10 +330,18 @@
      * indication that the mountd may be invalid, not
      * that it is known to be invalid.
      */
-    if (np->np_mountd_inval)
+    switch (np->np_mountd_inval) {
+    case 'Y':
       recompute_portmap(fs);
-    else
-      np->np_mountd_inval = TRUE;
+      break;
+    case 'N':
+      np->np_mountd_inval = 'Y';
+      break;
+    case 'P':
+      break;
+    default:
+      abort();
+    }
   }
   if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
     /*
@@ -425,7 +434,7 @@
       /*
        * Recompute portmap information if not known
        */
-      if (np->np_mountd_inval)
+      if (np->np_mountd_inval == 'Y')
 	recompute_portmap(fs);
 
       found_map++;
@@ -454,7 +463,7 @@
 	     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));
+  old_ipaddr = xstrdup(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",
@@ -474,7 +483,7 @@
 #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
+#endif /* 0 */
 }
 
 
@@ -562,22 +571,24 @@
   int error;
   nfs_private *np = (nfs_private *) fs->fs_private;
   int fstimeo = -1;
+  int fs_version = nfs_valid_version(gopt.nfs_vers_ping) &&
+    gopt.nfs_vers_ping < fs->fs_version ? gopt.nfs_vers_ping : fs->fs_version;
 
   /*
    * Send an NFS ping to this node
    */
 
-  if (ping_len[fs->fs_version - NFS_VERSION] == 0)
-    create_ping_payload(fs->fs_version);
+  if (ping_len[fs_version - NFS_VERSION] == 0)
+    create_ping_payload(fs_version);
 
   /*
    * Queue the packet...
    */
   error = fwd_packet(MK_RPC_XID(RPC_XID_NFSPING, np->np_xid),
-		     ping_buf[fs->fs_version - NFS_VERSION],
-		     ping_len[fs->fs_version - NFS_VERSION],
+		     ping_buf[fs_version - NFS_VERSION],
+		     ping_len[fs_version - NFS_VERSION],
 		     fs->fs_ip,
-		     (struct sockaddr_in *) 0,
+		     (struct sockaddr_in *) NULL,
 		     (voidp) ((long) np->np_xid), /* cast needed for 64-bit archs */
 		     nfs_keepalive_callback);
 
@@ -673,7 +684,7 @@
 fserver *
 find_nfs_srvr(mntfs *mf)
 {
-  char *host = mf->mf_fo->opt_rhost;
+  char *host;
   fserver *fs;
   int pingval;
   mntent_t mnt;
@@ -687,6 +698,11 @@
   int nfs_port_opt = 0;
   int fserver_is_down = 0;
 
+  if (mf->mf_fo == NULL) {
+    plog(XLOG_ERROR, "%s: NULL mf_fo", __func__);
+    return NULL;
+  }
+  host = mf->mf_fo->opt_rhost;
   /*
    * Get ping interval from mount options.
    * Current only used to decide whether pings
@@ -702,7 +718,8 @@
      */
     nfs_version = NFS_VERSION;
     nfs_proto = "udp";
-    plog(XLOG_WARNING, "find_nfs_srvr: NFS mount failed, trying again with NFSv2/UDP");
+    plog(XLOG_WARNING, "%s: NFS mount failed, trying again with NFSv2/UDP",
+      __func__);
     mf->mf_flags &= ~MFF_NFS_SCALEDOWN;
   } else {
     /*
@@ -742,12 +759,13 @@
     /* 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",
+      plog(XLOG_INFO, "%s: force NFS version to %d", __func__,
 	   (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);
+      plog(XLOG_INFO, "%s: force NFS protocol transport to %s", __func__,
+	nfs_proto);
     }
   }
 
@@ -769,7 +787,7 @@
   if (hp) {
     switch (hp->h_addrtype) {
     case AF_INET:
-      ip = ALLOC(struct sockaddr_in);
+      ip = CALLOC(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;
@@ -795,8 +813,7 @@
 	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);
+      XFREE(ip);
       return fs;
     }
   }
@@ -821,10 +838,12 @@
     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).
+     * Prefer NFSv4/tcp if the client supports it (cf. RFC 2054, 7).
      */
     if (!nfs_version) {
-#ifdef HAVE_FS_NFS3
+#if defined(HAVE_FS_NFS4)
+      nfs_version = NFS_VERSION4;
+#elif defined(HAVE_FS_NFS3)
       nfs_version = NFS_VERSION3;
 #else /* not HAVE_FS_NFS3 */
       nfs_version = NFS_VERSION;
@@ -833,11 +852,11 @@
 	   (int) nfs_version);
     }
     if (!nfs_proto) {
-#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3)
+#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) || defined(HAVE_FS_NFS4)
       nfs_proto = "tcp";
-#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
+#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) || defined(HAVE_FS_NFS4) */
       nfs_proto = "udp";
-#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */
+#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) || defined(HAVE_FS_NFS4) */
       plog(XLOG_INFO, "No NFS protocol transport specified, will use %s",
 	   nfs_proto);
     }
@@ -849,7 +868,8 @@
      */
     if (check_pmap_up(host, ip)) {
       if (nfs_proto) {
-	best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto);
+	best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto,
+	  gopt.nfs_vers);
 	nfs_port = ip->sin_port;
       }
 #ifdef MNTTAB_OPT_PROTO
@@ -858,8 +878,8 @@
 	char **p;
 
 	for (p = protocols; *p; p++) {
-	  proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p);
-
+	  proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p,
+	    gopt.nfs_vers);
 	  if (proto_nfs_version > best_nfs_version) {
 	    best_nfs_version = proto_nfs_version;
 	    nfs_proto = *p;
@@ -908,8 +928,8 @@
   if (!nfs_port)
     nfs_port = htons(NFS_PORT);
 
-  dlog("find_nfs_srvr: using port %d for nfs on %s",
-       (int) ntohs(nfs_port), host);
+  dlog("%s: using port %d for nfs on %s", __func__,
+    (int) ntohs(nfs_port), host);
   ip->sin_port = nfs_port;
 
 no_dns:
@@ -935,7 +955,7 @@
 		 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));
+	old_ipaddr = xstrdup(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",
@@ -962,24 +982,28 @@
        */
       if (!(fs->fs_flags & FSF_PINGING)) {
 	np = (nfs_private *) fs->fs_private;
-	np->np_mountd_inval = TRUE;
-	np->np_xid = XID_ALLOC();
-	np->np_error = -1;
-	np->np_ping = 0;
-	/*
-	 * Initially the server will be deemed dead
-	 * after MAX_ALLOWED_PINGS of the fast variety
-	 * have failed.
-	 */
-	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;
+	if (np->np_mountd_inval != 'P') {
+	  np->np_mountd_inval = TRUE;
+	  np->np_xid = XID_ALLOC();
+	  np->np_error = -1;
+	  np->np_ping = 0;
+	  /*
+	   * Initially the server will be deemed dead
+	   * after MAX_ALLOWED_PINGS of the fast variety
+	   * have failed.
+	   */
+	  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;
+	} else {
+	  fs->fs_flags = FSF_VALID;
+	}
+
       }
 
       fs->fs_refc++;
-      if (ip)
-	XFREE(ip);
+      XFREE(ip);
       return fs;
     }
   }
@@ -993,7 +1017,7 @@
    */
   fs = ALLOC(struct fserver);
   fs->fs_refc = 1;
-  fs->fs_host = strdup(hp ? hp->h_name : "unknown_hostname");
+  fs->fs_host = xstrdup(hp ? hp->h_name : "unknown_hostname");
   if (gopt.flags & CFM_NORMALIZE_HOSTNAMES)
     host_normalize(&fs->fs_host);
   fs->fs_ip = ip;
@@ -1014,9 +1038,18 @@
   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 = XID_ALLOC();
-  np->np_error = -1;
+  np->np_mountd = htons(hasmntval(&mnt, "mountport"));
+  if (np->np_mountd == 0) {
+    np->np_mountd_inval = 'Y';
+    np->np_xid = XID_ALLOC();
+    np->np_error = -1;
+  } else {
+    plog(XLOG_INFO, "%s: using mountport: %d", __func__,
+      (int) ntohs(np->np_mountd));
+    np->np_mountd_inval = 'P';
+    np->np_xid = 0;
+    np->np_error = 0;
+  }
 
   /*
    * Initially the server will be deemed dead after

Modified: trunk/contrib/amd/amq/amq.8
===================================================================
--- trunk/contrib/amd/amq/amq.8	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amq/amq.8	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
 .\" 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
+.\" 3. 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.
 .\"
@@ -36,12 +32,11 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: amq.8,v 1.1.1.4 2012-07-21 14:53:13 laffer1 Exp $
-.\" $FreeBSD$
+.\" File: am-utils/amq/amq.8
+.\" $FreeBSD: stable/10/contrib/amd/amq/amq.8 310490 2016-12-23 22:42:14Z cy $
 .\"
-.Dd January 2, 2006
+.Dd August 31, 2016
 .Dt AMQ 8
 .Os
 .Sh NAME
@@ -49,7 +44,7 @@
 .Nd automounter query tool
 .Sh SYNOPSIS
 .Nm
-.Op Fl fmpsvwHTU
+.Op Fl fimpqsvwHTU
 .Op Fl h Ar hostname
 .Op Fl l Ar log_file
 .Op Fl x Ar log_options
@@ -57,6 +52,13 @@
 .Op Fl P Ar program_number
 .Op Oo Fl u Oc Ar directory ...
 .Sh DESCRIPTION
+.Bf -symbolic
+This command is obsolete.
+Users are advised to use
+.Xr autofs 5
+instead.
+.Ef
+.Pp
 The
 .Nm
 utility
@@ -89,6 +91,10 @@
 .Tn HP-UX
 cluster, the root server is queried by default, since that is the system on
 which the automounter is normally run.
+.TP
+.It Fl i
+Print information about the mount maps.
+.TP
 .It Fl l Ar log_file
 Tell
 .Xr amd 8
@@ -119,6 +125,13 @@
 This option is used in the
 .Pa ctl-amd
 script.
+.TP
+.It Fl q
+Suppress error messages produced when attempting synchronous unmounts
+with the
+.B \-u
+option.
+.TP
 .It Fl s
 Ask the automounter to provide system-wide mount statistics.
 .It Fl u
@@ -131,9 +144,19 @@
 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.
+If the
+.B \-u
+option is repeated,
+.B amq
+will attempt to unmount the file system synchronously by waiting until
+the timeout action is taken and returning an error if the unmount
+fails.
+Any error messages produced may be suppressed with the
+.B \-q
+option.
+.TP
 .It Fl v
-Ask the automounter for its version information.
-This is a subset of the
+Ask the automounter for its version information.  This is a subset of the
 information output by
 .Xr amd 8 Ns 's
 .Fl v
@@ -150,8 +173,10 @@
 .It Fl x Ar log_options
 Ask the automounter to use the logging options specified in
 .Ar log_options
-from now on.
+from now on.  Note that the "fatal" and "error" options cannot be turned
+off.
 .It Fl D Ar debug_options
+.BI \-D " debug_options"
 Ask the automounter to use the debugging options specified in
 .Ar debug_options
 from now on.
@@ -237,11 +262,13 @@
 and this line to
 .Pa /etc/hosts.deny :
 .Pp
+.RS
 .Dl "amd: ALL"
 .Sh SEE ALSO
 .Xr amd.conf 5 ,
-.Xr hosts_access 5 ,
-.Xr amd 8
+.Xr hosts_access 5 .
+.Xr amd 8 ,
+.\" .Xr ctl-amd 8 ,
 .Pp
 .Dq am-utils
 .Xr info 1

Modified: trunk/contrib/amd/amq/amq.c
===================================================================
--- trunk/contrib/amd/amq/amq.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amq/amq.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -53,14 +49,17 @@
 
 /* locals */
 static int flush_flag;
+static int getpid_flag;
+static int getpwd_flag;
+static int getvers_flag;
 static int minfo_flag;
-static int getpid_flag;
+static int mapinfo_flag;
+static int quiet_flag;
+static int stats_flag;
 static int unmount_flag;
-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 int use_tcp_flag;
+static int use_udp_flag;
+static u_long amd_program_number = AMQ_PROGRAM;
 static char *debug_opts;
 static char *amq_logfile;
 static char *xlog_optstr;
@@ -77,6 +76,17 @@
 };
 
 
+static void
+time_print(time_type tt)
+{
+  time_t t = (time_t)*tt;
+  struct tm *tp = localtime(&t);
+  printf("%02d/%02d/%04d %02d:%02d:%02d",
+	 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);
+}
+
 /*
  * If (e) is Calc then just calculate the sizes
  * Otherwise display the mount node on stdout
@@ -101,8 +111,7 @@
 
   case Full:
     {
-      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",
+      printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d",
 	     *dwid, *dwid,
 	     *mt->mt_directory ? mt->mt_directory : "/",	/* XXX */
 	     *twid, *twid,
@@ -116,18 +125,15 @@
 	     mt->mt_lookup,
 	     mt->mt_readdir,
 	     mt->mt_readlink,
-	     mt->mt_statfs,
-
-	     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);
+	     mt->mt_statfs);
+      time_print(mt->mt_mounttime);
+      printf("\n");
     }
   break;
 
   case Stats:
     {
-      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",
+      printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d ",
 	     *dwid, *dwid,
 	     *mt->mt_directory ? mt->mt_directory : "/",	/* XXX */
 
@@ -136,11 +142,9 @@
 	     mt->mt_lookup,
 	     mt->mt_readdir,
 	     mt->mt_readlink,
-	     mt->mt_statfs,
-
-	     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);
+	     mt->mt_statfs);
+      time_print(mt->mt_mounttime);
+      printf("\n");
     }
   break;
 
@@ -229,7 +233,7 @@
     {
       for (i = 0; i < ml->amq_mount_info_list_len; i++) {
 	amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
-	printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s",
+	printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s ",
 	       *mwid, *mwid, mi->mi_mountinfo,
 	       *dwid, *dwid, mi->mi_mountpt,
 	       *twid, *twid, mi->mi_type,
@@ -251,7 +255,56 @@
   }
 }
 
+static void
+show_map(amq_map_info *mi)
+{
+}
 
+static void
+show_mapinfo(amq_map_info_list *ml, enum show_opt e, int *nwid, int *wwid)
+{
+  u_int i;
+
+  switch (e) {
+
+  case Calc:
+    {
+      for (i = 0; i < ml->amq_map_info_list_len; i++) {
+	amq_map_info *mi = &ml->amq_map_info_list_val[i];
+	int nw = strlen(mi->mi_name);
+	int ww = strlen(mi->mi_wildcard ? mi->mi_wildcard : "(null");
+	if (nw > *nwid)
+	  *nwid = nw;
+	if (ww > *wwid)
+	  *wwid = ww;
+      }
+    }
+  break;
+
+  case Full:
+    {
+      printf("%-*.*s %-*.*s %-8.8s %-7.7s %-7.7s %-7.7s %-s Modified\n",
+	*nwid, *nwid, "Name",
+	*wwid, *wwid, "Wild",
+	"Flags", "Refcnt", "Entries", "Reloads", "Stat");
+      for (i = 0; i < ml->amq_map_info_list_len; i++) {
+	amq_map_info *mi = &ml->amq_map_info_list_val[i];
+        printf("%-*.*s %*.*s %-8x %-7d %-7d %-7d %s ",
+	       *nwid, *nwid, mi->mi_name,
+	       *wwid, *wwid, mi->mi_wildcard,
+	       mi->mi_flags, mi->mi_refc, mi->mi_nentries, mi->mi_reloads,
+	       mi->mi_up == -1 ? "root" : (mi->mi_up ? "  up" : "down"));
+        time_print(mi->mi_modify);
+	fputc('\n', stdout);
+      }
+    }
+  break;
+
+  default:
+    break;
+  }
+}
+
 /*
  * Display general mount statistics
  */
@@ -287,6 +340,72 @@
 #endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */
 
 
+static void
+print_umnt_error(amq_sync_umnt *rv, const char *fs)
+{
+
+  switch (rv->au_etype) {
+  case AMQ_UMNT_OK:
+    break;
+  case AMQ_UMNT_FAILED:
+    printf("unmount failed: %s\n", strerror(rv->au_errno));
+    break;
+  case AMQ_UMNT_FORK:
+    if (rv->au_errno == 0)
+      printf("%s is not mounted\n", fs);
+    else
+      printf("falling back to asynchronous unmount: %s\n",
+	  strerror(rv->au_errno));
+    break;
+  case AMQ_UMNT_READ:
+    printf("pipe read error: %s\n", strerror(rv->au_errno));
+    break;
+  case AMQ_UMNT_SERVER:
+    printf("amd server down\n");
+    break;
+  case AMQ_UMNT_SIGNAL:
+    printf("got signal: %d\n", rv->au_signal);
+    break;
+  /*
+   * Omit default so the compiler can check for missing cases.
+   *
+  default:
+    break;
+   */
+  }
+}
+
+
+static int
+amu_sync_umnt_to_retval(amq_sync_umnt *rv)
+{
+  switch (rv->au_etype) {
+  case AMQ_UMNT_FORK:
+    if (rv->au_errno == 0) {
+      /*
+       * We allow this error so that things like:
+       *   amq -uu /l/cd0d && eject cd0
+       * will work when /l/cd0d is not mounted.
+       * XXX - We still print an error message.
+       */
+      return 0;
+    }
+    /*FALLTHROUGH*/
+  default:
+    return rv->au_etype;
+  }
+}
+
+
+static int
+clnt_failed(CLIENT *clnt, char *server)
+{
+  fprintf(stderr, "%s: ", am_get_progname());
+  clnt_perror(clnt, server);
+  return 1;
+}
+
+
 /*
  * MAIN
  */
@@ -320,7 +439,7 @@
   /*
    * Parse arguments
    */
-  while ((opt_ch = getopt(argc, argv, "Hfh:l:msuvx:D:pP:TUw")) != -1)
+  while ((opt_ch = getopt(argc, argv, "Hfh:il:mqsuvx:D:pP:TUw")) != -1)
     switch (opt_ch) {
     case 'H':
       goto show_usage;
@@ -335,6 +454,11 @@
       def_server = optarg;
       break;
 
+    case 'i':
+      mapinfo_flag = 1;
+      nodefault = 1;
+      break;
+
     case 'l':
       amq_logfile = optarg;
       nodefault = 1;
@@ -350,6 +474,11 @@
       nodefault = 1;
       break;
 
+    case 'q':
+      quiet_flag = 1;
+      nodefault = 1;
+      break;
+
     case 's':
       stats_flag = 1;
       nodefault = 1;
@@ -356,7 +485,7 @@
       break;
 
     case 'u':
-      unmount_flag = 1;
+      unmount_flag++;
       nodefault = 1;
       break;
 
@@ -403,9 +532,9 @@
   if (errs) {
   show_usage:
     fprintf(stderr, "\
-Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
+Usage: %s [-fimpqsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\
 \t[-x log_options] [-D debug_options]\n\
-\t[-P program_number] [[-u] directory ...]\n",
+\t[-P program_number] [[-u[u]] directory ...]\n",
 	    am_get_progname()
     );
     exit(1);
@@ -538,16 +667,19 @@
    */
   if (getpwd_flag) {
     char path[MAXPATHLEN+1];
-    char *wd = getcwd(path, MAXPATHLEN+1);
-    amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
+    char *wd;
+    amq_mount_tree_list *mlp;
     amq_mount_tree_p mt;
     u_int i;
     int flag;
 
+    wd = getcwd(path, MAXPATHLEN+1);
     if (!wd) {
-      perror("getcwd");
+      fprintf(stderr, "%s: getcwd failed (%s)", am_get_progname(),
+	  strerror(errno));
       exit(1);
     }
+    mlp = amqproc_export_1((voidp) 0, clnt);
     for (i = 0; mlp && i < mlp->amq_mount_tree_list_len; i++) {
       mt = mlp->amq_mount_tree_list_val[i];
       while (1) {
@@ -582,7 +714,27 @@
     }
   }
 
+
   /*
+   * Map
+   */
+  if (mapinfo_flag) {
+    int dummy;
+    amq_map_info_list *ml = amqproc_getmapinfo_1(&dummy, clnt);
+    if (ml) {
+      int mwid = 0, wwid = 0;
+      show_mapinfo(ml, Calc, &mwid, &wwid);
+      mwid++;
+      if (wwid)
+	 wwid++;
+      show_mapinfo(ml, Full, &mwid, &wwid);
+    } else {
+      fprintf(stderr, "%s: amd on %s cannot provide map info\n",
+	      am_get_progname(), server);
+    }
+  }
+
+  /*
    * Get Version
    */
   if (getvers_flag) {
@@ -616,8 +768,21 @@
   if (optind < argc) {
     do {
       char *fs = argv[optind++];
-      if (unmount_flag) {
+      if (unmount_flag > 1) {
+	amq_sync_umnt *sup;
 	/*
+	 * Synchronous unmount request
+	 */
+        sup = amqproc_sync_umnt_1(&fs, clnt);
+	if (sup) {
+	  if (quiet_flag == 0)
+	    print_umnt_error(sup, fs);
+	  errs = amu_sync_umnt_to_retval(sup);
+	} else {
+	  errs = clnt_failed(clnt, server);
+	}
+      }	else if (unmount_flag) {
+	/*
 	 * Unmount request
 	 */
 	amqproc_umnt_1(&fs, clnt);
@@ -641,9 +806,7 @@
 	  }
 	  xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp);
 	} else {
-	  fprintf(stderr, "%s: ", am_get_progname());
-	  clnt_perror(clnt, server);
-	  errs = 1;
+	  errs = clnt_failed(clnt, server);
 	}
       }
     } while (optind < argc);
@@ -656,9 +819,7 @@
     if (ms) {
       show_ms(ms);
     } else {
-      fprintf(stderr, "%s: ", am_get_progname());
-      clnt_perror(clnt, server);
-      errs = 1;
+      errs = clnt_failed(clnt, server);
     }
 
   } else if (!nodefault) {
@@ -682,9 +843,7 @@
       }
 
     } else {
-      fprintf(stderr, "%s: ", am_get_progname());
-      clnt_perror(clnt, server);
-      errs = 1;
+      errs = clnt_failed(clnt, server);
     }
   }
   exit(errs);

Modified: trunk/contrib/amd/amq/amq.h
===================================================================
--- trunk/contrib/amd/amq/amq.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amq/amq.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -51,10 +47,12 @@
 extern voidp amqproc_null_1(voidp argp, CLIENT *rqstp);
 extern amq_mount_tree_p *amqproc_mnttree_1(amq_string *argp, CLIENT *rqstp);
 extern voidp amqproc_umnt_1(amq_string *argp, CLIENT *rqstp);
+extern amq_sync_umnt *amqproc_sync_umnt_1(amq_string *argp, CLIENT *rqstp);
 extern amq_mount_stats *amqproc_stats_1(voidp argp, CLIENT *rqstp);
 extern amq_mount_tree_list *amqproc_export_1(voidp argp, CLIENT *rqstp);
 extern int *amqproc_setopt_1(amq_setopt *argp, CLIENT *rqstp);
 extern amq_mount_info_list *amqproc_getmntfs_1(voidp argp, CLIENT *rqstp);
+extern amq_map_info_list *amqproc_getmapinfo_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);

Modified: trunk/contrib/amd/amq/amq_clnt.c
===================================================================
--- trunk/contrib/amd/amq/amq_clnt.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amq/amq_clnt.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -99,6 +95,23 @@
 }
 
 
+amq_sync_umnt *
+amqproc_sync_umnt_1(amq_string *argp, CLIENT *clnt)
+{
+  static amq_sync_umnt res;
+  enum clnt_stat rv;
+
+  memset((char *) &res, 0, sizeof(res));
+  if ((rv = clnt_call(clnt, AMQPROC_SYNC_UMNT,
+		(XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
+		(XDRPROC_T_TYPE) xdr_amq_sync_umnt, (SVC_IN_ARG_TYPE) &res,
+		TIMEOUT)) != RPC_SUCCESS) {
+    return (NULL);
+  }
+  return &res;
+}
+
+
 amq_mount_stats *
 amqproc_stats_1(voidp argp, CLIENT *clnt)
 {
@@ -161,7 +174,21 @@
   return (&res);
 }
 
+amq_map_info_list *
+amqproc_getmapinfo_1(voidp argp, CLIENT *clnt)
+{
+  static amq_map_info_list res;
 
+  memset((char *) &res, 0, sizeof(res));
+  if (clnt_call(clnt, AMQPROC_GETMAPINFO, (XDRPROC_T_TYPE) xdr_void, argp,
+		(XDRPROC_T_TYPE) xdr_amq_map_info_list,
+		(SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) {
+    return (NULL);
+  }
+  return (&res);
+}
+
+
 int *
 amqproc_mount_1(voidp argp, CLIENT *clnt)
 {

Modified: trunk/contrib/amd/amq/amq_xdr.c
===================================================================
--- trunk/contrib/amd/amq/amq_xdr.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amq/amq_xdr.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -187,8 +183,61 @@
   return (TRUE);
 }
 
+bool_t
+xdr_amq_map_info(XDR *xdrs, amq_map_info *objp)
+{
+  if (!xdr_amq_string(xdrs, &objp->mi_name)) {
+    return (FALSE);
+  }
 
+  if (!xdr_amq_string(xdrs, &objp->mi_wildcard)) {
+    return (FALSE);
+  }
+
+  if (!xdr_time_type(xdrs, &objp->mi_modify)) {
+    return (FALSE);
+  }
+
+  if (!xdr_int(xdrs, &objp->mi_flags)) {
+    return (FALSE);
+  }
+
+  if (!xdr_int(xdrs, &objp->mi_nentries)) {
+    return (FALSE);
+  }
+
+  if (!xdr_int(xdrs, &objp->mi_reloads)) {
+    return (FALSE);
+  }
+
+  if (!xdr_int(xdrs, &objp->mi_refc)) {
+    return (FALSE);
+  }
+
+  if (!xdr_int(xdrs, &objp->mi_up)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+}
+
+
 bool_t
+xdr_amq_map_info_list(XDR *xdrs, amq_map_info_list *objp)
+{
+  if (!xdr_array(xdrs,
+		 (char **) ((voidp) &objp->amq_map_info_list_val),
+		 (u_int *) &objp->amq_map_info_list_len,
+		 ~0,
+		 sizeof(amq_map_info),
+		 (XDRPROC_T_TYPE) xdr_amq_map_info)) {
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+
+bool_t
 xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp)
 {
   if (!xdr_array(xdrs,

Modified: trunk/contrib/amd/amq/pawd.1
===================================================================
--- trunk/contrib/amd/amq/pawd.1	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amq/pawd.1	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
 .\" 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
+.\" 3. 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.
 .\"
@@ -36,10 +32,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: pawd.1,v 1.1.1.3 2012-07-21 14:53:13 laffer1 Exp $
-.\" $FreeBSD$
+.\" File: am-utils/amq/pawd.1
+.\" $FreeBSD: stable/10/contrib/amd/amq/pawd.1 310490 2016-12-23 22:42:14Z cy $
 .\"
 .Dd January 2, 2006
 .Dt PAWD 1

Modified: trunk/contrib/amd/amq/pawd.c
===================================================================
--- trunk/contrib/amd/amq/pawd.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/amq/pawd.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/bootstrap
===================================================================
--- trunk/contrib/amd/bootstrap	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/bootstrap	2018-06-15 22:31:15 UTC (rev 11011)
@@ -5,6 +5,16 @@
 # this is not meant to go into the distributions
 # Erez Zadok <ezk at cs.columbia.edu>
 
+validateversion() {
+    local v="$(autoreconf --version 2>&1 | head -1)"
+    case "$v" in
+    *2.69)	;;
+    *)		echo "am-utils requires autoconf 2.69, you have:"
+		echo "	$v"
+		exit 1;;
+    esac
+}
+
 # test cwd
 test -f ../amd/amd.c && cd ..
 if [ ! -f amd/amd.c ]; then
@@ -37,70 +47,16 @@
  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
+# generate the rest of the scripts
+echo "AMU: autoreconf..."
+validateversion
+if autoreconf -f -i; then
     :
 else
-    echo "aclocal command failed.  fix errors and rerun $0."
+    echo "autoreconf 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

Modified: trunk/contrib/amd/conf/checkmount/checkmount_bsd44.c
===================================================================
--- trunk/contrib/amd/conf/checkmount/checkmount_bsd44.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/conf/checkmount/checkmount_bsd44.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -45,6 +41,9 @@
 # include <config.h>
 #endif /* HAVE_CONFIG_H */
 #include <am_defs.h>
+#if __NetBSD_Version__ > 200030000
+#define statfs statvfs
+#endif
 
 extern int is_same_host(char *name1, char *name2, struct in_addr addr2);
 int fixmount_check_mount(char *host, struct in_addr hostaddr, char *path);

Modified: trunk/contrib/amd/conf/mtab/mtab_bsd.c
===================================================================
--- trunk/contrib/amd/conf/mtab/mtab_bsd.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/conf/mtab/mtab_bsd.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -53,6 +49,9 @@
 #include <am_defs.h>
 #include <amu.h>
 
+#if __NetBSD_Version__ > 200030000
+#define statfs statvfs
+#endif
 
 static mntent_t *
 mnt_dup(struct statfs *mp)
@@ -60,8 +59,8 @@
   mntent_t *new_mp = ALLOC(mntent_t);
   char *ty;
 
-  new_mp->mnt_fsname = strdup(mp->f_mntfromname);
-  new_mp->mnt_dir = strdup(mp->f_mntonname);
+  new_mp->mnt_fsname = xstrdup(mp->f_mntfromname);
+  new_mp->mnt_dir = xstrdup(mp->f_mntonname);
 
 #ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME
   ty = mp->f_fstypename;
@@ -93,8 +92,8 @@
   }
 #endif /* not HAVE_STRUCT_STATFS_F_FSTYPENAME */
 
-  new_mp->mnt_type = strdup(ty);
-  new_mp->mnt_opts = strdup("unset");
+  new_mp->mnt_type = xstrdup(ty);
+  new_mp->mnt_opts = xstrdup("unset");
   new_mp->mnt_freq = 0;
   new_mp->mnt_passno = 0;
 
@@ -138,7 +137,7 @@
   /*
    * Terminate the list
    */
-  *mpp = 0;
+  *mpp = NULL;
 
   return mhp;
 }

Modified: trunk/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h
===================================================================
--- trunk/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -139,7 +135,7 @@
  */
 #if 0
 #define MOUNT_NFS3 MOUNT_NFS
-#endif
+#endif /* 0 */
 
 
 #endif /* not _AMU_NFS_PROT_H */

Modified: trunk/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h
===================================================================
--- trunk/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -38,8 +34,8 @@
  *
  *
  * File: am-utils/conf/nfs_prot/nfs_prot_freebsd3.h
- * $Id: nfs_prot_freebsd3.h,v 1.1.1.3 2012-07-21 14:53:13 laffer1 Exp $
- * $FreeBSD$
+ * $Id: nfs_prot_freebsd3.h,v 1.5.2.7 2004/01/06 03:15:19 ezk Exp $
+ * $FreeBSD: stable/10/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h 310490 2016-12-23 22:42:14Z cy $
  *
  */
 
@@ -103,9 +99,11 @@
 #define na_ctime	ctime
 #define na_fileid	fileid
 #define na_fsid		fsid
+#define na_gid		gid
 #define na_mode		mode
 #define na_mtime	mtime
 #define na_nlink	nlink
+#define na_rdev		rdev
 #define na_size		size
 #define na_type		type
 #define na_uid		uid

Modified: trunk/contrib/amd/conf/transp/transp_sockets.c
===================================================================
--- trunk/contrib/amd/conf/transp/transp_sockets.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/conf/transp/transp_sockets.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -171,7 +167,7 @@
     /*
      * Bind to a privileged port
      */
-    if (bind_resv_port(*sock, (u_short *) 0) < 0)
+    if (bind_resv_port(*sock, (u_short *) NULL) < 0)
       plog(XLOG_ERROR, "can't bind privileged port (socket)");
 
     /*
@@ -198,7 +194,7 @@
   /*
    * Bind to a privileged port
    */
-  if (bind_resv_port(*sock, (u_short *) 0) < 0)
+  if (bind_resv_port(*sock, (u_short *) NULL) < 0)
     plog(XLOG_ERROR, "can't bind privileged port");
 
   /*
@@ -231,7 +227,8 @@
 
 
 /*
- * register an RPC server
+ * Register an RPC server:
+ * return 1 on success, 0 otherwise.
  */
 int
 amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum,
@@ -238,6 +235,7 @@
 		 void (*dispatch)(struct svc_req *rqstp, SVCXPRT *transp),
 		 u_long protocol, struct netconfig *dummy)
 {
+  /* on Sockets: svc_register returns 1 on success, 0 otherwise */
   return svc_register(xprt, prognum, versnum, dispatch, protocol);
 }
 
@@ -246,9 +244,8 @@
  * Create the nfs service for amd
  */
 int
-create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp))
+create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version)
 {
-
   *soNFSp = socket(AF_INET, SOCK_DGRAM, 0);
 
   if (*soNFSp < 0 || bind_resv_port(*soNFSp, nfs_portp) < 0) {
@@ -268,9 +265,9 @@
     close(*soNFSp);
     return 1;
   }
-  if (!svc_register(*nfs_xprtp, NFS_PROGRAM, NFS_VERSION, dispatch_fxn, 0)) {
-    plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)",
-	 (u_long) NFS_PROGRAM, (u_long) NFS_VERSION);
+  if (!svc_register(*nfs_xprtp, NFS_PROGRAM, nfs_version, dispatch_fxn, 0)) {
+    plog(XLOG_FATAL, "unable to register (%lu, %lu, 0)",
+	 (u_long) NFS_PROGRAM, nfs_version);
     svc_destroy(*nfs_xprtp);
     close(*soNFSp);
     return 3;
@@ -386,8 +383,8 @@
 
   if (client == (CLIENT *) NULL) {
     plog(XLOG_ERROR,
-	 "check_pmap_up: cannot create connection to contact portmapper on host \"%s\"%s",
-	 host, clnt_spcreateerror(""));
+	 "%s: cannot create connection to contact portmapper on host \"%s\"%s",
+	 __func__, host, clnt_spcreateerror(""));
     return 0;
   }
 
@@ -406,8 +403,8 @@
 
   if (clnt_stat == RPC_TIMEDOUT) {
     plog(XLOG_ERROR,
-	 "check_pmap_up: failed to contact portmapper on host \"%s\": %s",
-	 host, clnt_sperrno(clnt_stat));
+	 "%s: failed to contact portmapper on host \"%s\": %s",
+	 __func__, host, clnt_sperrno(clnt_stat));
     return 0;
   }
   return 1;
@@ -418,7 +415,7 @@
  * Find the best NFS version for a host and protocol.
  */
 u_long
-get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto)
+get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto, u_long def)
 {
   CLIENT *clnt;
   int again = 0;
@@ -431,68 +428,64 @@
    * If not set or set wrong, then try from NFS_VERS_MAX on down. If
    * set, then try from nfs_version on down.
    */
-  if (nfs_version <= 0 || nfs_version > NFS_VERS_MAX) {
-    nfs_version = NFS_VERS_MAX;
+  if (!nfs_valid_version(nfs_version)) {
+    if (nfs_valid_version(def))
+      nfs_version = def;
+    else
+      nfs_version = NFS_VERS_MAX;
     again = 1;
   }
   tv.tv_sec = 2;		/* retry every 2 seconds, but also timeout */
   tv.tv_usec = 0;
 
-#ifdef HAVE_FS_NFS3
-try_again:
-#endif /* HAVE_FS_NFS3 */
+  for (; nfs_version >= NFS_VERS_MIN; nfs_version--) {
 
-  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"))
-    clnt = clntudp_create(sin, NFS_PROGRAM, nfs_version, tv, &sock);
-  else
-    clnt = NULL;
+    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"))
+      clnt = clntudp_create(sin, NFS_PROGRAM, nfs_version, tv, &sock);
+    else
+      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 != 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);
+      if (clnt_stat != RPC_SUCCESS)
+	errstr = clnt_sperrno(clnt_stat);
 
-    close(sock);
-    clnt_destroy(clnt);
-  } else {
-#ifdef HAVE_CLNT_SPCREATEERROR
-    errstr = clnt_spcreateerror("");
-#else /* not HAVE_CLNT_SPCREATEERROR */
-    errstr = "";
-#endif /* not HAVE_CLNT_SPCREATEERROR */
-  }
+      close(sock);
+      clnt_destroy(clnt);
+      if (clnt_stat == RPC_SUCCESS)
+	break;
+    } else {
+  #ifdef HAVE_CLNT_SPCREATEERROR
+      errstr = clnt_spcreateerror("");
+  #else /* not HAVE_CLNT_SPCREATEERROR */
+      errstr = "";
+  #endif /* not HAVE_CLNT_SPCREATEERROR */
+    }
 
-  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) {
-	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 */
+    if (errstr) {
+      plog(XLOG_INFO, "%s: NFS(%lu,%s) failed for %s: %s", __func__,
+	   nfs_version, proto, host, errstr);
     }
-    return 0;
   }
 
-  plog(XLOG_INFO, "get_nfs_version: returning NFS(%d,%s) on host %s",
-       (int) nfs_version, proto, host);
+  if (nfs_version < NFS_VERS_MIN)
+    nfs_version = 0;
+
+  plog(XLOG_INFO, "%s: returning NFS(%lu,%s) on host %s", __func__,
+       nfs_version, proto, host);
   return nfs_version;
 }
 

Modified: trunk/contrib/amd/conf/trap/trap_default.h
===================================================================
--- trunk/contrib/amd/conf/trap/trap_default.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/conf/trap/trap_default.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,3 +1,3 @@
-/* $FreeBSD$ */
+/* $FreeBSD: stable/10/contrib/amd/conf/trap/trap_default.h 174313 2007-12-05 16:57:05Z obrien $ */
 /* $srcdir/conf/trap/trap_default.h */
 #define MOUNT_TRAP(type, mnt, flags, mnt_data) mount(type, mnt->mnt_dir, flags, mnt_data)

Modified: trunk/contrib/amd/conf/umount/umount_bsd44.c
===================================================================
--- trunk/contrib/amd/conf/umount/umount_bsd44.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/conf/umount/umount_bsd44.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -105,6 +101,7 @@
 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);

Modified: trunk/contrib/amd/doc/am-utils.texi
===================================================================
--- trunk/contrib/amd/doc/am-utils.texi	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/doc/am-utils.texi	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,6 +1,6 @@
 \input texinfo          @c -*-texinfo-*-
 @c
- at c Copyright (c) 1997-2006 Erez Zadok
+ at c Copyright (c) 1997-2014 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.
@@ -17,11 +17,7 @@
 @c 2. Redistributions in binary form must reproduce the above copyright
 @c    notice, this list of conditions and the following disclaimer in the
 @c    documentation and/or other materials provided with the distribution.
- at c 3. All advertising materials mentioning features or use of this software
- at c    must display the following acknowledgment:
- at c      This product includes software developed by the University of
- at c      California, Berkeley and its contributors.
- at c 4. Neither the name of the University nor the names of its contributors
+ at c 3. Neither the name of the University nor the names of its contributors
 @c    may be used to endorse or promote products derived from this software
 @c    without specific prior written permission.
 @c
@@ -60,7 +56,7 @@
 (Originally by Jan-Simon Pendry and Nick Williams)
 
 @page
-Copyright @copyright{} 1997-2006 Erez Zadok
+Copyright @copyright{} 1997-2014 Erez Zadok
 @*
 Copyright @copyright{} 1989 Jan-Simon Pendry
 @*
@@ -67,7 +63,7 @@
 Copyright @copyright{} 1989 Imperial College of Science, Technology & Medicine
 @*
 Copyright @copyright{} 1989 The Regents of the University of California.
- at sp
+ at sp 1
 All Rights Reserved.
 @vskip 1ex
 Permission to copy this document, or any portion of it, as
@@ -93,7 +89,7 @@
 @*
 (Originally by Jan-Simon Pendry and Nick Williams)
 
-Copyright @copyright{} 1997-2006 Erez Zadok
+Copyright @copyright{} 1997-2014 Erez Zadok
 @*
 Copyright @copyright{} 1989 Jan-Simon Pendry
 @*
@@ -179,16 +175,6 @@
 documentation and/or other materials provided with the distribution.
 
 @item
-All advertising materials mentioning features or use of this software
-must display the following acknowledgment:
-
- at cartouche
-``This product includes software developed by the University of
-California, Berkeley and its contributors, as well as the Trustees of
-Columbia University.''
- at end cartouche
-
- at item
 Neither the name of the University nor the names of its contributors may
 be used to endorse or promote products derived from this software
 without specific prior written permission.
@@ -234,7 +220,7 @@
 of the BSD network version 2 distribution
 
 Revision 6.0 was made independently by
- at email{ezk@@cs.columbia.edu,Erez Zadok} at the Computer Science
+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
@@ -262,7 +248,8 @@
 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
+your bug report to the ``am-utils'' list (see
+ at url{http://www.am-utils.org/} under ``Mailing Lists'') 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
@@ -297,11 +284,10 @@
 implementation and porting issues
 @end itemize
 
-To subscribe, visit
- at url{http://lists.am-utils.org/mailman/listinfo/am-utils}.  After
-subscribing, you can post a message to this list at
- at email{am-utils@@am-utils.org}.  To avoid as much spam as
-possible, only subscribers to this list may post to it.
+To subscribe, visit @url{http://www.am-utils.org/} under ``Mailing
+Lists.''  After subscribing, you can post a message to this list.  To
+avoid as much spam as possible, only subscribers to this list may post
+to it.
 
 Subscribers of @samp{am-utils} are most helpful if they have the time
 and resources to test new and development versions of amd, on as many
@@ -318,7 +304,7 @@
 @item
 The announcements mailing list, @samp{am-utils-announce} is for
 announcements only (mostly new releases).  To subscribe, visit
- at url{http://lists.am-utils.org/mailman/listinfo/am-utils-announce}.
+ at url{http://www.am-utils.org/} under ``Mailing Lists.''
 This list is read-only: only am-utils developers may post to it.
 
 @item
@@ -326,17 +312,18 @@
 @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
- at url{http://lists.am-utils.org/mailman/listinfo/am-utils-cvs}.
+ at url{http://www.am-utils.org/} under ``Mailing Lists.''
 
 @item
 The older list which was used to user discussions, @samp{amd-workers},
 is defunct as of January 2004.  (Its last address was
- at email{amd-workers@@majordomo.glue.umd.edu}.)  Don't use
+ at email{amd-workers AT 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
- at samp{am-utils-developers@@am-utils.org}.
+ at samp{am-utils-developers} (see @url{http://www.am-utils.org/} under
+``Mailing Lists'').
 
 @end enumerate
 
@@ -346,7 +333,7 @@
 @cindex Automounter book
 @cindex book
 
- at email{ezk@@cs.sunysb.edu,Erez Zadok} wrote a
+ at uref{http://www.cs.sunysb.edu/~ezk,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
@@ -389,7 +376,7 @@
 The @i{Amd} package has been without an official maintainer since 1992.
 Several people have stepped in to maintain it unofficially.  Most
 notable were the `upl' (Unofficial Patch Level) releases of @i{Amd},
-created by me (@email{ezk@@cs.sunysb.edu,Erez Zadok}), and available from
+created by me (@uref{http://www.cs.sunysb.edu/~ezk,Erez Zadok}), and available from
 @url{ftp://ftp.am-utils.org/pub/amd/}.  The last such unofficial
 release was `upl102'.
 
@@ -428,7 +415,7 @@
 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}.
+conjunction with @email{ionut AT badula.org,Ion Badulescu}.
 
 @c ################################################################
 @node Overview, Supported Platforms, History, Top
@@ -1040,7 +1027,7 @@
 the map entry used by @i{Amd} would be
 
 @example
-rfs:=/home/sugar;rhost:=sugar.cc;sublink:=jsp
+rfs:=/home/sugar;rhost:=sugar.cc;sublink:=mhj
 @end example
 
 @c ----------------------------------------------------------------
@@ -1795,8 +1782,8 @@
 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.
+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,
@@ -2098,6 +2085,10 @@
 @cindex Mount flags; cache
 Allow data to be cached from a remote server for this mount.
 
+ at item closesession
+ at cindex Mount flags; closesession
+For UDF mounts, close the session when unmounting.
+
 @item compress
 @cindex Mount flags; compress
 Use NFS compression protocol.
@@ -2137,10 +2128,16 @@
 Enable generations in ISO-9660 file systems.  Generations allow you to
 see all versions of a given file.
 
+ at item gmtoff=@var{n}
+ at cindex Mount flags; gmtoff
+For UDF mounts, set the time zone offset from UTC to @var{n} seconds,
+with positive values indicating east of the Prime Meridian.  If not
+set, the user's current time zone will be used.
+
 @item group=@var{n}
 @cindex Mount flags; group
-For PCFS mounts, set the group of the files in the file system to
- at var{n} (which can either be a group name or a GID number).  The
+For PCFS and UDF 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.
 
@@ -2199,6 +2196,11 @@
 Do not allow data to be cached from a remote server for this
 mount.
 
+ at item nocasetrans
+ at cindex Mount flags; nocasetrans
+Don't do case translation. Useful for CD-ROMS formatted as
+ISO-9660.
+
 @item noconn
 @cindex Mount flags; noconn
 Don't make a connection on datagram transports.
@@ -2226,6 +2228,10 @@
 @cindex Mount flags; noint
 Do not allow keyboard interrupts for this mount
 
+ at item nojoliet
+ at cindex Mount flags; nojoliet
+Turn off the Joliet extensions.  Useful for CD-ROMS formatted as ISO-9660.
+
 @item nolock
 @cindex Mount flags; nolock
 Do not use the NFS locking protocol
@@ -2320,6 +2326,11 @@
 @cindex Mount flags; retry
 Set the NFS retry counter.
 
+ at item rrcaseins
+ at cindex Mount flags; rrcaseins
+Enable the Rock Ridge Interchange Protocol (RRIP) case insensitive extensions.
+Useful for CD-ROMS formatted as ISO-9660.
+
 @item rrip
 @cindex Mount flags; rrip
 Uses the Rock Ridge Interchange Protocol (RRIP) extensions to ISO-9660.
@@ -2333,6 +2344,10 @@
 @cindex Mount flags; rw
 Allow reads and writes on this filesystem.
 
+ at item sessionnr=@var{n}
+ at cindex Mount Flags; sessionnr
+For multisession UDF mounts, use session number @var{n} when mounting.
+
 @item shortname
 @cindex Mount Flags; longname
 For PCFS mounts, force old DOS short names only.
@@ -2368,8 +2383,8 @@
 
 @item user=@var{n}
 @cindex Mount flags; user
-For PCFS mounts, set the owner of the files in the file system to
- at var{n} (which can either be a user name or a UID number).  The
+For PCFS and UDF 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.
 
@@ -2824,13 +2839,13 @@
 Copyright (c) 1990 Imperial College of Science, Technology & Medicine
 Copyright (c) 1990 The Regents of the University of California.
 am-utils version 6.0a15 (build 61).
-Built by ezk@@cs.columbia.edu on date Wed Oct 22 15:21:03 EDT 1997.
+Built by ezk@@example.com on date Wed Oct 22 15:21:03 EDT 1997.
 cpu=sparc (big-endian), arch=sun4, karch=sun4u.
 full_os=solaris2.5.1, os=sos5, osver=5.5.1, vendor=sun.
 Map support for: root, passwd, union, nisplus, nis, ndbm, file, error.
 AMFS: nfs, link, nfsx, nfsl, host, linkx, program, union, inherit,
       ufs, lofs, hsfs, pcfs, auto, direct, toplvl, error.
-FS: autofs, cachefs, cdfs, lofs, nfs, nfs3, pcfs, tfs, tmpfs, ufs.
+FS: autofs, cachefs, cdfs, lofs, nfs, nfs3, pcfs, tfs, tmpfs, udf, ufs.
 Network 1: wire="mcl-lab-net.cs.columbia.edu" (netnumber=128.59.13).
 Network 2: wire="14-net.cs.columbia.edu" (netnumber=128.59.14).
 Network 3: wire="old-net.cs.columbia.edu" (netnumber=128.59.16).
@@ -2879,9 +2894,9 @@
 
 @table @code
 @item fatal
-Fatal errors
+Fatal errors (cannot be turned off)
 @item error
-Non-fatal errors
+Non-fatal errors (cannot be turned off)
 @item user
 Non-fatal user errors
 @item warn
@@ -2896,10 +2911,15 @@
 Additional statistics
 @item all
 All of the above
+ at item defaults
+An alias for "fatal,error,user,warning,info".
 @end table
 
 Initially a set of default logging flags is enabled.  This is as if
- at samp{-x all,nomap,nostats} had been selected.  The command line is
+ at samp{-x defaults}
+or
+ at samp{-x fatal,error,user,warning,info}
+had been selected.  The command line is
 parsed and logging is controlled by the @code{-x} option.  The very first
 set of logging flags is saved and can not be subsequently disabled using
 @i{Amq}.  This default set of options is useful for general production
@@ -2932,7 +2952,6 @@
 @samp{LOG_INFO}
 @end table
 
-
 The options can be prefixed by the string @samp{no} to indicate
 that this option should be turned off.  For example, to obtain all
 but @samp{info} messages the option @samp{-x all,noinfo} would be used.
@@ -3011,13 +3030,17 @@
 
 @table @code
 @item all
-all ``reasonable'' options (currently trace|str|full|mem|info|readdir)
+all options (excluding hrtime and mtab)
+ at item defaults
+``sensible'' default options (all--excluding hrtime, mtab, and xdrtrace)
+ at item test
+full debug options plus mtab,nodaemon,nofork,noamq
 @item amq
-do not register for amq
+register @i{Amd} with the RPC portmapper, for @i{Amq}
 @item daemon
-do not enter daemon mode
+enter daemon mode
 @item fork
-do not fork child worker (hlfsd only)
+fork child worker (hlfsd only)
 @item full
 program trace
 @item hrtime
@@ -3028,16 +3051,14 @@
 info service specific debugging (hesiod, nis, etc.)  In the case of
 hesiod maps, turns on the hesiod RES_DEBUG internal debugging option.
 @item mem
-trace memory allocations. Needs to be explicitly enabled at compile
+trace memory allocations.  Needs to be explicitly enabled at compile
 time with --enable-debug=mem.
 @item mtab
-use local @file{./mtab} file
+use local mount-table file (defaults to @file{/tmp/mtab}, @pxref{debug_mtab_file Parameter})
 @item readdir
 show readdir progress
 @item str
 debug string munging
- at item test
-full debug but no daemon
 @item trace
 trace RPC protocol and NFS mount arguments
 @item xdrtrace
@@ -3150,6 +3171,7 @@
 * Unix Filesystem::             Native disk filesystem.
 * Caching Filesystem::          Caching from remote server filesystem.
 * CD-ROM Filesystem::           ISO9660 CD ROM.
+* UDF Filesystem::              Universal Disk Format filesystem.
 * Loopback Filesystem::         Local loopback-mount filesystem.
 * Memory/RAM Filesystem::       A memory or RAM-based filesystem.
 * Null Filesystem::             4.4BSD's loopback-mount filesystem.
@@ -3475,7 +3497,7 @@
 @end enumerate
 
 @c ----------------------------------------------------------------
- at node CD-ROM Filesystem, Loopback Filesystem, Caching Filesystem, Filesystem Types
+ at node CD-ROM Filesystem, UDF Filesystem, Caching Filesystem, Filesystem Types
 @comment  node-name,  next,  previous,  up
 @section CD-ROM Filesystem (@samp{cdfs})
 @cindex CD-ROM Filesystem
@@ -3504,8 +3526,37 @@
 @end example
 
 @c ----------------------------------------------------------------
- at node Loopback Filesystem, Memory/RAM Filesystem, CD-ROM Filesystem, Filesystem Types
+ at node UDF Filesystem, Loopback Filesystem, CD-ROM Filesystem, Filesystem Types
 @comment  node-name,  next,  previous,  up
+ at section CD-ROM Filesystem (@samp{udf})
+ at cindex CD-ROM Filesystem
+ at cindex udf, filesystem type
+ at cindex Filesystem type; udf
+
+The @dfn{udf} (@samp{type:=udf}) filesystem mounts media with a
+Universal Disk Format (UDF) filesystem on it, e.g., a video DVD.
+
+ at noindent
+The following option must be specified:
+
+ at table @code
+ at cindex dev, mount option
+ at cindex Mount option; dev
+ at item dev
+the block special device to be mounted.
+ at end table
+
+Some operating systems will fail to mount read-only media unless the
+ at samp{ro} option is specified.  A udf entry might be:
+
+ at example
+udf      os==sunos4;type:=udf;dev:=/dev/sr0 \
+         os==sunos5;addopts:=ro;type:=udf;dev:=/dev/dsk/c0t6d0s2
+ at end example
+
+ at c ----------------------------------------------------------------
+ at node Loopback Filesystem, Memory/RAM Filesystem, UDF Filesystem, Filesystem Types
+ at comment  node-name,  next,  previous,  up
 @section Loopback Filesystem (@samp{lofs})
 @cindex Loopback Filesystem
 @cindex lofs, filesystem type
@@ -4203,6 +4254,7 @@
 * mount_type Parameter::
 * search_path Parameter::
 * selectors_in_defaults Parameter::
+* sun_map_syntax Parameter::
 @end menu
 
 @c ----------------------------------------------------------------
@@ -4326,7 +4378,7 @@
 distributed maps in several locations as needed.
 
 @c ----------------------------------------------------------------
- at node selectors_in_defaults Parameter, , search_path Parameter, Common Parameters
+ at node selectors_in_defaults Parameter, sun_map_syntax Parameter, search_path Parameter, Common Parameters
 @comment  node-name,  next,  previous,  up
 @subsection @t{selectors_in_defaults} Parameter
 @cindex selectors_in_defaults Parameter
@@ -4346,7 +4398,16 @@
 
 Deprecated form: selectors_on_default.
 
+ at c ----------------------------------------------------------------
+ at node sun_map_syntax Parameter, , selectors_in_defaults Parameter, Common Parameters
+ at comment  node-name,  next,  previous,  up
+ at subsection @t{sun_map_syntax} Parameter
+ at cindex sun_map_syntax Parameter
 
+(type=boolean, default=@samp{no}).  If @samp{yes}, then @i{Amd} will
+parse the map according to the Sun Automount syntax.
+
+
 @c ================================================================
 @node Global Parameters, Regular Map Parameters, Common Parameters, Amd Configuration File
 @comment  node-name,  next,  previous,  up
@@ -4527,14 +4588,14 @@
 (type=string, default no cluster).  Same as the @code{-C} option to
 @i{Amd}.  Specifies the alternate HP-UX cluster to use.
 
- at c ---------------------------------------------------------------- 
- at node debug_mtab_file Parameter, debug_options Parameter, cluster Parameter, Global Parameters 
- at comment  node-name,  next,  previous,  up 
- at subsection @t{debug_mtab_file} Parameter 
- at cindex debug_mtab_file Parameter 
+ at c ----------------------------------------------------------------
+ at node debug_mtab_file Parameter, debug_options Parameter, cluster Parameter, Global Parameters
+ at comment  node-name,  next,  previous,  up
+ at subsection @t{debug_mtab_file} Parameter
+ at 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.  
+(type=string, default="/tmp/mtab").  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 ----------------------------------------------------------------
@@ -4774,7 +4835,7 @@
 @subsection @t{log_options} Parameter
 @cindex log_options Parameter
 
-(type=string, default no logging options).  Same as the @code{-x}
+(type=string, default=``defaults'').  Same as the @code{-x}
 option to @i{Amd}.  Specify any logging options for @i{Amd}.  Options
 are comma delimited, and can be preceded by the string @samp{no} to
 negate their meaning.  The @samp{debug} logging option is only available
@@ -4785,12 +4846,14 @@
 @table @samp
 @item all
 all messages
+ at item defaults
+an alias for "fatal,error,user,warning,info"
 @item debug
 debug messages
 @item error
-non-fatal system errors
+non-fatal system errors (cannot be turned off)
 @item fatal
-fatal errors
+fatal errors (cannot be turned off)
 @item info
 information
 @item map
@@ -5271,7 +5334,7 @@
 auto_dir =               /n
 log_file =               /var/log/amd
 log_options =            all
-#debug_options =         all
+#debug_options =         defaults
 plock =                  no
 selectors_in_defaults =  yes
 # config.guess picks up "sunos5" and I don't want to edit my maps yet
@@ -5436,6 +5499,7 @@
 * Amq -m option::     Obtaining mount statistics.
 * Amq -p option::     Getting Amd's process ID.
 * Amq -P option::     Contacting alternate Amd processes.
+* Amq -q option::     Suppress synchronous unmounting errors.
 * Amq -s option::     Obtaining global statistics.
 * Amq -T option::     Use TCP transport.
 * Amq -U option::     Use UDP transport.
@@ -5641,7 +5705,7 @@
 used in the @file{ctl-amd} script.
 
 @c ----------------------------------------------------------------
- at node Amq -P option, Amq -s option, Amq -p option, Controlling Amd
+ at node Amq -P option, Amq -q option, Amq -p option, Controlling Amd
 @comment  node-name,  next,  previous,  up
 @subsection @i{Amq} @code{-P} option
 @cindex Multiple Amd processes
@@ -5664,8 +5728,17 @@
 @end example
 
 @c ----------------------------------------------------------------
- at node Amq -s option, Amq -T option, Amq -P option, Controlling Amd
+ at node Amq -q option, Amq -s option, Amq -P option, Controlling Amd
 @comment  node-name,  next,  previous,  up
+ at subsection @i{Amq} @code{-q} option
+ at cindex Unmounting a filesystem
+
+Suppress any error messages produced when a synchronous unmount fails.
+See @ref{Amq -u option}.
+
+ at c ----------------------------------------------------------------
+ at node Amq -s option, Amq -T option, Amq -q option, Controlling Amd
+ at comment  node-name,  next,  previous,  up
 @subsection @i{Amq} @code{-s} option
 @cindex Global statistics
 @cindex Statistics
@@ -5729,12 +5802,20 @@
 @cindex Forcing filesystem to time out
 @cindex Unmounting a filesystem
 
-The @code{-u} option causes the time-to-live interval of the named mount
-points to be expired, thus causing an unmount attempt.  This is the only
-safe way to unmount an automounted filesystem.  It is not possible to
-unmount a filesystem which has been mounted with the @samp{nounmount}
-flag.
+The @code{-u} option causes the time-to-live interval of the named
+mount points to be expired, thus causing an unmount attempt.  This is
+the only safe way to unmount an automounted filesystem.  If @code{-u}
+is repeated, then @i{Amd} will attempt to unmount the filesystem
+synchronously.  This makes things like
 
+ at example
+amq -uu /t/cd0d && eject cd0
+ at end example
+
+ at noindent
+work as expected.  Any error messages this might produce can be
+suppressed with the @code{-q} option.  See @ref{Amq -q option}.
+
 @c The @code{-H} option informs @i{Amd} that the specified mount point
 @c has hung - as if its keepalive timer had expired.
 
@@ -5769,11 +5850,10 @@
 @code{-D} options have exactly the same effect as @i{Amd}'s corresponding
 command line options.
 
-When @i{Amd} receives a @code{-x} flag it limits the log options being
-modified to those which were not enabled at startup.  This prevents a
-user turning @emph{off} any logging option which was specified at
-startup, though any which have been turned on since then can still be
-turned off.  The @code{-D} option has a similar behavior.
+When @i{Amd} receives the @code{-x} flag, it disallows turning off the
+ at samp{fatal} or @samp{error} flags.  Both are on by default.  They are
+mandatory so that @i{Amd} could report important errors, including
+errors relating to turning flags on/off.
 
 @c ################################################################
 @node FSinfo, Hlfsd, Run-time Administration, Top
@@ -6904,8 +6984,8 @@
 on the user which accessed that link.  It was primarily designed to
 redirect incoming mail to users' home directories, so that it can be read
 from anywhere.  It was designed and implemented by
- at email{ezk@@cs.columbia.edu,Erez Zadok} and
- at email{dupuy@@cs.columbia.edu,Alexander Dupuy}, at the
+ at uref{http://www.cs.sunysb.edu/~ezk,Erez Zadok} and
+ at email{dupuy AT cs.columbia.edu,Alexander Dupuy}, at the
 @uref{http://www.cs.columbia.edu/,Computer Science Department} of
 @uref{http://www.columbia.edu/,Columbia University}.  A
 @uref{http://www.fsl.cs.sunysb.edu/docs/hlfsd/hlfsd.html,paper}
@@ -7522,7 +7602,6 @@
 * automount2amd::
 * ctl-amd::
 * ctl-hlfsd::
-* expn::
 * fix-amd-map::
 * fixmount::
 * fixrmtab::
@@ -7649,7 +7728,7 @@
 @xref{Run-time Administration}, for more details.
 
 @c ----------------------------------------------------------------
- at node ctl-hlfsd, expn, ctl-amd, Assorted Tools
+ at node ctl-hlfsd, fix-amd-map, ctl-amd, Assorted Tools
 @comment  node-name,  next,  previous,  up
 @section ctl-hlfsd
 @pindex ctl-hlfsd
@@ -7671,28 +7750,8 @@
 @xref{Hlfsd}, for more details.
 
 @c ----------------------------------------------------------------
- at node expn, fix-amd-map, ctl-hlfsd, Assorted Tools
+ at node fix-amd-map, fixmount, ctl-hlfsd, Assorted Tools
 @comment  node-name,  next,  previous,  up
- at section expn
- at pindex expn
-
-A script to expand email addresses into their full name.  It is
-generally useful when using with the @file{lostaltmail} script, but is a
-useful tools otherwise.
-
- at example
-$ expn -v ezk@@cs.columbia.edu
-ezk@@cs.columbia.edu ->
-        ezk@@shekel.mcl.cs.columbia.edu
-ezk@@shekel.mcl.cs.columbia.edu ->
-        Erez Zadok <"| /usr/local/mh/lib/slocal -user ezk || exit 75>
-        Erez Zadok <\ezk>
-        Erez Zadok </u/zing/ezk/.mailspool/backup>
- at end example
-
- at c ----------------------------------------------------------------
- at node fix-amd-map, fixmount, expn, Assorted Tools
- at comment  node-name,  next,  previous,  up
 @section fix-amd-map
 @pindex fix-amd-map
 
@@ -8581,7 +8640,7 @@
 @comment  node-name,  next,  previous,  up
 @unnumbered Acknowledgments & Trademarks
 
-Many thanks to the @email{am-utils@@am-utils.org,Am-Utils Users}
+Many thanks to the 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
@@ -8589,10 +8648,10 @@
 submitted patches, and especially to the maintainers:
 
 @itemize @bullet
- at item @email{ezk@@cs.sunysb.edu,Erez Zadok}
- at item @email{ib42@@cs.columbia.edu,Ion Badulescu}
- at item @email{ro@@techfak.uni-bielefeld.de,Rainer Orth}
- at item @email{nick.williams@@morganstanley.com,Nick Williams}
+ at item @uref{http://www.cs.sunysb.edu/~ezk,Erez Zadok}
+ at item @email{ionut AT badula.org,Ion Badulescu}
+ at item @email{ro AT techfak.uni-bielefeld.de,Rainer Orth}
+ at item @email{nick.williams AT morganstanley.com,Nick Williams}
 @end itemize
 
 Thanks to the Formal Methods Group at Imperial College for suffering
@@ -8602,7 +8661,7 @@
 @i{Amd}, especially Piete Brooks at the Cambridge University Computing
 Lab for many hours of testing, experimentation and discussion.
 
-Thanks to the older @email{amd-workers@@majordomo.glue.umd.edu,Amd
+Thanks to the older @email{amd-workers AT majordomo.glue.umd.edu,Amd
 Workers} mailing list (now defunct) members for many suggestions and
 bug reports to @i{Amd}.
 

Modified: trunk/contrib/amd/doc/stamp-vti
===================================================================
--- trunk/contrib/amd/doc/stamp-vti	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/doc/stamp-vti	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,4 +1,4 @@
- at set UPDATED 20 April 2006
- at set UPDATED-MONTH April 2006
- at set EDITION 6.1.5
- at set VERSION 6.1.5
+ at set UPDATED 28 October 2014
+ at set UPDATED-MONTH October 2014
+ at set EDITION 6.2
+ at set VERSION 6.2

Modified: trunk/contrib/amd/doc/texinfo.tex
===================================================================
--- trunk/contrib/amd/doc/texinfo.tex	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/doc/texinfo.tex	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,18 +1,18 @@
 % texinfo.tex -- TeX macros to handle Texinfo files.
-%
+% 
 % Load plain if necessary, i.e., if running under initex.
 \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
 %
-\def\texinfoversion{2004-09-06.16}
+\def\texinfoversion{2013-02-01.11}
 %
-% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
-% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
-% Foundation, Inc.
+% Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
+% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+% 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
 %
-% This texinfo.tex file is free software; you can redistribute it and/or
+% This texinfo.tex file is free software: you can redistribute it and/or
 % modify it under the terms of the GNU General Public License as
-% published by the Free Software Foundation; either version 2, or (at
-% your option) any later version.
+% published by the Free Software Foundation, either version 3 of the
+% License, or (at your option) any later version.
 %
 % This texinfo.tex file is distributed in the hope that it will be
 % useful, but WITHOUT ANY WARRANTY; without even the implied warranty
@@ -20,19 +20,18 @@
 % General Public License for more details.
 %
 % You should have received a copy of the GNU General Public License
-% along with this texinfo.tex file; see the file COPYING.  If not, write
-% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-% Boston, MA 02111-1307, USA.
+% along with this program.  If not, see <http://www.gnu.org/licenses/>.
 %
 % 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.)
+% restriction. This Exception is an additional permission under section 7
+% of the GNU General Public License, version 3 ("GPLv3").
 %
 % Please try the latest version of texinfo.tex before submitting bug
 % reports; you can get the latest version from:
-%   http://www.gnu.org/software/texinfo/ (the Texinfo home page), or
-%   ftp://tug.org/tex/texinfo.tex
-%     (and all CTAN mirrors, see http://www.ctan.org).
+%   http://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or
+%   http://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or
+%   http://www.gnu.org/software/texinfo/ (the Texinfo home page)
 % The texinfo.tex in any given distribution could well be out
 % of date, so if that's what you're using, please check.
 %
@@ -67,7 +66,6 @@
 \everyjob{\message{[Texinfo version \texinfoversion]}%
   \catcode`+=\active \catcode`\_=\active}
 
-\message{Basics,}
 \chardef\other=12
 
 % We never want plain's \outer definition of \+ in Texinfo.
@@ -89,15 +87,19 @@
 \let\ptexhat=^
 \let\ptexi=\i
 \let\ptexindent=\indent
-\let\ptexnoindent=\noindent
 \let\ptexinsert=\insert
 \let\ptexlbrace=\{
 \let\ptexless=<
+\let\ptexnewwrite\newwrite
+\let\ptexnoindent=\noindent
 \let\ptexplus=+
+\let\ptexraggedright=\raggedright
 \let\ptexrbrace=\}
 \let\ptexslash=\/
 \let\ptexstar=\*
 \let\ptext=\t
+\let\ptextop=\top
+{\catcode`\'=\active \global\let\ptexquoteright'}% active in plain's math mode
 
 % If this character appears in an error message or help string, it
 % starts a new line in the output.
@@ -115,10 +117,11 @@
 % 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\putworderror\undefined     \gdef\putworderror{error}\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\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
@@ -152,20 +155,25 @@
 \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.
+% Since the category of space is not known, we have to be careful.
+\chardef\spacecat = 10
+\def\spaceisspace{\catcode`\ =\spacecat}
+
+% sometimes characters are active, so we need control sequences.
+\chardef\ampChar   = `\&
 \chardef\colonChar = `\:
 \chardef\commaChar = `\,
+\chardef\dashChar  = `\-
 \chardef\dotChar   = `\.
 \chardef\exclamChar= `\!
+\chardef\hashChar  = `\#
+\chardef\lquoteChar= `\`
 \chardef\questChar = `\?
+\chardef\rquoteChar= `\'
 \chardef\semiChar  = `\;
+\chardef\slashChar = `\/
 \chardef\underChar = `\_
 
-\chardef\spaceChar = `\ %
-\chardef\spacecat = 10
-\def\spaceisspace{\catcode\spaceChar=\spacecat}
-
 % Ignore a token.
 %
 \def\gobble#1{}
@@ -194,37 +202,8 @@
 % that mark overfull boxes (in case you have decided
 % that the text looks ok even though it passes the margin).
 %
-\def\finalout{\overfullrule=0pt}
+\def\finalout{\overfullrule=0pt }
 
-% @| inserts a changebar to the left of the current line.  It should
-% surround any changed text.  This approach does *not* work if the
-% change spans more than two lines of output.  To handle that, we would
-% have adopt a much more difficult approach (putting marks into the main
-% vertical list for the beginning and end of each change).
-%
-\def\|{%
-  % \vadjust can only be used in horizontal mode.
-  \leavevmode
-  %
-  % Append this vertical mode material after the current line in the output.
-  \vadjust{%
-    % We want to insert a rule with the height and depth of the current
-    % leading; that is exactly what \strutbox is supposed to record.
-    \vskip-\baselineskip
-    %
-    % \vadjust-items are inserted at the left edge of the type.  So
-    % the \llap here moves out into the left-hand margin.
-    \llap{%
-      %
-      % For a thicker or thinner bar, change the `1pt'.
-      \vrule height\baselineskip width1pt
-      %
-      % This is the space between the bar and the text.
-      \hskip 12pt
-    }%
-  }%
-}
-
 % Sometimes it is convenient to have everything in the transcript file
 % and nothing on the terminal.  We don't just call \tracingall here,
 % since that produces some useless output on the terminal.  We also make
@@ -241,7 +220,7 @@
   \tracingmacros2
   \tracingrestores1
   \showboxbreadth\maxdimen \showboxdepth\maxdimen
-  \ifx\eTeXversion\undefined\else % etex gives us more logging
+  \ifx\eTeXversion\thisisundefined\else % etex gives us more logging
     \tracingscantokens1
     \tracingifs1
     \tracinggroups1
@@ -252,6 +231,13 @@
   \errorcontextlines16
 }%
 
+% @errormsg{MSG}.  Do the index-like expansions on MSG, but if things
+% aren't perfect, it's not the end of the world, being an error message,
+% after all.
+% 
+\def\errormsg{\begingroup \indexnofonts \doerrormsg}
+\def\doerrormsg#1{\errmessage{#1}}
+
 % 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.
 %
@@ -262,7 +248,6 @@
 \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
@@ -276,6 +261,50 @@
 \newdimen\cornerthick \cornerthick=.3pt
 \newdimen\topandbottommargin \topandbottommargin=.75in
 
+% Output a mark which sets \thischapter, \thissection and \thiscolor.
+% We dump everything together because we only have one kind of mark.
+% This works because we only use \botmark / \topmark, not \firstmark.
+%
+% A mark contains a subexpression of the \ifcase ... \fi construct.
+% \get*marks macros below extract the needed part using \ifcase.
+%
+% Another complication is to let the user choose whether \thischapter
+% (\thissection) refers to the chapter (section) in effect at the top
+% of a page, or that at the bottom of a page.  The solution is
+% described on page 260 of The TeXbook.  It involves outputting two
+% marks for the sectioning macros, one before the section break, and
+% one after.  I won't pretend I can describe this better than DEK...
+\def\domark{%
+  \toks0=\expandafter{\lastchapterdefs}%
+  \toks2=\expandafter{\lastsectiondefs}%
+  \toks4=\expandafter{\prevchapterdefs}%
+  \toks6=\expandafter{\prevsectiondefs}%
+  \toks8=\expandafter{\lastcolordefs}%
+  \mark{%
+                   \the\toks0 \the\toks2
+      \noexpand\or \the\toks4 \the\toks6
+    \noexpand\else \the\toks8
+  }%
+}
+% \topmark doesn't work for the very first chapter (after the title
+% page or the contents), so we use \firstmark there -- this gets us
+% the mark with the chapter defs, unless the user sneaks in, e.g.,
+% @setcolor (or @url, or @link, etc.) between @contents and the very
+% first @chapter.
+\def\gettopheadingmarks{%
+  \ifcase0\topmark\fi
+  \ifx\thischapter\empty \ifcase0\firstmark\fi \fi
+}
+\def\getbottomheadingmarks{\ifcase1\botmark\fi}
+\def\getcolormarks{\ifcase2\topmark\fi}
+
+% Avoid "undefined control sequence" errors.
+\def\lastchapterdefs{}
+\def\lastsectiondefs{}
+\def\prevchapterdefs{}
+\def\prevsectiondefs{}
+\def\lastcolordefs{}
+
 % Main output routine.
 \chardef\PAGE = 255
 \output = {\onepageout{\pagecontents\PAGE}}
@@ -293,7 +322,9 @@
   %
   % Do this outside of the \shipout so @code etc. will be expanded in
   % the headline as they should be, not taken literally (outputting ''code).
+  \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi
   \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+  \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi
   \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
   %
   {%
@@ -301,10 +332,14 @@
     % take effect in \write's, yet the group defined by the \vbox ends
     % before the \shipout runs.
     %
-    \escapechar = `\\     % use backslash in output files.
     \indexdummies         % don't expand commands in the output.
     \normalturnoffactive  % \ in index entries must not stay \, e.g., if
-                   % the page break happens to be in the middle of an example.
+               % the page break happens to be in the middle of an example.
+               % We don't want .vr (or whatever) entries like this:
+               % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}}
+               % "\acronym" won't work when it's read back in;
+               % it needs to be
+               % {\code {{\tt \backslashcurfont }acronym}
     \shipout\vbox{%
       % Do this early so pdf references go to the beginning of the page.
       \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi
@@ -332,9 +367,9 @@
       \pagebody{#1}%
       \ifdim\ht\footlinebox > 0pt
         % Only leave this space if the footline is nonempty.
-        % (We lessened \vsize for it in \oddfootingxxx.)
+        % (We lessened \vsize for it in \oddfootingyyy.)
         % The \baselineskip=24pt in plain's \makefootline has no effect.
-        \vskip 2\baselineskip
+        \vskip 24pt
         \unvbox\footlinebox
       \fi
       %
@@ -355,7 +390,7 @@
       \egroup % \vbox from first cropmarks clause
       \fi
     }% end of \shipout\vbox
-  }% end of group with \normalturnoffactive
+  }% end of group with \indexdummies
   \advancepageno
   \ifnum\outputpenalty>-20000 \else\dosupereject\fi
 }
@@ -368,7 +403,7 @@
 % marginal hacks, juha at viisa.uucp (Juha Takala)
 \ifvoid\margin\else % marginal info is present
   \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
-\dimen@=\dp#1 \unvbox#1
+\dimen@=\dp#1\relax \unvbox#1\relax
 \ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
 \ifr at ggedbottom \kern-\dimen@ \vfil \fi}
 }
@@ -390,7 +425,7 @@
 %
 \def\parsearg{\parseargusing{}}
 \def\parseargusing#1#2{%
-  \def\next{#2}%
+  \def\argtorun{#2}%
   \begingroup
     \obeylines
     \spaceisspace
@@ -409,7 +444,7 @@
 \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm}
 \def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm}
 
-% Each occurence of `\^^M' or `<space>\^^M' is replaced by a single space.
+% Each occurrence of `\^^M' or `<space>\^^M' is replaced by a single space.
 %
 % \argremovec might leave us with trailing space, e.g.,
 %    @end itemize  @c foo
@@ -421,8 +456,7 @@
 \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.
+    % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp:
     \let\temp\finishparsearg
   \else
     \let\temp\argcheckspaces
@@ -434,14 +468,14 @@
 % 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
+% just before passing the control to \argtorun.
+% (Similarly, we have to think about #3 of \argcheckspacesY above: it is
 % either the null string, or it ends with \^^M---thus there is no danger
 % that a pair of braces would be stripped.
 %
 % But first, we have to remove the trailing space token.
 %
-\def\finishparsearg#1 \ArgTerm{\expandafter\next\expandafter{#1}}
+\def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}}
 
 % \parseargdef\foo{...}
 %	is roughly equivalent to
@@ -492,12 +526,12 @@
 % 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
+% are not treated as environments; they don't open a group.  (The
 % implementation of @end takes care not to call \endgroup in this
 % special case.)
 
 
-% At runtime, environments start with this:
+% At run-time, environments start with this:
 \def\startenvironment#1{\begingroup\def\thisenv{#1}}
 % initialize
 \let\thisenv\empty
@@ -515,7 +549,7 @@
   \fi
 }
 
-% Evironment mismatch, #1 expected:
+% Environment mismatch, #1 expected:
 \def\badenverr{%
   \errhelp = \EMsimple
   \errmessage{This command can appear only \inenvironment\temp,
@@ -523,7 +557,7 @@
 }
 \def\inenvironment#1{%
   \ifx#1\empty
-    out of any environment%
+    outside of any environment%
   \else
     in environment \expandafter\string#1%
   \fi
@@ -535,7 +569,7 @@
 \parseargdef\end{%
   \if 1\csname iscond.#1\endcsname
   \else
-    % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03
+    % The general wording of \badenverr may not be ideal.
     \expandafter\checkenv\csname#1\endcsname
     \csname E#1\endcsname
     \endgroup
@@ -545,85 +579,6 @@
 \newhelp\EMsimple{Press RETURN to continue.}
 
 
-%% Simple single-character @ commands
-
-% @@ prints an @
-% Kludge this until the fonts are right (grr).
-\def\@{{\tt\char64}}
-
-% This is turned off because it was never documented
-% and you can use @w{...} around a quote to suppress ligatures.
-%% Define @` and @' to be the same as ` and '
-%% but suppressing ligatures.
-%\def\`{{`}}
-%\def\'{{'}}
-
-% Used to generate quoted braces.
-\def\mylbrace {{\tt\char123}}
-\def\myrbrace {{\tt\char125}}
-\let\{=\mylbrace
-\let\}=\myrbrace
-\begingroup
-  % Definitions to produce \{ and \} commands for indices,
-  % and @{ and @} for the aux file.
-  \catcode`\{ = \other \catcode`\} = \other
-  \catcode`\[ = 1 \catcode`\] = 2
-  \catcode`\! = 0 \catcode`\\ = \other
-  !gdef!lbracecmd[\{]%
-  !gdef!rbracecmd[\}]%
-  !gdef!lbraceatcmd[@{]%
-  !gdef!rbraceatcmd[@}]%
-!endgroup
-
-% @comma{} to avoid , parsing problems.
-\let\comma = ,
-
-% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
-% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
-\let\, = \c
-\let\dotaccent = \.
-\def\ringaccent#1{{\accent23 #1}}
-\let\tieaccent = \t
-\let\ubaraccent = \b
-\let\udotaccent = \d
-
-% Other special characters: @questiondown @exclamdown @ordf @ordm
-% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
-\def\questiondown{?`}
-\def\exclamdown{!`}
-\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}}
-\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}}
-
-% Dotless i and dotless j, used for accents.
-\def\imacro{i}
-\def\jmacro{j}
-\def\dotless#1{%
-  \def\temp{#1}%
-  \ifx\temp\imacro \ptexi
-  \else\ifx\temp\jmacro \j
-  \else \errmessage{@dotless can be used only with i or j}%
-  \fi\fi
-}
-
-% The \TeX{} logo, as in plain, but resetting the spacing so that a
-% period following counts as ending a sentence.  (Idea found in latex.)
-%
-\edef\TeX{\TeX \spacefactor=1000 }
-
-% @LaTeX{} logo.  Not quite the same results as the definition in
-% latex.ltx, since we use a different font for the raised A; it's most
-% convenient for us to use an explicitly smaller font, rather than using
-% the \scriptstyle font (since we don't reset \scriptstyle and
-% \scriptscriptstyle).
-%
-\def\LaTeX{%
-  L\kern-.36em
-  {\setbox0=\hbox{T}%
-   \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}%
-  \kern-.15em
-  \TeX
-}
-
 % Be sure we're in horizontal mode when doing a tie, since we make space
 % equivalent to this in @example-like environments. Otherwise, a space
 % at the beginning of a line will start with \penalty -- and
@@ -640,20 +595,35 @@
 \def\:{\spacefactor=1000 }
 
 % @* forces a line break.
-\def\*{\hfil\break\hbox{}\ignorespaces}
+\def\*{\unskip\hfil\break\hbox{}\ignorespaces}
 
 % @/ allows a line break.
 \let\/=\allowbreak
 
 % @. is an end-of-sentence period.
-\def\.{.\spacefactor=3000 }
+\def\.{.\spacefactor=\endofsentencespacefactor\space}
 
 % @! is an end-of-sentence bang.
-\def\!{!\spacefactor=3000 }
+\def\!{!\spacefactor=\endofsentencespacefactor\space}
 
 % @? is an end-of-sentence query.
-\def\?{?\spacefactor=3000 }
+\def\?{?\spacefactor=\endofsentencespacefactor\space}
 
+% @frenchspacing on|off  says whether to put extra space after punctuation.
+%
+\def\onword{on}
+\def\offword{off}
+%
+\parseargdef\frenchspacing{%
+  \def\temp{#1}%
+  \ifx\temp\onword \plainfrenchspacing
+  \else\ifx\temp\offword \plainnonfrenchspacing
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @frenchspacing option `\temp', must be on|off}%
+  \fi\fi
+}
+
 % @w prevents a word break.  Without the \leavevmode, @w at the
 % beginning of a paragraph, when TeX is still in vertical mode, would
 % produce a whole line of output instead of starting the paragraph.
@@ -732,15 +702,6 @@
 
 \newdimen\mil  \mil=0.001in
 
-% Old definition--didn't work.
-%\parseargdef\need{\par %
-%% This method tries to make TeX break the page naturally
-%% if the depth of the box does not fit.
-%{\baselineskip=0pt%
-%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
-%\prevdepth=-1000pt
-%}}
-
 \parseargdef\need{%
   % Ensure vertical mode, so we don't make a big box in the middle of a
   % paragraph.
@@ -804,7 +765,7 @@
 
 % @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'.
+% class.  WHICH is `l' or `r'.  Not documented, written for gawk manual.
 %
 \newskip\inmarginspacing \inmarginspacing=1cm
 \def\strutdepth{\dp\strutbox}
@@ -851,15 +812,51 @@
   \temp
 }
 
-% @include file    insert text of that file as input.
+% @| 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 command
+% is not documented, not supported, and doesn't work.
 %
+\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
+    }%
+  }%
+}
+
+% @include FILE -- \input text of FILE.
+%
 \def\include{\parseargusing\filenamecatcodes\includezzz}
 \def\includezzz#1{%
   \pushthisfilestack
   \def\thisfile{#1}%
   {%
-    \makevalueexpandable
-    \def\temp{\input #1 }%
+    \makevalueexpandable  % we want to expand any @value in FILE.
+    \turnoffactive        % and allow special characters in the expansion
+    \indexnofonts         % Allow `@@' and other weird things in file names.
+    \wlog{texinfo.tex: doing @include of #1^^J}%
+    \edef\temp{\noexpand\input #1 }%
+    %
+    % This trickery is to read FILE outside of a group, in case it makes
+    % definitions, etc.
     \expandafter
   }\temp
   \popthisfilestack
@@ -874,6 +871,8 @@
   \catcode`>=\other
   \catcode`+=\other
   \catcode`-=\other
+  \catcode`\`=\other
+  \catcode`\'=\other
 }
 
 \def\pushthisfilestack{%
@@ -889,7 +888,7 @@
 \def\popthisfilestack{\errthisfilestackempty}
 \def\errthisfilestackempty{\errmessage{Internal error:
   the stack of filenames is empty.}}
-
+%
 \def\thisfile{}
 
 % @center line
@@ -897,36 +896,46 @@
 %
 \parseargdef\center{%
   \ifhmode
-    \let\next\centerH
+    \let\centersub\centerH
   \else
-    \let\next\centerV
+    \let\centersub\centerV
   \fi
-  \next{\hfil \ignorespaces#1\unskip \hfil}%
+  \centersub{\hfil \ignorespaces#1\unskip \hfil}%
+  \let\centersub\relax % don't let the definition persist, just in case
 }
-\def\centerH#1{%
-  {%
-    \hfil\break
-    \advance\hsize by -\leftskip
-    \advance\hsize by -\rightskip
-    \line{#1}%
-    \break
-  }%
+\def\centerH#1{{%
+  \hfil\break
+  \advance\hsize by -\leftskip
+  \advance\hsize by -\rightskip
+  \line{#1}%
+  \break
+}}
+%
+\newcount\centerpenalty
+\def\centerV#1{%
+  % The idea here is the same as in \startdefun, \cartouche, etc.: if
+  % @center is the first thing after a section heading, we need to wipe
+  % out the negative parskip inserted by \sectionheading, but still
+  % prevent a page break here.
+  \centerpenalty = \lastpenalty
+  \ifnum\centerpenalty>10000 \vskip\parskip \fi
+  \ifnum\centerpenalty>9999 \penalty\centerpenalty \fi
+  \line{\kern\leftskip #1\kern\rightskip}%
 }
-\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}}
 
 % @sp n   outputs n lines of vertical space
-
+%
 \parseargdef\sp{\vskip #1\baselineskip}
 
 % @comment ...line which is ignored...
 % @c is the same as @comment
 % @ignore ... @end ignore  is another way to write a comment
-
+%
 \def\comment{\begingroup \catcode`\^^M=\other%
 \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
 \commentxxx}
 {\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}
-
+%
 \let\c=\comment
 
 % @paragraphindent NCHARS
@@ -1019,86 +1028,6 @@
 }
 
 
-% @asis just yields its argument.  Used with @table, for example.
-%
-\def\asis#1{#1}
-
-% @math outputs its argument in math mode.
-%
-% One complication: _ usually means subscripts, but it could also mean
-% an actual _ character, as in @math{@var{some_variable} + 1}.  So make
-% _ active, and distinguish by seeing if the current family is \slfam,
-% which is what @var uses.
-{
-  \catcode\underChar = \active
-  \gdef\mathunderscore{%
-    \catcode\underChar=\active
-    \def_{\ifnum\fam=\slfam \_\else\sb\fi}%
-  }
-}
-% Another complication: we want \\ (and @\) to output a \ character.
-% FYI, plain.tex uses \\ as a temporary control sequence (why?), but
-% this is not advertised and we don't care.  Texinfo does not
-% otherwise define @\.
-%
-% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\.
-\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi}
-%
-\def\math{%
-  \tex
-  \mathunderscore
-  \let\\ = \mathbackslash
-  \mathactive
-  $\finishmath
-}
-\def\finishmath#1{#1$\endgroup}  % Close the group opened by \tex.
-
-% Some active characters (such as <) are spaced differently in math.
-% We have to reset their definitions in case the @math was an argument
-% to a command which sets the catcodes (such as @item or @section).
-%
-{
-  \catcode`^ = \active
-  \catcode`< = \active
-  \catcode`> = \active
-  \catcode`+ = \active
-  \gdef\mathactive{%
-    \let^ = \ptexhat
-    \let< = \ptexless
-    \let> = \ptexgtr
-    \let+ = \ptexplus
-  }
-}
-
-% @bullet and @minus need the same treatment as @math, just above.
-\def\bullet{$\ptexbullet$}
-\def\minus{$-$}
-
-% @dots{} outputs an ellipsis using the current font.
-% We do .5em per period so that it has the same spacing in a typewriter
-% font as three actual period characters.
-%
-\def\dots{%
-  \leavevmode
-  \hbox to 1.5em{%
-    \hskip 0pt plus 0.25fil
-    .\hfil.\hfil.%
-    \hskip 0pt plus 0.5fil
-  }%
-}
-
-% @enddots{} is an end-of-sentence ellipsis.
-%
-\def\enddots{%
-  \dots
-  \spacefactor=3000
-}
-
-% @comma{} is so commas can be inserted into text without messing up
-% Texinfo's parsing.
-%
-\let\comma = ,
-
 % @refill is a no-op.
 \let\refill=\relax
 
@@ -1163,9 +1092,8 @@
 \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
+% can be set).  So we test for \relax and 0 as well as being undefined.
+\ifx\pdfoutput\thisisundefined
 \else
   \ifx\pdfoutput\relax
   \else
@@ -1175,14 +1103,120 @@
     \fi
   \fi
 \fi
-%
+
+% PDF uses PostScript string constants for the names of xref targets,
+% for display in the outlines, and in other places.  Thus, we have to
+% double any backslashes.  Otherwise, a name like "\node" will be
+% interpreted as a newline (\n), followed by o, d, e.  Not good.
+% 
+% See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and
+% related messages.  The final outcome is that it is up to the TeX user
+% to double the backslashes and otherwise make the string valid, so
+% that's what we do.  pdftex 1.30.0 (ca.2005) introduced a primitive to
+% do this reliably, so we use it.
+
+% #1 is a control sequence in which to do the replacements,
+% which we \xdef.
+\def\txiescapepdf#1{%
+  \ifx\pdfescapestring\thisisundefined
+    % No primitive available; should we give a warning or log?
+    % Many times it won't matter.
+  \else
+    % The expandable \pdfescapestring primitive escapes parentheses,
+    % backslashes, and other special chars.
+    \xdef#1{\pdfescapestring{#1}}%
+  \fi
+}
+
+\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images
+with PDF output, and none of those formats could be found.  (.eps cannot
+be supported due to the design of the PDF format; use regular TeX (DVI
+output) for that.)}
+
 \ifpdf
-  \input pdfcolor
-  \pdfcatalog{/PageMode /UseOutlines}%
+  %
+  % Color manipulation macros based on pdfcolor.tex,
+  % except using rgb instead of cmyk; the latter is said to render as a
+  % very dark gray on-screen and a very dark halftone in print, instead
+  % of actual black.
+  \def\rgbDarkRed{0.50 0.09 0.12}
+  \def\rgbBlack{0 0 0}
+  %
+  % k sets the color for filling (usual text, etc.);
+  % K sets the color for stroking (thin rules, e.g., normal _'s).
+  \def\pdfsetcolor#1{\pdfliteral{#1 rg  #1 RG}}
+  %
+  % Set color, and create a mark which defines \thiscolor accordingly,
+  % so that \makeheadline knows which color to restore.
+  \def\setcolor#1{%
+    \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}%
+    \domark
+    \pdfsetcolor{#1}%
+  }
+  %
+  \def\maincolor{\rgbBlack}
+  \pdfsetcolor{\maincolor}
+  \edef\thiscolor{\maincolor}
+  \def\lastcolordefs{}
+  %
+  \def\makefootline{%
+    \baselineskip24pt
+    \line{\pdfsetcolor{\maincolor}\the\footline}%
+  }
+  %
+  \def\makeheadline{%
+    \vbox to 0pt{%
+      \vskip-22.5pt
+      \line{%
+        \vbox to8.5pt{}%
+        % Extract \thiscolor definition from the marks.
+        \getcolormarks
+        % Typeset the headline with \maincolor, then restore the color.
+        \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}%
+      }%
+      \vss
+    }%
+    \nointerlineskip
+  }
+  %
+  %
+  \pdfcatalog{/PageMode /UseOutlines}
+  %
+  % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto).
   \def\dopdfimage#1#2#3{%
-    \def\imagewidth{#2}%
-    \def\imageheight{#3}%
-    % without \immediate, pdftex seg faults when the same image is
+    \def\pdfimagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}%
+    \def\pdfimageheight{#3}\setbox2 = \hbox{\ignorespaces #3}%
+    %
+    % pdftex (and the PDF format) support .pdf, .png, .jpg (among
+    % others).  Let's try in that order, PDF first since if
+    % someone has a scalable image, presumably better to use that than a
+    % bitmap.
+    \let\pdfimgext=\empty
+    \begingroup
+      \openin 1 #1.pdf \ifeof 1
+        \openin 1 #1.PDF \ifeof 1
+          \openin 1 #1.png \ifeof 1
+            \openin 1 #1.jpg \ifeof 1
+              \openin 1 #1.jpeg \ifeof 1
+                \openin 1 #1.JPG \ifeof 1
+                  \errhelp = \nopdfimagehelp
+                  \errmessage{Could not find image file #1 for pdf}%
+                \else \gdef\pdfimgext{JPG}%
+                \fi
+              \else \gdef\pdfimgext{jpeg}%
+              \fi
+            \else \gdef\pdfimgext{jpg}%
+            \fi
+          \else \gdef\pdfimgext{png}%
+          \fi
+        \else \gdef\pdfimgext{PDF}%
+        \fi
+      \else \gdef\pdfimgext{pdf}%
+      \fi
+      \closein 1
+    \endgroup
+    %
+    % without \immediate, ancient pdftex seg faults when the same image is
     % included twice.  (Version 3.14159-pre-1.0-unofficial-20010704.)
     \ifnum\pdftexversion < 14
       \immediate\pdfimage
@@ -1189,26 +1223,37 @@
     \else
       \immediate\pdfximage
     \fi
-      \ifx\empty\imagewidth\else width \imagewidth \fi
-      \ifx\empty\imageheight\else height \imageheight \fi
+      \ifdim \wd0 >0pt width \pdfimagewidth \fi
+      \ifdim \wd2 >0pt height \pdfimageheight \fi
       \ifnum\pdftexversion<13
-         #1.pdf%
+         #1.\pdfimgext
        \else
-         {#1.pdf}%
+         {#1.\pdfimgext}%
        \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%
+    % We have to set dummies so commands such as @code, and characters
+    % such as \, aren't expanded when present in a section title.
+    \indexnofonts
+    \turnoffactive
+    \makevalueexpandable
+    \def\pdfdestname{#1}%
+    \txiescapepdf\pdfdestname
+    \safewhatsit{\pdfdest name{\pdfdestname} xyz}%
   }}
+  %
+  % used to mark target names; must be expandable.
   \def\pdfmkpgn#1{#1}
-  \let\linkcolor = \Blue  % was Cyan, but that seems light?
-  \def\endlink{\Black\pdfendlink}
+  %
+  % by default, use a color that is dark enough to print on paper as
+  % nearly black, but still distinguishable for online viewing.
+  \def\urlcolor{\rgbDarkRed}
+  \def\linkcolor{\rgbDarkRed}
+  \def\endlink{\setcolor{\maincolor}\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%
@@ -1217,38 +1262,44 @@
     \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.
+  % #1 is the section text, which is what will be displayed in the
+  % outline by the pdf viewer.  #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
+    % seem worth the trouble, since most documents are normally structured.
+    \edef\pdfoutlinedest{#3}%
+    \ifx\pdfoutlinedest\empty
+      \def\pdfoutlinedest{#4}%
+    \else
+      \txiescapepdf\pdfoutlinedest
+    \fi
     %
-    \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{#1}%
+    % Also escape PDF chars in the display string.
+    \edef\pdfoutlinetext{#1}%
+    \txiescapepdf\pdfoutlinetext
+    %
+    \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}%
   }
   %
   \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\partentry##1##2##3##4{}% ignore parts in the outlines
       \def\numchapentry##1##2##3##4{%
 	\def\thischapnum{##2}%
-	\let\thissecnum\empty
-	\let\thissubsecnum\empty
+	\def\thissecnum{0}%
+	\def\thissubsecnum{0}%
       }%
       \def\numsecentry##1##2##3##4{%
 	\advancenumber{chap\thischapnum}%
 	\def\thissecnum{##2}%
-	\let\thissubsecnum\empty
+	\def\thissubsecnum{0}%
       }%
       \def\numsubsecentry##1##2##3##4{%
 	\advancenumber{sec\thissecnum}%
@@ -1257,9 +1308,9 @@
       \def\numsubsubsecentry##1##2##3##4{%
 	\advancenumber{subsec\thissubsecnum}%
       }%
-      \let\thischapnum\empty
-      \let\thissecnum\empty
-      \let\thissubsecnum\empty
+      \def\thischapnum{0}%
+      \def\thissecnum{0}%
+      \def\thissubsecnum{0}%
       %
       % use \def rather than \let here because we redefine \chapentry et
       % al. a second time, below.
@@ -1271,7 +1322,7 @@
       \def\unnsecentry{\numsecentry}%
       \def\unnsubsecentry{\numsubsecentry}%
       \def\unnsubsubsecentry{\numsubsubsecentry}%
-      \input \jobname.toc
+      \readdatafile{toc}%
       %
       % Read toc second time, this time actually producing the outlines.
       % The `-' means take the \expnumber as the absolute number of
@@ -1293,64 +1344,63 @@
       % 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.
+      % TODO this right, we have to translate 8-bit characters to
+      % their "best" equivalent, based on the @documentencoding.  Too
+      % much work for too little return.  Just use the ASCII equivalents
+      % we use for the index sort strings.
+      % 
       \indexnofonts
-      \turnoffactive
-      \input \jobname.toc
+      \setupdatafile
+      % We can have normal brace characters in the PDF outlines, unlike
+      % Texinfo index files.  So set that up.
+      \def\{{\lbracecharliteral}%
+      \def\}{\rbracecharliteral}%
+      \catcode`\\=\active \otherbackslash
+      \input \tocreadfilename
     \endgroup
   }
+  {\catcode`[=1 \catcode`]=2
+   \catcode`{=\other \catcode`}=\other
+   \gdef\lbracecharliteral[{]%
+   \gdef\rbracecharliteral[}]%
+  ]
   %
-  \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
+      \addtokens{\filename}{\PP}%
+      \advance\filenamelength by 1
     \fi
     \nextsp}
-  \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax}
+  \def\getfilename#1{%
+    \filenamelength=0
+    % If we don't expand the argument now, \skipspaces will get
+    % snagged on things like "@value{foo}".
+    \edef\temp{#1}%
+    \expandafter\skipspaces\temp|\relax
+  }
   \ifnum\pdftexversion < 14
     \let \startlink \pdfannotlink
   \else
     \let \startlink \pdfstartlink
   \fi
+  % make a live url in pdf output.
   \def\pdfurl#1{%
     \begingroup
-      \normalturnoffactive\def\@{@}%
+      % it seems we really need yet another set of dummies; have not
+      % tried to figure out what each command should do in the context
+      % of @url.  for now, just make @/ a no-op, that's the only one
+      % people have actually reported a problem with.
+      %
+      \normalturnoffactive
+      \def\@{@}%
+      \let\/=\empty
       \makevalueexpandable
-      \leavevmode\Red
+      % do we want to go so far as to use \indexnofonts instead of just
+      % special-casing \var here?
+      \def\var##1{##1}%
+      %
+      \leavevmode\setcolor{\urlcolor}%
       \startlink attr{/Border [0 0 0]}%
         user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
     \endgroup}
@@ -1377,13 +1427,15 @@
     {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
   \def\pdflink#1{%
     \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}}
-    \linkcolor #1\endlink}
+    \setcolor{\linkcolor}#1\endlink}
   \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
 \else
+  % non-pdf mode
   \let\pdfmkdest = \gobble
   \let\pdfurl = \gobble
   \let\endlink = \relax
-  \let\linkcolor = \relax
+  \let\setcolor = \gobble
+  \let\pdfsetcolor = \gobble
   \let\pdfmakeoutlines = \relax
 \fi  % \ifx\pdfoutput
 
@@ -1406,9 +1458,13 @@
 \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\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf}
 \def\tt{\fam=\ttfam \setfontstyle{tt}}
 
+% Unfortunately, we have to override this for titles and the like, since
+% in those cases "rm" is bold.  Sigh.
+\def\rmisbold{\rm\def\curfontstyle{bf}}
+
 % Texinfo sort of supports the sans serif font style, which plain TeX does not.
 % So we set up a \sf.
 \newfam\sffam
@@ -1418,8 +1474,6 @@
 % We don't need math for this font style.
 \def\ttsl{\setfontstyle{ttsl}}
 
-% Default leading.
-\newdimen\textleading  \textleading = 13.2pt
 
 % Set the baselineskip to #1, and the lineskip and strut size
 % correspondingly.  There is no deep meaning behind these magic numbers
@@ -1429,8 +1483,13 @@
 \def\strutheightpercent{.70833}
 \def\strutdepthpercent {.29167}
 %
+% can get a sort of poor man's double spacing by redefining this.
+\def\baselinefactor{1}
+%
+\newdimen\textleading
 \def\setleading#1{%
-  \normalbaselineskip = #1\relax
+  \dimen0 = #1\relax
+  \normalbaselineskip = \baselinefactor\dimen0
   \normallineskip = \lineskipfactor\normalbaselineskip
   \normalbaselines
   \setbox\strutbox =\hbox{%
@@ -1439,20 +1498,295 @@
   }%
 }
 
-% Set the font macro #1 to the font named #2, adding on the
-% specified font prefix (normally `cm').
-% #3 is the font's design size, #4 is a scale factor
-\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+% PDF CMaps.  See also LaTeX's t1.cmap.
+%
+% do nothing with this by default.
+\expandafter\let\csname cmapOT1\endcsname\gobble
+\expandafter\let\csname cmapOT1IT\endcsname\gobble
+\expandafter\let\csname cmapOT1TT\endcsname\gobble
 
+% if we are producing pdf, and we have \pdffontattr, then define cmaps.
+% (\pdffontattr was introduced many years ago, but people still run
+% older pdftex's; it's easy to conditionalize, so we do.)
+\ifpdf \ifx\pdffontattr\thisisundefined \else
+  \begingroup
+    \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
+    \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: ProcSet (CIDInit)
+%%IncludeResource: ProcSet (CIDInit)
+%%BeginResource: CMap (TeX-OT1-0)
+%%Title: (TeX-OT1-0 TeX OT1 0)
+%%Version: 1.000
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo
+<< /Registry (TeX)
+/Ordering (OT1)
+/Supplement 0
+>> def
+/CMapName /TeX-OT1-0 def
+/CMapType 2 def
+1 begincodespacerange
+<00> <7F>
+endcodespacerange
+8 beginbfrange
+<00> <01> <0393>
+<09> <0A> <03A8>
+<23> <26> <0023>
+<28> <3B> <0028>
+<3F> <5B> <003F>
+<5D> <5E> <005D>
+<61> <7A> <0061>
+<7B> <7C> <2013>
+endbfrange
+40 beginbfchar
+<02> <0398>
+<03> <039B>
+<04> <039E>
+<05> <03A0>
+<06> <03A3>
+<07> <03D2>
+<08> <03A6>
+<0B> <00660066>
+<0C> <00660069>
+<0D> <0066006C>
+<0E> <006600660069>
+<0F> <00660066006C>
+<10> <0131>
+<11> <0237>
+<12> <0060>
+<13> <00B4>
+<14> <02C7>
+<15> <02D8>
+<16> <00AF>
+<17> <02DA>
+<18> <00B8>
+<19> <00DF>
+<1A> <00E6>
+<1B> <0153>
+<1C> <00F8>
+<1D> <00C6>
+<1E> <0152>
+<1F> <00D8>
+<21> <0021>
+<22> <201D>
+<27> <2019>
+<3C> <00A1>
+<3D> <003D>
+<3E> <00BF>
+<5C> <201C>
+<5F> <02D9>
+<60> <2018>
+<7D> <02DD>
+<7E> <007E>
+<7F> <00A8>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+    }\endgroup
+  \expandafter\edef\csname cmapOT1\endcsname#1{%
+    \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
+  }%
+%
+% \cmapOT1IT
+  \begingroup
+    \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
+    \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: ProcSet (CIDInit)
+%%IncludeResource: ProcSet (CIDInit)
+%%BeginResource: CMap (TeX-OT1IT-0)
+%%Title: (TeX-OT1IT-0 TeX OT1IT 0)
+%%Version: 1.000
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo
+<< /Registry (TeX)
+/Ordering (OT1IT)
+/Supplement 0
+>> def
+/CMapName /TeX-OT1IT-0 def
+/CMapType 2 def
+1 begincodespacerange
+<00> <7F>
+endcodespacerange
+8 beginbfrange
+<00> <01> <0393>
+<09> <0A> <03A8>
+<25> <26> <0025>
+<28> <3B> <0028>
+<3F> <5B> <003F>
+<5D> <5E> <005D>
+<61> <7A> <0061>
+<7B> <7C> <2013>
+endbfrange
+42 beginbfchar
+<02> <0398>
+<03> <039B>
+<04> <039E>
+<05> <03A0>
+<06> <03A3>
+<07> <03D2>
+<08> <03A6>
+<0B> <00660066>
+<0C> <00660069>
+<0D> <0066006C>
+<0E> <006600660069>
+<0F> <00660066006C>
+<10> <0131>
+<11> <0237>
+<12> <0060>
+<13> <00B4>
+<14> <02C7>
+<15> <02D8>
+<16> <00AF>
+<17> <02DA>
+<18> <00B8>
+<19> <00DF>
+<1A> <00E6>
+<1B> <0153>
+<1C> <00F8>
+<1D> <00C6>
+<1E> <0152>
+<1F> <00D8>
+<21> <0021>
+<22> <201D>
+<23> <0023>
+<24> <00A3>
+<27> <2019>
+<3C> <00A1>
+<3D> <003D>
+<3E> <00BF>
+<5C> <201C>
+<5F> <02D9>
+<60> <2018>
+<7D> <02DD>
+<7E> <007E>
+<7F> <00A8>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+    }\endgroup
+  \expandafter\edef\csname cmapOT1IT\endcsname#1{%
+    \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
+  }%
+%
+% \cmapOT1TT
+  \begingroup
+    \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
+    \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: ProcSet (CIDInit)
+%%IncludeResource: ProcSet (CIDInit)
+%%BeginResource: CMap (TeX-OT1TT-0)
+%%Title: (TeX-OT1TT-0 TeX OT1TT 0)
+%%Version: 1.000
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo
+<< /Registry (TeX)
+/Ordering (OT1TT)
+/Supplement 0
+>> def
+/CMapName /TeX-OT1TT-0 def
+/CMapType 2 def
+1 begincodespacerange
+<00> <7F>
+endcodespacerange
+5 beginbfrange
+<00> <01> <0393>
+<09> <0A> <03A8>
+<21> <26> <0021>
+<28> <5F> <0028>
+<61> <7E> <0061>
+endbfrange
+32 beginbfchar
+<02> <0398>
+<03> <039B>
+<04> <039E>
+<05> <03A0>
+<06> <03A3>
+<07> <03D2>
+<08> <03A6>
+<0B> <2191>
+<0C> <2193>
+<0D> <0027>
+<0E> <00A1>
+<0F> <00BF>
+<10> <0131>
+<11> <0237>
+<12> <0060>
+<13> <00B4>
+<14> <02C7>
+<15> <02D8>
+<16> <00AF>
+<17> <02DA>
+<18> <00B8>
+<19> <00DF>
+<1A> <00E6>
+<1B> <0153>
+<1C> <00F8>
+<1D> <00C6>
+<1E> <0152>
+<1F> <00D8>
+<20> <2423>
+<27> <2019>
+<60> <2018>
+<7F> <00A8>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+    }\endgroup
+  \expandafter\edef\csname cmapOT1TT\endcsname#1{%
+    \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
+  }%
+\fi\fi
+
+
+% Set the font macro #1 to the font named \fontprefix#2.
+% #3 is the font's design size, #4 is a scale factor, #5 is the CMap
+% encoding (only OT1, OT1IT and OT1TT are allowed, or empty to omit).
+% Example:
+% #1 = \textrm
+% #2 = \rmshape
+% #3 = 10
+% #4 = \mainmagstep
+% #5 = OT1
+%
+\def\setfont#1#2#3#4#5{%
+  \font#1=\fontprefix#2#3 scaled #4
+  \csname cmap#5\endcsname#1%
+}
+% This is what gets called when #5 of \setfont is empty.
+\let\cmap\gobble
+%
+% (end of cmaps)
+
 % Use cm as the default font prefix.
 % To specify the font prefix, you must define \fontprefix
 % before you read in texinfo.tex.
-\ifx\fontprefix\undefined
+\ifx\fontprefix\thisisundefined
 \def\fontprefix{cm}
 \fi
 % Support font families that don't use the same naming scheme as CM.
 \def\rmshape{r}
-\def\rmbshape{bx}               %where the normal face is bold
+\def\rmbshape{bx}               % where the normal face is bold
 \def\bfshape{b}
 \def\bxshape{bx}
 \def\ttshape{tt}
@@ -1467,119 +1801,292 @@
 \def\scshape{csc}
 \def\scbshape{csc}
 
+% Definitions for a main text size of 11pt.  (The default in Texinfo.)
+%
+\def\definetextfontsizexi{%
 % Text fonts (11.2pt, magstep1).
-\newcount\mainmagstep
-\ifx\bigger\relax
-  % not really supported.
-  \mainmagstep=\magstep1
-  \setfont\textrm\rmshape{12}{1000}
-  \setfont\texttt\ttshape{12}{1000}
-\else
-  \mainmagstep=\magstephalf
-  \setfont\textrm\rmshape{10}{\mainmagstep}
-  \setfont\texttt\ttshape{10}{\mainmagstep}
-\fi
-\setfont\textbf\bfshape{10}{\mainmagstep}
-\setfont\textit\itshape{10}{\mainmagstep}
-\setfont\textsl\slshape{10}{\mainmagstep}
-\setfont\textsf\sfshape{10}{\mainmagstep}
-\setfont\textsc\scshape{10}{\mainmagstep}
-\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\def\textnominalsize{11pt}
+\edef\mainmagstep{\magstephalf}
+\setfont\textrm\rmshape{10}{\mainmagstep}{OT1}
+\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT}
+\setfont\textbf\bfshape{10}{\mainmagstep}{OT1}
+\setfont\textit\itshape{10}{\mainmagstep}{OT1IT}
+\setfont\textsl\slshape{10}{\mainmagstep}{OT1}
+\setfont\textsf\sfshape{10}{\mainmagstep}{OT1}
+\setfont\textsc\scshape{10}{\mainmagstep}{OT1}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT}
 \font\texti=cmmi10 scaled \mainmagstep
 \font\textsy=cmsy10 scaled \mainmagstep
+\def\textecsize{1095}
 
 % A few fonts for @defun names and args.
-\setfont\defbf\bfshape{10}{\magstep1}
-\setfont\deftt\ttshape{10}{\magstep1}
-\setfont\defttsl\ttslshape{10}{\magstep1}
+\setfont\defbf\bfshape{10}{\magstep1}{OT1}
+\setfont\deftt\ttshape{10}{\magstep1}{OT1TT}
+\setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT}
 \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}
+\def\smallnominalsize{9pt}
+\setfont\smallrm\rmshape{9}{1000}{OT1}
+\setfont\smalltt\ttshape{9}{1000}{OT1TT}
+\setfont\smallbf\bfshape{10}{900}{OT1}
+\setfont\smallit\itshape{9}{1000}{OT1IT}
+\setfont\smallsl\slshape{9}{1000}{OT1}
+\setfont\smallsf\sfshape{9}{1000}{OT1}
+\setfont\smallsc\scshape{10}{900}{OT1}
+\setfont\smallttsl\ttslshape{10}{900}{OT1TT}
 \font\smalli=cmmi9
 \font\smallsy=cmsy9
+\def\smallecsize{0900}
 
 % 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}
+\def\smallernominalsize{8pt}
+\setfont\smallerrm\rmshape{8}{1000}{OT1}
+\setfont\smallertt\ttshape{8}{1000}{OT1TT}
+\setfont\smallerbf\bfshape{10}{800}{OT1}
+\setfont\smallerit\itshape{8}{1000}{OT1IT}
+\setfont\smallersl\slshape{8}{1000}{OT1}
+\setfont\smallersf\sfshape{8}{1000}{OT1}
+\setfont\smallersc\scshape{10}{800}{OT1}
+\setfont\smallerttsl\ttslshape{10}{800}{OT1TT}
 \font\smalleri=cmmi8
 \font\smallersy=cmsy8
+\def\smallerecsize{0800}
 
 % Fonts for title page (20.4pt):
-\setfont\titlerm\rmbshape{12}{\magstep3}
-\setfont\titleit\itbshape{10}{\magstep4}
-\setfont\titlesl\slbshape{10}{\magstep4}
-\setfont\titlett\ttbshape{12}{\magstep3}
-\setfont\titlettsl\ttslshape{10}{\magstep4}
-\setfont\titlesf\sfbshape{17}{\magstep1}
+\def\titlenominalsize{20pt}
+\setfont\titlerm\rmbshape{12}{\magstep3}{OT1}
+\setfont\titleit\itbshape{10}{\magstep4}{OT1IT}
+\setfont\titlesl\slbshape{10}{\magstep4}{OT1}
+\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT}
+\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT}
+\setfont\titlesf\sfbshape{17}{\magstep1}{OT1}
 \let\titlebf=\titlerm
-\setfont\titlesc\scbshape{10}{\magstep4}
+\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
 \font\titlei=cmmi12 scaled \magstep3
 \font\titlesy=cmsy10 scaled \magstep4
-\def\authorrm{\secrm}
-\def\authortt{\sectt}
+\def\titleecsize{2074}
 
 % Chapter (and unnumbered) fonts (17.28pt).
-\setfont\chaprm\rmbshape{12}{\magstep2}
-\setfont\chapit\itbshape{10}{\magstep3}
-\setfont\chapsl\slbshape{10}{\magstep3}
-\setfont\chaptt\ttbshape{12}{\magstep2}
-\setfont\chapttsl\ttslshape{10}{\magstep3}
-\setfont\chapsf\sfbshape{17}{1000}
+\def\chapnominalsize{17pt}
+\setfont\chaprm\rmbshape{12}{\magstep2}{OT1}
+\setfont\chapit\itbshape{10}{\magstep3}{OT1IT}
+\setfont\chapsl\slbshape{10}{\magstep3}{OT1}
+\setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT}
+\setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT}
+\setfont\chapsf\sfbshape{17}{1000}{OT1}
 \let\chapbf=\chaprm
-\setfont\chapsc\scbshape{10}{\magstep3}
+\setfont\chapsc\scbshape{10}{\magstep3}{OT1}
 \font\chapi=cmmi12 scaled \magstep2
 \font\chapsy=cmsy10 scaled \magstep3
+\def\chapecsize{1728}
 
 % Section fonts (14.4pt).
-\setfont\secrm\rmbshape{12}{\magstep1}
-\setfont\secit\itbshape{10}{\magstep2}
-\setfont\secsl\slbshape{10}{\magstep2}
-\setfont\sectt\ttbshape{12}{\magstep1}
-\setfont\secttsl\ttslshape{10}{\magstep2}
-\setfont\secsf\sfbshape{12}{\magstep1}
+\def\secnominalsize{14pt}
+\setfont\secrm\rmbshape{12}{\magstep1}{OT1}
+\setfont\secit\itbshape{10}{\magstep2}{OT1IT}
+\setfont\secsl\slbshape{10}{\magstep2}{OT1}
+\setfont\sectt\ttbshape{12}{\magstep1}{OT1TT}
+\setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT}
+\setfont\secsf\sfbshape{12}{\magstep1}{OT1}
 \let\secbf\secrm
-\setfont\secsc\scbshape{10}{\magstep2}
+\setfont\secsc\scbshape{10}{\magstep2}{OT1}
 \font\seci=cmmi12 scaled \magstep1
 \font\secsy=cmsy10 scaled \magstep2
+\def\sececsize{1440}
 
 % Subsection fonts (13.15pt).
-\setfont\ssecrm\rmbshape{12}{\magstephalf}
-\setfont\ssecit\itbshape{10}{1315}
-\setfont\ssecsl\slbshape{10}{1315}
-\setfont\ssectt\ttbshape{12}{\magstephalf}
-\setfont\ssecttsl\ttslshape{10}{1315}
-\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\def\ssecnominalsize{13pt}
+\setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1}
+\setfont\ssecit\itbshape{10}{1315}{OT1IT}
+\setfont\ssecsl\slbshape{10}{1315}{OT1}
+\setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT}
+\setfont\ssecttsl\ttslshape{10}{1315}{OT1TT}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1}
 \let\ssecbf\ssecrm
-\setfont\ssecsc\scbshape{10}{1315}
+\setfont\ssecsc\scbshape{10}{1315}{OT1}
 \font\sseci=cmmi12 scaled \magstephalf
 \font\ssecsy=cmsy10 scaled 1315
+\def\ssececsize{1200}
 
 % 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}
+\def\reducednominalsize{10pt}
+\setfont\reducedrm\rmshape{10}{1000}{OT1}
+\setfont\reducedtt\ttshape{10}{1000}{OT1TT}
+\setfont\reducedbf\bfshape{10}{1000}{OT1}
+\setfont\reducedit\itshape{10}{1000}{OT1IT}
+\setfont\reducedsl\slshape{10}{1000}{OT1}
+\setfont\reducedsf\sfshape{10}{1000}{OT1}
+\setfont\reducedsc\scshape{10}{1000}{OT1}
+\setfont\reducedttsl\ttslshape{10}{1000}{OT1TT}
 \font\reducedi=cmmi10
 \font\reducedsy=cmsy10
+\def\reducedecsize{1000}
 
+\textleading = 13.2pt % line spacing for 11pt CM
+\textfonts            % reset the current fonts
+\rm
+} % end of 11pt text font size definitions, \definetextfontsizexi
+
+
+% Definitions to make the main text be 10pt Computer Modern, with
+% section, chapter, etc., sizes following suit.  This is for the GNU
+% Press printing of the Emacs 22 manual.  Maybe other manuals in the
+% future.  Used with @smallbook, which sets the leading to 12pt.
+%
+\def\definetextfontsizex{%
+% Text fonts (10pt).
+\def\textnominalsize{10pt}
+\edef\mainmagstep{1000}
+\setfont\textrm\rmshape{10}{\mainmagstep}{OT1}
+\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT}
+\setfont\textbf\bfshape{10}{\mainmagstep}{OT1}
+\setfont\textit\itshape{10}{\mainmagstep}{OT1IT}
+\setfont\textsl\slshape{10}{\mainmagstep}{OT1}
+\setfont\textsf\sfshape{10}{\mainmagstep}{OT1}
+\setfont\textsc\scshape{10}{\mainmagstep}{OT1}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+\def\textecsize{1000}
+
+% A few fonts for @defun names and args.
+\setfont\defbf\bfshape{10}{\magstephalf}{OT1}
+\setfont\deftt\ttshape{10}{\magstephalf}{OT1TT}
+\setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf}
+
+% Fonts for indices, footnotes, small examples (9pt).
+\def\smallnominalsize{9pt}
+\setfont\smallrm\rmshape{9}{1000}{OT1}
+\setfont\smalltt\ttshape{9}{1000}{OT1TT}
+\setfont\smallbf\bfshape{10}{900}{OT1}
+\setfont\smallit\itshape{9}{1000}{OT1IT}
+\setfont\smallsl\slshape{9}{1000}{OT1}
+\setfont\smallsf\sfshape{9}{1000}{OT1}
+\setfont\smallsc\scshape{10}{900}{OT1}
+\setfont\smallttsl\ttslshape{10}{900}{OT1TT}
+\font\smalli=cmmi9
+\font\smallsy=cmsy9
+\def\smallecsize{0900}
+
+% Fonts for small examples (8pt).
+\def\smallernominalsize{8pt}
+\setfont\smallerrm\rmshape{8}{1000}{OT1}
+\setfont\smallertt\ttshape{8}{1000}{OT1TT}
+\setfont\smallerbf\bfshape{10}{800}{OT1}
+\setfont\smallerit\itshape{8}{1000}{OT1IT}
+\setfont\smallersl\slshape{8}{1000}{OT1}
+\setfont\smallersf\sfshape{8}{1000}{OT1}
+\setfont\smallersc\scshape{10}{800}{OT1}
+\setfont\smallerttsl\ttslshape{10}{800}{OT1TT}
+\font\smalleri=cmmi8
+\font\smallersy=cmsy8
+\def\smallerecsize{0800}
+
+% Fonts for title page (20.4pt):
+\def\titlenominalsize{20pt}
+\setfont\titlerm\rmbshape{12}{\magstep3}{OT1}
+\setfont\titleit\itbshape{10}{\magstep4}{OT1IT}
+\setfont\titlesl\slbshape{10}{\magstep4}{OT1}
+\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT}
+\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT}
+\setfont\titlesf\sfbshape{17}{\magstep1}{OT1}
+\let\titlebf=\titlerm
+\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
+\font\titlei=cmmi12 scaled \magstep3
+\font\titlesy=cmsy10 scaled \magstep4
+\def\titleecsize{2074}
+
+% Chapter fonts (14.4pt).
+\def\chapnominalsize{14pt}
+\setfont\chaprm\rmbshape{12}{\magstep1}{OT1}
+\setfont\chapit\itbshape{10}{\magstep2}{OT1IT}
+\setfont\chapsl\slbshape{10}{\magstep2}{OT1}
+\setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT}
+\setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT}
+\setfont\chapsf\sfbshape{12}{\magstep1}{OT1}
+\let\chapbf\chaprm
+\setfont\chapsc\scbshape{10}{\magstep2}{OT1}
+\font\chapi=cmmi12 scaled \magstep1
+\font\chapsy=cmsy10 scaled \magstep2
+\def\chapecsize{1440}
+
+% Section fonts (12pt).
+\def\secnominalsize{12pt}
+\setfont\secrm\rmbshape{12}{1000}{OT1}
+\setfont\secit\itbshape{10}{\magstep1}{OT1IT}
+\setfont\secsl\slbshape{10}{\magstep1}{OT1}
+\setfont\sectt\ttbshape{12}{1000}{OT1TT}
+\setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT}
+\setfont\secsf\sfbshape{12}{1000}{OT1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep1}{OT1}
+\font\seci=cmmi12
+\font\secsy=cmsy10 scaled \magstep1
+\def\sececsize{1200}
+
+% Subsection fonts (10pt).
+\def\ssecnominalsize{10pt}
+\setfont\ssecrm\rmbshape{10}{1000}{OT1}
+\setfont\ssecit\itbshape{10}{1000}{OT1IT}
+\setfont\ssecsl\slbshape{10}{1000}{OT1}
+\setfont\ssectt\ttbshape{10}{1000}{OT1TT}
+\setfont\ssecttsl\ttslshape{10}{1000}{OT1TT}
+\setfont\ssecsf\sfbshape{10}{1000}{OT1}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{1000}{OT1}
+\font\sseci=cmmi10
+\font\ssecsy=cmsy10
+\def\ssececsize{1000}
+
+% Reduced fonts for @acro in text (9pt).
+\def\reducednominalsize{9pt}
+\setfont\reducedrm\rmshape{9}{1000}{OT1}
+\setfont\reducedtt\ttshape{9}{1000}{OT1TT}
+\setfont\reducedbf\bfshape{10}{900}{OT1}
+\setfont\reducedit\itshape{9}{1000}{OT1IT}
+\setfont\reducedsl\slshape{9}{1000}{OT1}
+\setfont\reducedsf\sfshape{9}{1000}{OT1}
+\setfont\reducedsc\scshape{10}{900}{OT1}
+\setfont\reducedttsl\ttslshape{10}{900}{OT1TT}
+\font\reducedi=cmmi9
+\font\reducedsy=cmsy9
+\def\reducedecsize{0900}
+
+\divide\parskip by 2  % reduce space between paragraphs
+\textleading = 12pt   % line spacing for 10pt CM
+\textfonts            % reset the current fonts
+\rm
+} % end of 10pt text font size definitions, \definetextfontsizex
+
+
+% We provide the user-level command
+%   @fonttextsize 10
+% (or 11) to redefine the text font size.  pt is assumed.
+%
+\def\xiword{11}
+\def\xword{10}
+\def\xwordpt{10pt}
+%
+\parseargdef\fonttextsize{%
+  \def\textsizearg{#1}%
+  %\wlog{doing @fonttextsize \textsizearg}%
+  %
+  % Set \globaldefs so that documents can use this inside @tex, since
+  % makeinfo 4.8 does not support it, but we need it nonetheless.
+  %
+ \begingroup \globaldefs=1
+  \ifx\textsizearg\xword \definetextfontsizex
+  \else \ifx\textsizearg\xiword \definetextfontsizexi
+  \else
+    \errhelp=\EMsimple
+    \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'}
+  \fi\fi
+ \endgroup
+}
+
+
 % In order for the font changes to affect most math symbols and letters,
 % we have to define the \textfont of the standard families.  Since
 % texinfo doesn't allow for producing subscripts and superscripts except
@@ -1608,6 +2115,7 @@
   \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
   \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
   \let\tenttsl=\textttsl
+  \def\curfontsize{text}%
   \def\lsize{reduced}\def\lllsize{smaller}%
   \resetmathfonts \setleading{\textleading}}
 \def\titlefonts{%
@@ -1615,13 +2123,16 @@
   \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc
   \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy
   \let\tenttsl=\titlettsl
+  \def\curfontsize{title}%
   \def\lsize{chap}\def\lllsize{subsec}%
-  \resetmathfonts \setleading{25pt}}
-\def\titlefont#1{{\titlefonts\rm #1}}
+  \resetmathfonts \setleading{27pt}}
+\def\titlefont#1{{\titlefonts\rmisbold #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
+  \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
+  \let\tenttsl=\chapttsl
+  \def\curfontsize{chap}%
   \def\lsize{sec}\def\lllsize{text}%
   \resetmathfonts \setleading{19pt}}
 \def\secfonts{%
@@ -1629,6 +2140,7 @@
   \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
   \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
   \let\tenttsl=\secttsl
+  \def\curfontsize{sec}%
   \def\lsize{subsec}\def\lllsize{reduced}%
   \resetmathfonts \setleading{16pt}}
 \def\subsecfonts{%
@@ -1636,6 +2148,7 @@
   \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
   \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
   \let\tenttsl=\ssecttsl
+  \def\curfontsize{ssec}%
   \def\lsize{text}\def\lllsize{small}%
   \resetmathfonts \setleading{15pt}}
 \let\subsubsecfonts = \subsecfonts
@@ -1644,6 +2157,7 @@
   \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc
   \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy
   \let\tenttsl=\reducedttsl
+  \def\curfontsize{reduced}%
   \def\lsize{small}\def\lllsize{smaller}%
   \resetmathfonts \setleading{10.5pt}}
 \def\smallfonts{%
@@ -1651,6 +2165,7 @@
   \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc
   \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy
   \let\tenttsl=\smallttsl
+  \def\curfontsize{small}%
   \def\lsize{smaller}\def\lllsize{smaller}%
   \resetmathfonts \setleading{10.5pt}}
 \def\smallerfonts{%
@@ -1658,9 +2173,20 @@
   \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc
   \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy
   \let\tenttsl=\smallerttsl
+  \def\curfontsize{smaller}%
   \def\lsize{smaller}\def\lllsize{smaller}%
   \resetmathfonts \setleading{9.5pt}}
 
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}{OT1}
+\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1}  % no cmb12
+\setfont\shortcontsl\slshape{12}{1000}{OT1}
+\setfont\shortconttt\ttshape{12}{1000}{OT1TT}
+
+% Define these just so they can be easily changed for other fonts.
+\def\angleleft{$\langle$}
+\def\angleright{$\rangle$}
+
 % Set the fonts to use with the @small... environments.
 \let\smallexamplefonts = \smallfonts
 
@@ -1674,55 +2200,219 @@
 %
 % By the way, for comparison, here's what fits with @example (10pt):
 %   8.5x11=71  smallbook=60  a4=75  a5=58
-%
-% I wish the USA used A4 paper.
 % --karl, 24jan03.
 
-
 % Set up the default fonts, so we can use them for creating boxes.
 %
-\textfonts \rm
+\definetextfontsizexi
 
-% Define these so they can be easily changed for other fonts.
-\def\angleleft{$\langle$}
-\def\angleright{$\rangle$}
 
+\message{markup,}
+
+% Check if we are currently using a typewriter font.  Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Markup style infrastructure.  \defmarkupstylesetup\INITMACRO will
+% define and register \INITMACRO to be called on markup style changes.
+% \INITMACRO can check \currentmarkupstyle for the innermost
+% style and the set of \ifmarkupSTYLE switches for all styles
+% currently in effect.
+\newif\ifmarkupvar
+\newif\ifmarkupsamp
+\newif\ifmarkupkey
+%\newif\ifmarkupfile % @file == @samp.
+%\newif\ifmarkupoption % @option == @samp.
+\newif\ifmarkupcode
+\newif\ifmarkupkbd
+%\newif\ifmarkupenv % @env == @code.
+%\newif\ifmarkupcommand % @command == @code.
+\newif\ifmarkuptex % @tex (and part of @math, for now).
+\newif\ifmarkupexample
+\newif\ifmarkupverb
+\newif\ifmarkupverbatim
+
+\let\currentmarkupstyle\empty
+
+\def\setupmarkupstyle#1{%
+  \csname markup#1true\endcsname
+  \def\currentmarkupstyle{#1}%
+  \markupstylesetup
+}
+
+\let\markupstylesetup\empty
+
+\def\defmarkupstylesetup#1{%
+  \expandafter\def\expandafter\markupstylesetup
+    \expandafter{\markupstylesetup #1}%
+  \def#1%
+}
+
+% Markup style setup for left and right quotes.
+\defmarkupstylesetup\markupsetuplq{%
+  \expandafter\let\expandafter \temp
+    \csname markupsetuplq\currentmarkupstyle\endcsname
+  \ifx\temp\relax \markupsetuplqdefault \else \temp \fi
+}
+
+\defmarkupstylesetup\markupsetuprq{%
+  \expandafter\let\expandafter \temp
+    \csname markupsetuprq\currentmarkupstyle\endcsname
+  \ifx\temp\relax \markupsetuprqdefault \else \temp \fi
+}
+
+{
+\catcode`\'=\active
+\catcode`\`=\active
+
+\gdef\markupsetuplqdefault{\let`\lq}
+\gdef\markupsetuprqdefault{\let'\rq}
+
+\gdef\markupsetcodequoteleft{\let`\codequoteleft}
+\gdef\markupsetcodequoteright{\let'\codequoteright}
+}
+
+\let\markupsetuplqcode \markupsetcodequoteleft
+\let\markupsetuprqcode \markupsetcodequoteright
+%
+\let\markupsetuplqexample \markupsetcodequoteleft
+\let\markupsetuprqexample \markupsetcodequoteright
+%
+\let\markupsetuplqkbd     \markupsetcodequoteleft
+\let\markupsetuprqkbd     \markupsetcodequoteright
+%
+\let\markupsetuplqsamp \markupsetcodequoteleft
+\let\markupsetuprqsamp \markupsetcodequoteright
+%
+\let\markupsetuplqverb \markupsetcodequoteleft
+\let\markupsetuprqverb \markupsetcodequoteright
+%
+\let\markupsetuplqverbatim \markupsetcodequoteleft
+\let\markupsetuprqverbatim \markupsetcodequoteright
+
+% Allow an option to not use regular directed right quote/apostrophe
+% (char 0x27), but instead the undirected quote from cmtt (char 0x0d).
+% The undirected quote is ugly, so don't make it the default, but it
+% works for pasting with more pdf viewers (at least evince), the
+% lilypond developers report.  xpdf does work with the regular 0x27.
+%
+\def\codequoteright{%
+  \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax
+    \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax
+      '%
+    \else \char'15 \fi
+  \else \char'15 \fi
+}
+%
+% and a similar option for the left quote char vs. a grave accent.
+% Modern fonts display ASCII 0x60 as a grave accent, so some people like
+% the code environments to do likewise.
+%
+\def\codequoteleft{%
+  \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax
+    \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax
+      % [Knuth] pp. 380,381,391
+      % \relax disables Spanish ligatures ?` and !` of \tt font.
+      \relax`%
+    \else \char'22 \fi
+  \else \char'22 \fi
+}
+
+% Commands to set the quote options.
+% 
+\parseargdef\codequoteundirected{%
+  \def\temp{#1}%
+  \ifx\temp\onword
+    \expandafter\let\csname SETtxicodequoteundirected\endcsname
+      = t%
+  \else\ifx\temp\offword
+    \expandafter\let\csname SETtxicodequoteundirected\endcsname
+      = \relax
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @codequoteundirected value `\temp', must be on|off}%
+  \fi\fi
+}
+%
+\parseargdef\codequotebacktick{%
+  \def\temp{#1}%
+  \ifx\temp\onword
+    \expandafter\let\csname SETtxicodequotebacktick\endcsname
+      = t%
+  \else\ifx\temp\offword
+    \expandafter\let\csname SETtxicodequotebacktick\endcsname
+      = \relax
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @codequotebacktick value `\temp', must be on|off}%
+  \fi\fi
+}
+
+% [Knuth] pp. 380,381,391, disable Spanish ligatures ?` and !` of \tt font.
+\def\noligaturesquoteleft{\relax\lq}
+
 % Count depth in font-changes, for error checks
 \newcount\fontdepth \fontdepth=0
 
-% Fonts for short table of contents.
-\setfont\shortcontrm\rmshape{12}{1000}
-\setfont\shortcontbf\bfshape{10}{\magstep1}  % no cmb12
-\setfont\shortcontsl\slshape{12}{1000}
-\setfont\shortconttt\ttshape{12}{1000}
+% Font commands.
 
-%% Add scribe-like font environments, plus @l for inline lisp (usually sans
-%% serif) and @ii for TeX italic
+% #1 is the font command (\sl or \it), #2 is the text to slant.
+% If we are in a monospaced environment, however, 1) always use \ttsl,
+% and 2) do not add an italic correction.
+\def\dosmartslant#1#2{%
+  \ifusingtt 
+    {{\ttsl #2}\let\next=\relax}%
+    {\def\next{{#1#2}\futurelet\next\smartitaliccorrection}}%
+  \next
+}
+\def\smartslanted{\dosmartslant\sl}
+\def\smartitalic{\dosmartslant\it}
 
-% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
-% unless the following character is such as not to need one.
-\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else
-                    \ptexslash\fi\fi\fi}
-\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx}
-\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx}
+% Output an italic correction unless \next (presumed to be the following
+% character) is such as not to need one.
+\def\smartitaliccorrection{%
+  \ifx\next,%
+  \else\ifx\next-%
+  \else\ifx\next.%
+  \else\ptexslash
+  \fi\fi\fi
+  \aftersmartic
+}
 
-% like \smartslanted except unconditionally uses \ttsl.
-% @var is set to this for defun arguments.
-\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx}
+% Unconditional use \ttsl, and no ic.  @var is set to this for defuns.
+\def\ttslanted#1{{\ttsl #1}}
 
-% like \smartslanted except unconditionally use \sl.  We never want
+% @cite is like \smartslanted except unconditionally use \sl.  We never want
 % ttsl for book titles, do we?
-\def\cite#1{{\sl #1}\futurelet\next\smartitalicx}
+\def\cite#1{{\sl #1}\futurelet\next\smartitaliccorrection}
 
+\def\aftersmartic{}
+\def\var#1{%
+  \let\saveaftersmartic = \aftersmartic
+  \def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}%
+  \smartslanted{#1}%
+}
+
 \let\i=\smartitalic
 \let\slanted=\smartslanted
-\let\var=\smartslanted
 \let\dfn=\smartslanted
 \let\emph=\smartitalic
 
+% Explicit font changes: @r, @sc, undocumented @ii.
+\def\r#1{{\rm #1}}              % roman font
+\def\sc#1{{\smallcaps#1}}       % smallcaps font
+\def\ii#1{{\it #1}}             % italic font
+
+% @b, explicit bold.  Also @strong.
 \def\b#1{{\bf #1}}
 \let\strong=\b
 
+% @sansserif, explicit sans.
+\def\sansserif#1{{\sf #1}}
+
 % We can't just use \exhyphenpenalty, because that only has effect at
 % the end of a paragraph.  Restore normal hyphenation at the end of the
 % group within which \nohyphenation is presumably called.
@@ -1735,35 +2425,34 @@
 % sometimes \x has an active definition that messes things up.
 %
 \catcode`@=11
-  \def\frenchspacing{%
+  \def\plainfrenchspacing{%
     \sfcode\dotChar  =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m
     \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m
+    \def\endofsentencespacefactor{1000}% for @. and friends
   }
+  \def\plainnonfrenchspacing{%
+    \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000
+    \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250
+    \def\endofsentencespacefactor{3000}% for @. and friends
+  }
 \catcode`@=\other
+\def\endofsentencespacefactor{3000}% default
 
+% @t, explicit typewriter.
 \def\t#1{%
-  {\tt \rawbackslash \frenchspacing #1}%
+  {\tt \rawbackslash \plainfrenchspacing #1}%
   \null
 }
-\def\samp#1{`\tclose{#1}'\null}
-\setfont\keyrm\rmshape{8}{1000}
-\font\keysy=cmsy9
-\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
-  \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
-    \vbox{\hrule\kern-0.4pt
-     \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
-    \kern-0.4pt\hrule}%
-  \kern-.06em\raise0.4pt\hbox{\angleright}}}}
-% The old definition, with no lozenge:
-%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
-\def\ctrl #1{{\tt \rawbackslash \hat}#1}
 
-% @file, @option are the same as @samp.
-\let\file=\samp
-\let\option=\samp
+% @samp.
+\def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}}
 
-% @code is a modification of @t,
-% which makes spaces the same size as normal in the surrounding text.
+% @indicateurl is \samp, that is, with quotes.
+\let\indicateurl=\samp
+
+% @code (and similar) prints in typewriter, but with spaces the same
+% size as normal in the surrounding text, without hyphenation, etc.
+% This is a subroutine for that.
 \def\tclose#1{%
   {%
     % Change normal interword space to be same as for the current font.
@@ -1779,16 +2468,16 @@
     \nohyphenation
     %
     \rawbackslash
-    \frenchspacing
+    \plainfrenchspacing
     #1%
   }%
-  \null
+  \null % reset spacefactor to 1000
 }
 
 % We *must* turn on hyphenation at `-' and `_' in @code.
 % Otherwise, it is too hard to avoid overfull hboxes
 % in the Emacs manual, the Library manual, etc.
-
+%
 % Unfortunately, TeX uses one parameter (\hyphenchar) to control
 % both hyphenation at - and hyphenation within words.
 % We must therefore turn them both off (\tclose does that)
@@ -1795,17 +2484,28 @@
 % and arrange explicitly to hyphenate at a dash.
 %  -- rms.
 {
-  \catcode`\-=\active
-  \catcode`\_=\active
+  \catcode`\-=\active \catcode`\_=\active
+  \catcode`\'=\active \catcode`\`=\active
+  \global\let'=\rq \global\let`=\lq  % default definitions
   %
   \global\def\code{\begingroup
-    \catcode`\-=\active \let-\codedash
-    \catcode`\_=\active \let_\codeunder
+    \setupmarkupstyle{code}%
+    % The following should really be moved into \setupmarkupstyle handlers.
+    \catcode\dashChar=\active  \catcode\underChar=\active
+    \ifallowcodebreaks
+     \let-\codedash
+     \let_\codeunder
+    \else
+     \let-\normaldash
+     \let_\realunder
+    \fi
     \codex
   }
 }
 
-\def\realdash{-}
+\def\codex #1{\tclose{#1}\endgroup}
+
+\def\normaldash{-}
 \def\codedash{-\discretionary{}{}{}}
 \def\codeunder{%
   % this is all so @math{@code{var_name}+1} can work.  In math mode, _
@@ -1818,53 +2518,44 @@
              \discretionary{}{}{}}%
             {\_}%
 }
-\def\codex #1{\tclose{#1}\endgroup}
 
-% @kbd is like @code, except that if the argument is just one @key command,
-% then @kbd has no effect.
+% An additional complication: the above will allow breaks after, e.g.,
+% each of the four underscores in __typeof__.  This is bad.
+% @allowcodebreaks provides a document-level way to turn breaking at -
+% and _ on and off.
+%
+\newif\ifallowcodebreaks  \allowcodebreakstrue
 
-% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
-%   `example' (@kbd uses ttsl only inside of @example and friends),
-%   or `code' (@kbd uses normal tty font always).
-\parseargdef\kbdinputstyle{%
-  \def\arg{#1}%
-  \ifx\arg\worddistinct
-    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
-  \else\ifx\arg\wordexample
-    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
-  \else\ifx\arg\wordcode
-    \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+\def\keywordtrue{true}
+\def\keywordfalse{false}
+
+\parseargdef\allowcodebreaks{%
+  \def\txiarg{#1}%
+  \ifx\txiarg\keywordtrue
+    \allowcodebreakstrue
+  \else\ifx\txiarg\keywordfalse
+    \allowcodebreaksfalse
   \else
     \errhelp = \EMsimple
-    \errmessage{Unknown @kbdinputstyle option `\arg'}%
-  \fi\fi\fi
+    \errmessage{Unknown @allowcodebreaks option `\txiarg', must be true|false}%
+  \fi\fi
 }
-\def\worddistinct{distinct}
-\def\wordexample{example}
-\def\wordcode{code}
 
-% Default is `distinct.'
-\kbdinputstyle distinct
-
-\def\xkey{\key}
-\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
-\ifx\one\xkey\ifx\threex\three \key{#2}%
-\else{\tclose{\kbdfont\look}}\fi
-\else{\tclose{\kbdfont\look}}\fi}
-
-% For @indicateurl, @env, @command quotes seem unnecessary, so use \code.
-\let\indicateurl=\code
+% For @command, @env, @file, @option quotes seem unnecessary,
+% so use \code rather than \samp.
+\let\command=\code
 \let\env=\code
-\let\command=\code
+\let\file=\code
+\let\option=\code
 
 % @uref (abbreviation for `urlref') takes an optional (comma-separated)
 % second argument specifying the text to display and an optional third
 % arg as text to display instead of (rather than in addition to) the url
-% itself.  First (mandatory) arg is the url.  Perhaps eventually put in
-% a hypertex \special here.
-%
-\def\uref#1{\douref #1,,,\finish}
-\def\douref#1,#2,#3,#4\finish{\begingroup
+% itself.  First (mandatory) arg is the url.
+% (This \urefnobreak definition isn't used now, leaving it for a while
+% for comparison.)
+\def\urefnobreak#1{\dourefnobreak #1,,,\finish}
+\def\dourefnobreak#1,#2,#3,#4\finish{\begingroup
   \unsepspaces
   \pdfurl{#1}%
   \setbox0 = \hbox{\ignorespaces #3}%
@@ -1885,6 +2576,103 @@
   \endlink
 \endgroup}
 
+% This \urefbreak definition is the active one.
+\def\urefbreak{\begingroup \urefcatcodes \dourefbreak}
+\let\uref=\urefbreak
+\def\dourefbreak#1{\urefbreakfinish #1,,,\finish}
+\def\urefbreakfinish#1,#2,#3,#4\finish{% doesn't work in @example
+  \unsepspaces
+  \pdfurl{#1}%
+  \setbox0 = \hbox{\ignorespaces #3}%
+  \ifdim\wd0 > 0pt
+    \unhbox0 % third arg given, show only that
+  \else
+    \setbox0 = \hbox{\ignorespaces #2}%
+    \ifdim\wd0 > 0pt
+      \ifpdf
+        \unhbox0             % PDF: 2nd arg given, show only it
+      \else
+        \unhbox0\ (\urefcode{#1})% DVI: 2nd arg given, show both it and url
+      \fi
+    \else
+      \urefcode{#1}% only url given, so show it
+    \fi
+  \fi
+  \endlink
+\endgroup}
+
+% Allow line breaks around only a few characters (only).
+\def\urefcatcodes{%
+  \catcode\ampChar=\active   \catcode\dotChar=\active
+  \catcode\hashChar=\active  \catcode\questChar=\active
+  \catcode\slashChar=\active
+}
+{
+  \urefcatcodes
+  %
+  \global\def\urefcode{\begingroup
+    \setupmarkupstyle{code}%
+    \urefcatcodes
+    \let&\urefcodeamp
+    \let.\urefcodedot
+    \let#\urefcodehash
+    \let?\urefcodequest
+    \let/\urefcodeslash
+    \codex
+  }
+  %
+  % By default, they are just regular characters.
+  \global\def&{\normalamp}
+  \global\def.{\normaldot}
+  \global\def#{\normalhash}
+  \global\def?{\normalquest}
+  \global\def/{\normalslash}
+}
+
+% we put a little stretch before and after the breakable chars, to help
+% line breaking of long url's.  The unequal skips make look better in
+% cmtt at least, especially for dots.
+\def\urefprestretch{\urefprebreak \hskip0pt plus.13em }
+\def\urefpoststretch{\urefpostbreak \hskip0pt plus.1em }
+%
+\def\urefcodeamp{\urefprestretch \&\urefpoststretch}
+\def\urefcodedot{\urefprestretch .\urefpoststretch}
+\def\urefcodehash{\urefprestretch \#\urefpoststretch}
+\def\urefcodequest{\urefprestretch ?\urefpoststretch}
+\def\urefcodeslash{\futurelet\next\urefcodeslashfinish}
+{
+  \catcode`\/=\active
+  \global\def\urefcodeslashfinish{%
+    \urefprestretch \slashChar
+    % Allow line break only after the final / in a sequence of
+    % slashes, to avoid line break between the slashes in http://.
+    \ifx\next/\else \urefpoststretch \fi
+  }
+}
+
+% One more complication: by default we'll break after the special
+% characters, but some people like to break before the special chars, so
+% allow that.  Also allow no breaking at all, for manual control.
+% 
+\parseargdef\urefbreakstyle{%
+  \def\txiarg{#1}%
+  \ifx\txiarg\wordnone
+    \def\urefprebreak{\nobreak}\def\urefpostbreak{\nobreak}
+  \else\ifx\txiarg\wordbefore
+    \def\urefprebreak{\allowbreak}\def\urefpostbreak{\nobreak}
+  \else\ifx\txiarg\wordafter
+    \def\urefprebreak{\nobreak}\def\urefpostbreak{\allowbreak}
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @urefbreakstyle setting `\txiarg'}%
+  \fi\fi\fi
+}
+\def\wordafter{after}
+\def\wordbefore{before}
+\def\wordnone{none}
+
+\urefbreakstyle after
+
 % @url synonym for @uref, since that's how everyone uses it.
 %
 \let\url=\uref
@@ -1906,34 +2694,81 @@
   \let\email=\uref
 \fi
 
-% Check if we are currently using a typewriter font.  Since all the
-% Computer Modern typewriter fonts have zero interword stretch (and
-% shrink), and it is reasonable to expect all typewriter fonts to have
-% this property, we can check that font parameter.
+% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
+%   `example' (@kbd uses ttsl only inside of @example and friends),
+%   or `code' (@kbd uses normal tty font always).
+\parseargdef\kbdinputstyle{%
+  \def\txiarg{#1}%
+  \ifx\txiarg\worddistinct
+    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
+  \else\ifx\txiarg\wordexample
+    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
+  \else\ifx\txiarg\wordcode
+    \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @kbdinputstyle setting `\txiarg'}%
+  \fi\fi\fi
+}
+\def\worddistinct{distinct}
+\def\wordexample{example}
+\def\wordcode{code}
+
+% Default is `distinct'.
+\kbdinputstyle distinct
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+\def\kbd#1{{\def\look{#1}\expandafter\kbdsub\look??\par}}
+
+\def\xkey{\key}
+\def\kbdsub#1#2#3\par{%
+  \def\one{#1}\def\three{#3}\def\threex{??}%
+  \ifx\one\xkey\ifx\threex\three \key{#2}%
+  \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi
+  \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi
+}
+
+% definition of @key that produces a lozenge.  Doesn't adjust to text size.
+%\setfont\keyrm\rmshape{8}{1000}{OT1}
+%\font\keysy=cmsy9
+%\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
+%  \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
+%    \vbox{\hrule\kern-0.4pt
+%     \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
+%    \kern-0.4pt\hrule}%
+%  \kern-.06em\raise0.4pt\hbox{\angleright}}}}
+
+% definition of @key with no lozenge.  If the current font is already
+% monospace, don't change it; that way, we respect @kbdinputstyle.  But
+% if it isn't monospace, then use \tt.
 %
-\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+\def\key#1{{\setupmarkupstyle{key}%
+  \nohyphenation
+  \ifmonospace\else\tt\fi
+  #1}\null}
 
+% @clicksequence{File @click{} Open ...}
+\def\clicksequence#1{\begingroup #1\endgroup}
+
+% @clickstyle @arrow   (by default)
+\parseargdef\clickstyle{\def\click{#1}}
+\def\click{\arrow}
+
 % Typeset a dimension, e.g., `in' or `pt'.  The only reason for the
 % argument is to make the input look right: @dmn{pt} instead of @dmn{}pt.
 %
 \def\dmn#1{\thinspace #1}
 
-\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
-
 % @l was never documented to mean ``switch to the Lisp font'',
 % and it is not used as such in any manual I can find.  We need it for
 % Polish suppressed-l.  --karl, 22sep96.
 %\def\l#1{{\li #1}\null}
 
-% Explicit font changes: @r, @sc, undocumented @ii.
-\def\r#1{{\rm #1}}              % roman font
-\def\sc#1{{\smallcaps#1}}       % smallcaps font
-\def\ii#1{{\it #1}}             % italic font
-
 % @acronym for "FBI", "NATO", and the like.
 % We print this one point size smaller, since it's intended for
 % all-uppercase.
-% 
+%
 \def\acronym#1{\doacronym #1,,\finish}
 \def\doacronym#1,#2,#3\finish{%
   {\selectfonts\lsize #1}%
@@ -1941,24 +2776,392 @@
   \ifx\temp\empty \else
     \space ({\unsepspaces \ignorespaces \temp \unskip})%
   \fi
+  \null % reset \spacefactor=1000
 }
 
 % @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}%
+  {\plainfrenchspacing #1}%
   \def\temp{#2}%
   \ifx\temp\empty \else
     \space ({\unsepspaces \ignorespaces \temp \unskip})%
   \fi
+  \null % reset \spacefactor=1000
 }
 
+% @asis just yields its argument.  Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math outputs its argument in math mode.
+%
+% One complication: _ usually means subscripts, but it could also mean
+% an actual _ character, as in @math{@var{some_variable} + 1}.  So make
+% _ active, and distinguish by seeing if the current family is \slfam,
+% which is what @var uses.
+{
+  \catcode`\_ = \active
+  \gdef\mathunderscore{%
+    \catcode`\_=\active
+    \def_{\ifnum\fam=\slfam \_\else\sb\fi}%
+  }
+}
+% Another complication: we want \\ (and @\) to output a math (or tt) \.
+% FYI, plain.tex uses \\ as a temporary control sequence (for no
+% particular reason), but this is not advertised and we don't care.
+%
+% 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
+  % make the texinfo accent commands work in math mode
+  \let\"=\ddot
+  \let\'=\acute
+  \let\==\bar
+  \let\^=\hat
+  \let\`=\grave
+  \let\u=\breve
+  \let\v=\check
+  \let\~=\tilde
+  \let\dotaccent=\dot
+  $\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
+  \catcode`' = \active
+  \gdef\mathactive{%
+    \let^ = \ptexhat
+    \let< = \ptexless
+    \let> = \ptexgtr
+    \let+ = \ptexplus
+    \let' = \ptexquoteright
+  }
+}
+
+% ctrl is no longer a Texinfo command, but leave this definition for fun.
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+% @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}.
+% Ignore unless FMTNAME == tex; then it is like @iftex and @tex,
+% except specified as a normal braced arg, so no newlines to worry about.
+% 
+\def\outfmtnametex{tex}
+%
+\long\def\inlinefmt#1{\doinlinefmt #1,\finish}
+\long\def\doinlinefmt#1,#2,\finish{%
+  \def\inlinefmtname{#1}%
+  \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\fi
+}
+% For raw, must switch into @tex before parsing the argument, to avoid
+% setting catcodes prematurely.  Doing it this way means that, for
+% example, @inlineraw{html, foo{bar} gets a parse error instead of being
+% ignored.  But this isn't important because if people want a literal
+% *right* brace they would have to use a command anyway, so they may as
+% well use a command to get a left brace too.  We could re-use the
+% delimiter character idea from \verb, but it seems like overkill.
+% 
+\long\def\inlineraw{\tex \doinlineraw}
+\long\def\doinlineraw#1{\doinlinerawtwo #1,\finish}
+\def\doinlinerawtwo#1,#2,\finish{%
+  \def\inlinerawname{#1}%
+  \ifx\inlinerawname\outfmtnametex \ignorespaces #2\fi
+  \endgroup % close group opened by \tex.
+}
+
+
+\message{glyphs,}
+% and logos.
+
+% @@ prints an @, as does @atchar{}.
+\def\@{\char64 }
+\let\atchar=\@
+
+% @{ @} @lbracechar{} @rbracechar{} all generate brace characters.
+% Unless we're in typewriter, use \ecfont because the CM text fonts do
+% not have braces, and we don't want to switch into math.
+\def\mylbrace{{\ifmonospace\else\ecfont\fi \char123}}
+\def\myrbrace{{\ifmonospace\else\ecfont\fi \char125}}
+\let\{=\mylbrace \let\lbracechar=\{
+\let\}=\myrbrace \let\rbracechar=\}
+\begingroup
+  % Definitions to produce \{ and \} commands for indices,
+  % and @{ and @} for the aux/toc files.
+  \catcode`\{ = \other \catcode`\} = \other
+  \catcode`\[ = 1 \catcode`\] = 2
+  \catcode`\! = 0 \catcode`\\ = \other
+  !gdef!lbracecmd[\{]%
+  !gdef!rbracecmd[\}]%
+  !gdef!lbraceatcmd[@{]%
+  !gdef!rbraceatcmd[@}]%
+!endgroup
+
+% @comma{} to avoid , parsing problems.
+\let\comma = ,
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
+\let\, = \ptexc
+\let\dotaccent = \ptexdot
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \ptext
+\let\ubaraccent = \ptexb
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown @ordf @ordm
+% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}}
+\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+  \def\temp{#1}%
+  \ifx\temp\imacro \ifmmode\imath \else\ptexi \fi
+  \else\ifx\temp\jmacro \ifmmode\jmath \else\j \fi
+  \else \errmessage{@dotless can be used only with i or j}%
+  \fi\fi
+}
+
+% The \TeX{} logo, as in plain, but resetting the spacing so that a
+% period following counts as ending a sentence.  (Idea found in latex.)
+%
+\edef\TeX{\TeX \spacefactor=1000 }
+
+% @LaTeX{} logo.  Not quite the same results as the definition in
+% latex.ltx, since we use a different font for the raised A; it's most
+% convenient for us to use an explicitly smaller font, rather than using
+% the \scriptstyle font (since we don't reset \scriptstyle and
+% \scriptscriptstyle).
+%
+\def\LaTeX{%
+  L\kern-.36em
+  {\setbox0=\hbox{T}%
+   \vbox to \ht0{\hbox{%
+     \ifx\textnominalsize\xwordpt
+       % for 10pt running text, \lllsize (8pt) is too small for the A in LaTeX.
+       % Revert to plain's \scriptsize, which is 7pt.
+       \count255=\the\fam $\fam\count255 \scriptstyle A$%
+     \else
+       % For 11pt, we can use our lllsize.
+       \selectfonts\lllsize A%
+     \fi
+     }%
+     \vss
+  }}%
+  \kern-.15em
+  \TeX
+}
+
+% Some math mode symbols.
+\def\bullet{$\ptexbullet$}
+\def\geq{\ifmmode \ge\else $\ge$\fi}
+\def\leq{\ifmmode \le\else $\le$\fi}
+\def\minus{\ifmmode -\else $-$\fi}
+
+% @dots{} outputs an ellipsis using the current font.
+% We do .5em per period so that it has the same spacing in the cm
+% typewriter fonts as three actual period characters; on the other hand,
+% in other typewriter fonts three periods are wider than 1.5em.  So do
+% whichever is larger.
+%
+\def\dots{%
+  \leavevmode
+  \setbox0=\hbox{...}% get width of three periods
+  \ifdim\wd0 > 1.5em
+    \dimen0 = \wd0
+  \else
+    \dimen0 = 1.5em
+  \fi
+  \hbox to \dimen0{%
+    \hskip 0pt plus.25fil
+    .\hskip 0pt plus1fil
+    .\hskip 0pt plus1fil
+    .\hskip 0pt plus.5fil
+  }%
+}
+
+% @enddots{} is an end-of-sentence ellipsis.
+%
+\def\enddots{%
+  \dots
+  \spacefactor=\endofsentencespacefactor
+}
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+%
+% Since these characters are used in examples, they should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+%
+\def\point{$\star$}
+\def\arrow{\leavevmode\raise.05ex\hbox to 1em{\hfil$\rightarrow$\hfil}}
+\def\result{\leavevmode\raise.05ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+\def\equiv{\leavevmode\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 \reducedsf \putworderror\kern-1.5pt}
+%
+\setbox\errorbox=\hbox to \dimen0{\hfil
+   \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+   \advance\hsize by -2\dimen2 % Rules.
+   \vbox{%
+      \hrule height\dimen2
+      \hbox{\vrule width\dimen2 \kern3pt          % Space to left of text.
+         \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+         \kern3pt\vrule width\dimen2}% Space to right.
+      \hrule height\dimen2}
+    \hfil}
+%
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
 % @pounds{} is a sterling sign, which Knuth put in the CM italic font.
 %
 \def\pounds{{\it\$}}
 
+% @euro{} comes from a separate font, depending on the current style.
+% We use the free feym* fonts from the eurosym package by Henrik
+% Theiling, which support regular, slanted, bold and bold slanted (and
+% "outlined" (blackboard board, sort of) versions, which we don't need).
+% It is available from http://www.ctan.org/tex-archive/fonts/eurosym.
+%
+% Although only regular is the truly official Euro symbol, we ignore
+% that.  The Euro is designed to be slightly taller than the regular
+% font height.
+%
+% feymr - regular
+% feymo - slanted
+% feybr - bold
+% feybo - bold slanted
+%
+% There is no good (free) typewriter version, to my knowledge.
+% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide.
+% Hmm.
+%
+% Also doesn't work in math.  Do we need to do math with euro symbols?
+% Hope not.
+%
+%
+\def\euro{{\eurofont e}}
+\def\eurofont{%
+  % We set the font at each command, rather than predefining it in
+  % \textfonts and the other font-switching commands, so that
+  % installations which never need the symbol don't have to have the
+  % font installed.
+  %
+  % There is only one designed size (nominal 10pt), so we always scale
+  % that to the current nominal size.
+  %
+  % By the way, simply using "at 1em" works for cmr10 and the like, but
+  % does not work for cmbx10 and other extended/shrunken fonts.
+  %
+  \def\eurosize{\csname\curfontsize nominalsize\endcsname}%
+  %
+  \ifx\curfontstyle\bfstylename
+    % bold:
+    \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize
+  \else
+    % regular:
+    \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize
+  \fi
+  \thiseurofont
+}
+
+% Glyphs from the EC fonts.  We don't use \let for the aliases, because
+% sometimes we redefine the original macro, and the alias should reflect
+% the redefinition.
+%
+% Use LaTeX names for the Icelandic letters.
+\def\DH{{\ecfont \char"D0}} % Eth
+\def\dh{{\ecfont \char"F0}} % eth
+\def\TH{{\ecfont \char"DE}} % Thorn
+\def\th{{\ecfont \char"FE}} % thorn
+%
+\def\guillemetleft{{\ecfont \char"13}}
+\def\guillemotleft{\guillemetleft}
+\def\guillemetright{{\ecfont \char"14}}
+\def\guillemotright{\guillemetright}
+\def\guilsinglleft{{\ecfont \char"0E}}
+\def\guilsinglright{{\ecfont \char"0F}}
+\def\quotedblbase{{\ecfont \char"12}}
+\def\quotesinglbase{{\ecfont \char"0D}}
+%
+% This positioning is not perfect (see the ogonek LaTeX package), but
+% we have the precomposed glyphs for the most common cases.  We put the
+% tests to use those glyphs in the single \ogonek macro so we have fewer
+% dummy definitions to worry about for index entries, etc.
+%
+% ogonek is also used with other letters in Lithuanian (IOU), but using
+% the precomposed glyphs for those is not so easy since they aren't in
+% the same EC font.
+\def\ogonek#1{{%
+  \def\temp{#1}%
+  \ifx\temp\macrocharA\Aogonek
+  \else\ifx\temp\macrochara\aogonek
+  \else\ifx\temp\macrocharE\Eogonek
+  \else\ifx\temp\macrochare\eogonek
+  \else
+    \ecfont \setbox0=\hbox{#1}%
+    \ifdim\ht0=1ex\accent"0C #1%
+    \else\ooalign{\unhbox0\crcr\hidewidth\char"0C \hidewidth}%
+    \fi
+  \fi\fi\fi\fi
+  }%
+}
+\def\Aogonek{{\ecfont \char"81}}\def\macrocharA{A}
+\def\aogonek{{\ecfont \char"A1}}\def\macrochara{a}
+\def\Eogonek{{\ecfont \char"86}}\def\macrocharE{E}
+\def\eogonek{{\ecfont \char"A6}}\def\macrochare{e}
+%
+% Use the ec* fonts (cm-super in outline format) for non-CM glyphs.
+\def\ecfont{%
+  % We can't distinguish serif/sans and italic/slanted, but this
+  % is used for crude hacks anyway (like adding French and German
+  % quotes to documents typeset with CM, where we lose kerning), so
+  % hopefully nobody will notice/care.
+  \edef\ecsize{\csname\curfontsize ecsize\endcsname}%
+  \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}%
+  \ifmonospace
+    % typewriter:
+    \font\thisecfont = ectt\ecsize \space at \nominalsize
+  \else
+    \ifx\curfontstyle\bfstylename
+      % bold:
+      \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize
+    \else
+      % regular:
+      \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize
+    \fi
+  \fi
+  \thisecfont
+}
+
 % @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.
@@ -1969,15 +3172,25 @@
     }$%
 }
 
+% @textdegree - the normal degrees sign.
+%
+\def\textdegree{$^\circ$}
+
 % 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
+%
+\ifx\Orb\thisisundefined
 \def\Orb{\mathhexbox20D}
 \fi
 
+% Quotes.
+\chardef\quotedblleft="5C
+\chardef\quotedblright=`\"
+\chardef\quoteleft=`\`
+\chardef\quoteright=`\'
 
+
 \message{page headings,}
 
 \newskip\titlepagetopglue \titlepagetopglue = 1.5in
@@ -1995,8 +3208,9 @@
 \newif\ifsetshortcontentsaftertitlepage
  \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue
 
-\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
-        \endgroup\page\hbox{}\page}
+\parseargdef\shorttitlepage{%
+  \begingroup \hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+  \endgroup\page\hbox{}\page}
 
 \envdef\titlepage{%
   % Open one extra group, as we want to close it in the middle of \Etitlepage.
@@ -2056,17 +3270,28 @@
   \finishedtitlepagetrue
 }
 
-%%% Macros to be used within @titlepage:
+% Settings used for typesetting titles: no hyphenation, no indentation,
+% don't worry much about spacing, ragged right.  This should be used
+% inside a \vbox, and fonts need to be set appropriately first.  Because
+% it is always used for titles, nothing else, we call \rmisbold.  \par
+% should be specified before the end of the \vbox, since a vbox is a group.
+% 
+\def\raggedtitlesettings{%
+  \rmisbold
+  \hyphenpenalty=10000
+  \parindent=0pt
+  \tolerance=5000
+  \ptexraggedright
+}
 
+% 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}
+  \vbox{\titlefonts \raggedtitlesettings #1\par}%
   % print a rule at the page bottom also.
   \finishedtitlepagefalse
   \vskip4pt \hrule height 4pt width \hsize \vskip4pt
@@ -2087,12 +3312,12 @@
   \else
     \checkenv\titlepage
     \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi
-    {\authorfont \leftline{#1}}%
+    {\secfonts\rmisbold \leftline{#1}}%
   \fi
 }
 
 
-%%% Set up page headings and footings.
+% Set up page headings and footings.
 
 \let\thispage=\folio
 
@@ -2140,13 +3365,40 @@
   %
   % Leave some space for the footline.  Hopefully ok to assume
   % @evenfooting will not be used by itself.
-  \global\advance\pageheight by -\baselineskip
-  \global\advance\vsize by -\baselineskip
+  \global\advance\pageheight by -12pt
+  \global\advance\vsize by -12pt
 }
 
 \parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}}
 
+% @evenheadingmarks top     \thischapter <- chapter at the top of a page
+% @evenheadingmarks bottom  \thischapter <- chapter at the bottom of a page
+%
+% The same set of arguments for:
+%
+% @oddheadingmarks
+% @evenfootingmarks
+% @oddfootingmarks
+% @everyheadingmarks
+% @everyfootingmarks
 
+\def\evenheadingmarks{\headingmarks{even}{heading}}
+\def\oddheadingmarks{\headingmarks{odd}{heading}}
+\def\evenfootingmarks{\headingmarks{even}{footing}}
+\def\oddfootingmarks{\headingmarks{odd}{footing}}
+\def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1}
+                          \headingmarks{odd}{heading}{#1} }
+\def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1}
+                          \headingmarks{odd}{footing}{#1} }
+% #1 = even/odd, #2 = heading/footing, #3 = top/bottom.
+\def\headingmarks#1#2#3 {%
+  \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname
+  \global\expandafter\let\csname get#1#2marks\endcsname \temp
+}
+
+\everyheadingmarks bottom
+\everyfootingmarks bottom
+
 % @headings double      turns headings on for double-sided printing.
 % @headings single      turns headings on for single-sided printing.
 % @headings off         turns them off.
@@ -2159,10 +3411,14 @@
 
 \def\headings #1 {\csname HEADINGS#1\endcsname}
 
-\def\HEADINGSoff{%
-\global\evenheadline={\hfil} \global\evenfootline={\hfil}
-\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
-\HEADINGSoff
+\def\headingsoff{% non-global headings elimination
+  \evenheadline={\hfil}\evenfootline={\hfil}%
+   \oddheadline={\hfil}\oddfootline={\hfil}%
+}
+
+\def\HEADINGSoff{{\globaldefs=1 \headingsoff}} % global setting
+\HEADINGSoff  % it's the default
+
 % When we turn headings on, set the page number to 1.
 % For double-sided printing, put current file name in lower left corner,
 % chapter name on inside top of right hand pages, document
@@ -2213,7 +3469,7 @@
 % 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
+\ifx\today\thisisundefined
 \def\today{%
   \number\day\space
   \ifcase\month
@@ -2274,7 +3530,7 @@
     \begingroup
       \advance\leftskip by-\tableindent
       \advance\hsize by\tableindent
-      \advance\rightskip by0pt plus1fil
+      \advance\rightskip by0pt plus1fil\relax
       \leavevmode\unhbox0\par
     \endgroup
     %
@@ -2288,7 +3544,7 @@
     % 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
@@ -2314,16 +3570,27 @@
 % @table, @ftable, @vtable.
 \envdef\table{%
   \let\itemindex\gobble
-  \tablex
+  \tablecheck{table}%
 }
 \envdef\ftable{%
   \def\itemindex ##1{\doind {fn}{\code{##1}}}%
-  \tablex
+  \tablecheck{ftable}%
 }
 \envdef\vtable{%
   \def\itemindex ##1{\doind {vr}{\code{##1}}}%
-  \tablex
+  \tablecheck{vtable}%
 }
+\def\tablecheck#1{%
+  \ifnum \the\catcode`\^^M=\active
+    \endgroup
+    \errmessage{This command won't work in this context; perhaps the problem is
+      that we are \inenvironment\thisenv}%
+    \def\next{\doignore{#1}}%
+  \else
+    \let\next\tablex
+  \fi
+  \next
+}
 \def\tablex#1{%
   \def\itemindicate{#1}%
   \parsearg\tabley
@@ -2371,9 +3638,18 @@
   \parindent=0pt
   \parskip=\smallskipamount
   \ifdim\parskip=0pt \parskip=2pt \fi
+  %
+  % Try typesetting the item mark that if the document erroneously says
+  % something like @itemize @samp (intending @table), there's an error
+  % right away at the @itemize.  It's not the best error message in the
+  % world, but it's better than leaving it to the @item.  This means if
+  % the user wants an empty mark, they have to say @w{} not just @w.
   \def\itemcontents{#1}%
+  \setbox0 = \hbox{\itemcontents}%
+  %
   % @itemize with no arg is equivalent to @itemize @bullet.
   \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi
+  %
   \let\item=\itemizeitem
 }
 
@@ -2394,6 +3670,7 @@
    \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
 }
@@ -2615,12 +3892,19 @@
 %
 % @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}%
+% of an alignment entry.  \everycr resets \everytab so we don't have to
+% undo it ourselves.
+\def\headitemfont{\b}% for people to use in the template row; not changeable
+\def\headitem{%
+  \checkenv\multitable
+  \crcr
+  \global\everytab={\bf}% can't use \headitemfont since the parsing differs
+  \the\everytab % for the first item
+}%
 %
 % 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.
+% we again encounter the problem the 1sp was intended to solve.
 %					--karl, nathan at acm.org, 20apr99.
 \def\tab{\checkenv\multitable &\the\everytab}%
 
@@ -2721,31 +4005,29 @@
   \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.
+\def\setmultitablespacing{%
+  \def\multistrut{\strut}% just use the standard line spacing
+  %
+  % Compute \multitablelinespace (if not defined by user) for use in
+  % \multitableparskip calculation.  We used define \multistrut based on
+  % this, but (ironically) that caused the spacing to be off.
+  % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100.
 \ifdim\multitablelinespace=0pt
 \setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip
 \global\advance\multitablelinespace by-\ht0
-%% strut to put in table in case some entry doesn't have descenders,
-%% to keep lines equally spaced
-\let\multistrut = \strut
-\else
-%% FIXME: what is \box0 supposed to be?
-\gdef\multistrut{\vrule height\multitablelinespace depth\dp0
-width0pt\relax} \fi
-%% Test to see if parskip is larger than space between lines of
-%% table. If not, do nothing.
-%%        If so, set to same dimension as multitablelinespace.
+\fi
+% Test to see if parskip is larger than space between lines of
+% table. If not, do nothing.
+%        If so, set to same dimension as multitablelinespace.
 \ifdim\multitableparskip>\multitablelinespace
 \global\multitableparskip=\multitablelinespace
-\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
-                                      %% than skip between lines in the table.
+\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller
+                                      % than skip between lines in the table.
 \fi%
 \ifdim\multitableparskip=0pt
 \global\multitableparskip=\multitablelinespace
-\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
-                                      %% than skip between lines in the table.
+\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller
+                                      % than skip between lines in the table.
 \fi}
 
 
@@ -2791,6 +4073,7 @@
 
 \def\doignore#1{\begingroup
   % Scan in ``verbatim'' mode:
+  \obeylines
   \catcode`\@ = \other
   \catcode`\{ = \other
   \catcode`\} = \other
@@ -2811,9 +4094,10 @@
   \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 at end #1{\doignoretextyyy##1^^M@#1\_STOP_}%
+    % Define a command to find the next `@end #1'.
+    \long\def\doignoretext##1^^M at 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.)
@@ -2820,7 +4104,6 @@
     \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}%
     %
     % And now expand that command.
-    \obeylines %
     \doignoretext ^^M%
   }%
 }
@@ -2850,7 +4133,12 @@
 }
 
 % Finish off ignored text.
-\def\enddoignore{\endgroup\ignorespaces}
+{ \obeylines%
+  % Ignore anything after the last `@end #1'; this matters in verbatim
+  % environments, where otherwise the newline after an ignored conditional
+  % would result in a blank line in the output.
+  \gdef\enddoignore#1^^M{\endgroup\ignorespaces}%
+}
 
 
 % @set VAR sets the variable VAR to an empty value.
@@ -2900,7 +4188,7 @@
     % ..., 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
+    \let-\normaldash \let_\normalunderscore
   }
 }
 
@@ -2940,7 +4228,7 @@
 }
 \def\ifsetfail{\doignore{ifset}}
 
-% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% @ifclear VAR ... @end executes 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
@@ -2951,6 +4239,35 @@
 \def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}}
 \def\ifclearfail{\doignore{ifclear}}
 
+% @ifcommandisdefined CMD ... @end executes the `...' if CMD (written
+% without the @) is in fact defined.  We can only feasibly check at the
+% TeX level, so something like `mathcode' is going to considered
+% defined even though it is not a Texinfo command.
+% 
+\makecond{ifcommanddefined}
+\def\ifcommanddefined{\parsearg{\doifcmddefined{\let\next=\ifcmddefinedfail}}}
+%
+\def\doifcmddefined#1#2{{%
+    \makevalueexpandable
+    \let\next=\empty
+    \expandafter\ifx\csname #2\endcsname\relax
+      #1% If not defined, \let\next as above.
+    \fi
+    \expandafter
+  }\next
+}
+\def\ifcmddefinedfail{\doignore{ifcommanddefined}}
+
+% @ifcommandnotdefined CMD ... handled similar to @ifclear above.
+\makecond{ifcommandnotdefined}
+\def\ifcommandnotdefined{%
+  \parsearg{\doifcmddefined{\else \let\next=\ifcmdnotdefinedfail}}}
+\def\ifcmdnotdefinedfail{\doignore{ifcommandnotdefined}}
+
+% Set the `txicommandconditionals' variable, so documents have a way to
+% test if the @ifcommand...defined conditionals are available.
+\set txicommandconditionals
+
 % @dircategory CATEGORY  -- specify a category of the dir file
 % which this file should belong to.  Ignore this in TeX.
 \let\dircategory=\comment
@@ -2963,9 +4280,8 @@
 % Index generation facilities
 
 % Define \newwrite to be identical to plain tex's \newwrite
-% except not \outer, so it can be used within \newindex.
-{\catcode`\@=11
-\gdef\newwrite{\alloc at 7\write\chardef\sixt@@n}}
+% except not \outer, so it can be used within macros and \if's.
+\edef\newwrite{\makecsname{ptexnewwrite}}
 
 % \newindex {foo} defines an index named foo.
 % It automatically defines \fooindex such that
@@ -3016,11 +4332,11 @@
 \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
+  \expandafter \ifx\csname donesynindex#2\endcsname \relax
     % 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
+    \expandafter\let\csname donesynindex#2\endcsname = 1
   \fi
   % redefine \fooindfile:
   \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname
@@ -3051,42 +4367,53 @@
 % we have to laboriously prevent expansion for those that we don't.
 %
 \def\indexdummies{%
+  \escapechar = `\\     % use backslash in output files.
   \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.
+  % Need these unexpandable (because we define \tt as a dummy)
+  % definitions when @{ or @} appear in index entry text.  Also, more
+  % complicated, when \tex is in effect and \{ is a \delimiter again.
+  % We can't use \lbracecmd and \rbracecmd because texindex assumes
+  % braces and backslashes are used only as delimiters.  Perhaps we
+  % should define @lbrace and @rbrace commands a la @comma.
+  \def\{{{\tt\char123}}%
+  \def\}{{\tt\char125}}%
   %
-  % For control letters, we have \definedummyletter, which omits the
-  % space.
+  % I don't entirely understand this, but when an index entry is
+  % generated from a macro call, the \endinput which \scanmacro inserts
+  % causes processing to be prematurely terminated.  This is,
+  % apparently, because \indexsorttmp is fully expanded, and \endinput
+  % is an expandable command.  The redefinition below makes \endinput
+  % disappear altogether for that purpose -- although logging shows that
+  % processing continues to some further point.  On the other hand, it
+  % seems \endinput does not hurt in the printed index arg, since that
+  % is still getting written without apparent harm.
   %
-  % 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).
+  % Sample source (mac-idx3.tex, reported by Graham Percival to
+  % help-texinfo, 22may06):
+  % @macro funindex {WORD}
+  % @findex xyz
+  % @end macro
+  % ...
+  % @funindex commtest
   %
-  \def\definedummyword##1{%
-    \expandafter\def\csname ##1\endcsname{\realbackslash ##1\space}%
-  }%
-  \def\definedummyletter##1{%
-    \expandafter\def\csname ##1\endcsname{\realbackslash ##1}%
-  }%
-  \let\definedummyaccent\definedummyletter
+  % The above is not enough to reproduce the bug, but it gives the flavor.
   %
+  % Sample whatsit resulting:
+  % . at write3{\entry{xyz}{@folio }{@code {xyz at endinput }}}
+  %
+  % So:
+  \let\endinput = \empty
+  %
   % 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.
+% For the aux and toc files, @ is the escape character.  So we want to
+% redefine everything using @ as the escape character (instead of
+% \realbackslash, still used for index files).  When everything uses @,
+% this will be simpler.
 %
 \def\atdummies{%
   \def\@{@@}%
@@ -3094,146 +4421,184 @@
   \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
+  \otherbackslash
 }
 
-% Called from \indexdummies and \atdummies.  \definedummyword and
-% \definedummyletter must be defined first.
+% Called from \indexdummies and \atdummies.
 %
 \def\commondummies{%
   %
-  \normalturnoffactive
+  % \definedummyword defines \#1 as \string\#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{\def##1{\string##1\space}}%
+  \def\definedummyletter##1{\def##1{\string##1}}%
+  \let\definedummyaccent\definedummyletter
+  %
   \commondummiesnofonts
   %
-  \definedummyletter{_}%
+  \definedummyletter\_%
+  \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}%
+  \definedummyword\AA
+  \definedummyword\AE
+  \definedummyword\DH
+  \definedummyword\L
+  \definedummyword\O
+  \definedummyword\OE
+  \definedummyword\TH
+  \definedummyword\aa
+  \definedummyword\ae
+  \definedummyword\dh
+  \definedummyword\exclamdown
+  \definedummyword\l
+  \definedummyword\o
+  \definedummyword\oe
+  \definedummyword\ordf
+  \definedummyword\ordm
+  \definedummyword\questiondown
+  \definedummyword\ss
+  \definedummyword\th
   %
   % 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\bf
+  \definedummyword\gtr
+  \definedummyword\hat
+  \definedummyword\less
+  \definedummyword\sf
+  \definedummyword\sl
+  \definedummyword\tclose
+  \definedummyword\tt
   %
-  \definedummyword{LaTeX}%
-  \definedummyword{TeX}%
+  \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}%
+  \definedummyword\arrow
+  \definedummyword\bullet
+  \definedummyword\comma
+  \definedummyword\copyright
+  \definedummyword\registeredsymbol
+  \definedummyword\dots
+  \definedummyword\enddots
+  \definedummyword\entrybreak
+  \definedummyword\equiv
+  \definedummyword\error
+  \definedummyword\euro
+  \definedummyword\expansion
+  \definedummyword\geq
+  \definedummyword\guillemetleft
+  \definedummyword\guillemetright
+  \definedummyword\guilsinglleft
+  \definedummyword\guilsinglright
+  \definedummyword\lbracechar
+  \definedummyword\leq
+  \definedummyword\minus
+  \definedummyword\ogonek
+  \definedummyword\pounds
+  \definedummyword\point
+  \definedummyword\print
+  \definedummyword\quotedblbase
+  \definedummyword\quotedblleft
+  \definedummyword\quotedblright
+  \definedummyword\quoteleft
+  \definedummyword\quoteright
+  \definedummyword\quotesinglbase
+  \definedummyword\rbracechar
+  \definedummyword\result
+  \definedummyword\textdegree
   %
+  % We want to disable all macros so that they are not expanded by \write.
+  \macrolist
+  %
+  \normalturnoffactive
+  %
   % 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}%
-  }
+\def\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\ogonek
+  \definedummyword\ringaccent
+  \definedummyword\tieaccent
+  \definedummyword\ubaraccent
+  \definedummyword\udotaccent
+  \definedummyword\dotless
+  %
+  % Texinfo font commands.
+  \definedummyword\b
+  \definedummyword\i
+  \definedummyword\r
+  \definedummyword\sansserif
+  \definedummyword\sc
+  \definedummyword\slanted
+  \definedummyword\t
+  %
+  % Commands that take arguments.
+  \definedummyword\abbr
+  \definedummyword\acronym
+  \definedummyword\anchor
+  \definedummyword\cite
+  \definedummyword\code
+  \definedummyword\command
+  \definedummyword\dfn
+  \definedummyword\dmn
+  \definedummyword\email
+  \definedummyword\emph
+  \definedummyword\env
+  \definedummyword\file
+  \definedummyword\image
+  \definedummyword\indicateurl
+  \definedummyword\inforef
+  \definedummyword\kbd
+  \definedummyword\key
+  \definedummyword\math
+  \definedummyword\option
+  \definedummyword\pxref
+  \definedummyword\ref
+  \definedummyword\samp
+  \definedummyword\strong
+  \definedummyword\tie
+  \definedummyword\uref
+  \definedummyword\url
+  \definedummyword\var
+  \definedummyword\verb
+  \definedummyword\w
+  \definedummyword\xref
 }
 
 % \indexnofonts is used when outputting the strings to sort the index
@@ -3243,14 +4608,10 @@
 %
 \def\indexnofonts{%
   % Accent commands should become @asis.
-  \def\definedummyaccent##1{%
-    \expandafter\let\csname ##1\endcsname\asis
-  }%
+  \def\definedummyaccent##1{\let##1\asis}%
   % We can just ignore other control letters.
-  \def\definedummyletter##1{%
-    \expandafter\def\csname ##1\endcsname{}%
-  }%
-  % Hopefully, all control words can become @asis.
+  \def\definedummyletter##1{\let##1\empty}%
+  % All control words become @asis by default; overrides below.
   \let\definedummyword\definedummyaccent
   %
   \commondummiesnofonts
@@ -3262,25 +4623,38 @@
   %
   \def\ { }%
   \def\@{@}%
-  % how to handle braces?
   \def\_{\normalunderscore}%
+  \def\-{}% @- shouldn't affect sorting
   %
+  % Unfortunately, texindex is not prepared to handle braces in the
+  % content at all.  So for index sorting, we map @{ and @} to strings
+  % starting with |, since that ASCII character is between ASCII { and }.
+  \def\{{|a}%
+  \def\lbracechar{|a}%
+  %
+  \def\}{|b}%
+  \def\rbracechar{|b}%
+  %
   % Non-English letters.
   \def\AA{AA}%
   \def\AE{AE}%
+  \def\DH{DZZ}%
   \def\L{L}%
   \def\OE{OE}%
   \def\O{O}%
+  \def\TH{ZZZ}%
   \def\aa{aa}%
   \def\ae{ae}%
+  \def\dh{dzz}%
+  \def\exclamdown{!}%
   \def\l{l}%
   \def\oe{oe}%
+  \def\ordf{a}%
+  \def\ordm{o}%
   \def\o{o}%
+  \def\questiondown{?}%
   \def\ss{ss}%
-  \def\exclamdown{!}%
-  \def\questiondown{?}%
-  \def\ordf{a}%
-  \def\ordm{o}%
+  \def\th{zzz}%
   %
   \def\LaTeX{LaTeX}%
   \def\TeX{TeX}%
@@ -3287,25 +4661,57 @@
   %
   % Assorted special characters.
   % (The following {} will end up in the sort string, but that's ok.)
+  \def\arrow{->}%
   \def\bullet{bullet}%
   \def\comma{,}%
   \def\copyright{copyright}%
-  \def\registeredsymbol{R}%
   \def\dots{...}%
   \def\enddots{...}%
   \def\equiv{==}%
   \def\error{error}%
+  \def\euro{euro}%
   \def\expansion{==>}%
+  \def\geq{>=}%
+  \def\guillemetleft{<<}%
+  \def\guillemetright{>>}%
+  \def\guilsinglleft{<}%
+  \def\guilsinglright{>}%
+  \def\leq{<=}%
   \def\minus{-}%
+  \def\point{.}%
   \def\pounds{pounds}%
-  \def\point{.}%
   \def\print{-|}%
+  \def\quotedblbase{"}%
+  \def\quotedblleft{"}%
+  \def\quotedblright{"}%
+  \def\quoteleft{`}%
+  \def\quoteright{'}%
+  \def\quotesinglbase{,}%
+  \def\registeredsymbol{R}%
   \def\result{=>}%
+  \def\textdegree{o}%
   %
-  % Don't write macro names.
-  \emptyusermacros
+  \expandafter\ifx\csname SETtxiindexlquoteignore\endcsname\relax
+  \else \indexlquoteignore \fi
+  %
+  % 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.
+  %
+  \macrolist
 }
 
+% Undocumented (for FSFS 2nd ed.): @set txiindexlquoteignore makes us
+% ignore left quotes in the sort term.
+{\catcode`\`=\active
+ \gdef\indexlquoteignore{\let`=\empty}}
+
 \let\indexbackslash=0  %overridden during \printindex.
 \let\SETmarginindex=\relax % put index entries in margin (undocumented)?
 
@@ -3331,11 +4737,7 @@
     %
     \edef\writeto{\csname#1indfile\endcsname}%
     %
-    \ifvmode
-      \dosubindsanitize
-    \else
-      \dosubindwrite
-    \fi
+    \safewhatsit\dosubindwrite
   }%
   \fi
 }
@@ -3350,7 +4752,6 @@
   %
   % 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.
   %
@@ -3373,13 +4774,13 @@
   \temp
 }
 
-% Take care of unwanted page breaks:
+% Take care of unwanted page breaks/skips around a whatsit:
 %
 % 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:
+% \write or \pdfdest will make \lastskip zero.  The result is that
+% sequences like this:
 % @end defun
 % @tindex whatever
 % @defun ...
@@ -3403,25 +4804,30 @@
 %
 \edef\zeroskipmacro{\expandafter\the\csname z at skip\endcsname}
 %
+\newskip\whatsitskip
+\newcount\whatsitpenalty
+%
 % ..., ready, GO:
 %
-\def\dosubindsanitize{%
+\def\safewhatsit#1{\ifhmode
+  #1%
+ \else
   % \lastskip and \lastpenalty cannot both be nonzero simultaneously.
-  \skip0 = \lastskip
+  \whatsitskip = \lastskip
   \edef\lastskipmacro{\the\lastskip}%
-  \count255 = \lastpenalty
+  \whatsitpenalty = \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
+  % -\whatsitskip 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
+    \vskip-\whatsitskip
   \fi
   %
-  \dosubindwrite
+  #1%
   %
   \ifx\lastskipmacro\zeroskipmacro
     % If \lastskip was zero, perhaps the last item was a penalty, and
@@ -3429,20 +4835,19 @@
     % 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
+    \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \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
+    \nobreak\vskip\whatsitskip
   \fi
-}
+\fi}
 
 % The index entry written in the file actually looks like
 %  \entry {sortstring}{page}{topic}
@@ -3484,6 +4889,7 @@
   %
   \smallfonts \rm
   \tolerance = 9500
+  \plainfrenchspacing
   \everypar = {}% don't want the \kern\-parindent from indentation suppression.
   %
   % See if the index file exists and is nonempty.
@@ -3557,10 +4963,9 @@
 %
 % A straightforward implementation would start like this:
 %	\def\entry#1#2{...
-% But this frozes the catcodes in the argument, and can cause problems to
+% But this freezes 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{%
@@ -3597,10 +5002,17 @@
     % columns.
     \vskip 0pt plus1pt
     %
+    % When reading the text of entry, convert explicit line breaks
+    % from @* into spaces.  The user might give these in long section
+    % titles, for instance.
+    \def\*{\unskip\space\ignorespaces}%
+    \def\entrybreak{\hfil\break}%
+    %
     % Swallow the left brace of the text (first parameter):
     \afterassignment\doentry
     \let\temp =
 }
+\def\entrybreak{\unskip\space\ignorespaces}%
 \def\doentry{%
     \bgroup % Instead of the swallowed brace.
       \noindent
@@ -3613,11 +5025,8 @@
     % 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
+    \setbox\boxA = \hbox{#1}%
+    \ifdim\wd\boxA = 0pt
       \ %
     \else
       %
@@ -3641,9 +5050,9 @@
   \endgroup
 }
 
-% Like \dotfill except takes at least 1 em.
+% Like plain.tex's \dotfill, except uses up at least 1 em.
 \def\indexdotfill{\cleaders
-  \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill}
+  \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill}
 
 \def\primary #1{\line{#1\hfil}}
 
@@ -3753,6 +5162,34 @@
 %
 % All done with double columns.
 \def\enddoublecolumns{%
+  % The following penalty ensures that the page builder is exercised
+  % _before_ we change the output routine.  This is necessary in the
+  % following situation:
+  %
+  % The last section of the index consists only of a single entry.
+  % Before this section, \pagetotal is less than \pagegoal, so no
+  % break occurs before the last section starts.  However, the last
+  % section, consisting of \initial and the single \entry, does not
+  % fit on the page and has to be broken off.  Without the following
+  % penalty the page builder will not be exercised until \eject
+  % below, and by that time we'll already have changed the output
+  % routine to the \balancecolumns version, so the next-to-last
+  % double-column page will be processed with \balancecolumns, which
+  % is wrong:  The two columns will go to the main vertical list, with
+  % the broken-off section in the recent contributions.  As soon as
+  % the output routine finishes, TeX starts reconsidering the page
+  % break.  The two columns and the broken-off section both fit on the
+  % page, because the two columns now take up only half of the page
+  % goal.  When TeX sees \eject from below which follows the final
+  % section, it invokes the new output routine that we've set after
+  % \balancecolumns below; \onepageout will try to fit the two columns
+  % and the final section into the vbox of \pageheight (see
+  % \pagebody), causing an overfull box.
+  %
+  % Note that glue won't work here, because glue does not exercise the
+  % page builder, unlike penalties (see The TeXbook, pp. 280-281).
+  \penalty0
+  %
   \output = {%
     % Split the last of the double-column material.  Leave it on the
     % current page, no automatic page break.
@@ -3808,7 +5245,22 @@
 \message{sectioning,}
 % Chapters, sections, etc.
 
-% \unnumberedno is an oxymoron, of course.  But we count the unnumbered
+% Let's start with @part.
+\outer\parseargdef\part{\partzzz{#1}}
+\def\partzzz#1{%
+  \chapoddpage
+  \null
+  \vskip.3\vsize  % move it down on the page a bit
+  \begingroup
+    \noindent \titlefonts\rmisbold #1\par % the text
+    \let\lastnode=\empty      % no node to associate with
+    \writetocentry{part}{#1}{}% but put it in the toc
+    \headingsoff              % no headline or footline on the part page
+    \chapoddpage
+  \endgroup
+}
+
+% \unnumberedno is an oxymoron.  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
@@ -3862,11 +5314,15 @@
   \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.
+% Each @chapter defines these (using marks) as the number+name, number
+% and name of the chapter.  Page headings and footings can use
+% these.  @section does likewise.
 \def\thischapter{}
+\def\thischapternum{}
+\def\thischaptername{}
 \def\thissection{}
+\def\thissectionnum{}
+\def\thissectionname{}
 
 \newcount\absseclevel % used to calculate proper heading level
 \newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count
@@ -3883,8 +5339,8 @@
 \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
+% To achieve this, remember the "biggest" unnum. sec. we are currently in:
+\chardef\unnlevel = \maxseclevel
 %
 % Trace whether the current chapter is an appendix or not:
 % \chapheadtype is "N" or "A", unnumbered chapters are ignored.
@@ -3909,8 +5365,8 @@
   % The heading type:
   \def\headtype{#1}%
   \if \headtype U%
-    \ifnum \absseclevel < \unmlevel
-      \chardef\unmlevel = \absseclevel
+    \ifnum \absseclevel < \unnlevel
+      \chardef\unnlevel = \absseclevel
     \fi
   \else
     % Check for appendix sections:
@@ -3922,10 +5378,10 @@
       \fi\fi
     \fi
     % Check for numbered within unnumbered:
-    \ifnum \absseclevel > \unmlevel
+    \ifnum \absseclevel > \unnlevel
       \def\headtype{U}%
     \else
-      \chardef\unmlevel = 3
+      \chardef\unnlevel = 3
     \fi
   \fi
   % Now print the heading:
@@ -3979,7 +5435,9 @@
   \gdef\chaplevelprefix{\the\chapno.}%
   \resetallfloatnos
   %
-  \message{\putwordChapter\space \the\chapno}%
+  % \putwordChapter can contain complex things in translations.
+  \toks0=\expandafter{\putwordChapter}%
+  \message{\the\toks0 \space \the\chapno}%
   %
   % Write the actual heading.
   \chapmacro{#1}{Ynumbered}{\the\chapno}%
@@ -3990,7 +5448,8 @@
   \global\let\subsubsection = \numberedsubsubsec
 }
 
-\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\outer\parseargdef\appendix{\apphead0{#1}} % normally calls appendixzzz
+%
 \def\appendixzzz#1{%
   \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
     \global\advance\appendixno by 1
@@ -3997,8 +5456,9 @@
   \gdef\chaplevelprefix{\appendixletter.}%
   \resetallfloatnos
   %
-  \def\appendixnum{\putwordAppendix\space \appendixletter}%
-  \message{\appendixnum}%
+  % \putwordAppendix can contain complex things in translations.
+  \toks0=\expandafter{\putwordAppendix}%
+  \message{\the\toks0 \space \appendixletter}%
   %
   \chapmacro{#1}{Yappendix}{\appendixletter}%
   %
@@ -4007,7 +5467,8 @@
   \global\let\subsubsection = \appendixsubsubsec
 }
 
-\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+% normally unnmhead0 calls unnumberedzzz:
+\outer\parseargdef\unnumbered{\unnmhead0{#1}}
 \def\unnumberedzzz#1{%
   \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
     \global\advance\unnumberedno by 1
@@ -4051,6 +5512,7 @@
 \let\top\unnumbered
 
 % Sections.
+% 
 \outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz
 \def\seczzz#1{%
   \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
@@ -4057,7 +5519,8 @@
   \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}%
 }
 
-\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz
+% normally calls appendixsectionzzz:
+\outer\parseargdef\appendixsection{\apphead1{#1}}
 \def\appendixsectionzzz#1{%
   \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
   \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}%
@@ -4064,7 +5527,8 @@
 }
 \let\appendixsec\appendixsection
 
-\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz
+% normally calls unnumberedseczzz:
+\outer\parseargdef\unnumberedsec{\unnmhead1{#1}}
 \def\unnumberedseczzz#1{%
   \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
   \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}%
@@ -4071,13 +5535,16 @@
 }
 
 % Subsections.
-\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz
+% 
+% normally calls numberedsubseczzz:
+\outer\parseargdef\numberedsubsec{\numhead2{#1}}
 \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
+% normally calls appendixsubseczzz:
+\outer\parseargdef\appendixsubsec{\apphead2{#1}}
 \def\appendixsubseczzz#1{%
   \global\subsubsecno=0  \global\advance\subsecno by 1
   \sectionheading{#1}{subsec}{Yappendix}%
@@ -4084,7 +5551,8 @@
                  {\appendixletter.\the\secno.\the\subsecno}%
 }
 
-\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+% normally calls unnumberedsubseczzz:
+\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}}
 \def\unnumberedsubseczzz#1{%
   \global\subsubsecno=0  \global\advance\subsecno by 1
   \sectionheading{#1}{subsec}{Ynothing}%
@@ -4092,7 +5560,9 @@
 }
 
 % Subsubsections.
-\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz
+% 
+% normally numberedsubsubseczzz:
+\outer\parseargdef\numberedsubsubsec{\numhead3{#1}}
 \def\numberedsubsubseczzz#1{%
   \global\advance\subsubsecno by 1
   \sectionheading{#1}{subsubsec}{Ynumbered}%
@@ -4099,7 +5569,8 @@
                  {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}%
 }
 
-\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz
+% normally appendixsubsubseczzz:
+\outer\parseargdef\appendixsubsubsec{\apphead3{#1}}
 \def\appendixsubsubseczzz#1{%
   \global\advance\subsubsecno by 1
   \sectionheading{#1}{subsubsec}{Yappendix}%
@@ -4106,7 +5577,8 @@
                  {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}%
 }
 
-\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+% normally unnumberedsubsubseczzz:
+\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}}
 \def\unnumberedsubsubseczzz#1{%
   \global\advance\subsubsecno by 1
   \sectionheading{#1}{subsubsec}{Ynothing}%
@@ -4122,15 +5594,6 @@
 
 % Define @majorheading, @heading and @subheading
 
-% NOTE on use of \vbox for chapter headings, section headings, and such:
-%       1) We use \vbox rather than the earlier \line to permit
-%          overlong headings to fold.
-%       2) \hyphenpenalty is set to 10000 because hyphenation in a
-%          heading is obnoxious; this forbids it.
-%       3) Likewise, headings look best if no \parindent is used, and
-%          if justification is not attempted.  Hence \raggedright.
-
-
 \def\majorheading{%
   {\advance\chapheadingskip by 10pt \chapbreak }%
   \parsearg\chapheadingzzz
@@ -4138,10 +5601,8 @@
 
 \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
+  \vbox{\chapfonts \raggedtitlesettings #1\par}%
+  \nobreak\bigskip \nobreak
   \suppressfirstparagraphindent
 }
 
@@ -4157,17 +5618,28 @@
 % (including whitespace, linebreaking, etc. around it),
 % given all the information in convenient, parsed form.
 
-%%% Args are the skip and penalty (usually negative)
+% Args are the skip and penalty (usually negative)
 \def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
 
-%%% Define plain chapter starts, and page on/off switching for it
 % Parameter controlling skip before chapter headings (if needed)
-
 \newskip\chapheadingskip
 
+% Define plain chapter starts, and page on/off switching for it.
 \def\chapbreak{\dobreak \chapheadingskip {-4000}}
 \def\chappager{\par\vfill\supereject}
-\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+% Because \domark is called before \chapoddpage, the filler page will
+% get the headings for the next chapter, which is wrong.  But we don't
+% care -- we just disable all headings on the filler page.
+\def\chapoddpage{%
+  \chappager
+  \ifodd\pageno \else
+    \begingroup
+      \headingsoff
+      \null
+      \chappager
+    \endgroup
+  \fi
+}
 
 \def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
 
@@ -4201,41 +5673,78 @@
 \def\Yappendixkeyword{Yappendix}
 %
 \def\chapmacro#1#2#3{%
+  % Insert the first mark before the heading break (see notes for \domark).
+  \let\prevchapterdefs=\lastchapterdefs
+  \let\prevsectiondefs=\lastsectiondefs
+  \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}%
+                        \gdef\thissection{}}%
+  %
+  \def\temptype{#2}%
+  \ifx\temptype\Ynothingkeyword
+    \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}%
+                          \gdef\thischapter{\thischaptername}}%
+  \else\ifx\temptype\Yomitfromtockeyword
+    \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}%
+                          \gdef\thischapter{}}%
+  \else\ifx\temptype\Yappendixkeyword
+    \toks0={#1}%
+    \xdef\lastchapterdefs{%
+      \gdef\noexpand\thischaptername{\the\toks0}%
+      \gdef\noexpand\thischapternum{\appendixletter}%
+      % \noexpand\putwordAppendix avoids expanding indigestible
+      % commands in some of the translations.
+      \gdef\noexpand\thischapter{\noexpand\putwordAppendix{}
+                                 \noexpand\thischapternum:
+                                 \noexpand\thischaptername}%
+    }%
+  \else
+    \toks0={#1}%
+    \xdef\lastchapterdefs{%
+      \gdef\noexpand\thischaptername{\the\toks0}%
+      \gdef\noexpand\thischapternum{\the\chapno}%
+      % \noexpand\putwordChapter avoids expanding indigestible
+      % commands in some of the translations.
+      \gdef\noexpand\thischapter{\noexpand\putwordChapter{}
+                                 \noexpand\thischapternum:
+                                 \noexpand\thischaptername}%
+    }%
+  \fi\fi\fi
+  %
+  % Output the mark.  Pass it through \safewhatsit, to take care of
+  % the preceding space.
+  \safewhatsit\domark
+  %
+  % Insert the chapter heading break.
   \pchapsepmacro
+  %
+  % Now the second mark, after the heading break.  No break points
+  % between here and the heading.
+  \let\prevchapterdefs=\lastchapterdefs
+  \let\prevsectiondefs=\lastsectiondefs
+  \domark
+  %
   {%
-    \chapfonts \rm
+    \chapfonts \rmisbold
     %
-    % Have to define \thissection before calling \donoderef, because the
+    % Have to define \lastsection 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}%
+    \gdef\lastsection{#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
@@ -4251,8 +5760,8 @@
     \donoderef{#2}%
     %
     % Typeset the actual heading.
-    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
-          \hangindent=\wd0 \centerparametersmaybe
+    \nobreak % Avoid page breaks at the interline glue.
+    \vbox{\raggedtitlesettings \hangindent=\wd0 \centerparametersmaybe
           \unhbox0 #1\par}%
   }%
   \nobreak\bigskip % no page break after a chapter title
@@ -4274,9 +5783,9 @@
 \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
+  \chapoddpage
+  \vbox{\chapfonts \raggedtitlesettings #1\par}%
+  \nobreak\bigskip\nobreak
 }
 \def\chfopen #1#2{\chapoddpage {\chapfonts
 \vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
@@ -4283,9 +5792,9 @@
 \par\penalty 5000 %
 }
 \def\centerchfopen #1{%
-\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
-                       \parindent=0pt
-                       \hfill {\rm #1}\hfill}}\bigskip \par\nobreak
+  \chapoddpage
+  \vbox{\chapfonts \raggedtitlesettings \hfill #1\hfill}%
+  \nobreak\bigskip \nobreak
 }
 \def\CHAPFopen{%
   \global\let\chapmacro=\chfopen
@@ -4313,25 +5822,80 @@
 % the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the
 % section number.
 %
+\def\seckeyword{sec}
+%
 \def\sectionheading#1#2#3#4{%
   {%
+    \checkenv{}% should not be in an environment.
+    %
     % Switch to the right set of fonts.
-    \csname #2fonts\endcsname \rm
+    \csname #2fonts\endcsname \rmisbold
     %
+    \def\sectionlevel{#2}%
+    \def\temptype{#3}%
+    %
+    % Insert first mark before the heading break (see notes for \domark).
+    \let\prevsectiondefs=\lastsectiondefs
+    \ifx\temptype\Ynothingkeyword
+      \ifx\sectionlevel\seckeyword
+        \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}%
+                              \gdef\thissection{\thissectionname}}%
+      \fi
+    \else\ifx\temptype\Yomitfromtockeyword
+      % Don't redefine \thissection.
+    \else\ifx\temptype\Yappendixkeyword
+      \ifx\sectionlevel\seckeyword
+        \toks0={#1}%
+        \xdef\lastsectiondefs{%
+          \gdef\noexpand\thissectionname{\the\toks0}%
+          \gdef\noexpand\thissectionnum{#4}%
+          % \noexpand\putwordSection avoids expanding indigestible
+          % commands in some of the translations.
+          \gdef\noexpand\thissection{\noexpand\putwordSection{}
+                                     \noexpand\thissectionnum:
+                                     \noexpand\thissectionname}%
+        }%
+      \fi
+    \else
+      \ifx\sectionlevel\seckeyword
+        \toks0={#1}%
+        \xdef\lastsectiondefs{%
+          \gdef\noexpand\thissectionname{\the\toks0}%
+          \gdef\noexpand\thissectionnum{#4}%
+          % \noexpand\putwordSection avoids expanding indigestible
+          % commands in some of the translations.
+          \gdef\noexpand\thissection{\noexpand\putwordSection{}
+                                     \noexpand\thissectionnum:
+                                     \noexpand\thissectionname}%
+        }%
+      \fi
+    \fi\fi\fi
+    %
+    % Go into vertical mode.  Usually we'll already be there, but we
+    % don't want the following whatsit to end up in a preceding paragraph
+    % if the document didn't happen to have a blank line.
+    \par
+    %
+    % Output the mark.  Pass it through \safewhatsit, to take care of
+    % the preceding space.
+    \safewhatsit\domark
+    %
     % Insert space above the heading.
     \csname #2headingbreak\endcsname
     %
+    % Now the second mark, after the heading break.  No break points
+    % between here and the heading.
+    \let\prevsectiondefs=\lastsectiondefs
+    \domark
+    %
     % 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}%
+      \gdef\lastsection{#1}%
     \else\ifx\temptype\Yomitfromtockeyword
       % for @headings -- no section number, don't include in toc,
-      % and don't redefine \thissection.
+      % and don't redefine \lastsection.
       \setbox0 = \hbox{}%
       \def\toctype{omit}%
       \let\sectionlevel=\empty
@@ -4338,22 +5902,30 @@
     \else\ifx\temptype\Yappendixkeyword
       \setbox0 = \hbox{#4\enspace}%
       \def\toctype{app}%
-      \gdef\thissection{#1}%
+      \gdef\lastsection{#1}%
     \else
       \setbox0 = \hbox{#4\enspace}%
       \def\toctype{num}%
-      \gdef\thissection{#1}%
+      \gdef\lastsection{#1}%
     \fi\fi\fi
     %
-    % Write the toc entry (before \donoderef).  See comments in \chfplain.
+    % Write the toc entry (before \donoderef).  See comments in \chapmacro.
     \writetocentry{\toctype\sectionlevel}{#1}{#4}%
     %
     % Write the node reference (= pdf destination for pdftex).
-    % Again, see comments in \chfplain.
+    % Again, see comments in \chapmacro.
     \donoderef{#3}%
     %
+    % Interline glue will be inserted when the vbox is completed.
+    % That glue will be a valid breakpoint for the page, since it'll be
+    % preceded by a whatsit (usually from the \donoderef, or from the
+    % \writetocentry if there was no node).  We don't want to allow that
+    % break, since then the whatsits could end up on page n while the
+    % section is on page n+1, thus toc/etc. are wrong.  Debian bug 276000.
+    \nobreak
+    %
     % Output the actual section heading.
-    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \ptexraggedright
           \hangindent=\wd0  % zero if no section number
           \unhbox0 #1}%
   }%
@@ -4367,15 +5939,15 @@
   %
   % 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.)
+  % discardable item.)  However, when a paragraph is not started next
+  % (\startdefun, \cartouche, \center, etc.), this needs to be wiped out
+  % or the negative glue will cause weirdly wrong output, typically
+  % obscuring the section heading with something else.
   \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
+  %
+  % This is so the last item on the main vertical list is a known
+  % \penalty > 10000, so \startdefun, etc., can recognize the situation
+  % and do the needful.
   \penalty 10001
 }
 
@@ -4410,11 +5982,11 @@
     \fi
     %
     \iflinks
-      \toks0 = {#2}%
-      \toks2 = \expandafter{\lastnode}%
-      \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}{#3}%
-                               {\the\toks2}{\noexpand\folio}}}%
-      \temp
+      {\atdummies
+       \edef\temp{%
+         \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}%
+       \temp
+      }%
     \fi
   \fi
   %
@@ -4427,6 +5999,31 @@
   \ifpdf \global\pdfmakepagedesttrue \fi
 }
 
+
+% These characters do not print properly in the Computer Modern roman
+% fonts, so we must take special care.  This is more or less redundant
+% with the Texinfo input format setup at the end of this file.
+%
+\def\activecatcodes{%
+  \catcode`\"=\active
+  \catcode`\$=\active
+  \catcode`\<=\active
+  \catcode`\>=\active
+  \catcode`\\=\active
+  \catcode`\^=\active
+  \catcode`\_=\active
+  \catcode`\|=\active
+  \catcode`\~=\active
+}
+
+
+% Read the toc file, which is essentially Texinfo input.
+\def\readtocfile{%
+  \setupdatafile
+  \activecatcodes
+  \input \tocreadfilename
+}
+
 \newskip\contentsrightmargin \contentsrightmargin=1in
 \newcount\savepageno
 \newcount\lastnegativepageno \lastnegativepageno = -1
@@ -4443,16 +6040,11 @@
   %
   % 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 at piuha.ydi.vtt.fi
-    \raggedbottom             % Worry more about breakpoints than the bottom.
+    \raggedbottom              % Worry more about breakpoints than the bottom.
     \advance\hsize by -\contentsrightmargin % Don't use the full line length.
     %
     % Roman numerals for page numbers.
@@ -4459,13 +6051,18 @@
     \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi
 }
 
+% redefined for the two-volume lispref.  We always output on
+% \jobname.toc even if this is redefined.
+%
+\def\tocreadfilename{\jobname.toc}
 
 % Normal (long) toc.
+%
 \def\contents{%
   \startcontents{\putwordTOC}%
-    \openin 1 \jobname.toc
+    \openin 1 \tocreadfilename\space
     \ifeof 1 \else
-      \input \jobname.toc
+      \readtocfile
     \fi
     \vfill \eject
     \contentsalignmacro % in case @setchapternewpage odd is in effect
@@ -4482,6 +6079,7 @@
 \def\summarycontents{%
   \startcontents{\putwordShortTOC}%
     %
+    \let\partentry = \shortpartentry
     \let\numchapentry = \shortchapentry
     \let\appentry = \shortchapentry
     \let\unnchapentry = \shortunnchapentry
@@ -4501,9 +6099,9 @@
     \let\numsubsubsecentry = \numsecentry
     \let\appsubsubsecentry = \numsecentry
     \let\unnsubsubsecentry = \numsecentry
-    \openin 1 \jobname.toc
+    \openin 1 \tocreadfilename\space
     \ifeof 1 \else
-      \input \jobname.toc
+      \readtocfile
     \fi
     \closein 1
     \vfill \eject
@@ -4537,6 +6135,19 @@
 % The last argument is the page number.
 % The arguments in between are the chapter number, section number, ...
 
+% Parts, in the main contents.  Replace the part number, which doesn't
+% exist, with an empty box.  Let's hope all the numbers have the same width.
+% Also ignore the page number, which is conventionally not printed.
+\def\numeralbox{\setbox0=\hbox{8}\hbox to \wd0{\hfil}}
+\def\partentry#1#2#3#4{\dochapentry{\numeralbox\labelspace#1}{}}
+%
+% Parts, in the short toc.
+\def\shortpartentry#1#2#3#4{%
+  \penalty-300
+  \vskip.5\baselineskip plus.15\baselineskip minus.1\baselineskip
+  \shortchapentry{{\bf #1}}{\numeralbox}{}{}%
+}
+
 % Chapters, in the main contents.
 \def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}}
 %
@@ -4626,45 +6237,12 @@
 \message{environments,}
 % @foo ... @end foo.
 
-% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
-%
-% Since these characters are used in examples, it should be an even number of
-% \tt widths. Each \tt character is 1en, so two makes it 1em.
-%
-\def\point{$\star$}
-\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
-\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
-\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
-\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
-
-% The @error{} command.
-% Adapted from the TeXbook's \boxit.
-%
-\newbox\errorbox
-%
-{\tentt \global\dimen0 = 3em}% Width of the box.
-\dimen2 = .55pt % Thickness of rules
-% The text. (`r' is open on the right, `e' somewhat less so on the left.)
-\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
-%
-\setbox\errorbox=\hbox to \dimen0{\hfil
-   \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
-   \advance\hsize by -2\dimen2 % Rules.
-   \vbox{%
-      \hrule height\dimen2
-      \hbox{\vrule width\dimen2 \kern3pt          % Space to left of text.
-         \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
-         \kern3pt\vrule width\dimen2}% Space to right.
-      \hrule height\dimen2}
-    \hfil}
-%
-\def\error{\leavevmode\lower.7ex\copy\errorbox}
-
-% @tex ... @end tex    escapes into raw Tex temporarily.
+% @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.
+% But \@ or @@ will get a plain @ character.
 
 \envdef\tex{%
+  \setupmarkupstyle{tex}%
   \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
   \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
   \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie
@@ -4674,8 +6252,14 @@
   \catcode `\|=\other
   \catcode `\<=\other
   \catcode `\>=\other
+  \catcode`\`=\other
+  \catcode`\'=\other
   \escapechar=`\\
   %
+  % ' is active in math mode (mathcode"8000).  So reset it, and all our
+  % other math active characters (just in case), to plain's definitions.
+  \mathactive
+  %
   \let\b=\ptexb
   \let\bullet=\ptexbullet
   \let\c=\ptexc
@@ -4693,6 +6277,8 @@
   \let\/=\ptexslash
   \let\*=\ptexstar
   \let\t=\ptext
+  \expandafter \let\csname top\endcsname=\ptextop  % outer
+  \let\frenchspacing=\plainfrenchspacing
   %
   \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
   \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
@@ -4738,7 +6324,8 @@
 
 \let\afterenvbreak = \aboveenvbreak
 
-% \nonarrowing is a flag.  If "set", @lisp etc don't narrow margins.
+% \nonarrowing is a flag.  If "set", @lisp etc don't narrow margins; it will
+% also clear it, so that its embedded environments do the narrowing again.
 \let\nonarrowing=\relax
 
 % @cartouche ... @end cartouche: draw rectangle w/rounded corners around
@@ -4775,7 +6362,13 @@
 				% each corner char, and rule thickness
   \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
   % Flag to tell @lisp, etc., not to narrow margin.
-  \let\nonarrowing=\comment
+  \let\nonarrowing = t%
+  %
+  % If this cartouche directly follows a sectioning command, we need the
+  % \parskip glue (backspaced over by default) or the cartouche can
+  % collide with the section heading.
+  \ifnum\lastpenalty>10000 \vskip\parskip \penalty\lastpenalty \fi
+  %
   \vbox\bgroup
       \baselineskip=0pt\parskip=0pt\lineskip=0pt
       \carttop
@@ -4789,7 +6382,7 @@
 	      \lineskip=\normlskip
 	      \parskip=\normpskip
 	      \vskip -\parskip
-	      \comment % For explanation, see the end of \def\group.
+	      \comment % For explanation, see the end of def\group.
 }
 \def\Ecartouche{%
               \ifhmode\par\fi
@@ -4806,6 +6399,7 @@
 
 % This macro is called at the beginning of all the @example variants,
 % inside a group.
+\newdimen\nonfillparindent
 \def\nonfillstart{%
   \aboveenvbreak
   \hfuzz = 12pt % Don't be fussy
@@ -4813,17 +6407,40 @@
   \let\par = \lisppar % don't ignore blank lines
   \obeylines % each line of input is a line of output
   \parskip = 0pt
+  % Turn off paragraph indentation but redefine \indent to emulate
+  % the normal \indent.
+  \nonfillparindent=\parindent
   \parindent = 0pt
+  \let\indent\nonfillindent
+  %
   \emergencystretch = 0pt % don't try to avoid overfull boxes
-  % @cartouche defines \nonarrowing to inhibit narrowing
-  % at next level down.
   \ifx\nonarrowing\relax
     \advance \leftskip by \lispnarrowing
     \exdentamount=\lispnarrowing
+  \else
+    \let\nonarrowing = \relax
   \fi
   \let\exdent=\nofillexdent
 }
 
+\begingroup
+\obeyspaces
+% We want to swallow spaces (but not other tokens) after the fake
+% @indent in our nonfill-environments, where spaces are normally
+% active and set to @tie, resulting in them not being ignored after
+% @indent.
+\gdef\nonfillindent{\futurelet\temp\nonfillindentcheck}%
+\gdef\nonfillindentcheck{%
+\ifx\temp %
+\expandafter\nonfillindentgobble%
+\else%
+\leavevmode\nonfillindentbox%
+\fi%
+}%
+\endgroup
+\def\nonfillindentgobble#1{\nonfillindent}
+\def\nonfillindentbox{\hbox to \nonfillparindent{\hss}}
+
 % 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:
@@ -4834,6 +6451,11 @@
 \let\SETdispenvsize\relax
 \def\setnormaldispenv{%
   \ifx\SETdispenvsize\smallword
+    % end paragraph for sake of leading, in case document has no blank
+    % line.  This is redundant with what happens in \aboveenvbreak, but
+    % we need to do it before changing the fonts, and it's inconvenient
+    % to change the fonts afterward.
+    \ifnum \lastpenalty=10000 \else \endgraf \fi
     \smallexamplefonts \rm
   \fi
 }
@@ -4840,40 +6462,41 @@
 \def\setsmalldispenv{%
   \ifx\SETdispenvsize\nosmallword
   \else
+    \ifnum \lastpenalty=10000 \else \endgraf \fi
     \smallexamplefonts \rm
   \fi
 }
 
 % We often define two environments, @foo and @smallfoo.
-% Let's do it by one command:
-\def\makedispenv #1#2{
-  \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}
-  \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}
+% Let's do it in one command.  #1 is the env name, #2 the definition.
+\def\makedispenvdef#1#2{%
+  \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}%
+  \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}%
   \expandafter\let\csname E#1\endcsname \afterenvbreak
   \expandafter\let\csname Esmall#1\endcsname \afterenvbreak
 }
 
-% Define two synonyms:
-\def\maketwodispenvs #1#2#3{
-  \makedispenv{#1}{#3}
-  \makedispenv{#2}{#3}
+% Define two environment synonyms (#1 and #2) for an environment.
+\def\maketwodispenvdef#1#2#3{%
+  \makedispenvdef{#1}{#3}%
+  \makedispenvdef{#2}{#3}%
 }
-
-% @lisp: indented, narrowed, typewriter font; @example: same as @lisp.
 %
+% @lisp: indented, narrowed, typewriter font;
+% @example: same as @lisp.
+%
 % @smallexample and @smalllisp: use smaller fonts.
 % Originally contributed by Pavel at xerox.
 %
-\maketwodispenvs {lisp}{example}{%
+\maketwodispenvdef{lisp}{example}{%
   \nonfillstart
-  \tt
+  \tt\setupmarkupstyle{example}%
   \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
-  \gobble       % eat return
+  \gobble % eat return
 }
-
 % @display/@smalldisplay: same as @lisp except keep current font.
 %
-\makedispenv {display}{%
+\makedispenvdef{display}{%
   \nonfillstart
   \gobble
 }
@@ -4880,7 +6503,7 @@
 
 % @format/@smallformat: same as @display except don't narrow margins.
 %
-\makedispenv{format}{%
+\makedispenvdef{format}{%
   \let\nonarrowing = t%
   \nonfillstart
   \gobble
@@ -4899,27 +6522,47 @@
 \envdef\flushright{%
   \let\nonarrowing = t%
   \nonfillstart
-  \advance\leftskip by 0pt plus 1fill
+  \advance\leftskip by 0pt plus 1fill\relax
   \gobble
 }
 \let\Eflushright = \afterenvbreak
 
 
+% @raggedright does more-or-less normal line breaking but no right
+% justification.  From plain.tex.
+\envdef\raggedright{%
+  \rightskip0pt plus2em \spaceskip.3333em \xspaceskip.5em\relax
+}
+\let\Eraggedright\par
+
+\envdef\raggedleft{%
+  \parindent=0pt \leftskip0pt plus2em
+  \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt
+  \hbadness=10000 % Last line will usually be underfull, so turn off
+                  % badness reporting.
+}
+\let\Eraggedleft\par
+
+\envdef\raggedcenter{%
+  \parindent=0pt \rightskip0pt plus1em \leftskip0pt plus1em
+  \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt
+  \hbadness=10000 % Last line will usually be underfull, so turn off
+                  % badness reporting.
+}
+\let\Eraggedcenter\par
+
+
 % @quotation does normal linebreaking (hence we can't use \nonfillstart)
 % and narrows the margins.  We keep \parskip nonzero in general, since
 % we're doing normal filling.  So, when using \aboveenvbreak and
 % \afterenvbreak, temporarily make \parskip 0.
 %
-\envdef\quotation{%
-  {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
-  \parindent=0pt
-  %
-  % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+\makedispenvdef{quotation}{\quotationstart}
+%
+\def\quotationstart{%
+  \indentedblockstart % same as \indentedblock, but increase right margin too.
   \ifx\nonarrowing\relax
-    \advance\leftskip by \lispnarrowing
     \advance\rightskip by \lispnarrowing
-    \exdentamount = \lispnarrowing
-    \let\nonarrowing = \relax
   \fi
   \parsearg\quotationlabel
 }
@@ -4929,12 +6572,13 @@
 %
 \def\Equotation{%
   \par
-  \ifx\quotationauthor\undefined\else
+  \ifx\quotationauthor\thisisundefined\else
     % indent a bit.
     \leftline{\kern 2\leftskip \sl ---\quotationauthor}%
   \fi
   {\parskip=0pt \afterenvbreak}%
 }
+\def\Esmallquotation{\Equotation}
 
 % If we're given an argument, typeset it in bold with a colon after.
 \def\quotationlabel#1{%
@@ -4944,7 +6588,33 @@
   \fi
 }
 
+% @indentedblock is like @quotation, but indents only on the left and
+% has no optional argument.
+% 
+\makedispenvdef{indentedblock}{\indentedblockstart}
+%
+\def\indentedblockstart{%
+  {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+  \parindent=0pt
+  %
+  % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+  \ifx\nonarrowing\relax
+    \advance\leftskip by \lispnarrowing
+    \exdentamount = \lispnarrowing
+  \else
+    \let\nonarrowing = \relax
+  \fi
+}
 
+% Keep a nonzero parskip for the environment, since we're doing normal filling.
+%
+\def\Eindentedblock{%
+  \par
+  {\parskip=0pt \afterenvbreak}%
+}
+\def\Esmallindentedblock{\Eindentedblock}
+
+
 % LaTeX-like @verbatim... at 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:
@@ -4959,6 +6629,10 @@
   \do\ \do\\\do\{\do\}\do\$\do\&%
   \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~%
   \do\<\do\>\do\|\do\@\do+\do\"%
+  % Don't do the quotes -- if we do, @set txicodequoteundirected and
+  % @set txicodequotebacktick will not have effect on @verb and
+  % @verbatim, and ?` and !` ligatures won't get disabled.
+  %\do\`\do\'%
 }
 %
 % [Knuth] p. 380
@@ -4965,12 +6639,6 @@
 \def\uncatcodespecials{%
   \def\do##1{\catcode`##1=\other}\dospecials}
 %
-% [Knuth] pp. 380,381,391
-% Disable Spanish ligatures ?` and !` of \tt font
-\begingroup
-  \catcode`\`=\active\gdef`{\relax\lq}
-\endgroup
-%
 % Setup for the @verb command.
 %
 % Eight spaces for a tab
@@ -4982,7 +6650,7 @@
 \def\setupverb{%
   \tt  % easiest (and conventionally used) font for verbatim
   \def\par{\leavevmode\endgraf}%
-  \catcode`\`=\active
+  \setupmarkupstyle{verb}%
   \tabeightspaces
   % Respect line breaks,
   % print special symbols as themselves, and
@@ -4993,35 +6661,46 @@
 
 % Setup for the @verbatim environment
 %
-% Real tab expansion
+% Real tab expansion.
 \newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount
 %
-\def\starttabbox{\setbox0=\hbox\bgroup}
+% We typeset each line of the verbatim in an \hbox, so we can handle
+% tabs.  The \global is in case the verbatim line starts with an accent,
+% or some other command that starts with a begin-group.  Otherwise, the
+% entire \verbbox would disappear at the corresponding end-group, before
+% it is typeset.  Meanwhile, we can't have nested verbatim commands
+% (can we?), so the \global won't be overwriting itself.
+\newbox\verbbox
+\def\starttabbox{\global\setbox\verbbox=\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
+      \dimen\verbbox=\wd\verbbox % the width so far, or since the previous tab
+      \divide\dimen\verbbox by\tabw
+      \multiply\dimen\verbbox by\tabw % compute previous multiple of \tabw
+      \advance\dimen\verbbox by\tabw  % advance to next multiple of \tabw
+      \wd\verbbox=\dimen\verbbox \box\verbbox \starttabbox
     }%
   }
 \endgroup
+
+% start the verbatim environment.
 \def\setupverbatim{%
+  \let\nonarrowing = t%
   \nonfillstart
-  \advance\leftskip by -\defbodyindent
-  % Easiest (and conventionally used) font for verbatim
-  \tt
-  \def\par{\leavevmode\egroup\box0\endgraf}%
-  \catcode`\`=\active
+  \tt % easiest (and conventionally used) font for verbatim
+  % The \leavevmode here is for blank lines.  Otherwise, we would
+  % never \starttabox and the \egroup would end verbatim mode.
+  \def\par{\leavevmode\egroup\box\verbbox\endgraf}%
   \tabexpand
+  \setupmarkupstyle{verbatim}%
   % Respect line breaks,
   % print special symbols as themselves, and
-  % make each space count
-  % must do in this order:
+  % make each space count.
+  % Must do in this order:
   \obeylines \uncatcodespecials \sepspaces
   \everypar{\starttabbox}%
 }
@@ -5077,6 +6756,8 @@
   {%
     \makevalueexpandable
     \setupverbatim
+    \indexnofonts       % Allow `@@' and other weird things in file names.
+    \wlog{texinfo.tex: doing @verbatiminclude of #1^^J}%
     \input #1
     \afterenvbreak
   }%
@@ -5102,6 +6783,7 @@
   \endgroup
 }
 
+
 \message{defuns,}
 % @defun etc.
 
@@ -5108,22 +6790,29 @@
 \newskip\defbodyindent \defbodyindent=.4in
 \newskip\defargsindent \defargsindent=50pt
 \newskip\deflastargmargin \deflastargmargin=18pt
+\newcount\defunpenalty
 
 % Start the processing of @deffn:
 \def\startdefun{%
   \ifnum\lastpenalty<10000
     \medbreak
+    \defunpenalty=10003 % Will keep this @deffn together with the
+                        % following @def command, see below.
   \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
+    % by \printdefunline, 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
     %
+    % As a further refinement, we avoid "club" headers by signalling
+    % with penalty of 10003 after the very first @deffn in the
+    % sequence (see above), and penalty of 10002 after any following
+    % @def command.
+    \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \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
@@ -5140,7 +6829,7 @@
   %
   % 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
+  \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi
   %
   % And now, it's time to reuse the body of the original defun:
   \expandafter\gobbledefun#1%
@@ -5155,10 +6844,10 @@
     #1#2 \endheader
     % common ending:
     \interlinepenalty = 10000
-    \advance\rightskip by 0pt plus 1fil
+    \advance\rightskip by 0pt plus 1fil\relax
     \endgraf
     \nobreak\vskip -\parskip
-    \penalty 10002  % signal to \startdefun and \dodefunx
+    \penalty\defunpenalty  % 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
@@ -5168,7 +6857,7 @@
 \def\Edefun{\endgraf\medbreak}
 
 % \makedefun{deffn} creates \deffn, \deffnx and \Edeffn;
-% the only thing remainnig is to define \deffnheader.
+% the only thing remaining is to define \deffnheader.
 %
 \def\makedefun#1{%
   \expandafter\let\csname E#1\endcsname = \Edefun
@@ -5185,6 +6874,7 @@
 \def\domakedefun#1#2#3{%
   \envdef#1{%
     \startdefun
+    \doingtypefnfalse    % distinguish typed functions from all else
     \parseargusing\activeparens{\printdefunline#3}%
   }%
   \def#2{\dodefunx#1}%
@@ -5191,8 +6881,30 @@
   \def#3%
 }
 
-%%% Untyped functions:
+\newif\ifdoingtypefn       % doing typed function?
+\newif\ifrettypeownline    % typeset return type on its own line?
 
+% @deftypefnnewline on|off says whether the return type of typed functions
+% are printed on their own line.  This affects @deftypefn, @deftypefun,
+% @deftypeop, and @deftypemethod.
+% 
+\parseargdef\deftypefnnewline{%
+  \def\temp{#1}%
+  \ifx\temp\onword
+    \expandafter\let\csname SETtxideftypefnnl\endcsname
+      = \empty
+  \else\ifx\temp\offword
+    \expandafter\let\csname SETtxideftypefnnl\endcsname
+      = \relax
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @txideftypefnnl value `\temp',
+                must be on|off}%
+  \fi\fi
+}
+
+% Untyped functions:
+
 % @deffn category name args
 \makedefun{deffn}{\deffngeneral{}}
 
@@ -5210,7 +6922,7 @@
   \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}%
 }
 
-%%% Typed functions:
+% Typed functions:
 
 % @deftypefn category type name args
 \makedefun{deftypefn}{\deftypefngeneral{}}
@@ -5225,10 +6937,11 @@
 %
 \def\deftypefngeneral#1#2 #3 #4 #5\endheader{%
   \dosubind{fn}{\code{#4}}{#1}%
+  \doingtypefntrue
   \defname{#2}{#3}{#4}\defunargs{#5\unskip}%
 }
 
-%%% Typed variables:
+% Typed variables:
 
 % @deftypevr category type var args
 \makedefun{deftypevr}{\deftypecvgeneral{}}
@@ -5246,7 +6959,7 @@
   \defname{#2}{#3}{#4}\defunargs{#5\unskip}%
 }
 
-%%% Untyped variables:
+% Untyped variables:
 
 % @defvr category var args
 \makedefun{defvr}#1 {\deftypevrheader{#1} {} }
@@ -5257,7 +6970,8 @@
 % \defcvof {category of}class var args
 \def\defcvof#1#2 {\deftypecvof{#1}#2 {} }
 
-%%% Type:
+% Types:
+
 % @deftp category name args
 \makedefun{deftp}#1 #2 #3\endheader{%
   \doind{tp}{\code{#2}}%
@@ -5285,25 +6999,49 @@
 % We are followed by (but not passed) the arguments, if any.
 %
 \def\defname#1#2#3{%
+  \par
   % 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
+  % Determine if we are typesetting the return type of a typed function
+  % on a line by itself.
+  \rettypeownlinefalse
+  \ifdoingtypefn  % doing a typed function specifically?
+    % then check user option for putting return type on its own line:
+    \expandafter\ifx\csname SETtxideftypefnnl\endcsname\relax \else
+      \rettypeownlinetrue
+    \fi
+  \fi
+  %
+  % How we'll format the category 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.
+  % Figure out line sizes for the paragraph shape.  We'll always have at
+  % least two.
+  \tempnum = 2
+  %
   % 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
+  %
+  % If doing a return type on its own line, we'll have another line.
+  \ifrettypeownline
+    \advance\tempnum by 1
+    \def\maybeshapeline{0in \hsize}%
+  \else
+    \def\maybeshapeline{}%
+  \fi
+  %
   % 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.
+  % The final paragraph shape:
+  \parshape \tempnum  0in \dimen0  \maybeshapeline  \defargsindent \dimen2
+  %
+  % Put the category name at the right margin.
   \noindent
   \hbox to 0pt{%
     \hfil\box0 \kern-\hsize
@@ -5325,8 +7063,16 @@
     % . 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
+    \def\temp{#2}% text of the return type
+    \ifx\temp\empty\else
+      \tclose{\temp}% typeset the return type
+      \ifrettypeownline
+        % put return type on its own line; prohibit line break following:
+        \hfil\vadjust{\nobreak}\break  
+      \else
+        \space  % type on same line, so just followed by a space
+      \fi
+    \fi           % no return type
     #3% output function name
   }%
   {\rm\enskip}% hskip 0.5 em of \tenrm
@@ -5346,8 +7092,11 @@
   \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
+  % want a way to get ttsl.  We used to recommend @var for that, so
+  % leave the code in, but it's strange for @var to lead to typewriter.
+  % Nowadays we recommend @code, since the difference between a ttsl hyphen
+  % and a tt hyphen is pretty tiny.  @code also disables ?` !`.
+  \def\var##1{{\setupmarkupstyle{var}\ttslanted{##1}}}%
   #1%
   \sl\hyphenchar\font=45
 }
@@ -5427,12 +7176,14 @@
   \ifnum\parencount=0 \else \badparencount \fi
   \ifnum\brackcount=0 \else \badbrackcount \fi
 }
+% these should not use \errmessage; the glibc manual, at least, actually
+% has such constructs (when documenting function pointers).
 \def\badparencount{%
-  \errmessage{Unbalanced parentheses in @def}%
+  \message{Warning: unbalanced parentheses in @def...}%
   \global\parencount=0
 }
 \def\badbrackcount{%
-  \errmessage{Unbalanced square braces in @def}%
+  \message{Warning: unbalanced square brackets in @def...}%
   \global\brackcount=0
 }
 
@@ -5442,7 +7193,7 @@
 
 % 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
+\ifx\eTeXversion\thisisundefined
   \newwrite\macscribble
   \def\scantokens#1{%
     \toks0={#1}%
@@ -5453,26 +7204,30 @@
   }
 \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\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 for \example:
+  \spaceisspace
+  %
+  % The \empty here causes a following catcode 5 newline to be eaten as
+  % part of reading whitespace after a control sequence.  It does not
+  % eat a catcode 13 newline.  There's no good way to handle the two
+  % cases (untried: maybe e-TeX's \everyeof could help, though plain TeX
+  % would then have different behavior).  See the Macro Details node in
+  % the manual for the workaround we recommend for macros and
+  % line-oriented commands.
+  % 
+  \scantokens{#1\empty}%
+\endgroup}
 
 \def\scanexp#1{%
   \edef\temp{\noexpand\scanmacro{#1}}%
@@ -5482,14 +7237,25 @@
 \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...
 
+% List of all defined macros in the form
+%    \definedummyword\macro1\definedummyword\macro2...
+% Currently is also contains all @aliases; the list can be split
+% if there is a need.
+\def\macrolist{}
+
+% Add the macro to \macrolist
+\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname}
+\def\addtomacrolistxxx#1{%
+     \toks0 = \expandafter{\macrolist\definedummyword#1}%
+     \xdef\macrolist{\the\toks0}%
+}
+
 % Utility routines.
 % This does \let #1 = #2, with \csnames; that is,
 %   \let \csname#1\endcsname = \csname#2\endcsname
 % (except of course we have to play expansion games).
-% 
+%
 \def\cslet#1#2{%
   \expandafter\let
   \csname#1\expandafter\endcsname
@@ -5515,13 +7281,18 @@
 
 % Macro bodies are absorbed as an argument in a context where
 % all characters are catcode 10, 11 or 12, except \ which is active
-% (as in normal texinfo). It is necessary to change the definition of \.
-
+% (as in normal texinfo). It is necessary to change the definition of \
+% to recognize macro arguments; this is the job of \mbodybackslash.
+%
+% Non-ASCII encodings make 8-bit characters active, so un-activate
+% them to avoid their expansion.  Must do this non-globally, to
+% confine the change to the current group.
+%
 % 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
+% done by making ^^M (\endlinechar) catcode 12 when reading the macro
 % body, and then making it the \newlinechar in \scanmacro.
-
-\def\scanctxt{%
+%
+\def\scanctxt{% used as subroutine
   \catcode`\"=\other
   \catcode`\+=\other
   \catcode`\<=\other
@@ -5531,15 +7302,16 @@
   \catcode`\_=\other
   \catcode`\|=\other
   \catcode`\~=\other
+  \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi
 }
 
-\def\scanargctxt{%
+\def\scanargctxt{% used for copying and captions, not macros.
   \scanctxt
   \catcode`\\=\other
   \catcode`\^^M=\other
 }
 
-\def\macrobodyctxt{%
+\def\macrobodyctxt{% used for @macro definitions
   \scanctxt
   \catcode`\{=\other
   \catcode`\}=\other
@@ -5547,17 +7319,33 @@
   \usembodybackslash
 }
 
-\def\macroargctxt{%
+\def\macroargctxt{% used when scanning invocations
   \scanctxt
-  \catcode`\\=\other
+  \catcode`\\=0
 }
+% why catcode 0 for \ in the above?  To recognize \\ \{ \} as "escapes"
+% for the single characters \ { }.  Thus, we end up with the "commands"
+% that would be written @\ @{ @} in a Texinfo document.
+% 
+% We already have @{ and @}.  For @\, we define it here, and only for
+% this purpose, to produce a typewriter backslash (so, the @\ that we
+% define for @math can't be used with @macro calls):
+%
+\def\\{\normalbackslash}%
+% 
+% We would like to do this for \, too, since that is what makeinfo does.
+% But it is not possible, because Texinfo already has a command @, for a
+% cedilla accent.  Documents must use @comma{} instead.
+%
+% \anythingelse will almost certainly be an error of some kind.
 
+
 % \mbodybackslash is the definition of \ in @macro bodies.
 % It maps \foo\ => \csname macarg.foo\endcsname => #N
 % where N is the macro parameter number.
 % We define \csname macarg.\endcsname to be \realbackslash, so
 % \\ in macro replacement text gets you a backslash.
-
+%
 {\catcode`@=0 @catcode`@\=@active
  @gdef at usembodybackslash{@let\=@mbodybackslash}
  @gdef at mbodybackslash#1\{@csname macarg.#1 at endcsname}
@@ -5564,15 +7352,23 @@
 }
 \expandafter\def\csname macarg.\endcsname{\realbackslash}
 
+\def\margbackslash#1{\char`\#1 }
+
 \def\macro{\recursivefalse\parsearg\macroxxx}
 \def\rmacro{\recursivetrue\parsearg\macroxxx}
 
 \def\macroxxx#1{%
-  \getargs{#1}%           now \macname is the macname and \argl the arglist
+  \getargs{#1}% now \macname is the macname and \argl the arglist
   \ifx\argl\empty       % no arguments
-     \paramno=0%
+     \paramno=0\relax
   \else
      \expandafter\parsemargdef \argl;%
+     \if\paramno>256\relax
+       \ifx\eTeXversion\thisisundefined
+         \errhelp = \EMsimple
+         \errmessage{You need eTeX to compile a file with macros with more than 256 arguments}
+       \fi
+     \fi
   \fi
   \if1\csname ismacro.\the\macname\endcsname
      \message{Warning: redefining \the\macname}%
@@ -5581,10 +7377,7 @@
      \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}%
+     \addtomacrolist{\the\macname}%
   \fi
   \begingroup \macrobodyctxt
   \ifrecursive \expandafter\parsermacbody
@@ -5598,7 +7391,7 @@
     % Remove the macro name from \macrolist:
     \begingroup
       \expandafter\let\csname#1\endcsname \relax
-      \let\do\unmacrodo
+      \let\definedummyword\unmacrodo
       \xdef\macrolist{\macrolist}%
     \endgroup
   \else
@@ -5610,10 +7403,10 @@
 % macro definitions that have been changed to \relax.
 %
 \def\unmacrodo#1{%
-  \ifx#1\relax
+  \ifx #1\relax
     % remove this
   \else
-    \noexpand\do \noexpand #1%
+    \noexpand\definedummyword \noexpand#1%
   \fi
 }
 
@@ -5622,46 +7415,269 @@
 % an opening brace, and that opening brace is not consumed.
 \def\getargs#1{\getargsxxx#1{}}
 \def\getargsxxx#1#{\getmacname #1 \relax\getmacargs}
-\def\getmacname #1 #2\relax{\macname={#1}}
+\def\getmacname#1 #2\relax{\macname={#1}}
 \def\getmacargs#1{\def\argl{#1}}
 
+% For macro processing make @ a letter so that we can make Texinfo private macro names.
+\edef\texiatcatcode{\the\catcode`\@}
+\catcode `@=11\relax
+
 % Parse the optional {params} list.  Set up \paramno and \paramlist
-% so \defmacro knows what to do.  Define \macarg.blah for each blah
-% in the params list, to be ##N where N is the position in that list.
+% so \defmacro knows what to do.  Define \macarg.BLAH for each BLAH
+% in the params list to some hook where the argument si to be expanded.  If
+% there are less than 10 arguments that hook is to be replaced by ##N where N
+% is the position in that list, that is to say the macro arguments are to be
+% defined `a la TeX in the macro body.  
+%
 % That gets used by \mbodybackslash (above).
-
+%
 % We need to get `macro parameter char #' into several definitions.
-% The technique used is stolen from LaTeX:  let \hash be something
+% The technique used is stolen from LaTeX: let \hash be something
 % unexpandable, insert that wherever you need a #, and then redefine
 % it to # just before using the token list produced.
 %
 % The same technique is used to protect \eatspaces till just before
 % the macro is used.
-
-\def\parsemargdef#1;{\paramno=0\def\paramlist{}%
-        \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,}
+%
+% If there are 10 or more arguments, a different technique is used, where the
+% hook remains in the body, and when macro is to be expanded the body is
+% processed again to replace the arguments.
+%
+% In that case, the hook is \the\toks N-1, and we simply set \toks N-1 to the
+% argument N value and then \edef  the body (nothing else will expand because of
+% the catcode regime underwhich the body was input).
+%
+% If you compile with TeX (not eTeX), and you have macros with 10 or more
+% arguments, you need that no macro has more than 256 arguments, otherwise an
+% error is produced.
+\def\parsemargdef#1;{%
+  \paramno=0\def\paramlist{}%
+  \let\hash\relax
+  \let\xeatspaces\relax
+  \parsemargdefxxx#1,;,%
+  % In case that there are 10 or more arguments we parse again the arguments
+  % list to set new definitions for the \macarg.BLAH macros corresponding to
+  % each BLAH argument. It was anyhow needed to parse already once this list
+  % in order to count the arguments, and as macros with at most 9 arguments
+  % are by far more frequent than macro with 10 or more arguments, defining
+  % twice the \macarg.BLAH macros does not cost too much processing power.
+  \ifnum\paramno<10\relax\else
+    \paramno0\relax
+    \parsemmanyargdef@@#1,;,% 10 or more arguments
+  \fi
+}
 \def\parsemargdefxxx#1,{%
   \if#1;\let\next=\relax
   \else \let\next=\parsemargdefxxx
-    \advance\paramno by 1%
+    \advance\paramno by 1
     \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
         {\xeatspaces{\hash\the\paramno}}%
     \edef\paramlist{\paramlist\hash\the\paramno,}%
   \fi\next}
 
+\def\parsemmanyargdef@@#1,{%
+  \if#1;\let\next=\relax
+  \else 
+    \let\next=\parsemmanyargdef@@
+    \edef\tempb{\eatspaces{#1}}%
+    \expandafter\def\expandafter\tempa
+       \expandafter{\csname macarg.\tempb\endcsname}%
+    % Note that we need some extra \noexpand\noexpand, this is because we
+    % don't want \the  to be expanded in the \parsermacbody  as it uses an
+    % \xdef .
+    \expandafter\edef\tempa
+      {\noexpand\noexpand\noexpand\the\toks\the\paramno}%
+    \advance\paramno by 1\relax
+  \fi\next}
+
 % These two commands read recursive and nonrecursive macro bodies.
 % (They're different since rec and nonrec macros end differently.)
+%
 
+\catcode `\@\texiatcatcode
 \long\def\parsemacbody#1 at end macro%
 {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
 \long\def\parsermacbody#1 at end rmacro%
 {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+\catcode `\@=11\relax
 
-% This defines the macro itself. There are six cases: recursive and
-% nonrecursive macros of zero, one, and many arguments.
+\let\endargs@\relax
+\let\nil@\relax
+\def\nilm@{\nil@}%
+\long\def\nillm@{\nil@}%
+
+% This macro is expanded during the Texinfo macro expansion, not during its
+% definition.  It gets all the arguments values and assigns them to macros
+% macarg.ARGNAME
+%
+% #1 is the macro name
+% #2 is the list of argument names
+% #3 is the list of argument values
+\def\getargvals@#1#2#3{%
+  \def\macargdeflist@{}%
+  \def\saveparamlist@{#2}% Need to keep a copy for parameter expansion.
+  \def\paramlist{#2,\nil@}%
+  \def\macroname{#1}%
+  \begingroup
+  \macroargctxt
+  \def\argvaluelist{#3,\nil@}%
+  \def\@tempa{#3}%
+  \ifx\@tempa\empty
+    \setemptyargvalues@
+  \else
+    \getargvals@@
+  \fi
+}
+
+% 
+\def\getargvals@@{%
+  \ifx\paramlist\nilm@
+      % Some sanity check needed here that \argvaluelist is also empty.
+      \ifx\argvaluelist\nillm@
+      \else
+        \errhelp = \EMsimple
+        \errmessage{Too many arguments in macro `\macroname'!}%
+      \fi
+      \let\next\macargexpandinbody@
+  \else
+    \ifx\argvaluelist\nillm@
+       % No more arguments values passed to macro.  Set remaining named-arg
+       % macros to empty.
+       \let\next\setemptyargvalues@
+    \else
+      % pop current arg name into \@tempb
+      \def\@tempa##1{\pop@{\@tempb}{\paramlist}##1\endargs@}%
+      \expandafter\@tempa\expandafter{\paramlist}%
+       % pop current argument value into \@tempc
+      \def\@tempa##1{\longpop@{\@tempc}{\argvaluelist}##1\endargs@}%
+      \expandafter\@tempa\expandafter{\argvaluelist}%
+       % Here \@tempb is the current arg name and \@tempc is the current arg value.
+       % First place the new argument macro definition into \@tempd
+       \expandafter\macname\expandafter{\@tempc}%
+       \expandafter\let\csname macarg.\@tempb\endcsname\relax
+       \expandafter\def\expandafter\@tempe\expandafter{%
+         \csname macarg.\@tempb\endcsname}%
+       \edef\@tempd{\long\def\@tempe{\the\macname}}%
+       \push@\@tempd\macargdeflist@
+       \let\next\getargvals@@
+    \fi
+  \fi
+  \next
+}
+
+\def\push@#1#2{%
+  \expandafter\expandafter\expandafter\def
+  \expandafter\expandafter\expandafter#2%
+  \expandafter\expandafter\expandafter{%
+  \expandafter#1#2}%
+}
+
+% Replace arguments by their values in the macro body, and place the result
+% in macro \@tempa
+\def\macvalstoargs@{%
+  %  To do this we use the property that token registers that are \the'ed
+  % within an \edef  expand only once. So we are going to place all argument
+  % values into respective token registers.
+  %
+  % First we save the token context, and initialize argument numbering.
+  \begingroup
+    \paramno0\relax
+    % Then, for each argument number #N, we place the corresponding argument
+    % value into a new token list register \toks#N
+    \expandafter\putargsintokens@\saveparamlist@,;,%
+    % Then, we expand the body so that argument are replaced by their
+    % values. The trick for values not to be expanded themselves is that they
+    % are within tokens and that tokens expand only once in an \edef .
+    \edef\@tempc{\csname mac.\macroname .body\endcsname}%
+    % Now we restore the token stack pointer to free the token list registers
+    % which we have used, but we make sure that expanded body is saved after
+    % group.
+    \expandafter
+  \endgroup
+  \expandafter\def\expandafter\@tempa\expandafter{\@tempc}%
+  }
+
+\def\macargexpandinbody@{% 
+  %% Define the named-macro outside of this group and then close this group. 
+  \expandafter
+  \endgroup
+  \macargdeflist@
+  % First the replace in body the macro arguments by their values, the result
+  % is in \@tempa .
+  \macvalstoargs@
+  % Then we point at the \norecurse or \gobble (for recursive) macro value
+  % with \@tempb .
+  \expandafter\let\expandafter\@tempb\csname mac.\macroname .recurse\endcsname
+  % Depending on whether it is recursive or not, we need some tailing
+  % \egroup .
+  \ifx\@tempb\gobble
+     \let\@tempc\relax
+  \else
+     \let\@tempc\egroup
+  \fi
+  % And now we do the real job:
+  \edef\@tempd{\noexpand\@tempb{\macroname}\noexpand\scanmacro{\@tempa}\@tempc}%
+  \@tempd
+}
+
+\def\putargsintokens@#1,{%
+  \if#1;\let\next\relax
+  \else
+    \let\next\putargsintokens@
+    % First we allocate the new token list register, and give it a temporary
+    % alias \@tempb .
+    \toksdef\@tempb\the\paramno
+    % Then we place the argument value into that token list register.
+    \expandafter\let\expandafter\@tempa\csname macarg.#1\endcsname
+    \expandafter\@tempb\expandafter{\@tempa}%
+    \advance\paramno by 1\relax
+  \fi
+  \next
+}
+
+% Save the token stack pointer into macro #1
+\def\texisavetoksstackpoint#1{\edef#1{\the\@cclvi}}
+% Restore the token stack pointer from number in macro #1
+\def\texirestoretoksstackpoint#1{\expandafter\mathchardef\expandafter\@cclvi#1\relax}
+% newtoks that can be used non \outer .
+\def\texinonouternewtoks{\alloc@ 5\toks \toksdef \@cclvi}
+
+% Tailing missing arguments are set to empty
+\def\setemptyargvalues@{%
+  \ifx\paramlist\nilm@
+    \let\next\macargexpandinbody@
+  \else
+    \expandafter\setemptyargvaluesparser@\paramlist\endargs@
+    \let\next\setemptyargvalues@
+  \fi
+  \next
+}
+
+\def\setemptyargvaluesparser@#1,#2\endargs@{%
+  \expandafter\def\expandafter\@tempa\expandafter{%
+    \expandafter\def\csname macarg.#1\endcsname{}}%
+  \push@\@tempa\macargdeflist@
+  \def\paramlist{#2}%
+}
+
+% #1 is the element target macro
+% #2 is the list macro
+% #3,#4\endargs@ is the list value
+\def\pop@#1#2#3,#4\endargs@{%
+   \def#1{#3}%
+   \def#2{#4}%
+}
+\long\def\longpop@#1#2#3,#4\endargs@{%
+   \long\def#1{#3}%
+   \long\def#2{#4}%
+}
+
+% This defines a Texinfo @macro. There are eight cases: recursive and
+% nonrecursive macros of zero, one, up to nine, and many arguments.
 % Much magic with \expandafter here.
 % \xdef is used so that macro definitions will survive the file
 % they're defined in; @include reads the file inside a group.
+%
 \def\defmacro{%
   \let\hash=##% convert placeholders to macro parameter chars
   \ifrecursive
@@ -5676,17 +7692,25 @@
          \expandafter\noexpand\csname\the\macname xxx\endcsname}%
       \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
          \egroup\noexpand\scanmacro{\temp}}%
-    \else % many
-      \expandafter\xdef\csname\the\macname\endcsname{%
-         \bgroup\noexpand\macroargctxt
-         \noexpand\csname\the\macname xx\endcsname}%
-      \expandafter\xdef\csname\the\macname xx\endcsname##1{%
-          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
-      \expandafter\expandafter
-      \expandafter\xdef
-      \expandafter\expandafter
-        \csname\the\macname xxx\endcsname
-          \paramlist{\egroup\noexpand\scanmacro{\temp}}%
+    \else
+      \ifnum\paramno<10\relax % at most 9
+        \expandafter\xdef\csname\the\macname\endcsname{%
+           \bgroup\noexpand\macroargctxt
+           \noexpand\csname\the\macname xx\endcsname}%
+        \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+            \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+        \expandafter\expandafter
+        \expandafter\xdef
+        \expandafter\expandafter
+          \csname\the\macname xxx\endcsname
+            \paramlist{\egroup\noexpand\scanmacro{\temp}}%
+      \else % 10 or more
+        \expandafter\xdef\csname\the\macname\endcsname{%
+          \noexpand\getargvals@{\the\macname}{\argl}%
+        }%    
+        \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp
+        \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\gobble
+      \fi
     \fi
   \else
     \ifcase\paramno
@@ -5703,63 +7727,57 @@
         \egroup
         \noexpand\norecurse{\the\macname}%
         \noexpand\scanmacro{\temp}\egroup}%
-    \else % many
-      \expandafter\xdef\csname\the\macname\endcsname{%
-         \bgroup\noexpand\macroargctxt
-         \expandafter\noexpand\csname\the\macname xx\endcsname}%
-      \expandafter\xdef\csname\the\macname xx\endcsname##1{%
-          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
-      \expandafter\expandafter
-      \expandafter\xdef
-      \expandafter\expandafter
-      \csname\the\macname xxx\endcsname
-      \paramlist{%
-          \egroup
-          \noexpand\norecurse{\the\macname}%
-          \noexpand\scanmacro{\temp}\egroup}%
+    \else % at most 9
+      \ifnum\paramno<10\relax
+        \expandafter\xdef\csname\the\macname\endcsname{%
+           \bgroup\noexpand\macroargctxt
+           \expandafter\noexpand\csname\the\macname xx\endcsname}%
+        \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+            \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+        \expandafter\expandafter
+        \expandafter\xdef
+        \expandafter\expandafter
+        \csname\the\macname xxx\endcsname
+        \paramlist{%
+            \egroup
+            \noexpand\norecurse{\the\macname}%
+            \noexpand\scanmacro{\temp}\egroup}%
+      \else % 10 or more:
+        \expandafter\xdef\csname\the\macname\endcsname{%
+          \noexpand\getargvals@{\the\macname}{\argl}%
+        }%
+        \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp
+        \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\norecurse
+      \fi
     \fi
   \fi}
 
+\catcode `\@\texiatcatcode\relax
+
 \def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
 
 % \braceorline decides whether the next nonwhitespace character is a
 % {.  If so it reads up to the closing }, if not, it reads the whole
 % line.  Whatever was read is then fed to the next control sequence
-% as an argument (by \parsebrace or \parsearg)
-\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx}
+% as an argument (by \parsebrace or \parsearg).
+% 
+\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx}
 \def\braceorlinexxx{%
   \ifx\nchar\bgroup\else
     \expandafter\parsearg
-  \fi \next}
+  \fi \macnamexxx}
 
-% 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.
+% sign.  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
+    \addtomacrolist{#1}%
     \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}%
   }%
   \next
@@ -5769,13 +7787,13 @@
 \message{cross references,}
 
 \newwrite\auxfile
-
 \newif\ifhavexrefs    % True if xref values are known.
 \newif\ifwarnedxrefs  % True if we warned once that they aren't known.
 
 % @inforef is relatively simple.
 \def\inforef #1{\inforefzzz #1,,,,**}
-\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+\def\inforefzzz #1,#2,#3,#4**{%
+  \putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
   node \samp{\ignorespaces#1{}}}
 
 % @node's only job in TeX is to define \lastnode, which is used in
@@ -5814,7 +7832,7 @@
 
 % \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,
+% 1) NAME-title - the current sectioning name taken from \lastsection,
 %                 or the anchor name.
 % 2) NAME-snt   - section number and type, passed as the SNT arg, or
 %                 empty for anchors.
@@ -5829,20 +7847,39 @@
   \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}%
+      \toks0 = \expandafter{\lastsection}%
       \immediate \writexrdef{title}{\the\toks0 }%
       \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc.
-      \writexrdef{pg}{\folio}% will be written later, during \shipout
+      \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, at \shipout
     }%
   \fi
 }
 
+% @xrefautosectiontitle on|off says whether @section(ing) names are used
+% automatically in xrefs, if the third arg is not explicitly specified.
+% This was provided as a "secret" @set xref-automatic-section-title
+% variable, now it's official.
+% 
+\parseargdef\xrefautomaticsectiontitle{%
+  \def\temp{#1}%
+  \ifx\temp\onword
+    \expandafter\let\csname SETxref-automatic-section-title\endcsname
+      = \empty
+  \else\ifx\temp\offword
+    \expandafter\let\csname SETxref-automatic-section-title\endcsname
+      = \relax
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @xrefautomaticsectiontitle value `\temp',
+                must be on|off}%
+  \fi\fi
+}
+
+% 

 % @xref, @pxref, and @ref generate cross-references.  For \xrefX, #1 is
 % the node name, #2 the name of the Info cross-reference, #3 the printed
 % node name, #4 the name of the Info file, #5 the name of the printed
@@ -5851,26 +7888,41 @@
 \def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
 \def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
 \def\ref#1{\xrefX[#1,,,,,,,]}
+%
+\newbox\toprefbox
+\newbox\printedrefnamebox
+\newbox\infofilenamebox
+\newbox\printedmanualbox
+%
 \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
   \unsepspaces
+  %
+  % Get args without leading/trailing spaces.
+  \def\printedrefname{\ignorespaces #3}%
+  \setbox\printedrefnamebox = \hbox{\printedrefname\unskip}%
+  %
+  \def\infofilename{\ignorespaces #4}%
+  \setbox\infofilenamebox = \hbox{\infofilename\unskip}%
+  %
   \def\printedmanual{\ignorespaces #5}%
-  \def\printedrefname{\ignorespaces #3}%
-  \setbox1=\hbox{\printedmanual\unskip}%
-  \setbox0=\hbox{\printedrefname\unskip}%
-  \ifdim \wd0 = 0pt
+  \setbox\printedmanualbox  = \hbox{\printedmanual\unskip}%
+  %
+  % If the printed reference name (arg #3) was not explicitly given in
+  % the @xref, figure out what we want to use.
+  \ifdim \wd\printedrefnamebox = 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.
+    \expandafter\ifx\csname SETxref-automatic-section-title\endcsname \relax
+      % Not auto section-title: use node name inside the square brackets.
       \def\printedrefname{\ignorespaces #1}%
     \else
-      % Use the actual chapter/section title appear inside
-      % the square brackets.  Use the real section title if we have it.
-      \ifdim \wd1 > 0pt
-        % It is in another manual, so we don't have it.
+      % Auto section-title: use chapter/section title inside
+      % the square brackets if we have it.
+      \ifdim \wd\printedmanualbox > 0pt
+        % It is in another manual, so we don't have it; use node name.
         \def\printedrefname{\ignorespaces #1}%
       \else
         \ifhavexrefs
-          % We know the real title if we have the xref values.
+          % We (should) know the real title if we have the xref values.
           \def\printedrefname{\refx{#1-title}{}}%
         \else
           % Otherwise just copy the Info node name.
@@ -5882,18 +7934,32 @@
   %
   % Make link in pdf output.
   \ifpdf
-    \leavevmode
-    \getfilename{#4}%
-    {\turnoffactive \otherbackslash
+    {\indexnofonts
+     \turnoffactive
+     \makevalueexpandable
+     % This expands tokens, so do it after making catcode changes, so _
+     % etc. don't get their TeX definitions.  This ignores all spaces in
+     % #4, including (wrongly) those in the middle of the filename.
+     \getfilename{#4}%
+     %
+     % This (wrongly) does not take account of leading or trailing
+     % spaces in #1, which should be ignored.
+     \edef\pdfxrefdest{#1}%
+     \ifx\pdfxrefdest\empty
+       \def\pdfxrefdest{Top}% no empty targets
+     \else
+       \txiescapepdf\pdfxrefdest  % escape PDF special chars
+     \fi
+     %
+     \leavevmode
+     \startlink attr{/Border [0 0 0]}%
      \ifnum\filenamelength>0
-       \startlink attr{/Border [0 0 0]}%
-         goto file{\the\filename.pdf} name{#1}%
+       goto file{\the\filename.pdf} name{\pdfxrefdest}%
      \else
-       \startlink attr{/Border [0 0 0]}%
-         goto name{\pdfmkpgn{#1}}%
+       goto name{\pdfmkpgn{\pdfxrefdest}}%
      \fi
     }%
-    \linkcolor
+    \setcolor{\linkcolor}%
   \fi
   %
   % Float references are printed completely differently: "Figure 1.2"
@@ -5904,7 +7970,6 @@
     % include an _ in the xref name, etc.
     \indexnofonts
     \turnoffactive
-    \otherbackslash
     \expandafter\global\expandafter\let\expandafter\Xthisreftitle
       \csname XR#1-title\endcsname
   }%
@@ -5911,41 +7976,54 @@
   \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}%
+    \ifdim\wd\printedrefnamebox = 0pt
+      \refx{#1-snt}{}%
     \else
       \printedrefname
     \fi
     %
-    % if the user also gave the printed manual name (fifth arg), append
+    % If the user also gave the printed manual name (fifth arg), append
     % "in MANUALNAME".
-    \ifdim \wd1 > 0pt
+    \ifdim \wd\printedmanualbox > 0pt
       \space \putwordin{} \cite{\printedmanual}%
     \fi
   \else
     % node/anchor (non-float) references.
+    % 
+    % If we use \unhbox 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 \wd\printedmanualbox > 0pt
+      % Cross-manual reference with a printed manual name.
+      % 
+      \crossmanualxref{\cite{\printedmanual\unskip}}%
     %
-    % 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\ifdim \wd\infofilenamebox > 0pt
+      % Cross-manual reference with only an info filename (arg 4), no
+      % printed manual name (arg 5).  This is essentially the same as
+      % the case above; we output the filename, since we have nothing else.
+      % 
+      \crossmanualxref{\code{\infofilename\unskip}}%
+    %
     \else
+      % Reference within this manual.
+      %
       % _ (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
+      {\turnoffactive
        % 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.
+      % output the `[mynode]' via the macro below so it can be overridden.
       \xrefprintnodename\printedrefname
       %
       % But we always want a comma and a space:
@@ -5952,12 +8030,38 @@
       ,\space
       %
       % output the `page 3'.
-      \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}%
-    \fi
+      \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+    \fi\fi
   \fi
   \endlink
 \endgroup}
 
+% Output a cross-manual xref to #1.  Used just above (twice).
+% 
+% Only include the text "Section ``foo'' in" if the foo is neither
+% missing or Top.  Thus, @xref{,,,foo,The Foo Manual} outputs simply
+% "see The Foo Manual", the idea being to refer to the whole manual.
+% 
+% But, this being TeX, we can't easily compare our node name against the
+% string "Top" while ignoring the possible spaces before and after in
+% the input.  By adding the arbitrary 7sp below, we make it much less
+% likely that a real node name would have the same width as "Top" (e.g.,
+% in a monospaced font).  Hopefully it will never happen in practice.
+% 
+% For the same basic reason, we retypeset the "Top" at every
+% reference, since the current font is indeterminate.
+% 
+\def\crossmanualxref#1{%
+  \setbox\toprefbox = \hbox{Top\kern7sp}%
+  \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}%
+  \ifdim \wd2 > 7sp  % nonempty?
+    \ifdim \wd2 = \wd\toprefbox \else  % same as Top?
+      \putwordSection{} ``\printedrefname'' \putwordin{}\space
+    \fi
+  \fi
+  #1%
+}
+
 % 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
@@ -6008,7 +8112,8 @@
     \angleleft un\-de\-fined\angleright
     \iflinks
       \ifhavexrefs
-        \message{\linenumber Undefined cross reference `#1'.}%
+        {\toks0 = {#1}% avoid expansion of possibly-complex value
+         \message{\linenumber Undefined cross reference `\the\toks0'.}}%
       \else
         \ifwarnedxrefs\else
           \global\warnedxrefstrue
@@ -6028,10 +8133,18 @@
 % 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.
+  {% The node name might contain 8-bit characters, which in our current
+   % implementation are changed to commands like @'e.  Don't let these
+   % mess up the control sequence name.
+    \indexnofonts
+    \turnoffactive
+    \xdef\safexrefname{#1}%
+  }%
   %
+  \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref
+  %
   % Was that xref control sequence that we just defined for a float?
-  \expandafter\iffloat\csname XR#1\endcsname
+  \expandafter\iffloat\csname XR\safexrefname\endcsname
     % it was a float, and we have the (safe) float type in \iffloattype.
     \expandafter\let\expandafter\floatlist
       \csname floatlist\iffloattype\endcsname
@@ -6046,7 +8159,8 @@
     %
     % Remember this xref in the control sequence \floatlistFLOATTYPE,
     % for later use in \listoffloats.
-    \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}%
+    \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0
+      {\safexrefname}}%
   \fi
 }
 
@@ -6055,13 +8169,13 @@
 \def\tryauxfile{%
   \openin 1 \jobname.aux
   \ifeof 1 \else
-    \readauxfile
+    \readdatafile{aux}%
     \global\havexrefstrue
   \fi
   \closein 1
 }
 
-\def\readauxfile{\begingroup
+\def\setupdatafile{%
   \catcode`\^^@=\other
   \catcode`\^^A=\other
   \catcode`\^^B=\other
@@ -6130,11 +8244,11 @@
   %
   % Make the characters 128-255 be printing characters.
   {%
-    \count 1=128
+    \count1=128
     \def\loop{%
-      \catcode\count 1=\other
-      \advance\count 1 by 1
-      \ifnum \count 1<256 \loop \fi
+      \catcode\count1=\other
+      \advance\count1 by 1
+      \ifnum \count1<256 \loop \fi
     }%
   }%
   %
@@ -6142,8 +8256,12 @@
   \catcode`\{=1
   \catcode`\}=2
   \catcode`\@=0
-  %
-  \input \jobname.aux
+}
+
+\def\readdatafile#1{%
+\begingroup
+  \setupdatafile
+  \input\jobname.#1
 \endgroup}
 
 
@@ -6159,7 +8277,7 @@
 % space to prevent strange expansion errors.)
 \def\supereject{\par\penalty -20000\footnoteno =0 }
 
-% @footnotestyle is meaningful for info output only.
+% @footnotestyle is meaningful for Info output only.
 \let\footnotestyle=\comment
 
 {\catcode `\@=11
@@ -6222,6 +8340,8 @@
   % expands into a box, it must come within the paragraph, lest it
   % provide a place where TeX can split the footnote.
   \footstrut
+  %
+  % Invoke rest of plain TeX footnote routine.
   \futurelet\next\fo at t
 }
 }%end \catcode `\@=11
@@ -6229,7 +8349,7 @@
 % 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
+% Similarly, 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.
 
@@ -6309,7 +8429,7 @@
   it from ftp://tug.org/tex/epsf.tex.}
 %
 \def\image#1{%
-  \ifx\epsfbox\undefined
+  \ifx\epsfbox\thisisundefined
     \ifwarnednoepsf \else
       \errhelp = \noepsfhelp
       \errmessage{epsf.tex not found, images will be ignored}%
@@ -6325,7 +8445,7 @@
 % #2 is (optional) width, #3 is (optional) height.
 % #4 is (ignored optional) html alt text.
 % #5 is (ignored optional) extension.
-% #6 is just the usual extra ignored arg for parsing this stuff.
+% #6 is just the usual extra ignored arg for parsing stuff.
 \newif\ifimagevmode
 \def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup
   \catcode`\^^M = 5     % in case we're inside an example
@@ -6333,15 +8453,30 @@
   % If the image is by itself, center it.
   \ifvmode
     \imagevmodetrue
-    \nobreak\bigskip
+  \else \ifx\centersub\centerV
+    % for @center @image, we need a vbox so we can have our vertical space
+    \imagevmodetrue
+    \vbox\bgroup % vbox has better behavior than vtop herev
+  \fi\fi
+  %
+  \ifimagevmode
+    \nobreak\medskip
     % Usually we'll have text after the image which will insert
     % \parskip glue, so insert it here too to equalize the space
     % above and below.
     \nobreak\vskip\parskip
     \nobreak
-    \line\bgroup\hss
   \fi
   %
+  % Leave vertical mode so that indentation from an enclosing
+  %  environment such as @quotation is respected.
+  % However, if we're at the top level, we don't want the
+  %  normal paragraph indentation.
+  % On the other hand, if we are in the case of @center @image, we don't
+  %  want to start a paragraph, which will create a hsize-width box and
+  %  eradicate the centering.
+  \ifx\centersub\centerV\else \noindent \fi
+  %
   % Output the image.
   \ifpdf
     \dopdfimage{#1}{#2}{#3}%
@@ -6352,7 +8487,10 @@
     \epsfbox{#1.eps}%
   \fi
   %
-  \ifimagevmode \hss \egroup \bigbreak \fi  % space after the image
+  \ifimagevmode
+    \medskip  % space after a standalone image
+  \fi  
+  \ifx\centersub\centerV \egroup \fi
 \endgroup}
 
 
@@ -6419,13 +8557,13 @@
       \global\advance\floatno by 1
       %
       {%
-        % This magic value for \thissection is output by \setref as the
+        % This magic value for \lastsection 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}%
+        \edef\lastsection{\floatmagic=\safefloattype}%
         \setref{\floatlabel}{Yfloat}%
       }%
     \fi
@@ -6492,7 +8630,8 @@
       % \floatlabel-lof.  Besides \floatident, we include the short
       % caption if specified, else the full caption if specified, else nothing.
       {%
-        \atdummies \turnoffactive \otherbackslash
+        \atdummies
+        %
         % 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.
@@ -6513,8 +8652,9 @@
   %
   % 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
+  % BEWARE: when the floats start floating, we have to issue warning
+  % whenever an insert appears inside a float which could possibly
+  % float. --kasal, 26may04
   %
   \checkinserts
 }
@@ -6558,7 +8698,7 @@
 
 % #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.
+% \lastsection value which we \setref above.
 %
 \def\iffloat#1{\expandafter\doiffloat#1==\finish}
 %
@@ -6619,39 +8759,909 @@
   \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.
+% For single-language documents, @documentlanguage is usually given very
+% early, just after @documentencoding.  Single argument is the language
+% (de) or locale (de_DE) abbreviation.
 %
-\parseargdef\documentlanguage{%
+{
+  \catcode`\_ = \active
+  \globaldefs=1
+\parseargdef\documentlanguage{\begingroup
+  \let_=\normalunderscore  % normal _ character for filenames
   \tex % read txi-??.tex file in plain TeX.
-    % Read the file if it exists.
+    % Read the file by the name they passed if it exists.
     \openin 1 txi-#1.tex
     \ifeof 1
-      \errhelp = \nolanghelp
-      \errmessage{Cannot read language file txi-#1.tex}%
+      \documentlanguagetrywithoutunderscore{#1_\finish}%
     \else
+      \globaldefs = 1  % everything in the txi-LL files needs to persist
       \input txi-#1.tex
     \fi
     \closein 1
-  \endgroup
+  \endgroup % end raw TeX
+\endgroup}
+%
+% If they passed de_DE, and txi-de_DE.tex doesn't exist,
+% try txi-de.tex.
+%
+\gdef\documentlanguagetrywithoutunderscore#1_#2\finish{%
+  \openin 1 txi-#1.tex
+  \ifeof 1
+    \errhelp = \nolanghelp
+    \errmessage{Cannot read language file txi-#1.tex}%
+  \else
+    \globaldefs = 1  % everything in the txi-LL files needs to persist
+    \input txi-#1.tex
+  \fi
+  \closein 1
 }
+}% end of special _ catcode
+%
 \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.}
+is empty.  Maybe you need to install it?  Putting it in the current
+directory should work if nowhere else does.}
 
+% This macro is called from txi-??.tex files; the first argument is the
+% \language name to set (without the "\lang@" prefix), the second and
+% third args are \{left,right}hyphenmin.
+%
+% The language names to pass are determined when the format is built.
+% See the etex.log file created at that time, e.g.,
+% /usr/local/texlive/2008/texmf-var/web2c/pdftex/etex.log.
+%
+% With TeX Live 2008, etex now includes hyphenation patterns for all
+% available languages.  This means we can support hyphenation in
+% Texinfo, at least to some extent.  (This still doesn't solve the
+% accented characters problem.)
+%
+\catcode`@=11
+\def\txisetlanguage#1#2#3{%
+  % do not set the language if the name is undefined in the current TeX.
+  \expandafter\ifx\csname lang@#1\endcsname \relax
+    \message{no patterns for #1}%
+  \else
+    \global\language = \csname lang@#1\endcsname
+  \fi
+  % but there is no harm in adjusting the hyphenmin values regardless.
+  \global\lefthyphenmin = #2\relax
+  \global\righthyphenmin = #3\relax
+}
 
-% @documentencoding should change something in TeX eventually, most
-% likely, but for now just recognize it.
-\let\documentencoding = \comment
+% Helpers for encodings.
+% Set the catcode of characters 128 through 255 to the specified number.
+%
+\def\setnonasciicharscatcode#1{%
+   \count255=128
+   \loop\ifnum\count255<256
+      \global\catcode\count255=#1\relax
+      \advance\count255 by 1
+   \repeat
+}
 
+\def\setnonasciicharscatcodenonglobal#1{%
+   \count255=128
+   \loop\ifnum\count255<256
+      \catcode\count255=#1\relax
+      \advance\count255 by 1
+   \repeat
+}
 
-% Page size parameters.
+% @documentencoding sets the definition of non-ASCII characters
+% according to the specified encoding.
 %
+\parseargdef\documentencoding{%
+  % Encoding being declared for the document.
+  \def\declaredencoding{\csname #1.enc\endcsname}%
+  %
+  % Supported encodings: names converted to tokens in order to be able
+  % to compare them with \ifx.
+  \def\ascii{\csname US-ASCII.enc\endcsname}%
+  \def\latnine{\csname ISO-8859-15.enc\endcsname}%
+  \def\latone{\csname ISO-8859-1.enc\endcsname}%
+  \def\lattwo{\csname ISO-8859-2.enc\endcsname}%
+  \def\utfeight{\csname UTF-8.enc\endcsname}%
+  %
+  \ifx \declaredencoding \ascii
+     \asciichardefs
+  %
+  \else \ifx \declaredencoding \lattwo
+     \setnonasciicharscatcode\active
+     \lattwochardefs
+  %
+  \else \ifx \declaredencoding \latone
+     \setnonasciicharscatcode\active
+     \latonechardefs
+  %
+  \else \ifx \declaredencoding \latnine
+     \setnonasciicharscatcode\active
+     \latninechardefs
+  %
+  \else \ifx \declaredencoding \utfeight
+     \setnonasciicharscatcode\active
+     \utfeightchardefs
+  %
+  \else
+    \message{Unknown document encoding #1, ignoring.}%
+  %
+  \fi % utfeight
+  \fi % latnine
+  \fi % latone
+  \fi % lattwo
+  \fi % ascii
+}
+
+% A message to be logged when using a character that isn't available
+% the default font encoding (OT1).
+%
+\def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}}
+
+% Take account of \c (plain) vs. \, (Texinfo) difference.
+\def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi}
+
+% First, make active non-ASCII characters in order for them to be
+% correctly categorized when TeX reads the replacement text of
+% macros containing the character definitions.
+\setnonasciicharscatcode\active
+%
+% Latin1 (ISO-8859-1) character definitions.
+\def\latonechardefs{%
+  \gdef^^a0{\tie}
+  \gdef^^a1{\exclamdown}
+  \gdef^^a2{\missingcharmsg{CENT SIGN}}
+  \gdef^^a3{{\pounds}}
+  \gdef^^a4{\missingcharmsg{CURRENCY SIGN}}
+  \gdef^^a5{\missingcharmsg{YEN SIGN}}
+  \gdef^^a6{\missingcharmsg{BROKEN BAR}}
+  \gdef^^a7{\S}
+  \gdef^^a8{\"{}}
+  \gdef^^a9{\copyright}
+  \gdef^^aa{\ordf}
+  \gdef^^ab{\guillemetleft}
+  \gdef^^ac{$\lnot$}
+  \gdef^^ad{\-}
+  \gdef^^ae{\registeredsymbol}
+  \gdef^^af{\={}}
+  %
+  \gdef^^b0{\textdegree}
+  \gdef^^b1{$\pm$}
+  \gdef^^b2{$^2$}
+  \gdef^^b3{$^3$}
+  \gdef^^b4{\'{}}
+  \gdef^^b5{$\mu$}
+  \gdef^^b6{\P}
+  %
+  \gdef^^b7{$^.$}
+  \gdef^^b8{\cedilla\ }
+  \gdef^^b9{$^1$}
+  \gdef^^ba{\ordm}
+  %
+  \gdef^^bb{\guillemetright}
+  \gdef^^bc{$1\over4$}
+  \gdef^^bd{$1\over2$}
+  \gdef^^be{$3\over4$}
+  \gdef^^bf{\questiondown}
+  %
+  \gdef^^c0{\`A}
+  \gdef^^c1{\'A}
+  \gdef^^c2{\^A}
+  \gdef^^c3{\~A}
+  \gdef^^c4{\"A}
+  \gdef^^c5{\ringaccent A}
+  \gdef^^c6{\AE}
+  \gdef^^c7{\cedilla C}
+  \gdef^^c8{\`E}
+  \gdef^^c9{\'E}
+  \gdef^^ca{\^E}
+  \gdef^^cb{\"E}
+  \gdef^^cc{\`I}
+  \gdef^^cd{\'I}
+  \gdef^^ce{\^I}
+  \gdef^^cf{\"I}
+  %
+  \gdef^^d0{\DH}
+  \gdef^^d1{\~N}
+  \gdef^^d2{\`O}
+  \gdef^^d3{\'O}
+  \gdef^^d4{\^O}
+  \gdef^^d5{\~O}
+  \gdef^^d6{\"O}
+  \gdef^^d7{$\times$}
+  \gdef^^d8{\O}
+  \gdef^^d9{\`U}
+  \gdef^^da{\'U}
+  \gdef^^db{\^U}
+  \gdef^^dc{\"U}
+  \gdef^^dd{\'Y}
+  \gdef^^de{\TH}
+  \gdef^^df{\ss}
+  %
+  \gdef^^e0{\`a}
+  \gdef^^e1{\'a}
+  \gdef^^e2{\^a}
+  \gdef^^e3{\~a}
+  \gdef^^e4{\"a}
+  \gdef^^e5{\ringaccent a}
+  \gdef^^e6{\ae}
+  \gdef^^e7{\cedilla c}
+  \gdef^^e8{\`e}
+  \gdef^^e9{\'e}
+  \gdef^^ea{\^e}
+  \gdef^^eb{\"e}
+  \gdef^^ec{\`{\dotless i}}
+  \gdef^^ed{\'{\dotless i}}
+  \gdef^^ee{\^{\dotless i}}
+  \gdef^^ef{\"{\dotless i}}
+  %
+  \gdef^^f0{\dh}
+  \gdef^^f1{\~n}
+  \gdef^^f2{\`o}
+  \gdef^^f3{\'o}
+  \gdef^^f4{\^o}
+  \gdef^^f5{\~o}
+  \gdef^^f6{\"o}
+  \gdef^^f7{$\div$}
+  \gdef^^f8{\o}
+  \gdef^^f9{\`u}
+  \gdef^^fa{\'u}
+  \gdef^^fb{\^u}
+  \gdef^^fc{\"u}
+  \gdef^^fd{\'y}
+  \gdef^^fe{\th}
+  \gdef^^ff{\"y}
+}
+
+% Latin9 (ISO-8859-15) encoding character definitions.
+\def\latninechardefs{%
+  % Encoding is almost identical to Latin1.
+  \latonechardefs
+  %
+  \gdef^^a4{\euro}
+  \gdef^^a6{\v S}
+  \gdef^^a8{\v s}
+  \gdef^^b4{\v Z}
+  \gdef^^b8{\v z}
+  \gdef^^bc{\OE}
+  \gdef^^bd{\oe}
+  \gdef^^be{\"Y}
+}
+
+% Latin2 (ISO-8859-2) character definitions.
+\def\lattwochardefs{%
+  \gdef^^a0{\tie}
+  \gdef^^a1{\ogonek{A}}
+  \gdef^^a2{\u{}}
+  \gdef^^a3{\L}
+  \gdef^^a4{\missingcharmsg{CURRENCY SIGN}}
+  \gdef^^a5{\v L}
+  \gdef^^a6{\'S}
+  \gdef^^a7{\S}
+  \gdef^^a8{\"{}}
+  \gdef^^a9{\v S}
+  \gdef^^aa{\cedilla S}
+  \gdef^^ab{\v T}
+  \gdef^^ac{\'Z}
+  \gdef^^ad{\-}
+  \gdef^^ae{\v Z}
+  \gdef^^af{\dotaccent Z}
+  %
+  \gdef^^b0{\textdegree}
+  \gdef^^b1{\ogonek{a}}
+  \gdef^^b2{\ogonek{ }}
+  \gdef^^b3{\l}
+  \gdef^^b4{\'{}}
+  \gdef^^b5{\v l}
+  \gdef^^b6{\'s}
+  \gdef^^b7{\v{}}
+  \gdef^^b8{\cedilla\ }
+  \gdef^^b9{\v s}
+  \gdef^^ba{\cedilla s}
+  \gdef^^bb{\v t}
+  \gdef^^bc{\'z}
+  \gdef^^bd{\H{}}
+  \gdef^^be{\v z}
+  \gdef^^bf{\dotaccent z}
+  %
+  \gdef^^c0{\'R}
+  \gdef^^c1{\'A}
+  \gdef^^c2{\^A}
+  \gdef^^c3{\u A}
+  \gdef^^c4{\"A}
+  \gdef^^c5{\'L}
+  \gdef^^c6{\'C}
+  \gdef^^c7{\cedilla C}
+  \gdef^^c8{\v C}
+  \gdef^^c9{\'E}
+  \gdef^^ca{\ogonek{E}}
+  \gdef^^cb{\"E}
+  \gdef^^cc{\v E}
+  \gdef^^cd{\'I}
+  \gdef^^ce{\^I}
+  \gdef^^cf{\v D}
+  %
+  \gdef^^d0{\DH}
+  \gdef^^d1{\'N}
+  \gdef^^d2{\v N}
+  \gdef^^d3{\'O}
+  \gdef^^d4{\^O}
+  \gdef^^d5{\H O}
+  \gdef^^d6{\"O}
+  \gdef^^d7{$\times$}
+  \gdef^^d8{\v R}
+  \gdef^^d9{\ringaccent U}
+  \gdef^^da{\'U}
+  \gdef^^db{\H U}
+  \gdef^^dc{\"U}
+  \gdef^^dd{\'Y}
+  \gdef^^de{\cedilla T}
+  \gdef^^df{\ss}
+  %
+  \gdef^^e0{\'r}
+  \gdef^^e1{\'a}
+  \gdef^^e2{\^a}
+  \gdef^^e3{\u a}
+  \gdef^^e4{\"a}
+  \gdef^^e5{\'l}
+  \gdef^^e6{\'c}
+  \gdef^^e7{\cedilla c}
+  \gdef^^e8{\v c}
+  \gdef^^e9{\'e}
+  \gdef^^ea{\ogonek{e}}
+  \gdef^^eb{\"e}
+  \gdef^^ec{\v e}
+  \gdef^^ed{\'{\dotless{i}}}
+  \gdef^^ee{\^{\dotless{i}}}
+  \gdef^^ef{\v d}
+  %
+  \gdef^^f0{\dh}
+  \gdef^^f1{\'n}
+  \gdef^^f2{\v n}
+  \gdef^^f3{\'o}
+  \gdef^^f4{\^o}
+  \gdef^^f5{\H o}
+  \gdef^^f6{\"o}
+  \gdef^^f7{$\div$}
+  \gdef^^f8{\v r}
+  \gdef^^f9{\ringaccent u}
+  \gdef^^fa{\'u}
+  \gdef^^fb{\H u}
+  \gdef^^fc{\"u}
+  \gdef^^fd{\'y}
+  \gdef^^fe{\cedilla t}
+  \gdef^^ff{\dotaccent{}}
+}
+
+% UTF-8 character definitions.
+%
+% This code to support UTF-8 is based on LaTeX's utf8.def, with some
+% changes for Texinfo conventions.  It is included here under the GPL by
+% permission from Frank Mittelbach and the LaTeX team.
+%
+\newcount\countUTFx
+\newcount\countUTFy
+\newcount\countUTFz
+
+\gdef\UTFviiiTwoOctets#1#2{\expandafter
+   \UTFviiiDefined\csname u8:#1\string #2\endcsname}
+%
+\gdef\UTFviiiThreeOctets#1#2#3{\expandafter
+   \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname}
+%
+\gdef\UTFviiiFourOctets#1#2#3#4{\expandafter
+   \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname}
+
+\gdef\UTFviiiDefined#1{%
+  \ifx #1\relax
+    \message{\linenumber Unicode char \string #1 not defined for Texinfo}%
+  \else
+    \expandafter #1%
+  \fi
+}
+
+\begingroup
+  \catcode`\~13
+  \catcode`\"12
+
+  \def\UTFviiiLoop{%
+    \global\catcode\countUTFx\active
+    \uccode`\~\countUTFx
+    \uppercase\expandafter{\UTFviiiTmp}%
+    \advance\countUTFx by 1
+    \ifnum\countUTFx < \countUTFy
+      \expandafter\UTFviiiLoop
+    \fi}
+
+  \countUTFx = "C2
+  \countUTFy = "E0
+  \def\UTFviiiTmp{%
+    \xdef~{\noexpand\UTFviiiTwoOctets\string~}}
+  \UTFviiiLoop
+
+  \countUTFx = "E0
+  \countUTFy = "F0
+  \def\UTFviiiTmp{%
+    \xdef~{\noexpand\UTFviiiThreeOctets\string~}}
+  \UTFviiiLoop
+
+  \countUTFx = "F0
+  \countUTFy = "F4
+  \def\UTFviiiTmp{%
+    \xdef~{\noexpand\UTFviiiFourOctets\string~}}
+  \UTFviiiLoop
+\endgroup
+
+\begingroup
+  \catcode`\"=12
+  \catcode`\<=12
+  \catcode`\.=12
+  \catcode`\,=12
+  \catcode`\;=12
+  \catcode`\!=12
+  \catcode`\~=13
+
+  \gdef\DeclareUnicodeCharacter#1#2{%
+    \countUTFz = "#1\relax
+    %\wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}%
+    \begingroup
+      \parseXMLCharref
+      \def\UTFviiiTwoOctets##1##2{%
+        \csname u8:##1\string ##2\endcsname}%
+      \def\UTFviiiThreeOctets##1##2##3{%
+        \csname u8:##1\string ##2\string ##3\endcsname}%
+      \def\UTFviiiFourOctets##1##2##3##4{%
+        \csname u8:##1\string ##2\string ##3\string ##4\endcsname}%
+      \expandafter\expandafter\expandafter\expandafter
+       \expandafter\expandafter\expandafter
+       \gdef\UTFviiiTmp{#2}%
+    \endgroup}
+
+  \gdef\parseXMLCharref{%
+    \ifnum\countUTFz < "A0\relax
+      \errhelp = \EMsimple
+      \errmessage{Cannot define Unicode char value < 00A0}%
+    \else\ifnum\countUTFz < "800\relax
+      \parseUTFviiiA,%
+      \parseUTFviiiB C\UTFviiiTwoOctets.,%
+    \else\ifnum\countUTFz < "10000\relax
+      \parseUTFviiiA;%
+      \parseUTFviiiA,%
+      \parseUTFviiiB E\UTFviiiThreeOctets.{,;}%
+    \else
+      \parseUTFviiiA;%
+      \parseUTFviiiA,%
+      \parseUTFviiiA!%
+      \parseUTFviiiB F\UTFviiiFourOctets.{!,;}%
+    \fi\fi\fi
+  }
+
+  \gdef\parseUTFviiiA#1{%
+    \countUTFx = \countUTFz
+    \divide\countUTFz by 64
+    \countUTFy = \countUTFz
+    \multiply\countUTFz by 64
+    \advance\countUTFx by -\countUTFz
+    \advance\countUTFx by 128
+    \uccode `#1\countUTFx
+    \countUTFz = \countUTFy}
+
+  \gdef\parseUTFviiiB#1#2#3#4{%
+    \advance\countUTFz by "#10\relax
+    \uccode `#3\countUTFz
+    \uppercase{\gdef\UTFviiiTmp{#2#3#4}}}
+\endgroup
+
+\def\utfeightchardefs{%
+  \DeclareUnicodeCharacter{00A0}{\tie}
+  \DeclareUnicodeCharacter{00A1}{\exclamdown}
+  \DeclareUnicodeCharacter{00A3}{\pounds}
+  \DeclareUnicodeCharacter{00A8}{\"{ }}
+  \DeclareUnicodeCharacter{00A9}{\copyright}
+  \DeclareUnicodeCharacter{00AA}{\ordf}
+  \DeclareUnicodeCharacter{00AB}{\guillemetleft}
+  \DeclareUnicodeCharacter{00AD}{\-}
+  \DeclareUnicodeCharacter{00AE}{\registeredsymbol}
+  \DeclareUnicodeCharacter{00AF}{\={ }}
+
+  \DeclareUnicodeCharacter{00B0}{\ringaccent{ }}
+  \DeclareUnicodeCharacter{00B4}{\'{ }}
+  \DeclareUnicodeCharacter{00B8}{\cedilla{ }}
+  \DeclareUnicodeCharacter{00BA}{\ordm}
+  \DeclareUnicodeCharacter{00BB}{\guillemetright}
+  \DeclareUnicodeCharacter{00BF}{\questiondown}
+
+  \DeclareUnicodeCharacter{00C0}{\`A}
+  \DeclareUnicodeCharacter{00C1}{\'A}
+  \DeclareUnicodeCharacter{00C2}{\^A}
+  \DeclareUnicodeCharacter{00C3}{\~A}
+  \DeclareUnicodeCharacter{00C4}{\"A}
+  \DeclareUnicodeCharacter{00C5}{\AA}
+  \DeclareUnicodeCharacter{00C6}{\AE}
+  \DeclareUnicodeCharacter{00C7}{\cedilla{C}}
+  \DeclareUnicodeCharacter{00C8}{\`E}
+  \DeclareUnicodeCharacter{00C9}{\'E}
+  \DeclareUnicodeCharacter{00CA}{\^E}
+  \DeclareUnicodeCharacter{00CB}{\"E}
+  \DeclareUnicodeCharacter{00CC}{\`I}
+  \DeclareUnicodeCharacter{00CD}{\'I}
+  \DeclareUnicodeCharacter{00CE}{\^I}
+  \DeclareUnicodeCharacter{00CF}{\"I}
+
+  \DeclareUnicodeCharacter{00D0}{\DH}
+  \DeclareUnicodeCharacter{00D1}{\~N}
+  \DeclareUnicodeCharacter{00D2}{\`O}
+  \DeclareUnicodeCharacter{00D3}{\'O}
+  \DeclareUnicodeCharacter{00D4}{\^O}
+  \DeclareUnicodeCharacter{00D5}{\~O}
+  \DeclareUnicodeCharacter{00D6}{\"O}
+  \DeclareUnicodeCharacter{00D8}{\O}
+  \DeclareUnicodeCharacter{00D9}{\`U}
+  \DeclareUnicodeCharacter{00DA}{\'U}
+  \DeclareUnicodeCharacter{00DB}{\^U}
+  \DeclareUnicodeCharacter{00DC}{\"U}
+  \DeclareUnicodeCharacter{00DD}{\'Y}
+  \DeclareUnicodeCharacter{00DE}{\TH}
+  \DeclareUnicodeCharacter{00DF}{\ss}
+
+  \DeclareUnicodeCharacter{00E0}{\`a}
+  \DeclareUnicodeCharacter{00E1}{\'a}
+  \DeclareUnicodeCharacter{00E2}{\^a}
+  \DeclareUnicodeCharacter{00E3}{\~a}
+  \DeclareUnicodeCharacter{00E4}{\"a}
+  \DeclareUnicodeCharacter{00E5}{\aa}
+  \DeclareUnicodeCharacter{00E6}{\ae}
+  \DeclareUnicodeCharacter{00E7}{\cedilla{c}}
+  \DeclareUnicodeCharacter{00E8}{\`e}
+  \DeclareUnicodeCharacter{00E9}{\'e}
+  \DeclareUnicodeCharacter{00EA}{\^e}
+  \DeclareUnicodeCharacter{00EB}{\"e}
+  \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}}
+  \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}}
+  \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}}
+  \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}}
+
+  \DeclareUnicodeCharacter{00F0}{\dh}
+  \DeclareUnicodeCharacter{00F1}{\~n}
+  \DeclareUnicodeCharacter{00F2}{\`o}
+  \DeclareUnicodeCharacter{00F3}{\'o}
+  \DeclareUnicodeCharacter{00F4}{\^o}
+  \DeclareUnicodeCharacter{00F5}{\~o}
+  \DeclareUnicodeCharacter{00F6}{\"o}
+  \DeclareUnicodeCharacter{00F8}{\o}
+  \DeclareUnicodeCharacter{00F9}{\`u}
+  \DeclareUnicodeCharacter{00FA}{\'u}
+  \DeclareUnicodeCharacter{00FB}{\^u}
+  \DeclareUnicodeCharacter{00FC}{\"u}
+  \DeclareUnicodeCharacter{00FD}{\'y}
+  \DeclareUnicodeCharacter{00FE}{\th}
+  \DeclareUnicodeCharacter{00FF}{\"y}
+
+  \DeclareUnicodeCharacter{0100}{\=A}
+  \DeclareUnicodeCharacter{0101}{\=a}
+  \DeclareUnicodeCharacter{0102}{\u{A}}
+  \DeclareUnicodeCharacter{0103}{\u{a}}
+  \DeclareUnicodeCharacter{0104}{\ogonek{A}}
+  \DeclareUnicodeCharacter{0105}{\ogonek{a}}
+  \DeclareUnicodeCharacter{0106}{\'C}
+  \DeclareUnicodeCharacter{0107}{\'c}
+  \DeclareUnicodeCharacter{0108}{\^C}
+  \DeclareUnicodeCharacter{0109}{\^c}
+  \DeclareUnicodeCharacter{0118}{\ogonek{E}}
+  \DeclareUnicodeCharacter{0119}{\ogonek{e}}
+  \DeclareUnicodeCharacter{010A}{\dotaccent{C}}
+  \DeclareUnicodeCharacter{010B}{\dotaccent{c}}
+  \DeclareUnicodeCharacter{010C}{\v{C}}
+  \DeclareUnicodeCharacter{010D}{\v{c}}
+  \DeclareUnicodeCharacter{010E}{\v{D}}
+
+  \DeclareUnicodeCharacter{0112}{\=E}
+  \DeclareUnicodeCharacter{0113}{\=e}
+  \DeclareUnicodeCharacter{0114}{\u{E}}
+  \DeclareUnicodeCharacter{0115}{\u{e}}
+  \DeclareUnicodeCharacter{0116}{\dotaccent{E}}
+  \DeclareUnicodeCharacter{0117}{\dotaccent{e}}
+  \DeclareUnicodeCharacter{011A}{\v{E}}
+  \DeclareUnicodeCharacter{011B}{\v{e}}
+  \DeclareUnicodeCharacter{011C}{\^G}
+  \DeclareUnicodeCharacter{011D}{\^g}
+  \DeclareUnicodeCharacter{011E}{\u{G}}
+  \DeclareUnicodeCharacter{011F}{\u{g}}
+
+  \DeclareUnicodeCharacter{0120}{\dotaccent{G}}
+  \DeclareUnicodeCharacter{0121}{\dotaccent{g}}
+  \DeclareUnicodeCharacter{0124}{\^H}
+  \DeclareUnicodeCharacter{0125}{\^h}
+  \DeclareUnicodeCharacter{0128}{\~I}
+  \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}}
+  \DeclareUnicodeCharacter{012A}{\=I}
+  \DeclareUnicodeCharacter{012B}{\={\dotless{i}}}
+  \DeclareUnicodeCharacter{012C}{\u{I}}
+  \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}}
+
+  \DeclareUnicodeCharacter{0130}{\dotaccent{I}}
+  \DeclareUnicodeCharacter{0131}{\dotless{i}}
+  \DeclareUnicodeCharacter{0132}{IJ}
+  \DeclareUnicodeCharacter{0133}{ij}
+  \DeclareUnicodeCharacter{0134}{\^J}
+  \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}}
+  \DeclareUnicodeCharacter{0139}{\'L}
+  \DeclareUnicodeCharacter{013A}{\'l}
+
+  \DeclareUnicodeCharacter{0141}{\L}
+  \DeclareUnicodeCharacter{0142}{\l}
+  \DeclareUnicodeCharacter{0143}{\'N}
+  \DeclareUnicodeCharacter{0144}{\'n}
+  \DeclareUnicodeCharacter{0147}{\v{N}}
+  \DeclareUnicodeCharacter{0148}{\v{n}}
+  \DeclareUnicodeCharacter{014C}{\=O}
+  \DeclareUnicodeCharacter{014D}{\=o}
+  \DeclareUnicodeCharacter{014E}{\u{O}}
+  \DeclareUnicodeCharacter{014F}{\u{o}}
+
+  \DeclareUnicodeCharacter{0150}{\H{O}}
+  \DeclareUnicodeCharacter{0151}{\H{o}}
+  \DeclareUnicodeCharacter{0152}{\OE}
+  \DeclareUnicodeCharacter{0153}{\oe}
+  \DeclareUnicodeCharacter{0154}{\'R}
+  \DeclareUnicodeCharacter{0155}{\'r}
+  \DeclareUnicodeCharacter{0158}{\v{R}}
+  \DeclareUnicodeCharacter{0159}{\v{r}}
+  \DeclareUnicodeCharacter{015A}{\'S}
+  \DeclareUnicodeCharacter{015B}{\'s}
+  \DeclareUnicodeCharacter{015C}{\^S}
+  \DeclareUnicodeCharacter{015D}{\^s}
+  \DeclareUnicodeCharacter{015E}{\cedilla{S}}
+  \DeclareUnicodeCharacter{015F}{\cedilla{s}}
+
+  \DeclareUnicodeCharacter{0160}{\v{S}}
+  \DeclareUnicodeCharacter{0161}{\v{s}}
+  \DeclareUnicodeCharacter{0162}{\cedilla{t}}
+  \DeclareUnicodeCharacter{0163}{\cedilla{T}}
+  \DeclareUnicodeCharacter{0164}{\v{T}}
+
+  \DeclareUnicodeCharacter{0168}{\~U}
+  \DeclareUnicodeCharacter{0169}{\~u}
+  \DeclareUnicodeCharacter{016A}{\=U}
+  \DeclareUnicodeCharacter{016B}{\=u}
+  \DeclareUnicodeCharacter{016C}{\u{U}}
+  \DeclareUnicodeCharacter{016D}{\u{u}}
+  \DeclareUnicodeCharacter{016E}{\ringaccent{U}}
+  \DeclareUnicodeCharacter{016F}{\ringaccent{u}}
+
+  \DeclareUnicodeCharacter{0170}{\H{U}}
+  \DeclareUnicodeCharacter{0171}{\H{u}}
+  \DeclareUnicodeCharacter{0174}{\^W}
+  \DeclareUnicodeCharacter{0175}{\^w}
+  \DeclareUnicodeCharacter{0176}{\^Y}
+  \DeclareUnicodeCharacter{0177}{\^y}
+  \DeclareUnicodeCharacter{0178}{\"Y}
+  \DeclareUnicodeCharacter{0179}{\'Z}
+  \DeclareUnicodeCharacter{017A}{\'z}
+  \DeclareUnicodeCharacter{017B}{\dotaccent{Z}}
+  \DeclareUnicodeCharacter{017C}{\dotaccent{z}}
+  \DeclareUnicodeCharacter{017D}{\v{Z}}
+  \DeclareUnicodeCharacter{017E}{\v{z}}
+
+  \DeclareUnicodeCharacter{01C4}{D\v{Z}}
+  \DeclareUnicodeCharacter{01C5}{D\v{z}}
+  \DeclareUnicodeCharacter{01C6}{d\v{z}}
+  \DeclareUnicodeCharacter{01C7}{LJ}
+  \DeclareUnicodeCharacter{01C8}{Lj}
+  \DeclareUnicodeCharacter{01C9}{lj}
+  \DeclareUnicodeCharacter{01CA}{NJ}
+  \DeclareUnicodeCharacter{01CB}{Nj}
+  \DeclareUnicodeCharacter{01CC}{nj}
+  \DeclareUnicodeCharacter{01CD}{\v{A}}
+  \DeclareUnicodeCharacter{01CE}{\v{a}}
+  \DeclareUnicodeCharacter{01CF}{\v{I}}
+
+  \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}}
+  \DeclareUnicodeCharacter{01D1}{\v{O}}
+  \DeclareUnicodeCharacter{01D2}{\v{o}}
+  \DeclareUnicodeCharacter{01D3}{\v{U}}
+  \DeclareUnicodeCharacter{01D4}{\v{u}}
+
+  \DeclareUnicodeCharacter{01E2}{\={\AE}}
+  \DeclareUnicodeCharacter{01E3}{\={\ae}}
+  \DeclareUnicodeCharacter{01E6}{\v{G}}
+  \DeclareUnicodeCharacter{01E7}{\v{g}}
+  \DeclareUnicodeCharacter{01E8}{\v{K}}
+  \DeclareUnicodeCharacter{01E9}{\v{k}}
+
+  \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}}
+  \DeclareUnicodeCharacter{01F1}{DZ}
+  \DeclareUnicodeCharacter{01F2}{Dz}
+  \DeclareUnicodeCharacter{01F3}{dz}
+  \DeclareUnicodeCharacter{01F4}{\'G}
+  \DeclareUnicodeCharacter{01F5}{\'g}
+  \DeclareUnicodeCharacter{01F8}{\`N}
+  \DeclareUnicodeCharacter{01F9}{\`n}
+  \DeclareUnicodeCharacter{01FC}{\'{\AE}}
+  \DeclareUnicodeCharacter{01FD}{\'{\ae}}
+  \DeclareUnicodeCharacter{01FE}{\'{\O}}
+  \DeclareUnicodeCharacter{01FF}{\'{\o}}
+
+  \DeclareUnicodeCharacter{021E}{\v{H}}
+  \DeclareUnicodeCharacter{021F}{\v{h}}
+
+  \DeclareUnicodeCharacter{0226}{\dotaccent{A}}
+  \DeclareUnicodeCharacter{0227}{\dotaccent{a}}
+  \DeclareUnicodeCharacter{0228}{\cedilla{E}}
+  \DeclareUnicodeCharacter{0229}{\cedilla{e}}
+  \DeclareUnicodeCharacter{022E}{\dotaccent{O}}
+  \DeclareUnicodeCharacter{022F}{\dotaccent{o}}
+
+  \DeclareUnicodeCharacter{0232}{\=Y}
+  \DeclareUnicodeCharacter{0233}{\=y}
+  \DeclareUnicodeCharacter{0237}{\dotless{j}}
+
+  \DeclareUnicodeCharacter{02DB}{\ogonek{ }}
+
+  \DeclareUnicodeCharacter{1E02}{\dotaccent{B}}
+  \DeclareUnicodeCharacter{1E03}{\dotaccent{b}}
+  \DeclareUnicodeCharacter{1E04}{\udotaccent{B}}
+  \DeclareUnicodeCharacter{1E05}{\udotaccent{b}}
+  \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}}
+  \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}}
+  \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}}
+  \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}}
+  \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}}
+  \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}}
+  \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}}
+  \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}}
+
+  \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}}
+  \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}}
+
+  \DeclareUnicodeCharacter{1E20}{\=G}
+  \DeclareUnicodeCharacter{1E21}{\=g}
+  \DeclareUnicodeCharacter{1E22}{\dotaccent{H}}
+  \DeclareUnicodeCharacter{1E23}{\dotaccent{h}}
+  \DeclareUnicodeCharacter{1E24}{\udotaccent{H}}
+  \DeclareUnicodeCharacter{1E25}{\udotaccent{h}}
+  \DeclareUnicodeCharacter{1E26}{\"H}
+  \DeclareUnicodeCharacter{1E27}{\"h}
+
+  \DeclareUnicodeCharacter{1E30}{\'K}
+  \DeclareUnicodeCharacter{1E31}{\'k}
+  \DeclareUnicodeCharacter{1E32}{\udotaccent{K}}
+  \DeclareUnicodeCharacter{1E33}{\udotaccent{k}}
+  \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}}
+  \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}}
+  \DeclareUnicodeCharacter{1E36}{\udotaccent{L}}
+  \DeclareUnicodeCharacter{1E37}{\udotaccent{l}}
+  \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}}
+  \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}}
+  \DeclareUnicodeCharacter{1E3E}{\'M}
+  \DeclareUnicodeCharacter{1E3F}{\'m}
+
+  \DeclareUnicodeCharacter{1E40}{\dotaccent{M}}
+  \DeclareUnicodeCharacter{1E41}{\dotaccent{m}}
+  \DeclareUnicodeCharacter{1E42}{\udotaccent{M}}
+  \DeclareUnicodeCharacter{1E43}{\udotaccent{m}}
+  \DeclareUnicodeCharacter{1E44}{\dotaccent{N}}
+  \DeclareUnicodeCharacter{1E45}{\dotaccent{n}}
+  \DeclareUnicodeCharacter{1E46}{\udotaccent{N}}
+  \DeclareUnicodeCharacter{1E47}{\udotaccent{n}}
+  \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}}
+  \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}}
+
+  \DeclareUnicodeCharacter{1E54}{\'P}
+  \DeclareUnicodeCharacter{1E55}{\'p}
+  \DeclareUnicodeCharacter{1E56}{\dotaccent{P}}
+  \DeclareUnicodeCharacter{1E57}{\dotaccent{p}}
+  \DeclareUnicodeCharacter{1E58}{\dotaccent{R}}
+  \DeclareUnicodeCharacter{1E59}{\dotaccent{r}}
+  \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}}
+  \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}}
+  \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}}
+  \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}}
+
+  \DeclareUnicodeCharacter{1E60}{\dotaccent{S}}
+  \DeclareUnicodeCharacter{1E61}{\dotaccent{s}}
+  \DeclareUnicodeCharacter{1E62}{\udotaccent{S}}
+  \DeclareUnicodeCharacter{1E63}{\udotaccent{s}}
+  \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}}
+  \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}}
+  \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}}
+  \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}}
+  \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}}
+  \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}}
+
+  \DeclareUnicodeCharacter{1E7C}{\~V}
+  \DeclareUnicodeCharacter{1E7D}{\~v}
+  \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}}
+  \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}}
+
+  \DeclareUnicodeCharacter{1E80}{\`W}
+  \DeclareUnicodeCharacter{1E81}{\`w}
+  \DeclareUnicodeCharacter{1E82}{\'W}
+  \DeclareUnicodeCharacter{1E83}{\'w}
+  \DeclareUnicodeCharacter{1E84}{\"W}
+  \DeclareUnicodeCharacter{1E85}{\"w}
+  \DeclareUnicodeCharacter{1E86}{\dotaccent{W}}
+  \DeclareUnicodeCharacter{1E87}{\dotaccent{w}}
+  \DeclareUnicodeCharacter{1E88}{\udotaccent{W}}
+  \DeclareUnicodeCharacter{1E89}{\udotaccent{w}}
+  \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}}
+  \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}}
+  \DeclareUnicodeCharacter{1E8C}{\"X}
+  \DeclareUnicodeCharacter{1E8D}{\"x}
+  \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}}
+  \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}}
+
+  \DeclareUnicodeCharacter{1E90}{\^Z}
+  \DeclareUnicodeCharacter{1E91}{\^z}
+  \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}}
+  \DeclareUnicodeCharacter{1E93}{\udotaccent{z}}
+  \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}}
+  \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}}
+  \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}}
+  \DeclareUnicodeCharacter{1E97}{\"t}
+  \DeclareUnicodeCharacter{1E98}{\ringaccent{w}}
+  \DeclareUnicodeCharacter{1E99}{\ringaccent{y}}
+
+  \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}}
+  \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}}
+
+  \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}}
+  \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}}
+  \DeclareUnicodeCharacter{1EBC}{\~E}
+  \DeclareUnicodeCharacter{1EBD}{\~e}
+
+  \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}}
+  \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}}
+  \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}}
+  \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}}
+
+  \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}}
+  \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}}
+
+  \DeclareUnicodeCharacter{1EF2}{\`Y}
+  \DeclareUnicodeCharacter{1EF3}{\`y}
+  \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}}
+
+  \DeclareUnicodeCharacter{1EF8}{\~Y}
+  \DeclareUnicodeCharacter{1EF9}{\~y}
+
+  \DeclareUnicodeCharacter{2013}{--}
+  \DeclareUnicodeCharacter{2014}{---}
+  \DeclareUnicodeCharacter{2018}{\quoteleft}
+  \DeclareUnicodeCharacter{2019}{\quoteright}
+  \DeclareUnicodeCharacter{201A}{\quotesinglbase}
+  \DeclareUnicodeCharacter{201C}{\quotedblleft}
+  \DeclareUnicodeCharacter{201D}{\quotedblright}
+  \DeclareUnicodeCharacter{201E}{\quotedblbase}
+  \DeclareUnicodeCharacter{2022}{\bullet}
+  \DeclareUnicodeCharacter{2026}{\dots}
+  \DeclareUnicodeCharacter{2039}{\guilsinglleft}
+  \DeclareUnicodeCharacter{203A}{\guilsinglright}
+  \DeclareUnicodeCharacter{20AC}{\euro}
+
+  \DeclareUnicodeCharacter{2192}{\expansion}
+  \DeclareUnicodeCharacter{21D2}{\result}
+
+  \DeclareUnicodeCharacter{2212}{\minus}
+  \DeclareUnicodeCharacter{2217}{\point}
+  \DeclareUnicodeCharacter{2261}{\equiv}
+}% end of \utfeightchardefs
+
+
+% US-ASCII character definitions.
+\def\asciichardefs{% nothing need be done
+   \relax
+}
+
+% Make non-ASCII characters printable again for compatibility with
+% existing Texinfo documents that may use them, even without declaring a
+% document encoding.
+%
+\setnonasciicharscatcode \other
+
+
+\message{formatting,}
+
 \newdimen\defaultparindent \defaultparindent = 15pt
 
 \chapheadingskip = 15pt plus 4pt minus 2pt
@@ -6661,10 +9671,10 @@
 % Prevent underfull vbox error messages.
 \vbadness = 10000
 
-% Don't be so finicky about underfull hboxes, either.
-\hbadness = 2000
+% Don't be very finicky about underfull hboxes, either.
+\hbadness = 6666
 
-% Following George Bush, just get rid of widows and orphans.
+% Following George Bush, get rid of widows and orphans.
 \widowpenalty=10000
 \clubpenalty=10000
 
@@ -6682,9 +9692,9 @@
   \fi
 }
 
-% Parameters in order: 1) textheight; 2) textwidth; 3) voffset;
-% 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8)
-% physical page width.
+% Parameters in order: 1) textheight; 2) textwidth;
+% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip;
+% 7) physical page height; 8) physical page width.
 %
 % We also call \setleading{\textleading}, so the caller should define
 % \textleading.  The caller should also set \parskip.
@@ -6711,6 +9721,10 @@
   \ifpdf
     \pdfpageheight #7\relax
     \pdfpagewidth #8\relax
+    % if we don't reset these, they will remain at "1 true in" of
+    % whatever layout pdftex was dumped with.
+    \pdfhorigin = 1 true in
+    \pdfvorigin = 1 true in
   \fi
   %
   \setleading{\textleading}
@@ -6725,19 +9739,19 @@
   \textleading = 13.2pt
   %
   % If page is nothing but text, make it come out even.
-  \internalpagesizes{46\baselineskip}{6in}%
+  \internalpagesizes{607.2pt}{6in}% that's 46 lines
                     {\voffset}{.25in}%
                     {\bindingoffset}{36pt}%
                     {11in}{8.5in}%
 }}
 
-% Use @smallbook to reset parameters for 7x9.5 (or so) format.
+% Use @smallbook to reset parameters for 7x9.25 trim size.
 \def\smallbook{{\globaldefs = 1
   \parskip = 2pt plus 1pt
   \textleading = 12pt
   %
   \internalpagesizes{7.5in}{5in}%
-                    {\voffset}{.25in}%
+                    {-.2in}{0in}%
                     {\bindingoffset}{16pt}%
                     {9.25in}{7in}%
   %
@@ -6748,6 +9762,24 @@
   \defbodyindent = .5cm
 }}
 
+% Use @smallerbook to reset parameters for 6x9 trim size.
+% (Just testing, parameters still in flux.)
+\def\smallerbook{{\globaldefs = 1
+  \parskip = 1.5pt plus 1pt
+  \textleading = 12pt
+  %
+  \internalpagesizes{7.4in}{4.8in}%
+                    {-.2in}{-.4in}%
+                    {0pt}{14pt}%
+                    {9in}{6in}%
+  %
+  \lispnarrowing = 0.25in
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = .4cm
+}}
+
 % Use @afourpaper to print on European A4 paper.
 \def\afourpaper{{\globaldefs = 1
   \parskip = 3pt plus 2pt minus 1pt
@@ -6763,7 +9795,7 @@
   % \global\normaloffset = -6mm
   % \global\bindingoffset = 10mm
   % @end tex
-  \internalpagesizes{51\baselineskip}{160mm}
+  \internalpagesizes{673.2pt}{160mm}% that's 51 lines
                     {\voffset}{\hoffset}%
                     {\bindingoffset}{44pt}%
                     {297mm}{210mm}%
@@ -6828,7 +9860,7 @@
   \parskip = 3pt plus 2pt minus 1pt
   \setleading{\textleading}%
   %
-  \dimen0 = #1
+  \dimen0 = #1\relax
   \advance\dimen0 by \voffset
   %
   \dimen2 = \hsize
@@ -6847,25 +9879,21 @@
 
 \message{and turning on texinfo input format.}
 
+\def^^L{\par} % remove \outer, so ^L can appear in an @comment
+
+% DEL is a comment character, in case @c does not suffice.
+\catcode`\^^? = 14
+
 % Define macros to output various characters with catcode for normal text.
-\catcode`\"=\other
-\catcode`\~=\other
-\catcode`\^=\other
-\catcode`\_=\other
-\catcode`\|=\other
-\catcode`\<=\other
-\catcode`\>=\other
-\catcode`\+=\other
-\catcode`\$=\other
-\def\normaldoublequote{"}
-\def\normaltilde{~}
-\def\normalcaret{^}
-\def\normalunderscore{_}
-\def\normalverticalbar{|}
-\def\normalless{<}
-\def\normalgreater{>}
-\def\normalplus{+}
-\def\normaldollar{$}%$ font-lock fix
+\catcode`\"=\other \def\normaldoublequote{"}
+\catcode`\$=\other \def\normaldollar{$}%$ font-lock fix
+\catcode`\+=\other \def\normalplus{+}
+\catcode`\<=\other \def\normalless{<}
+\catcode`\>=\other \def\normalgreater{>}
+\catcode`\^=\other \def\normalcaret{^}
+\catcode`\_=\other \def\normalunderscore{_}
+\catcode`\|=\other \def\normalverticalbar{|}
+\catcode`\~=\other \def\normaltilde{~}
 
 % 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,
@@ -6900,6 +9928,7 @@
 
 \catcode`\_=\active
 \def_{\ifusingtt\normalunderscore\_}
+\let\realunder=_
 % Subroutine for the previous macro.
 \def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }
 
@@ -6922,6 +9951,13 @@
 % \otherifyactive is called near the end of this file.
 \def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
 
+% Used sometimes to turn off (effectively) the active characters even after
+% parsing them.
+\def\turnoffactive{%
+  \normalturnoffactive
+  \otherbackslash
+}
+
 \catcode`\@=0
 
 % \backslashcurfont outputs one backslash character in current font,
@@ -6929,43 +9965,55 @@
 \global\chardef\backslashcurfont=`\\
 \global\let\rawbackslashxx=\backslashcurfont  % let existing .??s files work
 
-% \rawbackslash defines an active \ to do \backslashcurfont.
-% \otherbackslash defines an active \ to be a literal `\' character with
-% catcode other.
-{\catcode`\\=\active
- @gdef at rawbackslash{@let\=@backslashcurfont}
- @gdef at otherbackslash{@let\=@realbackslash}
-}
+% \realbackslash is an actual character `\' with catcode other, and
+% \doublebackslash is two of them (for the pdf outlines).
+{\catcode`\\=\other @gdef at realbackslash{\} @gdef at doublebackslash{\\}}
 
-% \realbackslash is an actual character `\' with catcode other.
-{\catcode`\\=\other @gdef at realbackslash{\}}
+% In texinfo, backslash is an active character; it prints the backslash
+% in fixed width font.
+\catcode`\\=\active  % @ for escape char from now on.
 
-% \normalbackslash outputs one backslash in fixed width font.
-\def\normalbackslash{{\tt\backslashcurfont}}
+% The story here is that in math mode, the \char of \backslashcurfont
+% ends up printing the roman \ from the math symbol font (because \char
+% in math mode uses the \mathcode, and plain.tex sets
+% \mathcode`\\="026E).  It seems better for @backslashchar{} to always
+% print a typewriter backslash, hence we use an explicit \mathchar,
+% which is the decimal equivalent of "715c (class 7, e.g., use \fam;
+% ignored family value; char position "5C).  We can't use " for the
+% usual hex value because it has already been made active.
+ at def@normalbackslash{{@tt @ifmmode @mathchar29020 @else @backslashcurfont @fi}}
+ at let@backslashchar = @normalbackslash % @backslashchar{} is for user documents.
 
-\catcode`\\=\active
+% On startup, @fixbackslash assigns:
+%  @let \ = @normalbackslash
+% \rawbackslash defines an active \ to do \backslashcurfont.
+% \otherbackslash defines an active \ to be a literal `\' character with
+% catcode other.  We switch back and forth between these.
+ at gdef@rawbackslash{@let\=@backslashcurfont}
+ at gdef@otherbackslash{@let\=@realbackslash}
 
-% Used sometimes to turn off (effectively) the active characters
-% even after parsing them.
- at 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.)
+% the literal character `\'.  Also revert - to its normal character, in
+% case the active - from code has slipped in.
 %
- at def@normalturnoffactive{@turnoffactive @let\=@normalbackslash}
+{@catcode`- = @active
+ @gdef at normalturnoffactive{%
+   @let-=@normaldash
+   @let"=@normaldoublequote
+   @let$=@normaldollar %$ font-lock fix
+   @let+=@normalplus
+   @let<=@normalless
+   @let>=@normalgreater
+   @let\=@normalbackslash
+   @let^=@normalcaret
+   @let_=@normalunderscore
+   @let|=@normalverticalbar
+   @let~=@normaltilde
+   @markupsetuplqdefault
+   @markupsetuprqdefault
+   @unsepspaces
+ }
+}
 
 % Make _ and + \other characters, temporarily.
 % This is canceled by @fixbackslash.
@@ -6979,9 +10027,9 @@
 @global at let\ = @eatinput
 
 % On the other hand, perhaps the file did not have a `\input texinfo'. Then
-% the first `\{ in the file would cause an error. This macro tries to fix
+% the first `\' in the file would cause an error. This macro tries to fix
 % that, assuming it is called before the first `\' could plausibly occur.
-% Also back turn on active characters that might appear in the input
+% Also turn back on active characters that might appear in the input
 % file name, in case not using a pre-dumped format.
 %
 @gdef at fixbackslash{%
@@ -6993,12 +10041,29 @@
 % Say @foo, not \foo, in error messages.
 @escapechar = `@@
 
+% These (along with & and #) are made active for url-breaking, so need
+% active definitions as the normal characters.
+ at def@normaldot{.}
+ at def@normalquest{?}
+ at def@normalslash{/}
+
 % These look ok in all fonts, so just make them not special.
- at catcode`@& = @other
- at catcode`@# = @other
- at catcode`@% = @other
+% @hashchar{} gets its own user-level command, because of #line.
+ at catcode`@& = @other @def at normalamp{&}
+ at catcode`@# = @other @def at normalhash{#}
+ at catcode`@% = @other @def at normalpercent{%}
 
+ at let @hashchar = @normalhash
 
+ at c Finally, make ` and ' active, so that txicodequoteundirected and
+ at c txicodequotebacktick work right in, e.g., @w{@code{`foo'}}.  If we
+ at c don't make ` and ' active, @code will not get them as active chars.
+ at c Do this last of all since we use ` in the previous @catcode assignments.
+ at catcode`@'=@active
+ at catcode`@`=@active
+ at markupsetuplqdefault
+ at markupsetuprqdefault
+
 @c Local variables:
 @c eval: (add-hook 'write-file-hooks 'time-stamp)
 @c page-delimiter: "^\\\\message"

Modified: trunk/contrib/amd/doc/version.texi
===================================================================
--- trunk/contrib/amd/doc/version.texi	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/doc/version.texi	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,4 +1,4 @@
- at set UPDATED 20 April 2006
- at set UPDATED-MONTH April 2006
- at set EDITION 6.1.5
- at set VERSION 6.1.5
+ at set UPDATED 28 October 2014
+ at set UPDATED-MONTH October 2014
+ at set EDITION 6.2
+ at set VERSION 6.2

Modified: trunk/contrib/amd/fixmount/fixmount.8
===================================================================
--- trunk/contrib/amd/fixmount/fixmount.8	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fixmount/fixmount.8	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
 .\" 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
+.\" 3. 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.
 .\"
@@ -36,10 +32,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: fixmount.8,v 1.1.1.4 2012-07-21 14:53:13 laffer1 Exp $
-.\" $FreeBSD$
+.\" File: am-utils/fixmount/fixmount.8
+.\" $FreeBSD: stable/10/contrib/amd/fixmount/fixmount.8 310490 2016-12-23 22:42:14Z cy $
 .\"
 .Dd January 2, 2006
 .Dt FIXMOUNT 8

Modified: trunk/contrib/amd/fixmount/fixmount.c
===================================================================
--- trunk/contrib/amd/fixmount/fixmount.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fixmount/fixmount.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -115,7 +111,7 @@
     } else if (!(he = gethostbyname(name1))) {
       return 0;
     } else {
-      xstrlcpy(lasthost, name1, MAXHOSTNAMELEN);
+      xstrlcpy(lasthost, name1, sizeof(lasthost));
       memcpy(&addr1, he->h_addr, sizeof(addr1));
       return (addr1.s_addr == addr2.s_addr);
     }
@@ -176,7 +172,7 @@
 			   (XDRPROC_T_TYPE) xdr_dirpath,
 			   (char *) &pathp,
 			   (XDRPROC_T_TYPE) xdr_void,
-			   (char *) 0,
+			   (char *) NULL,
 			   tv)) != RPC_SUCCESS) {
       fprintf(stderr, "%s:%s MOUNTPROC_UMNT: ",
 	      host, ml->ml_directory);
@@ -235,9 +231,9 @@
   if ((estat = clnt_call(client,
 			 MOUNTPROC_UMNTALL,
 			 (XDRPROC_T_TYPE) xdr_void,
-			 (char *) 0,
+			 (char *) NULL,
 			 (XDRPROC_T_TYPE) xdr_void,
-			 (char *) 0,
+			 (char *) NULL,
 			 tv)) != RPC_SUCCESS) {
     /*
      * RPC_SYSTEMERROR is returned even if all went well
@@ -389,7 +385,7 @@
       if ((estat = clnt_call(client,
 			     MOUNTPROC_DUMP,
 			     (XDRPROC_T_TYPE) xdr_void,
-			     (char *) 0,
+			     (char *) NULL,
 			     (XDRPROC_T_TYPE) xdr_mountlist,
 			     (char *) &mntdump,
 			     tv)) != RPC_SUCCESS) {
@@ -403,7 +399,7 @@
       if ((estat = clnt_call(client,
 			     MOUNTPROC_EXPORT,
 			     (XDRPROC_T_TYPE) xdr_void,
-			     (char *) 0,
+			     (char *) NULL,
 			     (XDRPROC_T_TYPE) xdr_exports,
 			     (char *) &mntexports,
 			     tv)) != RPC_SUCCESS) {

Modified: trunk/contrib/amd/fsinfo/fsi_analyze.c
===================================================================
--- trunk/contrib/amd/fsinfo/fsi_analyze.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/fsi_analyze.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -56,27 +52,27 @@
 
 char *disk_fs_strings[] =
 {
-  "fstype", "opts", "dumpset", "passno", "freq", "mount", "log", 0,
+  "fstype", "opts", "dumpset", "passno", "freq", "mount", "log", NULL,
 };
 
 char *mount_strings[] =
 {
-  "volname", "exportfs", 0,
+  "volname", "exportfs", NULL,
 };
 
 char *fsmount_strings[] =
 {
-  "as", "volname", "fstype", "opts", "from", 0,
+  "as", "volname", "fstype", "opts", "from", NULL,
 };
 
 char *host_strings[] =
 {
-  "host", "netif", "config", "arch", "cluster", "os", 0,
+  "host", "netif", "config", "arch", "cluster", "os", NULL,
 };
 
 char *ether_if_strings[] =
 {
-  "inaddr", "netmask", "hwaddr", 0,
+  "inaddr", "netmask", "hwaddr", NULL,
 };
 
 
@@ -122,7 +118,7 @@
   do {
     d = strrchr(p, '.');
     if (d) {
-      *d = 0;
+      *d = '\0';
       xstrlcat(path, d + 1, sizeof(path));
       xstrlcat(path, "/", sizeof(path));
     } else {
@@ -141,7 +137,7 @@
 find_volname(char *nn)
 {
   dict_ent *de;
-  char *p = strdup(nn);
+  char *p = xstrdup(nn);
   char *q;
 
   do {
@@ -186,7 +182,7 @@
 	lwarning(mp->m_ioloc, "%s has duplicate exportfs data", mp->m_name);
       mp->m_exported = mp;
       if (!ISSET(mp->m_mask, DM_VOLNAME))
-	set_mount(mp, DM_VOLNAME, strdup(mp->m_name));
+	set_mount(mp, DM_VOLNAME, xstrdup(mp->m_name));
     } else {
       mp->m_exported = e;
     }
@@ -228,7 +224,7 @@
 	lwarning(mp->m_ioloc, "sub-directory of %s is named \"default\"", parent->m_name);
       fsi_log("Changing name %s to %s", mp->m_name, n);
       XFREE(mp->m_name);
-      mp->m_name = strdup(n);
+      mp->m_name = xstrdup(n);
     }
 
     mp->m_name_len = strlen(mp->m_name);
@@ -251,7 +247,7 @@
 analyze_dkmounts(disk_fs *dk, qelem *q)
 {
   int errors = 0;
-  fsi_mount *mp, *mp2 = 0;
+  fsi_mount *mp, *mp2 = NULL;
   int i = 0;
 
   /*
@@ -286,7 +282,7 @@
       char nbuf[1024];
       compute_automount_point(nbuf, sizeof(nbuf), dk->d_host, mp2->m_volname);
       XFREE(mp2->m_name);
-      mp2->m_name = strdup(nbuf);
+      mp2->m_name = xstrdup(nbuf);
       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);
@@ -298,19 +294,19 @@
    * Fill in the disk mount point
    */
   if (!errors && mp2 && mp2->m_name)
-    dk->d_mountpt = strdup(mp2->m_name);
+    dk->d_mountpt = xstrdup(mp2->m_name);
   else
-    dk->d_mountpt = strdup("error");
+    dk->d_mountpt = xstrdup("error");
 
   /*
    * Analyze the mount tree
    */
-  errors += analyze_dkmount_tree(q, 0, dk);
+  errors += analyze_dkmount_tree(q, NULL, dk);
 
   /*
    * Analyze the export tree
    */
-  errors += check_exportfs(q, 0);
+  errors += check_exportfs(q, NULL);
 
   return errors;
 }
@@ -353,7 +349,7 @@
        * "opts"
        */
       if (!ISSET(dp->d_mask, DF_OPTS))
-	set_disk_fs(dp, DF_OPTS, strdup("swap"));
+	set_disk_fs(dp, DF_OPTS, xstrdup("swap"));
 
       /*
        * "mount"
@@ -362,7 +358,7 @@
 	qelem *q = new_que();
 	fsi_mount *m = new_mount();
 
-	m->m_name = strdup("swap");
+	m->m_name = xstrdup("swap");
 	m->m_mount = new_que();
 	ins_que(&m->m_q, q->q_back);
 	dp->d_mount = q;
@@ -400,7 +396,7 @@
        * "opts"
        */
       if (!ISSET(dp->d_mask, DF_OPTS))
-	set_disk_fs(dp, DF_OPTS, strdup("rw,defaults"));
+	set_disk_fs(dp, DF_OPTS, xstrdup("rw,defaults"));
 
     }
   }
@@ -415,7 +411,7 @@
       lerror(fp->f_ioloc, "ambiguous mount: %s is a replicated filesystem", fp->f_volname);
     } else {
       dict_data *dd;
-      fsi_mount *mp = 0;
+      fsi_mount *mp = NULL;
       dd = AM_FIRST(dict_data, &de->de_q);
       mp = (fsi_mount *) dd->dd_data;
       if (!mp)
@@ -427,18 +423,18 @@
   }
 
   if (!ISSET(fp->f_mask, FM_FSTYPE)) {
-    set_fsmount(fp, FM_FSTYPE, strdup("nfs"));
+    set_fsmount(fp, FM_FSTYPE, xstrdup("nfs"));
     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"));
+    set_fsmount(fp, FM_OPTS, xstrdup("rw,nosuid,grpid,defaults"));
     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));
+      set_fsmount(fp, FM_LOCALNAME, xstrdup(fp->f_volname));
       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);
@@ -485,7 +481,7 @@
 
   ITER(fp, fsmount, q) {
     char *p;
-    char *nn = strdup(fp->f_volname);
+    char *nn = xstrdup(fp->f_volname);
     int req;
     dict_ent *de = (dict_ent *) NULL;
     int found = 0;
@@ -496,7 +492,7 @@
       matched = 1;
     } else
       do {
-	p = 0;
+	p = NULL;
 	de = find_volname(nn);
 	fsi_log("Mount: %s (trying %s)", fp->f_volname, nn);
 
@@ -511,7 +507,7 @@
 	   */
 	  if (ISSET(fp->f_mask, FM_FROM) && !ISSET(fp->f_mask, FM_DIRECT)) {
 	    dict_data *dd;
-	    fsi_mount *mp2 = 0;
+	    fsi_mount *mp2 = NULL;
 
 	    ITER(dd, dict_data, &de->de_q) {
 	      fsi_mount *mp = (fsi_mount *) dd->dd_data;
@@ -535,7 +531,7 @@
 	}
 	p = strrchr(nn, '/');
 	if (p)
-	  *p = 0;
+	  *p = '\0';
       } while (de && p);
     XFREE(nn);
 
@@ -635,7 +631,7 @@
 	lerror(ap->a_ioloc, "not allowed '/' in a directory name");
     xsnprintf(nname, sizeof(nname), "%s/%s", pref, ap->a_name);
     XFREE(ap->a_name);
-    ap->a_name = strdup(nname[1] == '/' ? nname + 1 : nname);
+    ap->a_name = xstrdup(nname[1] == '/' ? nname + 1 : nname);
     fsi_log("automount point %s:", ap->a_name);
     show_new("ana-automount");
 
@@ -649,7 +645,7 @@
     } else if (ap->a_symlink) {
       fsi_log("\tsymlink to %s", ap->a_symlink);
     } else {
-      ap->a_volname = strdup(ap->a_name);
+      ap->a_volname = xstrdup(ap->a_name);
       fsi_log("\timplicit automount from %s", ap->a_volname);
       analyze_automount(ap);
     }

Modified: trunk/contrib/amd/fsinfo/fsi_data.h
===================================================================
--- trunk/contrib/amd/fsinfo/fsi_data.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/fsi_data.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/fsinfo/fsi_dict.c
===================================================================
--- trunk/contrib/amd/fsinfo/fsi_dict.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/fsi_dict.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/fsinfo/fsi_gram.y
===================================================================
--- trunk/contrib/amd/fsinfo/fsi_gram.y	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/fsi_gram.y	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -200,7 +196,7 @@
 
 opt_auto_opts :
 	  /* empty */
-	  { $$ = strdup(""); }
+	  { $$ = xstrdup(""); }
 
 	| tOPTS tSTR
 	  { $$ = $2; }
@@ -233,7 +229,7 @@
 	  { $4->d_dev = $2; $$ = $4; }
 
 	| tFS error '}'
-	  { $$ = (disk_fs *) 0; }
+	  { $$ = (disk_fs *) NULL; }
 	;
 
 /*

Modified: trunk/contrib/amd/fsinfo/fsi_lex.l
===================================================================
--- trunk/contrib/amd/fsinfo/fsi_lex.l	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/fsi_lex.l	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,6 +1,6 @@
 %{
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -17,11 +17,7 @@
  * 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
+ * 3. 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.
  *
@@ -102,7 +98,7 @@
  */
 #ifdef FLEX_SCANNER
 # ifndef ECHO
-#  define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#  define ECHO __IGNORE(fwrite( yytext, yyleng, 1, yyout ))
 # endif /* not ECHO */
 #endif /* FLEX_SCANNER */
 
@@ -111,10 +107,12 @@
  * which automatically generates yywrap macros and symbols.  So I must
  * distinguish between them and when yywrap is actually needed.
  */
-#ifndef yywrap
+#if !defined(yywrap) || defined(yylex)
 int yywrap(void);
-#endif /* not yywrap */
+#endif /* not yywrap or yylex */
 
+int fsi_error(const char *, ...);
+
 YYSTYPE yylval;
 static char *fsi_filename;
 static char *optr;
@@ -153,7 +151,7 @@
   { "passno", tPASSNO },
   { "sel", tSEL },
   { "volname", tVOLNAME },
-  { 0, 0 },
+  { NULL, 0 },
 };
 #define	NRES_WORDS (sizeof(rr)/sizeof(rr[0])-1)
 
@@ -162,6 +160,7 @@
 /* This option causes Solaris lex to fail.  Use flex.  See BUGS file */
 /* no need to use yyunput() */
 %option nounput
+%option noinput
 
 /* allocate more output slots so lex scanners don't run out of mem */
 %o 1024
@@ -177,7 +176,7 @@
 <F>[={}]		{ return *yytext; }
 
 <F>\"			{ BEGIN Q; optr = ostr; quoted = 1; }
-<Q>\n			{ ayylineno++; yyerror("\" expected"); BEGIN F; }
+<Q>\n			{ ayylineno++; fsi_error("\" expected"); BEGIN F; }
 <Q>\\b			{ *optr++ = '\b'; /* escape */ }
 <Q>\\t			{ *optr++ = '\t'; /* escape */ }
 <Q>\\\"			{ *optr++ = '\"'; /* escape */ }
@@ -187,11 +186,11 @@
 <Q>\\n			{ *optr++ = '\n'; /* escape */ }
 <Q>\\f			{ *optr++ = '\f'; /* escape */ }
 <Q>"\\ "		{ *optr++ = ' '; /* force space */ }
-<Q>\\.			{ yyerror("Unknown \\ sequence"); }
+<Q>\\.			{ fsi_error("Unknown \\ sequence"); }
 <Q>([ \t]|"\\\n"){2,}	{ char *p = (char *) yytext-1; while ((p = strchr(p+1, '\n'))) ayylineno++; }
 <Q>\"			{ BEGIN F; quoted = 0;
 				*optr = '\0';
-				yylval.s = strdup(ostr);
+				yylval.s = xstrdup(ostr);
 				return tSTR;
 			}
 <Q>.			{ *optr++ = *yytext; }
@@ -224,11 +223,11 @@
   switch (tok) {
   case tLOCALHOST:
     s = "${host}";
-    /* fall through... */
+    /*FALLTHROUGH*/
   case 0:
-    yylval.s = strdup(s);
+    yylval.s = xstrdup(s);
     tok = tSTR;
-    /* fall through... */
+    /*FALLTHROUGH*/
   default:
     return tok;
   }
@@ -236,7 +235,7 @@
 
 
 int
-yyerror(char *fmt, ...)
+fsi_error(const char *fmt, ...)
 {
   va_list ap;
 
@@ -266,9 +265,9 @@
  * which automatically generates yywrap macros and symbols.  So I must
  * distinguish between them and when yywrap is actually needed.
  */
-#ifndef yywrap
+#if !defined(yywrap) || defined(yylex)
 int yywrap(void)
 {
   return 1;
 }
-#endif /* not yywrap */
+#endif /* not yywrap or yylex */

Modified: trunk/contrib/amd/fsinfo/fsi_util.c
===================================================================
--- trunk/contrib/amd/fsinfo/fsi_util.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/fsi_util.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -13,11 +13,7 @@
  * 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
+ * 3. 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.
  *
@@ -201,7 +197,7 @@
 static void
 make_banner(FILE *fp)
 {
-  time_t t = time((time_t *) 0);
+  time_t t = time((time_t *) NULL);
   char *cp = ctime(&t);
 
   fprintf(fp,
@@ -235,7 +231,7 @@
 void
 show_area_being_processed(char *area, int n)
 {
-  static char *last_area = 0;
+  static char *last_area = NULL;
 
   if (verbose < 0)
     return;
@@ -316,9 +312,9 @@
 
   ap->a_ioloc = current_location();
   ap->a_name = name;
-  ap->a_volname = 0;
-  ap->a_mount = 0;
-  ap->a_opts = 0;
+  ap->a_volname = NULL;
+  ap->a_mount = NULL;
+  ap->a_opts = NULL;
   show_new("automount");
   return ap;
 }
@@ -355,7 +351,7 @@
   int m = 1 << k;
 
   if (hp->h_mask & m) {
-    yyerror("host field \"%s\" already set", host_strings[k]);
+    fsi_error("host field \"%s\" already set", host_strings[k]);
     return;
   }
   hp->h_mask |= m;
@@ -363,11 +359,11 @@
   switch (k) {
 
   case HF_HOST:{
-      char *p = strdup(v);
+      char *p = xstrdup(v);
       dict_ent *de = dict_locate(dict_of_hosts, v);
 
       if (de)
-	yyerror("duplicate host %s!", v);
+	fsi_error("duplicate host %s!", v);
       else
 	dict_add(dict_of_hosts, v, (char *) hp);
       hp->h_hostname = v;
@@ -442,7 +438,7 @@
   int m = 1 << k;
 
   if (ep->e_mask & m) {
-    yyerror("netif field \"%s\" already set", ether_if_strings[k]);
+    fsi_error("netif field \"%s\" already set", ether_if_strings[k]);
     return;
   }
   ep->e_mask |= m;
@@ -452,7 +448,7 @@
   case EF_INADDR:{
       ep->e_inaddr.s_addr = inet_addr(v);
       if ((int) ep->e_inaddr.s_addr == (int) INADDR_NONE)
-	yyerror("malformed IP dotted quad: %s", v);
+	fsi_error("malformed IP dotted quad: %s", v);
       XFREE(v);
     }
     break;
@@ -463,7 +459,7 @@
       if ((sscanf(v, "0x%lx", &nm) == 1 || sscanf(v, "%lx", &nm) == 1) && nm != 0)
 	ep->e_netmask = htonl(nm);
       else
-	yyerror("malformed netmask: %s", v);
+	fsi_error("malformed netmask: %s", v);
       XFREE(v);
     }
     break;
@@ -485,7 +481,7 @@
   int m = 1 << k;
 
   if (dp->d_mask & m) {
-    yyerror("fs field \"%s\" already set", disk_fs_strings[k]);
+    fsi_error("fs field \"%s\" already set", disk_fs_strings[k]);
     return;
   }
   dp->d_mask |= m;
@@ -546,7 +542,7 @@
   int m = 1 << k;
 
   if (mp->m_mask & m) {
-    yyerror("mount tree field \"%s\" already set", mount_strings[k]);
+    fsi_error("mount tree field \"%s\" already set", mount_strings[k]);
     return;
   }
   mp->m_mask |= m;
@@ -590,7 +586,7 @@
   int m = 1 << k;
 
   if (fp->f_mask & m) {
-    yyerror("mount field \"%s\" already set", fsmount_strings[k]);
+    fsi_error("mount field \"%s\" already set", fsmount_strings[k]);
     return;
   }
   fp->f_mask |= m;

Modified: trunk/contrib/amd/fsinfo/fsinfo.8
===================================================================
--- trunk/contrib/amd/fsinfo/fsinfo.8	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/fsinfo.8	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 Erez Zadok
 .\" Copyright (c) 1993 Jan-Simon Pendry.
 .\" Copyright (c) 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -12,11 +12,7 @@
 .\" 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
+.\" 3. 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.
 .\"
@@ -32,34 +28,42 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"     from: @(#)fsinfo.8	8.1 (Berkeley) 6/28/93
-.\"	$Id: fsinfo.8,v 1.1.1.3 2012-07-21 14:53:13 laffer1 Exp $
-.\"	$FreeBSD$
+.\"	$FreeBSD: stable/10/contrib/amd/fsinfo/fsinfo.8 310490 2016-12-23 22:42:14Z cy $
 .\"
-.Dd January 2, 2006
-.Dt FSINFO 8
-.Os
+.\" File: am-utils/fsinfo/fsinfo.8
+.\"
+.Dd August 31, 2016
 .Sh NAME
 .Nm fsinfo
 .Nd co-ordinate site-wide file system information
 .Sh SYNOPSIS
 .Nm
-.Op Fl qv
+.Op fl qv
 .Op Fl a Ar autodir
-.Op Fl b Ar bootparams_prefix
-.Op Fl d Ar dumpsets_prefix
-.Op Fl e Ar exports_prefix
-.Op Fl f Ar fstabs_prefix
+.Op Fl b Ar bootparams
+.Op Fl d Ar dumpsets
+.Op Fl e Ar exports
+.Op Fl f Ar fstabs
 .Op Fl h Ar hostname
-.Op Fl m Ar automounts_prefix
+.Op Fl m Ar automounts
 .Op Fl I Ar dir
 .Oo
 .Fl D
 .Ar name Ns Op = Ns Ar string
 .Oc
-.Op Fl U Ar name
+.Oo
+.Fl U
+.Ar name Ns Op = Ns Ar string
+.Oc
 .Ar config ...
 .Sh DESCRIPTION
+.Bf -symbolic
+This command is obsolete.
+Users are advised to use
+.Xr autofs 5
+instead.
+.Ef
+.Pp
 The
 .Nm
 utility takes a set of system configuration information, and generates

Modified: trunk/contrib/amd/fsinfo/fsinfo.c
===================================================================
--- trunk/contrib/amd/fsinfo/fsinfo.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/fsinfo.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -213,7 +209,7 @@
   if (!u)
     u = "root";
 
-  return strdup(u);
+  return xstrdup(u);
 }
 
 
@@ -258,7 +254,7 @@
    * Parse input
    */
   show_area_being_processed("read config", 11);
-  if (yyparse())
+  if (fsi_parse())
     errors = 1;
   errors += file_io_errors + parse_errors;
 

Modified: trunk/contrib/amd/fsinfo/fsinfo.h
===================================================================
--- trunk/contrib/amd/fsinfo/fsinfo.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/fsinfo.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -104,7 +100,7 @@
 extern void show_new(char *msg);
 extern void warning(void);
 
-extern int yyerror(char *fmt, ...)
+extern int fsi_error(const char *fmt, ...)
 	__attribute__((__format__(__printf__, 1, 2)));
 extern void domain_strip(char *otherdom, char *localdom);
 /*
@@ -115,7 +111,7 @@
 #ifndef yywrap
 extern int yywrap(void);
 #endif /* not yywrap */
-extern int yyparse(void);
+extern int fsi_parse(void);
 extern int write_atab(qelem *q);
 extern int write_bootparams(qelem *q);
 extern int write_dumpset(qelem *q);
@@ -124,7 +120,7 @@
 extern void col_cleanup(int eoj);
 extern void set_host(host *hp, int k, char *v);
 extern void set_ether_if(ether_if *ep, int k, char *v);
-extern int yylex(void);
+extern int fsi_lex(void);
 
 
 #define	BITSET(m,b)	((m) |= (1<<(b)))

Modified: trunk/contrib/amd/fsinfo/wr_atab.c
===================================================================
--- trunk/contrib/amd/fsinfo/wr_atab.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/wr_atab.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/fsinfo/wr_bparam.c
===================================================================
--- trunk/contrib/amd/fsinfo/wr_bparam.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/wr_bparam.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -56,7 +52,7 @@
 write_nfsname(FILE *ef, fsmount *fp, char *hn)
 {
   int errors = 0;
-  char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+  char *h = xstrdup(fp->f_ref->m_dk->d_host->h_hostname);
 
  domain_strip(h, hn);
   fprintf(ef, "%s:%s", h, fp->f_volname);

Modified: trunk/contrib/amd/fsinfo/wr_dumpset.c
===================================================================
--- trunk/contrib/amd/fsinfo/wr_dumpset.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/wr_dumpset.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/fsinfo/wr_exportfs.c
===================================================================
--- trunk/contrib/amd/fsinfo/wr_exportfs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/wr_exportfs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/fsinfo/wr_fstab.c
===================================================================
--- trunk/contrib/amd/fsinfo/wr_fstab.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/fsinfo/wr_fstab.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -89,7 +85,7 @@
     "u4_0", write_ultrix_dkfstab, write_ultrix_dkrmount
   },				/* Ultrix */
   {
-    0, 0, 0
+    NULL, NULL, NULL
   }
 };
 
@@ -102,7 +98,7 @@
 static void
 write_aix1_dkfstab(FILE *ef, disk_fs *dp)
 {
-  char *hp = strdup(dp->d_host->h_hostname);
+  char *hp = xstrdup(dp->d_host->h_hostname);
   char *p = strchr(hp, '.');
 
   if (p)
@@ -123,8 +119,8 @@
 static void
 write_aix1_dkrmount(FILE *ef, char *hn, fsmount *fp)
 {
-  char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
-  char *hp = strdup(h);
+  char *h = xstrdup(fp->f_ref->m_dk->d_host->h_hostname);
+  char *hp = xstrdup(h);
   char *p = strchr(hp, '.');
 
   if (p)
@@ -172,7 +168,7 @@
 static void
 write_aix3_dkrmount(FILE *ef, char *hn, fsmount *fp)
 {
-  char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+  char *h = xstrdup(fp->f_ref->m_dk->d_host->h_hostname);
 
   domain_strip(h, hn);
   fprintf(ef, "\n%s:\n\tdev = %s:%s\n\tvfs = %s\n\ttype = %s\n\tvol = %s\n\topts = %s\n\tmount = true\n\tcheck = true\n\tfree = false\n",
@@ -206,7 +202,7 @@
 static void
 write_ultrix_dkrmount(FILE *ef, char *hn, fsmount *fp)
 {
-  char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+  char *h = xstrdup(fp->f_ref->m_dk->d_host->h_hostname);
 
   domain_strip(h, hn);
   fprintf(ef, "%s@%s:%s:%s:%s:0:0\n",
@@ -243,9 +239,9 @@
   char *h;
 
   if (fp->f_ref) {
-    h = strdup(fp->f_ref->m_dk->d_host->h_hostname);
+    h = xstrdup(fp->f_ref->m_dk->d_host->h_hostname);
   } else {
-    h = strdup(fp->f_from);
+    h = xstrdup(fp->f_from);
   }
   domain_strip(h, hn);
   fprintf(ef, "%s:%s %s %s %s 0 0\n",
@@ -261,8 +257,8 @@
 static struct os_fstab_type *
 find_fstab_type(host *hp)
 {
-  struct os_fstab_type *op = 0;
-  char *os_name = 0;
+  struct os_fstab_type *op = NULL;
+  char *os_name = NULL;
 
 again:;
   if (os_name == 0) {

Modified: trunk/contrib/amd/hlfsd/hlfsd.8
===================================================================
--- trunk/contrib/amd/hlfsd/hlfsd.8	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/hlfsd/hlfsd.8	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
 .\" 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
+.\" 3. 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.
 .\"
@@ -36,9 +32,10 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $Id: hlfsd.8,v 1.1.1.3 2012-07-21 14:53:13 laffer1 Exp $
-.\" $FreeBSD$
+.\" $FreeBSD: stable/10/contrib/amd/hlfsd/hlfsd.8 310490 2016-12-23 22:42:14Z cy $
 .\"
+.\" File: am-utils/hlfsd/hlfsd.8
+.\"
 .\" HLFSD was written at Columbia University Computer Science Department, by
 .\" Erez Zadok <ezk at cs.columbia.edu> and Alexander Dupuy <dupuy at smarts.com>
 .\" It is distributed under the same terms and conditions as AMD.
@@ -330,14 +327,16 @@
 points if it is unable to verify the that
 user's home directory is accessible.
 .El
-.Sh SEE ALSO
-.Xr mail 1 ,
+.SH "SEE ALSO"
+.Xr mail1 ,
 .Xr getgrent 3 ,
 .Xr getpwent 3 ,
+.Xr mnttab 4 ,
+.Xr passwd 4 ,
 .Xr mtab 5 ,
-.Xr passwd 5 ,
 .Xr amd 8 ,
-.Xr cron 8 ,
+.Xr automount 8 ,
+.Xr cron8 ,
 .Xr mount 8 ,
 .Xr sendmail 8 ,
 .Xr umount 8

Modified: trunk/contrib/amd/hlfsd/hlfsd.c
===================================================================
--- trunk/contrib/amd/hlfsd/hlfsd.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/hlfsd/hlfsd.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -82,7 +78,7 @@
 char *home_subdir = HOME_SUBDIR;
 char *logfile = DEFAULT_LOGFILE;
 char *passwdfile = NULL;	/* alternate passwd file to use */
-char *slinkname = 0;
+char *slinkname = NULL;
 char hostname[MAXHOSTNAMELEN + 1] = "localhost";
 u_int cache_interval = DEFAULT_CACHE_INTERVAL;
 gid_t hlfs_gid = (gid_t) INVALIDID;
@@ -102,6 +98,7 @@
 
 /* forward declarations */
 void hlfsd_going_down(int rc);
+void fatalerror(char *str);
 
 
 static void
@@ -260,9 +257,6 @@
       opterrs++;
     }
 
-  /* set some default debugging options */
-  if (xlog_level_init == ~0)
-    switch_option("");
   /* need my pid before any dlog/plog */
   am_set_mypid();
 #ifdef DEBUG
@@ -312,7 +306,11 @@
   }
 
   /* get hostname for logging and open log before we reset umask */
-  gethostname(hostname, sizeof(hostname));
+  if (gethostname(hostname, sizeof(hostname)) == -1) {
+    fprintf(stderr, "%s: gethostname failed \"%s\".\n",
+	    am_get_progname(), strerror(errno));
+    exit(1);
+  }
   hostname[sizeof(hostname) - 1] = '\0';
   if ((dot = strchr(hostname, '.')) != NULL)
     *dot = '\0';
@@ -418,11 +416,8 @@
   /*
    * Register hlfsd as an nfs service with the portmapper.
    */
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-  ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
-#else /* not HAVE_TRANSPORT_TYPE_TLI */
-  ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
-#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+  ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2,
+    NFS_VERSION);
   if (ret != 0)
     fatal("cannot create NFS service");
 
@@ -450,10 +445,10 @@
 #endif /* not HAVE_SIGACTION */
 
   /*
-   * In the parent, if -D daemon, we don't need to
+   * In the parent, if -D nodaemon, we don't need to
    * set this signal handler.
    */
-  if (!amuDebug(D_DAEMON)) {
+  if (amuDebug(D_DAEMON)) {
     s = -99;
     while (stoplight != SIGUSR2) {
       plog(XLOG_INFO, "parent waits for child to setup (stoplight=%d)", stoplight);
@@ -628,10 +623,10 @@
 
   plog(XLOG_INFO, "hlfsd ready to serve");
   /*
-   * If asked not to fork a daemon (-D daemon), then hlfsd_init()
+   * If asked not to fork a daemon (-D nodaemon), then hlfsd_init()
    * will not run svc_run.  We must start svc_run here.
    */
-  if (amuDebug(D_DAEMON)) {
+  if (!amuDebug(D_DAEMON)) {
     plog(XLOG_DEBUG, "starting no-daemon debugging svc_run");
     svc_run();
   }
@@ -656,9 +651,9 @@
   hlfsd_init_filehandles();
 
   /*
-   * If not -D daemon then we must fork.
+   * If -D daemon then we must fork.
    */
-  if (!amuDebug(D_DAEMON))
+  if (amuDebug(D_DAEMON))
     child = fork();
 
   if (child < 0)
@@ -745,17 +740,17 @@
 # endif /* not defined(DEBUG) || defined(DEBUG_PRINT) */
 #endif /* not HAVE_SIGACTION */
 
-  if (setitimer(ITIMER_REAL, &reloadinterval, (struct itimerval *) 0) < 0)
+  if (setitimer(ITIMER_REAL, &reloadinterval, (struct itimerval *) NULL) < 0)
     fatal("setitimer: %m");
 
   clocktime(&startup);
 
   /*
-   * If not -D daemon, then start serving here in the child,
-   * and the parent will exit.  But if -D daemon, then
+   * If -D daemon, then start serving here in the child,
+   * and the parent will exit.  But if -D nodaemon, then
    * skip this code and make sure svc_run is entered elsewhere.
    */
-  if (!amuDebug(D_DAEMON)) {
+  if (amuDebug(D_DAEMON)) {
     /*
      * Dissociate from the controlling terminal
      */
@@ -839,7 +834,7 @@
   struct stat stbuf;
   int umount_result;
 
-  if (!amuDebug(D_DAEMON)) {
+  if (amuDebug(D_DAEMON)) {
     if (getpid() != masterpid)
       return;
 
@@ -865,7 +860,7 @@
     break;
   }
 
-  if (!amuDebug(D_DAEMON)) {
+  if (amuDebug(D_DAEMON)) {
     plog(XLOG_INFO, "cleanup(): killing processes and terminating");
     kill(masterpid, SIGKILL);
     kill(serverpid, SIGKILL);

Modified: trunk/contrib/amd/hlfsd/hlfsd.h
===================================================================
--- trunk/contrib/amd/hlfsd/hlfsd.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/hlfsd/hlfsd.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/hlfsd/homedir.c
===================================================================
--- trunk/contrib/amd/hlfsd/homedir.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/hlfsd/homedir.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -133,9 +129,10 @@
   }
 
   /*
-   * only run this forking code if did not ask for -D fork
+   * Only run this forking code if ask for -D fork (default).
+   * Disable forking using -D nofork.
    */
-  if (!amuDebug(D_FORK)) {
+  if (amuDebug(D_FORK)) {
     /* fork child to process request if none in progress */
     if (found->child && kill(found->child, 0))
       found->child = 0;
@@ -265,13 +262,14 @@
 {
   struct timeval tv;
 
-  dlog("delaying on child %ld for %d seconds", (long) found->child, secs);
+  if (found)
+    dlog("delaying on child %ld for %d seconds", (long) found->child, secs);
 
   tv.tv_usec = 0;
 
   do {
     tv.tv_sec = secs;
-    if (select(0, 0, 0, 0, &tv) == 0)
+    if (select(0, NULL, NULL, NULL, &tv) == 0)
       break;
   } while (--secs && found->child);
 }
@@ -292,7 +290,7 @@
 #ifdef HAVE_WAITPID
   while ((child = waitpid((pid_t) -1, &status, WNOHANG)) > 0) {
 #else /* not HAVE_WAITPID */
-  while ((child = wait3(&status, WNOHANG, (struct rusage *) 0)) > 0) {
+  while ((child = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0) {
 #endif /* not HAVE_WAITPID */
 
     /* high chances this was the last child forked */
@@ -494,7 +492,7 @@
   buf[0] = '\0';
   fgets(buf, 256, passwd_fp);
   passwd_line++;
-  if (!buf || buf[0] == '\0')
+  if (buf[0] == '\0')
     goto readent;
 
   /* read user name */
@@ -559,7 +557,7 @@
       int len;
       if (root_home)
 	XFREE(root_home);
-      root_home = strdup(pent_p->pw_dir);
+      root_home = xstrdup(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] == '/') {
@@ -576,7 +574,7 @@
 	unt_compare_fxn);
 
   if (!root_home)
-    root_home = strdup("");
+    root_home = xstrdup("");
 
   plog(XLOG_INFO, "password map read and sorted");
 }
@@ -671,7 +669,7 @@
     }
 
   /* add new password entry */
-  pwtab[cur_pwtab_num].home = strdup(h);
+  pwtab[cur_pwtab_num].home = xstrdup(h);
   pwtab[cur_pwtab_num].child = 0;
   pwtab[cur_pwtab_num].last_access_time = 0;
   pwtab[cur_pwtab_num].last_status = 0;	/* assume best: used homedir */
@@ -678,7 +676,7 @@
   pwtab[cur_pwtab_num].uid = u;
 
   /* add new userhome entry */
-  untab[cur_pwtab_num].username = strdup(n);
+  untab[cur_pwtab_num].username = xstrdup(n);
 
   /* just a second pointer */
   pwtab[cur_pwtab_num].uname = untab[cur_pwtab_num].username;

Modified: trunk/contrib/amd/hlfsd/nfs_prot_svc.c
===================================================================
--- trunk/contrib/amd/hlfsd/nfs_prot_svc.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/hlfsd/nfs_prot_svc.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/hlfsd/stubs.c
===================================================================
--- trunk/contrib/amd/hlfsd/stubs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/hlfsd/stubs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -137,7 +133,7 @@
       clocktime(&rootfattr.na_mtime);
       rootfattr.na_uid = uid;
     }
-#endif
+#endif /* 0 */
     res.ns_status = NFS_OK;
     res.ns_u.ns_attr_u = rootfattr;
   } else if (eq_fh(argp, &slink)) {
@@ -241,7 +237,7 @@
 	clocktime(&rootfattr.na_mtime);
 	rootfattr.na_uid = uid;
       }
-#endif
+#endif /* 0 */
       res.dr_u.dr_drok_u.drok_fhandle = root;
       res.dr_u.dr_drok_u.drok_attributes = rootfattr;
       res.dr_status = NFS_OK;
@@ -307,7 +303,7 @@
   uid_t userid = (uid_t) INVALIDID;
   gid_t groupid = hlfs_gid + 1;	/* anything not hlfs_gid */
   int retval = 0;
-  char *path_val = (char *) NULL;
+  char *path_val = NULL;
   char *username;
   static uid_t last_uid = (uid_t) INVALIDID;
 
@@ -328,7 +324,7 @@
        * processing, by getting a NULL returned as a
        * "special".  Child returns result.
        */
-      return (nfsreadlinkres *) NULL;
+      return NULL;
     }
 
   } else {			/* check if asked for user mailbox */
@@ -375,14 +371,15 @@
     retval = 0;
 
   /*
-   * If asked for -D fork, then must return the value,
+   * If asked for -D nofork, then must return the value,
    * NOT exit, or else the main hlfsd server exits.
+   * If -D fork (default), then we do want to exit from the process.
    * Bug: where is that status information being collected?
    */
   if (amuDebug(D_FORK))
+    exit(retval);
+  else
     return &res;
-
-  exit(retval);
 }
 
 
@@ -480,7 +477,7 @@
 nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
 {
   static nfsreaddirres res;
-  static nfsentry slinkent = {SLINKID, 0, {SLINKCOOKIE}};
+  static nfsentry slinkent = {SLINKID, NULL, {SLINKCOOKIE}};
   static nfsentry dotdotent = {ROOTID, "..", {DOTDOTCOOKIE}, &slinkent};
   static nfsentry dotent = {ROOTID, ".", {DOTCOOKIE}, &dotdotent};
 
@@ -503,7 +500,7 @@
       res.rdr_u.rdr_reply_u.dl_entries = &slinkent;
       break;
     case SLINKCOOKIE:
-      res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) 0;
+      res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) NULL;
       break;
     }
     res.rdr_u.rdr_reply_u.dl_eof = TRUE;

Modified: trunk/contrib/amd/include/am_compat.h
===================================================================
--- trunk/contrib/amd/include/am_compat.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/include/am_compat.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -90,6 +86,10 @@
 # define MNTTAB_OPT_NOAC "noac"
 #endif /* defined(MNT2_NFS_OPT_NOAC) && !defined(MNTTAB_OPT_NOAC) */
 
+#if defined(MNT2_NFS_OPT_NOACL) && !defined(MNTTAB_OPT_NOACL)
+# define MNTTAB_OPT_NOACL "noacl"
+#endif /* defined(MNT2_NFS_OPT_NOACL) && !defined(MNTTAB_OPT_NOACL) */
+
 #if defined(MNT2_NFS_OPT_NOCONN) && !defined(MNTTAB_OPT_NOCONN)
 # define MNTTAB_OPT_NOCONN "noconn"
 # ifndef MNTTAB_OPT_CONN
@@ -176,11 +176,31 @@
 #if defined(MNT2_CDFS_OPT_GENS) && !defined(MNTTAB_OPT_GENS)
 # define MNTTAB_OPT_GENS "gens"
 #endif /* defined(MNT2_CDFS_OPT_GENS) && !defined(MNTTAB_OPT_GENS) */
+
 #if defined(MNT2_CDFS_OPT_EXTATT) && !defined(MNTTAB_OPT_EXTATT)
 # define MNTTAB_OPT_EXTATT "extatt"
 #endif /* defined(MNT2_CDFS_OPT_EXTATT) && !defined(MNTTAB_OPT_EXTATT) */
 
+#if defined(MNT2_CDFS_OPT_NOJOLIET) && !defined(MNTTAB_OPT_NOJOLIET)
+# define MNTTAB_OPT_NOJOLIET "nojoliet"
+#endif /* defined(MNT2_CDFS_OPT_NOJOLIET) && !defined(MNTTAB_OPT_NOJOLIET) */
+
+#if defined(MNT2_CDFS_OPT_NOCASETRANS) && !defined(MNTTAB_OPT_NOCASETRANS)
+# define MNTTAB_OPT_NOCASETRANS "nocasetrans"
+#endif /* defined(MNT2_CDFS_OPT_NOCASETRANS) && !defined(MNTTAB_OPT_NOCASETRANS) */
+
+#if defined(MNT2_CDFS_OPT_RRCASEINS) && !defined(MNTTAB_OPT_RRCASEINS)
+# define MNTTAB_OPT_RRCASEINS "rrcaseins"
+#endif /* defined(MNT2_CDFS_OPT_RRCASEINS) && !defined(MNTTAB_OPT_RRCASEINS) */
+
 /*
+ * Complete MNTTAB_OPT_* options based on MNT2_UDF_OPT_* mount options.
+ */
+#if defined(MNT2_UDF_OPT_CLOSESESSION) && !defined(MNTTAB_OPT_CLOSESESSION)
+# define MNTTAB_OPT_CLOSESESSION "closesession"
+#endif /* defined(MNT2_UDF_OPT_CLOSESESSION) && !defined(MNTTAB_OPT_CLOSESESSION) */
+
+/*
  * Complete MNTTAB_OPT_* options based on MNT2_PCFS_OPT_* mount options.
  */
 #if defined(MNT2_PCFS_OPT_LONGNAME) && !defined(MNTTAB_OPT_LONGNAME)
@@ -236,7 +256,30 @@
 # define MNTTAB_OPT_SYNC "sync"
 #endif /* defined(MNT2_GEN_OPT_SYNC) && !defined(MNTTAB_OPT_SYNC) */
 
+#if defined(MNT2_GEN_OPT_LOG) && !defined(MNTTAB_OPT_LOG)
+# define MNTTAB_OPT_LOG "log"
+#endif /* defined(MNT2_GEN_OPT_LOG) && !defined(MNTTAB_OPT_LOG) */
 
+#if defined(MNT2_GEN_OPT_NOATIME) && !defined(MNTTAB_OPT_NOATIME)
+# define MNTTAB_OPT_NOATIME "noatime"
+#endif /* defined(MNT2_GEN_OPT_NOATIME) && !defined(MNTTAB_OPT_NOATIME) */
+
+#if defined(MNT2_GEN_OPT_NODEVMTIME) && !defined(MNTTAB_OPT_NODEVMTIME)
+# define MNTTAB_OPT_NODEVMTIME "nodevmtime"
+#endif /* defined(MNT2_GEN_OPT_NODEVMTIME) && !defined(MNTTAB_OPT_NODEVMTIME) */
+
+#if defined(MNT2_GEN_OPT_SOFTDEP) && !defined(MNTTAB_OPT_SOFTDEP)
+# define MNTTAB_OPT_SOFTDEP "softdep"
+#endif /* defined(MNT2_GEN_OPT_SOFTDEP) && !defined(MNTTAB_OPT_SOFTDEP) */
+
+#if defined(MNT2_GEN_OPT_SYMPERM) && !defined(MNTTAB_OPT_SYMPERM)
+# define MNTTAB_OPT_SYMPERM "symperm"
+#endif /* defined(MNT2_GEN_OPT_SYMPERM) && !defined(MNTTAB_OPT_SYMPERM) */
+
+#if defined(MNT2_GEN_OPT_UNION) && !defined(MNTTAB_OPT_UNION)
+# define MNTTAB_OPT_UNION "union"
+#endif /* defined(MNT2_GEN_OPT_UNION) && !defined(MNTTAB_OPT_UNION) */
+
 /*
  * Add missing MNTTAB_OPT_* options.
  */
@@ -298,6 +341,20 @@
 # define MNTTAB_OPT_DIRMASK "dirmask"
 #endif /* not MNTTAB_OPT_DIRMASK */
 
+/* useful for udf 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_GMTOFF
+# define MNTTAB_OPT_GMTOFF "gmtoff"
+#endif /* not MNTTAB_OPT_GMTOFF */
+#ifndef MNTTAB_OPT_SESSIONNR
+# define MNTTAB_OPT_SESSIONNR "sessionnr"
+#endif /* not MNTTAB_OPT_SESSIONNR */
+
 /*
  * Incomplete filesystem definitions (sunos4, irix6, solaris2)
  */
@@ -335,6 +392,13 @@
 #endif /* defined(HAVE_FS_UFS) && !defined(ufs_args_t) */
 
 /*
+ * if does not define struct udf_args, assume integer bit-field (linux)
+ */
+#if defined(HAVE_FS_UDF) && !defined(udf_args_t)
+# define udf_args_t u_int
+#endif /* defined(HAVE_FS_UDF) && !defined(udf_args_t) */
+
+/*
  * if does not define struct efs_args, assume integer bit-field (linux)
  */
 #if defined(HAVE_FS_EFS) && !defined(efs_args_t)
@@ -341,6 +405,10 @@
 # define efs_args_t u_int
 #endif /* defined(HAVE_FS_EFS) && !defined(efs_args_t) */
 
+#if defined(HAVE_FS_TMPFS) && !defined(tmpfs_args_t)
+# define tmpfs_args_t u_int
+#endif /* defined(HAVE_FS_TMPFS) && !defined(tmpfs_args_t) */
+
 /*
  * if does not define struct xfs_args, assume integer bit-field (linux)
  */
@@ -347,6 +415,9 @@
 #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_EXT) && !defined(ext_args_t)
+# define ext_args_t u_int
+#endif /* defined(HAVE_FS_EXT) && !defined(ext_args_t) */
 
 #if defined(HAVE_FS_AUTOFS) && defined(MOUNT_TYPE_AUTOFS) && !defined(MNTTYPE_AUTOFS)
 # define MNTTYPE_AUTOFS "autofs"
@@ -366,6 +437,14 @@
 #endif /* not HAVE_FS_NFS3 */
 
 /*
+ * If NFS4, then make sure that the "sec" mnttab option is available.
+ */
+#ifdef HAVE_FS_NFS4
+# ifndef MNTTAB_OPT_SEC
+#  define MNTTAB_OPT_SEC "sec"
+# endif /* not MNTTAB_OPT_SEC */
+#endif /* not HAVE_FS_NFS4 */
+/*
  * If loop device (header file) exists, define mount table option
  */
 #if defined(HAVE_LOOP_DEVICE) && !defined(MNTTAB_OPT_LOOP)

Modified: trunk/contrib/amd/include/am_defs.h
===================================================================
--- trunk/contrib/amd/include/am_defs.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/include/am_defs.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -38,8 +34,8 @@
  *
  *
  * File: am-utils/include/am_defs.h
- * $Id: am_defs.h,v 1.1.1.3 2012-07-21 14:53:13 laffer1 Exp $
- * $FreeBSD$
+ * $Id: am_defs.h,v 1.15.2.16 2004/05/12 15:54:31 ezk Exp $
+ * $FreeBSD: stable/10/contrib/amd/include/am_defs.h 310490 2016-12-23 22:42:14Z cy $
  *
  */
 
@@ -67,7 +63,7 @@
 #  define strchr index
 #  define strrchr rindex
 # endif /* not HAVE_STRCHR */
-char *strchr(), *strrchr(), *strdup();
+char *strchr(), *strrchr();
 #endif /* not STDC_HEADERS */
 
 /*
@@ -88,6 +84,14 @@
 # endif /* __GNUC__ < 2 ... */
 #endif /* not __attribute__ */
 
+#define __IGNORE(result) \
+    __ignore((unsigned long)result)
+
+static inline void
+__ignore(unsigned long result) {
+    (void)&result;
+}
+
 /*
  * How to handle signals of any type
  */
@@ -134,11 +138,19 @@
 /*
  * Big-endian or little-endian?
  */
-#ifdef WORDS_BIGENDIAN
-# define ARCH_ENDIAN "big"
-#else /* not WORDS_BIGENDIAN */
-# define ARCH_ENDIAN "little"
-#endif /* not WORDS_BIGENDIAN */
+#ifndef BYTE_ORDER
+# if defined(WORDS_BIGENDIAN)
+#  define ARCH_ENDIAN "big"
+# else /* not WORDS_BIGENDIAN */
+#  define ARCH_ENDIAN "little"
+# endif /* not WORDS_BIGENDIAN */
+#else
+# if BYTE_ORDER == BIG_ENDIAN
+#  define ARCH_ENDIAN "big"
+# else
+#  define ARCH_ENDIAN "little"
+# endif
+#endif
 
 /*
  * Actions to take if HAVE_SYS_TYPES_H is defined.
@@ -209,12 +221,6 @@
  * 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 */
 
@@ -318,14 +324,6 @@
 #endif /* HAVE_MNTENT_H */
 
 /*
- * Actions to take if <sys/errno.h> exists.
- */
-#ifdef HAVE_SYS_ERRNO_H
-# include <sys/errno.h>
-extern int errno;
-#endif /* HAVE_SYS_ERRNO_H */
-
-/*
  * Actions to take if <sys/fsid.h> exists.
  */
 #ifdef HAVE_SYS_FSID_H
@@ -864,7 +862,11 @@
 #ifdef HAVE_SYS_FS_TMP_H
 # include <sys/fs/tmp.h>
 #endif /* HAVE_SYS_FS_TMP_H */
+#ifdef HAVE_FS_TMPFS_TMPFS_ARGS_H
+# include <fs/tmpfs/tmpfs_args.h>
+#endif /* HAVE_FS_TMPFS_TMPFS_ARGS_H */
 
+
 /*
  * Actions to take if <sys/fs/ufs_mount.h> exists.
  */
@@ -886,6 +888,9 @@
 #ifdef HAVE_SYS_FS_EFS_CLNT_H
 # include <sys/fs/efs_clnt.h>
 #endif /* HAVE_SYS_FS_EFS_CLNT_H */
+#ifdef HAVE_FS_EFS_EFS_MOUNT_H
+# include <fs/efs/efs_mount.h>
+#endif /* HAVE_FS_EFS_EFS_MOUNT_H */
 
 /*
  * Actions to take if <sys/fs/xfs_clnt.h> exists.
@@ -927,6 +932,14 @@
  */
 #ifdef HAVE_ERRNO_H
 # include <errno.h>
+#else
+/*
+ * Actions to take if <sys/errno.h> exists.
+ */
+# ifdef HAVE_SYS_ERRNO_H
+#  include <sys/errno.h>
+extern int errno;
+# endif /* HAVE_SYS_ERRNO_H */
 #endif /* HAVE_ERRNO_H */
 
 /*
@@ -958,6 +971,13 @@
 #endif /* HAVE_ISOFS_CD9660_CD9660_MOUNT_H */
 
 /*
+ * Actions to take if <fs/udf/udf_mount.h> exists.
+ */
+#ifdef HAVE_FS_UDF_UDF_MOUNT_H
+# include <fs/udf/udf_mount.h>
+#endif /* HAVE_FS_UDF_UDF_MOUNT_H */
+
+/*
  * Actions to take if <mount.h> exists.
  */
 #ifdef HAVE_MOUNT_H
@@ -1517,14 +1537,6 @@
 extern int strcasecmp(const char *s1, const char *s2);
 #endif /* not HAVE_EXTERN_STRCASECMP */
 
-#ifndef HAVE_EXTERN_STRDUP
-/*
- * define this extern even if function does not exist, for it will
- * be filled in by libamu/strdup.c
- */
-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

Modified: trunk/contrib/amd/include/am_utils.h
===================================================================
--- trunk/contrib/amd/include/am_utils.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/include/am_utils.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -109,9 +105,15 @@
 #define	XLOG_DEBUG	0x0020
 #define	XLOG_MAP	0x0040
 #define	XLOG_STATS	0x0080
-#define XLOG_DEFSTR	"all,nomap,nostats"	/* Default log options */
+/* log option compositions */
+#define XLOG_MASK	0x00ff	/* mask for all flags */
+#define XLOG_MANDATORY	(XLOG_FATAL|XLOG_ERROR)	/* cannot turn these off */
 #define XLOG_ALL	(XLOG_FATAL|XLOG_ERROR|XLOG_USER|XLOG_WARNING|XLOG_INFO|XLOG_MAP|XLOG_STATS)
+/* default: fatal + error + user + warning + info */
+#define XLOG_DEFAULT	(XLOG_MASK & (XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS))
 
+/* default: no logging options */
+
 #define NO_SUBNET	"notknown"   /* default subnet name for no subnet */
 #define	NEXP_AP		(1022)			/* gdmr: was 254 */
 #define NEXP_AP_MARGIN	(128)			/* ???? not used */
@@ -258,8 +260,6 @@
 
 extern int foreground;		/* Foreground process */
 extern int orig_umask;		/* umask() on startup */
-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[];
@@ -278,15 +278,17 @@
 extern char *inet_dquad(char *, size_t, u_long);
 extern char *print_wires(void);
 extern char *str3cat(char *, char *, char *, char *);
+extern char *strvcat(const char *, ...);
 extern char *strealloc(char *, char *);
 extern char *strip_selectors(char *, char *);
 extern char *strnsave(const char *, int);
 extern int amu_close(int fd);
 extern int bind_resv_port(int, u_short *);
-extern int cmdoption(char *, struct opt_tab *, int *);
+extern int cmdoption(char *, struct opt_tab *, u_int *);
 extern int compute_automounter_mount_flags(mntent_t *);
 extern int compute_mount_flags(mntent_t *);
-extern int get_amd_program_number(void);
+extern void discard_nfs_args(void *, u_long);
+extern u_long 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 *);
@@ -300,6 +302,9 @@
 extern int mkdirs(char *, int);
 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 void nfs_program_3(struct svc_req *rqstp, SVCXPRT *transp);
+#define get_nfs_dispatcher_version(a) \
+    ((a) == nfs_program_2 ? NFS_VERSION : NFS_VERSION3)
 extern int pickup_rpc_reply(voidp, int, voidp, XDRPROC_T_TYPE);
 extern int switch_option(char *);
 extern int switch_to_logfile(char *logfile, int orig_umask, int truncate_log);
@@ -320,14 +325,16 @@
      __attribute__ ((__format__ (__printf__, 2, 3)));
 extern void rmdirs(char *);
 extern void rpc_msg_init(struct rpc_msg *, u_long, u_long, u_long);
-extern void set_amd_program_number(int program);
+extern void set_amd_program_number(u_long program);
 extern void show_opts(int ch, struct opt_tab *);
 extern void unregister_amq(void);
 extern voidp xmalloc(int);
 extern voidp xrealloc(voidp, int);
 extern voidp xzalloc(int);
+extern char *xstrdup(const char *);
 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 u_long get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto, u_long def);
+extern int nfs_valid_version(u_long vers);
 extern long get_server_pid(void);
 extern void setup_sighandler(int signum, void (*handler)(int));
 extern time_t clocktime(nfstime *nt);
@@ -367,9 +374,10 @@
 extern int syslogging;
 #endif /* defined(HAVE_SYSLOG_H) || defined(HAVE_SYS_SYSLOG_H) */
 
-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 void compute_nfs_args(void *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 void destroy_nfs_args(void *nap, u_long nfs_version);
 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 create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version);
 extern int amu_svc_register(SVCXPRT *, u_long, u_long, void (*)(struct svc_req *, SVCXPRT *), u_long, struct netconfig *);
 
 #ifdef HAVE_TRANSPORT_TYPE_TLI
@@ -392,9 +400,15 @@
 
 
 /*
- * Network File System: the new generation
- * NFS V.3
+ * Network File System: the old faithful generation NFS V.2
  */
+#ifndef NFS_VERSION2
+# define NFS_VERSION2 ((u_int) 2)
+#endif /* not NFS_VERSION2 */
+
+/*
+ * Network File System: the not so new anymore generation NFS V.3
+ */
 #ifdef HAVE_FS_NFS3
 # ifndef NFS_VERSION3
 #  define NFS_VERSION3 ((u_int) 3)
@@ -401,6 +415,14 @@
 # endif /* not NFS_VERSION3 */
 #endif /* HAVE_FS_NFS3 */
 
+/*
+ * Network File System: the new generation NFS V.4
+ */
+#ifdef HAVE_FS_NFS4
+# ifndef NFS_VERSION4
+#  define NFS_VERSION4 ((u_int) 4)
+# endif /* not NFS_VERSION4 */
+#endif /* HAVE_FS_NFS4 */
 
 /**************************************************************************/
 /*** DEBUGGING								***/
@@ -412,12 +434,11 @@
 
 #ifdef DEBUG
 
-# 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_DAEMON	0x0001	/* 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	/* Don't register amq program */
+# define	D_AMQ		0x0010	/* Register amq program */
 # define	D_STR		0x0020	/* Debug string munging */
 # ifdef DEBUG_MEM
 #  define	D_MEM		0x0040	/* Trace memory allocations */
@@ -424,19 +445,22 @@
 # 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_FORK		0x0080	/* Fork server (hlfsd only) */
+# define	D_INFO		0x0100	/* info service specific debugging (hesiod, nis, etc) */
 # define	D_HRTIME	0x0200	/* Print high resolution time stamps */
 # define	D_XDRTRACE	0x0400	/* Trace xdr routines */
 # define	D_READDIR	0x0800	/* Show browsable_dir progress */
+/* debug option compositions */
+# define	D_MASK		0x0fff  /* mask of known flags */
+# define	D_BASIC		(D_TRACE|D_FULL|D_STR|D_MEM|D_INFO|D_XDRTRACE|D_READDIR)
+# define	D_CONTROL	(D_DAEMON|D_AMQ|D_FORK)
+/* immutable flags: cannot be changed via "amq -D" */
+# define	D_IMMUTABLE	(D_MTAB  | D_CONTROL)
+# define	D_ALL		(D_BASIC | D_CONTROL)
+# define	D_DEFAULT	(D_MASK & D_ALL & ~D_XDRTRACE)
+/* test mode: nodaemon, noamq, nofork, (local) mtab */
+# define	D_TEST		(D_BASIC | D_MTAB)
 
-/*
- * Test mode is test mode: don't daemonize, don't register amq, don't fork,
- * don't touch system mtab, etc.
- */
-# define	D_TEST	(~(D_MEM|D_STR|D_XDRTRACE))
-
 # define	amuDebug(x)	(debug_flags & (x))
 # define	dlog		if (amuDebug(D_FULL)) dplog
 
@@ -460,7 +484,7 @@
 # endif /* not DEBUG_MEM */
 
 /* functions that depend solely on debugging */
-extern void print_nfs_args(const nfs_args_t *nap, u_long nfs_version);
+extern void print_nfs_args(const void *, u_long nfs_version);
 extern int debug_option (char *opt);
 extern void dplog(const char *fmt, ...)
      __attribute__ ((__format__ (__printf__, 1, 2)));
@@ -467,27 +491,42 @@
 
 #else /* not DEBUG */
 
+/* set dummy flags to zero */
+# define	D_DAEMON	0x0001	/* Enter daemon mode */
+# define	D_TRACE		0x0000	/* dummy: Do protocol trace */
+# define	D_FULL		0x0000	/* dummy: Do full trace */
+# define	D_MTAB		0x0000	/* dummy: Use local mtab */
+# define	D_AMQ		0x0010	/* Register amq program */
+# define	D_STR		0x0000	/* dummy: Debug string munging */
+# define	D_MEM		0x0000	/* dummy: Trace memory allocations */
+# define	D_FORK		0x0080	/* Fork server (hlfsd only) */
+# define	D_INFO		0x0000	/* dummy: info service debugging */
+# define	D_HRTIME	0x0000	/* dummy: hi-res time stamps */
+# define	D_XDRTRACE	0x0000	/* dummy: Trace xdr routines */
+# define	D_READDIR	0x0000	/* dummy: browsable_dir progress */
+# define	D_CONTROL	(D_DAEMON|D_AMQ|D_FORK)
+# define	amuDebug(x)	(debug_flags & (x))
 /*
  * If not debugging, then also reset the pointer.
  * It's safer -- and besides, free() should do that anyway.
  */
-#  define	XFREE(x) do { free((voidp)x); x = NULL;} while (0)
+# define	XFREE(x) do { free((voidp)x); x = NULL;} while (0)
 
-#define		amuDebug(x)	(0)
-
-#ifdef __GNUC__
-#define		dlog(fmt...)
-#else  /* not __GNUC__ */
+# if defined(HAVE_GCC_VARARGS_MACROS)
+#  define	dlog(fmt...)
+# elif defined(HAVE_C99_VARARGS_MACROS)
+#  define	dlog(...)
+# else  /* no c99 varargs */
 /* this define means that we CCP leaves code behind the (list,of,args)  */
-#define		dlog
-#endif /* not __GNUC__ */
+#  define	dlog
+# endif /* no c99 varargs */
 
-#define		print_nfs_args(nap, nfs_version)
-#define		debug_option(x)	(1)
+# define	print_nfs_args(nap, nfs_version)
+# define	debug_option(x)	(1)
 
 #endif /* not DEBUG */
 
-extern int debug_flags;		/* Debug options */
+extern u_int debug_flags;	/* Debug options */
 extern struct opt_tab dbg_opt[];
 
 /**************************************************************************/

Modified: trunk/contrib/amd/include/am_xdr_func.h
===================================================================
--- trunk/contrib/amd/include/am_xdr_func.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/include/am_xdr_func.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -43,9 +39,27 @@
 
 #ifdef HAVE_FS_NFS3
 
+#define AM_MOUNTVERS3 ((unsigned long)(3))
+
 #define AM_FHSIZE3 64		/* size in bytes of a file handle (v3) */
-#define	AM_MOUNTVERS3 ((unsigned long)(3))
+#define AM_NFS3_WRITEVERFSIZE 8
+#define AM_NFS3_CREATEVERFSIZE 8
+#define AM_NFS3_COOKIEVERFSIZE 8
+#define AM_ACCESS3_READ 0x0001
+#define AM_ACCESS3_LOOKUP 0x0002
+#define AM_ACCESS3_MODIFY 0x0004
+#define AM_ACCESS3_EXTEND 0x0008
+#define AM_ACCESS3_DELETE 0x0010
+#define AM_ACCESS3_EXECUTE 0x0020
+#define AM_FSF3_LINK 0x0001
+#define AM_FSF3_SYMLINK 0x0002
+#define AM_FSF3_HOMOGENEOUS 0x0008
+#define AM_FSF3_CANSETTIME 0x0010
 
+typedef char am_cookieverf3[AM_NFS3_COOKIEVERFSIZE];
+
+typedef uint64 am_cookie3;
+
 /* NFSv3 handle */
 struct am_nfs_fh3 {
   u_int am_fh3_length;
@@ -131,37 +145,830 @@
 };
 typedef struct am_diropargs3 am_diropargs3;
 
+enum am_ftype3 {
+  AM_NF3REG = 1,
+  AM_NF3DIR = 2,
+  AM_NF3BLK = 3,
+  AM_NF3CHR = 4,
+  AM_NF3LNK = 5,
+  AM_NF3SOCK = 6,
+  AM_NF3FIFO = 7,
+};
+typedef enum am_ftype3 am_ftype3;
+
+typedef u_int am_mode3;
+
+typedef u_int am_uid3;
+
+typedef u_int am_gid3;
+
+typedef uint64 am_size3;
+
+typedef uint64 am_fileid3;
+
+struct am_specdata3 {
+  u_int specdata1;
+  u_int specdata2;
+};
+typedef struct am_specdata3 am_specdata3;
+
+struct am_nfstime3 {
+  u_int seconds;
+  u_int nseconds;
+};
+typedef struct am_nfstime3 am_nfstime3;
+
+struct am_fattr3 {
+  am_ftype3 type;
+  am_mode3 mode;
+  u_int nlink;
+  am_uid3 uid;
+  am_gid3 gid;
+  am_size3 size;
+  am_size3 used;
+  am_specdata3 rdev;
+  uint64 fsid;
+  am_fileid3 fileid;
+  am_nfstime3 atime;
+  am_nfstime3 mtime;
+  am_nfstime3 ctime;
+};
+typedef struct am_fattr3 am_fattr3;
+
+struct am_post_op_attr {
+  bool_t attributes_follow;
+  union {
+    am_fattr3 attributes;
+  } am_post_op_attr_u;
+};
+typedef struct am_post_op_attr am_post_op_attr;
+
+enum am_stable_how {
+  AM_UNSTABLE = 0,
+  AM_DATA_SYNC = 1,
+  AM_FILE_SYNC = 2,
+};
+typedef enum am_stable_how am_stable_how;
+
+typedef uint64 am_offset3;
+
+typedef u_int am_count3;
+
+struct am_wcc_attr {
+  am_size3 size;
+  am_nfstime3 mtime;
+  am_nfstime3 ctime;
+};
+typedef struct am_wcc_attr am_wcc_attr;
+
+struct am_pre_op_attr {
+  bool_t attributes_follow;
+  union {
+    am_wcc_attr attributes;
+  } am_pre_op_attr_u;
+};
+typedef struct am_pre_op_attr am_pre_op_attr;
+
+struct am_wcc_data {
+  am_pre_op_attr before;
+  am_post_op_attr after;
+};
+typedef struct am_wcc_data am_wcc_data;
+
+struct am_WRITE3args {
+  am_nfs_fh3 file;
+  am_offset3 offset;
+  am_count3 count;
+  am_stable_how stable;
+  struct {
+    u_int data_len;
+    char *data_val;
+  } data;
+};
+typedef struct am_WRITE3args am_WRITE3args;
+
+typedef char am_writeverf3[AM_NFS3_WRITEVERFSIZE];
+
+struct am_WRITE3resok {
+  am_wcc_data file_wcc;
+  am_count3 count;
+  am_stable_how committed;
+  am_writeverf3 verf;
+};
+typedef struct am_WRITE3resok am_WRITE3resok;
+
+struct am_WRITE3resfail {
+  am_wcc_data file_wcc;
+};
+typedef struct am_WRITE3resfail am_WRITE3resfail;
+
+struct am_WRITE3res {
+  am_nfsstat3 status;
+  union {
+    am_WRITE3resok ok;
+    am_WRITE3resfail fail;
+  } res_u;
+};
+typedef struct am_WRITE3res am_WRITE3res;
+
 struct am_LOOKUP3args {
-	am_diropargs3 what;
+  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
+  am_nfs_fh3 object;
+  am_post_op_attr obj_attributes;
+  am_post_op_attr dir_attributes;
 };
 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
+  am_post_op_attr dir_attributes;
 };
 typedef struct am_LOOKUP3resfail am_LOOKUP3resfail;
 
 struct am_LOOKUP3res {
-	am_nfsstat3 status;
-	union {
-		am_LOOKUP3resok ok;
-		am_LOOKUP3resfail fail;
-	} res_u;
+  am_nfsstat3 status;
+  union {
+    am_LOOKUP3resok ok;
+    am_LOOKUP3resfail fail;
+  } res_u;
 };
 typedef struct am_LOOKUP3res am_LOOKUP3res;
+
+struct am_COMMIT3args {
+  am_nfs_fh3 file;
+  am_offset3 offset;
+  am_count3 count;
+};
+typedef struct am_COMMIT3args am_COMMIT3args;
+
+struct am_COMMIT3resok {
+  am_wcc_data file_wcc;
+  am_writeverf3 verf;
+};
+typedef struct am_COMMIT3resok am_COMMIT3resok;
+
+struct am_COMMIT3resfail {
+  am_wcc_data file_wcc;
+};
+typedef struct am_COMMIT3resfail am_COMMIT3resfail;
+
+struct am_COMMIT3res {
+  am_nfsstat3 status;
+  union {
+    am_COMMIT3resok ok;
+    am_COMMIT3resfail fail;
+  } res_u;
+};
+typedef struct am_COMMIT3res am_COMMIT3res;
+
+struct am_ACCESS3args {
+  am_nfs_fh3 object;
+  u_int access;
+};
+typedef struct am_ACCESS3args am_ACCESS3args;
+
+struct am_ACCESS3resok {
+  am_post_op_attr obj_attributes;
+  u_int access;
+};
+typedef struct am_ACCESS3resok am_ACCESS3resok;
+
+struct am_ACCESS3resfail {
+  am_post_op_attr obj_attributes;
+};
+typedef struct am_ACCESS3resfail am_ACCESS3resfail;
+
+struct am_ACCESS3res {
+  am_nfsstat3 status;
+  union {
+    am_ACCESS3resok ok;
+    am_ACCESS3resfail fail;
+  } res_u;
+};
+typedef struct am_ACCESS3res am_ACCESS3res;
+
+struct am_GETATTR3args {
+  am_nfs_fh3 object;
+};
+typedef struct am_GETATTR3args am_GETATTR3args;
+
+struct am_GETATTR3resok {
+  am_fattr3 obj_attributes;
+};
+typedef struct am_GETATTR3resok am_GETATTR3resok;
+
+struct am_GETATTR3res {
+  am_nfsstat3 status;
+  union {
+    am_GETATTR3resok ok;
+  } res_u;
+};
+typedef struct am_GETATTR3res am_GETATTR3res;
+
+enum am_time_how {
+  AM_DONT_CHANGE = 0,
+  AM_SET_TO_SERVER_TIME = 1,
+  AM_SET_TO_CLIENT_TIME = 2,
+};
+typedef enum am_time_how am_time_how;
+
+struct am_set_mode3 {
+  bool_t set_it;
+  union {
+    am_mode3 mode;
+  } am_set_mode3_u;
+};
+typedef struct am_set_mode3 am_set_mode3;
+
+struct am_set_uid3 {
+  bool_t set_it;
+  union {
+    am_uid3 uid;
+  } am_set_uid3_u;
+};
+typedef struct am_set_uid3 am_set_uid3;
+
+struct am_set_gid3 {
+  bool_t set_it;
+  union {
+    am_gid3 gid;
+  } am_set_gid3_u;
+};
+typedef struct am_set_gid3 am_set_gid3;
+
+struct am_set_size3 {
+  bool_t set_it;
+  union {
+    am_size3 size;
+  } am_set_size3_u;
+};
+typedef struct am_set_size3 am_set_size3;
+
+struct am_set_atime {
+  am_time_how set_it;
+  union {
+    am_nfstime3 atime;
+  } am_set_atime_u;
+};
+typedef struct am_set_atime am_set_atime;
+
+struct am_set_mtime {
+  am_time_how set_it;
+  union {
+    am_nfstime3 mtime;
+  } am_set_mtime_u;
+};
+typedef struct am_set_mtime am_set_mtime;
+
+struct am_sattr3 {
+  am_set_mode3 mode;
+  am_set_uid3 uid;
+  am_set_gid3 gid;
+  am_set_size3 size;
+  am_set_atime atime;
+  am_set_mtime mtime;
+};
+typedef struct am_sattr3 am_sattr3;
+
+enum am_createmode3 {
+  AM_UNCHECKED = 0,
+  AM_GUARDED = 1,
+  AM_EXCLUSIVE = 2,
+};
+typedef enum am_createmode3 am_createmode3;
+
+typedef char am_createverf3[AM_NFS3_CREATEVERFSIZE];
+
+struct am_createhow3 {
+  am_createmode3 mode;
+  union {
+    am_sattr3 obj_attributes;
+    am_sattr3 g_obj_attributes;
+    am_createverf3 verf;
+  } am_createhow3_u;
+};
+typedef struct am_createhow3 am_createhow3;
+
+struct am_CREATE3args {
+  am_diropargs3 where;
+  am_createhow3 how;
+};
+typedef struct am_CREATE3args am_CREATE3args;
+
+struct am_post_op_fh3 {
+  bool_t handle_follows;
+  union {
+    am_nfs_fh3 handle;
+  } am_post_op_fh3_u;
+};
+typedef struct am_post_op_fh3 am_post_op_fh3;
+
+struct am_CREATE3resok {
+  am_post_op_fh3 obj;
+  am_post_op_attr obj_attributes;
+  am_wcc_data dir_wcc;
+};
+typedef struct am_CREATE3resok am_CREATE3resok;
+
+struct am_CREATE3resfail {
+  am_wcc_data dir_wcc;
+};
+typedef struct am_CREATE3resfail am_CREATE3resfail;
+
+struct am_CREATE3res {
+  am_nfsstat3 status;
+  union {
+    am_CREATE3resok ok;
+    am_CREATE3resfail fail;
+  } res_u;
+};
+typedef struct am_CREATE3res am_CREATE3res;
+
+struct am_REMOVE3args {
+  am_diropargs3 object;
+};
+typedef struct am_REMOVE3args am_REMOVE3args;
+
+struct am_REMOVE3resok {
+  am_wcc_data dir_wcc;
+};
+typedef struct am_REMOVE3resok am_REMOVE3resok;
+
+struct am_REMOVE3resfail {
+  am_wcc_data dir_wcc;
+};
+typedef struct am_REMOVE3resfail am_REMOVE3resfail;
+
+struct am_REMOVE3res {
+  am_nfsstat3 status;
+  union {
+    am_REMOVE3resok ok;
+    am_REMOVE3resfail fail;
+  } res_u;
+};
+typedef struct am_REMOVE3res am_REMOVE3res;
+
+struct am_READ3args {
+  am_nfs_fh3 file;
+  am_offset3 offset;
+  am_count3 count;
+};
+typedef struct am_READ3args am_READ3args;
+
+struct am_READ3resok {
+  am_post_op_attr file_attributes;
+  am_count3 count;
+  bool_t eof;
+  struct {
+    u_int data_len;
+    char *data_val;
+  } data;
+};
+typedef struct am_READ3resok am_READ3resok;
+
+struct am_READ3resfail {
+  am_post_op_attr file_attributes;
+};
+typedef struct am_READ3resfail am_READ3resfail;
+
+struct am_READ3res {
+  am_nfsstat3 status;
+  union {
+    am_READ3resok ok;
+    am_READ3resfail fail;
+  } res_u;
+};
+typedef struct am_READ3res am_READ3res;
+
+struct am_FSINFO3args {
+  am_nfs_fh3 fsroot;
+};
+typedef struct am_FSINFO3args am_FSINFO3args;
+
+struct am_FSINFO3resok {
+  am_post_op_attr obj_attributes;
+  u_int rtmax;
+  u_int rtpref;
+  u_int rtmult;
+  u_int wtmax;
+  u_int wtpref;
+  u_int wtmult;
+  u_int dtpref;
+  am_size3 maxfilesize;
+  am_nfstime3 time_delta;
+  u_int properties;
+};
+typedef struct am_FSINFO3resok am_FSINFO3resok;
+
+struct am_FSINFO3resfail {
+  am_post_op_attr obj_attributes;
+};
+typedef struct am_FSINFO3resfail am_FSINFO3resfail;
+
+struct am_FSINFO3res {
+  am_nfsstat3 status;
+  union {
+    am_FSINFO3resok ok;
+    am_FSINFO3resfail fail;
+  } res_u;
+};
+typedef struct am_FSINFO3res am_FSINFO3res;
+
+struct am_FSSTAT3args {
+  am_nfs_fh3 fsroot;
+};
+typedef struct am_FSSTAT3args am_FSSTAT3args;
+
+struct am_FSSTAT3resok {
+  am_post_op_attr obj_attributes;
+  am_size3 tbytes;
+  am_size3 fbytes;
+  am_size3 abytes;
+  am_size3 tfiles;
+  am_size3 ffiles;
+  am_size3 afiles;
+  u_int invarsec;
+};
+typedef struct am_FSSTAT3resok am_FSSTAT3resok;
+
+struct am_FSSTAT3resfail {
+  am_post_op_attr obj_attributes;
+};
+typedef struct am_FSSTAT3resfail am_FSSTAT3resfail;
+
+struct am_FSSTAT3res {
+  am_nfsstat3 status;
+  union {
+    am_FSSTAT3resok ok;
+    am_FSSTAT3resfail fail;
+  } res_u;
+};
+typedef struct am_FSSTAT3res am_FSSTAT3res;
+
+struct am_PATHCONF3args {
+  am_nfs_fh3 object;
+};
+typedef struct am_PATHCONF3args am_PATHCONF3args;
+
+struct am_PATHCONF3resok {
+  am_post_op_attr obj_attributes;
+  u_int linkmax;
+  u_int name_max;
+  bool_t no_trunc;
+  bool_t chown_restricted;
+  bool_t case_insensitive;
+  bool_t case_preserving;
+};
+typedef struct am_PATHCONF3resok am_PATHCONF3resok;
+
+struct am_PATHCONF3resfail {
+  am_post_op_attr obj_attributes;
+};
+typedef struct am_PATHCONF3resfail am_PATHCONF3resfail;
+
+struct am_PATHCONF3res {
+  am_nfsstat3 status;
+  union {
+    am_PATHCONF3resok ok;
+    am_PATHCONF3resfail fail;
+  } res_u;
+};
+typedef struct am_PATHCONF3res am_PATHCONF3res;
+
+typedef char *am_nfspath3;
+
+struct am_symlinkdata3 {
+  am_sattr3 symlink_attributes;
+  am_nfspath3 symlink_data;
+};
+typedef struct am_symlinkdata3 am_symlinkdata3;
+
+struct am_SYMLINK3args {
+  am_diropargs3 where;
+  am_symlinkdata3 symlink;
+};
+typedef struct am_SYMLINK3args am_SYMLINK3args;
+
+struct am_SYMLINK3resok {
+  am_post_op_fh3 obj;
+  am_post_op_attr obj_attributes;
+  am_wcc_data dir_wcc;
+};
+typedef struct am_SYMLINK3resok am_SYMLINK3resok;
+
+struct am_SYMLINK3resfail {
+  am_wcc_data dir_wcc;
+};
+typedef struct am_SYMLINK3resfail am_SYMLINK3resfail;
+
+struct am_SYMLINK3res {
+  am_nfsstat3 status;
+  union {
+    am_SYMLINK3resok ok;
+    am_SYMLINK3resfail fail;
+  } res_u;
+};
+typedef struct am_SYMLINK3res am_SYMLINK3res;
+
+struct am_READLINK3args {
+  am_nfs_fh3 symlink;
+};
+typedef struct am_READLINK3args am_READLINK3args;
+
+struct am_READLINK3resok {
+  am_post_op_attr symlink_attributes;
+  am_nfspath3 data;
+};
+typedef struct am_READLINK3resok am_READLINK3resok;
+
+struct am_READLINK3resfail {
+  am_post_op_attr symlink_attributes;
+};
+typedef struct am_READLINK3resfail am_READLINK3resfail;
+
+struct am_READLINK3res {
+  am_nfsstat3 status;
+  union {
+    am_READLINK3resok ok;
+    am_READLINK3resfail fail;
+  } res_u;
+};
+typedef struct am_READLINK3res am_READLINK3res;
+
+struct am_devicedata3 {
+  am_sattr3 dev_attributes;
+  am_specdata3 spec;
+};
+typedef struct am_devicedata3 am_devicedata3;
+
+struct am_mknoddata3 {
+  am_ftype3 type;
+  union {
+    am_devicedata3 chr_device;
+    am_devicedata3 blk_device;
+    am_sattr3 sock_attributes;
+    am_sattr3 pipe_attributes;
+  } am_mknoddata3_u;
+};
+typedef struct am_mknoddata3 am_mknoddata3;
+
+struct am_MKNOD3args {
+  am_diropargs3 where;
+  am_mknoddata3 what;
+};
+typedef struct am_MKNOD3args am_MKNOD3args;
+
+struct am_MKNOD3resok {
+  am_post_op_fh3 obj;
+  am_post_op_attr obj_attributes;
+  am_wcc_data dir_wcc;
+};
+typedef struct am_MKNOD3resok am_MKNOD3resok;
+
+struct am_MKNOD3resfail {
+  am_wcc_data dir_wcc;
+};
+typedef struct am_MKNOD3resfail am_MKNOD3resfail;
+
+struct am_MKNOD3res {
+  am_nfsstat3 status;
+  union {
+    am_MKNOD3resok ok;
+    am_MKNOD3resfail fail;
+  } res_u;
+};
+typedef struct am_MKNOD3res am_MKNOD3res;
+
+struct am_MKDIR3args {
+  am_diropargs3 where;
+  am_sattr3 attributes;
+};
+typedef struct am_MKDIR3args am_MKDIR3args;
+
+struct am_MKDIR3resok {
+  am_post_op_fh3 obj;
+  am_post_op_attr obj_attributes;
+  am_wcc_data dir_wcc;
+};
+typedef struct am_MKDIR3resok am_MKDIR3resok;
+
+struct am_MKDIR3resfail {
+  am_wcc_data dir_wcc;
+};
+typedef struct am_MKDIR3resfail am_MKDIR3resfail;
+
+struct am_MKDIR3res {
+  am_nfsstat3 status;
+  union {
+    am_MKDIR3resok ok;
+    am_MKDIR3resfail fail;
+  } res_u;
+};
+typedef struct am_MKDIR3res am_MKDIR3res;
+
+struct am_RMDIR3args {
+  am_diropargs3 object;
+};
+typedef struct am_RMDIR3args am_RMDIR3args;
+
+struct am_RMDIR3resok {
+  am_wcc_data dir_wcc;
+};
+typedef struct am_RMDIR3resok am_RMDIR3resok;
+
+struct am_RMDIR3resfail {
+  am_wcc_data dir_wcc;
+};
+typedef struct am_RMDIR3resfail am_RMDIR3resfail;
+
+struct am_RMDIR3res {
+  am_nfsstat3 status;
+  union {
+    am_RMDIR3resok ok;
+    am_RMDIR3resfail fail;
+  } res_u;
+};
+typedef struct am_RMDIR3res am_RMDIR3res;
+
+struct am_RENAME3args {
+  am_diropargs3 from;
+  am_diropargs3 to;
+};
+typedef struct am_RENAME3args am_RENAME3args;
+
+struct am_RENAME3resok {
+  am_wcc_data fromdir_wcc;
+  am_wcc_data todir_wcc;
+};
+typedef struct am_RENAME3resok am_RENAME3resok;
+
+struct am_RENAME3resfail {
+  am_wcc_data fromdir_wcc;
+  am_wcc_data todir_wcc;
+};
+typedef struct am_RENAME3resfail am_RENAME3resfail;
+
+struct am_RENAME3res {
+  am_nfsstat3 status;
+  union {
+    am_RENAME3resok ok;
+    am_RENAME3resfail fail;
+  } res_u;
+};
+typedef struct am_RENAME3res am_RENAME3res;
+
+struct am_READDIRPLUS3args {
+  am_nfs_fh3 dir;
+  am_cookie3 cookie;
+  am_cookieverf3 cookieverf;
+  am_count3 dircount;
+  am_count3 maxcount;
+};
+typedef struct am_READDIRPLUS3args am_READDIRPLUS3args;
+
+struct am_entryplus3 {
+  am_fileid3 fileid;
+  am_filename3 name;
+  am_cookie3 cookie;
+  am_post_op_attr name_attributes;
+  am_post_op_fh3 name_handle;
+  struct am_entryplus3 *nextentry;
+};
+typedef struct am_entryplus3 am_entryplus3;
+
+struct am_dirlistplus3 {
+  am_entryplus3 *entries;
+  bool_t eof;
+};
+typedef struct am_dirlistplus3 am_dirlistplus3;
+
+struct am_READDIRPLUS3resok {
+  am_post_op_attr dir_attributes;
+  am_cookieverf3 cookieverf;
+  am_dirlistplus3 reply;
+};
+typedef struct am_READDIRPLUS3resok am_READDIRPLUS3resok;
+
+struct am_READDIRPLUS3resfail {
+  am_post_op_attr dir_attributes;
+};
+typedef struct am_READDIRPLUS3resfail am_READDIRPLUS3resfail;
+
+struct am_READDIRPLUS3res {
+  am_nfsstat3 status;
+  union {
+    am_READDIRPLUS3resok ok;
+    am_READDIRPLUS3resfail fail;
+  } res_u;
+};
+typedef struct am_READDIRPLUS3res am_READDIRPLUS3res;
+
+struct am_READDIR3args {
+  am_nfs_fh3 dir;
+  am_cookie3 cookie;
+  am_cookieverf3 cookieverf;
+  am_count3 count;
+};
+typedef struct am_READDIR3args am_READDIR3args;
+
+struct am_entry3 {
+  am_fileid3 fileid;
+  am_filename3 name;
+  am_cookie3 cookie;
+  struct am_entry3 *nextentry;
+};
+typedef struct am_entry3 am_entry3;
+
+struct am_dirlist3 {
+  am_entry3 *entries;
+  bool_t eof;
+};
+typedef struct am_dirlist3 am_dirlist3;
+
+struct am_READDIR3resok {
+  am_post_op_attr dir_attributes;
+  am_cookieverf3 cookieverf;
+  am_dirlist3 reply;
+};
+typedef struct am_READDIR3resok am_READDIR3resok;
+
+struct am_READDIR3resfail {
+  am_post_op_attr dir_attributes;
+};
+typedef struct am_READDIR3resfail am_READDIR3resfail;
+
+struct am_READDIR3res {
+  am_nfsstat3 status;
+  union {
+    am_READDIR3resok ok;
+    am_READDIR3resfail fail;
+  } res_u;
+};
+typedef struct am_READDIR3res am_READDIR3res;
+
+struct am_LINK3args {
+  am_nfs_fh3 file;
+  am_diropargs3 link;
+};
+typedef struct am_LINK3args am_LINK3args;
+
+struct am_LINK3resok {
+  am_post_op_attr file_attributes;
+  am_wcc_data linkdir_wcc;
+};
+typedef struct am_LINK3resok am_LINK3resok;
+
+struct am_LINK3resfail {
+  am_post_op_attr file_attributes;
+  am_wcc_data linkdir_wcc;
+};
+typedef struct am_LINK3resfail am_LINK3resfail;
+
+struct am_LINK3res {
+  am_nfsstat3 status;
+  union {
+    am_LINK3resok ok;
+    am_LINK3resfail fail;
+  } res_u;
+};
+typedef struct am_LINK3res am_LINK3res;
+
+struct am_sattrguard3 {
+  bool_t check;
+  union {
+    am_nfstime3 obj_ctime;
+  } am_sattrguard3_u;
+};
+typedef struct am_sattrguard3 am_sattrguard3;
+
+struct am_SETATTR3args {
+  am_nfs_fh3 object;
+  am_sattr3 new_attributes;
+  am_sattrguard3 guard;
+};
+typedef struct am_SETATTR3args am_SETATTR3args;
+
+struct am_SETATTR3resok {
+  am_wcc_data obj_wcc;
+};
+typedef struct am_SETATTR3resok am_SETATTR3resok;
+
+struct am_SETATTR3resfail {
+  am_wcc_data obj_wcc;
+};
+typedef struct am_SETATTR3resfail am_SETATTR3resfail;
+
+struct am_SETATTR3res {
+  am_nfsstat3 status;
+  union {
+    am_SETATTR3resok ok;
+    am_SETATTR3resfail fail;
+  } res_u;
+};
+typedef struct am_SETATTR3res am_SETATTR3res;
 #endif /* HAVE_FS_NFS3 */
 
 /*
@@ -310,6 +1117,74 @@
  * NFS3 XDR FUNCTIONS:
  */
 #ifdef HAVE_FS_NFS3
+#define AM_NFS3_NULL 0
+void * am_nfs3_null_3(void *, CLIENT *);
+void * am_nfs3_null_3_svc(void *, struct svc_req *);
+#define AM_NFS3_GETATTR 1
+am_GETATTR3res * am_nfs3_getattr_3(am_GETATTR3args *, CLIENT *);
+am_GETATTR3res * am_nfs3_getattr_3_svc(am_GETATTR3args *, struct svc_req *);
+#define AM_NFS3_SETATTR 2
+am_SETATTR3res * am_nfs3_setattr_3(am_SETATTR3args *, CLIENT *);
+am_SETATTR3res * am_nfs3_setattr_3_svc(am_SETATTR3args *, struct svc_req *);
+#define AM_NFS3_LOOKUP 3
+am_LOOKUP3res * am_nfs3_lookup_3(am_LOOKUP3args *, CLIENT *);
+am_LOOKUP3res * am_nfs3_lookup_3_svc(am_LOOKUP3args *, struct svc_req *);
+#define AM_NFS3_ACCESS 4
+am_ACCESS3res * am_nfs3_access_3(am_ACCESS3args *, CLIENT *);
+am_ACCESS3res * am_nfs3_access_3_svc(am_ACCESS3args *, struct svc_req *);
+#define AM_NFS3_READLINK 5
+am_READLINK3res * am_nfs3_readlink_3(am_READLINK3args *, CLIENT *);
+am_READLINK3res * am_nfs3_readlink_3_svc(am_READLINK3args *, struct svc_req *);
+#define AM_NFS3_READ 6
+am_READ3res * am_nfs3_read_3(am_READ3args *, CLIENT *);
+am_READ3res * am_nfs3_read_3_svc(am_READ3args *, struct svc_req *);
+#define AM_NFS3_WRITE 7
+am_WRITE3res * am_nfs3_write_3(am_WRITE3args *, CLIENT *);
+am_WRITE3res * am_nfs3_write_3_svc(am_WRITE3args *, struct svc_req *);
+#define AM_NFS3_CREATE 8
+am_CREATE3res * am_nfs3_create_3(am_CREATE3args *, CLIENT *);
+am_CREATE3res * am_nfs3_create_3_svc(am_CREATE3args *, struct svc_req *);
+#define AM_NFS3_MKDIR 9
+am_MKDIR3res * am_nfs3_mkdir_3(am_MKDIR3args *, CLIENT *);
+am_MKDIR3res * am_nfs3_mkdir_3_svc(am_MKDIR3args *, struct svc_req *);
+#define AM_NFS3_SYMLINK 10
+am_SYMLINK3res * am_nfs3_symlink_3(am_SYMLINK3args *, CLIENT *);
+am_SYMLINK3res * am_nfs3_symlink_3_svc(am_SYMLINK3args *, struct svc_req *);
+#define AM_NFS3_MKNOD 11
+am_MKNOD3res * am_nfs3_mknod_3(am_MKNOD3args *, CLIENT *);
+am_MKNOD3res * am_nfs3_mknod_3_svc(am_MKNOD3args *, struct svc_req *);
+#define AM_NFS3_REMOVE 12
+am_REMOVE3res * am_nfs3_remove_3(am_REMOVE3args *, CLIENT *);
+am_REMOVE3res * am_nfs3_remove_3_svc(am_REMOVE3args *, struct svc_req *);
+#define AM_NFS3_RMDIR 13
+am_RMDIR3res * am_nfs3_rmdir_3(am_RMDIR3args *, CLIENT *);
+am_RMDIR3res * am_nfs3_rmdir_3_svc(am_RMDIR3args *, struct svc_req *);
+#define AM_NFS3_RENAME 14
+am_RENAME3res * am_nfs3_rename_3(am_RENAME3args *, CLIENT *);
+am_RENAME3res * am_nfs3_rename_3_svc(am_RENAME3args *, struct svc_req *);
+#define AM_NFS3_LINK 15
+am_LINK3res * am_nfs3_link_3(am_LINK3args *, CLIENT *);
+am_LINK3res * am_nfs3_link_3_svc(am_LINK3args *, struct svc_req *);
+#define AM_NFS3_READDIR 16
+am_READDIR3res * am_nfs3_readdir_3(am_READDIR3args *, CLIENT *);
+am_READDIR3res * am_nfs3_readdir_3_svc(am_READDIR3args *, struct svc_req *);
+#define AM_NFS3_READDIRPLUS 17
+am_READDIRPLUS3res * am_nfs3_readdirplus_3(am_READDIRPLUS3args *, CLIENT *);
+am_READDIRPLUS3res * am_nfs3_readdirplus_3_svc(am_READDIRPLUS3args *, struct svc_req *);
+#define AM_NFS3_FSSTAT 18
+am_FSSTAT3res * am_nfs3_fsstat_3(am_FSSTAT3args *, CLIENT *);
+am_FSSTAT3res * am_nfs3_fsstat_3_svc(am_FSSTAT3args *, struct svc_req *);
+#define AM_NFS3_FSINFO 19
+am_FSINFO3res * am_nfs3_fsinfo_3(am_FSINFO3args *, CLIENT *);
+am_FSINFO3res * am_nfs3_fsinfo_3_svc(am_FSINFO3args *, struct svc_req *);
+#define AM_NFS3_PATHCONF 20
+am_PATHCONF3res * am_nfs3_pathconf_3(am_PATHCONF3args *, CLIENT *);
+am_PATHCONF3res * am_nfs3_pathconf_3_svc(am_PATHCONF3args *, struct svc_req *);
+#define AM_NFS3_COMMIT 21
+am_COMMIT3res * am_nfs3_commit_3(am_COMMIT3args *, CLIENT *);
+am_COMMIT3res * am_nfs3_commit_3_svc(am_COMMIT3args *, struct svc_req *);
+int nfs_program_3_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
 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);
@@ -322,6 +1197,134 @@
 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);
+bool_t xdr_am_cookieverf3 (XDR *, am_cookieverf3);
+bool_t xdr_uint64 (XDR *, uint64*);
+bool_t xdr_am_cookie3 (XDR *, am_cookie3*);
+bool_t xdr_am_nfs_fh3 (XDR *, am_nfs_fh3*);
+bool_t xdr_am_nfsstat3 (XDR *, am_nfsstat3*);
+bool_t xdr_am_filename3 (XDR *, am_filename3*);
+bool_t xdr_am_diropargs3 (XDR *, am_diropargs3*);
+bool_t xdr_am_ftype3 (XDR *, am_ftype3*);
+bool_t xdr_am_mode3 (XDR *, am_mode3*);
+bool_t xdr_am_uid3 (XDR *, am_uid3*);
+bool_t xdr_am_gid3 (XDR *, am_gid3*);
+bool_t xdr_am_size3 (XDR *, am_size3*);
+bool_t xdr_am_fileid3 (XDR *, am_fileid3*);
+bool_t xdr_am_specdata3 (XDR *, am_specdata3*);
+bool_t xdr_am_nfstime3 (XDR *, am_nfstime3*);
+bool_t xdr_am_fattr3 (XDR *, am_fattr3*);
+bool_t xdr_am_post_op_attr (XDR *, am_post_op_attr*);
+bool_t xdr_am_stable_how (XDR *, am_stable_how*);
+bool_t xdr_am_offset3 (XDR *, am_offset3*);
+bool_t xdr_am_count3 (XDR *, am_count3*);
+bool_t xdr_am_wcc_attr (XDR *, am_wcc_attr*);
+bool_t xdr_am_pre_op_attr (XDR *, am_pre_op_attr*);
+bool_t xdr_am_wcc_data (XDR *, am_wcc_data*);
+bool_t xdr_am_WRITE3args (XDR *, am_WRITE3args*);
+bool_t xdr_am_writeverf3 (XDR *, am_writeverf3);
+bool_t xdr_am_WRITE3resok (XDR *, am_WRITE3resok*);
+bool_t xdr_am_WRITE3resfail (XDR *, am_WRITE3resfail*);
+bool_t xdr_am_WRITE3res (XDR *, am_WRITE3res*);
+bool_t xdr_am_LOOKUP3args (XDR *, am_LOOKUP3args*);
+bool_t xdr_am_LOOKUP3resok (XDR *, am_LOOKUP3resok*);
+bool_t xdr_am_LOOKUP3resfail (XDR *, am_LOOKUP3resfail*);
+bool_t xdr_am_LOOKUP3res (XDR *, am_LOOKUP3res*);
+bool_t xdr_am_COMMIT3args (XDR *, am_COMMIT3args*);
+bool_t xdr_am_COMMIT3resok (XDR *, am_COMMIT3resok*);
+bool_t xdr_am_COMMIT3resfail (XDR *, am_COMMIT3resfail*);
+bool_t xdr_am_COMMIT3res (XDR *, am_COMMIT3res*);
+bool_t xdr_am_ACCESS3args (XDR *, am_ACCESS3args*);
+bool_t xdr_am_ACCESS3resok (XDR *, am_ACCESS3resok*);
+bool_t xdr_am_ACCESS3resfail (XDR *, am_ACCESS3resfail*);
+bool_t xdr_am_ACCESS3res (XDR *, am_ACCESS3res*);
+bool_t xdr_am_GETATTR3args (XDR *, am_GETATTR3args*);
+bool_t xdr_am_GETATTR3resok (XDR *, am_GETATTR3resok*);
+bool_t xdr_am_GETATTR3res (XDR *, am_GETATTR3res*);
+bool_t xdr_am_time_how (XDR *, am_time_how*);
+bool_t xdr_am_set_mode3 (XDR *, am_set_mode3*);
+bool_t xdr_am_set_uid3 (XDR *, am_set_uid3*);
+bool_t xdr_am_set_gid3 (XDR *, am_set_gid3*);
+bool_t xdr_am_set_size3 (XDR *, am_set_size3*);
+bool_t xdr_am_set_atime (XDR *, am_set_atime*);
+bool_t xdr_am_set_mtime (XDR *, am_set_mtime*);
+bool_t xdr_am_sattr3 (XDR *, am_sattr3*);
+bool_t xdr_am_createmode3 (XDR *, am_createmode3*);
+bool_t xdr_am_createverf3 (XDR *, am_createverf3);
+bool_t xdr_am_createhow3 (XDR *, am_createhow3*);
+bool_t xdr_am_CREATE3args (XDR *, am_CREATE3args*);
+bool_t xdr_am_post_op_fh3 (XDR *, am_post_op_fh3*);
+bool_t xdr_am_CREATE3resok (XDR *, am_CREATE3resok*);
+bool_t xdr_am_CREATE3resfail (XDR *, am_CREATE3resfail*);
+bool_t xdr_am_CREATE3res (XDR *, am_CREATE3res*);
+bool_t xdr_am_REMOVE3args (XDR *, am_REMOVE3args*);
+bool_t xdr_am_REMOVE3resok (XDR *, am_REMOVE3resok*);
+bool_t xdr_am_REMOVE3resfail (XDR *, am_REMOVE3resfail*);
+bool_t xdr_am_REMOVE3res (XDR *, am_REMOVE3res*);
+bool_t xdr_am_READ3args (XDR *, am_READ3args*);
+bool_t xdr_am_READ3resok (XDR *, am_READ3resok*);
+bool_t xdr_am_READ3resfail (XDR *, am_READ3resfail*);
+bool_t xdr_am_READ3res (XDR *, am_READ3res*);
+bool_t xdr_am_FSINFO3args (XDR *, am_FSINFO3args*);
+bool_t xdr_am_FSINFO3resok (XDR *, am_FSINFO3resok*);
+bool_t xdr_am_FSINFO3resfail (XDR *, am_FSINFO3resfail*);
+bool_t xdr_am_FSINFO3res (XDR *, am_FSINFO3res*);
+bool_t xdr_am_FSSTAT3args (XDR *, am_FSSTAT3args*);
+bool_t xdr_am_FSSTAT3resok (XDR *, am_FSSTAT3resok*);
+bool_t xdr_am_FSSTAT3resfail (XDR *, am_FSSTAT3resfail*);
+bool_t xdr_am_FSSTAT3res (XDR *, am_FSSTAT3res*);
+bool_t xdr_am_PATHCONF3args (XDR *, am_PATHCONF3args*);
+bool_t xdr_am_PATHCONF3resok (XDR *, am_PATHCONF3resok*);
+bool_t xdr_am_PATHCONF3resfail (XDR *, am_PATHCONF3resfail*);
+bool_t xdr_am_PATHCONF3res (XDR *, am_PATHCONF3res*);
+bool_t xdr_am_nfspath3 (XDR *, am_nfspath3*);
+bool_t xdr_am_symlinkdata3 (XDR *, am_symlinkdata3*);
+bool_t xdr_am_SYMLINK3args (XDR *, am_SYMLINK3args*);
+bool_t xdr_am_SYMLINK3resok (XDR *, am_SYMLINK3resok*);
+bool_t xdr_am_SYMLINK3resfail (XDR *, am_SYMLINK3resfail*);
+bool_t xdr_am_SYMLINK3res (XDR *, am_SYMLINK3res*);
+bool_t xdr_am_READLINK3args (XDR *, am_READLINK3args*);
+bool_t xdr_am_READLINK3resok (XDR *, am_READLINK3resok*);
+bool_t xdr_am_READLINK3resfail (XDR *, am_READLINK3resfail*);
+bool_t xdr_am_READLINK3res (XDR *, am_READLINK3res*);
+bool_t xdr_am_devicedata3 (XDR *, am_devicedata3*);
+bool_t xdr_am_mknoddata3 (XDR *, am_mknoddata3*);
+bool_t xdr_am_MKNOD3args (XDR *, am_MKNOD3args*);
+bool_t xdr_am_MKNOD3resok (XDR *, am_MKNOD3resok*);
+bool_t xdr_am_MKNOD3resfail (XDR *, am_MKNOD3resfail*);
+bool_t xdr_am_MKNOD3res (XDR *, am_MKNOD3res*);
+bool_t xdr_am_MKDIR3args (XDR *, am_MKDIR3args*);
+bool_t xdr_am_MKDIR3resok (XDR *, am_MKDIR3resok*);
+bool_t xdr_am_MKDIR3resfail (XDR *, am_MKDIR3resfail*);
+bool_t xdr_am_MKDIR3res (XDR *, am_MKDIR3res*);
+bool_t xdr_am_RMDIR3args (XDR *, am_RMDIR3args*);
+bool_t xdr_am_RMDIR3resok (XDR *, am_RMDIR3resok*);
+bool_t xdr_am_RMDIR3resfail (XDR *, am_RMDIR3resfail*);
+bool_t xdr_am_RMDIR3res (XDR *, am_RMDIR3res*);
+bool_t xdr_am_RENAME3args (XDR *, am_RENAME3args*);
+bool_t xdr_am_RENAME3resok (XDR *, am_RENAME3resok*);
+bool_t xdr_am_RENAME3resfail (XDR *, am_RENAME3resfail*);
+bool_t xdr_am_RENAME3res (XDR *, am_RENAME3res*);
+bool_t xdr_am_READDIRPLUS3args (XDR *, am_READDIRPLUS3args*);
+bool_t xdr_am_entryplus3 (XDR *, am_entryplus3*);
+bool_t xdr_am_dirlistplus3 (XDR *, am_dirlistplus3*);
+bool_t xdr_am_READDIRPLUS3resok (XDR *, am_READDIRPLUS3resok*);
+bool_t xdr_am_READDIRPLUS3resfail (XDR *, am_READDIRPLUS3resfail*);
+bool_t xdr_am_READDIRPLUS3res (XDR *, am_READDIRPLUS3res*);
+bool_t xdr_am_READDIR3args (XDR *, am_READDIR3args*);
+bool_t xdr_am_entry3 (XDR *, am_entry3*);
+bool_t xdr_am_dirlist3 (XDR *, am_dirlist3*);
+bool_t xdr_am_READDIR3resok (XDR *, am_READDIR3resok*);
+bool_t xdr_am_READDIR3resfail (XDR *, am_READDIR3resfail*);
+bool_t xdr_am_READDIR3res (XDR *, am_READDIR3res*);
+bool_t xdr_am_LINK3args (XDR *, am_LINK3args*);
+bool_t xdr_am_LINK3resok (XDR *, am_LINK3resok*);
+bool_t xdr_am_LINK3resfail (XDR *, am_LINK3resfail*);
+bool_t xdr_am_LINK3res (XDR *, am_LINK3res*);
+bool_t xdr_am_sattrguard3 (XDR *, am_sattrguard3*);
+bool_t xdr_am_SETATTR3args (XDR *, am_SETATTR3args*);
+bool_t xdr_am_SETATTR3resok (XDR *, am_SETATTR3resok*);
+bool_t xdr_am_SETATTR3resfail (XDR *, am_SETATTR3resfail*);
+bool_t xdr_am_SETATTR3res (XDR *, am_SETATTR3res*);
 #endif /* HAVE_FS_NFS3 */
 
 #endif /* not _AM_XDR_FUNC_H */

Modified: trunk/contrib/amd/include/amq_defs.h
===================================================================
--- trunk/contrib/amd/include/amq_defs.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/include/amq_defs.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -55,7 +51,7 @@
 #define AMQ_VERSION ((u_long)1)
 #define AMQPROC_NULL ((u_long)0)
 #define AMQPROC_MNTTREE ((u_long)1)
-#define AMQPROC_UMNT ((u_long)2)
+#define AMQPROC_UMNT ((u_long)2)	/* asynchronous unmount */
 #define AMQPROC_STATS ((u_long)3)
 #define AMQPROC_EXPORT ((u_long)4)
 #define AMQPROC_SETOPT ((u_long)5)
@@ -64,15 +60,19 @@
 #define AMQPROC_GETVERS ((u_long)8)
 #define AMQPROC_GETPID ((u_long)9)
 #define AMQPROC_PAWD ((u_long)10)
+#define AMQPROC_SYNC_UMNT ((u_long)11)	/* synchronous unmount */
+#define AMQPROC_GETMAPINFO ((u_long)12)
 
 /*
  * TYPEDEFS
  */
-typedef long *time_type;
+typedef time_t *time_type;
 typedef struct amq_mount_info amq_mount_info;
+typedef struct amq_map_info amq_map_info;
 typedef struct amq_mount_stats amq_mount_stats;
 typedef struct amq_mount_tree amq_mount_tree;
 typedef struct amq_setopt amq_setopt;
+typedef struct amq_sync_umnt amq_sync_umnt;
 typedef amq_mount_tree *amq_mount_tree_p;
 
 /*
@@ -114,6 +114,22 @@
   amq_mount_tree_p *amq_mount_tree_list_val;
 } amq_mount_tree_list;
 
+struct amq_map_info {
+  amq_string mi_name;
+  amq_string mi_wildcard;
+  time_type mi_modify;
+  int mi_flags;
+  int mi_refc;
+  int mi_up;
+  int mi_reloads;
+  int mi_nentries;
+};
+
+typedef struct {
+  u_int amq_map_info_list_len;
+  amq_map_info *amq_map_info_list_val;
+} amq_map_info_list;
+
 struct amq_mount_stats {
   int as_drops;
   int as_stale;
@@ -122,6 +138,21 @@
   int as_uerr;
 };
 
+typedef enum {
+  AMQ_UMNT_OK 		= 0,	/* must be zero! */
+  AMQ_UMNT_FAILED 	= 1,	/* unmount failed */
+  AMQ_UMNT_FORK 	= 2,	/* fork failed */
+  AMQ_UMNT_READ 	= 3,	/* pipe read failed */
+  AMQ_UMNT_SERVER 	= 4,	/* server down */
+  AMQ_UMNT_SIGNAL 	= 5	/* received signal */
+} au_etype;
+
+struct amq_sync_umnt {
+	au_etype	au_etype;	/* error type */
+	int		au_errno;	/* error number */
+	int		au_signal;	/* signal received */
+};
+
 enum amq_opt {
   AMOPT_DEBUG = 0,
   AMOPT_LOGFILE = 1,
@@ -145,6 +176,8 @@
  */
 extern bool_t xdr_amq_mount_info(XDR *xdrs, amq_mount_info *objp);
 extern bool_t xdr_amq_mount_info_list(XDR *xdrs, amq_mount_info_list *objp);
+extern bool_t xdr_amq_map_info(XDR *xdrs, amq_map_info *objp);
+extern bool_t xdr_amq_map_info_list(XDR *xdrs, amq_map_info_list *objp);
 extern bool_t xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp);
 extern bool_t xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp);
 extern bool_t xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp);
@@ -151,6 +184,7 @@
 extern bool_t xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp);
 extern bool_t xdr_amq_opt(XDR *xdrs, amq_opt *objp);
 extern bool_t xdr_amq_setopt(XDR *xdrs, amq_setopt *objp);
+extern bool_t xdr_amq_sync_umnt(XDR *xdrs, amq_sync_umnt *objp);
 extern bool_t xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr);
 extern bool_t xdr_time_type(XDR *xdrs, time_type *objp);
 

Modified: trunk/contrib/amd/include/mount_headers1.h
===================================================================
--- trunk/contrib/amd/include/mount_headers1.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/include/mount_headers1.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -123,50 +119,50 @@
 # include <sys/vmount.h>
 #endif /* HAVE_SYS_VMOUNT_H */
 
+#if HAVE_LINUX_FS_H
+# if !defined(__GLIBC__) || __GLIBC__ < 2
 /*
- * 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_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>
+# else
+#  include <linux/fs.h>
+# endif/* (!__GLIBC__ || __GLIBC__ < 2) */
+#endif /* HAVE_LINUX_FS_H */
 
 #ifdef HAVE_SYS_FS_TYPES_H
 # include <sys/fs_types.h>
@@ -192,6 +188,10 @@
 # include <isofs/cd9660/cd9660_mount.h>
 #endif /* HAVE_ISOFS_CD9660_CD9660_MOUNT_H */
 
+#ifdef HAVE_FS_UDF_UDF_MOUNT_H
+# include <fs/udf/udf_mount.h>
+#endif /* HAVE_FS_UDF_UDF_MOUNT_H */
+
 #ifdef HAVE_SYS_FS_PC_FS_H
 # include <sys/fs/pc_fs.h>
 #endif /* HAVE_SYS_FS_PC_FS_H */
@@ -202,6 +202,14 @@
 # include <fs/msdosfs/msdosfsmount.h>
 #endif /* HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H */
 
+#ifdef HAVE_FS_TMPFS_TMPFS_ARGS_H
+# include <fs/tmpfs/tmpfs_args.h>
+#endif /* HAVE_FS_TMPFS_TMPFS_ARGS_H */
+
+#ifdef HAVE_FS_EFS_EFS_MOUNT_H
+# include <fs/efs/efs_mount.h>
+#endif /* HAVE_FS_EFS_EFS_MOUNT_H */
+
 #ifdef HAVE_RPC_RPC_H
 # include <rpc/rpc.h>
 #endif /* HAVE_RPC_RPC_H */

Modified: trunk/contrib/amd/include/mount_headers2.h
===================================================================
--- trunk/contrib/amd/include/mount_headers2.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/include/mount_headers2.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/ldap-id.ms
===================================================================
--- trunk/contrib/amd/ldap-id.ms	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/ldap-id.ms	2018-06-15 22:31:15 UTC (rev 11011)
@@ -303,4 +303,4 @@
 S-106 91 Stockholm
          SWEDEN
 
-Email: leifj at matematik.su.se
+Email: leifj AT matematik.su.se

Modified: trunk/contrib/amd/ldap-id.txt
===================================================================
--- trunk/contrib/amd/ldap-id.txt	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/ldap-id.txt	2018-06-15 22:31:15 UTC (rev 11011)
@@ -333,7 +333,7 @@
    S-106 91 Stockholm
             SWEDEN
 
-   Email: leifj at matematik.su.se
+   Email: leifj AT matematik.su.se
 
 
 

Modified: trunk/contrib/amd/libamu/amu.h
===================================================================
--- trunk/contrib/amd/libamu/amu.h	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/amu.h	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -47,11 +43,14 @@
 /*
  * Decide what maximum level of NFS server to try and mount with.
  */
-#ifdef HAVE_FS_NFS3
+#if defined(HAVE_FS_NFS4)
+# define NFS_VERS_MAX NFS_VERSION4
+#elif defined(HAVE_FS_NFS3)
 # define NFS_VERS_MAX NFS_VERSION3
 #else /* not HAVE_FS_NFS3 */
 # define NFS_VERS_MAX NFS_VERSION
 #endif /* not HAVE_FS_NFS3 */
+# define NFS_VERS_MIN NFS_VERSION
 
 /* some systems like ncr2 do not define this in <rpcsvc/mount.h> */
 #ifndef MNTPATHLEN

Modified: trunk/contrib/amd/libamu/hasmntopt.c
===================================================================
--- trunk/contrib/amd/libamu/hasmntopt.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/hasmntopt.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -67,7 +63,7 @@
   /*
    * Skip past white space
    */
-  while (*cp && isspace((int) *cp))
+  while (*cp && isspace((unsigned char) *cp))
     cp++;
 
   /*
@@ -106,7 +102,7 @@
   char t[MNTMAXSTR];
   char *f;
   char *o = t;
-  int l = strlen(opt);
+  size_t l = strlen(opt);
 
   xstrlcpy(t, mnt->mnt_opts, sizeof(t));
 

Modified: trunk/contrib/amd/libamu/misc_rpc.c
===================================================================
--- trunk/contrib/amd/libamu/misc_rpc.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/misc_rpc.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/libamu/mount_fs.c
===================================================================
--- trunk/contrib/amd/libamu/mount_fs.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/mount_fs.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -46,6 +42,7 @@
 #endif /* HAVE_CONFIG_H */
 #include <am_defs.h>
 #include <amu.h>
+#include <nfs_common.h>
 
 
 /* ensure that mount table options are delimited by a comma */
@@ -105,6 +102,30 @@
   {MNTTAB_OPT_OVERLAY, MNT2_GEN_OPT_OVERLAY},
 #endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
 
+#if defined(MNT2_GEN_OPT_LOG) && defined(MNTTAB_OPT_LOG)
+  {MNTTAB_OPT_LOG, MNT2_GEN_OPT_LOG},
+#endif /* defined(MNT2_GEN_OPT_LOG) && defined(MNTTAB_OPT_LOG) */
+
+#if defined(MNT2_GEN_OPT_NOATIME) && defined(MNTTAB_OPT_NOATIME)
+  {MNTTAB_OPT_NOATIME, MNT2_GEN_OPT_NOATIME},
+#endif /* defined(MNT2_GEN_OPT_NOATIME) && defined(MNTTAB_OPT_NOATIME) */
+
+#if defined(MNT2_GEN_OPT_NODEVMTIME) && defined(MNTTAB_OPT_NODEVMTIME)
+  {MNTTAB_OPT_NODEVMTIME, MNT2_GEN_OPT_NODEVMTIME},
+#endif /* defined(MNT2_GEN_OPT_NODEVMTIME) && defined(MNTTAB_OPT_NODEVMTIME) */
+
+#if defined(MNT2_GEN_OPT_SOFTDEP) && defined(MNTTAB_OPT_SOFTDEP)
+  {MNTTAB_OPT_SOFTDEP, MNT2_GEN_OPT_SOFTDEP},
+#endif /* defined(MNT2_GEN_OPT_SOFTDEP) && defined(MNTTAB_OPT_SOFTDEP) */
+
+#if defined(MNT2_GEN_OPT_SYMPERM) && defined(MNTTAB_OPT_SYMPERM)
+  {MNTTAB_OPT_SYMPERM, MNT2_GEN_OPT_SYMPERM},
+#endif /* defined(MNT2_GEN_OPT_SYMPERM) && defined(MNTTAB_OPT_SYMPERM) */
+
+#if defined(MNT2_GEN_OPT_UNION) && defined(MNTTAB_OPT_UNION)
+  {MNTTAB_OPT_UNION, MNT2_GEN_OPT_UNION},
+#endif /* defined(MNT2_GEN_OPT_UNION) && defined(MNTTAB_OPT_UNION) */
+
   /*
    * 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
@@ -158,6 +179,25 @@
 }
 
 
+#if defined(MOUNT_TABLE_ON_FILE) && defined(MNTTAB_OPT_VERS)
+/*
+ * add the extra vers={2,3} field to the mount table,
+ * unless already specified by user
+ */
+static void
+addvers(char *zopts, size_t l, mntent_t *mnt, u_long have_vers,
+  u_long want_vers)
+{
+  if (have_vers == want_vers &&
+      hasmntval(mnt, MNTTAB_OPT_VERS) != want_vers) {
+    char optsbuf[48];
+    xsnprintf(optsbuf, sizeof(optsbuf),
+	      "%s=%d", MNTTAB_OPT_VERS, want_vers);
+    append_opts(zopts, l, optsbuf);
+  }
+}
+#endif /* MOUNT_TABLE_ON_FILE && MNTTAB_OPT_VERS */
+
 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, int on_autofs)
 {
@@ -166,10 +206,10 @@
   char *zopts = NULL, *xopts = NULL;
   size_t l;
 #endif /* MOUNT_TABLE_ON_FILE */
-  char *mnt_dir = 0;
+  char *mnt_dir = NULL;
 
 #ifdef NEED_AUTOFS_SPACE_HACK
-  char *old_mnt_dir = 0;
+  char *old_mnt_dir = NULL;
   /* perform space hack */
   if (on_autofs) {
     old_mnt_dir = mnt->mnt_dir;
@@ -176,7 +216,7 @@
     mnt->mnt_dir = mnt_dir = autofs_strdup_space_hack(old_mnt_dir);
   } else
 #endif /* NEED_AUTOFS_SPACE_HACK */
-    mnt_dir = strdup(mnt->mnt_dir);
+    mnt_dir = xstrdup(mnt->mnt_dir);
 
   dlog("'%s' fstype " MTYPE_PRINTF_TYPE " (%s) flags %#x (%s)",
        mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
@@ -256,19 +296,15 @@
   }
 # endif /* MNTTAB_OPT_DEV */
 
+# if defined(HAVE_FS_NFS4) && defined(MNTTAB_OPT_VERS)
+  addvers(zopts, l, mnt, nfs_version, NFS_VERSION4);
+# endif /* defined(HAVE_FS_NFS4) && defined(MNTTAB_OPT_VERS) */
 # if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
-  /*
-   * add the extra vers={2,3} field to the mount table,
-   * unless already specified by user
-   */
-   if (nfs_version == NFS_VERSION3 &&
-       hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) {
-     char optsbuf[48];
-     xsnprintf(optsbuf, sizeof(optsbuf),
-	       "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3);
-     append_opts(zopts, l, optsbuf);
-   }
+  addvers(zopts, l, mnt, nfs_version, NFS_VERSION3);
 # endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */
+# ifdef MNTTAB_OPT_VERS
+  addvers(zopts, l, mnt, nfs_version, NFS_VERSION2);
+# endif /* MNTTAB_OPT_VERS */
 
 # ifdef MNTTAB_OPT_PROTO
   /*
@@ -333,7 +369,7 @@
  * with caution.
  */
 static void
-compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp)
+compute_nfs_attrcache_flags(struct nfs_common_args *nap, mntent_t *mntp)
 {
   int acval = 0;
   int err_acval = 1;		/* 1 means we found no 'actimeo' value */
@@ -365,7 +401,9 @@
     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);
+    int tmp;
+    err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMIN, &tmp);
+    nap->acregmin = tmp;
 # else /* not MNTTAB_OPT_ACREGMIN */
     nap->acregmin = 0;
 # endif /* not MNTTAB_OPT_ACREGMIN */
@@ -384,7 +422,9 @@
     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);
+    int tmp;
+    err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMAX, &tmp);
+    nap->acregmax = tmp;
 # else /* not MNTTAB_OPT_ACREGMAX */
     nap->acregmax = 0;
 # endif /* not MNTTAB_OPT_ACREGMAX */
@@ -403,7 +443,9 @@
     nap->acdirmin = acval;	/* min ac timeout for dirs (sec) */
   } else {
 # ifdef MNTTAB_OPT_ACDIRMIN
-    err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, (int *) &nap->acdirmin);
+    int tmp;
+    err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, &tmp);
+    nap->acdirmin = tmp;
 # else /* not MNTTAB_OPT_ACDIRMIN */
     nap->acdirmin = 0;
 # endif /* not MNTTAB_OPT_ACDIRMIN */
@@ -422,7 +464,9 @@
     nap->acdirmax = acval;	/* max ac timeout for dirs (sec) */
   } else {
 # ifdef MNTTAB_OPT_ACDIRMAX
-    err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, (int *) &nap->acdirmax);
+    int tmp;
+    err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, &tmp);
+    nap->acdirmax = tmp;
 # else /* not MNTTAB_OPT_ACDIRMAX */
     nap->acdirmax = 0;
 # endif /* not MNTTAB_OPT_ACDIRMAX */
@@ -443,148 +487,16 @@
 }
 
 
-/*
- * Fill in the many possible fields and flags of struct nfs_args.
- *
- * nap:		pre-allocated structure to fill in.
- * mntp:	mount entry structure (includes options)
- * genflags:	generic mount flags already determined
- * nfsncp:	(TLI only) netconfig entry for this NFS mount
- * ip_addr:	IP address of file server
- * nfs_version:	2, 3, (4 in the future), or 0 if unknown
- * nfs_proto:	"udp", "tcp", or NULL.
- * fhp:		file handle structure pointer
- * host_name:	name of remote NFS host
- * fs_name:	remote file system name to mount
- */
-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)
+
+static void
+compute_nfs_common_args(struct nfs_common_args *nap, mntent_t *mntp,
+    const char *nfs_proto, u_long nfs_version)
 {
-  /* 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) {
-# 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, &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);
-
-#ifdef HAVE_NFS_ARGS_T_FHSIZE
-# ifdef HAVE_FS_NFS3
-  if (nfs_version == NFS_VERSION3)
-    nap->fhsize = fhp->v3.am_fh3_length;
-  else
-# endif /* HAVE_FS_NFS3 */
-    nap->fhsize = FHSIZE;
-#endif /* HAVE_NFS_ARGS_T_FHSIZE */
-
-  /* this is the version of the nfs_args structure, not of NFS! */
-#ifdef HAVE_NFS_ARGS_T_FH_LEN
-# ifdef HAVE_FS_NFS3
-  if (nfs_version == NFS_VERSION3)
-    nap->fh_len = fhp->v3.am_fh3_length;
-  else
-# endif /* HAVE_FS_NFS3 */
-    nap->fh_len = FHSIZE;
-#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 */
-
-  /************************************************************************/
-  /***	IP ADDRESS OF REMOTE HOST					***/
-  /************************************************************************/
-  if (ip_addr) {
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-    nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
-#endif /* HAVE_TRANSPORT_TYPE_TLI */
-    NFS_SA_DREF(nap, ip_addr);
-  }
-
-  /************************************************************************/
-  /***	NFS PROTOCOL (UDP, TCP) AND VERSION				***/
-  /************************************************************************/
 #ifdef MNT2_NFS_OPT_TCP
   if (nfs_proto && STREQ(nfs_proto, "tcp"))
     nap->flags |= MNT2_NFS_OPT_TCP;
 #endif /* MNT2_NFS_OPT_TCP */
 
-#ifdef HAVE_NFS_ARGS_T_SOTYPE
-  /* bsdi3 uses this */
-  if (nfs_proto) {
-    if (STREQ(nfs_proto, "tcp"))
-      nap->sotype = SOCK_STREAM;
-    else if (STREQ(nfs_proto, "udp"))
-      nap->sotype = SOCK_DGRAM;
-  }
-#endif /* HAVE_NFS_ARGS_T_SOTYPE */
-
-#ifdef HAVE_NFS_ARGS_T_PROTO
-  nap->proto = 0;		/* bsdi3 sets this field to zero  */
-# ifdef IPPROTO_TCP
-  if (nfs_proto) {
-    if (STREQ(nfs_proto, "tcp"))	/* AIX 4.2.x needs this */
-      nap->proto = IPPROTO_TCP;
-    else if (STREQ(nfs_proto, "udp"))
-      nap->proto = IPPROTO_UDP;
-  }
-# endif /* IPPROTO_TCP */
-#endif /* HAVE_NFS_ARGS_T_SOTYPE */
-
-#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_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 (amu_hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
@@ -624,28 +536,6 @@
 # endif /* not MNTTAB_OPT_RESVPORT */
 #endif /* MNT2_NFS_OPT_RESVPORT */
 
-  /************************************************************************/
-  /***	OTHER FLAGS AND OPTIONS						***/
-  /************************************************************************/
-
-#ifdef HAVE_TRANSPORT_TYPE_TLI
-  /* set up syncaddr field */
-  nap->syncaddr = (struct netbuf *) NULL;
-
-  /* set up knconf field */
-  if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
-    plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
-    going_down(1);
-  }
-  /* update the flags field for knconf */
-  nap->flags |= MNT2_NFS_OPT_KNCONF;
-#endif /* HAVE_TRANSPORT_TYPE_TLI */
-
-#ifdef MNT2_NFS_OPT_FSNAME
-  nap->fsname = fs_name;
-  nap->flags |= MNT2_NFS_OPT_FSNAME;
-#endif /* MNT2_NFS_OPT_FSNAME */
-
   nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE);
 #ifdef MNT2_NFS_OPT_RSIZE
   if (nap->rsize)
@@ -674,11 +564,6 @@
     nap->flags |= MNT2_NFS_OPT_RETRANS;
 #endif /* MNT2_NFS_OPT_RETRANS */
 
-#ifdef MNT2_NFS_OPT_BIODS
-  if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
-    nap->flags |= MNT2_NFS_OPT_BIODS;
-#endif /* MNT2_NFS_OPT_BIODS */
-
 #ifdef MNT2_NFS_OPT_SOFT
   if (amu_hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
     nap->flags |= MNT2_NFS_OPT_SOFT;
@@ -687,7 +572,7 @@
 #ifdef MNT2_NFS_OPT_SPONGY
   if (amu_hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
     nap->flags |= MNT2_NFS_OPT_SPONGY;
-    if (nap->flags & MNT2_NFS_OPT_SOFT) {
+    if (*flags & MNT2_NFS_OPT_SOFT) {
       plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
       nap->flags &= ~MNT2_NFS_OPT_SOFT;
     }
@@ -720,6 +605,11 @@
 # endif /* MNT2_NFS_OPT_NOINT */
 #endif /* MNTTAB_OPT_INTR */
 
+#ifdef MNT2_NFS_OPT_NOACL
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOACL) != NULL)
+    nap->flags |= MNT2_NFS_OPT_NOACL;
+#endif /* MNT2_NFS_OPT_NOACL */
+
 #ifdef MNTTAB_OPT_NODEVS
   if (amu_hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
     nap->flags |= MNT2_NFS_OPT_NODEVS;
@@ -735,39 +625,17 @@
     nap->flags |= MNT2_NFS_OPT_PRIVATE;
 #endif /* MNTTAB_OPT_PRIVATE */
 
-#ifdef MNTTAB_OPT_SYMTTL	/* symlink cache time-to-live */
-  if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
-    nap->flags |= MNT2_NFS_OPT_SYMTTL;
-#endif /* MNTTAB_OPT_SYMTTL */
 
-#ifdef MNT2_NFS_OPT_PGTHRESH	/* paging threshold */
-  if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
-    nap->flags |= MNT2_NFS_OPT_PGTHRESH;
-#endif /* MNT2_NFS_OPT_PGTHRESH */
-
 #if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
   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 (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) */
-
 #if defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK)
   if (amu_hasmntopt(mntp, MNTTAB_OPT_NOLOCK) != NULL)
     nap->flags |= MNT2_NFS_OPT_NONLM;
@@ -777,78 +645,36 @@
   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_NFS_ARGS_T_OPTSTR */
+static void
+print_nfs_common_args(const struct nfs_common_args *a)
+{
+  plog(XLOG_DEBUG, "NA->flags = 0x%lx", a->flags);
 
-  /************************************************************************/
-  /***	FINAL ACTIONS							***/
-  /************************************************************************/
+  plog(XLOG_DEBUG, "NA->rsize = %lu", a->rsize);
+  plog(XLOG_DEBUG, "NA->wsize = %lu", a->wsize);
+  plog(XLOG_DEBUG, "NA->timeo = %lu", a->timeo);
+  plog(XLOG_DEBUG, "NA->retrans = %lu", a->retrans);
 
-#ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
-  /* Ultrix stores generic flags in nfs_args.gfs_flags. */
-  nap->gfs_flags = genflags;
-#endif /* HAVE_NFS_ARGS_T_FLAGS */
-
-  return;			/* end of compute_nfs_args() function */
+#ifdef HAVE_NFS_ARGS_T_ACREGMIN
+  plog(XLOG_DEBUG, "NA->acregmin = %lu", a->acregmin);
+  plog(XLOG_DEBUG, "NA->acregmax = %lu", a->acregmax);
+  plog(XLOG_DEBUG, "NA->acdirmin = %lu", a->acdirmin);
+  plog(XLOG_DEBUG, "NA->acdirmax = %lu", a->acdirmax);
+#endif /* HAVE_NFS_ARGS_T_ACREGMIN */
 }
 
-
-/*
- * Fill in special values for flags and fields of nfs_args, for an
- * automounter NFS mount.
- */
-void
-compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
+static void
+discard_nfs23_args(nfs_args_t *nap)
 {
-#ifdef MNT2_NFS_OPT_SYMTTL
-  /*
-   * 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 0");
-  nap->flags |= MNT2_NFS_OPT_SYMTTL;
-  nap->symttl = 0;
-#endif /* MNT2_NFS_OPT_SYMTTL */
-
-  /*
-   * This completes the flags for the HIDE_MOUNT_TYPE  code in the
-   * mount_amfs_toplvl() function in amd/amfs_toplvl.c.
-   * Some systems don't have a mount type, but a mount flag.
-   */
-#ifdef MNT2_NFS_OPT_AUTO
-  nap->flags |= MNT2_NFS_OPT_AUTO;
-#endif /* MNT2_NFS_OPT_AUTO */
-#ifdef MNT2_NFS_OPT_IGNORE
-  nap->flags |= MNT2_NFS_OPT_IGNORE;
-#endif /* MNT2_NFS_OPT_IGNORE */
-#ifdef MNT2_GEN_OPT_AUTOMNTFS
-  nap->flags |= MNT2_GEN_OPT_AUTOMNTFS;
-#endif /* not MNT2_GEN_OPT_AUTOMNTFS */
-
-#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.
-   */
-  plog(XLOG_INFO, "%s: disabling nfs congestion window", mntp->mnt_dir);
-  nap->flags |= MNT2_NFS_OPT_DUMBTIMR;
-#endif /* MNT2_NFS_OPT_DUMBTIMR */
-
-  /* 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.
-   */
-#ifdef MNT2_NFS_OPT_RESVPORT
-  nap->flags |= MNT2_NFS_OPT_RESVPORT;
-#endif /* MNT2_NFS_OPT_RESVPORT */
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+  free_knetconfig(nap->knconf);
+  if (nap->addr)
+    XFREE(nap->addr);	/* allocated in compute_nfs_args() */
+#endif /* HAVE_TRANSPORT_TYPE_TLI */
 }
 
-
 #ifdef DEBUG
 /* get string version (in hex) of identifier */
 static char *
@@ -855,29 +681,48 @@
 get_hex_string(u_int len, const char *fhdata)
 {
   u_int i;
-  static char buf[128];		/* better not go over it! */
+  static u_int xlen;
+  static char *buf;
+  static u_short *arr;
   char str[16];
-  short int arr[64];
 
-  if (!fhdata)
+  if (!fhdata || len == 0 || len > 10240)
     return NULL;
+  i = len * 4 + 1;
+  if (xlen < i) {
+    buf = xrealloc(buf, i);
+    arr = xrealloc(arr, len * sizeof(*arr));
+    xlen = i;
+  }
+	
   buf[0] = '\0';
-  memset(&arr[0], 0, (64 * sizeof(short int)));
-  memcpy(&arr[0], &fhdata[0], len);
-  for (i=0; i<len/sizeof(unsigned short int); i++) {
+  memset(arr, 0, len * sizeof(*arr));
+  memcpy(arr, fhdata, len);
+  len /= sizeof(*arr);
+  for (i = 0; i < len; i++) {
     xsnprintf(str, sizeof(str), "%04x", ntohs(arr[i]));
-    xstrlcat(buf, str, sizeof(buf));
+    xstrlcat(buf, str, xlen);
   }
   return buf;
 }
 
+static void
+print_nfs_sockaddr_in(const char *tag, const struct sockaddr_in *sap)
+{
+  char name[64];
+  plog(XLOG_DEBUG, "NA->%s.sin_family = %d", tag, sap->sin_family);
+  plog(XLOG_DEBUG, "NA->%s.sin_port = %d", tag, ntohs(sap->sin_port));
+  if (inet_ntop(AF_INET, &sap->sin_addr, name, sizeof(name)) == NULL)
+    return;
+  plog(XLOG_DEBUG, "NA->%s.sin_addr = \"%s\"", tag, name);
+}
 
 /*
  * print a subset of fields from "struct nfs_args" that are otherwise
  * not being provided anywhere else.
  */
-void
-print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
+static void
+print_nfs23_args(const nfs_args_t *nap, u_long nfs_version)
 {
   int fhlen = 32;	/* default: NFS V.2 file handle length is 32 */
 #ifdef HAVE_TRANSPORT_TYPE_TLI
@@ -886,6 +731,7 @@
 #else /* not HAVE_TRANSPORT_TYPE_TLI */
   struct sockaddr_in *sap;
 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
+  struct nfs_common_args a;
 
   if (!nap) {
     plog(XLOG_DEBUG, "NULL nfs_args!");
@@ -919,17 +765,11 @@
 # 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_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));
+  print_nfs_sockaddr_in("addr", sap);
 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
 #ifdef HAVE_NFS_ARGS_T_ADDRLEN
   plog(XLOG_DEBUG, "NA->addrlen = %d", nap->addrlen);
@@ -972,22 +812,13 @@
   plog(XLOG_DEBUG, "NA->version = %d", nap->version);
 #endif /* HAVE_NFS_ARGS_T_VERSION */
 
-  plog(XLOG_DEBUG, "NA->flags = 0x%x", (int) nap->flags);
+  put_nfs_common_args(nap, a);
+  print_nfs_common_args(&a);
 
-  plog(XLOG_DEBUG, "NA->rsize = %d", (int) nap->rsize);
-  plog(XLOG_DEBUG, "NA->wsize = %d", (int) nap->wsize);
 #ifdef HAVE_NFS_ARGS_T_BSIZE
   plog(XLOG_DEBUG, "NA->bsize = %d", nap->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_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_NFS_ARGS_T_ACREGMIN */
 #ifdef MNTTAB_OPT_SYMTTL
   plog(XLOG_DEBUG, "NA->symttl = %d", nap->symttl);
 #endif /* MNTTAB_OPT_SYMTTL */
@@ -1001,3 +832,665 @@
 
 }
 #endif /* DEBUG */
+
+/*
+ * Fill in the many possible fields and flags of struct nfs_args.
+ *
+ * nap:		pre-allocated structure to fill in.
+ * mntp:	mount entry structure (includes options)
+ * genflags:	generic mount flags already determined
+ * nfsncp:	(TLI only) netconfig entry for this NFS mount
+ * ip_addr:	IP address of file server
+ * nfs_version:	2, 3, or 0 if unknown
+ * nfs_proto:	"udp", "tcp", or NULL.
+ * fhp:		file handle structure pointer
+ * host_name:	name of remote NFS host
+ * fs_name:	remote file system name to mount
+ */
+static void
+compute_nfs23_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)
+{
+  struct nfs_common_args a;
+  /* initialize just in case */
+  memset((voidp) nap, 0, sizeof(nfs_args_t));
+
+  /* compute all of the NFS attribute-cache flags */
+  memset(&a, 0, sizeof(a));
+  compute_nfs_attrcache_flags(&a, mntp);
+  compute_nfs_common_args(&a, mntp, nfs_proto, nfs_version);
+  get_nfs_common_args(nap, a);
+
+  /************************************************************************/
+  /***	FILEHANDLE DATA AND LENGTH					***/
+  /************************************************************************/
+#ifdef HAVE_FS_NFS3
+  if (nfs_version == NFS_VERSION3) {
+    if (fhp == NULL) {
+      plog(XLOG_FATAL, "cannot pass NULL fh for NFSv%lu", nfs_version);
+      going_down(1);
+      return;
+    }
+
+# 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, &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 */
+  {
+    if (fhp == NULL) {
+      plog(XLOG_FATAL, "cannot pass NULL fh for NFSv%lu", nfs_version);
+      going_down(1);
+      return;
+    }
+    NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v2);
+  }
+
+#ifdef HAVE_NFS_ARGS_T_FHSIZE
+# ifdef HAVE_FS_NFS3
+  if (nfs_version == NFS_VERSION3)
+    nap->fhsize = fhp->v3.am_fh3_length;
+  else
+# endif /* HAVE_FS_NFS3 */
+    nap->fhsize = FHSIZE;
+#endif /* HAVE_NFS_ARGS_T_FHSIZE */
+
+  /* this is the version of the nfs_args structure, not of NFS! */
+#ifdef HAVE_NFS_ARGS_T_FH_LEN
+# ifdef HAVE_FS_NFS3
+  if (nfs_version == NFS_VERSION3)
+    nap->fh_len = fhp->v3.am_fh3_length;
+  else
+# endif /* HAVE_FS_NFS3 */
+    nap->fh_len = FHSIZE;
+#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 */
+
+  /************************************************************************/
+  /***	IP ADDRESS OF REMOTE HOST					***/
+  /************************************************************************/
+  if (ip_addr) {
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+    nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
+#endif /* HAVE_TRANSPORT_TYPE_TLI */
+    NFS_SA_DREF(nap, ip_addr);
+  }
+
+  /************************************************************************/
+  /***	NFS PROTOCOL (UDP, TCP) AND VERSION				***/
+  /************************************************************************/
+#ifdef HAVE_NFS_ARGS_T_SOTYPE
+  /* bsdi3 uses this */
+  if (nfs_proto) {
+    if (STREQ(nfs_proto, "tcp"))
+      nap->sotype = SOCK_STREAM;
+    else if (STREQ(nfs_proto, "udp"))
+      nap->sotype = SOCK_DGRAM;
+  }
+#endif /* HAVE_NFS_ARGS_T_SOTYPE */
+
+#ifdef HAVE_NFS_ARGS_T_PROTO
+  nap->proto = 0;		/* bsdi3 sets this field to zero  */
+# ifdef IPPROTO_TCP
+  if (nfs_proto) {
+    if (STREQ(nfs_proto, "tcp"))	/* AIX 4.2.x needs this */
+      nap->proto = IPPROTO_TCP;
+    else if (STREQ(nfs_proto, "udp"))
+      nap->proto = IPPROTO_UDP;
+  }
+# endif /* IPPROTO_TCP */
+#endif /* HAVE_NFS_ARGS_T_SOTYPE */
+
+#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_NFS_ARGS_VERSION */
+
+  /************************************************************************/
+  /***	OTHER NFS SOCKET RELATED OPTIONS AND FLAGS			***/
+  /************************************************************************/
+
+  /************************************************************************/
+  /***	OTHER FLAGS AND OPTIONS						***/
+  /************************************************************************/
+
+#ifdef MNT2_NFS_OPT_BIODS
+  if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
+    nap->flags |= MNT2_NFS_OPT_BIODS;
+#endif /* MNT2_NFS_OPT_BIODS */
+
+#ifdef MNTTAB_OPT_SYMTTL	/* symlink cache time-to-live */
+  if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
+    nap->args.flags |= MNT2_NFS_OPT_SYMTTL;
+#endif /* MNTTAB_OPT_SYMTTL */
+
+#ifdef MNT2_NFS_OPT_PGTHRESH	/* paging threshold */
+  if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
+    nap->args.flags |= MNT2_NFS_OPT_PGTHRESH;
+#endif /* MNT2_NFS_OPT_PGTHRESH */
+
+#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
+    nap->flags |= MNT2_NFS_OPT_POSIX;
+# ifdef HAVE_NFS_ARGS_T_PATHCONF
+    nap->pathconf = NULL;
+# endif /* HAVE_NFS_ARGS_T_PATHCONF */
+  }
+#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
+
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+  /* set up syncaddr field */
+  nap->syncaddr = (struct netbuf *) NULL;
+
+  /* set up knconf field */
+  if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
+    plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
+    going_down(1);
+    return;
+  }
+  /* update the flags field for knconf */
+  nap->args.flags |= MNT2_NFS_OPT_KNCONF;
+#endif /* HAVE_TRANSPORT_TYPE_TLI */
+
+#ifdef MNT2_NFS_OPT_FSNAME
+  nap->fsname = fs_name;
+  nap->args.flags |= MNT2_NFS_OPT_FSNAME;
+#endif /* MNT2_NFS_OPT_FSNAME */
+
+
+#ifdef HAVE_NFS_ARGS_T_OPTSTR
+  nap->optstr = mntp->mnt_opts;
+#endif /* HAVE_NFS_ARGS_T_OPTSTR */
+
+#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) */
+
+  /************************************************************************/
+  /***	FINAL ACTIONS							***/
+  /************************************************************************/
+
+#ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
+  /* Ultrix stores generic flags in nfs_args.gfs_flags. */
+  nap->gfs_flags = genflags;
+#endif /* HAVE_NFS_ARGS_T_FLAGS */
+
+  return;			/* end of compute_nfs_args() function */
+}
+
+#ifdef HAVE_FS_NFS4
+
+#define RPC_AUTH_GSS_KRB5       390003
+#define RPC_AUTH_GSS_KRB5I      390004
+#define RPC_AUTH_GSS_KRB5P      390005
+#define RPC_AUTH_GSS_LKEY       390006
+#define RPC_AUTH_GSS_LKEYI      390007
+#define RPC_AUTH_GSS_LKEYP      390008
+#define RPC_AUTH_GSS_SPKM       390009
+#define RPC_AUTH_GSS_SPKMI      390010
+#define RPC_AUTH_GSS_SPKMP      390011
+
+struct {
+  const char *name;
+  int num;
+} flavours[] = {
+  { "unix",	AUTH_UNIX },
+  { "krb5",	RPC_AUTH_GSS_KRB5 },
+  { "krb5i",	RPC_AUTH_GSS_KRB5I },
+  { "krb5p",	RPC_AUTH_GSS_KRB5P },
+  { "lkey",	RPC_AUTH_GSS_LKEY },
+  { "lkeyi",	RPC_AUTH_GSS_LKEYI },
+  { "lkeyp",	RPC_AUTH_GSS_LKEYP },
+  { "spkm",	RPC_AUTH_GSS_SPKM },
+  { "spkmi",	RPC_AUTH_GSS_SPKMI },
+  { "spkmp",	RPC_AUTH_GSS_SPKMP },
+};
+
+static char *
+set_nfs4_security(nfs4_args_t *nap, mntent_t *mntp)
+{
+  const char *o = hasmnteq(mntp, MNTTAB_OPT_SEC);
+  char *q, *s, *ss;
+  size_t l, i;
+
+  if (o == NULL)
+    o = "unix";
+
+  for (l = 1, q = strchr(o, ','); q; q = strchr(q + 1, ','))
+    l++;
+
+  nap->auth_flavours = xmalloc(l * sizeof(*nap->auth_flavours));
+
+  s = ss = xstrdup(o);
+  for (;;) {
+    q = strchr(s, ',');
+    if (q)
+	*q = '\0';
+
+    for (l = 0, i = 0; i < sizeof(flavours) / sizeof(flavours[0]); i++)
+      if (strcmp(flavours[i].name, s) == 0) {
+	nap->auth_flavours[l++] = flavours[i].num;
+	break;
+      }
+
+    if (i == sizeof(flavours) / sizeof(flavours[0]))
+      plog(XLOG_ERROR, "Unknown NFSv4 security mechanism %s\n", s);
+
+    if (q == NULL)
+      break;
+
+    *q = ':';
+    s = ++q;
+  }
+
+  nap->auth_flavourlen = l;
+  return ss;
+}
+
+static int
+get_my_ipv4addr(struct nfs_string *ns)
+{
+  struct hostent *hp;
+  char myname[MAXHOSTNAMELEN];
+
+  if (gethostname(myname, sizeof(myname)) == -1)
+    return -1;
+  if ((hp = gethostbyname(myname)) == NULL)
+    return -1;
+  if (inet_ntop(AF_INET, hp->h_addr, myname, sizeof(myname)) == NULL)
+    return -1;
+  ns->len = strlen(myname);
+  ns->data = xmalloc(ns->len + 1);
+  memcpy(ns->data, myname, ns->len + 1);
+  return 0;
+}
+
+static void
+add_nfs4_mntopts(const nfs4_args_t *nap, mntent_t *mntp, char *sec)
+{
+  char *opts = mntp->mnt_opts;
+  char buf[1024], addr[128];
+  size_t len = strlen(mntp->mnt_opts);
+
+  if (inet_ntop(AF_INET,
+      &((const struct sockaddr_in *)nap->host_addr)->sin_addr,
+      addr, sizeof(addr)) == NULL)
+    return;
+
+  xsnprintf(buf, sizeof(buf), ",clientaddr=%s,addr=%s", nap->client_addr.data,
+	    addr);
+
+  len += strlen(buf) + 1;
+
+  if (sec && strcmp(sec, "unix") != 0) {
+    len += strlen(sec) + strlen(MNTTAB_OPT_SEC) + 2; /* 2 = ",=" */
+  } else
+    sec = NULL;
+
+  opts = xrealloc(mntp->mnt_opts, len);
+  xstrlcat(opts, buf, len);
+
+  if (sec) {
+    xstrlcat(opts, ",", len);
+    xstrlcat(opts, MNTTAB_OPT_SEC, len);
+    xstrlcat(opts, "=", len);
+    xstrlcat(opts, sec, len);
+  }
+
+  mntp->mnt_opts = opts;
+}
+
+static void
+print_nfs4_security(const nfs4_args_t *nap)
+{
+  char buf[1024];
+  char num[64];
+  size_t i, j;
+
+  buf[0] = '\0';
+
+  for (i = 0; i < nap->auth_flavourlen; i++) {
+
+    for (j = 0; j < sizeof(flavours) / sizeof(flavours[0]); j++)
+      if (flavours[j].num == nap->auth_flavours[i]) {
+	xstrlcpy(num, flavours[j].name, sizeof(num));
+	break;
+      }
+
+    if (j == sizeof(flavours) / sizeof(flavours[0])) {
+      plog(XLOG_ERROR, "Unknown NFSv4 security mechanism %d\n",
+           nap->auth_flavours[i]);
+      xsnprintf(num, sizeof(num), "*%d*", nap->auth_flavours[i]);
+    }
+
+    if (buf[0])
+      xstrlcat(buf, ":", sizeof(buf));
+
+    xstrlcat(buf, num, sizeof(buf));
+  }
+
+  plog(XLOG_DEBUG, "NA->auth_flavours \"%s\"\n", buf);
+}
+
+static void
+discard_nfs4_args(nfs4_args_t *nap)
+{
+  if (nap->client_addr.data)
+    free(nap->client_addr.data);
+  if (nap->hostname.data)
+    free(nap->hostname.data);
+  if (nap->mnt_path.data)
+    free(nap->mnt_path.data);
+  if (nap->host_addr)
+    free(nap->host_addr);
+  if (nap->auth_flavours)
+    free(nap->auth_flavours);
+}
+
+/*
+ * Fill in the many possible fields and flags of struct nfs4_args.
+ *
+ * nap:		pre-allocated structure to fill in.
+ * mntp:	mount entry structure (includes options)
+ * genflags:	generic mount flags already determined
+ * nfsncp:	(TLI only) netconfig entry for this NFS mount
+ * ip_addr:	IP address of file server
+ * nfs_version:	4, or 0 if unknown
+ * nfs_proto:	"udp", "tcp", or NULL.
+ * fhp:		file handle structure pointer
+ * host_name:	name of remote NFS host
+ * fs_name:	remote file system name to mount
+ */
+static void
+compute_nfs4_args(nfs4_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)
+{
+  char *s;
+  struct nfs_common_args a;
+  uint16_t nfs_port;
+
+  /* initialize just in case */
+  memset((voidp) nap, 0, sizeof(nfs4_args_t));
+
+  /* compute all of the NFS attribute-cache flags */
+  memset(&a, 0, sizeof(a));
+  compute_nfs_attrcache_flags(&a, mntp);
+  compute_nfs_common_args(&a, mntp, nfs_proto, nfs_version);
+  get_nfs_common_args(nap, a);
+
+  get_my_ipv4addr(&nap->client_addr);
+
+  /************************************************************************/
+  /***	HOST NAME							***/
+  /************************************************************************/
+  nap->hostname.len = strlen(host_name);
+  nap->hostname.data = xmalloc(nap->hostname.len + 1);
+  memcpy(nap->hostname.data, host_name, nap->hostname.len + 1);
+
+  if ((s = strchr(fs_name, ':')) != NULL)
+    s++;
+  else
+    s = fs_name;
+
+  nap->mnt_path.len = strlen(s);
+  nap->mnt_path.data = xmalloc(nap->mnt_path.len + 1);
+  memcpy(nap->mnt_path.data, s, nap->mnt_path.len + 1);
+  plog(XLOG_DEBUG, "dir name %s\n", nap->mnt_path.data);
+
+  /************************************************************************/
+  /***  IP ADDRESS OF REMOTE HOST                                       ***/
+  /************************************************************************/
+  nap->host_addrlen = sizeof(*ip_addr);
+  nap->host_addr = xmalloc(nap->host_addrlen);
+  memcpy(nap->host_addr, ip_addr, nap->host_addrlen);
+
+  nfs_port = hasmntval(mntp, MNTTAB_OPT_PORT);
+  if (nfs_port == 0)
+    nfs_port = htons(NFS_PORT);
+  else
+    nfs_port = htons(nfs_port);
+
+  ((struct sockaddr_in *)nap->host_addr)->sin_port = nfs_port;
+
+  nap->proto = 0;               /* bsdi3 sets this field to zero  */
+  if (nfs_proto) {
+    if (STREQ(nfs_proto, "tcp"))        /* AIX 4.2.x needs this */
+      nap->proto = IPPROTO_TCP;
+    else if (STREQ(nfs_proto, "udp"))
+      nap->proto = IPPROTO_UDP;
+  }
+
+  nap->version = NFS4_MOUNT_VERSION; /* BSDI 3.0 and OpenBSD 2.2 */
+
+  /************************************************************************/
+  /***  OTHER NFS SOCKET RELATED OPTIONS AND FLAGS                      ***/
+  /************************************************************************/
+
+
+  /************************************************************************/
+  /***  OTHER FLAGS AND OPTIONS                                         ***/
+  /************************************************************************/
+
+#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
+  if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
+    nap->args.flags |= MNT2_NFS_OPT_POSIX;
+# ifdef HAVE_NFS_ARGS_T_PATHCONF
+    nap->pathconf = NULL;
+# endif /* HAVE_NFS_ARGS_T_PATHCONF */
+  }
+#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
+
+#if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
+  nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
+  if (nap->maxgrouplist != 0)
+    nap->args.flags |= MNT2_NFS_OPT_MAXGRPS;
+#endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
+
+#ifdef HAVE_NFS_ARGS_T_OPTSTR
+  nap->optstr = mntp->mnt_opts;
+#endif /* HAVE_NFS_ARGS_T_OPTSTR */
+
+  /************************************************************************/
+  /***  FINAL ACTIONS                                                   ***/
+  /************************************************************************/
+
+#ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
+  /* Ultrix stores generic flags in nfs_args.gfs_flags. */
+  nap->gfs_flags = genflags;
+#endif /* HAVE_NFS_ARGS_T_FLAGS */
+
+  s = set_nfs4_security(nap, mntp);
+
+  /* Add addresses to the mount options */
+  add_nfs4_mntopts(nap, mntp, s);
+
+  return;                       /* end of compute_nfs4_args() function */
+}
+
+#ifdef DEBUG
+static void
+print_nfs4_args(const nfs4_args_t *nap, u_long nfs_version)
+{
+  struct sockaddr_in *sap;
+  struct nfs_common_args a;
+
+  if (!nap) {
+    plog(XLOG_DEBUG, "NULL nfs_args!");
+    return;
+  }
+
+  plog(XLOG_DEBUG, "NA->client_addr \"%s\"\n", nap->client_addr.data);
+  plog(XLOG_DEBUG, "NA->mnt_path = \"%s\"", nap->mnt_path.data);
+  plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname.data);
+  sap = (struct sockaddr_in *) nap->host_addr;
+  print_nfs_sockaddr_in("host_addr", sap);
+  plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto);
+#ifdef HAVE_NFS_ARGS_T_VERSION
+  plog(XLOG_DEBUG, "NA->version = %d", nap->version);
+#endif /* HAVE_NFS_ARGS_T_VERSION */
+  print_nfs4_security(nap);
+
+  put_nfs_common_args(nap, a);
+  print_nfs_common_args(&a);
+}
+#endif
+#endif /* HAVE_FS_NFS4 */
+
+void
+compute_nfs_args(void *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)
+{
+#ifdef HAVE_FS_NFS4
+  if (nfs_version == NFS_VERSION4)
+    compute_nfs4_args(nap, mntp, genflags, nfsncp, ip_addr, nfs_version,
+		      nfs_proto, fhp, host_name, fs_name);
+  else
+#endif /* HAVE_FS_NFS4 */
+    compute_nfs23_args(nap, mntp, genflags, nfsncp, ip_addr, nfs_version,
+		       nfs_proto, fhp, host_name, fs_name);
+}
+
+void
+discard_nfs_args(void *nap, u_long nfs_version)
+{
+#ifdef HAVE_FS_NFS4
+  if (nfs_version == NFS_VERSION4)
+    discard_nfs4_args(nap);
+  else
+#endif /* HAVE_FS_NFS4 */
+    discard_nfs23_args(nap);
+}
+
+#ifdef DEBUG
+void
+print_nfs_args(const void *nap, u_long nfs_version)
+{
+#ifdef HAVE_FS_NFS4
+  if (nfs_version == NFS_VERSION4)
+    print_nfs4_args(nap, nfs_version);
+  else
+#endif /* HAVE_FS_NFS4 */
+    print_nfs23_args(nap, nfs_version);
+}
+#endif
+
+
+/*
+ * Fill in special values for flags and fields of nfs_args, for an
+ * automounter NFS mount.
+ */
+void
+compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
+{
+  struct nfs_common_args a;
+
+#ifdef MNT2_NFS_OPT_SYMTTL
+  /*
+   * 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 0");
+  nap->flags |= MNT2_NFS_OPT_SYMTTL;
+  nap->symttl = 0;
+#endif /* MNT2_NFS_OPT_SYMTTL */
+
+  /*
+   * This completes the flags for the HIDE_MOUNT_TYPE  code in the
+   * mount_amfs_toplvl() function in amd/amfs_toplvl.c.
+   * Some systems don't have a mount type, but a mount flag.
+   */
+#ifdef MNT2_NFS_OPT_AUTO
+  nap->flags |= MNT2_NFS_OPT_AUTO;
+#endif /* MNT2_NFS_OPT_AUTO */
+#ifdef MNT2_NFS_OPT_IGNORE
+  nap->flags |= MNT2_NFS_OPT_IGNORE;
+#endif /* MNT2_NFS_OPT_IGNORE */
+#ifdef MNT2_GEN_OPT_AUTOMNTFS
+  nap->flags |= MNT2_GEN_OPT_AUTOMNTFS;
+#endif /* not MNT2_GEN_OPT_AUTOMNTFS */
+
+#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.
+   */
+  plog(XLOG_INFO, "%s: disabling nfs congestion window", mntp->mnt_dir);
+  nap->flags |= MNT2_NFS_OPT_DUMBTIMR;
+#endif /* MNT2_NFS_OPT_DUMBTIMR */
+
+  /* compute all of the NFS attribute-cache flags */
+  memset(&a, 0, sizeof(a));
+  a.flags = nap->flags;
+  compute_nfs_attrcache_flags(&a, mntp);
+  get_nfs_common_args(nap, a);
+
+  /*
+   * Provide a slight bit more security by requiring the kernel to use
+   * reserved ports.
+   */
+#ifdef MNT2_NFS_OPT_RESVPORT
+  nap->flags |= MNT2_NFS_OPT_RESVPORT;
+#endif /* MNT2_NFS_OPT_RESVPORT */
+}
+
+int
+nfs_valid_version(u_long v)
+{
+  return v >= NFS_VERS_MIN && v <= NFS_VERS_MAX;
+}

Modified: trunk/contrib/amd/libamu/mtab.c
===================================================================
--- trunk/contrib/amd/libamu/mtab.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/mtab.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -233,9 +229,9 @@
 
       char *endptr = strchr(eq, ',');
 
-      /* if saw no comma, return strdup'd string */
+      /* if saw no comma, return xstrdup'd string */
       if (!endptr)
-	return strdup(eq);
+	return xstrdup(eq);
       else {
 	/* else we need to copy only the chars needed */
 	int len = endptr - eq;

Modified: trunk/contrib/amd/libamu/nfs_prot_xdr.c
===================================================================
--- trunk/contrib/amd/libamu/nfs_prot_xdr.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/nfs_prot_xdr.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -56,3 +52,14 @@
   }
   return (TRUE);
 }
+
+
+bool_t
+xdr_amq_sync_umnt(XDR *xdrs, amq_sync_umnt *objp)
+{
+
+  if (!xdr_opaque(xdrs, (char *) objp, sizeof(*objp))) {
+    return (FALSE);
+  }
+  return (TRUE);
+}

Modified: trunk/contrib/amd/libamu/strerror.c
===================================================================
--- trunk/contrib/amd/libamu/strerror.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/strerror.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2002-2006 Ion Badulescu
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 2002-2014 Ion Badulescu
+ * Copyright (c) 1997-2014 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.
@@ -17,11 +17,7 @@
  * 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
+ * 3. 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.
  *

Modified: trunk/contrib/amd/libamu/strutil.c
===================================================================
--- trunk/contrib/amd/libamu/strutil.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/strutil.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -268,3 +264,37 @@
 
   return ret;
 }
+
+static size_t
+vstrlen(const char *src, va_list ap)
+{
+  size_t len = strlen(src);
+  while ((src = va_arg(ap, const char *)) != NULL)
+    len += strlen(src);
+  return len;
+}
+
+static void
+vstrcpy(char *dst, const char *src, va_list ap)
+{
+  strcpy(dst, src);
+  while ((src = va_arg(ap, const char *)) != NULL)
+    strcat(dst, src);
+}
+
+char *
+strvcat(const char *src, ...)
+{
+  size_t len;
+  char *dst;
+  va_list ap;
+
+  va_start(ap, src);
+  len = vstrlen(src, ap);
+  va_end(ap);
+  dst = xmalloc(len + 1);
+  va_start(ap, src);
+  vstrcpy(dst, src, ap);
+  va_end(ap);
+  return dst;
+}

Modified: trunk/contrib/amd/libamu/wire.c
===================================================================
--- trunk/contrib/amd/libamu/wire.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/wire.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -226,7 +222,7 @@
   }
 
   /* fill in network number (string) */
-  al->ip_net_num = strdup(netNumberBuf);
+  al->ip_net_num = xstrdup(netNumberBuf);
 
   if (np != NULL)
     s = np->n_name;
@@ -242,7 +238,7 @@
   }
 
   /* fill in network name (string) */
-  al->ip_net_name = strdup(s);
+  al->ip_net_name = xstrdup(s);
   /* Let's be cautious here about buffer overflows -Ion */
   if (strlen(s) > MAXHOSTNAMELEN) {
     al->ip_net_name[MAXHOSTNAMELEN] = '\0';
@@ -318,9 +314,14 @@
       if (STREQ(net, al->ip_net_name) || STREQ(net, al->ip_net_num))
 	return TRUE;
   } else {
-    char *netstr = strdup(net), *maskstr;
+    char *netstr = xstrdup(net), *maskstr;
     u_long netnum, masknum = 0;
     maskstr = strchr(netstr, '/');
+    if (maskstr == NULL) {
+      plog(XLOG_ERROR, "%s: netstr %s does not have a `/'", __func__, netstr);
+      XFREE(netstr);
+      return FALSE;
+    }
     maskstr[0] = '\0';		/* null terminate netstr */
     maskstr++;
     if (*maskstr == '\0')	/* if empty string, make it NULL */

Modified: trunk/contrib/amd/libamu/xdr_func.c
===================================================================
--- trunk/contrib/amd/libamu/xdr_func.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/xdr_func.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -951,7 +947,6 @@
   return (TRUE);
 }
 
-
 bool_t
 xdr_am_mountres3(XDR *xdrs, am_mountres3 *objp)
 {
@@ -968,8 +963,80 @@
   return (TRUE);
 }
 
+bool_t
+xdr_am_cookieverf3(XDR *xdrs, am_cookieverf3 objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_cookieverf3:");
 
+  if (!xdr_opaque(xdrs, objp, AM_NFS3_COOKIEVERFSIZE))
+    return FALSE;
+  return TRUE;
+}
+
+#if 0
+/* In FreeBSD xdr_uint64() is defined in ../../../include/rpcsvc/nfs_prot.x */
+/*
+ * Not ideal, xdr_u_int64_t() is not defined in Linux glibc RPC
+ * but xdr_u_quad_t() is. But in libtirpc xdr_u_quad_t() is not
+ * defined and xdr_u_int64_t() is. So xdr_u_int64_t() is probably
+ * an expected standard xdr function so, if it isn't defined use
+ * an internal xdr_u_int64_t() that uses xdr_u_quad_t().
+ */
+#ifndef HAVE_XDR_U_INT64_T
+#define xdr_u_int64_t(xdrs, objp) xdr_u_quad_t(xdrs, objp)
+#endif /* HAVE_XDR_U_INT64_T */
+
 bool_t
+xdr_uint64(XDR *xdrs, uint64 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_uint64:");
+
+  if (!xdr_u_int64_t(xdrs, objp))
+    return FALSE;
+  return TRUE;
+}
+#endif
+
+bool_t
+xdr_am_cookie3(XDR *xdrs, am_cookie3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_cookie3:");
+
+  if (!xdr_uint64(xdrs, objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_nfs_fh3(XDR *xdrs, am_nfs_fh3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_nfs_fh3:");
+
+  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);
+}
+
+bool_t
 xdr_am_diropargs3(XDR *xdrs, am_diropargs3 *objp)
 {
   if (amuDebug(D_XDRTRACE))
@@ -982,7 +1049,6 @@
   return (TRUE);
 }
 
-
 bool_t
 xdr_am_filename3(XDR *xdrs, am_filename3 *objp)
 {
@@ -994,8 +1060,317 @@
   return (TRUE);
 }
 
+bool_t
+xdr_am_ftype3(XDR *xdrs, am_ftype3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_ftype3:");
 
+  if (!xdr_enum(xdrs, (enum_t *) objp))
+    return FALSE;
+  return TRUE;
+}
+
 bool_t
+xdr_am_mode3(XDR *xdrs, am_mode3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_mode3:");
+
+  if (!xdr_u_int(xdrs, objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_uid3(XDR *xdrs, am_uid3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_uid3:");
+
+  if (!xdr_u_int(xdrs, objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_gid3(XDR *xdrs, am_gid3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_gid3:");
+
+  if (!xdr_u_int(xdrs, objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_size3(XDR *xdrs, am_size3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_size3:");
+
+  if (!xdr_uint64(xdrs, objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_fileid3(XDR *xdrs, am_fileid3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_fileid3:");
+
+  if (!xdr_uint64(xdrs, objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_specdata3(XDR *xdrs, am_specdata3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_specdata3:");
+
+  if (!xdr_u_int(xdrs, &objp->specdata1))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->specdata2))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_nfstime3(XDR *xdrs, am_nfstime3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_nfstime3:");
+
+  if (!xdr_u_int(xdrs, &objp->seconds))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->nseconds))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_fattr3(XDR *xdrs, am_fattr3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_fattr3:");
+
+  if (!xdr_am_ftype3(xdrs, &objp->type))
+    return FALSE;
+  if (!xdr_am_mode3(xdrs, &objp->mode))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->nlink))
+    return FALSE;
+  if (!xdr_am_uid3(xdrs, &objp->uid))
+    return FALSE;
+  if (!xdr_am_gid3(xdrs, &objp->gid))
+    return FALSE;
+  if (!xdr_am_size3(xdrs, &objp->size))
+    return FALSE;
+  if (!xdr_am_size3(xdrs, &objp->used))
+    return FALSE;
+  if (!xdr_am_specdata3(xdrs, &objp->rdev))
+    return FALSE;
+  if (!xdr_uint64(xdrs, &objp->fsid))
+    return FALSE;
+  if (!xdr_am_fileid3(xdrs, &objp->fileid))
+    return FALSE;
+  if (!xdr_am_nfstime3(xdrs, &objp->atime))
+    return FALSE;
+  if (!xdr_am_nfstime3(xdrs, &objp->mtime))
+    return FALSE;
+  if (!xdr_am_nfstime3(xdrs, &objp->ctime))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_post_op_attr(XDR *xdrs, am_post_op_attr *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_post_op_attr:");
+
+  if (!xdr_bool(xdrs, &objp->attributes_follow))
+    return FALSE;
+  switch (objp->attributes_follow) {
+  case TRUE:
+    if (!xdr_am_fattr3(xdrs, &objp->am_post_op_attr_u.attributes))
+      return FALSE;
+    break;
+  case FALSE:
+    break;
+  default:
+    return FALSE;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_stable_how(XDR *xdrs, am_stable_how *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_stable_how:");
+
+  if (!xdr_enum(xdrs, (enum_t *) objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_offset3(XDR *xdrs, am_offset3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_offset3:");
+
+  if (!xdr_uint64(xdrs, objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_count3(XDR *xdrs, am_count3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_count3:");
+
+  if (!xdr_u_int(xdrs, objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_wcc_attr(XDR *xdrs, am_wcc_attr *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_wcc_attr:");
+
+  if (!xdr_am_size3(xdrs, &objp->size))
+    return FALSE;
+  if (!xdr_am_nfstime3(xdrs, &objp->mtime))
+    return FALSE;
+  if (!xdr_am_nfstime3(xdrs, &objp->ctime))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_pre_op_attr(XDR *xdrs, am_pre_op_attr *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, ":xdr_am_pre_op_attr");
+
+  if (!xdr_bool(xdrs, &objp->attributes_follow))
+    return FALSE;
+  switch (objp->attributes_follow) {
+  case TRUE:
+    if (!xdr_am_wcc_attr(xdrs, &objp->am_pre_op_attr_u.attributes))
+      return FALSE;
+    break;
+  case FALSE:
+    break;
+  default:
+    return FALSE;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_wcc_data(XDR *xdrs, am_wcc_data *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_wcc_data:");
+
+  if (!xdr_am_pre_op_attr(xdrs, &objp->before))
+    return FALSE;
+  if (!xdr_am_post_op_attr(xdrs, &objp->after))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_WRITE3args(XDR *xdrs, am_WRITE3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_WRITE3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->file))
+    return FALSE;
+  if (!xdr_am_offset3(xdrs, &objp->offset))
+    return FALSE;
+  if (!xdr_am_count3(xdrs, &objp->count))
+    return FALSE;
+  if (!xdr_am_stable_how(xdrs, &objp->stable))
+    return FALSE;
+  if (!xdr_bytes(xdrs, (char **)&objp->data.data_val,
+                (u_int *) &objp->data.data_len, ~0))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_writeverf3(XDR *xdrs, am_writeverf3 objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_writeverf3:");
+
+  if (!xdr_opaque(xdrs, objp, AM_NFS3_WRITEVERFSIZE))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_WRITE3resok(XDR *xdrs, am_WRITE3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_WRITE3resok:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->file_wcc))
+    return FALSE;
+  if (!xdr_am_count3(xdrs, &objp->count))
+    return FALSE;
+  if (!xdr_am_stable_how(xdrs, &objp->committed))
+    return FALSE;
+  if (!xdr_am_writeverf3(xdrs, objp->verf))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_WRITE3resfail(XDR *xdrs, am_WRITE3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_WRITE3resfail:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->file_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_WRITE3res(XDR *xdrs, am_WRITE3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_WRITE3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_WRITE3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_WRITE3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
 xdr_am_LOOKUP3args(XDR *xdrs, am_LOOKUP3args *objp)
 {
   if (amuDebug(D_XDRTRACE))
@@ -1006,7 +1381,6 @@
   return (TRUE);
 }
 
-
 bool_t
 xdr_am_LOOKUP3res(XDR *xdrs, am_LOOKUP3res *objp)
 {
@@ -1028,7 +1402,6 @@
   return (TRUE);
 }
 
-
 bool_t
 xdr_am_LOOKUP3resfail(XDR *xdrs, am_LOOKUP3resfail *objp)
 {
@@ -1035,18 +1408,11 @@
   if (amuDebug(D_XDRTRACE))
     plog(XLOG_DEBUG, "xdr_am_LOOKUP3resfail:");
 
-  /*
-   * 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))
+  if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes))
     return (FALSE);
-#endif
   return (TRUE);
 }
 
-
 bool_t
 xdr_am_LOOKUP3resok(XDR *xdrs, am_LOOKUP3resok *objp)
 {
@@ -1055,44 +1421,1656 @@
 
   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))
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
     return (FALSE);
-  if (!xdr_post_op_attr(xdrs, &objp->dir_attributes))
+  if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes))
     return (FALSE);
-#endif
   return (TRUE);
 }
 
+bool_t
+xdr_am_COMMIT3args(XDR *xdrs, am_COMMIT3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_COMMIT3args:");
 
+  if (!xdr_am_nfs_fh3(xdrs, &objp->file))
+    return FALSE;
+  if (!xdr_am_offset3(xdrs, &objp->offset))
+    return FALSE;
+  if (!xdr_am_count3(xdrs, &objp->count))
+    return FALSE;
+  return TRUE;
+}
+
 bool_t
-xdr_am_nfs_fh3(XDR *xdrs, am_nfs_fh3 *objp)
+xdr_am_COMMIT3resok(XDR *xdrs, am_COMMIT3resok *objp)
 {
   if (amuDebug(D_XDRTRACE))
-    plog(XLOG_DEBUG, "xdr_am_nfs_fh3:");
+    plog(XLOG_DEBUG, "xdr_am_COMMIT3resok:");
 
-  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);
+  if (!xdr_am_wcc_data(xdrs, &objp->file_wcc))
+    return FALSE;
+  if (!xdr_am_writeverf3(xdrs, objp->verf))
+    return FALSE;
+  return TRUE;
 }
 
+bool_t
+xdr_am_COMMIT3resfail(XDR *xdrs, am_COMMIT3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_COMMIT3resfail:");
 
+  if (!xdr_am_wcc_data(xdrs, &objp->file_wcc))
+    return FALSE;
+  return TRUE;
+}
+
 bool_t
-xdr_am_nfsstat3(XDR *xdrs, am_nfsstat3 *objp)
+xdr_am_COMMIT3res(XDR *xdrs, am_COMMIT3res *objp)
 {
   if (amuDebug(D_XDRTRACE))
-    plog(XLOG_DEBUG, "xdr_am_nfsstat3:");
+    plog(XLOG_DEBUG, "xdr_am_COMMIT3res:");
 
-  if (!xdr_enum(xdrs, (enum_t *)objp))
-    return (FALSE);
-  return (TRUE);
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_COMMIT3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_COMMIT3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
 }
-#endif /* not HAVE_FS_NFS3 */
+
+bool_t
+xdr_am_ACCESS3args(XDR *xdrs, am_ACCESS3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_ACCESS3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->object))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->access))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_ACCESS3resok(XDR *xdrs, am_ACCESS3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_ACCESS3resok:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->access))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_ACCESS3resfail(XDR *xdrs, am_ACCESS3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_ACCESS3resfail:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_ACCESS3res(XDR *xdrs, am_ACCESS3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_ACCESS3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_ACCESS3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_ACCESS3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_GETATTR3args(XDR *xdrs, am_GETATTR3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_GETATTR3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->object))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_GETATTR3resok(XDR *xdrs, am_GETATTR3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_GETATTR3resok:");
+
+  if (!xdr_am_fattr3(xdrs, &objp->obj_attributes))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_GETATTR3res(XDR *xdrs, am_GETATTR3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_GETATTR3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_GETATTR3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_time_how(XDR *xdrs, am_time_how *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_time_how:");
+
+  if (!xdr_enum(xdrs, (enum_t *) objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_set_mode3(XDR *xdrs, am_set_mode3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_set_mode3:");
+
+  if (!xdr_bool(xdrs, &objp->set_it))
+    return FALSE;
+  switch (objp->set_it) {
+  case TRUE:
+    if (!xdr_am_mode3(xdrs, &objp->am_set_mode3_u.mode))
+      return FALSE;
+    break;
+  default:
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_set_uid3(XDR *xdrs, am_set_uid3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_set_uid3:");
+
+  if (!xdr_bool(xdrs, &objp->set_it))
+    return FALSE;
+  switch (objp->set_it) {
+  case TRUE:
+    if (!xdr_am_uid3(xdrs, &objp->am_set_uid3_u.uid))
+      return FALSE;
+    break;
+  default:
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_set_gid3(XDR *xdrs, am_set_gid3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_set_gid3:");
+
+  if (!xdr_bool(xdrs, &objp->set_it))
+    return FALSE;
+  switch (objp->set_it) {
+  case TRUE:
+    if (!xdr_am_gid3(xdrs, &objp->am_set_gid3_u.gid))
+      return FALSE;
+    break;
+  default:
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_set_size3(XDR *xdrs, am_set_size3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_set_size3:");
+
+  if (!xdr_bool(xdrs, &objp->set_it))
+    return FALSE;
+  switch (objp->set_it) {
+  case TRUE:
+    if (!xdr_am_size3(xdrs, &objp->am_set_size3_u.size))
+      return FALSE;
+    break;
+  default:
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_set_atime(XDR *xdrs, am_set_atime *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_set_atime:");
+
+  if (!xdr_am_time_how(xdrs, &objp->set_it))
+    return FALSE;
+  switch (objp->set_it) {
+  case AM_SET_TO_CLIENT_TIME:
+    if (!xdr_am_nfstime3(xdrs, &objp->am_set_atime_u.atime))
+      return FALSE;
+    break;
+  default:
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_set_mtime(XDR *xdrs, am_set_mtime *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_set_mtime:");
+
+  if (!xdr_am_time_how(xdrs, &objp->set_it))
+    return FALSE;
+  switch (objp->set_it) {
+  case AM_SET_TO_CLIENT_TIME:
+    if (!xdr_am_nfstime3(xdrs, &objp->am_set_mtime_u.mtime))
+      return FALSE;
+    break;
+  default:
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_sattr3(XDR *xdrs, am_sattr3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_sattr3:");
+
+  if (!xdr_am_set_mode3(xdrs, &objp->mode))
+    return FALSE;
+  if (!xdr_am_set_uid3(xdrs, &objp->uid))
+    return FALSE;
+  if (!xdr_am_set_gid3(xdrs, &objp->gid))
+    return FALSE;
+  if (!xdr_am_set_size3(xdrs, &objp->size))
+     return FALSE;
+  if (!xdr_am_set_atime(xdrs, &objp->atime))
+    return FALSE;
+  if (!xdr_am_set_mtime(xdrs, &objp->mtime))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_createmode3(XDR *xdrs, am_createmode3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_createmode3:");
+
+  if (!xdr_enum(xdrs, (enum_t *) objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_createverf3(XDR *xdrs, am_createverf3 objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_createverf3:");
+
+  if (!xdr_opaque(xdrs, objp, AM_NFS3_CREATEVERFSIZE))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_createhow3(XDR *xdrs, am_createhow3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_createhow3:");
+
+   if (!xdr_am_createmode3(xdrs, &objp->mode))
+     return FALSE;
+  switch (objp->mode) {
+  case AM_UNCHECKED:
+    if (!xdr_am_sattr3(xdrs, &objp->am_createhow3_u.obj_attributes))
+      return FALSE;
+    break;
+  case AM_GUARDED:
+    if (!xdr_am_sattr3(xdrs, &objp->am_createhow3_u.g_obj_attributes))
+      return FALSE;
+    break;
+  case AM_EXCLUSIVE:
+    if (!xdr_am_createverf3(xdrs, objp->am_createhow3_u.verf))
+      return FALSE;
+    break;
+  default:
+    return FALSE;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_CREATE3args(XDR *xdrs, am_CREATE3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_CREATE3args:");
+
+  if (!xdr_am_diropargs3(xdrs, &objp->where))
+    return FALSE;
+  if (!xdr_am_createhow3(xdrs, &objp->how))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_post_op_fh3(XDR *xdrs, am_post_op_fh3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_post_op_fh3:");
+
+  if (!xdr_bool(xdrs, &objp->handle_follows))
+    return FALSE;
+  switch (objp->handle_follows) {
+  case TRUE:
+    if (!xdr_am_nfs_fh3(xdrs, &objp->am_post_op_fh3_u.handle))
+      return FALSE;
+    break;
+  case FALSE:
+    break;
+  default:
+    return FALSE;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_CREATE3resok(XDR *xdrs, am_CREATE3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_CREATE3resok:");
+
+  if (!xdr_am_post_op_fh3(xdrs, &objp->obj))
+    return FALSE;
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_CREATE3resfail(XDR *xdrs, am_CREATE3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_CREATE3resfail:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_CREATE3res(XDR *xdrs, am_CREATE3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_CREATE3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_CREATE3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_CREATE3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_REMOVE3args(XDR *xdrs, am_REMOVE3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_REMOVE3args:");
+
+  if (!xdr_am_diropargs3(xdrs, &objp->object))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_REMOVE3resok(XDR *xdrs, am_REMOVE3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_REMOVE3resok:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_REMOVE3resfail(XDR *xdrs, am_REMOVE3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_REMOVE3resfail:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_REMOVE3res(XDR *xdrs, am_REMOVE3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_REMOVE3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_REMOVE3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_REMOVE3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_READ3args(XDR *xdrs, am_READ3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READ3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->file))
+    return FALSE;
+  if (!xdr_am_offset3(xdrs, &objp->offset))
+    return FALSE;
+  if (!xdr_am_count3(xdrs, &objp->count))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READ3resok(XDR *xdrs, am_READ3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READ3resok:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->file_attributes))
+    return FALSE;
+  if (!xdr_am_count3(xdrs, &objp->count))
+    return FALSE;
+  if (!xdr_bool(xdrs, &objp->eof))
+    return FALSE;
+  if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READ3resfail(XDR *xdrs, am_READ3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READ3resfail:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->file_attributes))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READ3res(XDR *xdrs, am_READ3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READ3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_READ3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_READ3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_FSINFO3args(XDR *xdrs, am_FSINFO3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_FSINFO3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->fsroot))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_FSINFO3resok(XDR *xdrs, am_FSINFO3resok *objp)
+{
+  register int32_t *buf;
+
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_FSINFO3resok:");
+
+  if (xdrs->x_op == XDR_ENCODE) {
+    if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+      return FALSE;
+    buf = XDR_INLINE(xdrs, 7 * BYTES_PER_XDR_UNIT);
+    if (buf == NULL) {
+      if (!xdr_u_int(xdrs, &objp->rtmax))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->rtpref))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->rtmult))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->wtmax))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->wtpref))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->wtmult))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->dtpref))
+        return FALSE;
+    } else {
+      IXDR_PUT_U_LONG(buf, objp->rtmax);
+      IXDR_PUT_U_LONG(buf, objp->rtpref);
+      IXDR_PUT_U_LONG(buf, objp->rtmult);
+      IXDR_PUT_U_LONG(buf, objp->wtmax);
+      IXDR_PUT_U_LONG(buf, objp->wtpref);
+      IXDR_PUT_U_LONG(buf, objp->wtmult);
+      IXDR_PUT_U_LONG(buf, objp->dtpref);
+    }
+    if (!xdr_am_size3(xdrs, &objp->maxfilesize))
+      return FALSE;
+    if (!xdr_am_nfstime3(xdrs, &objp->time_delta))
+      return FALSE;
+    if (!xdr_u_int(xdrs, &objp->properties))
+      return FALSE;
+    return TRUE;
+  } else if (xdrs->x_op == XDR_DECODE) {
+    if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+      return FALSE;
+    buf = XDR_INLINE(xdrs, 7 * BYTES_PER_XDR_UNIT);
+    if (buf == NULL) {
+      if (!xdr_u_int (xdrs, &objp->rtmax))
+        return FALSE;
+      if (!xdr_u_int (xdrs, &objp->rtpref))
+        return FALSE;
+      if (!xdr_u_int (xdrs, &objp->rtmult))
+        return FALSE;
+      if (!xdr_u_int (xdrs, &objp->wtmax))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->wtpref))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->wtmult))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->dtpref))
+        return FALSE;
+    } else {
+      objp->rtmax = IXDR_GET_U_LONG(buf);
+      objp->rtpref = IXDR_GET_U_LONG(buf);
+      objp->rtmult = IXDR_GET_U_LONG(buf);
+      objp->wtmax = IXDR_GET_U_LONG(buf);
+      objp->wtpref = IXDR_GET_U_LONG(buf);
+      objp->wtmult = IXDR_GET_U_LONG(buf);
+      objp->dtpref = IXDR_GET_U_LONG(buf);
+    }
+    if (!xdr_am_size3(xdrs, &objp->maxfilesize))
+      return FALSE;
+    if (!xdr_am_nfstime3(xdrs, &objp->time_delta))
+      return FALSE;
+    if (!xdr_u_int(xdrs, &objp->properties))
+      return FALSE;
+    return TRUE;
+  }
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->rtmax))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->rtpref))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->rtmult))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->wtmax))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->wtpref))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->wtmult))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->dtpref))
+   return FALSE;
+  if (!xdr_am_size3(xdrs, &objp->maxfilesize))
+    return FALSE;
+  if (!xdr_am_nfstime3(xdrs, &objp->time_delta))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->properties))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_FSINFO3resfail(XDR *xdrs, am_FSINFO3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_FSINFO3resfail:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_FSINFO3res(XDR *xdrs, am_FSINFO3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_FSINFO3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_FSINFO3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_FSINFO3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_FSSTAT3args(XDR *xdrs, am_FSSTAT3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_FSSTAT3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->fsroot))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_FSSTAT3resok(XDR *xdrs, am_FSSTAT3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_FSSTAT3resok:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  if (!xdr_am_size3(xdrs, &objp->tbytes))
+    return FALSE;
+  if (!xdr_am_size3(xdrs, &objp->fbytes))
+    return FALSE;
+  if (!xdr_am_size3(xdrs, &objp->abytes))
+    return FALSE;
+  if (!xdr_am_size3(xdrs, &objp->tfiles))
+    return FALSE;
+  if (!xdr_am_size3(xdrs, &objp->ffiles))
+    return FALSE;
+  if (!xdr_am_size3(xdrs, &objp->afiles))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->invarsec))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_FSSTAT3resfail(XDR *xdrs, am_FSSTAT3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_FSSTAT3resfail:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_FSSTAT3res(XDR *xdrs, am_FSSTAT3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_FSSTAT3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_FSSTAT3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_FSSTAT3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_PATHCONF3args(XDR *xdrs, am_PATHCONF3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_PATHCONF3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->object))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_PATHCONF3resok(XDR *xdrs, am_PATHCONF3resok *objp)
+{
+  register int32_t *buf;
+
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_PATHCONF3resok:");
+
+  if (xdrs->x_op == XDR_ENCODE) {
+    if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+      return FALSE;
+    buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
+    if (buf == NULL) {
+      if (!xdr_u_int(xdrs, &objp->linkmax))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->name_max))
+        return FALSE;
+      if (!xdr_bool(xdrs, &objp->no_trunc))
+        return FALSE;
+      if (!xdr_bool(xdrs, &objp->chown_restricted))
+        return FALSE;
+      if (!xdr_bool(xdrs, &objp->case_insensitive))
+        return FALSE;
+      if (!xdr_bool(xdrs, &objp->case_preserving))
+        return FALSE;
+    } else {
+      IXDR_PUT_U_LONG(buf, objp->linkmax);
+      IXDR_PUT_U_LONG(buf, objp->name_max);
+      IXDR_PUT_BOOL(buf, objp->no_trunc);
+      IXDR_PUT_BOOL(buf, objp->chown_restricted);
+      IXDR_PUT_BOOL(buf, objp->case_insensitive);
+      IXDR_PUT_BOOL(buf, objp->case_preserving);
+    }
+    return TRUE;
+  } else if (xdrs->x_op == XDR_DECODE) {
+    if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+      return FALSE;
+    buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
+    if (buf == NULL) {
+      if (!xdr_u_int(xdrs, &objp->linkmax))
+        return FALSE;
+      if (!xdr_u_int(xdrs, &objp->name_max))
+        return FALSE;
+      if (!xdr_bool(xdrs, &objp->no_trunc))
+        return FALSE;
+      if (!xdr_bool(xdrs, &objp->chown_restricted))
+        return FALSE;
+      if (!xdr_bool(xdrs, &objp->case_insensitive))
+        return FALSE;
+      if (!xdr_bool(xdrs, &objp->case_preserving))
+        return FALSE;
+    } else {
+      objp->linkmax = IXDR_GET_U_LONG(buf);
+      objp->name_max = IXDR_GET_U_LONG(buf);
+      objp->no_trunc = IXDR_GET_BOOL(buf);
+      objp->chown_restricted = IXDR_GET_BOOL(buf);
+      objp->case_insensitive = IXDR_GET_BOOL(buf);
+      objp->case_preserving = IXDR_GET_BOOL(buf);
+    }
+    return TRUE;
+  }
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->linkmax))
+    return FALSE;
+  if (!xdr_u_int(xdrs, &objp->name_max))
+    return FALSE;
+  if (!xdr_bool(xdrs, &objp->no_trunc))
+    return FALSE;
+  if (!xdr_bool(xdrs, &objp->chown_restricted))
+    return FALSE;
+  if (!xdr_bool(xdrs, &objp->case_insensitive))
+    return FALSE;
+  if (!xdr_bool(xdrs, &objp->case_preserving))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_PATHCONF3resfail(XDR *xdrs, am_PATHCONF3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_PATHCONF3resfail:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_PATHCONF3res(XDR *xdrs, am_PATHCONF3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_PATHCONF3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_PATHCONF3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_PATHCONF3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_nfspath3(XDR *xdrs, am_nfspath3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_nfspath3:");
+
+  if (!xdr_string(xdrs, objp, ~0))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_symlinkdata3(XDR *xdrs, am_symlinkdata3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_symlinkdata3:");
+
+  if (!xdr_am_sattr3(xdrs, &objp->symlink_attributes))
+    return FALSE;
+  if (!xdr_am_nfspath3(xdrs, &objp->symlink_data))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_SYMLINK3args(XDR *xdrs, am_SYMLINK3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_SYMLINK3args:");
+
+  if (!xdr_am_diropargs3(xdrs, &objp->where))
+    return FALSE;
+  if (!xdr_am_symlinkdata3(xdrs, &objp->symlink))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_SYMLINK3resok(XDR *xdrs, am_SYMLINK3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_SYMLINK3resok:");
+
+  if (!xdr_am_post_op_fh3(xdrs, &objp->obj))
+    return FALSE;
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_SYMLINK3resfail(XDR *xdrs, am_SYMLINK3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_SYMLINK3resfail:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_SYMLINK3res(XDR *xdrs, am_SYMLINK3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_SYMLINK3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_SYMLINK3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_SYMLINK3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_READLINK3args(XDR *xdrs, am_READLINK3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READLINK3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->symlink))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READLINK3resok(XDR *xdrs, am_READLINK3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READLINK3resok:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->symlink_attributes))
+    return FALSE;
+  if (!xdr_am_nfspath3(xdrs, &objp->data))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READLINK3resfail(XDR *xdrs, am_READLINK3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READLINK3resfail:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->symlink_attributes))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READLINK3res(XDR *xdrs, am_READLINK3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READLINK3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_READLINK3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_READLINK3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_devicedata3(XDR *xdrs, am_devicedata3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_devicedata3:");
+
+  if (!xdr_am_sattr3(xdrs, &objp->dev_attributes))
+    return FALSE;
+  if (!xdr_am_specdata3(xdrs, &objp->spec))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_mknoddata3(XDR *xdrs, am_mknoddata3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_mknoddata3:");
+
+  if (!xdr_am_ftype3(xdrs, &objp->type))
+    return FALSE;
+  switch (objp->type) {
+  case AM_NF3CHR:
+    if (!xdr_am_devicedata3(xdrs, &objp->am_mknoddata3_u.chr_device))
+      return FALSE;
+    break;
+  case AM_NF3BLK:
+    if (!xdr_am_devicedata3(xdrs, &objp->am_mknoddata3_u.blk_device))
+      return FALSE;
+    break;
+  case AM_NF3SOCK:
+    if (!xdr_am_sattr3(xdrs, &objp->am_mknoddata3_u.sock_attributes))
+      return FALSE;
+    break;
+  case AM_NF3FIFO:
+    if (!xdr_am_sattr3(xdrs, &objp->am_mknoddata3_u.pipe_attributes))
+      return FALSE;
+    break;
+  default:
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_MKNOD3args(XDR *xdrs, am_MKNOD3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_MKNOD3args:");
+
+  if (!xdr_am_diropargs3(xdrs, &objp->where))
+    return FALSE;
+  if (!xdr_am_mknoddata3(xdrs, &objp->what))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_MKNOD3resok(XDR *xdrs, am_MKNOD3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_MKNOD3resok:");
+
+  if (!xdr_am_post_op_fh3(xdrs, &objp->obj))
+    return FALSE;
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_MKNOD3resfail(XDR *xdrs, am_MKNOD3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_MKNOD3resfail:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_MKNOD3res(XDR *xdrs, am_MKNOD3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, ":");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_MKNOD3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_MKNOD3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_MKDIR3args(XDR *xdrs, am_MKDIR3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, ":");
+
+  if (!xdr_am_diropargs3(xdrs, &objp->where))
+    return FALSE;
+  if (!xdr_am_sattr3(xdrs, &objp->attributes))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_MKDIR3resok(XDR *xdrs, am_MKDIR3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_MKDIR3resok:");
+
+  if (!xdr_am_post_op_fh3(xdrs, &objp->obj))
+    return FALSE;
+  if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes))
+    return FALSE;
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_MKDIR3resfail(XDR *xdrs, am_MKDIR3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_MKDIR3resfail:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_MKDIR3res(XDR *xdrs, am_MKDIR3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_MKDIR3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_MKDIR3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_MKDIR3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_RMDIR3args(XDR *xdrs, am_RMDIR3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_RMDIR3args:");
+
+  if (!xdr_am_diropargs3(xdrs, &objp->object))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_RMDIR3resok(XDR *xdrs, am_RMDIR3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_RMDIR3resok:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_RMDIR3resfail(XDR *xdrs, am_RMDIR3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_RMDIR3resfail:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_RMDIR3res(XDR *xdrs, am_RMDIR3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_RMDIR3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_RMDIR3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_RMDIR3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_RENAME3args(XDR *xdrs, am_RENAME3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_RENAME3args:");
+
+  if (!xdr_am_diropargs3(xdrs, &objp->from))
+    return FALSE;
+  if (!xdr_am_diropargs3(xdrs, &objp->to))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_RENAME3resok(XDR *xdrs, am_RENAME3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_RENAME3resok:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->fromdir_wcc))
+    return FALSE;
+  if (!xdr_am_wcc_data(xdrs, &objp->todir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_RENAME3resfail(XDR *xdrs, am_RENAME3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_RENAME3resfail:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->fromdir_wcc))
+    return FALSE;
+  if (!xdr_am_wcc_data(xdrs, &objp->todir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_RENAME3res(XDR *xdrs, am_RENAME3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_RENAME3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_RENAME3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_RENAME3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_READDIRPLUS3args(XDR *xdrs, am_READDIRPLUS3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READDIRPLUS3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->dir))
+    return FALSE;
+  if (!xdr_am_cookie3(xdrs, &objp->cookie))
+    return FALSE;
+  if (!xdr_am_cookieverf3(xdrs, objp->cookieverf))
+    return FALSE;
+  if (!xdr_am_count3(xdrs, &objp->dircount))
+    return FALSE;
+  if (!xdr_am_count3(xdrs, &objp->maxcount))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_entryplus3(XDR *xdrs, am_entryplus3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_entryplus3:");
+
+   if (!xdr_am_fileid3(xdrs, &objp->fileid))
+     return FALSE;
+   if (!xdr_am_filename3(xdrs, &objp->name))
+     return FALSE;
+   if (!xdr_am_cookie3(xdrs, &objp->cookie))
+     return FALSE;
+   if (!xdr_am_post_op_attr(xdrs, &objp->name_attributes))
+     return FALSE;
+   if (!xdr_am_post_op_fh3(xdrs, &objp->name_handle))
+     return FALSE;
+   if (!xdr_pointer(xdrs, (char **)&objp->nextentry,
+                   sizeof(am_entryplus3), (xdrproc_t) xdr_am_entryplus3))
+     return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_dirlistplus3(XDR *xdrs, am_dirlistplus3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_dirlistplus3:");
+
+  if (!xdr_pointer(xdrs, (char **)&objp->entries,
+                   sizeof(am_entryplus3), (xdrproc_t) xdr_am_entryplus3))
+    return FALSE;
+  if (!xdr_bool(xdrs, &objp->eof))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READDIRPLUS3resok(XDR *xdrs, am_READDIRPLUS3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READDIRPLUS3resok:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes))
+    return FALSE;
+  if (!xdr_am_cookieverf3(xdrs, objp->cookieverf))
+    return FALSE;
+  if (!xdr_am_dirlistplus3(xdrs, &objp->reply))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READDIRPLUS3resfail(XDR *xdrs, am_READDIRPLUS3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READDIRPLUS3resfail:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READDIRPLUS3res(XDR *xdrs, am_READDIRPLUS3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READDIRPLUS3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_READDIRPLUS3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_READDIRPLUS3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_READDIR3args(XDR *xdrs, am_READDIR3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READDIR3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->dir))
+    return FALSE;
+  if (!xdr_am_cookie3(xdrs, &objp->cookie))
+    return FALSE;
+  if (!xdr_am_cookieverf3(xdrs, objp->cookieverf))
+    return FALSE;
+  if (!xdr_am_count3(xdrs, &objp->count))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_entry3(XDR *xdrs, am_entry3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_entry3:");
+
+  if (!xdr_am_fileid3(xdrs, &objp->fileid))
+    return FALSE;
+  if (!xdr_am_filename3(xdrs, &objp->name))
+    return FALSE;
+  if (!xdr_am_cookie3(xdrs, &objp->cookie))
+    return FALSE;
+  if (!xdr_pointer(xdrs, (char **)&objp->nextentry,
+                   sizeof(am_entry3), (xdrproc_t) xdr_am_entry3))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_dirlist3(XDR *xdrs, am_dirlist3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_dirlist3:");
+
+  if (!xdr_pointer(xdrs, (char **)&objp->entries,
+                   sizeof(am_entry3), (xdrproc_t) xdr_am_entry3))
+    return FALSE;
+  if (!xdr_bool (xdrs, &objp->eof))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READDIR3resok(XDR *xdrs, am_READDIR3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READDIR3resok:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes))
+    return FALSE;
+  if (!xdr_am_cookieverf3(xdrs, objp->cookieverf))
+    return FALSE;
+  if (!xdr_am_dirlist3(xdrs, &objp->reply))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READDIR3resfail(XDR *xdrs, am_READDIR3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READDIR3resfail:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_READDIR3res(XDR *xdrs, am_READDIR3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_READDIR3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_READDIR3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_READDIR3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_LINK3args(XDR *xdrs, am_LINK3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_LINK3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->file))
+    return FALSE;
+  if (!xdr_am_diropargs3(xdrs, &objp->link))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_LINK3resok(XDR *xdrs, am_LINK3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_LINK3resok:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->file_attributes))
+    return FALSE;
+  if (!xdr_am_wcc_data(xdrs, &objp->linkdir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_LINK3resfail(XDR *xdrs, am_LINK3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_LINK3resfail:");
+
+  if (!xdr_am_post_op_attr(xdrs, &objp->file_attributes))
+    return FALSE;
+  if (!xdr_am_wcc_data(xdrs, &objp->linkdir_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_LINK3res(XDR *xdrs, am_LINK3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_LINK3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_LINK3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_LINK3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_sattrguard3(XDR *xdrs, am_sattrguard3 *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_sattrguard3:");
+
+  if (!xdr_bool(xdrs, &objp->check))
+    return FALSE;
+  switch (objp->check) {
+  case TRUE:
+    if (!xdr_am_nfstime3(xdrs, &objp->am_sattrguard3_u.obj_ctime))
+      return FALSE;
+    break;
+  case FALSE:
+    break;
+  default:
+    return FALSE;
+  }
+  return TRUE;
+}
+
+bool_t
+xdr_am_SETATTR3args(XDR *xdrs, am_SETATTR3args *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_SETATTR3args:");
+
+  if (!xdr_am_nfs_fh3(xdrs, &objp->object))
+    return FALSE;
+  if (!xdr_am_sattr3(xdrs, &objp->new_attributes))
+    return FALSE;
+  if (!xdr_am_sattrguard3(xdrs, &objp->guard))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_SETATTR3resok(XDR *xdrs, am_SETATTR3resok *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_SETATTR3resok:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->obj_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_SETATTR3resfail(XDR *xdrs, am_SETATTR3resfail *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_SETATTR3resfail:");
+
+  if (!xdr_am_wcc_data(xdrs, &objp->obj_wcc))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_am_SETATTR3res(XDR *xdrs, am_SETATTR3res *objp)
+{
+  if (amuDebug(D_XDRTRACE))
+    plog(XLOG_DEBUG, "xdr_am_SETATTR3res:");
+
+  if (!xdr_am_nfsstat3(xdrs, &objp->status))
+    return FALSE;
+  switch (objp->status) {
+  case AM_NFS3_OK:
+    if (!xdr_am_SETATTR3resok(xdrs, &objp->res_u.ok))
+      return FALSE;
+    break;
+  default:
+    if (!xdr_am_SETATTR3resfail(xdrs, &objp->res_u.fail))
+      return FALSE;
+    break;
+  }
+  return TRUE;
+}
+#endif /* HAVE_FS_NFS3 */

Modified: trunk/contrib/amd/libamu/xutil.c
===================================================================
--- trunk/contrib/amd/libamu/xutil.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/libamu/xutil.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -63,14 +59,13 @@
 pid_t am_mypid = -1;		/* process ID */
 serv_state amd_state;		/* amd's state */
 int foreground = 1;		/* 1 == this is the top-level server */
-int debug_flags = 0;
+u_int debug_flags = D_CONTROL;	/* set regardless if compiled with debugging */
 
 #ifdef HAVE_SYSLOG
 int syslogging;
 #endif /* HAVE_SYSLOG */
-int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS;
-int xlog_level_init = ~0;
-static int amd_program_number = AMQ_PROGRAM;
+static u_int xlog_level = XLOG_DEFAULT;
+static u_long amd_program_number = AMQ_PROGRAM;
 
 #ifdef DEBUG_MEM
 # if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY)
@@ -92,23 +87,23 @@
 struct opt_tab dbg_opt[] =
 {
   {"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 */
+  {"defaults", D_DEFAULT},	/* Default options */
+  {"test", D_TEST},		/* Full debug - no daemon, no fork, no amq, local mtab */
+  {"amq", D_AMQ},		/* Register for AMQ program */
+  {"daemon", D_DAEMON},		/* Enter daemon mode */
+  {"fork", D_FORK},		/* Fork server (hlfsd only) */
   {"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},
+  {"info", D_INFO},		/* info service specific debugging (hesiod, nis, etc) */
   {"mem", D_MEM},		/* Trace memory allocations */
   {"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 - no daemon, no amq, local mtab */
   {"trace", D_TRACE},		/* Protocol trace */
   {"xdrtrace", D_XDRTRACE},	/* Trace xdr routines */
-  {0, 0}
+  {NULL, 0}
 };
 #endif /* DEBUG */
 
@@ -118,6 +113,7 @@
 struct opt_tab xlog_opt[] =
 {
   {"all", XLOG_ALL},		/* All messages */
+  {"defaults", XLOG_DEFAULT},	/* Default messages */
 #ifdef DEBUG
   {"debug", XLOG_DEBUG},	/* Debug messages */
 #endif /* DEBUG */		/* DEBUG */
@@ -129,7 +125,7 @@
   {"user", XLOG_USER},		/* Non-fatal user errors */
   {"warn", XLOG_WARNING},	/* Warnings */
   {"warning", XLOG_WARNING},	/* Warnings */
-  {0, 0}
+  {NULL, 0}
 };
 
 
@@ -150,7 +146,7 @@
 void
 am_set_hostname(char *hn)
 {
-  xstrlcpy(am_hostname, hn, MAXHOSTNAMELEN);
+  xstrlcpy(am_hostname, hn, sizeof(am_hostname));
 }
 
 
@@ -295,17 +291,23 @@
   const char *p;
   char *q;
   int error = errno;
-  int len = 0;
+  size_t len = 0, l;
 
-  for (p = f, q = e; (*q = *p) && (size_t) len < maxlen; len++, q++, p++) {
+  *e = '\0';
+  for (p = f, q = e; len < maxlen && (*q = *p); len++, q++, p++) {
     if (p[0] == '%' && p[1] == 'm') {
-      xstrlcpy(q, strerror(error), maxlen);
-      len += strlen(q) - 1;
-      q += strlen(q) - 1;
+      if (len >= maxlen)
+	break;
+      xstrlcpy(q, strerror(error), maxlen - len);
+      l = strlen(q);
+      if (l != 0)
+	  l--;
+      len += l;
+      q += l;
       p++;
     }
   }
-  e[maxlen-1] = '\0';		/* null terminate, to be sure */
+  e[maxlen - 1] = '\0';		/* null terminate, to be sure */
   return e;
 }
 
@@ -317,7 +319,7 @@
 show_time_host_and_name(int lvl)
 {
   static time_t last_t = 0;
-  static char *last_ctime = 0;
+  static char *last_ctime = NULL;
   time_t t;
 #if defined(HAVE_CLOCK_GETTIME) && defined(DEBUG)
   struct timespec ts;
@@ -390,7 +392,30 @@
 int
 debug_option(char *opt)
 {
-  return cmdoption(opt, dbg_opt, &debug_flags);
+  u_int dl = debug_flags;
+  static int initialized_debug_flags = 0;
+  int rc = cmdoption(opt, dbg_opt, &dl);
+
+  if (rc)		    /* if got any error, don't update debug flags */
+    return EINVAL;
+
+  /*
+   * If we already initialized the debugging flags once (via amd.conf), then
+   * don't allow "immutable" flags to be changed again (via amq -D), because
+   * they could mess Amd's state and only make sense to be set once when Amd
+   * starts.
+   */
+  if (initialized_debug_flags &&
+      debug_flags != 0 &&
+      (dl & D_IMMUTABLE) != (debug_flags & D_IMMUTABLE)) {
+    plog(XLOG_ERROR, "cannot change immutable debug flags");
+    /* undo any attempted change to an immutable flag */
+    dl = (dl & ~D_IMMUTABLE) | (debug_flags & D_IMMUTABLE);
+  }
+  initialized_debug_flags = 1;
+  debug_flags = dl;
+
+  return rc;
 }
 
 
@@ -397,8 +422,21 @@
 void
 dplog(const char *fmt, ...)
 {
+#ifdef HAVE_SIGACTION
+  sigset_t old, chld;
+#else /* not HAVE_SIGACTION */
+  int mask;
+#endif /* not HAVE_SIGACTION */
   va_list ap;
 
+#ifdef HAVE_SIGACTION
+  sigemptyset(&chld);
+  sigaddset(&chld, SIGCHLD);
+#else /* not HAVE_SIGACTION */
+  mask = sigblock(sigmask(SIGCHLD));
+#endif /* not HAVE_SIGACTION */
+
+  sigprocmask(SIG_BLOCK, &chld, &old);
   if (!logfp)
     logfp = stderr;		/* initialize before possible first use */
 
@@ -405,6 +443,12 @@
   va_start(ap, fmt);
   real_plog(XLOG_DEBUG, fmt, ap);
   va_end(ap);
+
+#ifdef HAVE_SIGACTION
+  sigprocmask(SIG_SETMASK, &old, NULL);
+#else /* not HAVE_SIGACTION */
+  mask = sigblock(sigmask(SIGCHLD));
+#endif /* not HAVE_SIGACTION */
 }
 #endif /* DEBUG */
 
@@ -412,8 +456,21 @@
 void
 plog(int lvl, const char *fmt, ...)
 {
+#ifdef HAVE_SIGACTION
+  sigset_t old, chld;
+#else /* not HAVE_SIGACTION */
+  int mask;
+#endif /* not HAVE_SIGACTION */
   va_list ap;
 
+#ifdef HAVE_SIGACTION
+  sigemptyset(&chld);
+  sigaddset(&chld, SIGCHLD);
+  sigprocmask(SIG_BLOCK, &chld, &old);
+#else /* not HAVE_SIGACTION */
+  mask = sigblock(sigmask(SIGCHLD));
+#endif /* not HAVE_SIGACTION */
+
   if (!logfp)
     logfp = stderr;		/* initialize before possible first use */
 
@@ -420,6 +477,12 @@
   va_start(ap, fmt);
   real_plog(lvl, fmt, ap);
   va_end(ap);
+
+#ifdef HAVE_SIGACTION
+  sigprocmask(SIG_SETMASK, &old, NULL);
+#else /* not HAVE_SIGACTION */
+  sigsetmask(mask);
+#endif /* not HAVE_SIGACTION */
 }
 
 
@@ -497,11 +560,11 @@
   switch (last_count) {
   case 0:			/* never printed at all */
     last_count = 1;
-    if (strlcpy(last_msg, msg, 1024) >= 1024) /* don't use xstrlcpy here (recursive!) */
+    if (strlcpy(last_msg, msg, sizeof(last_msg)) >= sizeof(last_msg)) /* 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);
+    __IGNORE(fwrite(msg, ptr - msg, 1, logfp));
     fflush(logfp);
     break;
 
@@ -510,11 +573,11 @@
       last_count++;
     } else {			/* last msg printed once, new one differs */
       /* last_count remains at 1 */
-      if (strlcpy(last_msg, msg, 1024) >= 1024) /* don't use xstrlcpy here (recursive!) */
+      if (strlcpy(last_msg, msg, sizeof(last_msg)) >= sizeof(last_msg)) /* 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);
+      __IGNORE(fwrite(msg, ptr - msg, 1, logfp));
       fflush(logfp);
     }
     break;
@@ -527,7 +590,7 @@
     show_time_host_and_name(last_lvl);
     xsnprintf(last_msg, sizeof(last_msg),
 	      "last message repeated %d times\n", last_count);
-    fwrite(last_msg, strlen(last_msg), 1, logfp);
+    __IGNORE(fwrite(last_msg, strlen(last_msg), 1, logfp));
     fflush(logfp);
     last_count = 0;		/* start from scratch */
     break;
@@ -539,13 +602,13 @@
       show_time_host_and_name(last_lvl);
       xsnprintf(last_msg, sizeof(last_msg),
 		"last message repeated %d times\n", last_count);
-      fwrite(last_msg, strlen(last_msg), 1, logfp);
+      __IGNORE(fwrite(last_msg, strlen(last_msg), 1, logfp));
       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 */
-      fwrite(msg, ptr - msg, 1, logfp);
+      __IGNORE(fwrite(msg, ptr - msg, 1, logfp));
       fflush(logfp);
     }
     break;
@@ -573,7 +636,7 @@
 
 
 int
-cmdoption(char *s, struct opt_tab *optb, int *flags)
+cmdoption(char *s, struct opt_tab *optb, u_int *flags)
 {
   char *p = s;
   int errs = 0;
@@ -581,7 +644,7 @@
   while (p && *p) {
     int neg;
     char *opt;
-    struct opt_tab *dp, *dpn = 0;
+    struct opt_tab *dp, *dpn = NULL;
 
     s = p;
     p = strchr(p, ',');
@@ -624,7 +687,7 @@
        * This will log to stderr when parsing the command line
        * since any -l option will not yet have taken effect.
        */
-      plog(XLOG_USER, "option \"%s\" not recognized", s);
+      plog(XLOG_ERROR, "option \"%s\" not recognized", s);
       errs++;
     }
 
@@ -645,22 +708,22 @@
 int
 switch_option(char *opt)
 {
-  int xl = xlog_level;
+  u_int xl = xlog_level;
   int rc = cmdoption(opt, xlog_opt, &xl);
 
-  if (rc) {
-    rc = EINVAL;
-  } else {
-    /*
-     * Keep track of initial log level, and
-     * don't allow options to be turned off.
-     */
-    if (xlog_level_init == ~0)
-      xlog_level_init = xl;
-    else
-      xl |= xlog_level_init;
-    xlog_level = xl;
+  if (rc)			/* if got any error, don't update flags */
+    return EINVAL;
+
+  /*
+   * Don't allow "mandatory" flags to be turned off, because
+   * we must always be able to report on flag re/setting errors.
+   */
+  if ((xl & XLOG_MANDATORY) != XLOG_MANDATORY) {
+    plog(XLOG_ERROR, "cannot turn off mandatory logging options");
+    xl |= XLOG_MANDATORY;
   }
+  if (xlog_level != xl)
+    xlog_level = xl;		/* set new flags */
   return rc;
 }
 
@@ -801,7 +864,7 @@
     } else {			/* regular log file */
       (void) umask(old_umask);
       if (truncate_log)
-	truncate(logfile, 0);
+	__IGNORE(truncate(logfile, 0));
       new_logfp = fopen(logfile, "a");
       umask(0);
     }
@@ -834,7 +897,8 @@
 void
 unregister_amq(void)
 {
-  if (!amuDebug(D_AMQ)) {
+
+  if (amuDebug(D_AMQ)) {
     /* find which instance of amd to unregister */
     u_long amd_prognum = get_amd_program_number();
 
@@ -875,7 +939,7 @@
 
 
 /* return the rpc program number under which amd was used */
-int
+u_long
 get_amd_program_number(void)
 {
   return amd_program_number;
@@ -884,7 +948,7 @@
 
 /* set the rpc program number used for amd */
 void
-set_amd_program_number(int program)
+set_amd_program_number(u_long program)
 {
   amd_program_number = program;
 }
@@ -955,9 +1019,9 @@
     close(fd);
   }
   return;
+#else
+  plog(XLOG_ERROR, "unable to release controlling tty");
 #endif /* not TIOCNOTTY */
-
-  plog(XLOG_ERROR, "unable to release controlling tty");
 }
 
 
@@ -1012,7 +1076,7 @@
   /*
    * take a copy in case path is in readonly store
    */
-  char *p2 = strdup(path);
+  char *p2 = xstrdup(path);
   char *sp = p2;
   struct stat stb;
   int error_so_far = 0;
@@ -1056,7 +1120,7 @@
 void
 rmdirs(char *dir)
 {
-  char *xdp = strdup(dir);
+  char *xdp = xstrdup(dir);
   char *dp;
 
   do {
@@ -1089,3 +1153,15 @@
 
   XFREE(xdp);
 }
+
+/*
+ * Dup a string
+ */
+char *
+xstrdup(const char *s)
+{
+  size_t len = strlen(s);
+  char *sp = xmalloc(len + 1);
+  memcpy(sp, s, len + 1);
+  return sp;
+}

Modified: trunk/contrib/amd/mk-amd-map/mk-amd-map.8
===================================================================
--- trunk/contrib/amd/mk-amd-map/mk-amd-map.8	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/mk-amd-map/mk-amd-map.8	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 Erez Zadok
 .\" Copyright (c) 1993 Jan-Simon Pendry
 .\" Copyright (c) 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -12,11 +12,7 @@
 .\" 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
+.\" 3. 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.
 .\"
@@ -32,10 +28,10 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"     from: @(#)mk-amd-map.8	8.1 (Berkeley) 6/28/93
-.\"	$Id: mk-amd-map.8,v 1.1.1.3 2012-07-21 14:53:13 laffer1 Exp $
-.\"	$FreeBSD$
+.\"	$FreeBSD: stable/10/contrib/amd/mk-amd-map/mk-amd-map.8 310490 2016-12-23 22:42:14Z cy $
 .\"
+.\" File: am-utils/mk-amd-map/mk-amd-map.8
+.\"
 .Dd January 2, 2006
 .Dt MK-AMD-MAP 8
 .Os

Modified: trunk/contrib/amd/mk-amd-map/mk-amd-map.c
===================================================================
--- trunk/contrib/amd/mk-amd-map/mk-amd-map.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/mk-amd-map/mk-amd-map.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -93,7 +89,7 @@
 	/*
 	 * Skip leading white space on next line
 	 */
-	while ((ch = getc(fp)) != EOF && isascii(ch) && isspace(ch)) ;
+	while ((ch = getc(fp)) != EOF && isascii((unsigned char)ch) && isspace((unsigned char)ch)) ;
 	(void) ungetc(ch, fp);
       } else {
 	return done;
@@ -144,7 +140,7 @@
     /*
      * Find start of key
      */
-    for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ;
+    for (kp = key_val; *kp && isascii((unsigned char)*kp) && isspace((unsigned char)*kp); kp++) ;
 
     /*
      * Ignore blank lines
@@ -155,7 +151,7 @@
     /*
      * Find end of key
      */
-    for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ;
+    for (cp = kp; *cp && (!isascii((unsigned char)*cp) || !isspace((unsigned char)*cp)); cp++) ;
 
     /*
      * Check whether key matches, or whether
@@ -163,7 +159,7 @@
      */
     if (*cp)
       *cp++ = '\0';
-    while (*cp && isascii(*cp) && isspace((int)*cp))
+    while (*cp && isascii((unsigned char)*cp) && isspace((unsigned char)*cp))
       cp++;
     if (*kp == '+') {
       fprintf(stderr, "Can't interpolate %s\n", kp);

Modified: trunk/contrib/amd/scripts/amd.conf-sample
===================================================================
--- trunk/contrib/amd/scripts/amd.conf-sample	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/scripts/amd.conf-sample	2018-06-15 22:31:15 UTC (rev 11011)
@@ -64,8 +64,8 @@
 # (amd -x)
 log_options =			fatal,error,user,warn,info,map,stats,all
 # (amd -D)
-debug_options =			all,amq,daemon,fork,full,hrtime,info,mem,mtab,\
-				str,readdir,test,trace,xdrtrace
+debug_options =			all,defaults,test,amq,daemon,fork,\
+				full,hrtime,info,mem,mtab,str,readdir,trace,xdrtrace
 # path for mtab file during mtab debug mode
 debug_mtab_file =               /tmp/mnttab
 # (amd -S)
@@ -108,7 +108,7 @@
 normalize_slashes =		yes | no
 
 ##############################################################################
-# these 8 global options can be overridden by each map individually
+# these 9 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
@@ -119,6 +119,8 @@
 search_path =			/etc/local:/etc/amdmaps:/misc/yp
 # selectors are not recognized by default in the /defaults entry
 selectors_in_defaults =		no | yes
+# does this map use Sun Automounter map syntax?
+sun_map_syntax =		no | yes
 ##############################################################################
 
 ##############################################################################

Modified: trunk/contrib/amd/scripts/amd.conf.5
===================================================================
--- trunk/contrib/amd/scripts/amd.conf.5	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/scripts/amd.conf.5	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
 .\" 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
+.\" 3. 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.
 .\"
@@ -36,10 +32,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: amd.conf.5,v 1.1.1.4 2012-07-21 14:53:13 laffer1 Exp $
-.\" $FreeBSD$
+.\" File: am-utils/scripts/amd.conf.5
+.\" $FreeBSD: stable/10/contrib/amd/scripts/amd.conf.5 310490 2016-12-23 22:42:14Z cy $
 .\"
 .Dd April 21, 2006
 .Dt AMD.CONF 5
@@ -267,8 +262,14 @@
 	wire!=slip-net;opts:=intr,rsize=8192,wsize=8192
 .Ed
 Deprecated form: selectors_on_default
+.TP
+.BR sun_map_syntax " (boolean, default=no)"
+If "yes," then Amd will parse the map according to the Sun Automount syntax.
+
+.\" **************************************************************************
 .El
 .Ss "Parameters applicable to the global section only"
+
 .Bl -tag -width 4n
 .It Va arch Pq string, default to compiled in value
 Same as the
@@ -338,12 +339,13 @@
 Specify any debugging options for
 .Xr amd 8 .
 Works only if
+Works only if
 am-utils was configured for debugging using the
 .Fl Fl enable-debug
 option.
 The
 .Cm mem
-option alone can be turned on via
+option, as well as all other options, can be turned on via
 .Fl Fl enable-debug Ns = Ns Cm mem .
 Otherwise debugging options are ignored.
 Options are
@@ -357,7 +359,9 @@
 .Pp
 .Bl -tag -width ".Cm xdrtrace" -compact
 .It Cm all
-all options
+all options (excludes hrtime and mtab)
+.It Cm defaults
+"sensible" default options (all--excluding hrtime, mtab, and xdrtrace)
 .It Cm amq
 register for
 .Xr amq 8
@@ -367,6 +371,8 @@
 fork server
 .It Cm full
 program trace
+.It Cm hrtime
+print high resolution time stamps (only if syslog(3) is not used)
 .It Cm info
 info service specific debugging
 (hesiod, nis, etc.)
@@ -376,14 +382,16 @@
 use local
 .Pa ./mtab
 file
+\fBreaddir\fR   show browsable_dirs progress
 .It Cm str
 debug string munging
 .It Cm test
-full debug but no daemon
+full debug options plus mtab,nodaemon,nofork,noamq
 .It Cm trace
 trace protocol and NFS mount arguments
 .It Cm xdrtrace
 trace XDR routines
+.BR dismount_interval " (numeric, default=120)"
 .El
 .It Va dismount_interval Pq numeric, default=120
 Same as the
@@ -573,12 +581,14 @@
 .Bl -tag -width ".Cm warning" -compact
 .It Cm all
 all messages
+.It Cm defaults
+default messages (fatal,error,user,warning,info)
 .It Cm debug
 debug messages
 .It Cm error
-non-fatal system errors
+non-fatal system errors (cannot be turned off)
 .It Cm fatal
-fatal errors
+fatal errors (cannot be turned off)
 .It Cm info
 information
 .It Cm map
@@ -589,6 +599,7 @@
 non-fatal user errors
 .It Cm warn
 warnings
+\fBwarning\fR   warnings
 .It Cm warning
 warnings
 .El
@@ -1067,7 +1078,9 @@
 .Sh SEE ALSO
 .Xr hosts_access 5 ,
 .Xr amd 8 ,
-.Xr amq 8
+.Xr amq 8 ,
+.xr automount 8 ,
+.Xr ctl-amd 8 .
 .Pp
 .Dq am-utils
 .Xr info 1

Modified: trunk/contrib/amd/scripts/automount2amd.8
===================================================================
--- trunk/contrib/amd/scripts/automount2amd.8	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/scripts/automount2amd.8	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
 .\" 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
+.\" 3. 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.
 .\"
@@ -36,9 +32,8 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: automount2amd.8,v 1.1.1.3 2012-07-21 14:53:13 laffer1 Exp $
+.\" File: am-utils/scripts/automount2amd.8
 .\"
 .TH AUTOMOUNT2AMD 8L "24 May 1993"
 .SH NAME

Modified: trunk/contrib/amd/scripts/automount2amd.in
===================================================================
--- trunk/contrib/amd/scripts/automount2amd.in	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/scripts/automount2amd.in	2018-06-15 22:31:15 UTC (rev 11011)
@@ -26,7 +26,7 @@
 #
 # You should set the DOMAIN and DEFAULT variables to your preferences.
 #
-# $Id: automount2amd.in,v 1.1.1.3 2012-07-21 14:53:13 laffer1 Exp $
+# $Id: automount2amd.in,v 1.2 2002/01/15 18:25:25 ezk Exp $
 #
 
 require "ctime.pl";

Modified: trunk/contrib/amd/scripts/expn.1
===================================================================
--- trunk/contrib/amd/scripts/expn.1	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/scripts/expn.1	2018-06-15 22:31:15 UTC (rev 11011)
@@ -16,7 +16,7 @@
 # system requirements:
 # 	must have 'nslookup' and 'hostname' programs.
 
-# $Header: /home/cvs/src/contrib/amd/scripts/expn.1,v 1.1.1.3 2012-07-21 14:53:13 laffer1 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

Modified: trunk/contrib/amd/scripts/expn.in
===================================================================
--- trunk/contrib/amd/scripts/expn.in	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/scripts/expn.in	2018-06-15 22:31:15 UTC (rev 11011)
@@ -15,7 +15,7 @@
 # system requirements:
 # 	must have 'nslookup' and 'hostname' programs.
 
-# $Header: /home/cvs/src/contrib/amd/scripts/expn.in,v 1.1.1.3 2012-07-21 14:53:13 laffer1 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

Modified: trunk/contrib/amd/scripts/fixrmtab.in
===================================================================
--- trunk/contrib/amd/scripts/fixrmtab.in	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/scripts/fixrmtab.in	2018-06-15 22:31:15 UTC (rev 11011)
@@ -10,15 +10,23 @@
 
 #set -x
 
-RMTAB=/etc/rmtab
-TMP=/tmp/rmtab.$$
+# allow user to pass RMTAB file name from environment
+if test -z "${RMTAB}" ; then
+	RMTAB=/etc/rmtab
+fi
 
-if [ ! -f /etc/rmtab ]; then
+if [ ! -f "$RMTAB" ]; then
 	exit 0
 fi
 
-for host in $*
+TMP="$(mktemp ${RMTAB}.XXXXXX)"
+if [ -z "$TMP" ]; then
+	exit 1
+fi
+
+trap "rm -f $TMP" 0 1 2 3 15
+
+for host
 do
-	sed -e '/^'$host':/s/^./#/' $RMTAB > $TMP && cp $TMP $RMTAB
+	sed -e "/^$host:/s/^./#/" "$RMTAB" > "$TMP" && cp "$TMP" "$RMTAB"
 done
-rm -f $TMP

Modified: trunk/contrib/amd/vers.m4
===================================================================
--- trunk/contrib/amd/vers.m4	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/vers.m4	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1 +1 @@
-[6.1.5]dnl
+[6.2]dnl

Modified: trunk/contrib/amd/wire-test/wire-test.8
===================================================================
--- trunk/contrib/amd/wire-test/wire-test.8	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/wire-test/wire-test.8	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 1997-2006 Erez Zadok
+.\" Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
 .\" 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
+.\" 3. 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.
 .\"
@@ -36,10 +32,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"	%W% (Berkeley) %G%
 .\"
-.\" $Id: wire-test.8,v 1.1.1.3 2012-07-21 14:53:13 laffer1 Exp $
-.\" $FreeBSD$
+.\" File: am-utils/wire-test/wire-test.8
+.\" $FreeBSD: stable/10/contrib/amd/wire-test/wire-test.8 310490 2016-12-23 22:42:14Z cy $
 .\"
 .Dd January 2, 2006
 .Dt WIRE-TEST 8

Modified: trunk/contrib/amd/wire-test/wire-test.c
===================================================================
--- trunk/contrib/amd/wire-test/wire-test.c	2018-06-15 22:29:16 UTC (rev 11010)
+++ trunk/contrib/amd/wire-test/wire-test.c	2018-06-15 22:31:15 UTC (rev 11011)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2006 Erez Zadok
+ * Copyright (c) 1997-2014 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.
@@ -16,11 +16,7 @@
  * 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
+ * 3. 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.
  *
@@ -59,7 +55,7 @@
   char *testhost, *proto, *tmp_buf;
   int nv, ret;
   struct sockaddr_in *ip;
-  struct hostent *hp = 0;
+  struct hostent *hp = NULL;
 
   am_set_progname(argv[0]);
 
@@ -102,12 +98,11 @@
   memmove((voidp) &ip->sin_addr, (voidp) hp->h_addr, sizeof(ip->sin_addr));
   ip->sin_port = htons(NFS_PORT);
 
-  xlog_level = 0;		/* turn off debugging */
   fprintf(stderr, "NFS Version and protocol tests to host \"%s\"...\n", testhost);
   proto = "udp";
   for (nv=2; nv<=3; ++nv) {
     fprintf(stderr, "\ttesting vers=%d, proto=\"%s\" -> ", nv, proto);
-    ret = get_nfs_version(testhost, ip, nv, proto);
+    ret = get_nfs_version(testhost, ip, nv, proto, 0);
     if (ret == 0)
       fprintf(stderr, "failed!\n");
     else
@@ -117,7 +112,7 @@
   proto = "tcp";
   for (nv=2; nv<=3; ++nv) {
     fprintf(stderr, "\ttesting vers=%d, proto=\"%s\" -> ", nv, proto);
-    ret = get_nfs_version(testhost, ip, nv, proto);
+    ret = get_nfs_version(testhost, ip, nv, proto, 0);
     if (ret == 0)
       fprintf(stderr, "failed!\n");
     else



More information about the Midnightbsd-cvs mailing list