Initial revision
authorhjl <hjl>
Mon, 18 Oct 1999 23:21:12 +0000 (23:21 +0000)
committerhjl <hjl>
Mon, 18 Oct 1999 23:21:12 +0000 (23:21 +0000)
169 files changed:
ChangeLog [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
config.mk.in [new file with mode: 0644]
configure [new file with mode: 0755]
configure.in [new file with mode: 0644]
etc/redhat/nfs.init [new file with mode: 0755]
etc/redhat/nfslock.init [new file with mode: 0755]
install-sh [new file with mode: 0644]
linux-nfs/ChangeLog [new file with mode: 0644]
linux-nfs/INSTALL [new file with mode: 0644]
linux-nfs/KNOWNBUGS [new file with mode: 0644]
linux-nfs/NEW [new file with mode: 0644]
linux-nfs/README [new file with mode: 0644]
linux-nfs/THANKS [new file with mode: 0644]
linux-nfs/TODO [new file with mode: 0644]
nfs-utils.spec [new file with mode: 0644]
rules.mk [new file with mode: 0644]
support/Makefile [new file with mode: 0644]
support/export/Makefile [new file with mode: 0644]
support/export/client.c [new file with mode: 0644]
support/export/export.c [new file with mode: 0644]
support/export/hostname.c [new file with mode: 0644]
support/export/keys.c [new file with mode: 0644]
support/export/mount.x [new file with mode: 0644]
support/export/nfsctl.c [new file with mode: 0644]
support/export/rmtab.c [new file with mode: 0644]
support/export/xtab.c [new file with mode: 0644]
support/include/Makefile [new file with mode: 0644]
support/include/config.h.in [new file with mode: 0644]
support/include/exportfs.h [new file with mode: 0644]
support/include/misc.h [new file with mode: 0644]
support/include/nfs/debug.h [new file with mode: 0644]
support/include/nfs/export.h [new file with mode: 0644]
support/include/nfs/nfs.h [new file with mode: 0644]
support/include/nfslib.h [new file with mode: 0644]
support/include/rpcdispatch.h [new file with mode: 0644]
support/include/rpcmisc.h [new file with mode: 0644]
support/include/rpcsec.h [new file with mode: 0644]
support/include/rpcsvc/nfs_prot.h [new file with mode: 0644]
support/include/sys/fs/ext2fs.h [new file with mode: 0644]
support/include/version.h [new file with mode: 0644]
support/include/xio.h [new file with mode: 0644]
support/include/xlog.h [new file with mode: 0644]
support/include/xmalloc.h [new file with mode: 0644]
support/include/ypupdate.h [new file with mode: 0644]
support/lib/Makefile [new file with mode: 0644]
support/nfs/Makefile [new file with mode: 0644]
support/nfs/clients.c [new file with mode: 0644]
support/nfs/exports.c [new file with mode: 0644]
support/nfs/getfh.c [new file with mode: 0644]
support/nfs/keytab.c [new file with mode: 0644]
support/nfs/lockdsvc.c [new file with mode: 0644]
support/nfs/nfsclient.c [new file with mode: 0644]
support/nfs/nfsctl.c [new file with mode: 0644]
support/nfs/nfsexport.c [new file with mode: 0644]
support/nfs/nfssvc.c [new file with mode: 0644]
support/nfs/rmtab.c [new file with mode: 0644]
support/nfs/rpcdispatch.c [new file with mode: 0644]
support/nfs/rpcmisc.c [new file with mode: 0644]
support/nfs/wildmat.c [new file with mode: 0644]
support/nfs/xio.c [new file with mode: 0644]
support/nfs/xlog.c [new file with mode: 0644]
support/nfs/xmalloc.c [new file with mode: 0644]
support/nfs/ypupdate_xdr.c [new file with mode: 0644]
tools/Makefile [new file with mode: 0644]
tools/getiversion/Makefile [new file with mode: 0644]
tools/getiversion/getiversion.c [new file with mode: 0644]
tools/getkversion/Makefile [new file with mode: 0644]
tools/getkversion/getkversion.c [new file with mode: 0644]
tools/locktest/Makefile [new file with mode: 0644]
tools/locktest/testlk.c [new file with mode: 0644]
tools/nlmtest/Makefile [new file with mode: 0644]
tools/nlmtest/README [new file with mode: 0644]
tools/nlmtest/host.h [new file with mode: 0644]
tools/nlmtest/nlm_prot.x [new file with mode: 0644]
tools/nlmtest/nlmtest.c [new file with mode: 0644]
tools/rpcdebug/Makefile [new file with mode: 0644]
tools/rpcdebug/neat_idea.c [new file with mode: 0644]
tools/rpcdebug/rpcdebug.c [new file with mode: 0644]
tools/rpcgen/Makefile [new file with mode: 0644]
tools/rpcgen/README [new file with mode: 0644]
tools/rpcgen/rpc_clntout.c [new file with mode: 0644]
tools/rpcgen/rpc_cout.c [new file with mode: 0644]
tools/rpcgen/rpc_hout.c [new file with mode: 0644]
tools/rpcgen/rpc_main.c [new file with mode: 0644]
tools/rpcgen/rpc_output.h [new file with mode: 0644]
tools/rpcgen/rpc_parse.c [new file with mode: 0644]
tools/rpcgen/rpc_parse.h [new file with mode: 0644]
tools/rpcgen/rpc_sample.c [new file with mode: 0644]
tools/rpcgen/rpc_scan.c [new file with mode: 0644]
tools/rpcgen/rpc_scan.h [new file with mode: 0644]
tools/rpcgen/rpc_svcout.c [new file with mode: 0644]
tools/rpcgen/rpc_tblout.c [new file with mode: 0644]
tools/rpcgen/rpc_util.c [new file with mode: 0644]
tools/rpcgen/rpc_util.h [new file with mode: 0644]
tools/rpcgen/rpcgen.new.1 [new file with mode: 0644]
utils/Makefile [new file with mode: 0644]
utils/exportfs/Makefile [new file with mode: 0644]
utils/exportfs/exportfs.c [new file with mode: 0644]
utils/exportfs/exportfs.man [new file with mode: 0644]
utils/exportfs/exports.man [new file with mode: 0644]
utils/lockd/Makefile [new file with mode: 0644]
utils/lockd/lockd.c [new file with mode: 0644]
utils/mountd/Makefile [new file with mode: 0644]
utils/mountd/auth.c [new file with mode: 0644]
utils/mountd/mount_dispatch.c [new file with mode: 0644]
utils/mountd/mount_xdr.c [new file with mode: 0644]
utils/mountd/mountd.c [new file with mode: 0644]
utils/mountd/mountd.h [new file with mode: 0644]
utils/mountd/mountd.man [new file with mode: 0644]
utils/mountd/rmtab.c [new file with mode: 0644]
utils/nfsd/Makefile [new file with mode: 0644]
utils/nfsd/nfsd.c [new file with mode: 0644]
utils/nfsd/nfsd.man [new file with mode: 0644]
utils/nfsstat/Makefile [new file with mode: 0644]
utils/nfsstat/nfsstat.c [new file with mode: 0644]
utils/nfsstat/nfsstat.man [new file with mode: 0644]
utils/nhfsstone/DISCLAIMER [new file with mode: 0644]
utils/nhfsstone/Makefile [new file with mode: 0644]
utils/nhfsstone/README [new file with mode: 0644]
utils/nhfsstone/README.linux [new file with mode: 0644]
utils/nhfsstone/nhfsgraph [new file with mode: 0755]
utils/nhfsstone/nhfsnums [new file with mode: 0755]
utils/nhfsstone/nhfsrun [new file with mode: 0755]
utils/nhfsstone/nhfsstone.1 [new file with mode: 0644]
utils/nhfsstone/nhfsstone.c [new file with mode: 0644]
utils/rquotad/Makefile [new file with mode: 0644]
utils/rquotad/NEW [new file with mode: 0644]
utils/rquotad/README.okir [new file with mode: 0644]
utils/rquotad/hasquota.c [new file with mode: 0644]
utils/rquotad/mntent.h [new file with mode: 0644]
utils/rquotad/pathnames.h [new file with mode: 0644]
utils/rquotad/quotactl.c [new file with mode: 0644]
utils/rquotad/rquota.h [new file with mode: 0644]
utils/rquotad/rquota.x [new file with mode: 0644]
utils/rquotad/rquota_server.c [new file with mode: 0644]
utils/rquotad/rquota_svc.c [new file with mode: 0644]
utils/rquotad/rquota_xdr.c [new file with mode: 0644]
utils/rquotad/rquotad.man [new file with mode: 0644]
utils/showmount/Makefile [new file with mode: 0644]
utils/showmount/showmount.c [new file with mode: 0644]
utils/showmount/showmount.man [new file with mode: 0644]
utils/statd/COPYING [new file with mode: 0644]
utils/statd/COPYRIGHT [new file with mode: 0644]
utils/statd/Makefile [new file with mode: 0644]
utils/statd/TODO [new file with mode: 0644]
utils/statd/callback.c [new file with mode: 0644]
utils/statd/log.c [new file with mode: 0644]
utils/statd/log.h [new file with mode: 0644]
utils/statd/misc.c [new file with mode: 0644]
utils/statd/monitor.c [new file with mode: 0644]
utils/statd/notify.c [new file with mode: 0644]
utils/statd/notlist.c [new file with mode: 0644]
utils/statd/notlist.h [new file with mode: 0644]
utils/statd/rmtcall.c [new file with mode: 0644]
utils/statd/sim_sm_inter.x [new file with mode: 0644]
utils/statd/simu.c [new file with mode: 0644]
utils/statd/simulate.c [new file with mode: 0644]
utils/statd/sm_inter.x [new file with mode: 0644]
utils/statd/stat.c [new file with mode: 0644]
utils/statd/statd.c [new file with mode: 0644]
utils/statd/statd.h [new file with mode: 0644]
utils/statd/statd.man [new file with mode: 0644]
utils/statd/state.c [new file with mode: 0644]
utils/statd/svc_run.c [new file with mode: 0644]
utils/statd/system.h [new file with mode: 0644]
utils/statd/version.h [new file with mode: 0644]

diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..f8c4d9e
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,178 @@
+Mon Oct 18 14:56:22 1999  H.J. Lu <hjl@lucon.org>
+
+       * Initial version 0.1 released.
+
+       * configure.in (VERSION): Set to "nfs-utils 0.1".
+       * configure: Regenerated.
+
+Mon Oct 18 14:54:57 1999  H.J. Lu <hjl@lucon.org>
+
+       * utils/mountd/mountd.c (get_exportlist): Cleanup.
+
+       * utils/exportfs/exportfs.c (unexport_all): Unexport from
+       kernel only if the entry is exported to kernel.
+       (unexportfs): Likewise.
+
+Wed Sep 08 16:49:32 1999  Neil Brown <neilb@cse.unsw.edu.au>
+
+1/ utils/mountd/rmtab.c::mountlist_list
+
+     This routine stats the rmtab file to see if it has changed.  It
+     if has, it cleans up it's old copy of the data. But it still
+     always re-read the file, thus returning multiple copies of the
+     data on consecutive calls without intervening changes.
+     "Showmount -a" didn't show this as it appears to sort/unique the
+     data, but 'strace showmount -a' showed that the size of the
+     datagram that it received grew.
+
+     I moved the getrmtabent loop inside the mtime test.
+
+2/ utils/exportfs/exportfs.c
+   
+     Many routines used the m_path field of m_export instead of
+     e_path.
+     According to the comment in nfslib.h, m_path should only
+     be used when processing a mount request (i.e. in mountd)
+     where the mountpoint may be a subdirectory of the export point.
+
+     I changed all occurances of m_path to e_path
+
+
+3/ utils/exportfs/exportfs.c:main
+
+      extra arguments are not meaningful with -a or -r, but
+      exportfs accepted them and then ignored the -a/-r, expect that
+      -r would still unexport everything first.
+
+      I generate an error if there are extra args and f_all
+
+4/ utils/exportfs/exportfs.c:main
+     extract dump out as a special case.
+
+5/ utils/exportfs/exportfs.c
+     made f_reexport a local variable.
+
+
+6/ utils/exportfs/exportfs.c:main,exportall
+
+    support/export/rmtab.c
+       only  mayexport on newly created entries, don't set xtabent at all
+
+7/ support/include/nfslib.h
+
+      add #define _PATH_PROC_EXPORTS to be /proc/fs/nds/exports
+
+8/ support/export/xtab.c
+
+      xtab_mount_read loads data from _PATH_PROC_EXPORTS if it exists,
+      else from xtab
+
+
+9/ support/export/xtab.c
+
+      xtab_mount_read now sets m_exported, and NOT
+       xtabent and mayexport
+
+      removed the append arguement from xtab_write as it was
+       never used.
+
+      added is_export flag to xtab_write similar to xtab_read
+       if is_export, only write entries with m_xtabent or m_addxtab
+       if !is_export, only write entries with m_exported
+     
+10/ support/export/export.c::export_allowed_internal
+
+      added test for exp->m_mayexport, as the export tree
+       may have entries that are no longer allowed to be exported,
+       and so shouldn't caused deduced exported by rmtab_read
+
+11/ utils/exportfs/exportfs.c::main
+       error checking of flags.
+
+12/ utils/exportfs/exportfs.c
+
+       total rewrite of export and unexport logic.
+       We now:
+       -  build an exportslist of valid exports, based on
+          current etab file  and arguments,
+        -  read rmtab to instantiate relevant wild card entries
+       -  read etab to find out what is currently exported
+       -  synchronise intention with reality
+       -  write out etab and xtab
+
+13/  various
+       discard the m_addxtab flag
+       add m_changed flag so we know what to report in exportfs
+
+14/ utils/mountd/auth.c:auth_authenticate
+
+       the value returned by gethostbyaddr was trusted.
+
+       It now follows this with a call to gethostbyname
+       and checks that the address is in the list.
+
+15/ support/export/nfsctl.c::cltsetup,expsetup
+
+       force client names to lowercase as kernel is
+       sensitive to case
+
+16/ quietened a few compiler warnings
+
+17/ support/export/client:client_lookup
+
+     look for pre-existing client with same name before creating
+       a new one.
+
+18/ support/include/exportfs.h
+
+     The ordering of the MCL_* enum was:
+       ANONYMOUS, FQDN, SUBNETWORK, WILDCARD, NETGROUP
+
+     I moved ANONYMOUS to the end.
+
+     The ordering is significant when an export entry is being searched for to 
+       match a given address.  There are two problems with ANONYMOUS being first.
+
+       1/ if a directory is exported rw to a couple of hosts and ro to everyone else,
+          then the ro case will always be found first and the privileged hosts won't get
+          their privilege
+       2/ When mountd gets a request to mount an ANONYMOUSly exported tree, it creates a FQDN
+          export entry for the specific host, and writes it to xtab.
+          When another request comes from the same host, the ANONYMOUS entry is found again, 
+          before the new FQDN entry, so it creates another FQDN entry and writes it to xtab
+          again.  If causes bloat in xtab.
+
+      Putting ANONYMOUS at the end reflects it's nature as a catch-all
+
+19/ utils/exportfs/exportfs.man
+       many updates to the man page to reflect changes to the code
+
+-----------------------
+
+
+
+TODO:
+
+- allow exportfs to modify rmtab file
+- make sure kernel never gets two clients with same IP address
+    - possible kernel should reject
+    - needs to be some way to lookup client in kernel by IP address
+- maybe get kernel to do case-insensitive comparisons on client names
+- remove unused clients from kernel
+
+- change etab to xtab and xtab to xtab.active
+
+- timestamp and/or statd-stamp in rmtab for removing old entries.
+
+Mon Oct 18 11:48:07 1999  H.J. Lu <hjl@lucon.org>
+
+       * linux-nfs: New directory.
+       * linux-nfs/ChangeLog: Moved from ..
+       * linux-nfs/INSTALL: Likewise.
+       * linux-nfs/KNOWNBUGS: Likewise.
+       * linux-nfs/NEW: Likewise.
+       * linux-nfs/README: Likewise.
+       * linux-nfs/THANKS: Likewise.
+       * linux-nfs/TODO: Likewise.
+
+       * Starting from knfsd 1.4.7.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..2789f00
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,22 @@
+#
+# linux-nfs/Makefile
+#
+
+SUBDIRS        = tools support utils
+TOP    = 
+
+include $(TOP)rules.mk
+
+distclean clean::
+       rm -f postscript/*.ps
+       rm -f LOG make.log
+
+distclean::
+       rm -fr bin
+       rm -f config.cache config.log config.mk config.status
+
+install:: installman
+       if [ ! -d $(STATEDIR) ]; then mkdir -p $(STATEDIR); fi
+       touch $(STATEDIR)/xtab; chmod 644 $(STATEDIR)/xtab
+       touch $(STATEDIR)/etab; chmod 644 $(STATEDIR)/etab
+       touch $(STATEDIR)/rmtab; chmod 644 $(STATEDIR)/rmtab
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..3fb4bb0
--- /dev/null
+++ b/README
@@ -0,0 +1,92 @@
+This is the Linux NFS utility package version 0.1. It is based on knfsd
+1.4.7.
+
+WARNING: The NFS servers in Linux 2.2 to 2.2.12 are not compatible with
+other NFS client implemenations. If you plan to use Linux 2.2.x as an
+NFS server for non-Linux NFS clients, you should get the Linux NFS
+kernel from the Linux NFS CVS server:
+
+1. Set the environment variable, CVS_RSH, to ssh.
+2. Login to the Linux NFS CVS server:
+
+# cvs -z 9 -d:pserver:anonymous@cvs.linuxnfs.sourceforge.org:/cvsroot/nfs login
+
+without password if it is your first time.
+
+3. Check out the current Linux 2.2 NFS kernel:
+
+# cvs -z 9 -d:pserver:anonymous@cvs.linuxnfs.sourceforge.org:/cvsroot/nfs co -r linux-2-2-nfsv2 linux-2.2
+
+4. If you don't want to use the current NFS kernel, you can find out
+for which kernels the NFS patch is available:
+
+# cd linux-2.2
+# cvs -z 9 -d:pserver:anonymous@cvs.linuxnfs.sourceforge.org:/cvsroot/nfs status -v Makefile
+
+Then generate the kernel patch:
+
+# cvs -z 9 -d:pserver:anonymous@cvs.linuxnfs.sourceforge.org:/cvsroot/nfs rdiff -ko -u -r linux-2-2-xx -r linux-2-2-xx-nfsv2-xxxxx linux-2.2
+
+If there is no NFS patch for the kernel you are interested in, you have
+to make a patch closest to your kernel version and apply it by hand.
+
+There is a Linux NFS kernel source tree for Linux 2.3, linux-2.3, on
+the Linux NFS CVS server. However, it is not maintained. We will need
+all the help we can get. To contribute to the Linux NFS project, please
+go to
+
+http://www.linuxnfs.sourceforge.org
+
+and login as "beta" with password "beta4u". You register yourself.
+please send an email to nfs-admin@linuxnfs.sourceforge.org with
+
+1. Your user id on www.linuxnfs.sourceforge.org.
+2. The area in NFS you'd like to work on.
+
+You will be notified when it is done.
+
+There is a Linux NFS mailing list at
+
+http://lists.varesearch.com/lists/listinfo/nfs/
+
+You can subscribe it and search the mailing list archive via a web
+browser.
+
+The nfs-utils package is avaible from the CVS server:
+
+# cvs -z 9 -d:pserver:anonymous@cvs.linuxnfs.sourceforge.org:/cvsroot/nfs co nfs-utils
+
+will get the latest version.
+
+The tar file is at
+
+ftp://ftp.valinux.com/pub/support/hjl/nfs/nfs-utils-0.1.tar.gz
+
+To compile, just do
+
+# ./configure
+# make
+
+# make install
+
+will install the nfs-utils binaries. You have to install the NFS
+service scripts. There are 2 in etc/redhat provided for RedHat 6.x.
+They are tested on RedHat 6.1.
+
+On RedHat 6.1, you can use
+
+# rpm -ta nfs-utils-0.1.tar.gz
+
+to build the source and binary RPMs.
+
+If your mount from util-linux is too old, you will need 2 patches:
+
+ftp://ftp.valinux.com/pub/support/hjl/nfs/util-linux-2.9o-mount-nfsv3.patch
+ftp://ftp.valinux.com/pub/support/hjl/nfs/util-linux-2.9w-mount-nfsv3try.patch
+
+Thanks.
+
+
+H.J.
+hjl@lucon.org
+10/18/99
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..baa54d1
--- /dev/null
@@ -0,0 +1,120 @@
+dnl aclocal.m4 -- custom autoconf macros for various purposes
+dnl Updated for Autoconf v2
+dnl
+dnl ******** save/restore stuff **********
+define(AC_KNFSD_SAVE,
+  [AC_LANG_SAVE
+   save_LDFLAGS=$LDFLAGS
+   save_CFLAGS=$CFLAGS
+   save_CXXFLAGS=$CXXFLAGS
+   save_LIBS=$LIBS
+])dnl
+define(AC_KNFSD_RESTORE,
+  [LDFLAGS=$save_LDFLAGS
+   CFLAGS=$save_CFLAGS
+   CXXFLAGS=$save_CXXFLAGS
+   LIBS=$save_LIBS
+   AC_LANG_RESTORE
+])dnl
+dnl *********** GNU libc 2 ***************
+define(AC_GNULIBC,
+  [AC_MSG_CHECKING(for GNU libc2)
+  AC_CACHE_VAL(knfsd_cv_glibc2,
+  [AC_TRY_CPP([
+      #include <features.h>
+      #if !defined(__GLIBC__)
+      # error Nope
+      #endif], knfsd_cv_glibc2=yes, knfsd_cv_glibc2=no)])
+  AC_MSG_RESULT($knfsd_cv_glibc2)
+  if test $knfsd_cv_glibc2 = yes; then
+    CFLAGS="$CFLAGS -D_GNU_SOURCE"
+    CXXFLAGS="$CXXFLAGS -D_GNU_SOURCE"
+  fi
+]) dnl
+dnl
+dnl ************* egcs *******************
+define(AC_PROG_EGCS,
+  [AC_MSG_CHECKING(for egcs)
+  AC_CACHE_VAL(knfsd_cv_prog_EGCS,
+  [case `$CC --version 2>/dev/null` in
+   egcs*)
+       knfsd_cv_prog_EGCS=yes;;
+   *)
+       knfsd_cv_prog_EGCS=no;;
+   esac
+  ])
+  AC_MSG_RESULT($knfsd_cv_prog_EGCS)
+  test $knfsd_cv_prog_EGCS = yes && AC_DEFINE(HAVE_EGCS)
+]) dnl
+dnl *********** sizeof(dev_t) **************
+dnl ** We have to kludge this rather than use AC_CHECK_SIZEOF because
+dnl ** we have to include sys/types.h. Ugh.
+define(AC_DEV_T_SIZE,
+  [AC_MSG_CHECKING(size of dev_t)
+   AC_CACHE_VAL(ac_cv_sizeof_dev_t,
+   [AC_TRY_RUN(
+    [#include <stdio.h>
+     #include <sys/types.h>
+     main()
+     {
+      FILE *f=fopen("conftestval", "w");
+      if (!f) exit(1);
+      fprintf(f, "%d\n", sizeof(dev_t));
+      exit(0);
+    }], ac_cv_sizeof_dev_t=`cat conftestval`, ac_cv_sizeof_dev_t=0)])
+    AC_MSG_RESULT($ac_cv_sizeof_dev_t)
+    AC_DEFINE(SIZEOF_DEV_T,$ac_cv_sizeof_dev_t)
+  ])
+dnl *********** sizeof(xxx_t) **************
+dnl ** Overwrite the AC_CHECK_SIZEOF macro as we must include sys/types.h
+define([AC_CHECK_SIZEOF],
+  [changequote(<<, >>)dnl
+   define(<<AC_TYPE_NAME>>,translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
+   define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
+   changequote([, ])dnl
+   AC_MSG_CHECKING(size of $1)
+   AC_CACHE_VAL(AC_CV_NAME,
+   [AC_TRY_RUN(
+    [#include <stdio.h>
+     #include <sys/types.h>
+     main()
+     {
+      FILE *f=fopen("conftestval", "w");
+      if (!f) exit(1);
+      fprintf(f, "%d\n", sizeof($1));
+      exit(0);
+    }], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0)])
+    AC_MSG_RESULT($AC_CV_NAME)
+    AC_DEFINE_UNQUOTED(AC_TYPE_NAME,$AC_CV_NAME)
+    undefine([AC_TYPE_NAME])dnl
+    undefine([AC_CV_NAME])dnl
+  ])
+dnl *********** BSD vs. POSIX signal handling **************
+define([AC_BSD_SIGNALS],
+  [AC_MSG_CHECKING(for BSD signal semantics)
+  AC_CACHE_VAL(knfsd_cv_bsd_signals,
+    [AC_TRY_RUN([
+       #include <signal.h>
+       #include <unistd.h>
+       #include <sys/wait.h>
+
+       static int counter = 0;
+       static RETSIGTYPE handler(int num) { counter++; }
+
+       int main()
+       {
+               int     s;
+               if ((s = fork()) < 0) return 1;
+               if (s != 0) {
+                       if (wait(&s) < 0) return 1;
+                       return WIFSIGNALED(s)? 1 : 0;
+               }
+
+               signal(SIGHUP, handler);
+               kill(getpid(), SIGHUP); kill(getpid(), SIGHUP);
+               return (counter == 2)? 0 : 1;
+       }
+    ], knfsd_cv_bsd_signals=yes, knfsd_cv_bsd_signals=no)]) dnl
+    AC_MSG_RESULT($knfsd_cv_bsd_signals)
+    test $knfsd_cv_bsd_signals = yes && AC_DEFINE(HAVE_BSD_SIGNALS)
+])dnl
diff --git a/config.mk.in b/config.mk.in
new file mode 100644 (file)
index 0000000..57d16be
--- /dev/null
@@ -0,0 +1,79 @@
+#
+# Configuration stuff for nfs-utils
+#
+
+VERSION                = @VERSION@
+
+prefix         = $(install_prefix)@prefix@
+exec_prefix    = $(install_prefix)@prefix@
+BINDIR         = @bindir@
+SBINDIR                = @sbindir@
+MANDIR         = @mandir@
+STATEDIR       = $(install_prefix)@statedir@
+
+##################################################################
+# This is the prefix that will be used for nfsd and mountd. Leave this
+# empty, or set to `k'.
+KPREFIX                = @kprefix@
+
+# This define will turn NFSv3 support on or off one day. Not functional yet.
+NFSV3          = @enable_nfsv3@
+
+# Where and how to install manpages
+MAN1EXT                = 1
+MAN5EXT                = 5
+MAN8EXT                = 8
+MAN9EXT                = 9
+MANOWNER       = root
+MANGROUP       = root
+
+# Various libs
+LIBBSD         = @LIBBSD@
+
+################# END OF USER SERVICEABLE PARTS ##################
+ALLTARGETS     = all clean distclean install installman \
+                 depend dep postscript indent
+
+ifndef ARCHFLAGS
+  ARCH         = $(shell uname -m)
+  FLAGS_alpha  = -mno-fp-regs -ffixed-8
+  ARCHFLAGS    = $(FLAGS_$(ARCH))
+.EXPORT:       ARCHFLAGS
+endif
+
+CC             = gcc
+AR             = ar
+LD             = ld
+RM             = rm -f
+MKDIR          = mkdir -p
+LN_S           = ln -sf
+RANLIB         = ranlib
+INDENT         = indent
+RPCGEN         = $(TOP)bin/rpcgen
+GETKVER                = $(TOP)tools/getkversion
+INSTALL                = install
+MAN2PS         = groff -Tps -man
+
+AFLAGS         = -I$(TOP)support/include \
+                 -Wall $(ARCHFLAGS) -pipe
+ifdef KERNEL_INCDIR
+AFLAGS        += -I$(KERNEL_INCDIR)
+endif
+
+CFLAGS         = @CFLAGS@ $(AFLAGS) $(CCOPTS) -DVERSION="\"$(VERSION)\""
+LDFLAGS                = @LDFLAGS@ $(LDOPTS) -L$(TOP)support/lib
+
+ifdef NFSV3
+ CFLAGS        += -DNFS3_SUPPORTED
+endif
+
+k              = $(KPREFIX)
+
+INSTALLBIN     = $(INSTALL) -m 755 -s
+INSTALLSUID    = $(INSTALL) -m 4755
+INSTALLMOD     = $(INSTALL) -m 600
+INSTALLMAN     = $(INSTALL) -m 644
+MAN1DIR                = $(MANDIR)/man$(MAN1EXT)
+MAN5DIR                = $(MANDIR)/man$(MAN5EXT)
+MAN8DIR                = $(MANDIR)/man$(MAN8EXT)
+MAN9DIR                = $(MANDIR)/man$(MAN9EXT)
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..947822a
--- /dev/null
+++ b/configure
@@ -0,0 +1,1861 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_default_prefix=/usr
+ac_help="$ac_help
+  --with-statedir=/foo    use state dir /foo [/var/lib/nfs]"
+ac_help="$ac_help
+  --enable-nfsv3          enable support for NFSv3"
+ac_help="$ac_help
+  --enable-kprefix       install progs as rpc.knfsd etc"
+ac_help="$ac_help
+  --enable-secure-statd  Only lockd can use statd (security)"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+sitefile=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir="$ac_optarg" ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$ac_optarg" ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file="$ac_optarg" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he)
+    # Omit some internal or obsolete options to make the list less imposing.
+    # This message is too long to be a string in the A/UX 3.1 sh.
+    cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --site-file=FILE        use FILE as the site file
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$ac_optarg" ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir="$ac_optarg" ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir="$ac_optarg" ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir="$ac_optarg" ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir="$ac_optarg" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir="$ac_optarg" ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir="$ac_optarg" ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir="$ac_optarg" ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix="$ac_optarg" ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix="$ac_optarg" ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name="$ac_optarg" ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir="$ac_optarg" ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir="$ac_optarg" ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site="$ac_optarg" ;;
+
+  -site-file | --site-file | --site-fil | --site-fi | --site-f)
+    ac_prev=sitefile ;;
+  -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*)
+    sitefile="$ac_optarg" ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir="$ac_optarg" ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir="$ac_optarg" ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes="$ac_optarg" ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries="$ac_optarg" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=rules.mk
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$sitefile"; then
+  if test -z "$CONFIG_SITE"; then
+    if test "x$prefix" != xNONE; then
+      CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+    else
+      CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+    fi
+  fi
+else
+  CONFIG_SITE="$sitefile"
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+# The nfs-utils version
+VERSION="nfs-utils 0.1"
+
+
+# Check whether --with-statedir or --without-statedir was given.
+if test "${with_statedir+set}" = set; then
+  withval="$with_statedir"
+  statedir=$withval
+else
+  statedir=/var/lib/nfs
+fi
+
+       
+# Check whether --enable-nfsv3 or --disable-nfsv3 was given.
+if test "${enable_nfsv3+set}" = set; then
+  enableval="$enable_nfsv3"
+  enable_nfsv3=$enableval
+else
+  enable_nfsv3=no
+fi
+
+       if test "$enable_nfsv3" = yes; then
+               cat >> confdefs.h <<\EOF
+#define NFS3_SUPPORTED 1
+EOF
+
+       else
+               enable_nfsv3=
+       fi
+       
+# Check whether --enable-kprefix or --disable-kprefix was given.
+if test "${enable_kprefix+set}" = set; then
+  enableval="$enable_kprefix"
+  test "$enableval" = "yes" && kprefix=k
+else
+  kprefix=
+fi
+
+       
+# Check whether --enable-secure-statd or --disable-secure-statd was given.
+if test "${enable_secure_statd+set}" = set; then
+  enableval="$enable_secure_statd"
+  test "$enableval" = "yes" && secure_statd=yes
+else
+  secure_statd=no
+fi
+
+       if test "$secure_statd" = yes; then
+               cat >> confdefs.h <<\EOF
+#define RESTRICTED_STATD 1
+EOF
+
+       fi
+       
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:606: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:636: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_prog_rejected=no
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+       continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# -gt 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:687: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:719: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 730 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:761: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:766: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:775: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:794: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+
+for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:830: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CXX="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+  echo "$ac_t""$CXX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="gcc"
+
+
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:862: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 873 "configure"
+#include "confdefs.h"
+
+int main(){return(0);}
+EOF
+if { (eval echo configure:878: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cxx_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cxx_cross=no
+  else
+    ac_cv_prog_cxx_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cxx_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
+if test $ac_cv_prog_cxx_works = no; then
+  { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:904: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
+echo "configure:909: checking whether we are using GNU C++" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.C <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:918: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gxx=yes
+else
+  ac_cv_prog_gxx=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+
+if test $ac_cv_prog_gxx = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+
+ac_test_CXXFLAGS="${CXXFLAGS+set}"
+ac_save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS=
+echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
+echo "configure:937: checking whether ${CXX-g++} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.cc
+if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+  ac_cv_prog_cxx_g=yes
+else
+  ac_cv_prog_cxx_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS="$ac_save_CXXFLAGS"
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:969: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 984 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:990: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 1001 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1007: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 1018 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1024: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1079: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1132: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1137 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1145: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  ac_cv_header_stdc=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1162 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1180 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+  :
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1201 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1212: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  :
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for GNU libc2""... $ac_c" 1>&6
+echo "configure:1236: checking for GNU libc2" >&5
+  if eval "test \"`echo '$''{'knfsd_cv_glibc2'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1241 "configure"
+#include "confdefs.h"
+
+      #include <features.h>
+      #if !defined(__GLIBC__)
+      # error Nope
+      #endif
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1250: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  knfsd_cv_glibc2=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  knfsd_cv_glibc2=no
+fi
+rm -f conftest*
+fi
+
+  echo "$ac_t""$knfsd_cv_glibc2" 1>&6
+  if test $knfsd_cv_glibc2 = yes; then
+    CFLAGS="$CFLAGS -D_GNU_SOURCE"
+    CXXFLAGS="$CXXFLAGS -D_GNU_SOURCE"
+  fi
+
+
+echo $ac_n "checking for main in -lsocket""... $ac_c" 1>&6
+echo "configure:1273: checking for main in -lsocket" >&5
+ac_lib_var=`echo socket'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lsocket  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1281 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:1288: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBSOCKET="-lnsl"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6
+echo "configure:1309: checking for main in -lnsl" >&5
+ac_lib_var=`echo nsl'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lnsl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1317 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:1324: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBNSL="-lnsl"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
+echo "configure:1345: checking for crypt in -lcrypt" >&5
+ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lcrypt  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1353 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char crypt();
+
+int main() {
+crypt()
+; return 0; }
+EOF
+if { (eval echo configure:1364: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBCRYPT="-lcrypt"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test "$knfsd_cv_glibc2" = no; then
+    echo $ac_n "checking for daemon in -lbsd""... $ac_c" 1>&6
+echo "configure:1386: checking for daemon in -lbsd" >&5
+ac_lib_var=`echo bsd'_'daemon | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lbsd  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1394 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char daemon();
+
+int main() {
+daemon()
+; return 0; }
+EOF
+if { (eval echo configure:1405: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBBSD="-lbsd"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+
+
+
+
+
+for ac_func in innetgr
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1435: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1440 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1463: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+cat >> confdefs.h <<EOF
+#define NFS_STATEDIR "$statedir"
+EOF
+
+
+
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "config.mk support/include/config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@VERSION@%$VERSION%g
+s%@statedir@%$statedir%g
+s%@enable_nfsv3@%$enable_nfsv3%g
+s%@kprefix@%$kprefix%g
+s%@secure_statd@%$secure_statd%g
+s%@CC@%$CC%g
+s%@CXX@%$CXX%g
+s%@CPP@%$CPP%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@LIBSOCKET@%$LIBSOCKET%g
+s%@LIBNSL@%$LIBNSL%g
+s%@LIBCRYPT@%$LIBCRYPT%g
+s%@LIBBSD@%$LIBBSD%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"config.mk"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  case "$ac_given_INSTALL" in
+  [/$]*) INSTALL="$ac_given_INSTALL" ;;
+  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([  ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='\([     ][      ]*\)[^  ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='\([     ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="support/include/config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..1d91f5b
--- /dev/null
@@ -0,0 +1,85 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl
+AC_INIT(rules.mk)
+AC_PREFIX_DEFAULT(/usr)
+
+# The nfs-utils version
+VERSION="nfs-utils 0.1"
+AC_SUBST(VERSION)
+
+dnl *************************************************************
+dnl * Define the set of applicable options
+dnl *************************************************************
+AC_ARG_WITH(statedir,
+       [  --with-statedir=/foo    use state dir /foo [/var/lib/nfs]],
+       statedir=$withval,
+       statedir=/var/lib/nfs)
+       AC_SUBST(statedir)
+AC_ARG_ENABLE(nfsv3,
+       [  --enable-nfsv3          enable support for NFSv3],
+       enable_nfsv3=$enableval,
+       enable_nfsv3=no)
+       if test "$enable_nfsv3" = yes; then
+               AC_DEFINE(NFS3_SUPPORTED)
+       else
+               enable_nfsv3=
+       fi
+       AC_SUBST(enable_nfsv3)
+AC_ARG_ENABLE(kprefix,
+       [  --enable-kprefix       install progs as rpc.knfsd etc],
+       test "$enableval" = "yes" && kprefix=k,
+       kprefix=)
+       AC_SUBST(kprefix)
+AC_ARG_ENABLE(secure-statd,
+       [  --enable-secure-statd  Only lockd can use statd (security)],
+       test "$enableval" = "yes" && secure_statd=yes,
+       secure_statd=no)
+       if test "$secure_statd" = yes; then
+               AC_DEFINE(RESTRICTED_STATD)
+       fi
+       AC_SUBST(secure_statd)
+dnl AC_ARG_ENABLE(frob,        enable frobnicator,,                enable_frob=test)
+AC_CONFIG_HEADER(support/include/config.h)
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_STDC_HEADERS
+AC_GNULIBC
+dnl AC_LN_SF
+dnl AC_BSD_SIGNALS
+
+dnl *************************************************************
+dnl * Check for required librarues
+dnl *************************************************************
+AC_CHECK_LIB(socket, main, [LIBSOCKET="-lnsl"])
+AC_CHECK_LIB(nsl, main,        [LIBNSL="-lnsl"])
+AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"])
+if test "$knfsd_cv_glibc2" = no; then
+    AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"])
+fi
+AC_SUBST(LIBSOCKET)
+AC_SUBST(LIBNSL)
+AC_SUBST(LIBCRYPT)
+AC_SUBST(LIBBSD)
+
+dnl *************************************************************
+dnl Check for headers
+dnl *************************************************************
+dnl AC_HAVE_HEADERS(string.h)
+
+dnl *************************************************************
+dnl Check for functions
+dnl *************************************************************
+AC_HAVE_FUNCS(innetgr)
+
+dnl *************************************************************
+dnl Export some path names to config.h
+dnl *************************************************************
+AC_DEFINE_UNQUOTED(NFS_STATEDIR, "$statedir")
+
+AC_SUBST(LDFLAGS)
+AC_SUBST(CXXFLAGS)
+AC_SUBST(CFLAGS)
+AC_OUTPUT(config.mk)
diff --git a/etc/redhat/nfs.init b/etc/redhat/nfs.init
new file mode 100755 (executable)
index 0000000..6da8e0c
--- /dev/null
@@ -0,0 +1,102 @@
+#!/bin/sh
+#
+# nfs           This shell script takes care of starting and stopping
+#               the NFS services.
+#
+# chkconfig: - 60 20
+# description: NFS is a popular protocol for file sharing across TCP/IP \
+#              networks. This service provides NFS server functionality, \
+#              which is configured via the /etc/exports file.
+# probe: true
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+# Source networking configuration.
+if [ ! -f /etc/sysconfig/network ]; then
+    exit 0
+fi
+
+. /etc/sysconfig/network
+
+# Check that networking is up.
+[ ${NETWORKING} = "no" ] && exit 0
+
+[ -x /usr/sbin/rpc.nfsd ] || exit 0
+[ -x /usr/sbin/rpc.mountd ] || exit 0
+[ -x /usr/sbin/exportfs ] || exit 0
+[ -s /etc/exports ] || exit 0
+
+# Number of servers to be started uo by default
+RPCNFSDCOUNT=8
+# No NFS V3.
+RPCMOUNTDOPTS="--no-nfs-version 3"
+
+# See how we were called.
+case "$1" in
+  start)
+       # Start daemons.
+       action "Starting NFS services: " /usr/sbin/exportfs -r
+       echo -n "Starting NFS quotas: "
+       daemon rpc.rquotad
+       echo
+       echo -n "Starting NFS mountd: "
+       daemon rpc.mountd $RPCMOUNTDOPTS
+       echo
+       echo -n "Starting NFS daemon: "
+       daemon rpc.nfsd $RPCNFSDCOUNT
+       echo
+       touch /var/lock/subsys/nfs
+       ;;
+  stop)
+       # Stop daemons.
+       action "Shutting down NFS services: " /usr/sbin/exportfs -au
+       echo -n "Shutting down NFS mountd: "
+       killproc rpc.mountd
+       echo
+       echo -n "Shutting down NFS daemon: "
+       killproc nfsd
+       echo
+       echo -n "Shutting down NFS quotas: "
+       killproc rpc.rquotad
+       echo
+       rm -f /var/lock/subsys/nfs
+       ;;
+  status)
+       status rpc.mountd
+       status nfsd
+       status rpc.rquotad
+       ;;
+  restart)
+       echo -n "Restarting NFS services: "
+       echo -n "rpc.mountd "
+       killproc rpc.mountd
+       daemon rpc.mountd $RPCMOUNTDOPTS
+       /usr/sbin/exportfs -r
+       touch /var/lock/subsys/nfs
+       echo "done."
+       ;;
+  reload)
+       /usr/sbin/exportfs -r
+       touch /var/lock/subsys/nfs
+       ;;
+  probe)
+       if [ ! -f /var/lock/subsys/nfs ] ; then
+         echo start; exit 0
+       fi
+       /sbin/pidof rpc.mountd >/dev/null 2>&1; MOUNTD="$?"
+       /sbin/pidof nfsd >/dev/null 2>&1; NFSD="$?"
+       if [ $MOUNTD = 1 -o $NFSD = 1 ] ; then
+         echo restart; exit 0
+       fi
+       if [ /etc/exports -nt /var/lock/subsys/nfs ] ; then
+         echo reload; exit 0
+       fi
+       ;;
+  *)
+       echo "Usage: nfs {start|stop|status|restart|reload}"
+       exit 1
+esac
+
+exit 0
+
diff --git a/etc/redhat/nfslock.init b/etc/redhat/nfslock.init
new file mode 100755 (executable)
index 0000000..1442637
--- /dev/null
@@ -0,0 +1,82 @@
+#!/bin/sh
+#
+# nfslock       This shell script takes care of starting and stopping
+#               the NFS file locking service.
+#
+# chkconfig: 345 60 20
+# description: NFS is a popular protocol for file sharing across \
+#             TCP/IP networks. This service provides NFS file \
+#             locking functionality.
+# probe: true
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+# Source networking configuration.
+if [ ! -f /etc/sysconfig/network ]; then
+    exit 0
+fi
+
+. /etc/sysconfig/network
+
+# Check that networking is up.
+[ ${NETWORKING} = "no" ] && exit 0
+
+[ -x /usr/sbin/rpc.lockd ] || exit 0
+[ -x /usr/sbin/rpc.statd ] || exit 0
+
+# See how we were called.
+case "$1" in
+  start)
+       # Start daemons.
+       echo "Starting NFS file locking services: "
+       echo -n "Starting NFS lockd: "
+       daemon rpc.lockd
+       echo
+       echo -n "Starting NFS statd: "
+       daemon rpc.statd
+       echo
+       touch /var/lock/subsys/nfslock
+       ;;
+  stop)
+       # Stop daemons.
+       echo "Shutting down NFS file locking services: "
+       echo -n "Shutting down NFS lockd: "
+       killproc lockd
+       echo
+       echo -n "Shutting down NFS statd: "
+       killproc rpc.statd
+       echo
+       rm -f /var/lock/subsys/nfslock
+       ;;
+  status)
+       status lockd
+       status rpc.statd
+       ;;
+  restart)
+       echo -n "Restarting NFS file locking services: "
+       echo -n "rpc.lockd "
+       killproc lockd
+       daemon rpc.lockd
+       echo -n "rpc.statd "
+       killproc rpc.statd
+       daemon rpc.statd
+       touch /var/lock/subsys/nfslock
+       echo "done."
+       ;;
+  probe)
+       if [ ! -f /var/lock/subsys/nfslock ] ; then
+         echo start; exit 0
+       fi
+       /sbin/pidof rpc.statd >/dev/null 2>&1; STATD="$?"
+       /sbin/pidof lockd >/dev/null 2>&1; LOCKD="$?"
+       if [ $STATD = 1 -o $LOCKD = 1 ] ; then
+         echo restart; exit 0
+       fi
+       ;;
+  *)
+       echo "Usage: nfslock {start|stop|status|restart}"
+       exit 1
+esac
+
+exit 0
diff --git a/install-sh b/install-sh
new file mode 100644 (file)
index 0000000..89fc9b0
--- /dev/null
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/linux-nfs/ChangeLog b/linux-nfs/ChangeLog
new file mode 100644 (file)
index 0000000..11ffe15
--- /dev/null
@@ -0,0 +1,78 @@
+
+Release 0.4.11
+
+ *     Added async writes.
+ *     Fixed bug where two rpciod's would be started when insmod'ing
+       both nfs.o and nfsd.o.
+
+Release 0.4.12
+
+ *     Fixed compile problem after renaming some debug macros.
+ *     Improved readdir cache, which can now hold up to 16 (configurable)
+       readdir replies.
+ *     Fixed async write bug(s)
+ *     client file locking now does at least lock/unlock without
+       crashing the machine
+ *     Started to work on NFS swapping
+ *     nfs_get_super no longer requires the file handle passed by
+       mount but does a straight xprt_create_proto().
+ *     TCP reconnect should work now (not yet tested for long disconnect
+       periods, but it does work if you kill and restart nfsd).
+
+Release 0.4.13
+
+ *     More writeback bugs removed.
+ *     Added a modified (and ansified) tirpc rpcgen to get rid of all
+       the warnings in files generated from *.x descriptions. That old Sun
+       code is a real mess.
+ *     Cleaned up nfsd export handling a bit. All syscalls now
+       take dev/ino rather than the pathname.
+ *     Added sysctl interface to set/get debug flags (see tools/rpcdebug).
+ *     Cleaned up Makefiles.
+ *     (experimental) Gathered writes for nfsd (use the wdelay option in
+       /etc/exports).
+ *     Fixed silly bug in nfs_readdir (the in-place decoding of readdir
+       replies requires a temporary buffer).
+ *     Fixed readdir bug in nfsd (long directories were truncated).
+
+Release 0.4.14
+
+ *     Upgraded to kernel 2.0.23
+ *     Fixed bug in rpcdebug
+ *     readdir still didn't work right in nfsd. Argh!
+ *     nfsd would refuse to create symlinks with slashes in them:-)
+ *     nfsd's RPC reply cache should now work again.
+ *     Heavily modified rpc.statd for more robust callback/notify handling
+
+Release 0.4.17
+
+ *     Upgraded to kernel 2.1.14
+ *     Got lockd working with HPUX in most areas.
+
+Release 0.4.19
+
+ *     RPC server UDP sockets now receive the sk_buff directly rather
+       than going through sock->ops->recvmsg.
+       Also got rid of all those cli/sti's and replaced them with
+       disable_bh/enable_bh calls.
+ *     Fixed a bug in nfsd's handling of rename and friends.
+
+Release 0.4.20
+
+ *     Some bugfixes, esp in the writeback code
+ *     Avoid some unnecessary cli/sti pairs
+ *     Added nhfsstone
+
+Release 0.4.21
+
+ *     Minor bugfixes
+ *     Moved to post-2.1.16 module handling code
+
+Release 0.4.22
+
+ *     Fixed a bug that made rpcinfo -u host nlockmgr provoke a kernel
+       oops.
+ *     Upgraded to mount-2.6b
+ *     Added NFSv3 support to mountd and nfsd
+ *     Made sure it compiles with glibc2.
+
diff --git a/linux-nfs/INSTALL b/linux-nfs/INSTALL
new file mode 100644 (file)
index 0000000..351f733
--- /dev/null
@@ -0,0 +1,11 @@
+
+Even though the Makefiles offer a `make install' instruction,
+I would suggest against using it yet. I have run nfsd and the nfs
+client without kernel oopses for a while, but the picture may change
+if you start playing with lockd. Automatic installation may not even
+work for the kernel makefiles yet.
+
+I'd therefore advise that you use a separate Linux box for testing
+if you have one. Use the etc/copy script to copy all modules and
+support programs, and run the ins script to start the show. rmm
+will clean up afterwards (provided you didn't trigger an oops).
diff --git a/linux-nfs/KNOWNBUGS b/linux-nfs/KNOWNBUGS
new file mode 100644 (file)
index 0000000..b0ecd5c
--- /dev/null
@@ -0,0 +1,37 @@
+
+nfsd:
+
+ *     We currently keep the inode in the exports struct. This is
+       a bad idea with directories that are intended to be used as
+       a mount point. Must store the file name instead and do a
+       lookup when getfh is called. Yuck!
+
+       Even yuckier: what do we do about exports matching when we
+       can't keep the inode number?
+
+ *     stating a file on remote cdrom returns st_blocks == 0 for some
+       apps.
+
+ *     Should allow multiple exports per dev if one of the directories
+       isn't a subdir of the other.
+
+nfsclnt:
+
+ *     On some occasions, an EAGAIN reported by the transport layer
+       will be propagated to the VFS.
+ *     Some operations do not seem to release the inode properly, so
+       unmounting the device fails.
+
+lockd:
+
+ *     Handle portmap registration in a separate thread. portmap may
+       not be running when we try to mount the first NFS volume (esp.
+       when mounting /usr).
+
+ *     Does not inform rpc.statd when hosts no longer require
+       monitoring; hosts are incorrectly monitored until next system
+       reboot.
+
+exportfs/mountd:
+
+ *     Export handling is reported to do odd things at times.
diff --git a/linux-nfs/NEW b/linux-nfs/NEW
new file mode 100644 (file)
index 0000000..43f5c69
--- /dev/null
@@ -0,0 +1,319 @@
+This is the Linux kernel NFS daemon 1.4.7. It is based on linux-nfs
+0.4.22. It is tested on Linux/alpha and Linux/x86 running glibc 2.1.1.
+
+WARNING: The NFS servers in Linux 2.2 to 2.2.11 are not compatible with
+other NFS client implemenations. If you plan to use Linux 2.2.x as an
+NFS server for non-Linux NFS clients, you should apply the patches
+enlosed here.
+
+linux-2.2.7-sunrpc.patch, nfsd-2.2.7-2.lockd.patch, nfsd-2.2.7-3.patch
+and nfsd-2.2.7-nfsfh.patch are required for Linux 2.2.7 to 2.2.11.
+For other kernel versions, they have to be applied by hand if they are
+still needed.
+
+For Linux 2.2.7 to 2.2.10, nfsd-2.2.7-1.lock.patch is also required.
+
+I made my knfsd package available only because I use it and noone else
+seems to maintain it. But I don't have much time to really work on it.
+I will only fix bugs in the NFS utilities and serious kernel NFS bugs
+which I can duplcate easily. If you have any kernel NFS server problem,
+please report it to the Linux kernel mailing list. If it can be
+reproduced with Linux NFS server and client in less than 5 minutes, you
+can also send me a copy in addition to sending it to the Linux kernel
+mailing list. I may take a look when I have time. However I will collect
+kernel NFS related patches. Contributions are more than welcome.
+
+The NFS lock only works with lockd. Please make sure the portmapper,
+portmap, is started before mounting NFS.
+
+Changes from knfsd 1.4.6:
+
+1. Fix a typo in knfslock.init.
+2. A new kernel patch, nfsd-2.2.7-1.lock.patch, to fix some NFS lock
+   bugs.
+
+Changes from knfsd 1.4.5:
+
+1. Rename /var/lib/nfs/xtab.export to /var/lib/nfs/etab.
+
+Changes from knfsd 1.4.4:
+
+1. Try to fix mountd performance problem by introducing
+   /var/lib/nfs/xtab.export. That is
+   
+  a. "exportfs" reads from /var/lib/nfs/xtab and writes to
+     /var/lib/nfs/xtab.export.
+  b. "mountd" reads from /var/lib/nfs/xtab.export and writes to
+     /var/lib/nfs/xtab.
+
+  The idea is "mountd" doesn't have to read /var/lib/nfs/xtab, which
+  is very expensive.
+
+Changes from knfsd 1.4.3:
+
+1. nfsd-2.2.7-nfsfh.patch, a new kernel patch for filehandle.
+2. nfsd-2.2.7-2.lockd.patch, a new patch for lockd.
+3. Misc bug fixes.
+
+Changes from knfsd 1.4.2:
+
+1. A mountd patch so that the syslog reports unknown requests, and also
+   reports *what* is being (un)mounted, from Piete Brooks
+   <Piete.Brooks@cl.cam.ac.uk>.
+2. Fix knfsd.init for restart.
+3. Add knfslock.init.
+4. knfsd-compat.spec is removed.
+5. nfsd-2.2.7-lockd.patch, a patch to start lockd independent of
+   nfs and nfsd.
+
+Changes from knfsd 1.4.1:
+
+1. Resolve symlink for umount from Piete.Brooks@cl.cam.ac.uk (Piete
+   Brooks)
+2. Fix knfsd.init for statd.
+
+Changes from knfsd 1.4:
+
+1. nfsd-2.2.7-3.patch. This is the only patch you need for Linux 2.2.7
+   to 2.2.10.
+2. Remove
+       nfsd-2.2.5-1.patch
+       nfsd-2.2.5-3.patch
+       nfsd-2.2.8-1.patch
+       nfsd-2.2.7-iget.diff
+       nfsd-2.2.5-nfsfh.diff
+       nfsd-2.2.5-file.patch
+       nfsd-2.2.7-quota.patch
+       nfsd-2.2.7-mknod.patch
+3. Statd update by Jeff Uphoff <juphoff@transmeta.com>.
+4. netgroups patch from Peter Breitenlohner <peb@mppmu.mpg.de>.
+5. Add option checking to exportfs.
+
+Changes from knfsd 1.3.3b:
+
+1. Add linux-2.2.7-sunrpc.patch for a SMP bug in sunrpc.
+2. Add --port/-P to nfsd/mountd, by Jeff Johnson <jbj@redhat.com>.
+3. Add nfsd.8, mountd.8 and statd.man, by Olaf Kirch
+   <okir@monad.swb.de>.
+4. Update nfsstat.man by Olaf Kirch <okir@monad.swb.de>.
+5. Statd fix by Jeff Uphoff <juphoff@transmeta.com>.
+6. Remove knfsd-nok.patch.
+
+Changes from knfsd 1.3.3a:
+
+1. Fix stdin/stdout/stdout handling in mountd.
+2. nfsd-2.2.7-mknod.patch. A patch for mknod.
+3. nfsd-2.2.7-quota.patch. A patch for quota.
+
+Changes from knfsd 1.3.3:
+
+1. Fix hostname matching for wildcard, subnet and netgroup.
+
+Changes from knfsd 1.3.2:
+
+1. Modified mountd to allow clients without IP address to hostname map.
+
+Changes from knfsd 1.3.1a:
+
+1. nfsd-2.2.5-3.patch. This is the only patch you need for Linux 2.2.5.
+
+Changes from knfsd 1.3.1:
+
+1. A patch for knfsd.spec from Markus Linnala <maage@cs.tut.fi>.
+
+Changes from knfsd 1.3a:
+
+1. nfsd-2.2.8-1.patch. This is the only patch you need for Linux 2.2.8.
+2. nfsd-2.2.7-2.patch. This is the only patch you need for Linux 2.2.7.
+
+Changes from knfsd 1.3:
+
+1. Adding "--no-nfs-version 3" to mountd in knfsd.init from RedHat 6.0.
+
+Changes from knfsd 1.2.2a:
+
+1. Updated knfsd.init from RedHat 6.0.
+2. nfsd-2.2.7-1.patch. This is the only patch you need for Linux 2.2.7.
+3. Misc updates from RedHat 6.0.
+
+Changes from knfsd 1.2.2:
+
+1. Make the default NFS server kernel thread to 8 in the rc script.
+
+Changes from knfsd 1.2:
+
+1. Moved knfsd.spec to knfsd-compat.spec.
+2. Update knfsd.spec from knfsd-981204-3.src.rpm.
+3. Fix the squash_[ug]id parsing in /etc/exports from Anders
+   Hammarquist <iko@cd.chalmers.se>.
+4. nfsd-2.2.5-file.patch to clear the bogus bit for MKDIR and SYMLINK.
+5. nfsd-2.2.5-1.patch. A NFS patch based on nfsd-2.2.3-1.patch for
+   Linux 2.2.5.
+
+Changes from knfsd 1.1:
+
+1. Remove
+       cache-2.1.131-1.patch
+       linux-2.1.1xx.diff
+       lock-2.1.131.diff
+       lock-2.1.1xx.diff
+       nfsd-2.1.127-5.patch
+       nullproc-2.1.1xx.diff
+       procfs-2.1.127.patch
+       quota-2.1.1xx.diff
+       root-2.1.1xx.diff
+       socket-2.1.1xx.diff
+       sunrpc-2.1.123-1.patch
+2. locks-2.2.3.diff. A patch for file lock.
+3. nfsd-2.2.3-1.patch. A NFS patch by "G. Allen Morris III"
+(gam3@acm.org).
+
+Changes from knfsd 1.0:
+
+1. Handle broken /var/lib/nfs/rmtab.
+2. Handle lower/upper cases in wildcard hostnames in /etc/exports.
+
+Changes from knfsd-981204:
+
+1. Modify etc/rc.nfsd to check /var/lib/nfs/rmtab during startup.
+2. Add knfsd.spec for RedHat 5. Need nfs-server-2.2beta37-1.1.src.rpm
+   and initscripts-3.78.1-2.src.rpm.
+3. Add support for "make install prefix=...".
+
+Changes from knfsd-981122:
+
+1. Modify etc/rc.nfsd and etc/rc.nfsfs to handle statd during shutdown.
+2. Remove maximum knfsd count checking.
+3. Clean up mountd.
+4. cache-2.1.131-1.patch from G. Allen Morris III (gam3@acm.org).
+5. lock-2.1.131.diff. A nfsd lock patch for Linux 2.1.131.
+
+Changes from knfsd-981113:
+
+1. procfs-2.1.127.patch from G. Allen Morris III (gam3@acm.org).
+2. Modify etc/rc.nfsd and etc/rc.nfsfs to better handle statd.
+3. Fix the sub-mounted directories.
+
+Changes from knfsd-981022:
+
+1. Fix buffer overruns from Peter Benie <pjb1008@cus.cam.ac.uk>.
+2. Fix hostname matching.
+3. Correctly handle dupilcations in /etc/exports.
+4. Add -F flag to statd.
+5. nfsd-2.1.127-5.patch from G. Allen Morris III (gam3@acm.org).
+
+Changes from knfsd-981014:
+
+1. lock-2.1.1xx.diff. A nfsd lock patch.
+2. nullproc-2.1.1xx.diff. Allow any clients to call the nfsd NULL proc.
+3. Add etc/rc.nfsfs to handle statd.
+3. Update etc/rc.nfsd to handle statd.
+4. nfsd-2.1.125-2.patch from G. Allen Morris III (gam3@acm.org).
+5. Fix inet_ntoa usage in statd.
+
+Changes from knfsd-981010:
+
+1. Check client aliases when matching for wildcard client hostnames.
+2. Fix memory leak in mountd.
+3. Fix filename in nfsd-2.1.125-1.patch.
+
+Changes from knfsd-980930:
+
+1. nfsd-2.1.125-1.patch from G. Allen Morris III (gam3@acm.org) and me.
+2. Fix the hostent bugs in mountd and statd.
+3. Remove "kexportfs -au" for "rc.nfsd stop".
+
+Changes from knfsd-980925:
+
+1. socket-2.1.1xx.diff for creating socket on NFS client.
+2. There is a knsfd root_squash patch for Linux 2.1.1xx,
+   root-2.1.1xx.diff. It is only tested on linux 2.1.123.
+   It also fixes the server side 0711 mode bug.
+3. sunrpc-2.1.123-1.patch from Bill Hawes <whawes@transmeta.com>.
+4. nfsd-2.1.122-3.patch from G. Allen Morris III (gam3@acm.org).
+5. Various buffer overrun changes.
+6. Fix mountd to check the duplicated entry in rmtab.
+7. Change exportfs to ignore warnings for "-r".
+8. Fix showmount -e.
+
+Changes from knfsd-980922:
+
+1. nfsd-2.1.121-4.patch from G. Allen Morris III (gam3@acm.org).
+2. Make async as default for export. It matches the user space NFS
+   server.
+
+Changes from knfsd-980920:
+
+1. Add NFS mount version flags to mountd. Change rc.nfsd to disable
+   NFS V3 for mountd.
+2. Fix client hostname.
+3. rc.nfsd runs kexportfs with -r instead of -a for restart and reload.
+
+Changes from knfsd-980915:
+
+1. There is a knsfd quota patch for Linux 2.1.1xx, quota-2.1.1xx.diff.
+   It is only tested on linux 2.1.122.
+2. The submount pathname is removed from the xtab file.
+3. rc.nfsd runs kexportfs with -r instead of -a for start.
+4. Fix kshowmount -e.
+5. Fix hostname matching.
+6. Fix compiling on libc 5.
+
+Changes from knfsd-980910:
+
+1. nfsd-2.1.121-3.patch from G. Allen Morris III (gam3@acm.org).
+2. A new flag, -r, for exportfs.
+3. Don't put an entry in xtab if kernel rejects it.
+4. Use the official hostname when checking if 2 hostnames are the same.
+5. Allow submounts.
+
+It is available at
+
+ftp://ftp.varesearch.com/pub/support/hjl/knfsd/knfsd-1.4.7.tar.gz
+ftp://ftp.varesearch.com/pub/support/hjl/knfsd/knfsd-1.4.6-1.4.7.diff.gz
+ftp://ftp.kernel.org/pub/linux/devel/gcc/knfsd-1.4.7.tar.gz
+ftp://ftp.kernel.org/pub/linux/devel/gcc/knfsd-1.4.6-1.4.7.diff.gz
+
+You have to apply the patch, locks-2.2.3.diff, to the Linux kernel
+first. It fixes quite some file lock bugs. That patch is against Linux
+2.2.3. If your kernel is different, you have to apply it by hand.
+
+nfsd-2.2.3-1.patch is a new knfsd patch against linux 2.2.3 from
+"G. Allen Morris III" (gam3@acm.org). It works for me on x86 and alpha.
+It is needed for the none-Linux NFS clients. You can get Allen's
+current patch from
+
+http://www.CSUA.Berkeley.EDU/~gam3/knfsd/
+
+nfsd-2.2.7-3.patch is based on nfsd-2.2.3-1.patch for Linux 2.2.7. If
+you use Linux 2.2.7, you should apply nfsd-2.2.7-3.patch instead of
+nfsd-2.2.3-1.patch. Please don't use any other patches included here
+for Linux 2.2.7. For other kernel versions, you may have to apply it
+by hand.
+
+nfsd-2.2.7-2.lockd.patch is also necessary to start lockd independent
+of nfs and nfsd.
+
+To compile, just do
+
+# ./configure
+# make
+
+Makefile will try to determine which C library you are using and compile
+this package accordingly.
+
+# make install
+
+will install the knfsd binaries. You have to install a knfs start up
+script by hand. There is a new rc.nfsd in etc. I use it for both the
+user-space nfsd and the kernel nfsd.
+
+There is one RPM spec file, knfs.spec, which is for a Linux system
+based on Linux 2.2 without support for Linux 2.0. You also need
+knfsd-1.4.6.tar.gz to create the knfsd RPMs.
+
+Thanks.
+
+H.J.
+hjl@lucon.org
+08/14/99
diff --git a/linux-nfs/README b/linux-nfs/README
new file mode 100644 (file)
index 0000000..b210c61
--- /dev/null
@@ -0,0 +1,56 @@
+
+This package contains a greatly revised NFS implementation for Linux
+along with the necessary daemons and utilities. There are still several
+features missing that I'd want to include, and there are some recent
+improvements to the Linux NFS kernel client not reflected here (notably
+the attrtimeo fix).
+
+This thing has become much too large for me to handle all alone anymore.
+Originally, I had planned to have most of the NFS implementation running
+stably by August, so I could start to concentrate more on other jobs that
+are currently in the queue (like updating the NAG). As it turned out, it
+was much more work than I anticipated, and I fell short of my time goal.
+I'm therefore looking for volunteers who would like to work with me on
+finishing this package. Otherwise, this project could end up rusting in
+the corner of some FTP site...
+
+Ideally, I would want to hand over parts of the source tree to other
+hackers to maintain/enhance/etc. But that's not a requirement; if you
+feel you don't have that much time, you can also contribute by picking
+up one of the loose ends and finish what needs to be done (take a look
+at the TODO file...) And then, you can also be plainly a tester.
+
+There's currently a mailing list for lockd development at NRAO
+(lockd-statd@linux.nrao.edu --- mail majordomo@linux.nrao.edu to
+subscribe). If Jeff agress, we could turn this into a general linux-nfs
+mailing list.
+
+
+Hope this covers about what I wanted to say,
+Olaf
+
+------------------------------------------------------------------
+
+
+                       SOURCE TREE OVERVIEW
+
+
+
+support/       Support libraries for user-space programs
+
+support/nfs    Generic library for nfsd utilities
+support/export Manipulation of /etc/exports and /var/lib/nfs/{xtab,rmtab}
+
+utils/         Code for various user-space programs.
+utils/exportfs Management of nfsd export table.
+utils/mount    Modified mount command to support NFS over TCP.
+utils/mountd   New rpc.mountd for kernel nfsd.
+utils/nfsd     New nfsd (just starts kernel nfsd).
+utils/nfsstat  Pretty-print NFS stats from /proc/net/rpc/nfs*
+utils/rquotad  Marco van Wieringen's rquotad
+utils/showmount        Rick Sladkey's showmount client
+utils/statd    Jeff Uphoff's rpc.statd.
+
+tools/         Support tools for developers/debuggers/testers
+tools/rpcdebug This one sets/gets the debug flags for each of the kernel
+               modules.
diff --git a/linux-nfs/THANKS b/linux-nfs/THANKS
new file mode 100644 (file)
index 0000000..22a80dc
--- /dev/null
@@ -0,0 +1,10 @@
+
+       This piece of software owes a lot to all the people who
+       hacked on Linux NFS before me, most notably Rick Sladkey
+       and Donald Becker.
+
+       I also wish to thank Holger Grothe for loaning me a hard
+       disk and a monitor to get my old 486 flying again so I have
+       a decentish test platform.
+
+       Olaf
diff --git a/linux-nfs/TODO b/linux-nfs/TODO
new file mode 100644 (file)
index 0000000..3a439d4
--- /dev/null
@@ -0,0 +1,121 @@
+
+Todo/Status List for Linux-NFS
+
+ *     denotes to be done;
+ o     denotes draft implementation, possibly commented out
+ -     denotes done,
+ +     denotes done and tested
+------------------------------------------------------------------
+
+RPC:
+
+ *     Server-side AUTH_DES authentication
+
+NFS:
+
+ *     stat() calls don't check whether the cached attrs are stil valid
+       (this is a problem in the VFS).
+ -     NFS_ROOT stuff needs fixing.
+ o     Swapping over NFS.
+
+       Issues of swapout:
+        *      Avoid recursion in low memory situations where
+               kmalloc may call try_to_swap_out etc ad inf.
+        *      Don't do async I/O on swap files.
+
+       For special-casing related to NFS swap I/O, flag swap file 
+       semantics in inode->i_flags. In swapfile.c, change functions
+       to call readpage/writepage if available, otherwise proceed
+       as usual.
+
+ -     Write-back support.
+ *     Disable page cache invalidation/flushing for locked file
+       regions.
+ -     Directory caching (we now have page-sized dircache entries
+       which could easily be organized into a linked list). These
+       dircache pages come along as a linked list that can be copied
+       almost 1-to-1 into a dirent struct. If this is put into the
+       VFS, other remote fs's will also benefit.
+
+       [Note: I just increased the readdir cache to hold more than
+       one directory. With this, the exclusive lock on readdir goes
+       away, too. With a larger cache, it may also be worth to think
+       about directory readahead...]
+ *     Better lookup caching?
+ *     When a read lock is present, don't time out attr cache or
+       page cache for that region. Likewise, if a write lock is present,
+       be lazy on write-back.
+ *     Implement CTO.
+ -     BUG: Invalidate readdir cache after remove/rename/unlink
+ *     Automatic `mounting' when the server crosses mount points
+       transparently (some IRIX machines seem to do this when
+       using -nohide).
+ *     NFSv3 support. This requires careful design to maximize
+       code sharing between NFSv2 and NFSv3.
+ *     More robust rename handling (see comment before nfs_rename).
+ *     Add Miquel's O_EXCL hack for file creation.
+ *     Performance improvement: When a complete reply is received, and
+       the (async) task is woken up, don't put it on rpciod's scheduling
+       queue, but add it to a `fast scheduler queue.' The fast scheduler
+       could be a special handler that's registered on the tq_scheduler task
+       queue. This queue is fired by the kernel scheduler as soon as
+       the other bottom halves have been run.
+
+       Note that implementing this for sync tasks is even trickier than
+       for async tasks, because you have to make sure you do the right
+       thing in rpc_sleep_on().
+ *     writeback of writable mmaps. Dirty pages are not subject to
+       writeback scheduling. Also, msync should make sure pages are
+       written with O_SYNC on.
+
+
+nfsd:
+
+ *     uid/gid mapping, and rpc.ugidd support
+ -     Don't read/write a file that might have mandatory locks.
+ *     Implement secure/kerberos export options (take care of lockd
+       fopen() calls--most clients seem to use NULL creds for lockd).
+ -     there's a bug in readdir wrt large directories. Try mounting
+       the linux source tree and do an ls on include/linux...
+ *     Support for UNIX socket creation.
+ *     Someone should look over the error return codes. I tend to
+       mix up EPERM and EACCES.
+ *     NFSv3 support.
+ -     Refuse to look up inodes in procfs (security issues).
+ o     Delayed writes (delay syncing of file data when nfsd handles
+       several write requests for the same file concurrently).
+       (Draft - see nfsd_write in fs/nfsd/write.c. Needs benchmarking).
+ *     Faster read operations (single copy): mmap the file region
+       to be read into VM, and pass the VMA to the xdr routines
+       which pass the region's VM address into sock->ops->writemsg.
+       This copies the file data directly from the page cache into
+       the network buffer.
+       Release the vma region after encoding.
+ *     Faster write operations (single copy, with IPv6 net layout):
+       Get the unfragmented UDP datagram, pull the header and
+       do normal processing. Then mmap the file, copy the write data,
+       and release VMA.
+ -     Clear setuid/setgid bit after write().
+ *     Quota support.
+
+lockd:
+
+ *     Server should run on privileged port.
+ *     Testing reclaim support.
+ *     HP lockd accepts our GRANT_MSG callback and passes on the grant
+       to the blocking process, but doesn't reply with a GRANT_RES. 
+       It's not clear to me why it would do this.
+ *     Unregister hosts (SM_UNMON) with rpc.statd when appropriate.
+
+mountd
+
+ *     Unregister service from portmapper upon exit/SIGTERM
+
+mount
+
+ *     If available, use version 3 of the mount protocol and
+       obtain pathconf data (fill in data->bsize).
+
+documentation:
+
+ -     Manpages need to be written
diff --git a/nfs-utils.spec b/nfs-utils.spec
new file mode 100644 (file)
index 0000000..245c933
--- /dev/null
@@ -0,0 +1,80 @@
+Summary: The utilities for Linux NFS client and server.
+Name: nfs-utils
+Version: 0.1
+Release: 1
+Source0: ftp://ftp.valinux.com/pub/support/hjl/nfs/%{name}-%{version}.tar.gz
+Group: System Environment/Daemons
+Obsoletes: nfs-server nfs-server-clients knfsd knfsd-client knfsd-lock
+Provides: nfs-server nfs-server-clients knfsd knfsd-client knfsd-lock
+Copyright: GPL
+ExcludeArch: armv4l
+Buildroot: /var/tmp/%{name}-root
+Serial: 1
+Requires: kernel >= 2.2.5, portmap >= 4.0
+
+%description
+The nfs-utils package provides the utilities for Linux NFS client and
+server.
+
+%prep
+%setup -q
+
+%build
+./configure
+make all
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT{/sbin,/usr/{sbin,man/man5,man/man8}}
+mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
+mkdir -p $RPM_BUILD_ROOT/dev
+
+make install install_prefix=$RPM_BUILD_ROOT
+install -s -m 755 tools/rpcdebug/rpcdebug $RPM_BUILD_ROOT/sbin
+install -m 755 etc/redhat/nfsd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/nfs
+install -m 755 etc/redhat/nfslock.init $RPM_BUILD_ROOT/etc/rc.d/init.d/nfslock
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+/sbin/chkconfig --add nfs
+/sbin/chkconfig --add nfslock
+
+%preun
+if [ "$1" = "0" ]; then
+    /sbin/chkconfig --del nfs
+    /sbin/chkconfig --del nfslock
+fi
+
+%files
+%defattr(-,root,root)
+/sbin/rpcdebug
+/usr/sbin/exportfs
+/usr/sbin/nfsstat
+/usr/sbin/nhfsstone
+/usr/sbin/rpc.lockd
+/usr/sbin/rpc.mountd
+/usr/sbin/rpc.nfsd
+/usr/sbin/rpc.rquotad
+/usr/sbin/rpc.statd
+/usr/sbin/showmount
+/usr/man/man5/exports.5
+/usr/man/man8/exportfs.8
+/usr/man/man8/mountd.8
+/usr/man/man8/nfsd.8
+/usr/man/man8/nfsstat.8
+/usr/man/man8/rpc.mountd.8
+/usr/man/man8/rpc.nfsd.8
+/usr/man/man8/rpc.statd.8
+/usr/man/man8/rpc.rquotad.8
+/usr/man/man8/rquotad.8
+/usr/man/man8/showmount.8
+/usr/man/man8/statd.8
+%config /etc/rc.d/init.d/nfs
+%config /etc/rc.d/init.d/nfslock
+%dir /var/lib/nfs
+%config(noreplace) /var/lib/nfs/xtab
+%config(noreplace) /var/lib/nfs/etab
+%config(noreplace) /var/lib/nfs/rmtab
+%doc README
diff --git a/rules.mk b/rules.mk
new file mode 100644 (file)
index 0000000..c773460
--- /dev/null
+++ b/rules.mk
@@ -0,0 +1,126 @@
+#
+# General make rules
+#
+.DEFAULT:      all
+.PHONY:                $(ALLTARGETS)
+
+include $(TOP)config.mk
+
+##################################################################
+# Subdirectory handling
+##################################################################
+ifneq ($(SUBDIRS),)
+$(ALLTARGETS)::
+       @set -e; for d in $(SUBDIRS); do \
+               echo "Making $@ in $$d"; \
+               $(MAKE) --no-print-directory TOP=../$(TOP) -C $$d $@; \
+       done
+endif
+
+##################################################################
+# Building an RPC daemon
+##################################################################
+ifneq ($(PROGRAM),)
+TARGET = $(PROGRAM)
+
+$(PROGRAM): $(OBJS) $(LIBDEPS)
+       $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+install:: $(PROGRAM)
+       -$(MKDIR) $(SBINDIR)
+       $(INSTALLBIN) $(PROGRAM) $(SBINDIR)/$(PREFIX)$k$(PROGRAM)
+endif
+
+##################################################################
+# Building a tool
+##################################################################
+ifneq ($(TOOL),)
+TARGET = $(TOOL)
+
+$(TOOL): $(OBJS) $(LIBDEPS)
+       $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+endif
+
+##################################################################
+# Building a library
+##################################################################
+ifneq ($(LIBNAME),)
+TARGET = $(LIBNAME)
+
+$(LIBNAME): $(OBJS)
+       $(AR) cr $@ $^
+       $(RANLIB) $@
+endif
+
+##################################################################
+# Generic target rules
+##################################################################
+ifneq ($(TARGET),)
+all:: $(TARGET)
+       @echo "Building $(TARGET) done."
+
+install:: $(TARGET)
+
+distclean::
+       rm -f $(TARGET)
+endif
+
+##################################################################
+# Cleaning rules
+##################################################################
+clean distclean::
+       rm -f *.o *~ \#* a.out core
+
+distclean::
+       rm -f LOG X Y Z x y z .depend
+
+##################################################################
+# Manpage installation
+# Isn't GNU make a wonderful thing?
+##################################################################
+ifneq ($(MAN1)$(MAN5)$(MAN8)$(MAN9),)
+MANINIT        = ext=$(MAN$sEXT); dir=$(MAN$sDIR); pgs="$(MAN$s)";
+MANLOOP = $(MANINIT) for man in $$pgs; do eval $$cmd; done
+MDCMD  = $(MKDIR) \$$dir
+MICMD  = $(RM) \$$dir/\$$man.\$$ext; \
+         echo $(INSTALLMAN) \$$man.man \$$dir/\$$man.\$$ext; \
+         $(INSTALLMAN) \$$man.man \$$dir/\$$man.\$$ext
+LNCMD  = $(RM) \$$dir/$(PREFIX)\$$man.\$$ext; \
+         echo $(LN_S) \$$man.\$$ext \$$dir/$(PREFIX)\$$man.\$$ext; \
+         $(LN_S) \$$man.\$$ext \$$dir/$(PREFIX)\$$man.\$$ext
+PSCMD  = echo \"$(MAN2PS) \$$man.man > $(TOP)postscript/\$$man.ps\"; \
+         $(MAN2PS) \$$man.man > $(TOP)postscript/\$$man.ps
+
+installman::
+       @$(foreach s, 1 5 8 9, cmd="$(MDCMD)" $(MANLOOP);)
+       @$(foreach s, 1 5 8 9, cmd="$(MICMD)" $(MANLOOP);)
+ifneq ($(PREFIX),)
+       @$(foreach s, 1 5 8 9, cmd="$(LNCMD)" $(MANLOOP);)
+endif
+
+postscript::
+       @$(foreach s, 1 5 8 9, cmd="$(PSCMD)" $(MANLOOP);)
+else
+postscript installman::
+       @: No manpages...
+endif
+
+##################################################################
+# Indenting
+##################################################################
+ifneq ($(SRCS),)
+indent:
+       $(INDENT) $(SRCS)
+endif
+       
+##################################################################
+# Handling of dependencies
+##################################################################
+ifneq ($(OBJS),)
+depend dep::
+       $(CC) $(CFLAGS) -M $(OBJS:.o=.c) > .depend
+endif
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff --git a/support/Makefile b/support/Makefile
new file mode 100644 (file)
index 0000000..6b8598b
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for linux-nfs/support
+#
+
+SUBDIRS        = include nfs export lib
+.DEFAULT: all
+
+include $(TOP)rules.mk
+
diff --git a/support/export/Makefile b/support/export/Makefile
new file mode 100644 (file)
index 0000000..1243305
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# libexport.a
+# Miscellaneous utility functions related to exporting and mounting
+# of NFS volumes.
+#
+
+LIBNAME        = libexport.a
+SRCS   = $(RPCSRCS) client.c export.c hostname.c nfsctl.c rmtab.c \
+         xtab.c
+OBJS   = $(SRCS:.c=.o)
+
+RPCSRCS        = mount_clnt.c mount_xdr.c
+RPCHDRS        = mount.h
+
+include $(TOP)rules.mk
+
+$(RPCHDRS) $(RPCSRCS): mount.x
+       $(RM) $(RPCHDRS) $(RPCSRCS)
+       $(RPCGEN) -h -o mount.h $<
+       $(RPCGEN) -l -o mount_clnt.c $<
+       $(RPCGEN) -c -o mount_xdr.c $<
+
+clean distclean::
+       $(RM) $(RPCHDRS) $(RPCSRCS)
+
+install::
+       @:
diff --git a/support/export/client.c b/support/export/client.c
new file mode 100644 (file)
index 0000000..8c5200a
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * support/export/client.c
+ *
+ * Maintain list of nfsd clients.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include "xmalloc.h"
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+
+/* netgroup stuff never seems to be defined in any header file. Linux is
+ * not alone in this.
+ */
+#if !defined(__GLIBC__) || __GLIBC__ < 2
+extern int     innetgr(char *netgr, char *host, char *, char *);
+#endif
+static void    client_init(nfs_client *clp, const char *hname,
+                                       struct hostent *hp);
+static int     client_checkaddr(nfs_client *clp, struct in_addr addr);
+
+nfs_client     *clientlist[MCL_MAXTYPES] = { NULL, };
+
+
+nfs_client *
+client_lookup(char *hname)
+{
+       nfs_client      *clp = NULL;
+       int             htype;
+       struct hostent  *hp = NULL;
+
+       htype = client_gettype(hname);
+
+       if (htype == MCL_FQDN) {
+               hp = gethostbyname(hname);
+               if (hp == NULL || hp->h_addrtype != AF_INET) {
+                       xlog(L_ERROR, "%s has non-inet addr", hname);
+                       return NULL;
+               }
+               hp = hostent_dup (hp);
+               hname = (char *) hp->h_name;
+
+               for (clp = clientlist[htype]; clp; clp = clp->m_next) {
+                       if (client_check(clp, hp))
+                               break;
+               }
+       } else {
+               for (clp = clientlist[htype]; clp; clp = clp->m_next) {
+                       if (strcmp(hname, clp->m_hostname)==0)
+                               break;
+               }
+       }
+
+       if (!clp) {
+               clp = (nfs_client *) xmalloc(sizeof(*clp));
+               memset(clp, 0, sizeof(*clp));
+               clp->m_type = htype;
+               client_init(clp, hname, NULL);
+               client_add(clp);
+       }
+
+       if (htype == MCL_FQDN && clp->m_naddr == 0 && hp != NULL) {
+               char    **ap = hp->h_addr_list;
+               int     i;
+
+               for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++)
+                       clp->m_addrlist[i] = *(struct in_addr *)*ap;
+               clp->m_naddr = i;
+       }
+
+       if (hp)
+               free (hp);
+
+       return clp;
+}
+
+nfs_client *
+client_dup(nfs_client *clp, struct hostent *hp)
+{
+       nfs_client              *new;
+
+       new = (nfs_client *) xmalloc(sizeof(*new));
+       memcpy(new, clp, sizeof(*new));
+       new->m_type = MCL_FQDN;
+
+       client_init(new, (char *) hp->h_name, hp);
+       client_add(new);
+       return new;
+}
+
+static void
+client_init(nfs_client *clp, const char *hname, struct hostent *hp)
+{
+       if (hp) {
+               strncpy(clp->m_hostname, hp->h_name,
+                       sizeof (clp->m_hostname) -  1);
+       } else {
+               strncpy(clp->m_hostname, hname,
+                       sizeof (clp->m_hostname) - 1);
+       }
+       clp->m_hostname[sizeof (clp->m_hostname) - 1] = '\0';
+
+       clp->m_exported = 0;
+       clp->m_count = 0;
+
+       if (clp->m_type == MCL_SUBNETWORK) {
+               char    *cp = strchr(clp->m_hostname, '/');
+
+               *cp = '\0';
+               clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname);
+               clp->m_addrlist[1].s_addr = inet_addr(cp+1);
+               *cp = '/';
+               clp->m_naddr = 0;
+       } else if (!hp) {
+               clp->m_naddr = 0;
+       } else {
+               char    **ap = hp->h_addr_list;
+               int     i;
+
+               for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++) {
+                       clp->m_addrlist[i] = *(struct in_addr *)*ap;
+               }
+               clp->m_naddr = i;
+       }
+}
+
+void
+client_add(nfs_client *clp)
+{
+       nfs_client      **cpp;
+
+       if (clp->m_type < 0 || clp->m_type >= MCL_MAXTYPES)
+               xlog(L_FATAL, "unknown client type in client_add");
+       cpp = clientlist + clp->m_type;
+       while (*cpp)
+               cpp = &((*cpp)->m_next);
+       clp->m_next = NULL;
+       *cpp = clp;
+}
+
+void
+client_release(nfs_client *clp)
+{
+       if (clp->m_count <= 0)
+               xlog(L_FATAL, "client_free: m_count <= 0!");
+       clp->m_count--;
+}
+
+void
+client_freeall(void)
+{
+       nfs_client      *clp, **head;
+       int             i;
+
+       for (i = 0; i < MCL_MAXTYPES; i++) {
+               head = clientlist + i;
+               while (*head) {
+                       *head = (clp = *head)->m_next;
+                       xfree(clp);
+               }
+       }
+}
+
+nfs_client *
+client_find(struct hostent *hp)
+{
+       nfs_client      *clp;
+       int             i;
+
+       for (i = 0; i < MCL_MAXTYPES; i++) {
+               for (clp = clientlist[i]; clp; clp = clp->m_next) {
+                       if (!client_check(clp, hp))
+                               continue;
+#ifdef notdef
+                       if (clp->m_type == MCL_FQDN)
+                               return clp;
+                       return client_dup(clp, hp);
+#else
+                       return clp;
+#endif
+               }
+       }
+       return NULL;
+}
+
+/*
+ * Match a host (given its hostent record) to a client record. This
+ * is usually called from mountd.
+ */
+int
+client_check(nfs_client *clp, struct hostent *hp)
+{
+       char    *hname = (char *) hp->h_name;
+       char    *cname = clp->m_hostname;
+       char    **ap;
+
+       switch (clp->m_type) {
+       case MCL_FQDN:
+       case MCL_SUBNETWORK:
+               for (ap = hp->h_addr_list; *ap; ap++) {
+                       if (client_checkaddr(clp, *(struct in_addr *) *ap))
+                               return 1;
+               }
+               return 0;
+       case MCL_WILDCARD:
+               if (wildmat(hname, cname))
+                       return 1;
+               else {
+                       for (ap = hp->h_aliases; *ap; ap++)
+                               if (wildmat(*ap, cname))
+                                       return 1;
+               }
+               return 0;
+       case MCL_NETGROUP:
+#ifdef HAVE_INNETGR
+               {
+                       char    *dot;
+                       int     match;
+
+                       /* First, try to match the hostname without
+                        * splitting off the domain */
+                       if (innetgr(cname+1, hname, NULL, NULL))
+                               return 1;
+
+                       /* Okay, strip off the domain (if we have one) */
+                       if ((dot = strchr(hname, '.')) == NULL)
+                               return 0;
+
+                       *dot = '\0';
+                       match = innetgr(cname+1, hname, NULL, dot + 1);
+                       *dot = '.';
+
+                       return match;
+               }
+#else
+               return 0;
+#endif
+       case MCL_ANONYMOUS:
+               return 1;
+       default:
+               xlog(L_FATAL, "internal: bad client type %d", clp->m_type);
+       }
+
+       return 0;
+}
+
+static int
+client_checkaddr(nfs_client *clp, struct in_addr addr)
+{
+       int     i;
+
+       switch (clp->m_type) {
+       case MCL_FQDN:
+               for (i = 0; i < clp->m_naddr; i++) {
+                       if (clp->m_addrlist[i].s_addr == addr.s_addr)
+                               return 1;
+               }
+               return 0;
+       case MCL_SUBNETWORK:
+               return !((clp->m_addrlist[0].s_addr ^ addr.s_addr)
+                       & clp->m_addrlist[1].s_addr);
+       }
+       return 0;
+}
+
+int
+client_gettype(char *ident)
+{
+       char    *sp;
+
+       if (ident[0] == '\0')
+               return MCL_ANONYMOUS;
+       if (ident[0] == '@') {
+#ifndef HAVE_INNETGR
+               xlog(L_WARNING, "netgroup support not compiled in");
+#endif
+               return MCL_NETGROUP;
+       }
+       for (sp = ident; *sp; sp++) {
+               if (*sp == '*' || *sp == '?' || *sp == '[')
+                       return MCL_WILDCARD;
+               if (*sp == '/')
+                       return MCL_SUBNETWORK;
+               if (*sp == '\\' && sp[1])
+                       sp++;
+       }
+       return MCL_FQDN;
+}
diff --git a/support/export/export.c b/support/export/export.c
new file mode 100644 (file)
index 0000000..09efaa8
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * support/export/export.c
+ *
+ * Maintain list of exported file systems.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include "xmalloc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+
+nfs_export     *exportlist[MCL_MAXTYPES] = { NULL, };
+
+static void    export_init(nfs_export *exp, nfs_client *clp,
+                                       struct exportent *nep);
+static int     export_check(nfs_export *, struct hostent *, char *);
+static nfs_export *
+               export_allowed_internal(struct hostent *hp, char *path);
+
+int
+export_read(char *fname)
+{
+       struct exportent        *eep;
+       nfs_export              *exp;
+
+       setexportent(fname, "r");
+       while ((eep = getexportent()) != NULL) {
+         exp = export_lookup(eep->e_hostname, eep->e_path);
+         if (!exp)
+           export_create(eep);
+         else {
+           if (exp->m_export.e_flags != eep->e_flags) {
+             xlog(L_ERROR, "incompatible dupilcated export entries:");
+             xlog(L_ERROR, "\t%s:%s (0x%x) [IGNORED]", eep->e_hostname,
+                  eep->e_path, eep->e_flags);
+             xlog(L_ERROR, "\t%s:%s (0x%x)", exp->m_export.e_hostname,
+                  exp->m_export.e_path, exp->m_export.e_flags);
+           }
+           else {
+             xlog(L_ERROR, "dupilcated export entries:");
+             xlog(L_ERROR, "\t%s:%s", eep->e_hostname, eep->e_path);
+             xlog(L_ERROR, "\t%s:%s", exp->m_export.e_hostname,
+                  exp->m_export.e_path);
+           }
+         }
+       }
+       endexportent();
+
+       return 0;
+}
+
+/*
+ * Create an in-core export struct from an export entry.
+ */
+nfs_export *
+export_create(struct exportent *xep)
+{
+       nfs_client      *clp;
+       nfs_export      *exp;
+
+       if (!(clp = client_lookup(xep->e_hostname))) {
+               /* bad export entry; complaint already logged */
+               return NULL;
+       }
+       exp = (nfs_export *) xmalloc(sizeof(*exp));
+       export_init(exp, clp, xep);
+       export_add(exp);
+
+       return exp;
+}
+
+static void
+export_init(nfs_export *exp, nfs_client *clp, struct exportent *nep)
+{
+       struct exportent        *e = &exp->m_export;
+
+       dupexportent(e, nep);
+
+       exp->m_exported = 0;
+       exp->m_xtabent = 0;
+       exp->m_mayexport = 0;
+       exp->m_changed = 0;
+       exp->m_client = clp;
+       clp->m_count++;
+}
+
+/*
+ * Duplicate exports data. The in-core export struct retains the
+ * original hostname from /etc/exports, while the in-core client struct
+ * gets the newly found FQDN.
+ */
+nfs_export *
+export_dup(nfs_export *exp, struct hostent *hp)
+{
+       nfs_export              *new;
+       nfs_client              *clp;
+
+       new = (nfs_export *) xmalloc(sizeof(*new));
+       memcpy(new, exp, sizeof(*new));
+       dupexportent(&new->m_export, &exp->m_export);
+       clp = client_dup(exp->m_client, hp);
+       clp->m_count++;
+       new->m_client = clp;
+       new->m_mayexport = exp->m_mayexport;
+       new->m_exported = 0;
+       new->m_xtabent = 0;
+       new->m_changed = 0;
+       export_add(new);
+
+       return new;
+}
+
+void
+export_add(nfs_export *exp)
+{
+       nfs_export      **epp;
+       int             type = exp->m_client->m_type;
+       int             slen = strlen(exp->m_export.e_path);
+
+       if (type < 0 || type >= MCL_MAXTYPES)
+               xlog(L_FATAL, "unknown client type in export_add");
+
+       epp = exportlist + type;
+       while (*epp && slen < strlen((*epp)->m_export.e_path))
+               epp = &((*epp)->m_next);
+       exp->m_next = *epp;
+       *epp = exp;
+}
+
+nfs_export *
+export_find(struct hostent *hp, char *path)
+{
+       nfs_export      *exp;
+       int             i;
+
+       for (i = 0; i < MCL_MAXTYPES; i++) {
+               for (exp = exportlist[i]; exp; exp = exp->m_next) {
+                       if (!export_check(exp, hp, path))
+                               continue;
+                       if (exp->m_client->m_type == MCL_FQDN)
+                               return exp;
+                       return export_dup(exp, hp);
+               }
+       }
+
+       return NULL;
+}
+
+static nfs_export *
+export_allowed_internal (struct hostent *hp, char *path)
+{
+       nfs_export      *exp;
+       int             i;
+
+       for (i = 0; i < MCL_MAXTYPES; i++) {
+               for (exp = exportlist[i]; exp; exp = exp->m_next) {
+                       if (!exp->m_mayexport ||
+                           !export_check(exp, hp, path))
+                               continue;
+                       return exp;
+               }
+       }
+
+       return NULL;
+}
+
+struct exportent *
+export_allowed(struct hostent *hp, char *path)
+{
+       static struct exportent ee;
+       nfs_export              *exp;
+       char                    epath[MAXPATHLEN+1];
+       char                    *p = NULL;
+
+       if (path [0] != '/') return NULL;
+
+       strncpy(epath, path, sizeof (epath) - 1);
+       epath[sizeof (epath) - 1] = '\0';
+
+       /* Try the longest matching exported pathname. */
+       while (1) {
+               exp = export_allowed_internal (hp, epath);
+               if (exp) {
+                       dupexportent(&ee, &exp->m_export);
+                       return &ee;
+               }
+               /* We have to treat the root, "/", specially. */
+               if (p == &epath[1]) break;
+               p = strrchr(epath, '/');
+               if (p == epath) p++;
+               *p = '\0';
+       }
+
+       return NULL;
+}
+
+nfs_export *
+export_lookup(char *hname, char *path)
+{
+       nfs_client      *clp;
+       nfs_export      *exp;
+
+       if (!(clp = client_lookup(hname)))
+               return NULL;
+       for (exp = exportlist[clp->m_type]; exp; exp = exp->m_next)
+               if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path))
+                       return exp;
+       return NULL;
+}
+
+static int
+export_check(nfs_export *exp, struct hostent *hp, char *path)
+{
+       if (strcmp(path, exp->m_export.e_path))
+               return 0;
+
+       return client_check(exp->m_client, hp);
+}
+
+void
+export_freeall(void)
+{
+       nfs_export      *exp, *nxt;
+       int             i;
+
+       for (i = 0; i < MCL_MAXTYPES; i++) {
+               for (exp = exportlist[i]; exp; exp = nxt) {
+                       nxt = exp->m_next;
+                       client_release(exp->m_client);
+                       if (exp->m_export.e_squids)
+                               xfree(exp->m_export.e_squids);
+                       if (exp->m_export.e_sqgids)
+                               xfree(exp->m_export.e_sqgids);
+                       xfree(exp);
+               }
+               exportlist[i] = NULL;
+       }
+       client_freeall();
+}
+
+void
+export_reset(nfs_export *exp)
+{
+       if (!exp)
+               return;
+
+       /* Restore m_path. */
+       strncpy(exp->m_export.m_path, exp->m_export.e_path,
+               sizeof (exp->m_export.m_path) - 1);
+       exp->m_export.m_path[sizeof (exp->m_export.m_path) - 1] = '\0';
+}
diff --git a/support/export/hostname.c b/support/export/hostname.c
new file mode 100644 (file)
index 0000000..a37d4de
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * support/export/hostname.c
+ *
+ * Functions for hostname.
+ *
+ */
+
+#include "config.h"
+
+/*
+#define TEST
+*/
+
+#include <string.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#ifdef TEST
+#define xmalloc malloc
+#else
+#include "xmalloc.h"
+#include "misc.h"
+#endif
+
+#define ALIGNMENT      sizeof (char *)
+
+static int
+align (int len, int al)
+{
+  int i;
+  i = len % al;
+  if (i)
+    len += al - i;
+  return len;
+}
+
+struct hostent *
+get_hostent (const char *addr, int len, int type)
+{
+  struct hostent *cp;
+  int len_ent;
+  const char *name;
+  int len_name;
+  int num_aliases = 1;
+  int len_aliases = sizeof (char *);
+  int num_addr_list = 1;
+  int len_addr_list = sizeof (char *);
+  int pos;
+  struct in_addr *ipv4;
+
+  switch (type)
+    {
+    case AF_INET:
+      ipv4 = (struct in_addr *) addr;
+      name = inet_ntoa (*ipv4);
+      break;
+
+    default:
+      return NULL;
+    }
+
+  len_ent = align (sizeof (*cp), ALIGNMENT);
+  len_name = align (strlen (name) + 1, ALIGNMENT);
+
+  num_addr_list++;
+  len_addr_list += align (len, ALIGNMENT) + sizeof (char *);
+
+  cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases
+                                  + len_addr_list);
+
+  cp->h_addrtype = type;
+  cp->h_length = len;
+  pos = len_ent;
+  cp->h_name = (char *) &(((char *) cp) [pos]);
+  strcpy (cp->h_name, name);
+
+  pos += len_name;
+  cp->h_aliases = (char **) &(((char *) cp) [pos]);
+  pos += num_aliases * sizeof (char *);
+  cp->h_aliases [0] = NULL;
+
+  pos = len_ent + len_name + len_aliases;
+  cp->h_addr_list = (char **) &(((char *) cp) [pos]);
+  pos += num_addr_list * sizeof (char *);
+  cp->h_addr_list [0] = (char *) &(((char *) cp) [pos]);
+  memcpy (cp->h_addr_list [0], addr, cp->h_length);
+  pos += align (cp->h_length, ALIGNMENT);
+  cp->h_addr_list [1] = NULL;
+
+  return cp;
+}
+
+struct hostent *
+hostent_dup (struct hostent *hp)
+{
+  int len_ent = align (sizeof (*hp), ALIGNMENT);
+  int len_name = align (strlen (hp->h_name) + 1, ALIGNMENT);
+  int num_aliases = 1;
+  int len_aliases = sizeof (char *);
+  int num_addr_list = 1;
+  int len_addr_list = sizeof (char *);
+  int pos, i;
+  char **sp;
+  struct hostent *cp;
+
+  for (sp = hp->h_aliases; *sp; sp++)
+    {
+      num_aliases++;
+      len_aliases += align (strlen (*sp) + 1, ALIGNMENT)
+                    + sizeof (char *);
+    }
+
+  for (sp = hp->h_addr_list; *sp; sp++)
+    {
+      num_addr_list++;
+      len_addr_list += align (hp->h_length, ALIGNMENT)
+                      + sizeof (char *);
+    }
+  
+  cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases
+                                  + len_addr_list);
+
+  *cp = *hp;
+  pos = len_ent;
+  cp->h_name = (char *) &(((char *) cp) [pos]);
+  strcpy (cp->h_name, hp->h_name);
+
+  pos += len_name;
+  cp->h_aliases = (char **) &(((char *) cp) [pos]);
+  pos += num_aliases * sizeof (char *);
+  for (sp = hp->h_aliases, i = 0; i < num_aliases; i++, sp++)
+    if (*sp)
+      {
+       cp->h_aliases [i] = (char *) &(((char *) cp) [pos]);
+       strcpy (cp->h_aliases [i], *sp);
+       pos += align (strlen (*sp) + 1, ALIGNMENT);
+      }
+    else
+      cp->h_aliases [i] = *sp;
+
+  pos = len_ent + len_name + len_aliases;
+  cp->h_addr_list = (char **) &(((char *) cp) [pos]);
+  pos += num_addr_list * sizeof (char *);
+  for (sp = hp->h_addr_list, i = 0; i < num_addr_list; i++, sp++)
+    if (*sp)
+      {
+       cp->h_addr_list [i] = (char *) &(((char *) cp) [pos]);
+       memcpy (cp->h_addr_list [i], *sp, hp->h_length);
+       pos += align (hp->h_length, ALIGNMENT);
+      }
+    else
+      cp->h_addr_list [i] = *sp;
+
+  return cp;
+}
+
+static int
+is_hostname(const char *sp)
+{
+  if (*sp == '\0' || *sp == '@')
+    return 0;
+
+  for (; *sp; sp++)
+    {
+      if (*sp == '*' || *sp == '?' || *sp == '[' || *sp == '/')
+       return 0;
+      if (*sp == '\\' && sp[1])
+       sp++;
+    }
+
+  return 1;
+}
+
+int
+matchhostname (const char *h1, const char *h2)
+{
+  struct hostent *hp1, *hp2;
+  int status;
+
+  if (strcasecmp (h1, h2) == 0)
+    return 1;
+
+  if (!is_hostname (h1) || !is_hostname (h2))
+    return 0;
+
+  hp1 = gethostbyname (h1);
+  if (hp1 == NULL)
+    return 0;
+
+  hp1 = hostent_dup (hp1);
+
+  hp2 = gethostbyname (h2);
+  if (hp2)
+    {
+      if (strcasecmp (hp1->h_name, hp2->h_name) == 0)
+       status = 1;
+      else
+       {
+         char **ap1, **ap2;
+
+         status = 0;
+         for (ap1 = hp1->h_addr_list; *ap1 && status == 0; ap1++)
+           for (ap2 = hp2->h_addr_list; *ap2; ap2++)
+             if (memcmp (*ap1, *ap2, sizeof (struct in_addr)) == 0)
+               {
+                 status = 1;
+                 break;
+               }
+       }
+    }
+  else
+    status = 0;
+
+  free (hp1);
+  return status;
+}
+
+#ifdef TEST
+void
+print_host (struct hostent *hp)
+{
+  char **sp;
+
+  if (hp)
+    {
+      printf ("official hostname: %s\n", hp->h_name); 
+      printf ("aliases:\n");
+      for (sp = hp->h_aliases; *sp; sp++)
+       printf ("  %s\n", *sp);
+      printf ("IP addresses:\n");
+      for (sp = hp->h_addr_list; *sp; sp++)
+       printf ("  %s\n", inet_ntoa (*(struct in_addr *) *sp));
+    }
+  else
+    printf ("Not host information\n");
+}
+
+int
+main (int argc, char **argv)
+{
+  struct hostent *hp = gethostbyname (argv [1]);
+  struct hostent *cp;
+  struct in_addr addr;
+
+  print_host (hp);
+
+  if (hp)
+    {
+      cp = hostent_dup (hp);
+      print_host (cp);
+      free (cp);
+    }
+  printf ("127.0.0.1 == %s: %d\n", argv [1],
+         matchhostname ("127.0.0.1", argv [1]));
+  addr.s_addr = inet_addr(argv [2]);
+  printf ("%s\n", inet_ntoa (addr));
+  cp = get_hostent ((const char *)&addr, sizeof(addr), AF_INET);
+  print_host (cp);
+  return 0;
+}
+#endif
diff --git a/support/export/keys.c b/support/export/keys.c
new file mode 100644 (file)
index 0000000..4814808
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * keys.c              Key management for nfsd. Currently, keys
+ *                     are kept in a single file only, but eventually,
+ *                     support for a key server should be added.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/stat.h>
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xmalloc.h"
+
+struct keycache {
+       struct keycache *       k_next;
+       struct nfskeyent        k_data;
+};
+
+static struct keycache *       keycache = NULL;
+static time_t                  lastmod = 0;
+
+static void    key_reload(void);
+
+
+struct nfskey *
+key_lookup(char *hname)
+{
+       struct keycache *kc;
+
+       key_reload();
+
+       for (kc = keycache; kc; kc = kc->k_next) {
+#if 0
+               if (matchhostname(kc->k_data.k_hostname, hname))
+#else
+               if (!strcmp(kc->k_data.k_hostname, hname))
+#endif
+                       return &kc->k_data.k_key;
+       }
+
+       return NULL;
+}
+
+static void
+key_reload(void)
+{
+       struct stat     stb;
+       struct keycache *cp;
+       struct nfskeyent *kp;
+
+       if (stat(_PATH_NFSKEYS, &stb) >= 0 && stb.st_mtime == lastmod)
+               return;
+
+       while (keycache) {
+               cp = keycache->k_next;
+               xfree(keycache);
+               keycache = cp;
+       }
+
+       setnfskeyent(_PATH_NFSKEYS);
+       while ((kp = getnfskeyent()) != NULL) {
+               cp = (struct keycache *) xmalloc(sizeof(*cp));
+               cp->k_data = *kp;
+               cp->k_next = keycache;
+               keycache = cp;
+       }
+       endnfskeyent();
+
+       lastmod = stb.st_mtime;
+}
diff --git a/support/export/mount.x b/support/export/mount.x
new file mode 100644 (file)
index 0000000..f504e7c
--- /dev/null
@@ -0,0 +1,345 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part.  Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California  94043
+% */
+
+%/*
+% * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+% */
+%
+%/* from @(#)mount.x   1.3 91/03/11 TIRPC 1.0 */
+
+/*
+ * Protocol description for the mount program
+ */
+
+#ifdef RPC_HDR
+%#ifndef _rpcsvc_mount_h
+%#define _rpcsvc_mount_h
+%#include <memory.h>
+#endif
+
+const MNTPATHLEN = 1024;       /* maximum bytes in a pathname argument */
+const MNTNAMLEN = 255;         /* maximum bytes in a name argument */
+const FHSIZE = 32;             /* size in bytes of a file handle */
+
+/*
+ * The fhandle is the file handle that the server passes to the client.
+ * All file operations are done using the file handles to refer to a file
+ * or a directory. The file handle can contain whatever information the
+ * server needs to distinguish an individual file.
+ */
+typedef opaque fhandle[FHSIZE];        
+
+/*
+ * If a status of zero is returned, the call completed successfully, and 
+ * a file handle for the directory follows. A non-zero status indicates
+ * some sort of error. The status corresponds with UNIX error numbers.
+ */
+union fhstatus switch (unsigned fhs_status) {
+case 0:
+       fhandle fhs_fhandle;
+default:
+       void;
+};
+
+/*
+ * The type dirpath is the pathname of a directory
+ */
+typedef string dirpath<MNTPATHLEN>;
+
+/*
+ * The type name is used for arbitrary names (hostnames, groupnames)
+ */
+typedef string name<MNTNAMLEN>;
+
+/*
+ * A list of who has what mounted
+ */
+typedef struct mountbody *mountlist;
+struct mountbody {
+       name ml_hostname;
+       dirpath ml_directory;
+       mountlist ml_next;
+};
+
+/*
+ * A list of netgroups
+ */
+typedef struct groupnode *groups;
+struct groupnode {
+       name gr_name;
+       groups gr_next;
+};
+
+/*
+ * A list of what is exported and to whom
+ */
+typedef struct exportnode *exports;
+struct exportnode {
+       dirpath ex_dir;
+       groups ex_groups;
+       exports ex_next;
+};
+
+/*
+ * POSIX pathconf information
+ */
+struct ppathcnf {
+       int     pc_link_max;    /* max links allowed */
+       short   pc_max_canon;   /* max line len for a tty */
+       short   pc_max_input;   /* input a tty can eat all at once */
+       short   pc_name_max;    /* max file name length (dir entry) */
+       short   pc_path_max;    /* max path name length (/x/y/x/.. ) */
+       short   pc_pipe_buf;    /* size of a pipe (bytes) */
+       u_char  pc_vdisable;    /* safe char to turn off c_cc[i] */
+       char    pc_xxx;         /* alignment padding; cc_t == char */
+       short   pc_mask[2];     /* validity and boolean bits */
+};
+
+/*
+ * NFSv3 file handle
+ */
+const FHSIZE3 =        64;             /* max size of NFSv3 file handle in bytes */
+typedef opaque         fhandle3<FHSIZE3>;
+
+/*
+ * NFSv3 mount status
+ */
+enum mountstat3 {
+       MNT_OK                  = 0,    /* no error */
+       MNT3ERR_PERM            = 1,    /* not owner */
+       MNT3ERR_NOENT           = 2,    /* no such file or directory */
+       MNT3ERR_IO              = 5,    /* I/O error */
+       MNT3ERR_ACCES           = 13,   /* Permission denied */
+       MNT3ERR_NOTDIR          = 20,   /* Not a directory */
+       MNT3ERR_INVAL           = 22,   /* Invalid argument */
+       MNT3ERR_NAMETOOLONG     = 63,   /* File name too long */
+       MNT3ERR_NOTSUPP         = 10004,/* Operation not supported */
+       MNT3ERR_SERVERFAULT     = 10006 /* A failure on the server */
+};
+
+/*
+ * NFSv3 mount result
+ */
+struct mountres3_ok {
+       fhandle3        fhandle;
+       int             auth_flavors<>;
+};
+
+union mountres3 switch (mountstat3 fhs_status) {
+case MNT_OK:
+       mountres3_ok    mountinfo; /* File handle and supported flavors */
+default:
+       void;
+};
+
+program MOUNTPROG {
+       /*
+        * Version one of the mount protocol communicates with version two
+        * of the NFS protocol. The only connecting point is the fhandle 
+        * structure, which is the same for both protocols.
+        */
+       version MOUNTVERS {
+               /*
+                * Does no work. It is made available in all RPC services
+                * to allow server reponse testing and timing
+                */
+               void
+               MOUNTPROC_NULL(void) = 0;
+
+               /*      
+                * If fhs_status is 0, then fhs_fhandle contains the
+                * file handle for the directory. This file handle may
+                * be used in the NFS protocol. This procedure also adds
+                * a new entry to the mount list for this client mounting
+                * the directory.
+                * Unix authentication required.
+                */
+               fhstatus 
+               MOUNTPROC_MNT(dirpath) = 1;
+
+               /*
+                * Returns the list of remotely mounted filesystems. The 
+                * mountlist contains one entry for each hostname and 
+                * directory pair.
+                */
+               mountlist
+               MOUNTPROC_DUMP(void) = 2;
+
+               /*
+                * Removes the mount list entry for the directory
+                * Unix authentication required.
+                */
+               void
+               MOUNTPROC_UMNT(dirpath) = 3;
+
+               /*
+                * Removes all of the mount list entries for this client
+                * Unix authentication required.
+                */
+               void
+               MOUNTPROC_UMNTALL(void) = 4;
+
+               /*
+                * Returns a list of all the exported filesystems, and which
+                * machines are allowed to import it.
+                */
+               exports
+               MOUNTPROC_EXPORT(void)  = 5;
+
+               /*
+                * Identical to MOUNTPROC_EXPORT above
+                */
+               exports
+               MOUNTPROC_EXPORTALL(void) = 6;
+       } = 1;
+
+       /*
+        * Version two of the mount protocol communicates with version two
+        * of the NFS protocol.
+        * The only difference from version one is the addition of a POSIX
+        * pathconf call.
+        */
+       version MOUNTVERS_POSIX {
+               /*
+                * Does no work. It is made available in all RPC services
+                * to allow server reponse testing and timing
+                */
+               void
+               MOUNTPROC_NULL(void) = 0;
+
+               /*      
+                * If fhs_status is 0, then fhs_fhandle contains the
+                * file handle for the directory. This file handle may
+                * be used in the NFS protocol. This procedure also adds
+                * a new entry to the mount list for this client mounting
+                * the directory.
+                * Unix authentication required.
+                */
+               fhstatus 
+               MOUNTPROC_MNT(dirpath) = 1;
+
+               /*
+                * Returns the list of remotely mounted filesystems. The 
+                * mountlist contains one entry for each hostname and 
+                * directory pair.
+                */
+               mountlist
+               MOUNTPROC_DUMP(void) = 2;
+
+               /*
+                * Removes the mount list entry for the directory
+                * Unix authentication required.
+                */
+               void
+               MOUNTPROC_UMNT(dirpath) = 3;
+
+               /*
+                * Removes all of the mount list entries for this client
+                * Unix authentication required.
+                */
+               void
+               MOUNTPROC_UMNTALL(void) = 4;
+
+               /*
+                * Returns a list of all the exported filesystems, and which
+                * machines are allowed to import it.
+                */
+               exports
+               MOUNTPROC_EXPORT(void)  = 5;
+
+               /*
+                * Identical to MOUNTPROC_EXPORT above
+                */
+               exports
+               MOUNTPROC_EXPORTALL(void) = 6;
+
+               /*
+                * POSIX pathconf info (Sun hack)
+                */
+               ppathcnf
+               MOUNTPROC_PATHCONF(dirpath) = 7;
+       } = 2;
+
+       /*
+        * Version 3 of the protocol is for NFSv3
+        */
+       version MOUNTVERS_NFSV3 {
+               /*
+                * Does no work. It is made available in all RPC services
+                * to allow server reponse testing and timing
+                */
+               void
+               MOUNTPROC3_NULL(void) = 0;
+
+               /*      
+                * If fhs_status is 0, then fhs_fhandle contains the
+                * file handle for the directory. This file handle may
+                * be used in the NFS protocol. This procedure also adds
+                * a new entry to the mount list for this client mounting
+                * the directory.
+                * Unix authentication required.
+                */
+               mountres3 
+               MOUNTPROC3_MNT(dirpath) = 1;
+
+               /*
+                * Returns the list of remotely mounted filesystems. The 
+                * mountlist contains one entry for each hostname and 
+                * directory pair.
+                */
+               mountlist
+               MOUNTPROC3_DUMP(void) = 2;
+
+               /*
+                * Removes the mount list entry for the directory
+                * Unix authentication required.
+                */
+               void
+               MOUNTPROC3_UMNT(dirpath) = 3;
+
+               /*
+                * Removes all of the mount list entries for this client
+                * Unix authentication required.
+                */
+               void
+               MOUNTPROC3_UMNTALL(void) = 4;
+
+               /*
+                * Returns a list of all the exported filesystems, and which
+                * machines are allowed to import it.
+                */
+               exports
+               MOUNTPROC3_EXPORT(void)  = 5;
+       } = 3;
+} = 100005;
+
+#ifdef RPC_HDR
+%#endif /*!_rpcsvc_mount_h*/
+#endif
diff --git a/support/export/nfsctl.c b/support/export/nfsctl.c
new file mode 100644 (file)
index 0000000..6612a76
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * support/export/nfsctl.c
+ *
+ * Communicate export information to knfsd.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+
+static int     expsetup(struct nfsctl_export *exparg, nfs_export *exp);
+static int     cltsetup(struct nfsctl_client *cltarg, nfs_client *clp);
+
+int
+export_export(nfs_export *exp)
+{
+       nfs_client *    clp = exp->m_client;
+       struct nfsctl_export    exparg;
+       struct nfsctl_client    cltarg;
+
+       if (!clp->m_exported) {
+               if (!cltsetup(&cltarg, clp))
+                       return 0;
+               if (nfsaddclient(&cltarg) < 0)
+                       return 0;
+               clp->m_exported = 1;
+       }
+       if (!expsetup(&exparg, exp))
+               return 0;
+       if (nfsexport(&exparg) < 0)
+               return 0;
+       exp->m_exported = 1;
+       return 1;
+}
+
+int
+export_unexport(nfs_export *exp)
+{
+       struct nfsctl_export    exparg;
+
+       if (!expsetup(&exparg, exp) || nfsunexport(&exparg) < 0)
+               return 0;
+       exp->m_exported = 0;
+       return 1;
+}
+
+static void
+str_tolower(char *s)
+{
+       for ( ; *s; s++)
+               if (isupper(*s))
+                       *s = tolower(*s);
+}
+
+static int
+cltsetup(struct nfsctl_client *cltarg, nfs_client *clp)
+{
+       int     i;
+
+       if (clp->m_type != MCL_FQDN) {
+               xlog(L_ERROR, "internal: can't export non-FQDN host");
+               return 0;
+       }
+       memset(cltarg, 0, sizeof(*cltarg));
+       strncpy(cltarg->cl_ident, clp->m_hostname,
+               sizeof (cltarg->cl_ident) - 1);
+       str_tolower(cltarg->cl_ident);
+       cltarg->cl_naddr = clp->m_naddr;
+       for (i = 0; i < cltarg->cl_naddr && i < NFSCLNT_ADDRMAX; i++)
+               cltarg->cl_addrlist[i] = clp->m_addrlist[i];
+
+       return 1;
+}
+
+static int
+expsetup(struct nfsctl_export *exparg, nfs_export *exp)
+{
+       nfs_client              *clp = exp->m_client;
+       struct stat             stb;
+
+       if (stat(exp->m_export.m_path, &stb) < 0)
+               return 0;
+
+       memset(exparg, 0, sizeof(*exparg));
+       strncpy(exparg->ex_path, exp->m_export.m_path,
+               sizeof (exparg->ex_path) - 1);
+       strncpy(exparg->ex_client, clp->m_hostname,
+               sizeof (exparg->ex_client) - 1);
+       str_tolower(exparg->ex_client);
+       exparg->ex_flags    = exp->m_export.e_flags;
+       exparg->ex_dev      = stb.st_dev;
+       exparg->ex_ino      = stb.st_ino;
+       exparg->ex_anon_uid = exp->m_export.e_anonuid;
+       exparg->ex_anon_gid = exp->m_export.e_anongid;
+
+       return 1;
+}
diff --git a/support/export/rmtab.c b/support/export/rmtab.c
new file mode 100644 (file)
index 0000000..44a0edc
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * support/export/rmntab.c
+ *
+ * Interface to the rmnt file.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "xmalloc.h"
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+#include "xlog.h"
+
+int
+rmtab_read(void)
+{
+       struct rmtabent         *rep;
+       nfs_export              *exp;
+
+       setrmtabent("r");
+       while ((rep = getrmtabent(1)) != NULL) {
+               exp = export_lookup(rep->r_client, rep->r_path);
+               if (!exp) {
+                       struct exportent        *xp;
+                       struct hostent          *hp;
+                       int                     htype;
+
+                       htype = client_gettype(rep->r_client);
+                       if (htype == MCL_FQDN
+                           && (hp = gethostbyname (rep->r_client), hp)
+                           && (hp = hostent_dup (hp),
+                                  xp = export_allowed (hp, rep->r_path))) {
+                               strncpy (xp->e_hostname, rep->r_client,
+                                        sizeof (xp->e_hostname) - 1);
+                               xp->e_hostname[sizeof (xp->e_hostname) -1] = '\0';
+                               exp = export_create(xp);
+                               free (hp);
+                       }
+
+                       if (!exp)
+                               continue;
+                       exp->m_mayexport = 1;
+               }
+       }
+       if (errno == EINVAL) {
+               /* Something goes wrong. We need to fix the rmtab
+                  file. */
+               int     lockid;
+               FILE    *fp;
+               if ((lockid = xflock(_PATH_RMTAB, "w")) < 0)
+                       return -1;
+               rewindrmtabent();
+               if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) {
+                       endrmtabent ();
+                       xfunlock(lockid);
+                       return -1;
+               }
+               while ((rep = getrmtabent(0)) != NULL) {
+                       fputrmtabent(fp, rep);
+               }
+               if (rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) {
+                       xlog(L_ERROR, "couldn't rename %s to %s",
+                            _PATH_RMTABTMP, _PATH_RMTAB);
+               }
+               endrmtabent();
+               fendrmtabent(fp);
+               xfunlock(lockid);
+       }
+       else {
+               endrmtabent();
+       }
+       return 0;
+}
diff --git a/support/export/xtab.c b/support/export/xtab.c
new file mode 100644 (file)
index 0000000..4289d7c
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * support/export/xtab.c
+ *
+ * Interface to the xtab file.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "xmalloc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+#include "xlog.h"
+
+static int
+xtab_read(char *xtab, int is_export)
+{
+       struct exportent        *xp;
+       nfs_export              *exp;
+       int                     lockid;
+
+       if ((lockid = xflock(xtab, "r")) < 0)
+               return 0;
+       setexportent(xtab, "r");
+       while ((xp = getexportent()) != NULL) {
+               if (!(exp = export_lookup(xp->e_hostname, xp->e_path)) &&
+                   !(exp = export_create(xp))) {
+                       continue;
+               }
+               if (is_export) {
+                       exp->m_xtabent = 1;
+                       exp->m_mayexport = 1;
+               } else
+                       exp->m_exported = 1;
+       }
+       endexportent();
+       xfunlock(lockid);
+
+       return 0;
+}
+
+int
+xtab_mount_read(void)
+{
+       int fd;
+       if ((fd=open(_PATH_PROC_EXPORTS, O_RDONLY))>=0) {
+               close(fd);
+               return xtab_read(_PATH_PROC_EXPORTS, 0);
+       } else
+               return xtab_read(_PATH_XTAB, 0);
+}
+
+int
+xtab_export_read(void)
+{
+       return xtab_read(_PATH_ETAB, 1);
+}
+
+static int
+xtab_write(char *xtab, char *xtabtmp, int is_export)
+{
+       struct exportent        xe;
+       nfs_export              *exp;
+       int                     lockid, i;
+
+       if ((lockid = xflock(xtab, "w")) < 0) {
+               xlog(L_ERROR, "can't lock %s for writing", xtab);
+               return 0;
+       }
+       setexportent(xtabtmp, "w");
+
+       for (i = 0; i < MCL_MAXTYPES; i++) {
+               for (exp = exportlist[i]; exp; exp = exp->m_next) {
+                       if (is_export && !exp->m_xtabent)
+                               continue;
+                       if (!is_export && ! exp->m_exported)
+                               continue;
+
+                       /* write out the export entry using the FQDN */
+                       xe = exp->m_export;
+                       strncpy(xe.e_hostname,
+                               exp->m_client->m_hostname,
+                               sizeof (xe.e_hostname) - 1);
+                       xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0';
+                       putexportent(&xe);
+               }
+       }
+       endexportent();
+
+       rename(xtabtmp, xtab);
+
+       xfunlock(lockid);
+
+       return 1;
+}
+
+int
+xtab_export_write()
+{
+       return xtab_write(_PATH_ETAB, _PATH_ETABTMP, 1);
+}
+
+int
+xtab_mount_write()
+{
+       return xtab_write(_PATH_XTAB, _PATH_XTABTMP, 0);
+}
+
+void
+xtab_append(nfs_export *exp)
+{
+       struct exportent xe;
+       int             lockid;
+
+       if ((lockid = xflock(_PATH_XTAB, "w")) < 0)
+               return;
+       setexportent(_PATH_XTAB, "a");
+       xe = exp->m_export;
+       strncpy(xe.e_hostname, exp->m_client->m_hostname,
+              sizeof (xe.e_hostname) - 1);
+       xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0';
+       putexportent(&xe);
+       endexportent();
+       xfunlock(lockid);
+       exp->m_xtabent = 1;
+}
+
diff --git a/support/include/Makefile b/support/include/Makefile
new file mode 100644 (file)
index 0000000..e1cbfc4
--- /dev/null
@@ -0,0 +1,16 @@
+#
+# Makefile for linux-nfs/support
+#
+
+include $(TOP)rules.mk
+
+all install::  mount.h
+       @:
+
+distclean::
+       $(RM) mount.h config.h
+
+mount.h:
+       $(LN_S) ../export/mount.h .
+
+# .EXPORT_ALL_VARIABLES:
diff --git a/support/include/config.h.in b/support/include/config.h.in
new file mode 100644 (file)
index 0000000..f8c1497
--- /dev/null
@@ -0,0 +1,25 @@
+/* Define this if you have standard C headers
+ */
+#undef  STDC_HEADERS
+
+/* Define this if you have string.h */
+#undef  HAVE_STRING_H
+
+/* Define this if you have netgroup support
+ */
+#undef  HAVE_INNETGR
+
+/* Define this if you want NFSv3 support compiled in
+ */
+#undef  NFS3_SUPPORTED
+
+/* This defines the location of the NFS state files
+ * Warning: these must match definitions in config.mk!
+ */
+#define NFS_STATEDIR           "/var/lib/nfs"
+
+/* Define this if you want to enable various security
+ * checks in statd. These checks basically keep anyone
+ * but lockd from using this service.
+ */
+#undef RESTRICTED_STATD
diff --git a/support/include/exportfs.h b/support/include/exportfs.h
new file mode 100644 (file)
index 0000000..d440dc1
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * support/include/exportfs.h
+ *
+ * Declarations for exportfs and mountd
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef EXPORTFS_H
+#define EXPORTFS_H
+
+#include <netdb.h>
+#include "nfslib.h"
+
+enum {
+       MCL_FQDN = 0,
+       MCL_SUBNETWORK,
+       MCL_IPADDR = MCL_SUBNETWORK,
+       MCL_WILDCARD,
+       MCL_NETGROUP,
+       MCL_ANONYMOUS,
+       MCL_MAXTYPES
+};
+
+typedef struct mclient {
+       struct mclient *        m_next;
+       char                    m_hostname[NFSCLNT_IDMAX+1];
+       int                     m_type;
+       int                     m_naddr;
+       struct in_addr          m_addrlist[NFSCLNT_ADDRMAX];
+       int                     m_exported;     /* exported to nfsd */
+       int                     m_count;
+} nfs_client;
+
+typedef struct mexport {
+       struct mexport *        m_next;
+       struct mclient *        m_client;
+       struct exportent        m_export;
+       int                     m_exported : 1, /* known to knfsd */
+                               m_xtabent  : 1, /* xtab entry exists */
+                               m_mayexport: 1, /* derived from xtabbed */
+                               m_changed  : 1; /* options (may) have changed */
+} nfs_export;
+
+extern nfs_client *            clientlist[MCL_MAXTYPES];
+extern nfs_export *            exportlist[MCL_MAXTYPES];
+
+nfs_client *                   client_lookup(char *hname);
+nfs_client *                   client_find(struct hostent *);
+void                           client_add(nfs_client *);
+nfs_client *                   client_dup(nfs_client *, struct hostent *);
+int                            client_gettype(char *hname);
+int                            client_check(nfs_client *, struct hostent *);
+int                            client_match(nfs_client *, char *hname);
+void                           client_release(nfs_client *);
+void                           client_freeall(void);
+
+int                            export_read(char *fname);
+void                           export_add(nfs_export *);
+void                           export_reset(nfs_export *);
+nfs_export *                   export_lookup(char *hname, char *path);
+nfs_export *                   export_find(struct hostent *, char *path);
+struct exportent *             export_allowed(struct hostent *, char *path);
+nfs_export *                   export_create(struct exportent *);
+nfs_export *                   export_dup(nfs_export *, struct hostent *);
+void                           export_freeall(void);
+int                            export_export(nfs_export *);
+int                            export_unexport(nfs_export *);
+
+int                            xtab_mount_read(void);
+int                            xtab_export_read(void);
+int                            xtab_mount_write(void);
+int                            xtab_export_write(void);
+void                           xtab_append(nfs_export *);
+
+int                            rmtab_read(void);
+
+struct nfskey *                        key_lookup(char *hname);
+
+#endif /* EXPORTFS_H */
diff --git a/support/include/misc.h b/support/include/misc.h
new file mode 100644 (file)
index 0000000..a3cdcfd
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * misc.h      All that didn't fit elsewhere.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef MISC_H
+#define MISC_H
+
+/*
+ * Generate random key, returning the length of the result. Currently,
+ * weakrandomkey generates a maximum of 20 bytes are generated, but this
+ * may change with future implementations.
+ */
+int    randomkey(unsigned char *keyout, int len);
+int    weakrandomkey(unsigned char *keyout, int len);
+
+int    matchhostname(const char *h1, const char *h2); 
+
+struct hostent;
+struct hostent *hostent_dup(struct hostent *hp);
+struct hostent *get_hostent (const char *addr, int len, int type);
+
+#endif /* MISC_H */
diff --git a/support/include/nfs/debug.h b/support/include/nfs/debug.h
new file mode 100644 (file)
index 0000000..876b5db
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef _NFS_DEBUG_H
+#define _NFS_DEBUG_H
+
+/*
+ * RPC debug facilities
+ */
+#define RPCDBG_XPRT            0x0001
+#define RPCDBG_CALL            0x0002
+#define RPCDBG_DEBUG           0x0004
+#define RPCDBG_NFS             0x0008
+#define RPCDBG_AUTH            0x0010
+#define RPCDBG_PMAP            0x0020
+#define RPCDBG_SCHED           0x0040
+#define RPCDBG_SVCSOCK         0x0100
+#define RPCDBG_SVCDSP          0x0200
+#define RPCDBG_MISC            0x0400
+#define RPCDBG_ALL             0x7fff
+
+/*
+ * Declarations for the sysctl debug interface, which allows to read or
+ * change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc
+ * module currently registers its sysctl table dynamically, the sysctl path
+ * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
+ */
+#define CTL_SUNRPC     7249    /* arbitrary and hopefully unused */
+
+enum {
+       CTL_RPCDEBUG = 1,
+       CTL_NFSDEBUG,
+       CTL_NFSDDEBUG,
+       CTL_NLMDEBUG,
+};
+
+
+/*
+ * knfsd debug flags
+ */
+#define NFSDDBG_SOCK           0x0001
+#define NFSDDBG_FH             0x0002
+#define NFSDDBG_EXPORT         0x0004
+#define NFSDDBG_SVC            0x0008
+#define NFSDDBG_PROC           0x0010
+#define NFSDDBG_FILEOP         0x0020
+#define NFSDDBG_AUTH           0x0040
+#define NFSDDBG_REPCACHE       0x0080
+#define NFSDDBG_XDR            0x0100
+#define NFSDDBG_LOCKD          0x0200
+#define NFSDDBG_ALL            0x7FFF
+#define NFSDDBG_NOCHANGE       0xFFFF
+
+/*
+ * Debug flags
+ */
+#define NLMDBG_SVC             0x0001
+#define NLMDBG_CLIENT          0x0002
+#define NLMDBG_CLNTLOCK                0x0004
+#define NLMDBG_SVCLOCK         0x0008
+#define NLMDBG_MONITOR         0x0010
+#define NLMDBG_CLNTSUBS                0x0020
+#define NLMDBG_SVCSUBS         0x0040
+#define NLMDBG_HOSTCACHE       0x0080
+#define NLMDBG_ALL             0x7fff
+
+
+#define NFSDBG_VFS             0x0001
+#define NFSDBG_DIRCACHE                0x0002
+#define NFSDBG_LOOKUPCACHE     0x0004
+#define NFSDBG_PAGECACHE       0x0008
+#define NFSDBG_PROC            0x0010
+#define NFSDBG_XDR             0x0020
+#define NFSDBG_FILE            0x0040
+#define NFSDBG_ROOT            0x0080
+#define NFSDBG_ALL             0xFFFF
+
+#endif /* _NFS_DEBUG_H */
diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h
new file mode 100644 (file)
index 0000000..80d23fd
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _NSF_EXPORT_H
+#define _NSF_EXPORT_H
+
+/*
+ * Important limits for the exports stuff.
+ */
+#define NFSCLNT_IDMAX          1024
+#define NFSCLNT_ADDRMAX                16
+#define NFSCLNT_KEYMAX         32
+
+/*
+ * Export flags.
+ */
+#define NFSEXP_READONLY                0x0001
+#define NFSEXP_INSECURE_PORT   0x0002
+#define NFSEXP_ROOTSQUASH      0x0004
+#define NFSEXP_ALLSQUASH       0x0008
+#define NFSEXP_ASYNC           0x0010
+#define NFSEXP_GATHERED_WRITES 0x0020
+#define NFSEXP_UIDMAP          0x0040
+#define NFSEXP_KERBEROS                0x0080          /* not available */
+#define NFSEXP_SUNSECURE       0x0100
+#define NFSEXP_CROSSMNT                0x0200          /* not available */
+#define NFSEXP_ALLFLAGS                0x03FF
+
+#endif /* _NSF_EXPORT_H */
diff --git a/support/include/nfs/nfs.h b/support/include/nfs/nfs.h
new file mode 100644 (file)
index 0000000..0cfed07
--- /dev/null
@@ -0,0 +1,145 @@
+#ifndef _NFS_NFS_H
+#define _NFS_NFS_H
+
+#include <linux/posix_types.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <rpcsvc/nfs_prot.h>
+#include <nfs/export.h>
+
+struct dentry;
+
+/*
+ * This is the new "dentry style" Linux NFSv2 file handle.
+ *
+ * The xino and xdev fields are currently used to transport the
+ * ino/dev of the exported inode.
+ */
+struct nfs_fhbase {
+       struct dentry * fb_dentry;      /* dentry cookie */
+       u_int32_t               fb_ino;         /* our inode number */
+       u_int32_t               fb_dirino;      /* dir inode number */
+       u_int32_t               fb_dev;         /* our device */
+       u_int32_t               fb_xdev;
+       u_int32_t               fb_xino;
+};
+
+#define NFS_FH_PADDING         (NFS_FHSIZE - sizeof(struct nfs_fhbase))
+struct knfs_fh {
+       struct nfs_fhbase       fh_base;
+       u_int8_t                        fh_cookie[NFS_FH_PADDING];
+};
+
+#define fh_dcookie             fh_base.fb_dentry
+#define fh_ino                 fh_base.fb_ino
+#define fh_dirino              fh_base.fb_dirino
+#define fh_dev                 fh_base.fb_dev
+#define fh_xdev                        fh_base.fb_xdev
+#define fh_xino                        fh_base.fb_xino
+
+/*
+ * Version of the syscall interface
+ */
+#define NFSCTL_VERSION         0x0201
+
+/*
+ * These are the commands understood by nfsctl().
+ */
+#define NFSCTL_SVC             0       /* This is a server process. */
+#define NFSCTL_ADDCLIENT       1       /* Add an NFS client. */
+#define NFSCTL_DELCLIENT       2       /* Remove an NFS client. */
+#define NFSCTL_EXPORT          3       /* export a file system. */
+#define NFSCTL_UNEXPORT                4       /* unexport a file system. */
+#define NFSCTL_UGIDUPDATE      5       /* update a client's uid/gid map. */
+#define NFSCTL_GETFH           6       /* get an fh (used by mountd) */
+#define NFSCTL_GETFD           7       /* get an fh by path (used by mountd) */
+
+/* Above this is for lockd. */
+#define NFSCTL_LOCKD           0x10000
+#define LOCKDCTL_SVC           NFSCTL_LOCKD
+
+
+
+/* SVC */
+struct nfsctl_svc {
+       unsigned short          svc_port;
+       int                     svc_nthreads;
+};
+
+/* ADDCLIENT/DELCLIENT */
+struct nfsctl_client {
+       char                    cl_ident[NFSCLNT_IDMAX+1];
+       int                     cl_naddr;
+       struct in_addr          cl_addrlist[NFSCLNT_ADDRMAX];
+       int                     cl_fhkeytype;
+       int                     cl_fhkeylen;
+       unsigned char           cl_fhkey[NFSCLNT_KEYMAX];
+};
+
+/* EXPORT/UNEXPORT */
+struct nfsctl_export {
+       char                    ex_client[NFSCLNT_IDMAX+1];
+       char                    ex_path[NFS_MAXPATHLEN+1];
+       __kernel_dev_t          ex_dev;
+       __kernel_ino_t          ex_ino;
+       int                     ex_flags;
+       __kernel_uid_t          ex_anon_uid;
+       __kernel_gid_t          ex_anon_gid;
+};
+
+/* UGIDUPDATE */
+struct nfsctl_uidmap {
+       char *                  ug_ident;
+       __kernel_uid_t          ug_uidbase;
+       int                     ug_uidlen;
+       __kernel_uid_t *        ug_udimap;
+       __kernel_gid_t          ug_gidbase;
+       int                     ug_gidlen;
+       __kernel_gid_t *        ug_gdimap;
+};
+
+/* GETFH */
+struct nfsctl_fhparm {
+       struct sockaddr         gf_addr;
+       __kernel_dev_t          gf_dev;
+       __kernel_ino_t          gf_ino;
+       int                     gf_version;
+};
+
+/* GETFD */
+struct nfsctl_fdparm {
+       struct sockaddr         gd_addr;
+       char                    gd_path[NFS_MAXPATHLEN+1];
+       int                     gd_version;
+};
+
+/*
+ * This is the argument union.
+ */
+struct nfsctl_arg {
+       int                     ca_version;     /* safeguard */
+       union {
+               struct nfsctl_svc       u_svc;
+               struct nfsctl_client    u_client;
+               struct nfsctl_export    u_export;
+               struct nfsctl_uidmap    u_umap;
+               struct nfsctl_fhparm    u_getfh;
+               struct nfsctl_fdparm    u_getfd;
+               unsigned int            u_debug;
+       } u;
+#define ca_svc         u.u_svc
+#define ca_client      u.u_client
+#define ca_export      u.u_export
+#define ca_umap                u.u_umap
+#define ca_getfh       u.u_getfh
+#define ca_getfd       u.u_getfd
+#define ca_authd       u.u_authd
+#define ca_debug       u.u_debug
+};
+
+union nfsctl_res {
+       struct knfs_fh          cr_getfh;
+       unsigned int            cr_debug;
+};
+
+#endif /* _NFS_NFS_H */
diff --git a/support/include/nfslib.h b/support/include/nfslib.h
new file mode 100644 (file)
index 0000000..d8be926
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * support/include/nfslib.h
+ *
+ * General support functions for NFS user-space programs.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef NFSLIB_H
+#define NFSLIB_H
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <paths.h>
+#include <rpcsvc/nfs_prot.h>
+#include <nfs/nfs.h>
+#include "xlog.h"
+
+#ifndef _PATH_EXPORTS
+#define _PATH_EXPORTS          "/etc/exports"
+#endif
+#ifndef _PATH_XTAB
+#define _PATH_XTAB             NFS_STATEDIR "/xtab"
+#endif
+#ifndef _PATH_XTABTMP
+#define _PATH_XTABTMP          NFS_STATEDIR "/xtab.tmp"
+#endif
+#ifndef _PATH_ETAB
+#define _PATH_ETAB             NFS_STATEDIR "/etab"
+#endif
+#ifndef _PATH_ETABTMP
+#define _PATH_ETABTMP          NFS_STATEDIR "/etab.tmp"
+#endif
+#ifndef _PATH_RMTAB
+#define _PATH_RMTAB            NFS_STATEDIR "/rmtab"
+#endif
+#ifndef _PATH_RMTABTMP
+#define _PATH_RMTABTMP         _PATH_RMTAB ".tmp"
+#endif
+#ifndef _PATH_PROC_EXPORTS
+#define        _PATH_PROC_EXPORTS      "/proc/fs/nfs/exports"
+#endif
+
+enum cle_maptypes {
+       CLE_MAP_IDENT = 0,
+       CLE_MAP_FILE,
+       CLE_MAP_UGIDD,
+};
+
+/*
+ * Data related to a single exports entry as returned by getexportent.
+ * FIXME: export options should probably be parsed at a later time to 
+ * allow overrides when using exportfs.
+ */
+struct exportent {
+       char            e_hostname[NFSCLNT_IDMAX+1];
+       char            e_path[NFS_MAXPATHLEN+1];
+       /* The mount path may be different from the exported path due
+          to submount. It may change for every mount. The idea is we
+          set m_path every time when we process a mount. We should not
+          use it for anything else. */
+       char            m_path[NFS_MAXPATHLEN+1];
+       int             e_flags;
+       int             e_maptype;
+       int             e_anonuid;
+       int             e_anongid;
+       int *           e_squids;
+       int             e_nsquids;
+       int *           e_sqgids;
+       int             e_nsqgids;
+};
+
+struct rmtabent {
+       char            r_client[NFSCLNT_IDMAX+1];
+       char            r_path[NFS_MAXPATHLEN+1];
+};
+
+/*
+ * configuration file parsing
+ */
+void                   setexportent(char *fname, char *type);
+struct exportent *     getexportent(void);
+void                   putexportent(struct exportent *xep);
+void                   endexportent(void);
+struct exportent *     mkexportent(char *hname, char *path, char *opts);
+void                   dupexportent(struct exportent *dst,
+                                       struct exportent *src);
+int                    updateexportent(struct exportent *eep, char *options);
+
+int                    setrmtabent(char *type);
+struct rmtabent *      getrmtabent(int log);
+void                   putrmtabent(struct rmtabent *xep);
+void                   endrmtabent(void);
+void                   rewindrmtabent(void);
+FILE *                 fsetrmtabent(char *fname, char *type);
+struct rmtabent *      fgetrmtabent(FILE *fp, int log);
+void                   fputrmtabent(FILE *fp, struct rmtabent *xep);
+void                   fendrmtabent(FILE *fp);
+void                   frewindrmtabent(FILE *fp);
+
+/*
+ * wildmat borrowed from INN
+ */
+int                    wildmat(char *text, char *pattern);
+
+/*
+ * nfsd library functions.
+ */
+int                    nfsctl(int, struct nfsctl_arg *, union nfsctl_res *);
+int                    nfssvc(int port, int nrservs);
+int                    nfsaddclient(struct nfsctl_client *clp);
+int                    nfsdelclient(struct nfsctl_client *clp);
+int                    nfsexport(struct nfsctl_export *exp);
+int                    nfsunexport(struct nfsctl_export *exp);
+struct knfs_fh *       getfh_old(struct sockaddr *addr, dev_t dev, ino_t ino);
+struct knfs_fh *       getfh(struct sockaddr *addr, const char *);
+
+/* lockd. */
+int                    lockdsvc();
+
+#endif /* NFSLIB_H */
diff --git a/support/include/rpcdispatch.h b/support/include/rpcdispatch.h
new file mode 100644 (file)
index 0000000..866d4bf
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *     nlm_dispatch    This is a generic RPC call dispatcher.
+ *                     It is loosely based on the dispatch mechanism I
+ *                     first encountered in the UNFSD source.
+ *
+ *     Cyopright (C) 1995, Olaf Kirch <okir@monad.swb.de>
+ *
+ *     24.05.95        okir
+ *
+ */
+
+#ifndef RPCDISPATCH_H
+#define RPCDISPATCH_H
+
+#include <rpc/rpc.h>
+
+#ifdef __STDC__
+#   define CONCAT(a,b)         a##b
+#   define CONCAT3(a,b,c)      a##b##c
+#   define STRING(a)           #a
+#else
+#   define CONCAT(a,b)         a/**/b
+#   define CONCAT3(a,b,c)      a/**/b/**/c
+#   define STRING(a)           "a"
+#endif
+
+#ifdef __STDC__
+typedef bool_t (*rpcsvc_fn_t)(struct svc_req *, void *argp, void *resp);
+#else
+typedef bool_t (*rpcsvc_fn_t)();
+#endif
+
+#define table_ent(func, vers, arg_type, res_type) \
+       {       STRING(func), \
+               (rpcsvc_fn_t)CONCAT(func,_svc), vers,\
+               (xdrproc_t)CONCAT(xdr_, arg_type), sizeof(arg_type), \
+               (xdrproc_t)CONCAT(xdr_, res_type), sizeof(res_type), \
+       }
+#define nlm_undef_svc  NULL
+#define xdr_nlm_void   xdr_void
+
+struct dispatch_entry {
+       const char      *name;
+       rpcsvc_fn_t     func;
+       unsigned int    versions;               /* bitmap of versions */
+       xdrproc_t       xdr_arg_fn;             /* argument XDR */
+       size_t          xdr_arg_size;
+       xdrproc_t       xdr_res_fn;             /* result XDR */
+       size_t          xdr_res_size;
+};
+
+void   rpc_dispatch(struct svc_req *rq, SVCXPRT *tp,
+                       struct dispatch_entry *dtable, int nproc,
+                       void *argp, void *resp);
+void   rpc_svcrun(void);
+
+#endif /* RPCDISPATCH_H */
diff --git a/support/include/rpcmisc.h b/support/include/rpcmisc.h
new file mode 100644 (file)
index 0000000..06970cd
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * rpcmisc     Support for RPC startup, dispatching and logging.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef RPCMISC_H
+#define RPCMISC_H
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+
+#ifdef __STDC__
+#   define CONCAT(a,b)         a##b
+#   define STRING(a)           #a
+#else
+#   define CONCAT(a,b)         a/**/b
+#   define STRING(a)           "a"
+#endif
+
+typedef bool_t (*rpcsvc_fn_t)(struct svc_req *, void *argp, void *resp);
+
+struct rpc_dentry {
+       const char      *name;
+       rpcsvc_fn_t     func;
+       xdrproc_t       xdr_arg_fn;             /* argument XDR */
+       size_t          xdr_arg_size;
+       xdrproc_t       xdr_res_fn;             /* result XDR */
+       size_t          xdr_res_size;
+};
+
+struct rpc_dtable {
+       struct rpc_dentry *entries;
+       int             nproc;
+};
+
+#define dtable_ent(func, vers, arg_type, res_type) \
+       {       STRING(func), \
+               (rpcsvc_fn_t)func##_##vers##_svc, \
+               (xdrproc_t)xdr_##arg_type, sizeof(arg_type), \
+               (xdrproc_t)xdr_##res_type, sizeof(res_type), \
+       }
+
+void           rpc_init(char *name, int prog, int vers,
+                               void (*dispatch)(struct svc_req *, SVCXPRT *),
+                               int defport, int bufsize);
+void           rpc_svcrun(void);
+void           rpc_dispatch(struct svc_req *rq, SVCXPRT *xprt,
+                               struct rpc_dtable *dtable, int nvers,
+                               void *argp, void *resp);
+void           rpc_logcall(struct svc_req *, char *xname, char *args);
+
+extern int     _rpcpmstart;
+extern int     _rpcfdtype;
+extern int     _rpcsvcdirty;
+
+
+#endif /* RPCMISC_H */
diff --git a/support/include/rpcsec.h b/support/include/rpcsec.h
new file mode 100644 (file)
index 0000000..84d4497
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  Declarations needed for the authdes library. Some of the functions
+ *  mentioned herein have been omitted from the Linux libc header files
+ */
+
+#ifndef RPCSEC_H
+#define RPCSEC_H
+
+int    netname2user(char *netname, int *uidp, int *gidp,
+                                       int *gidlenp, int *gidlist);
+int    netname2host(char *netname, char *hostname, int hostlen);
+int    getnetname(char *name);
+int    user2netname(char *netname, int uid, char *domain);
+int    host2netname(char *netname, char *hostname, char *domain);
+void   passwd2des(char *pw, char *key);
+int    getsecretkey(char *netname, char *secretkey, char *passwd);
+int    getpublickey(char *hostname, char *publickey);
+int    yp_update(char *domain, char *map, unsigned int ypop,
+                       char *key, int keylen, char *data, int datalen);
+int    key_setsecret(char *secret);
+int    xencrypt(char *secret, char *passwd);
+int    xdecrypt(char *secret, char *passwd);
+
+
+#define PUBLICKEY_MAP  "publickey.byname"
+#define NETID_MAP      "netid.byname"
+
+#ifndef DEBUG
+#define RPCSEC_BASE    "/etc/"
+#else
+#define RPCSEC_BASE    "/tmp/"
+#endif
+
+#define PUBLICKEY_FILE RPCSEC_BASE "publickey"
+#define PUBLICKEY_LOCK RPCSEC_BASE "publickey.lock"
+#define ROOTKEY_FILE   RPCSEC_BASE ".rootkey"
+#define KEYSTORE_FILE  RPCSEC_BASE "keystore"
+
+#endif /* RPCSEC_H */
diff --git a/support/include/rpcsvc/nfs_prot.h b/support/include/rpcsvc/nfs_prot.h
new file mode 100644 (file)
index 0000000..9311341
--- /dev/null
@@ -0,0 +1,661 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _NFS_PROT_H_RPCGEN
+#define _NFS_PROT_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+#define NFS_PORT 2049
+#define NFS_MAXDATA 8192
+#define NFS_MAXPATHLEN 1024
+#define NFS_MAXNAMLEN 255
+#define NFS_FHSIZE 32
+#define NFS_COOKIESIZE 4
+#define NFS_FIFO_DEV -1
+#define NFSMODE_FMT 0170000
+#define NFSMODE_DIR 0040000
+#define NFSMODE_CHR 0020000
+#define NFSMODE_BLK 0060000
+#define NFSMODE_REG 0100000
+#define NFSMODE_LNK 0120000
+#define NFSMODE_SOCK 0140000
+#define NFSMODE_FIFO 0010000
+
+enum nfsstat {
+       NFS_OK = 0,
+       NFSERR_PERM = 1,
+       NFSERR_NOENT = 2,
+       NFSERR_IO = 5,
+       NFSERR_NXIO = 6,
+       NFSERR_ACCES = 13,
+       NFSERR_EXIST = 17,
+       NFSERR_NODEV = 19,
+       NFSERR_NOTDIR = 20,
+       NFSERR_ISDIR = 21,
+       NFSERR_FBIG = 27,
+       NFSERR_NOSPC = 28,
+       NFSERR_ROFS = 30,
+       NFSERR_NAMETOOLONG = 63,
+       NFSERR_NOTEMPTY = 66,
+       NFSERR_DQUOT = 69,
+       NFSERR_STALE = 70,
+       NFSERR_WFLUSH = 99,
+};
+typedef enum nfsstat nfsstat;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_nfsstat(XDR *, nfsstat*);
+#elif __STDC__ 
+extern  bool_t xdr_nfsstat(XDR *, nfsstat*);
+#else /* Old Style C */ 
+bool_t xdr_nfsstat();
+#endif /* Old Style C */ 
+
+
+enum ftype {
+       NFNON = 0,
+       NFREG = 1,
+       NFDIR = 2,
+       NFBLK = 3,
+       NFCHR = 4,
+       NFLNK = 5,
+       NFSOCK = 6,
+       NFBAD = 7,
+       NFFIFO = 8,
+};
+typedef enum ftype ftype;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ftype(XDR *, ftype*);
+#elif __STDC__ 
+extern  bool_t xdr_ftype(XDR *, ftype*);
+#else /* Old Style C */ 
+bool_t xdr_ftype();
+#endif /* Old Style C */ 
+
+
+struct nfs_fh {
+       char data[NFS_FHSIZE];
+};
+typedef struct nfs_fh nfs_fh;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_nfs_fh(XDR *, nfs_fh*);
+#elif __STDC__ 
+extern  bool_t xdr_nfs_fh(XDR *, nfs_fh*);
+#else /* Old Style C */ 
+bool_t xdr_nfs_fh();
+#endif /* Old Style C */ 
+
+
+struct nfstime {
+       u_int seconds;
+       u_int useconds;
+};
+typedef struct nfstime nfstime;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_nfstime(XDR *, nfstime*);
+#elif __STDC__ 
+extern  bool_t xdr_nfstime(XDR *, nfstime*);
+#else /* Old Style C */ 
+bool_t xdr_nfstime();
+#endif /* Old Style C */ 
+
+
+struct fattr {
+       ftype type;
+       u_int mode;
+       u_int nlink;
+       u_int uid;
+       u_int gid;
+       u_int size;
+       u_int blocksize;
+       u_int rdev;
+       u_int blocks;
+       u_int fsid;
+       u_int fileid;
+       nfstime atime;
+       nfstime mtime;
+       nfstime ctime;
+};
+typedef struct fattr fattr;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_fattr(XDR *, fattr*);
+#elif __STDC__ 
+extern  bool_t xdr_fattr(XDR *, fattr*);
+#else /* Old Style C */ 
+bool_t xdr_fattr();
+#endif /* Old Style C */ 
+
+
+struct sattr {
+       u_int mode;
+       u_int uid;
+       u_int gid;
+       u_int size;
+       nfstime atime;
+       nfstime mtime;
+};
+typedef struct sattr sattr;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_sattr(XDR *, sattr*);
+#elif __STDC__ 
+extern  bool_t xdr_sattr(XDR *, sattr*);
+#else /* Old Style C */ 
+bool_t xdr_sattr();
+#endif /* Old Style C */ 
+
+
+typedef char *filename;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_filename(XDR *, filename*);
+#elif __STDC__ 
+extern  bool_t xdr_filename(XDR *, filename*);
+#else /* Old Style C */ 
+bool_t xdr_filename();
+#endif /* Old Style C */ 
+
+
+typedef char *nfspath;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_nfspath(XDR *, nfspath*);
+#elif __STDC__ 
+extern  bool_t xdr_nfspath(XDR *, nfspath*);
+#else /* Old Style C */ 
+bool_t xdr_nfspath();
+#endif /* Old Style C */ 
+
+
+struct attrstat {
+       nfsstat status;
+       union {
+               fattr attributes;
+       } attrstat_u;
+};
+typedef struct attrstat attrstat;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_attrstat(XDR *, attrstat*);
+#elif __STDC__ 
+extern  bool_t xdr_attrstat(XDR *, attrstat*);
+#else /* Old Style C */ 
+bool_t xdr_attrstat();
+#endif /* Old Style C */ 
+
+
+struct sattrargs {
+       nfs_fh file;
+       sattr attributes;
+};
+typedef struct sattrargs sattrargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_sattrargs(XDR *, sattrargs*);
+#elif __STDC__ 
+extern  bool_t xdr_sattrargs(XDR *, sattrargs*);
+#else /* Old Style C */ 
+bool_t xdr_sattrargs();
+#endif /* Old Style C */ 
+
+
+struct diropargs {
+       nfs_fh dir;
+       filename name;
+};
+typedef struct diropargs diropargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_diropargs(XDR *, diropargs*);
+#elif __STDC__ 
+extern  bool_t xdr_diropargs(XDR *, diropargs*);
+#else /* Old Style C */ 
+bool_t xdr_diropargs();
+#endif /* Old Style C */ 
+
+
+struct diropokres {
+       nfs_fh file;
+       fattr attributes;
+};
+typedef struct diropokres diropokres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_diropokres(XDR *, diropokres*);
+#elif __STDC__ 
+extern  bool_t xdr_diropokres(XDR *, diropokres*);
+#else /* Old Style C */ 
+bool_t xdr_diropokres();
+#endif /* Old Style C */ 
+
+
+struct diropres {
+       nfsstat status;
+       union {
+               diropokres diropres;
+       } diropres_u;
+};
+typedef struct diropres diropres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_diropres(XDR *, diropres*);
+#elif __STDC__ 
+extern  bool_t xdr_diropres(XDR *, diropres*);
+#else /* Old Style C */ 
+bool_t xdr_diropres();
+#endif /* Old Style C */ 
+
+
+struct readlinkres {
+       nfsstat status;
+       union {
+               nfspath data;
+       } readlinkres_u;
+};
+typedef struct readlinkres readlinkres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readlinkres(XDR *, readlinkres*);
+#elif __STDC__ 
+extern  bool_t xdr_readlinkres(XDR *, readlinkres*);
+#else /* Old Style C */ 
+bool_t xdr_readlinkres();
+#endif /* Old Style C */ 
+
+
+struct readargs {
+       nfs_fh file;
+       u_int offset;
+       u_int count;
+       u_int totalcount;
+};
+typedef struct readargs readargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readargs(XDR *, readargs*);
+#elif __STDC__ 
+extern  bool_t xdr_readargs(XDR *, readargs*);
+#else /* Old Style C */ 
+bool_t xdr_readargs();
+#endif /* Old Style C */ 
+
+
+struct readokres {
+       fattr attributes;
+       struct {
+               u_int data_len;
+               char *data_val;
+       } data;
+};
+typedef struct readokres readokres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readokres(XDR *, readokres*);
+#elif __STDC__ 
+extern  bool_t xdr_readokres(XDR *, readokres*);
+#else /* Old Style C */ 
+bool_t xdr_readokres();
+#endif /* Old Style C */ 
+
+
+struct readres {
+       nfsstat status;
+       union {
+               readokres reply;
+       } readres_u;
+};
+typedef struct readres readres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readres(XDR *, readres*);
+#elif __STDC__ 
+extern  bool_t xdr_readres(XDR *, readres*);
+#else /* Old Style C */ 
+bool_t xdr_readres();
+#endif /* Old Style C */ 
+
+
+struct writeargs {
+       nfs_fh file;
+       u_int beginoffset;
+       u_int offset;
+       u_int totalcount;
+       struct {
+               u_int data_len;
+               char *data_val;
+       } data;
+};
+typedef struct writeargs writeargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_writeargs(XDR *, writeargs*);
+#elif __STDC__ 
+extern  bool_t xdr_writeargs(XDR *, writeargs*);
+#else /* Old Style C */ 
+bool_t xdr_writeargs();
+#endif /* Old Style C */ 
+
+
+struct createargs {
+       diropargs where;
+       sattr attributes;
+};
+typedef struct createargs createargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_createargs(XDR *, createargs*);
+#elif __STDC__ 
+extern  bool_t xdr_createargs(XDR *, createargs*);
+#else /* Old Style C */ 
+bool_t xdr_createargs();
+#endif /* Old Style C */ 
+
+
+struct renameargs {
+       diropargs from;
+       diropargs to;
+};
+typedef struct renameargs renameargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_renameargs(XDR *, renameargs*);
+#elif __STDC__ 
+extern  bool_t xdr_renameargs(XDR *, renameargs*);
+#else /* Old Style C */ 
+bool_t xdr_renameargs();
+#endif /* Old Style C */ 
+
+
+struct linkargs {
+       nfs_fh from;
+       diropargs to;
+};
+typedef struct linkargs linkargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_linkargs(XDR *, linkargs*);
+#elif __STDC__ 
+extern  bool_t xdr_linkargs(XDR *, linkargs*);
+#else /* Old Style C */ 
+bool_t xdr_linkargs();
+#endif /* Old Style C */ 
+
+
+struct symlinkargs {
+       diropargs from;
+       nfspath to;
+       sattr attributes;
+};
+typedef struct symlinkargs symlinkargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_symlinkargs(XDR *, symlinkargs*);
+#elif __STDC__ 
+extern  bool_t xdr_symlinkargs(XDR *, symlinkargs*);
+#else /* Old Style C */ 
+bool_t xdr_symlinkargs();
+#endif /* Old Style C */ 
+
+
+typedef char nfscookie[NFS_COOKIESIZE];
+#ifdef __cplusplus 
+extern "C" bool_t xdr_nfscookie(XDR *, nfscookie);
+#elif __STDC__ 
+extern  bool_t xdr_nfscookie(XDR *, nfscookie);
+#else /* Old Style C */ 
+bool_t xdr_nfscookie();
+#endif /* Old Style C */ 
+
+
+struct readdirargs {
+       nfs_fh dir;
+       nfscookie cookie;
+       u_int count;
+};
+typedef struct readdirargs readdirargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readdirargs(XDR *, readdirargs*);
+#elif __STDC__ 
+extern  bool_t xdr_readdirargs(XDR *, readdirargs*);
+#else /* Old Style C */ 
+bool_t xdr_readdirargs();
+#endif /* Old Style C */ 
+
+
+struct entry {
+       u_int fileid;
+       filename name;
+       nfscookie cookie;
+       struct entry *nextentry;
+};
+typedef struct entry entry;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_entry(XDR *, entry*);
+#elif __STDC__ 
+extern  bool_t xdr_entry(XDR *, entry*);
+#else /* Old Style C */ 
+bool_t xdr_entry();
+#endif /* Old Style C */ 
+
+
+struct dirlist {
+       entry *entries;
+       bool_t eof;
+};
+typedef struct dirlist dirlist;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_dirlist(XDR *, dirlist*);
+#elif __STDC__ 
+extern  bool_t xdr_dirlist(XDR *, dirlist*);
+#else /* Old Style C */ 
+bool_t xdr_dirlist();
+#endif /* Old Style C */ 
+
+
+struct readdirres {
+       nfsstat status;
+       union {
+               dirlist reply;
+       } readdirres_u;
+};
+typedef struct readdirres readdirres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readdirres(XDR *, readdirres*);
+#elif __STDC__ 
+extern  bool_t xdr_readdirres(XDR *, readdirres*);
+#else /* Old Style C */ 
+bool_t xdr_readdirres();
+#endif /* Old Style C */ 
+
+
+struct statfsokres {
+       u_int tsize;
+       u_int bsize;
+       u_int blocks;
+       u_int bfree;
+       u_int bavail;
+};
+typedef struct statfsokres statfsokres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_statfsokres(XDR *, statfsokres*);
+#elif __STDC__ 
+extern  bool_t xdr_statfsokres(XDR *, statfsokres*);
+#else /* Old Style C */ 
+bool_t xdr_statfsokres();
+#endif /* Old Style C */ 
+
+
+struct statfsres {
+       nfsstat status;
+       union {
+               statfsokres reply;
+       } statfsres_u;
+};
+typedef struct statfsres statfsres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_statfsres(XDR *, statfsres*);
+#elif __STDC__ 
+extern  bool_t xdr_statfsres(XDR *, statfsres*);
+#else /* Old Style C */ 
+bool_t xdr_statfsres();
+#endif /* Old Style C */ 
+
+
+#define NFS_PROGRAM ((u_long)100003)
+#define NFS_VERSION ((u_long)2)
+
+#ifdef __cplusplus
+#define NFSPROC_NULL ((u_long)0)
+extern "C" void * nfsproc_null_2(void *, CLIENT *);
+extern "C" void * nfsproc_null_2_svc(void *, struct svc_req *);
+#define NFSPROC_GETATTR ((u_long)1)
+extern "C" attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *);
+extern "C" attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_SETATTR ((u_long)2)
+extern "C" attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *);
+extern "C" attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *);
+#define NFSPROC_ROOT ((u_long)3)
+extern "C" void * nfsproc_root_2(void *, CLIENT *);
+extern "C" void * nfsproc_root_2_svc(void *, struct svc_req *);
+#define NFSPROC_LOOKUP ((u_long)4)
+extern "C" diropres * nfsproc_lookup_2(diropargs *, CLIENT *);
+extern "C" diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READLINK ((u_long)5)
+extern "C" readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *);
+extern "C" readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_READ ((u_long)6)
+extern "C" readres * nfsproc_read_2(readargs *, CLIENT *);
+extern "C" readres * nfsproc_read_2_svc(readargs *, struct svc_req *);
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern "C" void * nfsproc_writecache_2(void *, CLIENT *);
+extern "C" void * nfsproc_writecache_2_svc(void *, struct svc_req *);
+#define NFSPROC_WRITE ((u_long)8)
+extern "C" attrstat * nfsproc_write_2(writeargs *, CLIENT *);
+extern "C" attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *);
+#define NFSPROC_CREATE ((u_long)9)
+extern "C" diropres * nfsproc_create_2(createargs *, CLIENT *);
+extern "C" diropres * nfsproc_create_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_REMOVE ((u_long)10)
+extern "C" nfsstat * nfsproc_remove_2(diropargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_RENAME ((u_long)11)
+extern "C" nfsstat * nfsproc_rename_2(renameargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *);
+#define NFSPROC_LINK ((u_long)12)
+extern "C" nfsstat * nfsproc_link_2(linkargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *);
+#define NFSPROC_SYMLINK ((u_long)13)
+extern "C" nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *);
+#define NFSPROC_MKDIR ((u_long)14)
+extern "C" diropres * nfsproc_mkdir_2(createargs *, CLIENT *);
+extern "C" diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_RMDIR ((u_long)15)
+extern "C" nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READDIR ((u_long)16)
+extern "C" readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *);
+extern "C" readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *);
+#define NFSPROC_STATFS ((u_long)17)
+extern "C" statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *);
+extern "C" statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *);
+
+#elif __STDC__
+#define NFSPROC_NULL ((u_long)0)
+extern  void * nfsproc_null_2(void *, CLIENT *);
+extern  void * nfsproc_null_2_svc(void *, struct svc_req *);
+#define NFSPROC_GETATTR ((u_long)1)
+extern  attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *);
+extern  attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_SETATTR ((u_long)2)
+extern  attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *);
+extern  attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *);
+#define NFSPROC_ROOT ((u_long)3)
+extern  void * nfsproc_root_2(void *, CLIENT *);
+extern  void * nfsproc_root_2_svc(void *, struct svc_req *);
+#define NFSPROC_LOOKUP ((u_long)4)
+extern  diropres * nfsproc_lookup_2(diropargs *, CLIENT *);
+extern  diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READLINK ((u_long)5)
+extern  readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *);
+extern  readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_READ ((u_long)6)
+extern  readres * nfsproc_read_2(readargs *, CLIENT *);
+extern  readres * nfsproc_read_2_svc(readargs *, struct svc_req *);
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern  void * nfsproc_writecache_2(void *, CLIENT *);
+extern  void * nfsproc_writecache_2_svc(void *, struct svc_req *);
+#define NFSPROC_WRITE ((u_long)8)
+extern  attrstat * nfsproc_write_2(writeargs *, CLIENT *);
+extern  attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *);
+#define NFSPROC_CREATE ((u_long)9)
+extern  diropres * nfsproc_create_2(createargs *, CLIENT *);
+extern  diropres * nfsproc_create_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_REMOVE ((u_long)10)
+extern  nfsstat * nfsproc_remove_2(diropargs *, CLIENT *);
+extern  nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_RENAME ((u_long)11)
+extern  nfsstat * nfsproc_rename_2(renameargs *, CLIENT *);
+extern  nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *);
+#define NFSPROC_LINK ((u_long)12)
+extern  nfsstat * nfsproc_link_2(linkargs *, CLIENT *);
+extern  nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *);
+#define NFSPROC_SYMLINK ((u_long)13)
+extern  nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *);
+extern  nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *);
+#define NFSPROC_MKDIR ((u_long)14)
+extern  diropres * nfsproc_mkdir_2(createargs *, CLIENT *);
+extern  diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_RMDIR ((u_long)15)
+extern  nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *);
+extern  nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READDIR ((u_long)16)
+extern  readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *);
+extern  readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *);
+#define NFSPROC_STATFS ((u_long)17)
+extern  statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *);
+extern  statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *);
+
+#else /* Old Style C */ 
+#define NFSPROC_NULL ((u_long)0)
+extern  void * nfsproc_null_2();
+extern  void * nfsproc_null_2_svc();
+#define NFSPROC_GETATTR ((u_long)1)
+extern  attrstat * nfsproc_getattr_2();
+extern  attrstat * nfsproc_getattr_2_svc();
+#define NFSPROC_SETATTR ((u_long)2)
+extern  attrstat * nfsproc_setattr_2();
+extern  attrstat * nfsproc_setattr_2_svc();
+#define NFSPROC_ROOT ((u_long)3)
+extern  void * nfsproc_root_2();
+extern  void * nfsproc_root_2_svc();
+#define NFSPROC_LOOKUP ((u_long)4)
+extern  diropres * nfsproc_lookup_2();
+extern  diropres * nfsproc_lookup_2_svc();
+#define NFSPROC_READLINK ((u_long)5)
+extern  readlinkres * nfsproc_readlink_2();
+extern  readlinkres * nfsproc_readlink_2_svc();
+#define NFSPROC_READ ((u_long)6)
+extern  readres * nfsproc_read_2();
+extern  readres * nfsproc_read_2_svc();
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern  void * nfsproc_writecache_2();
+extern  void * nfsproc_writecache_2_svc();
+#define NFSPROC_WRITE ((u_long)8)
+extern  attrstat * nfsproc_write_2();
+extern  attrstat * nfsproc_write_2_svc();
+#define NFSPROC_CREATE ((u_long)9)
+extern  diropres * nfsproc_create_2();
+extern  diropres * nfsproc_create_2_svc();
+#define NFSPROC_REMOVE ((u_long)10)
+extern  nfsstat * nfsproc_remove_2();
+extern  nfsstat * nfsproc_remove_2_svc();
+#define NFSPROC_RENAME ((u_long)11)
+extern  nfsstat * nfsproc_rename_2();
+extern  nfsstat * nfsproc_rename_2_svc();
+#define NFSPROC_LINK ((u_long)12)
+extern  nfsstat * nfsproc_link_2();
+extern  nfsstat * nfsproc_link_2_svc();
+#define NFSPROC_SYMLINK ((u_long)13)
+extern  nfsstat * nfsproc_symlink_2();
+extern  nfsstat * nfsproc_symlink_2_svc();
+#define NFSPROC_MKDIR ((u_long)14)
+extern  diropres * nfsproc_mkdir_2();
+extern  diropres * nfsproc_mkdir_2_svc();
+#define NFSPROC_RMDIR ((u_long)15)
+extern  nfsstat * nfsproc_rmdir_2();
+extern  nfsstat * nfsproc_rmdir_2_svc();
+#define NFSPROC_READDIR ((u_long)16)
+extern  readdirres * nfsproc_readdir_2();
+extern  readdirres * nfsproc_readdir_2_svc();
+#define NFSPROC_STATFS ((u_long)17)
+extern  statfsres * nfsproc_statfs_2();
+extern  statfsres * nfsproc_statfs_2_svc();
+#endif /* Old Style C */ 
+
+#endif /* !_NFS_PROT_H_RPCGEN */
diff --git a/support/include/sys/fs/ext2fs.h b/support/include/sys/fs/ext2fs.h
new file mode 100644 (file)
index 0000000..93b3e2b
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _SYS_FS_EXT2FS_H
+#define _SYS_FS_EXT2FS_H
+
+/*
+ * ioctl commands
+ */
+#define        EXT2_IOC_GETFLAGS               _IOR('f', 1, long)
+#define        EXT2_IOC_SETFLAGS               _IOW('f', 2, long)
+#define        EXT2_IOC_GETVERSION             _IOR('v', 1, long)
+#define        EXT2_IOC_SETVERSION             _IOW('v', 2, long)
+
+/*
+ * File system states
+ */
+#define        EXT2_VALID_FS                   0x0001  /* Unmounted cleanly */
+#define        EXT2_ERROR_FS                   0x0002  /* Errors detected */
+
+/*
+ * Mount flags
+ */
+#define EXT2_MOUNT_CHECK_NORMAL                0x0001  /* Do some more checks */
+#define EXT2_MOUNT_CHECK_STRICT                0x0002  /* Do again more checks */
+#define EXT2_MOUNT_CHECK               (EXT2_MOUNT_CHECK_NORMAL | \
+                                        EXT2_MOUNT_CHECK_STRICT)
+#define EXT2_MOUNT_GRPID               0x0004  /* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG               0x0008  /* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT         0x0010  /* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO           0x0020  /* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC                0x0040  /* Panic on errors */
+#define EXT2_MOUNT_MINIX_DF            0x0080  /* Mimics the Minix statfs */
+
+#define clear_opt(o, opt)              o &= ~EXT2_MOUNT_##opt
+#define set_opt(o, opt)                        o |= EXT2_MOUNT_##opt
+#define test_opt(sb, opt)              ((sb)->u.ext2_sb.s_mount_opt & \
+                                        EXT2_MOUNT_##opt)
+/*
+ * Maximal mount counts between two filesystem checks
+ */
+#define EXT2_DFL_MAX_MNT_COUNT         20      /* Allow 20 mounts */
+#define EXT2_DFL_CHECKINTERVAL         0       /* Don't use interval check */
+
+#endif /* _SYS_FS_EXT2FS_H */
diff --git a/support/include/version.h b/support/include/version.h
new file mode 100644 (file)
index 0000000..a74ec35
--- /dev/null
@@ -0,0 +1 @@
+#define VERSION "1.4.7 (0.4.22)"
diff --git a/support/include/xio.h b/support/include/xio.h
new file mode 100644 (file)
index 0000000..858f5bb
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * xio.h       Declarations for simple parsing functions.
+ *
+ */
+
+#ifndef XIO_H
+#define XIO_H
+
+#include <stdio.h>
+
+typedef struct XFILE {
+       FILE            *x_fp;
+       int             x_line;
+} XFILE;
+
+XFILE  *xfopen(char *fname, char *type);
+int    xflock(char *fname, char *type);
+void   xfunlock(int lockid);
+void   xfclose(XFILE *xfp);
+int    xgettok(XFILE *xfp, char sepa, char *tok, int len);
+char   xgetc(XFILE *xfp);
+void   xungetc(char c, XFILE *xfp);
+void   xskip(XFILE *xfp, char *str);
+char   xskipcomment(XFILE *xfp);
+
+#endif /* XIO_H */
diff --git a/support/include/xlog.h b/support/include/xlog.h
new file mode 100644 (file)
index 0000000..2a839c7
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * xlog                Logging functionality
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef XLOG_H
+#define XLOG_H
+
+#define L_FATAL                0x0100
+#define L_ERROR                0x0200
+#define L_WARNING      0x0400
+#define L_NOTICE       0x0800
+#define L_ALL          0xFF00
+
+#define D_GENERAL      0x0001          /* general debug info */
+#define D_CALL         0x0002
+#define D_AUTH         0x0004
+#define D_FAC3         0x0008
+#define D_FAC4         0x0010
+#define D_FAC5         0x0020
+#define D_PARSE                0x0040
+#define D_FAC7         0x0080
+#define D_ALL          0x00FF
+
+/* This can be used to define symbolic log names that can be passed to
+ * xlog_config. */
+struct xlog_debugfac {
+       char            *df_name;
+       int             df_fac;
+};
+
+void                   xlog_open(char *progname);
+void                   xlog_background(void);
+void                   xlog_config(int fac, int on);
+void                   xlog_sconfig(char *, int on);
+int                    xlog_enabled(int fac);
+void                   xlog(int fac, const char *fmt, ...);
+
+#endif /* XLOG_H */
diff --git a/support/include/xmalloc.h b/support/include/xmalloc.h
new file mode 100644 (file)
index 0000000..866cfd8
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * xmalloc     Module for memory allocation. Drop in your
+ *             debugging malloc module if you feel like it.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef XMALLOC_H
+#define XMALLOC_H
+
+void   *xmalloc(size_t size);
+void   *xrealloc(void *ptr, size_t size);
+char   *xstrdup(const char *s);
+void   xfree(void *ptr);
+
+#endif /* XMALLOC_H */
diff --git a/support/include/ypupdate.h b/support/include/ypupdate.h
new file mode 100644 (file)
index 0000000..e0cee15
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * ypupdate.h  This file contains the public declarations for the
+ *             ypupdate client side RPC stubs.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef YPUPDATE_H
+#define YPUPDATE_H
+
+#include <rpcsvc/ypclnt.h>
+
+int    yp_update(char *domain, char *map, unsigned int ypop,
+                       char *key, int keylen, char *data, int datalen);
+
+#endif YPUPDATE_H
diff --git a/support/lib/Makefile b/support/lib/Makefile
new file mode 100644 (file)
index 0000000..b5fa14a
--- /dev/null
@@ -0,0 +1,13 @@
+
+include        $(TOP)rules.mk
+
+LIBS   = libnfs.a libexport.a
+
+all install::  $(LIBS)
+       @:
+
+clean distclean::
+       rm -f $(LIBS)
+
+lib%.a:
+       ln -sf ../$*/$@ .
diff --git a/support/nfs/Makefile b/support/nfs/Makefile
new file mode 100644 (file)
index 0000000..ed1e1ff
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# linux-nfs/support/nfs/Makefile
+#
+
+LIBNAME        = libnfs.a
+OBJS   = exports.o rmtab.o xio.o \
+         rpcmisc.o rpcdispatch.o xlog.o xmalloc.o wildmat.o \
+         nfssvc.o nfsclient.o nfsexport.o getfh.o nfsctl.o lockdsvc.o
+
+include $(TOP)rules.mk
+
+install::
+       @:
diff --git a/support/nfs/clients.c b/support/nfs/clients.c
new file mode 100644 (file)
index 0000000..b1970e0
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * support/nfs/nfsclient.c
+ *
+ * Parse the nfsclients file.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <ctype.h>
+#include "xmalloc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+
+static XFILE   *cfp = NULL;
+static int     *squash_uids = NULL,
+               *squash_gids = NULL;
+static int     squash_uidlen = 0,
+               squash_gidlen = 0;
+static char    *hosts = NULL;
+
+static int     parsesquash(char *list, int **idp, int *lenp);
+static int     parsenum(char **cpp);
+static int     parsekey(struct nfskey *keyp, char *str);
+static int     hexdigit(char c);
+static int     gettag(char *tag, int len);
+static int     getattr(char *attr, int alen, char *value, int vlen);
+static void    syntaxerr(char *msg);
+
+#ifndef isblank
+#define isblank(c)     ((c) == ' ' || (c) == '\t')
+#endif
+
+void
+setnfsclntent(char *fname)
+{
+       if (cfp)
+               xfclose(cfp);
+       if (!fname)
+               fname = _PATH_NFSCLIENTS;
+       if ((cfp = xfopen(fname)) == NULL)
+               xlog(L_ERROR, "can't open %s for reading", fname);
+}
+
+struct nfsclntent *
+getnfsclntent(void)
+{
+       static struct nfsclntent cle;
+       static char     *hostptr = NULL;
+       char            attr[32], val[512], *sp;
+       int             ok;
+
+       if (!cfp)
+               endnfsclntent();
+
+again:
+       if (hosts) {
+               if (hostptr)
+                       goto nexthost;
+               xfree(hosts);
+               hosts = NULL;
+       }
+
+       if ((ok = gettag(cle.c_tag, sizeof(cle.c_tag))) < 0)
+               syntaxerr("expected tag");
+       if (ok <= 0)
+               return NULL;
+
+       cle.c_hostname[0] = '\0';
+       cle.c_fhkey.k_type = CLE_KEY_NONE;
+       cle.c_mapping = CLE_MAP_IDENT;
+       cle.c_anonuid = -2;
+       cle.c_anongid = -2;
+
+       if (squash_uids)
+               xfree(squash_uids);
+       if (squash_gids)
+               xfree(squash_gids);
+       squash_uids = squash_gids = NULL;
+       squash_uidlen = squash_gidlen = 0;
+
+       while (ok) {
+               if ((ok = getattr(attr, sizeof(attr), val, sizeof(val))) < 0)
+                       return NULL;
+               if (!ok)
+                       break;
+               if (attr[0] == 'h' && !strcmp(attr, "hosts")) {
+                       int     l0 = hosts? strlen(hosts) : 0;
+
+                       hosts = (char *) xrealloc(hosts, l0+strlen(val)+2);
+                       if (l0)
+                               hosts[l0++] = ':';
+                       strcpy(hosts+l0, val);
+               } else
+               if (attr[0] == 'f' && !strcmp(attr, "fhmac")) {
+                       if (!parsekey(&cle.c_fhkey, val))
+                               return NULL;
+               } else
+               if (attr[0] == 'm' && !strcmp(attr, "mapping")) {
+                       if (!strcmp(val, "identity"))
+                               cle.c_mapping = CLE_MAP_IDENT;
+                       else if (!strcmp(val, "file"))
+                               cle.c_mapping = CLE_MAP_FILE;
+                       else if (!strcmp(val, "daemon"))
+                               cle.c_mapping = CLE_MAP_UGIDD;
+                       else {
+                               syntaxerr("invalid mapping type");
+                               return NULL;
+                       }
+               } else
+               if (attr[0] == 's' && !strcmp(attr, "squash_uids")) {
+                       if (!parsesquash(val, &squash_uids, &squash_uidlen))
+                               return NULL;
+               } else
+               if (attr[0] == 's' && !strcmp(attr, "squash_gids")) {
+                       if (!parsesquash(val, &squash_gids, &squash_gidlen))
+                               return NULL;
+               } else
+               if (attr[0] == 'a' && !strcmp(attr, "anonuid"))
+                       cle.c_anonuid = atoi(val);
+               else
+               if (attr[0] == 'a' && !strcmp(attr, "anongid"))
+                       cle.c_anongid = atoi(val);
+               else
+                       syntaxerr("unknown attribute");
+       }
+
+       cle.c_squashuids = squash_uids;
+       cle.c_squashgids = squash_gids;
+
+       /* This is the anon entry */
+       if (!hosts) {
+               if (strcmp(cle.c_tag, "anonymous")) {
+                       xlog(L_ERROR, "nfsclients entry %s allows anonymous "
+                                       "access. Ignored.", cle.c_tag);
+                       goto again;
+               }
+               return &cle;
+       }
+       hostptr = hosts;
+
+nexthost:
+       if (*hostptr == ':' && strcmp(cle.c_tag, "anonymous")) {
+               xlog(L_ERROR, "nfsclients entry %s allows anonymous "
+                               "access. Ignored.", cle.c_tag);
+               while (*hostptr == ':')
+                       hostptr++;
+       }
+
+       /* Ignore trailing colons */
+       if (!*hostptr) {
+               hostptr = NULL;
+               goto again;
+       }
+
+       sp = hostptr;
+       hostptr = strchr(hostptr, ':');
+       if (hostptr)
+               *hostptr++ = '\0';
+       strncpy(cle.c_hostname, sp, sizeof(cle.c_hostname) - 1);
+       cle.c_hostname [sizeof(cle.c_hostname) - 1] = '\0';
+       return &cle;
+}
+
+void
+endnfsclntent(void)
+{
+       if (cfp)
+               xfclose(cfp);
+       if (squash_uids)
+               xfree(squash_uids);
+       if (squash_gids)
+               xfree(squash_gids);
+       if (hosts)
+               xfree(hosts);
+       cfp = NULL;
+       squash_uids = NULL;
+       squash_gids = NULL;
+       hosts = NULL;
+}
+
+static int
+parsekey(struct nfskey *keyp, char *str)
+{
+       char    *sp;
+       int     i, l, x0, x1;
+
+
+       if ((sp = strchr(str, ':')) != NULL)
+               *sp++ = '\0';
+       if (!strcmp(str, "null"))
+               keyp->k_type = CLE_KEY_NULL;
+       else if (!strcmp(str, "md5"))
+               keyp->k_type = CLE_KEY_MD5;
+       else if (!strcmp(str, "sha"))
+               keyp->k_type = CLE_KEY_SHA;
+       else {
+               syntaxerr("unknown key type");
+               return 0;
+       }
+       if (keyp->k_type == CLE_KEY_NULL) {
+               keyp->k_len = 0;
+               if (sp)
+                       syntaxerr("unexpected key data for null key");
+               return sp? 0 : 1;
+       } else if (sp) {
+               if ((l = strlen(sp)) & 1) {
+                       syntaxerr("odd key length");
+                       return 0;
+               }
+
+               l >>= 1;
+               for (i = 0; i < l && i < sizeof(keyp->k_key); i++, sp += 2) {
+                       if ((x0 = hexdigit(sp[0])) == 0xff ||
+                           (x1 = hexdigit(sp[1])) == 0xff) {
+                               syntaxerr("bad key digit");
+                               return 0;
+                       }
+                       keyp->k_key[i] = (x0 << 4) | x1;
+               }
+               keyp->k_len = i;
+               return 1;
+       }
+       return 0;
+}
+
+static int
+hexdigit(char c)
+{
+       if ((c = tolower(c)) >= '0' && c <= '9')
+               return c - '0';
+       if (c >= 'a' && c <= 'f')
+               return c - 'a' + 10;
+       return 0xff;
+}
+
+static int
+parsesquash(char *list, int **idp, int *lenp)
+{
+       char    *cp = list;
+       int     id0, id1;
+       int     len = *lenp;
+       int     *id = *idp;
+
+       do {
+               id0 = parsenum(&cp);
+               if (*cp == '-') {
+                       cp++;
+                       id1 = parsenum(&cp);
+               } else {
+                       id1 = id0;
+               }
+               if (id0 == -1 || id1 == -1) {
+                       syntaxerr("uid/gid -1 not permitted");
+                       return 0;
+               }
+               if ((len % 8) == 0)
+                       id = (int *) xrealloc(id, (len + 9) * sizeof(*id));
+               id[len++] = id0;
+               id[len++] = id1;
+               if (!*cp)
+                       break;
+               if (*cp != ',') {
+                       syntaxerr("bad uid/gid list");
+                       return 0;
+               }
+               cp++;
+       } while(1);
+
+       id[len] = -1;
+       *lenp = len;
+       *idp = id;
+       return 1;
+}
+
+static int
+parsenum(char **cpp)
+{
+       char    *cp = *cpp, c;
+       int     num = 0;
+
+       if (**cpp == '-')
+               (*cpp)++;
+       while (isdigit(**cpp))
+               (*cpp)++;
+       c = **cpp; **cpp = '\0'; num = atoi(cp); **cpp = c;
+       return num;
+}
+
+static int
+gettag(char *tag, int len)
+{
+       xskip(cfp, " \t\n");
+       return xgettok(cfp, ':', tag, len);
+}
+
+static int
+getattr(char *attr, int alen, char *value, int vlen)
+{
+       int     ok;
+
+       xskip(cfp, " \t");
+       if ((ok = xgettok(cfp, '=', attr, alen)) < 0)
+               xlog(L_ERROR, "error parsing attribute");
+       if (ok <= 0)
+               return ok;
+       xskip(cfp, " \t=");
+
+       return xgettok(cfp, 0, value, vlen);
+}
+
+static void
+syntaxerr(char *msg)
+{
+       xlog(L_ERROR, "syntax error in nfsclients file (line %d): %s",
+                               cfp->x_line, msg);
+}
+
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
new file mode 100644 (file)
index 0000000..21b85be
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * support/nfs/export.c
+ *
+ * Parse the exports file. Derived from the unfsd implementation.
+ *
+ * Authors:    Donald J. Becker, <becker@super.org>
+ *             Rick Sladkey, <jrs@world.std.com>
+ *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *             Olaf Kirch, <okir@monad.swb.de>
+ *             Alexander O. Yuriev, <alex@bach.cis.temple.edu>
+ *
+ *             This software maybe be used for any purpose provided
+ *             the above copyright notice is retained.  It is supplied
+ *             as is, with no warranty expressed or implied.
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xmalloc.h"
+#include "xlog.h"
+#include "xio.h"
+
+#define EXPORT_DEFAULT_FLAGS   \
+  (NFSEXP_ASYNC|NFSEXP_READONLY|NFSEXP_ROOTSQUASH|NFSEXP_GATHERED_WRITES)
+
+static XFILE   *efp = NULL;
+static int     first;
+static int     *squids = NULL, nsquids = 0,
+               *sqgids = NULL, nsqgids = 0;
+
+static int     getexport(char *exp, int len);
+static int     getpath(char *path, int len);
+static int     parseopts(char *cp, struct exportent *ep);
+static int     parsesquash(char *list, int **idp, int *lenp, char **ep);
+static int     parsenum(char **cpp);
+static int     parsemaptype(char *type);
+static void    freesquash(void);
+static void    syntaxerr(char *msg);
+
+void
+setexportent(char *fname, char *type)
+{
+       if (efp)
+               endexportent();
+       if (!fname)
+               fname = _PATH_EXPORTS;
+       if (!(efp = xfopen(fname, type)))
+               xlog(L_ERROR, "can't open %s for %sing",
+                               fname, strcmp(type, "r")? "writ" : "read");
+       first = 1;
+}
+
+struct exportent *
+getexportent(void)
+{
+       static struct exportent ee;
+       char            exp[512];
+       char            rpath[MAXPATHLEN+1];
+       char            *opt, *sp;
+       int             ok;
+
+       if (!efp)
+               return NULL;
+
+       freesquash();
+       ee.e_flags = EXPORT_DEFAULT_FLAGS;
+       ee.e_maptype = CLE_MAP_IDENT;
+       ee.e_anonuid = -2;
+       ee.e_anongid = -2;
+       ee.e_squids = NULL;
+       ee.e_sqgids = NULL;
+       ee.e_nsquids = 0;
+       ee.e_nsqgids = 0;
+
+       if (first || (ok = getexport(exp, sizeof(exp))) == 0) {
+               ok = getpath(ee.e_path, sizeof(ee.e_path));
+               if (ok <= 0)
+                       return NULL;
+               strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1);
+               ee.m_path [sizeof (ee.m_path) - 1] = '\0';
+               ok = getexport(exp, sizeof(exp));
+       }
+       if (ok < 0) {
+               xlog(L_ERROR, "expected client(options...)");
+               return NULL;
+       }
+       first = 0;
+
+       /* Check for default client */
+       if (ok == 0)
+               exp[0] = '\0';
+       if ((opt = strchr(exp, '(')) != NULL) {
+               *opt++ = '\0';
+               if (!(sp = strchr(opt, ')')) || sp[1] != '\0') {
+                       syntaxerr("bad option list");
+                       return NULL;
+               }
+               *sp = '\0';
+               if (parseopts(opt, &ee) < 0)
+                       return NULL;
+       }
+       if (strlen(exp) >= sizeof(ee.e_hostname)) {
+               syntaxerr("client name too long");
+               return NULL;
+       }
+       strncpy(ee.e_hostname, exp, sizeof (ee.e_hostname) - 1);
+       ee.e_hostname[sizeof (ee.e_hostname) - 1] = '\0';
+
+       /* resolve symlinks */
+       if (realpath(ee.e_path, rpath) != NULL) {
+               rpath[sizeof (rpath) - 1] = '\0';
+               strncpy(ee.e_path, rpath, sizeof (ee.e_path) - 1);
+               ee.e_path[sizeof (ee.e_path) - 1] = '\0';
+               strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1);
+               ee.m_path [sizeof (ee.m_path) - 1] = '\0';
+       }
+
+       return &ee;
+}
+
+void
+putexportent(struct exportent *ep)
+{
+       FILE    *fp;
+       int     *id, i;
+
+       if (!efp)
+               return;
+
+       fp = efp->x_fp;
+       fprintf(fp, "%s\t%s(", ep->e_path, ep->e_hostname);
+       fprintf(fp, "%s,", (ep->e_flags & NFSEXP_READONLY)? "ro" : "rw");
+       fprintf(fp, "%ssync,", (ep->e_flags & NFSEXP_ASYNC)? "a" : "");
+       fprintf(fp, "%swdelay,", (ep->e_flags & NFSEXP_GATHERED_WRITES)?
+                               "" : "no_");
+       fprintf(fp, "%ssecure,", (ep->e_flags & NFSEXP_INSECURE_PORT)?
+                               "in" : "");
+       fprintf(fp, "%sroot_squash,", (ep->e_flags & NFSEXP_ROOTSQUASH)?
+                               "" : "no_");
+       fprintf(fp, "%sall_squash,", (ep->e_flags & NFSEXP_ALLSQUASH)?
+                               "" : "no_");
+
+       fprintf(fp, "mapping=");
+       switch (ep->e_maptype) {
+       case CLE_MAP_IDENT:
+               fprintf(fp, "identity,");
+               break;
+       case CLE_MAP_UGIDD:
+               fprintf(fp, "ugidd,");
+               break;
+       case CLE_MAP_FILE:
+               fprintf(fp, "file,");
+               break;
+       default:
+               xlog(L_ERROR, "unknown mapping type for %s:%s",
+                                       ep->e_hostname, ep->e_path);
+       }
+       if ((id = ep->e_squids) != NULL) {
+               fprintf(fp, "squash_uids=");
+               for (i = 0; i < ep->e_nsquids; i += 2)
+                       if (id[i] != id[i+1])
+                               fprintf(fp, "%d-%d,", id[i], id[i+1]);
+                       else
+                               fprintf(fp, "%d,", id[i]);
+       }
+       if ((id = ep->e_sqgids) != NULL) {
+               fprintf(fp, "squash_gids=");
+               for (i = 0; i < ep->e_nsquids; i += 2)
+                       if (id[i] != id[i+1])
+                               fprintf(fp, "%d-%d,", id[i], id[i+1]);
+                       else
+                               fprintf(fp, "%d,", id[i]);
+       }
+       fprintf(fp, "anonuid=%d,anongid=%d)\n", ep->e_anonuid, ep->e_anongid);
+}
+
+void
+endexportent(void)
+{
+       if (efp)
+               xfclose(efp);
+       efp = NULL;
+       freesquash();
+}
+
+void
+dupexportent(struct exportent *dst, struct exportent *src)
+{
+       int     n;
+
+       *dst = *src;
+       if ((n = src->e_nsquids) != 0) {
+               dst->e_squids = (int *) xmalloc(n * sizeof(int));
+               memcpy(dst->e_squids, src->e_squids, n * sizeof(int));
+       }
+       if ((n = src->e_nsqgids) != 0) {
+               dst->e_sqgids = (int *) xmalloc(n * sizeof(int));
+               memcpy(dst->e_sqgids, src->e_sqgids, n * sizeof(int));
+       }
+}
+
+struct exportent *
+mkexportent(char *hname, char *path, char *options)
+{
+       static struct exportent ee;
+
+       ee.e_flags = EXPORT_DEFAULT_FLAGS;
+       ee.e_maptype = CLE_MAP_IDENT;
+       ee.e_anonuid = -2;
+       ee.e_anongid = -2;
+       ee.e_squids = NULL;
+       ee.e_sqgids = NULL;
+       ee.e_nsquids = 0;
+       ee.e_nsqgids = 0;
+
+       if (strlen(hname) >= sizeof(ee.e_hostname)) {
+               xlog(L_WARNING, "client name %s too long", hname);
+               return NULL;
+       }
+       strncpy(ee.e_hostname, hname, sizeof (ee.e_hostname) - 1);
+       ee.e_hostname[sizeof (ee.e_hostname) - 1] = '\0';
+       if (strlen(path) >= sizeof(ee.e_path)) {
+               xlog(L_WARNING, "path name %s too long", path);
+               return NULL;
+       }
+       strncpy(ee.e_path, path, sizeof (ee.e_path));
+       ee.e_path[sizeof (ee.e_path) - 1] = '\0';
+       strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1);
+       ee.m_path [sizeof (ee.m_path) - 1] = '\0';
+       if (options && parseopts(options, &ee) < 0)
+               return NULL;
+       return &ee;
+}
+
+int
+updateexportent(struct exportent *eep, char *options)
+{
+       if (options && parseopts(options, eep) < 0)
+               return 0;
+       return 1;
+}
+
+/*
+ * Parse option string pointed to by s and set mount options accordingly.
+ */
+static int
+parseopts(char *cp, struct exportent *ep)
+{
+       char    *opt;
+
+       squids = ep->e_squids; nsquids = ep->e_nsquids;
+       sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids;
+
+       while (isblank(*cp))
+               cp++;
+       while (*cp) {
+               opt = cp;
+               while (*cp && *cp != ',')
+                       cp++;
+               if (*cp)
+                       *cp++ = '\0';
+
+               /* process keyword */
+               if (strcmp(opt, "ro") == 0)
+                       ep->e_flags |= NFSEXP_READONLY;
+               else if (strcmp(opt, "rw") == 0)
+                       ep->e_flags &= ~NFSEXP_READONLY;
+               else if (!strcmp(opt, "secure"))
+                       ep->e_flags &= ~NFSEXP_INSECURE_PORT;
+               else if (!strcmp(opt, "insecure"))
+                       ep->e_flags |= NFSEXP_INSECURE_PORT;
+               else if (!strcmp(opt, "sync"))
+                       ep->e_flags &= ~NFSEXP_ASYNC;
+               else if (!strcmp(opt, "async"))
+                       ep->e_flags |= NFSEXP_ASYNC;
+               else if (!strcmp(opt, "wdelay"))
+                       ep->e_flags |= NFSEXP_GATHERED_WRITES;
+               else if (!strcmp(opt, "no_wdelay"))
+                       ep->e_flags &= ~NFSEXP_GATHERED_WRITES;
+               else if (strcmp(opt, "root_squash") == 0)
+                       ep->e_flags |= NFSEXP_ROOTSQUASH;
+               else if (!strcmp(opt, "no_root_squash"))
+                       ep->e_flags &= ~NFSEXP_ROOTSQUASH;
+               else if (strcmp(opt, "all_squash") == 0)
+                       ep->e_flags |= NFSEXP_ALLSQUASH;
+               else if (strcmp(opt, "no_all_squash") == 0)
+                       ep->e_flags &= ~NFSEXP_ALLSQUASH;
+               else if (strncmp(opt, "mapping=", 8) == 0)
+                       ep->e_maptype = parsemaptype(opt+8);
+               else if (strcmp(opt, "map_identity") == 0)      /* old style */
+                       ep->e_maptype = CLE_MAP_IDENT;
+               else if (strcmp(opt, "map_daemon") == 0)        /* old style */
+                       ep->e_maptype = CLE_MAP_UGIDD;
+               else if (strncmp(opt, "anonuid=", 8) == 0)
+                       ep->e_anonuid = atoi(opt+8);
+               else if (strncmp(opt, "anongid=", 8) == 0)
+                       ep->e_anongid = atoi(opt+8);
+               else if (strncmp(opt, "squash_uids=", 12) == 0) {
+                       if (parsesquash(opt+12, &squids, &nsquids, &cp) < 0)
+                               return -1;
+               } else if (strncmp(opt, "squash_gids=", 12) == 0) {
+                       if (parsesquash(opt+12, &sqgids, &nsqgids, &cp) < 0)
+                               return -1;
+               } else {
+                       xlog(L_ERROR,
+                               "Unknown keyword \"%s\" in export file\n",
+                               opt);
+                       ep->e_flags |= NFSEXP_ALLSQUASH | NFSEXP_READONLY;
+                       return -1;
+               }
+               while (isblank(*cp))
+                       cp++;
+       }
+
+       ep->e_squids = squids;
+       ep->e_sqgids = sqgids;
+       ep->e_nsquids = nsquids;
+       ep->e_nsqgids = nsqgids;
+
+       return 1;
+}
+
+static int
+parsesquash(char *list, int **idp, int *lenp, char **ep)
+{
+       char    *cp = list;
+       int     id0, id1;
+       int     len = *lenp;
+       int     *id = *idp;
+
+       if (**ep)
+           *--(*ep) = ',';
+
+       do {
+               id0 = parsenum(&cp);
+               if (*cp == '-') {
+                       cp++;
+                       id1 = parsenum(&cp);
+               } else {
+                       id1 = id0;
+               }
+               if (id0 == -1 || id1 == -1) {
+                       syntaxerr("uid/gid -1 not permitted");
+                       return -1;
+               }
+               if ((len % 8) == 0)
+                       id = (int *) xrealloc(id, (len + 8) * sizeof(*id));
+               id[len++] = id0;
+               id[len++] = id1;
+               if (!*cp || *cp == ')' || (*cp == ',' && !isdigit(cp[1])))
+                       break;
+               if (*cp != ',') {
+                       syntaxerr("bad uid/gid list");
+                       return -1;
+               }
+               cp++;
+       } while(1);
+
+       if (*cp == ',') *ep = cp+1;
+       
+       *lenp = len;
+       *idp = id;
+       return 1;
+}
+
+static void
+freesquash(void)
+{
+       if (squids) {
+               xfree (squids);
+               squids = NULL;
+               nsquids = 0;
+       }
+       if (sqgids) {
+               xfree (sqgids);
+               sqgids = NULL;
+               nsqgids = 0;
+       }
+}
+
+static int
+parsenum(char **cpp)
+{
+       char    *cp = *cpp, c;
+       int     num = 0;
+
+       if (**cpp == '-')
+               (*cpp)++;
+       while (isdigit(**cpp))
+               (*cpp)++;
+       c = **cpp; **cpp = '\0'; num = atoi(cp); **cpp = c;
+       return num;
+}
+
+static int
+parsemaptype(char *type)
+{
+       if (!strcmp(type, "identity"))
+               return CLE_MAP_IDENT;
+       if (!strcmp(type, "ugidd"))
+               return CLE_MAP_UGIDD;
+       if (!strcmp(type, "file"))
+               return CLE_MAP_FILE;
+       syntaxerr("invalid map type");
+       return CLE_MAP_IDENT;   /* default */
+}
+
+static int
+getpath(char *path, int len)
+{
+       xskip(efp, " \t\n");
+       return xgettok(efp, 0, path, len);
+}
+
+static int
+getexport(char *exp, int len)
+{
+       int     ok;
+
+       xskip(efp, " \t");
+       if ((ok = xgettok(efp, 0, exp, len)) < 0)
+               xlog(L_ERROR, "error parsing export entry");
+       return ok;
+}
+
+static void
+syntaxerr(char *msg)
+{
+       xlog(L_ERROR, "syntax error in exports file (line %d): %s",
+                               efp->x_line, msg);
+}
+
diff --git a/support/nfs/getfh.c b/support/nfs/getfh.c
new file mode 100644 (file)
index 0000000..5a6f1a4
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * support/nfs/getfh.c
+ *
+ * Get the FH for a given client and directory. This function takes
+ * the NFS protocol version number as an additional argument.
+ *
+ * This function has nothing in common with the SunOS getfh function,
+ * which is a front-end to the RPC mount call.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+#include "nfslib.h"
+
+struct knfs_fh *
+getfh_old (struct sockaddr *addr, dev_t dev, ino_t ino)
+{
+       static union nfsctl_res res;
+       struct nfsctl_arg       arg;
+
+       arg.ca_version = NFSCTL_VERSION;
+       arg.ca_getfh.gf_version = 2;    /* obsolete */
+       arg.ca_getfh.gf_dev = dev;
+       arg.ca_getfh.gf_ino = ino;
+       memcpy(&arg.ca_getfh.gf_addr, addr, sizeof(struct sockaddr_in));
+
+       if (nfsctl(NFSCTL_GETFH, &arg, &res) < 0)
+               return NULL;
+
+       return &res.cr_getfh;
+}
+
+struct knfs_fh *
+getfh(struct sockaddr *addr, const char *path)
+{
+        static union nfsctl_res res;
+        struct nfsctl_arg       arg;
+
+        arg.ca_version = NFSCTL_VERSION;
+        arg.ca_getfd.gd_version = 2;    /* obsolete */
+        strncpy(arg.ca_getfd.gd_path, path,
+               sizeof(arg.ca_getfd.gd_path) - 1);
+       arg.ca_getfd.gd_path[sizeof (arg.ca_getfd.gd_path) - 1] = '\0';
+        memcpy(&arg.ca_getfd.gd_addr, addr, sizeof(struct sockaddr_in));
+
+        if (nfsctl(NFSCTL_GETFD, &arg, &res) < 0)
+                return NULL;
+
+        return &res.cr_getfh;
+}
diff --git a/support/nfs/keytab.c b/support/nfs/keytab.c
new file mode 100644 (file)
index 0000000..e33dded
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * support/nfs/keytab.c
+ *
+ * Manage the nfskeys database.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <ctype.h>
+#include "xmalloc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+
+static FILE    *cfp = NULL;
+
+int
+setnfskeyent(char *fname)
+{
+       if (cfp)
+               fclose(cfp);
+       if (!fname)
+               fname = _PATH_NFSKEYS;
+       cfp = fsetnfskeyent(fname, "r");
+       return cfp != NULL;
+}
+
+FILE *
+fsetnfskeyent(char *fname, char *type)
+{
+#if 0
+       FILE    *fp;
+
+       if ((fp = fopen(fname, type)) == NULL)
+               xlog(L_ERROR, "can't open %s for %sing\n",
+                               fname, type[0] == 'r'? "read" : "writ");
+       return fp;
+#else
+       return fopen(fname, type);
+#endif
+}
+
+struct nfskeyent *
+getnfskeyent(void)
+{
+       return fgetnfskeyent(cfp);
+}
+
+struct nfskeyent *
+fgetnfskeyent(FILE *fp)
+{
+       static struct nfskeyent ke;
+
+       if (!fp)
+               return NULL;
+
+       do {
+               if (fread(&ke, sizeof(ke), 1, fp) != 1)
+                       return NULL;
+       } while(ke.k_hostname[0] == '\0');
+       return &ke;
+}
+
+void
+endnfskeyent(void)
+{
+       if (cfp)
+               fclose(cfp);
+       cfp = NULL;
+}
+
+void
+fendnfskeyent(FILE *fp)
+{
+       if (fp)
+               fclose(fp);
+}
+
+void
+fputnfskeyent(FILE *fp, struct nfskeyent *kep)
+{
+       fwrite(kep, sizeof(*kep), 1, fp);
+}
+
+int
+getnfskeytype(char *st)
+{
+       if (!strcasecmp(st, "null"))
+               return CLE_KEY_NULL;
+       if (!strcasecmp(st, "md5"))
+               return CLE_KEY_MD5;
+       if (!strcasecmp(st, "sha"))
+               return CLE_KEY_SHA;
+       return CLE_KEY_NONE;
+}
+
+char *
+getnfskeyname(int type)
+{
+       switch (type) {
+       case CLE_KEY_NONE:
+               return "none";
+       case CLE_KEY_NULL:
+               return "null";
+       case CLE_KEY_MD5:
+               return "md5";
+       case CLE_KEY_SHA:
+               return "sha";
+       }
+       return "unk";
+}
+
+int
+getnfskeysize(int type)
+{
+       switch (type) {
+       case CLE_KEY_MD5:
+               return 16;
+       case CLE_KEY_SHA:
+               return 20;
+       }
+       return 0;
+}
diff --git a/support/nfs/lockdsvc.c b/support/nfs/lockdsvc.c
new file mode 100644 (file)
index 0000000..532e721
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * support/nfs/nfssvc.c
+ *
+ * Run an NFS daemon.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include "nfslib.h"
+
+int
+lockdsvc()
+{
+       struct nfsctl_arg       arg;
+
+       arg.ca_version = NFSCTL_VERSION;
+       return nfsctl(LOCKDCTL_SVC, &arg, NULL);
+}
diff --git a/support/nfs/nfsclient.c b/support/nfs/nfsclient.c
new file mode 100644 (file)
index 0000000..5886484
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * support/nfs/client.c
+ *
+ * Add or delete an NFS client in knfsd.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include "nfslib.h"
+
+int
+nfsaddclient(struct nfsctl_client *clp)
+{
+       struct nfsctl_arg       arg;
+
+       arg.ca_version = NFSCTL_VERSION;
+       memcpy(&arg.ca_client, clp, sizeof(arg.ca_client));
+       return nfsctl(NFSCTL_ADDCLIENT, &arg, NULL);
+}
+
+int
+nfsdelclient(struct nfsctl_client *clp)
+{
+       struct nfsctl_arg       arg;
+
+       arg.ca_version = NFSCTL_VERSION;
+       memcpy(&arg.ca_client, clp, sizeof(arg.ca_client));
+       return nfsctl(NFSCTL_DELCLIENT, &arg, NULL);
+}
diff --git a/support/nfs/nfsctl.c b/support/nfs/nfsctl.c
new file mode 100644 (file)
index 0000000..c04588f
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * support/nfs/nfsctl.c
+ *
+ * Central syscall to the nfsd kernel module.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <asm/unistd.h>
+#include "nfslib.h"
+
+/* compatibility hack... */
+#ifndef __NR_nfsctl
+#define __NR_nfsctl    __NR_nfsservctl
+#endif
+
+int
+nfsctl (int cmd, struct nfsctl_arg * argp, union nfsctl_res * resp)
+{
+  return syscall (__NR_nfsctl, cmd, argp, resp);
+}
diff --git a/support/nfs/nfsexport.c b/support/nfs/nfsexport.c
new file mode 100644 (file)
index 0000000..ce8b867
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * support/nfs/export.c
+ *
+ * Add or delete an NFS export in knfsd.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include "nfslib.h"
+
+int
+nfsexport(struct nfsctl_export *exp)
+{
+       struct nfsctl_arg       arg;
+
+       arg.ca_version = NFSCTL_VERSION;
+       memcpy(&arg.ca_export, exp, sizeof(arg.ca_export));
+       return nfsctl(NFSCTL_EXPORT, &arg, NULL);
+}
+
+int
+nfsunexport(struct nfsctl_export *exp)
+{
+       struct nfsctl_arg       arg;
+
+       arg.ca_version = NFSCTL_VERSION;
+       memcpy(&arg.ca_export, exp, sizeof(arg.ca_export));
+       return nfsctl(NFSCTL_UNEXPORT, &arg, NULL);
+}
diff --git a/support/nfs/nfssvc.c b/support/nfs/nfssvc.c
new file mode 100644 (file)
index 0000000..7419baf
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * support/nfs/nfssvc.c
+ *
+ * Run an NFS daemon.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include "nfslib.h"
+
+int
+nfssvc(int port, int nrservs)
+{
+       struct nfsctl_arg       arg;
+
+       arg.ca_version = NFSCTL_VERSION;
+       arg.ca_svc.svc_nthreads = nrservs;
+       arg.ca_svc.svc_port = port;
+       return nfsctl(NFSCTL_SVC, &arg, NULL);
+}
diff --git a/support/nfs/rmtab.c b/support/nfs/rmtab.c
new file mode 100644 (file)
index 0000000..b9b5ff1
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * support/nfs/rmtab.c
+ *
+ * Handling for rmtab.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include "nfslib.h"
+
+static FILE    *rmfp = NULL;
+
+int
+setrmtabent(char *type)
+{
+       if (rmfp)
+               fclose(rmfp);
+       rmfp = fsetrmtabent(_PATH_RMTAB, type);
+       return (rmfp != NULL);
+}
+
+FILE *
+fsetrmtabent(char *fname, char *type)
+{
+       int     readonly = !strcmp(type, "r");
+       FILE    *fp;
+
+       if (!fname)
+               return NULL;
+       if ((fp = fopen(fname, type)) == NULL) {
+               xlog(L_ERROR, "can't open %s for %sing", fname,
+                               readonly ? "read" : "writ");
+               return NULL;
+       }
+       return fp;
+}
+
+struct rmtabent *
+getrmtabent(int log)
+{
+       return fgetrmtabent(rmfp, log);
+}
+
+struct rmtabent *
+fgetrmtabent(FILE *fp, int log)
+{
+       static struct rmtabent  re;
+       char    buf[2048], *sp;
+
+       errno = 0;
+       if (!fp)
+               return NULL;
+       do {
+               if (fgets(buf, sizeof(buf)-1, fp) == NULL)
+                       return NULL;
+               if ((sp = strchr(buf, '\n')) != NULL)
+                       *sp = '\0';
+               if (!(sp = strchr(buf, ':'))) {
+                       if (log)
+                               xlog(L_ERROR, "malformed entry in rmtab file");
+                       errno = EINVAL;
+                       return NULL;
+               }
+               *sp++ = '\0';
+       } while (0);
+       strncpy(re.r_client, buf, sizeof (re.r_client) - 1);
+       re.r_client[sizeof (re.r_client) - 1] = '\0';
+       strncpy(re.r_path, sp, sizeof (re.r_path) - 1);
+       re.r_path[sizeof (re.r_path) - 1] = '\0';
+       return &re;
+}
+
+void
+putrmtabent(struct rmtabent *rep)
+{
+       fputrmtabent(rmfp, rep);
+}
+
+void
+fputrmtabent(FILE *fp, struct rmtabent *rep)
+{
+       if (!fp)
+               return;
+       fprintf(fp, "%s:%s\n", rep->r_client, rep->r_path);
+}
+
+void
+endrmtabent(void)
+{
+       fendrmtabent(rmfp);
+       rmfp = NULL;
+}
+
+void
+fendrmtabent(FILE *fp)
+{
+       if (fp)
+               fclose(fp);
+}
+
+void
+rewindrmtabent(void)
+{
+       if (rmfp)
+               rewind(rmfp);
+}
+
+void
+frewindrmtabent(FILE *fp)
+{
+       if (fp)
+               rewind (fp);
+}
diff --git a/support/nfs/rpcdispatch.c b/support/nfs/rpcdispatch.c
new file mode 100644 (file)
index 0000000..e798ea5
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * support/nfs/rcpdispatch.c
+ *
+ * Generic RPC dispatcher.
+ *
+ * Copyright (C) 1995, 1996, Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <signal.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <string.h>
+#include "rpcmisc.h"
+#include "xlog.h"
+
+void
+rpc_dispatch(struct svc_req *rqstp, SVCXPRT *transp,
+                       struct rpc_dtable *dtable, int nvers,
+                       void *argp, void *resp)
+{
+       struct rpc_dentry       *dent;
+
+       if (rqstp->rq_vers > nvers) {
+               svcerr_progvers(transp, 1, nvers);
+               return;
+       }
+       dtable += (rqstp->rq_vers - 1);
+       if (rqstp->rq_proc > dtable->nproc) {
+               svcerr_noproc(transp);
+               return;
+       }
+
+       dent = dtable->entries + rqstp->rq_proc;
+
+       if (dent->func == NULL) {
+               svcerr_noproc(transp);
+               return;
+       }
+
+       memset(argp, 0, dent->xdr_arg_size);
+       memset(resp, 0, dent->xdr_res_size);
+
+       if (!svc_getargs(transp, dent->xdr_arg_fn, argp)) {
+               svcerr_decode(transp);
+               return;
+       }
+
+       if ((dent->func)(rqstp, argp, resp) && resp != 0) {
+               if (!svc_sendreply(transp, dent->xdr_res_fn, (caddr_t)resp)) 
+                       svcerr_systemerr(transp);
+       }
+       if (!svc_freeargs(transp, dent->xdr_arg_fn, argp)) {
+               xlog(L_ERROR, "failed to free RPC arguments");
+               exit (2);
+       }
+}
+
+#if 0
+/*
+ * This is our replacement for svc_run. It turns off some signals while
+ * executing the server procedures to avoid nasty race conditions.
+ */
+void
+rpc_svcrun(fd_set *morefds, void (*func)(int fd))
+{
+       sigset_t        block, current;
+       fd_set          readfds;
+
+       for (;;) {
+               readfds = svc_fdset;
+               if (morefds) {
+                       int     i;
+
+                       /* most efficient */
+                       for (i = 0; i < FD_SETSIZE; i++)
+                               if (FD_ISSET(i, morefds))
+                                       FD_SET(i, &readfs);
+               }
+               switch (select(FD_SETSIZE, &readfds, NULL, NULL, NULL)) {
+               case -1:
+                       if (errno == EINTR)
+                               continue;
+                       xlog(L_ERROR, "svc_run: - select failed");
+                       break;
+               case 0:
+                       continue;
+               default:
+                       if (morefds) {
+                               int     i;
+
+                               /* most efficient */
+                               for (i = 0; i < FD_SETSIZE; i++)
+                                       if (FD_ISSET(i, morefds) &&
+                                           FD_ISSET(i, &readfds))
+                                               func(i);
+                       }
+                       sigemptyset(&block);
+                       sigaddset(&block, SIGALRM);
+                       sigaddset(&block, SIGVTALRM);
+                       sigaddset(&block, SIGIO);
+                       sigprocmask(SIG_BLOCK, &block, &current);
+                       svc_getreqset(&readfds);
+                       sigprocmask(SIG_SETMASK, &current, NULL);
+               }
+       }
+}
+#endif
diff --git a/support/nfs/rpcmisc.c b/support/nfs/rpcmisc.c
new file mode 100644 (file)
index 0000000..7b182fd
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * support/nfs/rpcmisc.c
+ *
+ * Miscellaneous functions for RPC startup and shutdown.
+ * This code is partially snarfed from rpcgen -s tcp -s udp,
+ * partly written by Mark Shand, Donald Becker, and Rick 
+ * Sladkey. It was tweaked slightly by Olaf Kirch to be
+ * usable by both unfsd and mountd.
+ *
+ * This software may be used for any purpose provided
+ * the above copyright notice is retained.  It is supplied
+ * as is, with no warranty expressed or implied.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <memory.h>
+#include <errno.h>
+#include <unistd.h>
+#include "nfslib.h"
+
+static void    closedown(int sig);
+static int     makesock(int port, int proto, int socksz);
+
+#define _RPCSVC_CLOSEDOWN      120
+int    _rpcpmstart = 0;
+int    _rpcfdtype = 0;
+int    _rpcsvcdirty = 0;
+
+void
+rpc_init(char *name, int prog, int vers, void (*dispatch)(), int defport,
+                                                       int bufsiz)
+{
+       struct sockaddr_in saddr;
+       SVCXPRT *transp;
+       int     sock;
+       int     asize;
+
+       asize = sizeof(saddr);
+       sock = 0;
+       _rpcfdtype = 0;
+       if (getsockname(0, (struct sockaddr *) &saddr, &asize) == 0) {
+               int ssize = sizeof (int);
+               if (saddr.sin_family != AF_INET)
+                       xlog(L_FATAL, "init: stdin is bound to non-inet addr");
+               if (getsockopt(0, SOL_SOCKET, SO_TYPE,
+                               (char *)&_rpcfdtype, &ssize) == -1)
+                       xlog(L_FATAL, "getsockopt failed: %s", strerror(errno));
+               _rpcpmstart = 1;
+       } else {
+               pmap_unset(prog, vers);
+               sock = RPC_ANYSOCK;
+       }
+
+       if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
+               if (_rpcfdtype == 0 && defport != 0 &&
+                   ((sock = makesock(defport, IPPROTO_UDP, bufsiz)) < 0)) {
+                       xlog(L_FATAL, "%s: could not make a UDP socket\n",
+                                       name);
+               }
+               transp = svcudp_create(sock);
+               if (transp == NULL) {
+                       xlog(L_FATAL, "cannot create udp service.");
+               }
+               if (!svc_register(transp, prog, vers, dispatch, IPPROTO_UDP)) {
+                       xlog(L_FATAL, "unable to register (%s, %d, udp).",
+                                       name, vers);
+               }
+       }
+
+       if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
+               if (_rpcfdtype == 0 && defport != 0 &&
+                   ((sock = makesock(defport, IPPROTO_TCP, bufsiz)) < 0)) {
+                       xlog(L_FATAL, "%s: could not make a TCP socket\n",
+                                       name);
+               }
+               transp = svctcp_create(sock, 0, 0);
+               if (transp == NULL) {
+                       xlog(L_FATAL, "cannot create tcp service.");
+               }
+               if (!svc_register(transp, prog, vers, dispatch, IPPROTO_TCP)) {
+                       xlog(L_FATAL, "unable to register (%s, %d, tcp).",
+                                       name, vers);
+               }
+       }
+
+       if (_rpcpmstart) {
+               signal (SIGALRM, closedown);
+               alarm (_RPCSVC_CLOSEDOWN);
+       }
+}
+
+static void closedown(sig)
+int sig;
+{
+       (void) signal(sig, closedown);
+       if (_rpcsvcdirty == 0) {
+               extern fd_set svc_fdset;
+               static int size;
+               int i, openfd;
+
+               if (_rpcfdtype == SOCK_DGRAM)
+                       exit(0);
+               if (size == 0) {
+                       size = getdtablesize();
+               }
+               for (i = 0, openfd = 0; i < size && openfd < 2; i++)
+                       if (FD_ISSET(i, &svc_fdset))
+                               openfd++;
+               if (openfd <= 1)
+                       exit(0);
+       }
+       (void) alarm(_RPCSVC_CLOSEDOWN);
+}
+
+static int makesock(port, proto, socksz)
+int port;
+int proto;
+int socksz;
+{
+       struct sockaddr_in sin;
+       int     s;
+       int     sock_type;
+       int     val;
+
+       sock_type = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+       s = socket(AF_INET, sock_type, proto);
+       if (s < 0) {
+               xlog(L_FATAL, "Could not make a socket: %s\n",
+                                       strerror(errno));
+               return (-1);
+       }
+       memset((char *) &sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = INADDR_ANY;
+       sin.sin_port = htons(port);
+
+       val = 1;
+       if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0)
+               xlog(L_ERROR, "setsockopt failed: %s\n", strerror(errno));
+
+#ifdef SO_SNDBUF
+       {
+               int sblen, rblen;
+
+               /* 1024 for rpc & transport overheads */
+               sblen = rblen = socksz + 1024;
+               if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sblen, sizeof sblen) < 0 ||
+                   setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rblen, sizeof rblen) < 0)
+                       xlog(L_ERROR, "setsockopt failed: %s\n", strerror(errno));
+       }
+#endif                         /* SO_SNDBUF */
+
+       if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
+               xlog(L_FATAL, "Could not bind name to socket: %s\n",
+                                       strerror(errno));
+               return (-1);
+       }
+       return (s);
+}
+
+
+/* Log an incoming call. */
+void
+rpc_logcall(struct svc_req *rqstp, char *xname, char *arg)
+{
+       char            buff[1024];
+       int             buflen=sizeof(buff);
+       int             len;
+       char            *sp;
+       int             i;
+
+       if (!xlog_enabled(D_CALL))
+               return;
+
+       sp = buff;
+       switch (rqstp->rq_cred.oa_flavor) {
+       case AUTH_NULL:
+               sprintf(sp, "NULL");
+               break;
+       case AUTH_UNIX: {
+               struct authunix_parms *unix_cred;
+               struct tm *tm;
+
+               unix_cred = (struct authunix_parms *) rqstp->rq_clntcred;
+               tm = localtime(&unix_cred->aup_time);
+               snprintf(sp, buflen, "UNIX %d/%d/%d %02d:%02d:%02d %s %d.%d",
+                       tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+                       tm->tm_hour, tm->tm_min, tm->tm_sec,
+                       unix_cred->aup_machname,
+                       unix_cred->aup_uid,
+                       unix_cred->aup_gid);
+               sp[buflen-1] = 0;
+               len = strlen(sp);
+               sp += buflen;
+               buflen -= len;
+               if ((int) unix_cred->aup_len > 0) {
+                       snprintf(sp, buflen, "+%d", unix_cred->aup_gids[0]);
+                       sp[buflen-1] = 0;
+                       len = strlen(sp);
+                       sp += buflen;
+                       buflen -= len;
+                       for (i = 1; i < unix_cred->aup_len; i++) {
+                               snprintf(sp, buflen, ",%d", 
+                                       unix_cred->aup_gids[i]);
+                               sp[buflen-1] = 0;
+                               len = strlen(sp);
+                               sp += buflen;
+                               buflen -= len;
+                       }
+               }
+               }
+               break;
+       default:
+               sprintf(sp, "CRED %d", rqstp->rq_cred.oa_flavor);
+       }
+       xlog(D_CALL, "%s [%s]\n\t%s\n", xname, buff, arg);
+}
diff --git a/support/nfs/wildmat.c b/support/nfs/wildmat.c
new file mode 100644 (file)
index 0000000..8f7b760
--- /dev/null
@@ -0,0 +1,177 @@
+/*  $Revision: 0.2.18.1 $
+**
+**  Do shell-style pattern matching for ?, \, [], and * characters.
+**  Might not be robust in face of malformed patterns; e.g., "foo[a-"
+**  could cause a segmentation violation.  It is 8bit clean.
+**
+**  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
+**  Rich $alz is now <rsalz@osf.org>.
+**  April, 1991:  Replaced mutually-recursive calls with in-line code
+**  for the star character.
+**
+**  Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
+**  This can greatly speed up failing wildcard patterns.  For example:
+**     pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
+**     text 1:  -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
+**     text 2:  -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
+**  Text 1 matches with 51 calls, while text 2 fails with 54 calls.  Without
+**  the ABORT code, it takes 22310 calls to fail.  Ugh.  The following
+**  explanation is from Lars:
+**  The precondition that must be fulfilled is that DoMatch will consume
+**  at least one character in text.  This is true if *p is neither '*' nor
+**  '\0'.)  The last return has ABORT instead of FALSE to avoid quadratic
+**  behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx".  With
+**  FALSE, each star-loop has to run to the end of the text; with ABORT
+**  only the last one does.
+**
+**  Once the control of one instance of DoMatch enters the star-loop, that
+**  instance will return either TRUE or ABORT, and any calling instance
+**  will therefore return immediately after (without calling recursively
+**  again).  In effect, only one star-loop is ever active.  It would be
+**  possible to modify the code to maintain this context explicitly,
+**  eliminating all recursive calls at the cost of some complication and
+**  loss of clarity (and the ABORT stuff seems to be unclear enough by
+**  itself).  I think it would be unwise to try to get this into a
+**  released version unless you have a good test data base to try it out
+**  on.
+*/
+
+#include "config.h"
+
+#include <ctype.h>
+
+#define TRUE                   1
+#define FALSE                  0
+#define ABORT                  -1
+
+
+    /* What character marks an inverted character class? */
+#define NEGATE_CLASS           '^'
+    /* Is "*" a common pattern? */
+#define OPTIMIZE_JUST_STAR
+    /* Do tar(1) matching rules, which ignore a trailing slash? */
+#undef MATCH_TAR_PATTERN
+
+
+/*
+**  Match text and p, return TRUE, FALSE, or ABORT.
+*/
+static int
+DoMatch(text, p)
+    register char      *text;
+    register char      *p;
+{
+    register int       last;
+    register int       matched;
+    register int       reverse;
+
+    for ( ; *p; text++, p++) {
+       if (*text == '\0' && *p != '*')
+           return ABORT;
+       switch (*p) {
+       case '\\':
+           /* Literal match with following character. */
+           p++;
+           /* FALLTHROUGH */
+       default:
+           if (toupper (*text) != toupper (*p))
+               return FALSE;
+           continue;
+       case '?':
+           /* Match anything. */
+           continue;
+       case '*':
+           while (*++p == '*')
+               /* Consecutive stars act just like one. */
+               continue;
+           if (*p == '\0')
+               /* Trailing star matches everything. */
+               return TRUE;
+           while (*text)
+               if ((matched = DoMatch(text++, p)) != FALSE)
+                   return matched;
+           return ABORT;
+       case '[':
+           reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
+           if (reverse)
+               /* Inverted character class. */
+               p++;
+           matched = FALSE;
+           if (p[1] == ']' || p[1] == '-')
+               if (toupper (*++p) == toupper(*text))
+                   matched = TRUE;
+           for (last = *p; *++p && *p != ']'; last = *p)
+               /* This next line requires a good C compiler. */
+               if (*p == '-' && p[1] != ']'
+                   ? *text <= *++p && *text >= last
+                     : toupper (*text) == toupper (*p))
+                   matched = TRUE;
+           if (matched == reverse)
+               return FALSE;
+           continue;
+       }
+    }
+
+#ifdef MATCH_TAR_PATTERN
+    if (*text == '/')
+       return TRUE;
+#endif /* MATCH_TAR_ATTERN */
+    return *text == '\0';
+}
+
+
+/*
+**  User-level routine.  Returns TRUE or FALSE.
+*/
+int
+wildmat(text, p)
+    char       *text;
+    char       *p;
+{
+#ifdef OPTIMIZE_JUST_STAR
+    if (p[0] == '*' && p[1] == '\0')
+       return TRUE;
+#endif /* OPTIMIZE_JUST_STAR */
+    return DoMatch(text, p) == TRUE;
+}
+
+\f
+
+#if    defined(TEST)
+#include <stdio.h>
+
+/* Yes, we use gets not fgets.  Sue me. */
+extern char    *gets();
+
+
+int
+main()
+{
+    char        p[80];
+    char        text[80];
+
+    printf("Wildmat tester.  Enter pattern, then strings to test.\n");
+    printf("A blank line gets prompts for a new pattern; a blank pattern\n");
+    printf("exits the program.\n");
+
+    for ( ; ; ) {
+       printf("\nEnter pattern:  ");
+       (void)fflush(stdout);
+       if (gets(p) == NULL || p[0] == '\0')
+           break;
+       for ( ; ; ) {
+           printf("Enter text:  ");
+           (void)fflush(stdout);
+           if (gets(text) == NULL)
+               exit(0);
+           if (text[0] == '\0')
+               /* Blank line; go back and get a new pattern. */
+               break;
+           printf("      %s\n", wildmat(text, p) ? "YES" : "NO");
+       }
+    }
+
+    exit(0);
+    /* NOTREACHED */
+}
+#endif /* defined(TEST) */
diff --git a/support/nfs/xio.c b/support/nfs/xio.c
new file mode 100644 (file)
index 0000000..1bcd41b
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * support/nfs/xio.c
+ * 
+ * Simple I/O functions for the parsing of /etc/exports and /etc/nfsclients.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <unistd.h>
+#include "xmalloc.h"
+#include "xlog.h"
+#include "xio.h"
+
+XFILE *
+xfopen(char *fname, char *type)
+{
+       XFILE   *xfp;
+       FILE    *fp;
+
+       if (!(fp = fopen(fname, type)))
+               return NULL;
+       xfp = (XFILE *) xmalloc(sizeof(*xfp));
+       xfp->x_fp = fp;
+       xfp->x_line = 0;
+
+       return xfp;
+}
+
+void
+xfclose(XFILE *xfp)
+{
+       fclose(xfp->x_fp);
+       xfree(xfp);
+}
+
+static void
+doalarm(int sig)
+{
+       return;
+}
+
+int
+xflock(char *fname, char *type)
+{
+       struct sigaction sa, oldsa;
+       int             readonly = !strcmp(type, "r");
+       struct flock    fl = { readonly? F_RDLCK : F_WRLCK, SEEK_SET, 0, 0, 0 };
+       int             fd;
+
+       if ((fd = open(fname, readonly? O_RDONLY : O_RDWR)) < 0) {
+               xlog(L_WARNING, "could not open %s for locking", fname);
+               return -1;
+       }
+       sa.sa_handler = doalarm;
+       sa.sa_flags = 0;
+       sigemptyset(&sa.sa_mask);
+       sigaction(SIGALRM, &sa, &oldsa);
+       alarm(10);
+       if (fcntl(fd, F_SETLKW, &fl) < 0) {
+               alarm(0);
+               xlog(L_WARNING, "failed to lock %s", fname);
+               close(fd);
+               fd = 0;
+       } else {
+               alarm(0);
+       }
+       sigaction(SIGALRM, &oldsa, NULL);
+
+       return fd;
+}
+
+void
+xfunlock(int fd)
+{
+       close(fd);
+}
+
+int
+xgettok(XFILE *xfp, char sepa, char *tok, int len)
+{
+       int     i = 0;
+       char    c = 0;
+
+       while (i < len && (c = xgetc(xfp)) != EOF && c != sepa && !isspace(c))
+               tok[i++] = c;
+       if (c == '\n')
+               ungetc(c, xfp->x_fp);
+       if (!i)
+               return 0;
+       if (i >= len || (sepa && c != sepa))
+               return -1;
+       tok[i] = '\0';
+       return 1;
+}
+
+char
+xgetc(XFILE *xfp)
+{
+       char    c = getc(xfp->x_fp);
+
+       if (c == EOF)
+               return c;
+       if (c == '\\') {
+               if ((c = getc(xfp->x_fp)) != '\n') {
+                       ungetc(c, xfp->x_fp);
+                       return '\\';
+               }
+               xfp->x_line++;
+               while ((c = getc(xfp->x_fp)) == ' ' || c == '\t');
+               ungetc(c, xfp->x_fp);
+               return ' ';
+       }
+       if (c == '#')
+               c = xskipcomment(xfp);
+       if (c == '\n')
+               xfp->x_line++;
+       return c;
+}
+
+void
+xungetc(char c, XFILE *xfp)
+{
+       if (c != EOF)
+               ungetc(c, xfp->x_fp);
+}
+
+void
+xskip(XFILE *xfp, char *str)
+{
+       char    c;
+
+       while ((c = xgetc(xfp)) != EOF && strchr(str, c));
+       ungetc(c, xfp->x_fp);
+}
+
+char
+xskipcomment(XFILE *xfp)
+{
+       char    c;
+
+       while ((c = getc(xfp->x_fp)) != EOF && c != '\n');
+       return c;
+}
diff --git a/support/nfs/xlog.c b/support/nfs/xlog.c
new file mode 100644 (file)
index 0000000..90c7e63
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * support/nfs/xlog.c
+ *
+ * This module handles the logging of requests.
+ *
+ * TODO:       Merge the two "XXX_log() calls.
+ *
+ * Authors:    Donald J. Becker, <becker@super.org>
+ *             Rick Sladkey, <jrs@world.std.com>
+ *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *             Olaf Kirch, <okir@monad.swb.de>
+ *
+ *             This software maybe be used for any purpose provided
+ *             the above copyright notice is retained.  It is supplied
+ *             as is, with no warranty expressed or implied.
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include "nfslib.h"
+
+#undef VERBOSE_PRINTF
+
+static int  foreground = 1;            /* not a daemon initially       */
+static int  logging = 0;               /* enable/disable DEBUG logs    */
+static int  logmask = 0;               /* What will be logged          */
+static char log_name[256];             /* name of this program         */
+static int  log_pid = -1;              /* PID of this program          */
+static FILE *log_fp = (FILE *)NULL;    /* fp for the log file          */
+
+static void    xlog_toggle(int sig);
+static struct xlog_debugfac    debugnames[] = {
+       { "general",    D_GENERAL, },
+       { "call",       D_CALL, },
+       { "auth",       D_AUTH, },
+       { "parse",      D_PARSE, },
+       { "all",        D_ALL, },
+       { NULL,         0, },
+};
+
+void
+xlog_open(char *progname)
+{
+       openlog(progname, LOG_PID, LOG_DAEMON);
+       if (foreground) {
+               log_fp = stderr;
+               if (log_fp != NULL)
+                       setbuf(log_fp, NULL);
+       }
+
+       strncpy(log_name, progname, sizeof (log_name) - 1);
+       log_name [sizeof (log_name) - 1] = '\0';
+       log_pid = getpid();
+
+       signal(SIGUSR1, xlog_toggle);
+       signal(SIGUSR2, xlog_toggle);
+}
+
+void
+xlog_background(void)
+{
+       foreground = 0;
+}
+
+static void
+xlog_toggle(int sig)
+{
+       unsigned int    tmp, i;
+
+       if (sig == SIGUSR1) {
+               if ((logmask & D_ALL) && !logging) {
+                       xlog(D_GENERAL, "turned on logging");
+                       logging = 1;
+                       return;
+               }
+               tmp = ~logmask;
+               logmask |= ((logmask & D_ALL) << 1) | D_GENERAL;
+               for (i = -1, tmp &= logmask; tmp; tmp >>= 1, i++)
+                       if (tmp & 1)
+                               xlog(D_GENERAL,
+                                       "turned on logging level %d", i);
+       } else {
+               xlog(D_GENERAL, "turned off logging");
+               logging = 0;
+       }
+       signal(sig, xlog_toggle);
+}
+
+void
+xlog_config(int fac, int on)
+{
+       if (on)
+               logmask |= fac;
+       else
+               logmask &= ~fac;
+       if (on)
+               logging = 1;
+}
+
+void
+xlog_sconfig(char *kind, int on)
+{
+       struct xlog_debugfac    *tbl = debugnames;
+
+       while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind)) 
+               tbl++;
+       if (!tbl->df_name) {
+               xlog (L_WARNING, "Invalid debug facility: %s\n", kind);
+               return;
+       }
+       xlog_config(tbl->df_fac, on);
+}
+
+int
+xlog_enabled(int fac)
+{
+       return (logging && (fac & logmask));
+}
+
+
+/* Write something to the system logfile. */
+void
+xlog(int kind, const char *fmt, ...)
+{
+       char            buff[1024];
+       va_list         args;
+       int             logged = 1, n;
+#ifdef VERBOSE_PRINTF
+       time_t          now;
+       struct tm       *tm;
+#endif
+
+       if (!(kind & (L_ALL)) && !(logging && (kind & logmask)))
+               return;
+
+       va_start(args, fmt);
+       vsnprintf(buff, sizeof (buff), fmt, args);
+       va_end(args);
+       buff[sizeof (buff) - 1] = 0;
+
+       if ((n = strlen(buff)) > 0 && buff[n-1] != '\n') {
+               buff[n++] = '\n'; buff[n++] = '\0';
+       }
+
+       switch (kind) {
+       case L_FATAL:
+               syslog(LOG_ERR, "%s", buff);
+               break;
+       case L_ERROR:
+               syslog(LOG_ERR, "%s", buff);
+               break;
+       case L_WARNING:
+               syslog(LOG_WARNING, "%s", buff);
+               break;
+       case L_NOTICE:
+               syslog(LOG_NOTICE, "%s", buff);
+               break;
+       default:
+               logged = 0;
+               break;
+       }
+       if (!logged || foreground) {
+               if (!logged && log_fp == NULL) {
+                       syslog(LOG_DEBUG, "%s", buff);
+               } else if (log_fp != NULL) {
+#ifdef VERBOSE_PRINTF
+                       time(&now);
+                       tm = localtime(&now);
+                       fprintf(log_fp, "%s[%d] %02d/%02d/%02d %02d:%02d %s\n",
+                                       log_name, log_pid,
+                                       tm->tm_mon + 1, tm->tm_mday,
+                                       tm->tm_year, tm->tm_hour, tm->tm_min,
+                                       buff);
+#else
+                       fprintf(log_fp, "%s: %s", log_name, buff);
+#endif
+               }
+       }
+       if (kind == L_FATAL)
+               exit(1);
+}
diff --git a/support/nfs/xmalloc.c b/support/nfs/xmalloc.c
new file mode 100644 (file)
index 0000000..9523afc
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * support/nfs/xmalloc.c
+ *
+ * malloc with NULL checking.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "xmalloc.h"
+#include "xlog.h"
+
+void *
+xmalloc(size_t size)
+{
+       void    *ptr;
+
+       if (!(ptr = malloc(size)))
+               xlog(L_FATAL, "malloc: out of memory");
+       return ptr;
+}
+
+void *
+xrealloc(void *ptr, size_t size)
+{
+       if (!(ptr = realloc(ptr, size)))
+               xlog(L_FATAL, "realloc: out of memory");
+       return ptr;
+}
+
+void
+xfree(void *ptr)
+{
+       free(ptr);
+}
+
+char *
+xstrdup(const char *str)
+{
+       char    *ret;
+
+       if (!(ret = strdup(str)))
+               xlog(L_FATAL, "strdup: out of memory");
+       return ret;
+}
diff --git a/support/nfs/ypupdate_xdr.c b/support/nfs/ypupdate_xdr.c
new file mode 100644 (file)
index 0000000..9fe1098
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * support/nfs/ypupdate_xdr.c
+ *
+ * This file contains the XDR code for the ypupdate protocol.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <ypupdate.h>
+
+bool_t
+xdr_ypupdate_args(XDR *xdrs, ypupdate_args *objp)
+{
+        return xdr_string(xdrs, &objp->mapname, MAXMAPNAMELEN) &&
+               xdr_bytes(xdrs, &objp->key.yp_buf_val,
+                               &objp->key.yp_buf_len, MAXYPDATALEN) &&
+               xdr_bytes(xdrs, &objp->datum.yp_buf_val,
+                               &objp->datum.yp_buf_len, MAXYPDATALEN);
+}
+
+bool_t
+xdr_ypdelete_args(XDR *xdrs, ypdelete_args *objp)
+{
+        return xdr_string(xdrs, &objp->mapname, MAXMAPNAMELEN) &&
+               xdr_bytes(xdrs, &objp->key.yp_buf_val,
+                               &objp->key.yp_buf_len, MAXYPDATALEN);
+}
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644 (file)
index 0000000..6378850
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Various debugging/testing tools
+#
+
+SUBDIRS        = rpcgen getiversion getkversion nlmtest rpcdebug locktest
+
+include $(TOP)rules.mk
diff --git a/tools/getiversion/Makefile b/tools/getiversion/Makefile
new file mode 100644 (file)
index 0000000..46c7150
--- /dev/null
@@ -0,0 +1,11 @@