summaryrefslogtreecommitdiffstats
path: root/contrib/amd/libamu
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1998-08-23 22:07:21 +0000
committerobrien <obrien@FreeBSD.org>1998-08-23 22:07:21 +0000
commit663d5a0f32ed8dfc091ffb6153161591ac6ba563 (patch)
tree60b090a6cbdb64326bb128ea49a231d08eb2680e /contrib/amd/libamu
downloadFreeBSD-src-663d5a0f32ed8dfc091ffb6153161591ac6ba563.zip
FreeBSD-src-663d5a0f32ed8dfc091ffb6153161591ac6ba563.tar.gz
Virgin import of AMD (am-utils) v6.0a16
Diffstat (limited to 'contrib/amd/libamu')
-rw-r--r--contrib/amd/libamu/amu.h78
-rw-r--r--contrib/amd/libamu/hasmntopt.c119
-rw-r--r--contrib/amd/libamu/misc_rpc.c168
-rw-r--r--contrib/amd/libamu/mount_fs.c892
-rw-r--r--contrib/amd/libamu/mtab.c121
-rw-r--r--contrib/amd/libamu/nfs_prot_xdr.c59
-rw-r--r--contrib/amd/libamu/util.c176
-rw-r--r--contrib/amd/libamu/wire.c404
-rw-r--r--contrib/amd/libamu/xdr_func.c1155
-rw-r--r--contrib/amd/libamu/xutil.c825
10 files changed, 3997 insertions, 0 deletions
diff --git a/contrib/amd/libamu/amu.h b/contrib/amd/libamu/amu.h
new file mode 100644
index 0000000..f69b99e
--- /dev/null
+++ b/contrib/amd/libamu/amu.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: amu.h,v 1.1 1996/01/13 23:23:39 ezk Exp ezk $
+ *
+ */
+
+#ifndef _AMU_H
+#define _AMU_H
+
+/*
+ * Decide what maximum level of NFS server to try and mount with.
+ */
+#ifdef HAVE_FS_NFS3
+# define NFS_VERS_MAX NFS_VERSION3
+#else /* not HAVE_FS_NFS3 */
+# define NFS_VERS_MAX NFS_VERSION
+#endif /* not HAVE_FS_NFS3 */
+
+/* some systems like ncr2 do not define this in <rpcsvc/mount.h> */
+#ifndef MNTPATHLEN
+# define MNTPATHLEN 1024
+#endif /* not MNTPATHLEN */
+#ifndef MNTNAMLEN
+# define MNTNAMLEN 255
+#endif /* not MNTNAMLEN */
+
+/*
+ * external definitions for building libamu.a
+ */
+extern voidp amqproc_null_1(voidp argp, CLIENT *rqstp);
+extern amq_mount_tree_p *amqproc_mnttree_1(amq_string *argp, CLIENT *rqstp);
+extern voidp amqproc_umnt_1(amq_string *argp, CLIENT *rqstp);
+extern amq_mount_stats *amqproc_stats_1(voidp argp, CLIENT *rqstp);
+extern amq_mount_tree_list *amqproc_export_1(voidp argp, CLIENT *rqstp);
+extern int *amqproc_setopt_1(amq_setopt *argp, CLIENT *rqstp);
+extern amq_mount_info_list *amqproc_getmntfs_1(voidp argp, CLIENT *rqstp);
+extern int *amqproc_mount_1(voidp argp, CLIENT *rqstp);
+extern amq_string *amqproc_getvers_1(voidp argp, CLIENT *rqstp);
+
+#endif /* not _AMU_H */
diff --git a/contrib/amd/libamu/hasmntopt.c b/contrib/amd/libamu/hasmntopt.c
new file mode 100644
index 0000000..7cf9167
--- /dev/null
+++ b/contrib/amd/libamu/hasmntopt.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+n * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: hasmntopt.c,v 5.2.2.2 1992/05/31 16:35:45 jsp Exp $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+#ifndef MNTMAXSTR
+# define MNTMAXSTR 128
+#endif /* not MNTMAXSTR */
+
+
+/*
+ * Some systems don't provide these to the user,
+ * but amd needs them, so...
+ *
+ * From: Piete Brooks <pb@cl.cam.ac.uk>
+ */
+
+static char *
+nextmntopt(char **p)
+{
+ char *cp = *p;
+ char *rp;
+
+ /*
+ * Skip past white space
+ */
+ while (*cp && isspace(*cp))
+ cp++;
+
+ /*
+ * Word starts here
+ */
+ rp = cp;
+
+ /*
+ * Scan to send of string or separator
+ */
+ while (*cp && *cp != ',')
+ cp++;
+
+ /*
+ * If separator found the overwrite with nul char.
+ */
+ if (*cp) {
+ *cp = '\0';
+ cp++;
+ }
+
+ /*
+ * Return value for next call
+ */
+ *p = cp;
+ return rp;
+}
+
+/*
+ * replacement for hasmntopt if the system does not have it.
+ */
+char *
+hasmntopt(mntent_t *mnt, char *opt)
+{
+ char t[MNTMAXSTR];
+ char *f;
+ char *o = t;
+ int l = strlen(opt);
+
+ strcpy(t, mnt->mnt_opts);
+
+ while (*(f = nextmntopt(&o)))
+ if (NSTREQ(opt, f, l))
+ return f - t + mnt->mnt_opts;
+
+ return 0;
+}
diff --git a/contrib/amd/libamu/misc_rpc.c b/contrib/amd/libamu/misc_rpc.c
new file mode 100644
index 0000000..b6d23cd
--- /dev/null
+++ b/contrib/amd/libamu/misc_rpc.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: misc_rpc.c,v 5.2.2.1 1992/02/09 15:08:40 jsp beta $
+ *
+ */
+
+/*
+ * Additions to Sun RPC.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+/*
+ * Some systems renamed _seterr_reply to __seterr_reply (with two
+ * leading underscores)
+ */
+#if !defined(HAVE__SETERR_REPLY) && defined(HAVE___SETERR_REPLY)
+# define _seterr_reply __seterr_reply
+#endif /* !defined(HAVE__SETERR_REPLY) && defined(HAVE___SETERR_REPLY) */
+
+
+void
+rpc_msg_init(struct rpc_msg *mp, u_long prog, u_long vers, u_long proc)
+{
+ /*
+ * Initialise the message
+ */
+ memset((voidp) mp, 0, sizeof(*mp));
+ mp->rm_xid = 0;
+ mp->rm_direction = CALL;
+ mp->rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ mp->rm_call.cb_prog = prog;
+ mp->rm_call.cb_vers = vers;
+ mp->rm_call.cb_proc = proc;
+}
+
+
+/*
+ * Field reply to call to mountd
+ */
+int
+pickup_rpc_reply(voidp pkt, int len, voidp where, XDRPROC_T_TYPE where_xdr)
+{
+ XDR reply_xdr;
+ int ok;
+ struct rpc_err err;
+ struct rpc_msg reply_msg;
+ int error = 0;
+
+ /* memset((voidp) &err, 0, sizeof(err)); */
+ memset((voidp) &reply_msg, 0, sizeof(reply_msg));
+ memset((voidp) &reply_xdr, 0, sizeof(reply_xdr));
+
+ reply_msg.acpted_rply.ar_results.where = (caddr_t) where;
+ reply_msg.acpted_rply.ar_results.proc = where_xdr;
+
+ xdrmem_create(&reply_xdr, pkt, len, XDR_DECODE);
+
+ ok = xdr_replymsg(&reply_xdr, &reply_msg);
+ if (!ok) {
+ error = EIO;
+ goto drop;
+ }
+ _seterr_reply(&reply_msg, &err);
+ if (err.re_status != RPC_SUCCESS) {
+ error = EIO;
+ goto drop;
+ }
+
+drop:
+ if (reply_msg.rm_reply.rp_stat == MSG_ACCEPTED &&
+ reply_msg.acpted_rply.ar_verf.oa_base) {
+ reply_xdr.x_op = XDR_FREE;
+ (void) xdr_opaque_auth(&reply_xdr,
+ &reply_msg.acpted_rply.ar_verf);
+ }
+ xdr_destroy(&reply_xdr);
+
+ return error;
+}
+
+
+int
+make_rpc_packet(char *buf, int buflen, u_long proc, struct rpc_msg *mp, voidp arg, XDRPROC_T_TYPE arg_xdr, AUTH *auth)
+{
+ XDR msg_xdr;
+ int len;
+
+ xdrmem_create(&msg_xdr, buf, buflen, XDR_ENCODE);
+
+ /*
+ * Basic protocol header
+ */
+ if (!xdr_callhdr(&msg_xdr, mp))
+ return -EIO;
+
+ /*
+ * Called procedure number
+ */
+ if (!xdr_enum(&msg_xdr, (enum_t *) & proc))
+ return -EIO;
+
+ /*
+ * Authorization
+ */
+ if (!AUTH_MARSHALL(auth, &msg_xdr))
+ return -EIO;
+
+ /*
+ * Arguments
+ */
+ if (!(*arg_xdr) (&msg_xdr, arg))
+ return -EIO;
+
+ /*
+ * Determine length
+ */
+ len = xdr_getpos(&msg_xdr);
+
+ /*
+ * Throw away xdr
+ */
+ xdr_destroy(&msg_xdr);
+
+ return len;
+}
diff --git a/contrib/amd/libamu/mount_fs.c b/contrib/amd/libamu/mount_fs.c
new file mode 100644
index 0000000..948b18d
--- /dev/null
+++ b/contrib/amd/libamu/mount_fs.c
@@ -0,0 +1,892 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: mount_fs.c,v 5.2.2.2 1992/05/31 16:35:45 jsp Exp $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+
+/* ensure that mount table options are delimited by a comma */
+#define append_opts(old, new) { \
+ if (*(old) != '\0') strcat(old, ","); \
+ strcat(old, new); }
+
+/*
+ * Standard mount flags
+ */
+struct opt_tab mnt_flags[] =
+{
+#if defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO)
+ {MNTTAB_OPT_RO, MNT2_GEN_OPT_RDONLY},
+#endif /* defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO) */
+
+#if defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE)
+ {MNTTAB_OPT_NOCACHE, MNT2_GEN_OPT_NOCACHE},
+#endif /* defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE) */
+
+ /* the "grpid" mount option can be offered as generic of NFS */
+#ifdef MNTTAB_OPT_GRPID
+# ifdef MNT2_GEN_OPT_GRPID
+ {MNTTAB_OPT_GRPID, MNT2_GEN_OPT_GRPID},
+# endif /* MNT2_GEN_OPT_GRPID */
+# ifdef MNT2_NFS_OPT_GRPID
+ {MNTTAB_OPT_GRPID, MNT2_NFS_OPT_GRPID},
+# endif /* MNT2_NFS_OPT_GRPID */
+#endif /* MNTTAB_OPT_GRPID */
+
+#if defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI)
+ {MNTTAB_OPT_MULTI, MNT2_GEN_OPT_MULTI},
+#endif /* defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI) */
+
+#if defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV)
+ {MNTTAB_OPT_NODEV, MNT2_GEN_OPT_NODEV},
+#endif /* defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV) */
+
+#if defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC)
+ {MNTTAB_OPT_NOEXEC, MNT2_GEN_OPT_NOEXEC},
+#endif /* defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC) */
+
+#if defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB)
+ {MNTTAB_OPT_NOSUB, MNT2_GEN_OPT_NOSUB},
+#endif /* defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB) */
+
+#if defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID)
+ {MNTTAB_OPT_NOSUID, MNT2_GEN_OPT_NOSUID},
+#endif /* defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID) */
+
+#if defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC)
+ {MNTTAB_OPT_SYNC, MNT2_GEN_OPT_SYNC},
+#endif /* defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC) */
+
+#if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
+ {MNTTAB_OPT_OVERLAY, MNT2_GEN_OPT_OVERLAY},
+#endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
+
+ {0, 0}
+};
+
+
+int
+compute_mount_flags(mntent_t *mntp)
+{
+ struct opt_tab *opt;
+ int flags;
+
+ /* start: this must come first */
+#ifdef MNT2_GEN_OPT_NEWTYPE
+ flags = MNT2_GEN_OPT_NEWTYPE;
+#else /* not MNT2_GEN_OPT_NEWTYPE */
+ /* Not all machines have MNT2_GEN_OPT_NEWTYPE (HP-UX 9.01) */
+ flags = 0;
+#endif /* not MNT2_GEN_OPT_NEWTYPE */
+
+#if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
+ /*
+ * Overlay this amd mount (presumably on another amd which died
+ * before and left the machine hung). This will allow a new amd or
+ * hlfsd to be remounted on top of another one.
+ */
+ if (hasmntopt(mntp, MNTTAB_OPT_OVERLAY)) {
+ flags |= MNT2_GEN_OPT_OVERLAY;
+ plog(XLOG_INFO, "using an overlay mount");
+ }
+#endif /* defined(MNT2_GEN_OVERLAY) && defined(MNTOPT_OVERLAY) */
+
+ /*
+ * Crack basic mount options
+ */
+ for (opt = mnt_flags; opt->opt; opt++) {
+ flags |= hasmntopt(mntp, opt->opt) ? opt->flag : 0;
+ }
+
+ return flags;
+}
+
+
+int
+mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto, const char *mnttabname)
+{
+ int error = 0;
+#ifdef MOUNT_TABLE_ON_FILE
+# ifdef MNTTAB_OPT_DEV
+ struct stat stb;
+# endif /* MNTTAB_OPT_DEV */
+ char *zopts = NULL, *xopts = NULL;
+# if defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO)
+ char optsbuf[48];
+# endif /* defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO) */
+#endif /* MOUNT_TABLE_ON_FILE */
+#ifdef DEBUG
+ char buf[80]; /* buffer for sprintf */
+#endif /* DEBUG */
+
+#ifdef DEBUG
+ sprintf(buf, "%s%s%s",
+ "%s fstype ", MTYPE_PRINTF_TYPE, " (%s) flags %#x (%s)");
+ dlog(buf, mnt->mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
+#endif /* DEBUG */
+
+again:
+ clock_valid = 0;
+
+ error = MOUNT_TRAP(type, mnt, flags, mnt_data);
+
+ if (error < 0) {
+ plog(XLOG_ERROR, "%s: mount: %m", mnt->mnt_dir);
+ /*
+ * The following code handles conditions which shouldn't
+ * occur. They are possible either because amd screws up
+ * in preparing for the mount, or because some human
+ * messed with the mount point. Both have been known to
+ * happen. -- stolcke 2/22/95
+ */
+ if (errno == ENOENT) {
+ /*
+ * Occasionally the mount point vanishes, probably
+ * due to some race condition. Just recreate it
+ * as necessary.
+ */
+ errno = mkdirs(mnt->mnt_dir, 0555);
+ if (errno != 0 && errno != EEXIST)
+ plog(XLOG_ERROR, "%s: mkdirs: %m", mnt->mnt_dir);
+ else {
+ plog(XLOG_WARNING, "extra mkdirs required for %s",
+ mnt->mnt_dir);
+ error = MOUNT_TRAP(type, mnt, flags, mnt_data);
+ }
+ } else if (errno == EBUSY) {
+ /*
+ * Also, sometimes unmount isn't called, e.g., because
+ * our mountlist is garbled. This leaves old mount
+ * points around which need to be removed before we
+ * can mount something new in their place.
+ */
+ errno = umount_fs(mnt->mnt_dir, mnttabname);
+ if (errno != 0)
+ plog(XLOG_ERROR, "%s: umount: %m", mnt->mnt_dir);
+ else {
+ plog(XLOG_WARNING, "extra umount required for %s",
+ mnt->mnt_dir);
+ error = MOUNT_TRAP(type, mnt, flags, mnt_data);
+ }
+ }
+ }
+
+ if (error < 0 && --retry > 0) {
+ sleep(1);
+ goto again;
+ }
+ if (error < 0) {
+ return errno;
+ }
+
+#ifdef MOUNT_TABLE_ON_FILE
+ /*
+ * Allocate memory for options:
+ * dev=..., vers={2,3}, proto={tcp,udp}
+ */
+ zopts = (char *) xmalloc(strlen(mnt->mnt_opts) + 48);
+
+ /* copy standard options */
+ xopts = mnt->mnt_opts;
+
+ strcpy(zopts, xopts);
+
+# ifdef MNTTAB_OPT_DEV
+ /* add the extra dev= field to the mount table */
+ if (lstat(mnt->mnt_dir, &stb) == 0) {
+ if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */
+ sprintf(optsbuf, "%s=%04lx",
+ MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff);
+ else /* e.g. System Vr4 */
+ sprintf(optsbuf, "%s=%08lx",
+ MNTTAB_OPT_DEV, (u_long) stb.st_dev);
+ append_opts(zopts, optsbuf);
+ }
+# endif /* MNTTAB_OPT_DEV */
+
+# if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
+ /*
+ * add the extra vers={2,3} field to the mount table,
+ * unless already specified by user
+ */
+ if (nfs_version == NFS_VERSION3 &&
+ hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) {
+ sprintf(optsbuf, "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3);
+ append_opts(zopts, optsbuf);
+ }
+# endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */
+
+# ifdef MNTTAB_OPT_PROTO
+ /*
+ * add the extra proto={tcp,udp} field to the mount table,
+ * unless already specified by user.
+ */
+ if (nfs_proto && !hasmntopt(mnt, MNTTAB_OPT_PROTO)) {
+ sprintf(optsbuf, "%s=%s", MNTTAB_OPT_PROTO, nfs_proto);
+ append_opts(zopts, optsbuf);
+ }
+# endif /* MNTTAB_OPT_PROTO */
+
+ /* finally, store the options into the mount table structure */
+ mnt->mnt_opts = zopts;
+
+ /*
+ * Additional fields in mntent_t
+ * are fixed up here
+ */
+# ifdef HAVE_FIELD_MNTENT_T_MNT_CNODE
+ mnt->mnt_cnode = 0;
+# endif /* HAVE_FIELD_MNTENT_T_MNT_CNODE */
+
+# ifdef HAVE_FIELD_MNTENT_T_MNT_RO
+ mnt->mnt_ro = (hasmntopt(mnt, MNTTAB_OPT_RO) != NULL);
+# endif /* HAVE_FIELD_MNTENT_T_MNT_RO */
+
+# ifdef HAVE_FIELD_MNTENT_T_MNT_TIME
+# ifdef HAVE_FIELD_MNTENT_T_MNT_TIME_STRING
+ { /* allocate enough space for a long */
+ char *str = (char *) xmalloc(13 * sizeof(char));
+ sprintf(str, "%ld", time((time_t *) NULL));
+ mnt->mnt_time = str;
+ }
+# else /* not HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
+ mnt->mnt_time = time((time_t *) NULL);
+# endif /* not HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
+# endif /* HAVE_FIELD_MNTENT_T_MNT_TIME */
+
+ write_mntent(mnt, mnttabname);
+
+# ifdef MNTTAB_OPT_DEV
+ if (xopts) {
+ XFREE(mnt->mnt_opts);
+ mnt->mnt_opts = xopts;
+ }
+# endif /* MNTTAB_OPT_DEV */
+#endif /* MOUNT_TABLE_ON_FILE */
+
+ return 0;
+}
+
+
+/*
+ * Fill in the many possible fields and flags of struct nfs_args.
+ *
+ * nap: pre-allocted structure to fill in.
+ * mntp: mount entry structure (includes options)
+ * genflags: generic mount flags already determined
+ * nfsncp: (TLI only) netconfig entry for this NFS mount
+ * ip_addr: IP address of file server
+ * nfs_version: 2, 3, (4 in the future), or 0 if unknown
+ * nfs_proto: "udp", "tcp", or NULL.
+ * fhp: file handle structure pointer
+ * host_name: name of remote NFS host
+ * fs_name: remote file system name to mount
+ */
+void
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct netconfig *nfsncp, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name)
+#else /* not HAVE_TRANSPORT_TYPE_TLI */
+compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name)
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+{
+ int acval = 0;
+#ifdef HAVE_FS_NFS3
+ static am_nfs_fh3 fh3; /* static, b/c gcc on aix corrupts stack */
+#endif /* HAVE_FS_NFS3 */
+
+ /* initialize just in case */
+ memset((voidp) nap, 0, sizeof(nfs_args_t));
+
+ /************************************************************************/
+ /*** FILEHANDLE DATA AND LENGTH ***/
+ /************************************************************************/
+#ifdef HAVE_FS_NFS3
+ if (nfs_version == NFS_VERSION3) {
+ memset((voidp) &fh3, 0, sizeof(am_nfs_fh3));
+ fh3.fh3_length = fhp->v3.mountres3_u.mountinfo.fhandle.fhandle3_len;
+ memmove(fh3.fh3_u.data,
+ fhp->v3.mountres3_u.mountinfo.fhandle.fhandle3_val,
+ fh3.fh3_length);
+
+# if defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN)
+ /*
+ * Some systems (Irix/bsdi3) have a separate field in nfs_args for
+ * the length of the file handle for NFS V3. They insist that
+ * the file handle set in nfs_args be plain bytes, and not
+ * include the length field.
+ */
+ NFS_FH_DREF(nap->NFS_FH_FIELD, &(fh3.fh3_u.data));
+# else /* not defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN) */
+ NFS_FH_DREF(nap->NFS_FH_FIELD, &fh3);
+# endif /* not defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN) */
+# ifdef MNT2_NFS_OPT_NFSV3
+ nap->flags |= MNT2_NFS_OPT_NFSV3;
+# endif /* MNT2_NFS_OPT_NFSV3 */
+ } else
+#endif /* HAVE_FS_NFS3 */
+ NFS_FH_DREF(nap->NFS_FH_FIELD, &(fhp->v2.fhs_fh));
+
+#ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
+# ifdef HAVE_FS_NFS3
+ if (nfs_version == NFS_VERSION3)
+ nap->fhsize = fh3.fh3_length;
+ else
+# endif /* HAVE_FS_NFS3 */
+ nap->fhsize = FHSIZE;
+#endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
+
+ /* this is the version of the nfs_args structure, not of NFS! */
+#ifdef HAVE_FIELD_NFS_ARGS_T_FH_LEN
+# ifdef HAVE_FS_NFS3
+ if (nfs_version == NFS_VERSION3)
+ nap->fh_len = fh3.fh3_length;
+ else
+# endif /* HAVE_FS_NFS3 */
+ nap->fh_len = FHSIZE;
+#endif /* HAVE_FIELD_NFS_ARGS_T_FH_LEN */
+
+ /************************************************************************/
+ /*** HOST NAME ***/
+ /************************************************************************/
+ NFS_HN_DREF(nap->hostname, host_name);
+#ifdef MNT2_NFS_OPT_HOSTNAME
+ nap->flags |= MNT2_NFS_OPT_HOSTNAME;
+#endif /* MNT2_NFS_OPT_HOSTNAME */
+
+ /************************************************************************/
+ /*** ATTRIBUTE CACHES ***/
+ /************************************************************************/
+ /*
+ * acval is set to 0 at the top of the function. If actimeo mount option
+ * exists and defined in mntopts, then it acval is set to it.
+ * If the value is non-zero, then we set all attribute cache fields to it.
+ * If acval is zero, it means it was never defined in mntopts or the
+ * actimeo mount option does not exist, in which case we check for
+ * individual mount options per attribute cache.
+ * Regardless of the value of acval, mount flags are set based directly
+ * on the values of the attribute caches.
+ */
+#ifdef MNTTAB_OPT_ACTIMEO
+ acval = hasmntval(mntp, MNTTAB_OPT_ACTIMEO); /* attr cache timeout (sec) */
+#endif /* MNTTAB_OPT_ACTIMEO */
+
+ if (acval) {
+#ifdef HAVE_FIELD_NFS_ARGS_T_ACREGMIN
+ nap->acregmin = acval; /* min ac timeout for reg files (sec) */
+ nap->acregmax = acval; /* max ac timeout for reg files (sec) */
+#endif /* HAVE_FIELD_NFS_ARGS_T_ACREGMIN */
+#ifdef HAVE_FIELD_NFS_ARGS_T_ACDIRMIN
+ nap->acdirmin = acval; /* min ac timeout for dirs (sec) */
+ nap->acdirmax = acval; /* max ac timeout for dirs (sec) */
+#endif /* HAVE_FIELD_NFS_ARGS_T_ACDIRMIN */
+ } else {
+#ifdef MNTTAB_OPT_ACREGMIN
+ nap->acregmin = hasmntval(mntp, MNTTAB_OPT_ACREGMIN);
+#endif /* MNTTAB_OPT_ACREGMIN */
+#ifdef MNTTAB_OPT_ACREGMAX
+ nap->acregmax = hasmntval(mntp, MNTTAB_OPT_ACREGMAX);
+#endif /* MNTTAB_OPT_ACREGMAX */
+#ifdef MNTTAB_OPT_ACDIRMIN
+ nap->acdirmin = hasmntval(mntp, MNTTAB_OPT_ACDIRMIN);
+#endif /* MNTTAB_OPT_ACDIRMIN */
+#ifdef MNTTAB_OPT_ACDIRMAX
+ nap->acdirmax = hasmntval(mntp, MNTTAB_OPT_ACDIRMAX);
+#endif /* MNTTAB_OPT_ACDIRMAX */
+ } /* end of "if (acval)" statement */
+
+#ifdef MNT2_NFS_OPT_ACREGMIN
+ if (nap->acregmin)
+ nap->flags |= MNT2_NFS_OPT_ACREGMIN;
+#endif /* MNT2_NFS_OPT_ACREGMIN */
+#ifdef MNT2_NFS_OPT_ACREGMAX
+ if (nap->acregmax)
+ nap->flags |= MNT2_NFS_OPT_ACREGMAX;
+#endif /* MNT2_NFS_OPT_ACREGMAX */
+#ifdef MNT2_NFS_OPT_ACDIRMIN
+ if (nap->acdirmin)
+ nap->flags |= MNT2_NFS_OPT_ACDIRMIN;
+#endif /* MNT2_NFS_OPT_ACDIRMIN */
+#ifdef MNT2_NFS_OPT_ACDIRMAX
+ if (nap->acdirmax)
+ nap->flags |= MNT2_NFS_OPT_ACDIRMAX;
+#endif /* MNT2_NFS_OPT_ACDIRMAX */
+
+#ifdef MNTTAB_OPT_NOAC /* don't cache attributes */
+ if (hasmntopt(mntp, MNTTAB_OPT_NOAC) != NULL)
+ nap->flags |= MNT2_NFS_OPT_NOAC;
+#endif /* MNTTAB_OPT_NOAC */
+
+ /************************************************************************/
+ /*** IP ADDRESS OF REMOTE HOST ***/
+ /************************************************************************/
+ if (ip_addr) {
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+ nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
+#endif /* HAVE_TRANSPORT_TYPE_TLI */
+ NFS_SA_DREF(nap, ip_addr);
+ }
+
+ /************************************************************************/
+ /*** NFS PROTOCOL (UDP, TCP) AND VERSION ***/
+ /************************************************************************/
+#ifdef MNT2_NFS_OPT_TCP
+ if (nfs_proto && STREQ(nfs_proto, "tcp"))
+ nap->flags |= MNT2_NFS_OPT_TCP;
+#endif /* MNT2_NFS_OPT_TCP */
+
+#ifdef HAVE_FIELD_NFS_ARGS_T_SOTYPE
+ /* bsdi3 uses this */
+ if (nfs_proto) {
+ if (STREQ(nfs_proto, "tcp"))
+ nap->sotype = SOCK_STREAM;
+ else if (STREQ(nfs_proto, "udp"))
+ nap->sotype = SOCK_DGRAM;
+ }
+#endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
+
+#ifdef HAVE_FIELD_NFS_ARGS_T_PROTO
+ nap->proto = 0; /* bsdi3 sets this field to zero */
+# ifdef IPPROTO_TCP
+ if (nfs_proto) {
+ if (STREQ(nfs_proto, "tcp")) /* AIX 4.2.x needs this */
+ nap->proto = IPPROTO_TCP;
+ else if (STREQ(nfs_proto, "udp"))
+ nap->proto = IPPROTO_UDP;
+ }
+# endif /* IPPROTO_TCP */
+#endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
+
+#ifdef HAVE_FIELD_NFS_ARGS_T_VERSION
+# ifdef NFS_ARGSVERSION
+ nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */
+# endif /* NFS_ARGSVERSION */
+# ifdef DG_MOUNT_NFS_VERSION
+ nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */
+# endif /* DG_MOUNT_NFS_VERSION */
+#endif /* HAVE_FIELD_NFS_ARGS_VERSION */
+
+ /************************************************************************/
+ /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/
+ /************************************************************************/
+#ifdef MNT2_NFS_OPT_NOCONN
+ /* check if user specified to use unconnected or connected sockets */
+ if (hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
+ nap->flags |= MNT2_NFS_OPT_NOCONN;
+ else if (hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL)
+ nap->flags &= ~MNT2_NFS_OPT_NOCONN;
+ else {
+ /*
+ * Some OSs want you to set noconn always. Some want you to always turn
+ * it off. Others want you to turn it on/off only if NFS V.3 is used.
+ * And all of that changes from revision to another. This is
+ * particularly true of OpenBSD, NetBSD, and FreeBSD. So, rather than
+ * attempt to auto-detect this, I'm forced to "fix" it in the individual
+ * conf/nfs_prot/nfs_prot_*.h files.
+ */
+# ifdef USE_UNCONNECTED_NFS_SOCKETS
+ nap->flags |= MNT2_NFS_OPT_NOCONN;
+ plog(XLOG_WARNING, "noconn option exists, and was turned ON! (May cause NFS hangs on some systems...)");
+# endif /* USE_UNCONNECTED_NFS_SOCKETS */
+# ifdef USE_CONNECTED_NFS_SOCKETS
+ nap->flags &= ~MNT2_NFS_OPT_NOCONN;
+ plog(XLOG_WARNING, "noconn option exists, and was turned OFF! (May cause NFS hangs on some systems...)");
+# endif /* USE_CONNECTED_NFS_SOCKETS */
+ }
+#endif /* MNT2_NFS_OPT_NOCONN */
+
+#ifdef MNT2_NFS_OPT_RESVPORT
+# ifdef MNTTAB_OPT_RESVPORT
+ if (hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL)
+ nap->flags |= MNT2_NFS_OPT_RESVPORT;
+# else /* not MNTTAB_OPT_RESVPORT */
+ nap->flags |= MNT2_NFS_OPT_RESVPORT;
+# endif /* not MNTTAB_OPT_RESVPORT */
+#endif /* MNT2_NFS_OPT_RESVPORT */
+
+ /************************************************************************/
+ /*** OTHER FLAGS AND OPTIONS ***/
+ /************************************************************************/
+
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+ /* set up syncaddr field */
+ nap->syncaddr = (struct netbuf *) NULL;
+
+ /* set up knconf field */
+ if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
+ plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
+ going_down(1);
+ }
+ /* update the flags field for knconf */
+ nap->flags |= MNT2_NFS_OPT_KNCONF;
+#endif /* HAVE_TRANSPORT_TYPE_TLI */
+
+#ifdef MNT2_NFS_OPT_FSNAME
+ nap->fsname = fs_name;
+ nap->flags |= MNT2_NFS_OPT_FSNAME;
+#endif /* MNT2_NFS_OPT_FSNAME */
+
+ nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE);
+#ifdef MNT2_NFS_OPT_RSIZE
+ if (nap->rsize)
+ nap->flags |= MNT2_NFS_OPT_RSIZE;
+#endif /* MNT2_NFS_OPT_RSIZE */
+
+ nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE);
+#ifdef MNT2_NFS_OPT_WSIZE
+ if (nap->wsize)
+ nap->flags |= MNT2_NFS_OPT_WSIZE;
+#endif /* MNT2_NFS_OPT_WSIZE */
+
+ nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO);
+#ifdef MNT2_NFS_OPT_TIMEO
+ if (nap->timeo)
+ nap->flags |= MNT2_NFS_OPT_TIMEO;
+#endif /* MNT2_NFS_OPT_TIMEO */
+
+ nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS);
+#ifdef MNT2_NFS_OPT_RETRANS
+ if (nap->retrans)
+ nap->flags |= MNT2_NFS_OPT_RETRANS;
+#endif /* MNT2_NFS_OPT_RETRANS */
+
+#ifdef MNT2_NFS_OPT_BIODS
+ if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
+ nap->flags |= MNT2_NFS_OPT_BIODS;
+#endif /* MNT2_NFS_OPT_BIODS */
+
+ if (hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
+ nap->flags |= MNT2_NFS_OPT_SOFT;
+
+#ifdef MNT2_NFS_OPT_SPONGY
+ if (hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
+ nap->flags |= MNT2_NFS_OPT_SPONGY;
+ if (nap->flags & MNT2_NFS_OPT_SOFT) {
+ plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
+ nap->flags &= ~MNT2_NFS_OPT_SOFT;
+ }
+ }
+#endif /* MNT2_NFS_OPT_SPONGY */
+
+#if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY)
+ /* Ultrix has separate generic and NFS ro flags */
+ if (genflags & MNT2_GEN_OPT_RONLY)
+ nap->flags |= MNT2_NFS_OPT_RONLY;
+#endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */
+
+#ifdef MNTTAB_OPT_INTR
+ if (hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL)
+ /*
+ * Either turn on the "allow interrupts" option, or
+ * turn off the "disallow interrupts" option"
+ */
+# ifdef MNT2_NFS_OPT_INT
+ nap->flags |= MNT2_NFS_OPT_INT;
+# endif /* MNT2_NFS_OPT_INT */
+# ifdef MNT2_NFS_OPT_NOINT
+ nap->flags &= ~MNT2_NFS_OPT_NOINT;
+# endif /* MNT2_NFS_OPT_NOINT */
+#endif /* MNTTAB_OPT_INTR */
+
+#ifdef MNTTAB_OPT_NODEVS
+ if (hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
+ nap->flags |= MNT2_NFS_OPT_NODEVS;
+#endif /* MNTTAB_OPT_NODEVS */
+
+#ifdef MNTTAB_OPT_COMPRESS
+ if (hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL)
+ nap->flags |= MNT2_NFS_OPT_COMPRESS;
+#endif /* MNTTAB_OPT_COMPRESS */
+
+#ifdef MNTTAB_OPT_PRIVATE /* mount private, single-client tree */
+ if (hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL)
+ nap->flags |= MNT2_NFS_OPT_PRIVATE;
+#endif /* MNTTAB_OPT_PRIVATE */
+
+#ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */
+ if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
+ nap->flags |= MNT2_NFS_OPT_SYMTTL;
+#endif /* MNTTAB_OPT_SYMTTL */
+
+#ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */
+ if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
+ nap->flags |= MNT2_NFS_OPT_PGTHRESH;
+#endif /* MNT2_NFS_OPT_PGTHRESH */
+
+#if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
+ if (hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL)
+ nap->flags |= MNT2_NFS_OPT_NOCTO;
+#endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */
+
+#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
+ if (hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
+ nap->flags |= MNT2_NFS_OPT_POSIX;
+ nap->pathconf = NULL;
+ }
+#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
+
+#if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
+ nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
+ if (nap->maxgrouplist != NULL)
+ nap->flags |= MNT2_NFS_OPT_MAXGRPS;
+#endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
+
+#ifdef HAVE_FIELD_NFS_ARGS_T_OPTSTR
+ nap->optstr = mntp->mnt_opts;
+#endif /* HAVE_FIELD_NFS_ARGS_T_OPTSTR */
+
+ /************************************************************************/
+ /*** FINAL ACTIONS ***/
+ /************************************************************************/
+
+#ifdef HAVE_FIELD_NFS_ARGS_T_GFS_FLAGS
+ /* Ultrix stores generic flags in nfs_args.gfs_flags. */
+ nap->gfs_flags = genflags;
+#endif /* HAVE_FIELD_NFS_ARGS_T_FLAGS */
+
+ return; /* end of compute_nfs_args() function */
+}
+
+
+/*
+ * Fill in special values for flags and fields of nfs_args, for an
+ * automounter NFS mount.
+ */
+void
+compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
+{
+#ifdef MNT2_NFS_OPT_SYMTTL
+ /*
+ * Don't let the kernel cache symbolic links we generate, or else lookups
+ * will bypass amd and fail to remount stuff as needed.
+ */
+ plog(XLOG_INFO, "turning on NFS option symttl and setting value to %d", 0);
+ nap->flags |= MNT2_NFS_OPT_SYMTTL;
+ nap->symttl = 0;
+#endif /* MNT2_NFS_OPT_SYMTTL */
+
+ /*
+ * This completes the flags for the HIDE_MOUNT_TYPE code above.
+ * Some systems don't have a mount type, but a mount flag.
+ */
+#ifdef MNT2_NFS_OPT_AUTO
+ nap->flags |= MNT2_NFS_OPT_AUTO;
+#endif /* MNT2_NFS_OPT_AUTO */
+#ifdef MNT2_NFS_OPT_IGNORE
+ nap->flags |= MNT2_NFS_OPT_IGNORE;
+#endif /* MNT2_NFS_OPT_IGNORE */
+
+#ifdef MNT2_NFS_OPT_DUMBTIMR
+ /*
+ * Don't let the kernel start computing throughput of Amd The numbers will
+ * be meaningless because of the way Amd does mount retries.
+ */
+ plog(XLOG_INFO, "%s: disabling nfs congestion window", mntp->mnt_dir);
+ nap->flags |= MNT2_NFS_OPT_DUMBTIMR;
+#endif /* MNT2_NFS_OPT_DUMBTIMR */
+
+#ifdef MNT2_NFS_OPT_NOAC
+ /*
+ * Don't cache attributes - they are changing under the kernel's feet.
+ * For example, IRIX5.2 will dispense with nfs lookup calls and hand stale
+ * filehandles to getattr unless we disable attribute caching on the
+ * automount points.
+ */
+ nap->flags |= MNT2_NFS_OPT_NOAC;
+#else /* not MNT2_NFS_OPT_NOAC */
+ /*
+ * Setting these to 0 results in an error on some systems, which is why
+ * it's better to use "noac" if possible.
+ */
+# if defined(MNT2_NFS_OPT_ACREGMIN) && defined(MNT2_NFS_OPT_ACREGMAX)
+ nap->acregmin = nap->acregmax = 0; /* XXX: was 1, but why? */
+ nap->flags |= MNT2_NFS_OPT_ACREGMIN | MNT2_NFS_OPT_ACREGMAX;
+# endif /* defined(MNT2_NFS_OPT_ACREGMIN) && defined(MNT2_NFS_OPT_ACREGMAX) */
+# if defined(MNT2_NFS_OPT_ACDIRMIN) && defined(MNT2_NFS_OPT_ACDIRMAX)
+ nap->acdirmin = nap->acdirmax = 0; /* XXX: was 1, but why? */
+ nap->flags |= MNT2_NFS_OPT_ACDIRMIN | MNT2_NFS_OPT_ACDIRMAX;
+# endif /* defined(MNT2_NFS_OPT_ACDIRMIN) && defined(MNT2_NFS_OPT_ACDIRMAX) */
+#endif /* not MNT2_NFS_OPT_NOAC */
+}
+
+
+#ifdef DEBUG
+/* get string version (in hex) of identifier */
+static char *
+get_hex_string(u_int len, const char *fhdata)
+{
+ int i;
+ static char buf[128]; /* better not go over it! */
+ char str[16];
+ short int arr[64];
+
+ if (!fhdata)
+ return NULL;
+ buf[0] = '\0';
+ memset(&arr[0], 0, (64 * sizeof(short int)));
+ memcpy(&arr[0], &fhdata[0], len);
+ for (i=0; i<len/sizeof(short int); i++) {
+ sprintf(str, "%04x", ntohs(arr[i]));
+ strcat(buf, str);
+ }
+ return buf;
+}
+
+
+/*
+ * print a subset of fields from "struct nfs_args" that are otherwise
+ * not being provided anywhere else.
+ */
+void
+print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
+{
+ int fhlen = 32; /* default: NFS V.2 file handle length is 32 */
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+ struct netbuf *nbp;
+ struct knetconfig *kncp;
+#else /* not HAVE_TRANSPORT_TYPE_TLI */
+ struct sockaddr_in *sap;
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+
+ if (!nap) {
+ plog(XLOG_DEBUG, "NULL nfs_args!");
+ return;
+ }
+
+ /* override default file handle size */
+#ifdef FHSIZE
+ fhlen = FHSIZE;
+#endif /* FHSIZE */
+#ifdef NFS_FHSIZE
+ fhlen = NFS_FHSIZE;
+#endif /* NFS_FHSIZE */
+
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+ nbp = nap->addr;
+ plog(XLOG_DEBUG, "NA->addr {netbuf} (maxlen=%d, len=%d) = \"%s\"",
+ nbp->maxlen, nbp->len,
+ get_hex_string(nbp->len, nbp->buf));
+ nbp = nap->syncaddr;
+ plog(XLOG_DEBUG, "NA->syncaddr {netbuf} 0x%x", (int) nbp);
+ kncp = nap->knconf;
+ plog(XLOG_DEBUG, "NA->knconf->semantics %lu", kncp->knc_semantics);
+ plog(XLOG_DEBUG, "NA->knconf->protofmly \"%s\"", kncp->knc_protofmly);
+ plog(XLOG_DEBUG, "NA->knconf->proto \"%s\"", kncp->knc_proto);
+ plog(XLOG_DEBUG, "NA->knconf->rdev %lu", kncp->knc_rdev);
+ /* don't print knconf->unused field */
+#else /* not HAVE_TRANSPORT_TYPE_TLI */
+ sap = (struct sockaddr_in *) &nap->addr;
+ plog(XLOG_DEBUG, "NA->addr {sockaddr_in} (len=%d) = \"%s\"",
+ sizeof(struct sockaddr_in),
+ get_hex_string(sizeof(struct sockaddr_in), (const char *)sap));
+#ifdef HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN_off
+ plog(XLOG_DEBUG, "NA->addr.sin_len = \"%d\"", sap->sin_len);
+#endif /* HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN */
+ plog(XLOG_DEBUG, "NA->addr.sin_family = \"%d\"", sap->sin_family);
+ plog(XLOG_DEBUG, "NA->addr.sin_port = \"%d\"", sap->sin_port);
+ plog(XLOG_DEBUG, "NA->addr.sin_addr = \"%s\"",
+ get_hex_string(sizeof(struct in_addr), (const char *) &sap->sin_addr));
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+
+ plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname ? nap->hostname : "null");
+#ifdef MNT2_NFS_OPT_FSNAME
+ plog(XLOG_DEBUG, "NA->fsname = \"%s\"", nap->fsname ? nap->fsname : "null");
+#endif /* MNT2_NFS_OPT_FSNAME */
+
+#ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
+ plog(XLOG_DEBUG, "NA->fhsize = %d", nap->fhsize);
+ fhlen = nap->fhsize;
+#endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
+#ifdef HAVE_FIELD_NFS_ARGS_T_FH_LEN
+ plog(XLOG_DEBUG, "NA->fh_len = %d", nap->fh_len);
+ fhlen = nap->fh_len;
+#endif /* HAVE_FIELD_NFS_ARGS_T_FH_LEN */
+
+ /*
+ * XXX: need to figure out how to correctly print file handles,
+ * since some times they are pointers, and sometimes the real structure
+ * is stored in nfs_args. Even if it is a pointer, it can be the actual
+ * char[] array, or a structure containing multiple fields.
+ */
+ plog(XLOG_DEBUG, "NA->filehandle = \"%s\"",
+ get_hex_string(fhlen, (const char *) &nap->NFS_FH_FIELD));
+
+#ifdef HAVE_FIELD_NFS_ARGS_T_SOTYPE
+ plog(XLOG_DEBUG, "NA->sotype = %d", nap->sotype);
+#endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
+#ifdef HAVE_FIELD_NFS_ARGS_T_PROTO
+ plog(XLOG_DEBUG, "NA->proto = %d", nap->proto);
+#endif /* HAVE_FIELD_NFS_ARGS_T_PROTO */
+#ifdef HAVE_FIELD_NFS_ARGS_T_VERSION
+ plog(XLOG_DEBUG, "NA->version = %d", nap->version);
+#endif /* HAVE_FIELD_NFS_ARGS_T_VERSION */
+
+ plog(XLOG_DEBUG, "NA->flags = 0x%x", nap->flags);
+
+ plog(XLOG_DEBUG, "NA->rsize = %d", nap->rsize);
+ plog(XLOG_DEBUG, "NA->wsize = %d", nap->wsize);
+ plog(XLOG_DEBUG, "NA->timeo = %d", nap->timeo);
+ plog(XLOG_DEBUG, "NA->retrans = %d", nap->retrans);
+
+#ifdef HAVE_FIELD_NFS_ARGS_T_ACREGMIN
+ plog(XLOG_DEBUG, "NA->acregmin = %d", nap->acregmin);
+ plog(XLOG_DEBUG, "NA->acregmax = %d", nap->acregmax);
+ plog(XLOG_DEBUG, "NA->acdirmin = %d", nap->acdirmin);
+ plog(XLOG_DEBUG, "NA->acdirmax = %d", nap->acdirmax);
+#endif /* HAVE_FIELD_NFS_ARGS_T_ACREGMIN */
+#ifdef MNTTAB_OPT_SYMTTL
+ plog(XLOG_DEBUG, "NA->symttl = %d", nap->symttl);
+#endif /* MNTTAB_OPT_SYMTTL */
+#ifdef MNTTAB_OPT_PG_THRESH
+ plog(XLOG_DEBUG, "NA->pg_thresh = %d", nap->pg_thresh);
+#endif /* MNTTAB_OPT_PG_THRESH */
+
+#ifdef MNT2_NFS_OPT_BIODS
+ plog(XLOG_DEBUG, "NA->biods = %d", nap->biods);
+#endif /* MNT2_NFS_OPT_BIODS */
+
+}
+#endif /* DEBUG */
diff --git a/contrib/amd/libamu/mtab.c b/contrib/amd/libamu/mtab.c
new file mode 100644
index 0000000..20cae62
--- /dev/null
+++ b/contrib/amd/libamu/mtab.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: mtab.c,v 5.2.2.1 1992/02/09 15:08:45 jsp beta $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+
+/*
+ * Firewall /etc/mtab entries
+ */
+void
+mnt_free(mntent_t *mp)
+{
+ XFREE(mp->mnt_fsname);
+ XFREE(mp->mnt_dir);
+ XFREE(mp->mnt_type);
+ XFREE(mp->mnt_opts);
+
+#ifdef HAVE_FIELD_MNTENT_T_MNT_TIME
+# ifdef HAVE_FIELD_MNTENT_T_MNT_TIME_STRING
+ XFREE(mp->mnt_time);
+# endif /* HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
+#endif /* HAVE_FIELD_MNTENT_T_MNT_TIME */
+
+ XFREE(mp);
+}
+
+
+/*
+ * Discard memory allocated for mount list
+ */
+void
+discard_mntlist(mntlist *mp)
+{
+ mntlist *mp2;
+
+ while ((mp2 = mp)) {
+ mp = mp->mnext;
+ if (mp2->mnt)
+ mnt_free(mp2->mnt);
+ XFREE(mp2);
+ }
+}
+
+
+/*
+ * Throw away a mount list
+ */
+void
+free_mntlist(mntlist *mp)
+{
+ discard_mntlist(mp);
+#ifdef MOUNT_TABLE_ON_FILE
+ unlock_mntlist();
+#endif /* MOUNT_TABLE_ON_FILE */
+}
+
+
+/*
+ * Utility routine which determines the value of a
+ * numeric option in the mount options (such as port=%d).
+ * Returns 0 if the option is not specified.
+ */
+int
+hasmntval(mntent_t *mnt, char *opt)
+{
+ char *str = hasmntopt(mnt, opt);
+
+ if (str) {
+ char *eq = strchr(str, '=');
+ if (eq)
+ return atoi(eq + 1);
+ else
+ plog(XLOG_USER, "bad numeric option \"%s\" in \"%s\"", opt, str);
+ }
+ return 0;
+}
diff --git a/contrib/amd/libamu/nfs_prot_xdr.c b/contrib/amd/libamu/nfs_prot_xdr.c
new file mode 100644
index 0000000..2098b5d
--- /dev/null
+++ b/contrib/amd/libamu/nfs_prot_xdr.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: nfs_prot_xdr.c,v 5.2.2.1 1992/02/09 15:09:32 jsp beta $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+
+bool_t
+xdr_amq_string(XDR *xdrs, amq_string *objp)
+{
+ if (!xdr_string(xdrs, objp, AMQ_STRLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
diff --git a/contrib/amd/libamu/util.c b/contrib/amd/libamu/util.c
new file mode 100644
index 0000000..1198347
--- /dev/null
+++ b/contrib/amd/libamu/util.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: util.c,v 5.2.2.2 1992/03/07 17:52:06 jsp Exp $
+ *
+ */
+
+/*
+ * General Utilitiles.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+
+char *
+strnsave(const char *str, int len)
+{
+ char *sp = (char *) xmalloc(len + 1);
+ memmove(sp, str, len);
+ sp[len] = 0;
+
+ return sp;
+}
+
+
+/*
+ * Concatenate three strings and store in buffer pointed to
+ * by p, making p large enough to hold the strings
+ */
+char *
+str3cat(char *p, char *s1, char *s2, char *s3)
+{
+ int l1 = strlen(s1);
+ int l2 = strlen(s2);
+ int l3 = strlen(s3);
+
+ p = (char *) xrealloc(p, l1 + l2 + l3 + 1);
+ memmove(p, s1, l1);
+ memmove(p + l1, s2, l2);
+ memmove(p + l1 + l2, s3, l3 + 1);
+ return p;
+}
+
+
+/*
+ * Make all the directories in the path.
+ */
+int
+mkdirs(char *path, int mode)
+{
+ /*
+ * take a copy in case path is in readonly store
+ */
+ char *p2 = strdup(path);
+ char *sp = p2;
+ struct stat stb;
+ int error_so_far = 0;
+
+ /*
+ * Skip through the string make the directories.
+ * Mostly ignore errors - the result is tested at the end.
+ *
+ * This assumes we are root so that we can do mkdir in a
+ * mode 555 directory...
+ */
+ while ((sp = strchr(sp + 1, '/'))) {
+ *sp = '\0';
+ if (mkdir(p2, mode) < 0) {
+ error_so_far = errno;
+ } else {
+#ifdef DEBUG
+ dlog("mkdir(%s)", p2);
+#endif /* DEBUG */
+ }
+ *sp = '/';
+ }
+
+ if (mkdir(p2, mode) < 0) {
+ error_so_far = errno;
+ } else {
+#ifdef DEBUG
+ dlog("mkdir(%s)", p2);
+#endif /* DEBUG */
+ }
+
+ XFREE(p2);
+
+ return stat(path, &stb) == 0 &&
+ (stb.st_mode & S_IFMT) == S_IFDIR ? 0 : error_so_far;
+}
+
+
+/*
+ * Remove as many directories in the path as possible.
+ * Give up if the directory doesn't appear to have
+ * been created by Amd (not mode dr-x) or an rmdir
+ * fails for any reason.
+ */
+void
+rmdirs(char *dir)
+{
+ char *xdp = strdup(dir);
+ char *dp;
+
+ do {
+ struct stat stb;
+ /*
+ * Try to find out whether this was
+ * created by amd. Do this by checking
+ * for owner write permission.
+ */
+ if (stat(xdp, &stb) == 0 && (stb.st_mode & 0200) == 0) {
+ if (rmdir(xdp) < 0) {
+ if (errno != ENOTEMPTY &&
+ errno != EBUSY &&
+ errno != EEXIST &&
+ errno != EINVAL)
+ plog(XLOG_ERROR, "rmdir(%s): %m", xdp);
+ break;
+ } else {
+#ifdef DEBUG
+ dlog("rmdir(%s)", xdp);
+#endif /* DEBUG */
+ }
+ } else {
+ break;
+ }
+
+ dp = strrchr(xdp, '/');
+ if (dp)
+ *dp = '\0';
+ } while (dp && dp > xdp);
+
+ XFREE(xdp);
+}
diff --git a/contrib/amd/libamu/wire.c b/contrib/amd/libamu/wire.c
new file mode 100644
index 0000000..f610f92
--- /dev/null
+++ b/contrib/amd/libamu/wire.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: wire.c,v 5.2.2.2 1992/06/07 18:06:46 jsp Exp jsp $
+ *
+ */
+
+/*
+ * This function returns the subnet (address&netmask) for the primary network
+ * interface. If the resulting address has an entry in the hosts file, the
+ * corresponding name is retuned, otherwise the address is returned in
+ * standard internet format.
+ * As a side-effect, a list of local IP/net address is recorded for use
+ * by the islocalnet() function.
+ *
+ * Derived from original by Paul Anderson (23/4/90)
+ * Updates from Dirk Grunwald (11/11/91)
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+
+/*
+ * List of locally connected networks
+ */
+typedef struct addrlist addrlist;
+struct addrlist {
+ addrlist *ip_next;
+ u_long ip_addr; /* address of network */
+ u_long ip_mask;
+ char *ip_net_num; /* number of network */
+ char *ip_net_name; /* name of network */
+};
+static addrlist *localnets = NULL;
+
+#if defined(IFF_LOCAL_LOOPBACK) && !defined(IFF_LOOPBACK)
+# define IFF_LOOPBACK IFF_LOCAL_LOOPBACK
+#endif /* defined(IFF_LOCAL_LOOPBACK) && !defined(IFF_LOOPBACK) */
+
+#if defined(HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN)
+# define SIZE(ifr) (MAX((ifr)->ifr_addr.sa_len, sizeof((ifr)->ifr_addr)) + sizeof(ifr->ifr_name))
+#else /* not defined(HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN) */
+# define SIZE(ifr) sizeof(struct ifreq)
+#endif /* not defined(HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN) */
+
+#define C(x) ((x) & 0xff)
+#define GFBUFLEN 1024
+#define clist (ifc.ifc_ifcu.ifcu_req)
+#define count (ifc.ifc_len/sizeof(struct ifreq))
+
+
+/* return malloc'ed buffer. caller must free it */
+char *
+print_wires(void)
+{
+ addrlist *al;
+ char s[256];
+ int i;
+ char *buf;
+ int bufcount = 0;
+ int buf_size = 1024;
+
+ buf = malloc(1024);
+ if (!buf)
+ return NULL;
+
+ if (!localnets) {
+ sprintf(buf, "No networks.\n");
+ return buf;
+ }
+ /* check if there's more than one network */
+ if (!localnets->ip_next) {
+ sprintf(buf,
+ "Network: wire=\"%s\" (netnumber=%s).\n",
+ localnets->ip_net_name, localnets->ip_net_num);
+ return buf;
+ }
+ buf[0] = '\0'; /* null out buffer before appending */
+ for (i = 1, al = localnets; al; al = al->ip_next, i++) {
+ sprintf(s, "Network %d: wire=\"%s\" (netnumber=%s).\n",
+ i, al->ip_net_name, al->ip_net_num);
+ bufcount += strlen(s);
+ if (bufcount > buf_size) {
+ buf_size *= 2;
+ buf = xrealloc(buf, buf_size);
+ }
+ strcat(buf, s);
+ }
+ return buf;
+}
+
+
+void
+getwire(char **name1, char **number1)
+{
+ struct hostent *hp;
+ struct netent *np;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ caddr_t cp, cplim;
+ u_long address, netmask, subnet;
+ char buf[GFBUFLEN], *s;
+ int fd = -1;
+ u_long net;
+ u_long mask;
+ u_long subnetshift;
+ char netNumberBuf[64];
+ addrlist *al = NULL, *tail = NULL;
+
+#ifndef SIOCGIFFLAGS
+ /* if cannot get interface flags, return nothing */
+ plog(XLOG_ERROR, "getwire unable to get interface flags");
+ localnets = NULL;
+ return;
+#endif /* not SIOCGIFFLAGS */
+
+ /*
+ * Get suitable socket
+ */
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ goto out;
+
+ /*
+ * Fill in ifconf details
+ */
+ memset(&buf[0], 0, GFBUFLEN);
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+
+ /*
+ * Get network interface configurations
+ */
+ if (ioctl(fd, SIOCGIFCONF, (caddr_t) & ifc) < 0)
+ goto out;
+
+ /*
+ * Upper bound on array
+ */
+ cplim = buf + ifc.ifc_len;
+
+ /*
+ * This is some magic to cope with both "traditional" and the
+ * new 4.4BSD-style struct sockaddrs. The new structure has
+ * variable length and a size field to support longer addresses.
+ * AF_LINK is a new definition for 4.4BSD.
+ */
+
+ /*
+ * Scan the list looking for a suitable interface
+ */
+ for (cp = buf; cp < cplim; cp += SIZE(ifr)) {
+ ifr = (struct ifreq *) cp;
+
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+ else
+ address = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
+
+ /*
+ * Get interface flags
+ */
+ if (ioctl(fd, SIOCGIFFLAGS, (caddr_t) ifr) < 0)
+ continue;
+
+ /*
+ * If the interface is a loopback, or its not running
+ * then ignore it.
+ */
+#ifdef IFF_LOOPBACK
+ if ((ifr->ifr_flags & IFF_LOOPBACK) != 0)
+ continue;
+#endif /* IFF_LOOPBACK */
+ /*
+ * Fix for 0.0.0.0 loopback on SunOS 3.X which defines IFF_ROUTE
+ * instead of IFF_LOOPBACK.
+ */
+#ifdef IFF_ROUTE
+ if (ifr->ifr_flags == (IFF_UP|IFF_RUNNING))
+ continue;
+#endif /* IFF_ROUTE */
+
+ /* if the interface is not UP or not RUNNING, skip it */
+ if ((ifr->ifr_flags & IFF_RUNNING) == 0 ||
+ (ifr->ifr_flags & IFF_UP) == 0)
+ continue;
+
+ /*
+ * Get the netmask of this interface
+ */
+ if (ioctl(fd, SIOCGIFNETMASK, (caddr_t) ifr) < 0)
+ continue;
+
+ netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
+
+ /*
+ * Add interface to local network singly linked list
+ */
+ al = ALLOC(struct addrlist);
+ al->ip_addr = address;
+ al->ip_mask = netmask;
+ al->ip_net_name = NO_SUBNET; /* fill in a bit later */
+ al->ip_net_num = "0.0.0.0"; /* fill in a bit later */
+ al->ip_next = NULL;
+ /* append to the end of the list */
+ if (!localnets) {
+ localnets = tail = al;
+ tail->ip_next = NULL;
+ } else {
+ tail->ip_next = al;
+ tail = al;
+ }
+
+ /*
+ * Figure out the subnet's network address
+ */
+ subnet = address & netmask;
+
+#ifdef IN_CLASSA
+ subnet = htonl(subnet);
+
+ if (IN_CLASSA(subnet)) {
+ mask = IN_CLASSA_NET;
+ subnetshift = 8;
+ } else if (IN_CLASSB(subnet)) {
+ mask = IN_CLASSB_NET;
+ subnetshift = 8;
+ } else {
+ mask = IN_CLASSC_NET;
+ subnetshift = 4;
+ }
+
+ /*
+ * If there are more bits than the standard mask
+ * would suggest, subnets must be in use.
+ * Guess at the subnet mask, assuming reasonable
+ * width subnet fields.
+ * XXX: Or-in at least 1 byte's worth of 1s to make
+ * sure the top bits remain set.
+ */
+ while (subnet & ~mask)
+ mask = (mask >> subnetshift) | 0xff000000;
+
+ net = subnet & mask;
+ while ((mask & 1) == 0)
+ mask >>= 1, net >>= 1;
+
+ /*
+ * Now get a usable name.
+ * First use the network database,
+ * then the host database,
+ * and finally just make a dotted quad.
+ */
+ np = getnetbyaddr(net, AF_INET);
+
+ /* the network address has been masked off */
+ if ((subnet & 0xffffff) == 0) {
+ sprintf(netNumberBuf, "%lu", C(subnet >> 24));
+ } else if ((subnet & 0xffff) == 0) {
+ sprintf(netNumberBuf, "%lu.%lu",
+ C(subnet >> 24), C(subnet >> 16));
+ } else if ((subnet & 0xff) == 0) {
+ sprintf(netNumberBuf, "%lu.%lu.%lu",
+ C(subnet >> 24), C(subnet >> 16),
+ C(subnet >> 8));
+ } else {
+ sprintf(netNumberBuf, "%lu.%lu.%lu.%lu",
+ C(subnet >> 24), C(subnet >> 16),
+ C(subnet >> 8), C(subnet));
+ }
+
+ /* fill in network number (string) */
+ al->ip_net_num = strdup(netNumberBuf);
+
+#else /* not IN_CLASSA */
+ /* This is probably very wrong. */
+ np = getnetbyaddr(subnet, AF_INET);
+#endif /* not IN_CLASSA */
+
+ if (np)
+ s = np->n_name;
+ else {
+ subnet = address & netmask;
+ hp = gethostbyaddr((char *) &subnet, 4, AF_INET);
+ if (hp)
+ s = (char *) hp->h_name;
+ else
+ s = inet_dquad(buf, subnet);
+ }
+
+ /* fill in network name (string) */
+ al->ip_net_name = strdup(s);
+ }
+
+out:
+ if (fd >= 0)
+ close(fd);
+ if (localnets) {
+ *name1 = localnets->ip_net_name;
+ *number1 = localnets->ip_net_num;
+ } else {
+ *name1 = NO_SUBNET;
+ *number1 = "0.0.0.0";
+ }
+}
+
+
+/*
+ * Make a dotted quad from a 32bit IP address
+ * addr is in network byte order.
+ * sizeof(buf) needs to be at least 16.
+ */
+char *
+inet_dquad(char *buf, u_long addr)
+{
+ addr = ntohl(addr);
+ sprintf(buf, "%ld.%ld.%ld.%ld",
+ ((addr >> 24) & 0xff),
+ ((addr >> 16) & 0xff),
+ ((addr >> 8) & 0xff),
+ ((addr >> 0) & 0xff));
+ return buf;
+}
+
+
+/*
+ * Determine whether a network is on a local network
+ * (addr) is in network byte order.
+ */
+int
+islocalnet(u_long addr)
+{
+ addrlist *al;
+#ifdef DEBUG
+ char buf[16];
+#endif /* DEBUG */
+
+ for (al = localnets; al; al = al->ip_next)
+ if (((addr ^ al->ip_addr) & al->ip_mask) == 0)
+ return TRUE;
+
+#ifdef DEBUG
+ plog(XLOG_INFO, "%s is on a remote network", inet_dquad(buf, addr));
+#endif /* DEBUG */
+
+ return FALSE;
+}
+
+
+/*
+ * Determine whether a network name is one of the local networks
+ * of a host.
+ */
+int
+is_network_member(const char *net)
+{
+ addrlist *al;
+
+ for (al = localnets; al; al = al->ip_next)
+ if (STREQ(net, al->ip_net_name) || STREQ(net, al->ip_net_num))
+ return TRUE;
+
+ return FALSE;
+}
diff --git a/contrib/amd/libamu/xdr_func.c b/contrib/amd/libamu/xdr_func.c
new file mode 100644
index 0000000..feafbae
--- /dev/null
+++ b/contrib/amd/libamu/xdr_func.c
@@ -0,0 +1,1155 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: xdr_func.c,v 5.2.2.1 1992/02/09 15:08:40 jsp beta $
+ *
+ */
+
+/*
+ * Complete list of all possible xdr functions which may be needed.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+/*
+ * MACROS:
+ */
+#ifdef HAVE_FS_AUTOFS
+# ifndef A_MAXNAME
+# define A_MAXNAME 255
+# endif /* not A_MAXNAME */
+# ifndef A_MAXOPTS
+# define A_MAXOPTS 255
+# endif /* not A_MAXOPTS */
+# ifndef A_MAXPATH
+# define A_MAXPATH 1024
+# endif /* not A_MAXPATH */
+#endif /* HAVE_FS_AUTOFS */
+
+/* forward definitions, are they needed? */
+extern bool_t xdr_exportnode(XDR *xdrs, exportnode *objp);
+extern bool_t xdr_groupnode(XDR *xdrs, groupnode *objp);
+extern bool_t xdr_name(XDR *xdrs, name *objp);
+
+
+#ifndef HAVE_XDR_ATTRSTAT
+bool_t
+xdr_attrstat(XDR *xdrs, nfsattrstat *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_attrstat:");
+#endif /* DEBUG */
+
+ if (!xdr_nfsstat(xdrs, &objp->ns_status)) {
+ return (FALSE);
+ }
+ switch (objp->ns_status) {
+ case NFS_OK:
+ if (!xdr_fattr(xdrs, &objp->ns_u.ns_attr_u)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_ATTRSTAT */
+
+
+#ifndef HAVE_XDR_CREATEARGS
+bool_t
+xdr_createargs(XDR *xdrs, nfscreateargs *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_createargs:");
+#endif /* DEBUG */
+
+ if (!xdr_diropargs(xdrs, &objp->ca_where)) {
+ return (FALSE);
+ }
+ if (!xdr_sattr(xdrs, &objp->ca_attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_CREATEARGS */
+
+
+#ifndef HAVE_XDR_DIRLIST
+bool_t
+xdr_dirlist(XDR *xdrs, nfsdirlist *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_dirlist:");
+#endif /* DEBUG */
+
+ if (!xdr_pointer(xdrs, (char **) &objp->dl_entries, sizeof(nfsentry), (XDRPROC_T_TYPE) xdr_entry)) {
+ return (FALSE);
+ }
+ if (!xdr_bool(xdrs, &objp->dl_eof)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_DIRLIST */
+
+
+#ifndef HAVE_XDR_DIROPARGS
+bool_t
+xdr_diropargs(XDR *xdrs, nfsdiropargs *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_diropargs:");
+#endif /* DEBUG */
+
+ if (!xdr_nfs_fh(xdrs, &objp->da_fhandle)) {
+ return (FALSE);
+ }
+ if (!xdr_filename(xdrs, &objp->da_name)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_DIROPARGS */
+
+
+#ifndef HAVE_XDR_DIROPOKRES
+bool_t
+xdr_diropokres(XDR *xdrs, nfsdiropokres *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_diropokres:");
+#endif /* DEBUG */
+
+ if (!xdr_nfs_fh(xdrs, &objp->drok_fhandle)) {
+ return (FALSE);
+ }
+ if (!xdr_fattr(xdrs, &objp->drok_attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_DIROPOKRES */
+
+
+#ifndef HAVE_XDR_DIROPRES
+bool_t
+xdr_diropres(XDR *xdrs, nfsdiropres *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_diropres:");
+#endif /* DEBUG */
+
+ if (!xdr_nfsstat(xdrs, &objp->dr_status)) {
+ return (FALSE);
+ }
+ switch (objp->dr_status) {
+ case NFS_OK:
+ if (!xdr_diropokres(xdrs, &objp->dr_u.dr_drok_u)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_DIROPRES */
+
+
+#ifndef HAVE_XDR_DIRPATH
+bool_t
+xdr_dirpath(XDR *xdrs, dirpath *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_dirpath:");
+#endif /* DEBUG */
+
+ if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_DIRPATH */
+
+
+#ifndef HAVE_XDR_ENTRY
+bool_t
+xdr_entry(XDR *xdrs, nfsentry *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_entry:");
+#endif /* DEBUG */
+
+ if (!xdr_u_int(xdrs, &objp->ne_fileid)) {
+ return (FALSE);
+ }
+ if (!xdr_filename(xdrs, &objp->ne_name)) {
+ return (FALSE);
+ }
+ if (!xdr_nfscookie(xdrs, objp->ne_cookie)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **) &objp->ne_nextentry, sizeof(nfsentry), (XDRPROC_T_TYPE) xdr_entry)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_ENTRY */
+
+
+#ifndef HAVE_XDR_EXPORTNODE
+bool_t
+xdr_exportnode(XDR *xdrs, exportnode *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_exportnode:");
+#endif /* DEBUG */
+
+ if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
+ return (FALSE);
+ }
+ /*
+ * This cast to (groups) is needed for Irix6. If you change it, it
+ * may produce a warning/error on other systems.
+ */
+ if (!xdr_groups(xdrs, (groups) &objp->ex_groups)) {
+ return (FALSE);
+ }
+ if (!xdr_exports(xdrs, &objp->ex_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_EXPORTNODE */
+
+
+#ifndef HAVE_XDR_EXPORTS
+bool_t
+xdr_exports(XDR *xdrs, exports *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_exports:");
+#endif /* DEBUG */
+
+ if (!xdr_pointer(xdrs, (char **) objp, sizeof(exportnode), (XDRPROC_T_TYPE) xdr_exportnode)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_EXPORTS */
+
+
+#ifndef HAVE_XDR_FATTR
+bool_t
+xdr_fattr(XDR *xdrs, nfsfattr *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_fattr:");
+#endif /* DEBUG */
+
+ if (!xdr_ftype(xdrs, &objp->na_type)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->na_mode)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->na_nlink)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->na_uid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->na_gid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->na_size)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->na_blocksize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->na_rdev)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->na_blocks)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->na_fsid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->na_fileid)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->na_atime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->na_mtime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->na_ctime)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_FATTR */
+
+
+#ifndef HAVE_XDR_FHANDLE
+bool_t
+xdr_fhandle(XDR *xdrs, fhandle objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_fhandle:");
+#endif /* DEBUG */
+
+ if (!xdr_opaque(xdrs, objp, NFS_FHSIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_FHANDLE */
+
+
+#ifndef HAVE_XDR_FHSTATUS
+bool_t
+xdr_fhstatus(XDR *xdrs, fhstatus *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_fhstatus:");
+#endif /* DEBUG */
+
+ if (!xdr_u_int(xdrs, &objp->fhs_status)) {
+ return (FALSE);
+ }
+ if (objp->fhs_status == 0 && !xdr_fhandle(xdrs, objp->fhs_fh)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_FHSTATUS */
+
+
+#ifndef HAVE_XDR_FILENAME
+bool_t
+xdr_filename(XDR *xdrs, filename *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_filename:");
+#endif /* DEBUG */
+
+ if (!xdr_string(xdrs, objp, NFS_MAXNAMLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_FILENAME */
+
+
+#ifndef HAVE_XDR_FTYPE
+bool_t
+xdr_ftype(XDR *xdrs, nfsftype *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_ftype:");
+#endif /* DEBUG */
+
+ if (!xdr_enum(xdrs, (enum_t *) objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_FTYPE */
+
+
+#ifndef HAVE_XDR_GROUPNODE
+bool_t
+xdr_groupnode(XDR *xdrs, groupnode *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_groupnode:");
+#endif /* DEBUG */
+
+ if (!xdr_name(xdrs, &objp->gr_name)) {
+ return (FALSE);
+ }
+ /*
+ * This cast to (groups) is needed for Irix6. If you change it, it
+ * may produce a warning/error on other systems.
+ */
+ if (!xdr_groups(xdrs, (groups) &objp->gr_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_GROUPNODE */
+
+
+#ifndef HAVE_XDR_GROUPS
+bool_t
+xdr_groups(XDR *xdrs, groups objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_groups:");
+#endif /* DEBUG */
+
+ if (!xdr_pointer(xdrs, (char **) objp, sizeof(groupnode), (XDRPROC_T_TYPE) xdr_groupnode)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_GROUPS */
+
+
+#ifndef HAVE_XDR_LINKARGS
+bool_t
+xdr_linkargs(XDR *xdrs, nfslinkargs *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_linkargs:");
+#endif /* DEBUG */
+
+ if (!xdr_nfs_fh(xdrs, &objp->la_fhandle)) {
+ return (FALSE);
+ }
+ if (!xdr_diropargs(xdrs, &objp->la_to)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_LINKARGS */
+
+
+#ifndef HAVE_XDR_MOUNTBODY
+bool_t
+xdr_mountbody(XDR *xdrs, mountbody *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_mountbody:");
+#endif /* DEBUG */
+
+ if (!xdr_name(xdrs, &objp->ml_hostname)) {
+ return (FALSE);
+ }
+ if (!xdr_dirpath(xdrs, &objp->ml_directory)) {
+ return (FALSE);
+ }
+ if (!xdr_mountlist(xdrs, &objp->ml_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_MOUNTBODY */
+
+
+#ifndef HAVE_XDR_MOUNTLIST
+bool_t
+xdr_mountlist(XDR *xdrs, mountlist *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_mountlist:");
+#endif /* DEBUG */
+
+ if (!xdr_pointer(xdrs, (char **) objp, sizeof(mountbody), (XDRPROC_T_TYPE) xdr_mountbody)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_MOUNTLIST */
+
+
+#if defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3)
+/*
+ * This ifdef is a hack: this whole file needs to be compiled
+ * only if the system has NFS V3 and does not have the xdr_mountres3
+ * function. Autoconf should pick this source file to compile only
+ * if these two conditions apply.
+ */
+
+bool_t
+xdr_fhandle3(XDR *xdrs, fhandle3 *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_fhandle3:");
+#endif /* DEBUG */
+
+ if (!xdr_bytes(xdrs,
+ (char **) &objp->fhandle3_val,
+ (u_int *) &objp->fhandle3_len,
+ FHSIZE3))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+bool_t
+xdr_mountstat3(XDR *xdrs, mountstat3 *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_mountstat3:");
+#endif /* DEBUG */
+
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+bool_t
+xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_mountres3_ok:");
+#endif /* DEBUG */
+
+ if (!xdr_fhandle3(xdrs, &objp->fhandle))
+ return (FALSE);
+ if (!xdr_array(xdrs,
+ (char **)&objp->auth_flavors.auth_flavors_val,
+ (u_int *) &objp->auth_flavors.auth_flavors_len,
+ ~0,
+ sizeof (int),
+ (xdrproc_t) xdr_int))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+bool_t
+xdr_mountres3(XDR *xdrs, mountres3 *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_mountres3:");
+#endif /* DEBUG */
+
+ if (!xdr_mountstat3(xdrs, &objp->fhs_status))
+ return (FALSE);
+
+ if (objp->fhs_status == 0) { /* 0 == MNT_OK or MNT3_OK */
+ if (!xdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo))
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3) */
+
+
+#ifndef HAVE_XDR_NAME
+bool_t
+xdr_name(XDR *xdrs, name *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_name:");
+#endif /* DEBUG */
+
+ if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_NAME */
+
+
+#ifndef HAVE_XDR_NFS_FH
+bool_t
+xdr_nfs_fh(XDR *xdrs, am_nfs_fh *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_nfs_fh:");
+#endif /* DEBUG */
+
+ if (!xdr_opaque(xdrs, (caddr_t) objp->fh_data, NFS_FHSIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_NFS_FH */
+
+
+#ifndef HAVE_XDR_NFSCOOKIE
+bool_t
+xdr_nfscookie(XDR *xdrs, nfscookie objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_nfscookie:");
+#endif /* DEBUG */
+
+ if (!xdr_opaque(xdrs, objp, NFS_COOKIESIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_NFSCOOKIE */
+
+
+#ifndef HAVE_XDR_NFSPATH
+bool_t
+xdr_nfspath(XDR *xdrs, nfspath *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_nfspath:");
+#endif /* DEBUG */
+
+ if (!xdr_string(xdrs, objp, NFS_MAXPATHLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_NFSPATH */
+
+
+#ifndef HAVE_XDR_NFSSTAT
+bool_t
+xdr_nfsstat(XDR *xdrs, nfsstat *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_nfsstat:");
+#endif /* DEBUG */
+
+ if (!xdr_enum(xdrs, (enum_t *) objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_NFSSTAT */
+
+
+#ifndef HAVE_XDR_NFSTIME
+bool_t
+xdr_nfstime(XDR *xdrs, nfstime *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_nfstime:");
+#endif /* DEBUG */
+
+ if (!xdr_u_int(xdrs, (u_int *) &objp->nt_seconds)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, (u_int *) &objp->nt_useconds)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_NFSTIME */
+
+
+#ifndef HAVE_XDR_POINTER
+bool_t
+xdr_pointer(register XDR *xdrs, char **objpp, u_int obj_size, XDRPROC_T_TYPE xdr_obj)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_pointer:");
+#endif /* DEBUG */
+
+
+ bool_t more_data;
+
+ more_data = (*objpp != NULL);
+ if (!xdr_bool(xdrs, &more_data)) {
+ return (FALSE);
+ }
+ if (!more_data) {
+ *objpp = NULL;
+ return (TRUE);
+ }
+
+ return (xdr_reference(xdrs, objpp, obj_size, xdr_obj));
+}
+#endif /* not HAVE_XDR_POINTER */
+
+
+#ifndef HAVE_XDR_READARGS
+bool_t
+xdr_readargs(XDR *xdrs, nfsreadargs *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_readargs:");
+#endif /* DEBUG */
+
+ if (!xdr_nfs_fh(xdrs, &objp->ra_fhandle)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->ra_offset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->ra_count)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->ra_totalcount)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_READARGS */
+
+
+#ifndef HAVE_XDR_READDIRARGS
+bool_t
+xdr_readdirargs(XDR *xdrs, nfsreaddirargs *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_readdirargs:");
+#endif /* DEBUG */
+
+ if (!xdr_nfs_fh(xdrs, &objp->rda_fhandle)) {
+ return (FALSE);
+ }
+ if (!xdr_nfscookie(xdrs, objp->rda_cookie)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->rda_count)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_READDIRARGS */
+
+
+#ifndef HAVE_XDR_READDIRRES
+bool_t
+xdr_readdirres(XDR *xdrs, nfsreaddirres *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_readdirres:");
+#endif /* DEBUG */
+
+ if (!xdr_nfsstat(xdrs, &objp->rdr_status)) {
+ return (FALSE);
+ }
+ switch (objp->rdr_status) {
+ case NFS_OK:
+ if (!xdr_dirlist(xdrs, &objp->rdr_u.rdr_reply_u)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_READDIRRES */
+
+
+#ifndef HAVE_XDR_READLINKRES
+bool_t
+xdr_readlinkres(XDR *xdrs, nfsreadlinkres *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_readlinkres:");
+#endif /* DEBUG */
+
+ if (!xdr_nfsstat(xdrs, &objp->rlr_status)) {
+ return (FALSE);
+ }
+ switch (objp->rlr_status) {
+ case NFS_OK:
+ if (!xdr_nfspath(xdrs, &objp->rlr_u.rlr_data_u)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_READLINKRES */
+
+
+#ifndef HAVE_XDR_READOKRES
+bool_t
+xdr_readokres(XDR *xdrs, nfsreadokres *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_readokres:");
+#endif /* DEBUG */
+
+ if (!xdr_fattr(xdrs, &objp->raok_attributes)) {
+ return (FALSE);
+ }
+ if (!xdr_bytes(xdrs,
+ (char **) & objp->raok_u.raok_val_u,
+ (u_int *) & objp->raok_u.raok_len_u,
+ NFS_MAXDATA)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_READOKRES */
+
+
+#ifndef HAVE_XDR_READRES
+bool_t
+xdr_readres(XDR *xdrs, nfsreadres *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_readres:");
+#endif /* DEBUG */
+
+ if (!xdr_nfsstat(xdrs, &objp->rr_status)) {
+ return (FALSE);
+ }
+ switch (objp->rr_status) {
+ case NFS_OK:
+ if (!xdr_readokres(xdrs, &objp->rr_u.rr_reply_u)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_READRES */
+
+
+#ifndef HAVE_XDR_RENAMEARGS
+bool_t
+xdr_renameargs(XDR *xdrs, nfsrenameargs *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_renameargs:");
+#endif /* DEBUG */
+
+ if (!xdr_diropargs(xdrs, &objp->rna_from)) {
+ return (FALSE);
+ }
+ if (!xdr_diropargs(xdrs, &objp->rna_to)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_RENAMEARGS */
+
+
+#ifndef HAVE_XDR_SATTR
+bool_t
+xdr_sattr(XDR *xdrs, nfssattr *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_sattr:");
+#endif /* DEBUG */
+
+ if (!xdr_u_int(xdrs, &objp->sa_mode)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->sa_uid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->sa_gid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->sa_size)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->sa_atime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->sa_mtime)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_SATTR */
+
+
+#ifndef HAVE_XDR_SATTRARGS
+bool_t
+xdr_sattrargs(XDR *xdrs, nfssattrargs *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_sattrargs:");
+#endif /* DEBUG */
+
+ if (!xdr_nfs_fh(xdrs, &objp->sag_fhandle)) {
+ return (FALSE);
+ }
+ if (!xdr_sattr(xdrs, &objp->sag_attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_SATTRARGS */
+
+
+#ifndef HAVE_XDR_STATFSOKRES
+bool_t
+xdr_statfsokres(XDR *xdrs, nfsstatfsokres *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_statfsokres:");
+#endif /* DEBUG */
+
+ if (!xdr_u_int(xdrs, &objp->sfrok_tsize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->sfrok_bsize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->sfrok_blocks)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->sfrok_bfree)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->sfrok_bavail)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_STATFSOKRES */
+
+
+#ifndef HAVE_XDR_STATFSRES
+bool_t
+xdr_statfsres(XDR *xdrs, nfsstatfsres *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_statfsres:");
+#endif /* DEBUG */
+
+ if (!xdr_nfsstat(xdrs, &objp->sfr_status)) {
+ return (FALSE);
+ }
+ switch (objp->sfr_status) {
+ case NFS_OK:
+ if (!xdr_statfsokres(xdrs, &objp->sfr_u.sfr_reply_u)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_STATFSRES */
+
+
+#ifndef HAVE_XDR_SYMLINKARGS
+bool_t
+xdr_symlinkargs(XDR *xdrs, nfssymlinkargs *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_symlinkargs:");
+#endif /* DEBUG */
+
+ if (!xdr_diropargs(xdrs, &objp->sla_from)) {
+ return (FALSE);
+ }
+ if (!xdr_nfspath(xdrs, &objp->sla_to)) {
+ return (FALSE);
+ }
+ if (!xdr_sattr(xdrs, &objp->sla_attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_SYMLINKARGS */
+
+
+#ifndef HAVE_XDR_WRITEARGS
+bool_t
+xdr_writeargs(XDR *xdrs, nfswriteargs *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_writeargs:");
+#endif /* DEBUG */
+
+ if (!xdr_nfs_fh(xdrs, &objp->wra_fhandle)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->wra_beginoffset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->wra_offset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->wra_totalcount)) {
+ return (FALSE);
+ }
+ if (!xdr_bytes(xdrs,
+ (char **) & objp->wra_u.wra_val_u,
+ (u_int *) & objp->wra_u.wra_len_u,
+ NFS_MAXDATA)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+#endif /* not HAVE_XDR_WRITEARGS */
+
+
+/*
+ * AUTOFS XDR FUNCTIONS:
+ */
+#ifdef HAVE_FS_AUTOFS
+# ifndef HAVE_XDR_MNTREQUEST
+bool_t
+xdr_mntrequest(XDR *xdrs, mntrequest *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_mntrequest:");
+#endif /* DEBUG */
+
+ if (!xdr_string(xdrs, &objp->name, A_MAXNAME))
+ return (FALSE);
+
+ if (!xdr_string(xdrs, &objp->map, A_MAXNAME))
+ return (FALSE);
+
+ if (!xdr_string(xdrs, &objp->opts, A_MAXOPTS))
+ return (FALSE);
+
+ if (!xdr_string(xdrs, &objp->path, A_MAXPATH))
+ return (FALSE);
+
+ return (TRUE);
+}
+# endif /* not HAVE_XDR_MNTREQUEST */
+
+
+# ifndef HAVE_XDR_MNTRES
+bool_t
+xdr_mntres(XDR *xdrs, mntres *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_mntres:");
+#endif /* DEBUG */
+
+ if (!xdr_int(xdrs, &objp->status))
+ return (FALSE);
+
+ return (TRUE);
+}
+# endif /* not HAVE_XDR_MNTRES */
+
+
+# ifndef HAVE_XDR_UMNTREQUEST
+bool_t
+xdr_umntrequest(XDR *xdrs, umntrequest *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_umntrequest:");
+#endif /* DEBUG */
+
+ if (!xdr_int(xdrs, &objp->isdirect))
+ return (FALSE);
+
+ if (!xdr_u_int(xdrs, (u_int *) &objp->devid))
+ return (FALSE);
+
+#ifdef HAVE_FIELD_UMNTREQUEST_RDEVID
+ if (!xdr_u_long(xdrs, &objp->rdevid))
+ return (FALSE);
+#endif /* HAVE_FIELD_UMNTREQUEST_RDEVID */
+
+ if (!xdr_pointer(xdrs, (char **) &objp->next, sizeof(umntrequest), (XDRPROC_T_TYPE) xdr_umntrequest))
+ return (FALSE);
+
+ return (TRUE);
+}
+# endif /* not HAVE_XDR_UMNTREQUEST */
+
+
+# ifndef HAVE_XDR_UMNTRES
+bool_t
+xdr_umntres(XDR *xdrs, umntres *objp)
+{
+#ifdef DEBUG
+ amuDebug(D_TRACE)
+ plog(XLOG_DEBUG, "xdr_mntres:");
+#endif /* DEBUG */
+
+ if (!xdr_int(xdrs, &objp->status))
+ return (FALSE);
+
+ return (TRUE);
+}
+# endif /* not HAVE_XDR_UMNTRES */
+#endif /* HAVE_FS_AUTOFS */
diff --git a/contrib/amd/libamu/xutil.c b/contrib/amd/libamu/xutil.c
new file mode 100644
index 0000000..15d2cee
--- /dev/null
+++ b/contrib/amd/libamu/xutil.c
@@ -0,0 +1,825 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: xutil.c,v 1.1 1997-1998/01/11 21:06:22 ezk Exp ezk $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amu.h>
+
+FILE *logfp = stderr; /* Log errors to stderr initially */
+
+#ifdef HAVE_SYSLOG
+int syslogging;
+#endif /* HAVE_SYSLOG */
+int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS;
+int xlog_level_init = ~0;
+static int amd_program_number = AMQ_PROGRAM;
+
+time_t clock_valid = 0;
+time_t xclock_valid = 0;
+
+#ifdef DEBUG_MEM
+static int mem_bytes;
+static int orig_mem_bytes;
+#endif /* DEBUG_MEM */
+
+/* forward definitions */
+static void real_plog(int lvl, char *fmt, va_list vargs);
+
+#ifdef DEBUG
+/*
+ * List of debug options.
+ */
+struct opt_tab dbg_opt[] =
+{
+ {"all", D_ALL}, /* All */
+ {"amq", D_AMQ}, /* Register for AMQ program */
+ {"daemon", D_DAEMON}, /* Enter daemon mode */
+ {"fork", D_FORK}, /* Fork server (nofork = don't fork) */
+ {"full", D_FULL}, /* Program trace */
+ /* info service specific debugging (hesiod, nis, etc) */
+ {"info", D_INFO},
+# ifdef DEBUG_MEM
+ {"mem", D_MEM}, /* Trace memory allocations */
+# endif /* DEBUG_MEM */
+ {"mtab", D_MTAB}, /* Use local mtab file */
+ {"str", D_STR}, /* Debug string munging */
+ {"test", D_TEST}, /* Full debug - but no daemon */
+ {"trace", D_TRACE}, /* Protocol trace */
+ {0, 0}
+};
+#endif /* DEBUG */
+
+/*
+ * List of log options
+ */
+struct opt_tab xlog_opt[] =
+{
+ {"all", XLOG_ALL}, /* All messages */
+#ifdef DEBUG
+ {"debug", XLOG_DEBUG}, /* Debug messages */
+#endif /* DEBUG */ /* DEBUG */
+ {"error", XLOG_ERROR}, /* Non-fatal system errors */
+ {"fatal", XLOG_FATAL}, /* Fatal errors */
+ {"info", XLOG_INFO}, /* Information */
+ {"map", XLOG_MAP}, /* Map errors */
+ {"stats", XLOG_STATS}, /* Additional statistical information */
+ {"user", XLOG_USER}, /* Non-fatal user errors */
+ {"warn", XLOG_WARNING}, /* Warnings */
+ {"warning", XLOG_WARNING}, /* Warnings */
+ {0, 0}
+};
+
+
+voidp
+xmalloc(int len)
+{
+ voidp p;
+ int retries = 600;
+
+ /*
+ * Avoid malloc's which return NULL for malloc(0)
+ */
+ if (len == 0)
+ len = 1;
+
+ do {
+ p = (voidp) malloc((unsigned) len);
+ if (p) {
+#if defined(DEBUG) && defined(DEBUG_MEM)
+ amuDebug(D_MEM)
+ plog(XLOG_DEBUG, "Allocated size %d; block %#x", len, p);
+#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
+ return p;
+ }
+ if (retries > 0) {
+ plog(XLOG_ERROR, "Retrying memory allocation");
+ sleep(1);
+ }
+ } while (--retries);
+
+ plog(XLOG_FATAL, "Out of memory");
+ going_down(1);
+
+ abort();
+
+ return 0;
+}
+
+
+/* like xmalloc, but zeros out the bytes */
+voidp
+xzalloc(int len)
+{
+ voidp p = xmalloc(len);
+
+ if (p)
+ memset(p, 0, len);
+ return p;
+}
+
+
+voidp
+xrealloc(voidp ptr, int len)
+{
+#if defined(DEBUG) && defined(DEBUG_MEM)
+ amuDebug(D_MEM) plog(XLOG_DEBUG, "Reallocated size %d; block %#x", len, ptr);
+#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
+
+ if (len == 0)
+ len = 1;
+
+ if (ptr)
+ ptr = (voidp) realloc(ptr, (unsigned) len);
+ else
+ ptr = (voidp) xmalloc((unsigned) len);
+
+ if (!ptr) {
+ plog(XLOG_FATAL, "Out of memory in realloc");
+ going_down(1);
+ abort();
+ }
+ return ptr;
+}
+
+
+#if defined(DEBUG) && defined(DEBUG_MEM)
+void
+dxfree(char *file, int line, voidp ptr)
+{
+ amuDebug(D_MEM)
+ plog(XLOG_DEBUG, "Free in %s:%d: block %#x", file, line, ptr);
+ /* this is the only place that must NOT use XFREE()!!! */
+ free(ptr);
+ ptr = NULL; /* paranoid */
+}
+#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
+
+
+#ifdef DEBUG_MEM
+static void
+checkup_mem(void)
+{
+ struct mallinfo mi = mallinfo();
+ u_long uordbytes = mi.uordblks * 4096;
+
+ if (mem_bytes != uordbytes) {
+ if (orig_mem_bytes == 0)
+ mem_bytes = orig_mem_bytes = uordbytes;
+ else {
+ fprintf(logfp, "%s[%ld]: ", progname, (long) mypid);
+ if (mem_bytes < uordbytes) {
+ fprintf(logfp, "ALLOC: %ld bytes", uordbytes - mem_bytes);
+ } else {
+ fprintf(logfp, "FREE: %ld bytes", mem_bytes - uordbytes);
+ }
+ mem_bytes = uordbytes;
+ fprintf(logfp, ", making %d missing\n", mem_bytes - orig_mem_bytes);
+ }
+ }
+ malloc_verify();
+}
+#endif /* DEBUG_MEM */
+
+
+/*
+ * Take a log format string and expand occurences of %m
+ * with the current error code taken from errno.
+ */
+static void
+expand_error(char *f, char *e)
+{
+ extern int sys_nerr;
+ char *p;
+ int error = errno;
+
+ for (p = f; (*e = *p); e++, p++) {
+ if (p[0] == '%' && p[1] == 'm') {
+ const char *errstr;
+ if (error < 0 || error >= sys_nerr)
+ errstr = NULL;
+ else
+ errstr = sys_errlist[error];
+ if (errstr)
+ strcpy(e, errstr);
+ else
+ sprintf(e, "Error %d", error);
+ e += strlen(e) - 1;
+ p++;
+ }
+ }
+}
+
+
+/*
+ * Output the time of day and hostname to the logfile
+ */
+static void
+show_time_host_and_name(int lvl)
+{
+ static time_t last_t = 0;
+ static char *last_ctime = 0;
+ time_t t = clocktime();
+ char *sev;
+
+ if (t != last_t) {
+ last_ctime = ctime(&t);
+ last_t = t;
+ }
+ switch (lvl) {
+ case XLOG_FATAL:
+ sev = "fatal:";
+ break;
+ case XLOG_ERROR:
+ sev = "error:";
+ break;
+ case XLOG_USER:
+ sev = "user: ";
+ break;
+ case XLOG_WARNING:
+ sev = "warn: ";
+ break;
+ case XLOG_INFO:
+ sev = "info: ";
+ break;
+ case XLOG_DEBUG:
+ sev = "debug:";
+ break;
+ case XLOG_MAP:
+ sev = "map: ";
+ break;
+ case XLOG_STATS:
+ sev = "stats:";
+ break;
+ default:
+ sev = "hmm: ";
+ break;
+ }
+ fprintf(logfp, "%15.15s %s %s[%ld]/%s ",
+ last_ctime + 4, hostname,
+ progname,
+ (long) mypid,
+ sev);
+}
+
+
+#ifdef DEBUG
+/*
+ * Switch on/off debug options
+ */
+int
+debug_option(char *opt)
+{
+ return cmdoption(opt, dbg_opt, &debug_flags);
+}
+
+
+void
+dplog(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ real_plog(XLOG_DEBUG, fmt, ap);
+ va_end(ap);
+}
+#endif /* DEBUG */
+
+
+void
+plog(int lvl, char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ real_plog(lvl, fmt, ap);
+ va_end(ap);
+}
+
+
+static void
+real_plog(int lvl, char *fmt, va_list vargs)
+{
+ char msg[1024];
+ char efmt[1024];
+ char *ptr = msg;
+ static char last_msg[1024];
+ static int last_count = 0, last_lvl = 0;
+
+ if (!(xlog_level & lvl))
+ return;
+
+#ifdef DEBUG_MEM
+ checkup_mem();
+#endif /* DEBUG_MEM */
+
+ expand_error(fmt, efmt);
+
+ vsprintf(ptr, efmt, vargs);
+
+ ptr += strlen(ptr);
+ if (ptr[-1] == '\n')
+ *--ptr = '\0';
+
+#ifdef HAVE_SYSLOG
+ if (syslogging) {
+ switch (lvl) { /* from mike <mcooper@usc.edu> */
+ case XLOG_FATAL:
+ lvl = LOG_CRIT;
+ break;
+ case XLOG_ERROR:
+ lvl = LOG_ERR;
+ break;
+ case XLOG_USER:
+ lvl = LOG_WARNING;
+ break;
+ case XLOG_WARNING:
+ lvl = LOG_WARNING;
+ break;
+ case XLOG_INFO:
+ lvl = LOG_INFO;
+ break;
+ case XLOG_DEBUG:
+ lvl = LOG_DEBUG;
+ break;
+ case XLOG_MAP:
+ lvl = LOG_DEBUG;
+ break;
+ case XLOG_STATS:
+ lvl = LOG_INFO;
+ break;
+ default:
+ lvl = LOG_ERR;
+ break;
+ }
+ syslog(lvl, "%s", msg);
+ return;
+ }
+#endif /* HAVE_SYSLOG */
+
+ *ptr++ = '\n';
+ *ptr = '\0';
+
+ /*
+ * mimic syslog behavior: only write repeated strings if they differ
+ */
+ switch (last_count) {
+ case 0: /* never printed at all */
+ last_count = 1;
+ strncpy(last_msg, msg, 1024);
+ last_lvl = lvl;
+ show_time_host_and_name(lvl); /* mimic syslog header */
+ fwrite(msg, ptr - msg, 1, logfp);
+ fflush(logfp);
+ break;
+
+ case 1: /* item printed once, if same, don't repeat */
+ if (STREQ(last_msg, msg)) {
+ last_count++;
+ } else { /* last msg printed once, new one differs */
+ /* last_count remains at 1 */
+ strncpy(last_msg, msg, 1024);
+ last_lvl = lvl;
+ show_time_host_and_name(lvl); /* mimic syslog header */
+ fwrite(msg, ptr - msg, 1, logfp);
+ fflush(logfp);
+ }
+ break;
+
+ case 100:
+ /*
+ * Don't allow repetitions longer than 100, so you can see when something
+ * cycles like crazy.
+ */
+ show_time_host_and_name(last_lvl);
+ sprintf(last_msg, "last message repeated %d times\n", last_count);
+ fwrite(last_msg, strlen(last_msg), 1, logfp);
+ fflush(logfp);
+ last_count = 0; /* start from scratch */
+ break;
+
+ default: /* item repeated multiple times */
+ if (STREQ(last_msg, msg)) {
+ last_count++;
+ } else { /* last msg repeated+skipped, new one differs */
+ show_time_host_and_name(last_lvl);
+ sprintf(last_msg, "last message repeated %d times\n", last_count);
+ fwrite(last_msg, strlen(last_msg), 1, logfp);
+ strncpy(last_msg, msg, 1024);
+ last_count = 1;
+ last_lvl = lvl;
+ show_time_host_and_name(lvl); /* mimic syslog header */
+ fwrite(msg, ptr - msg, 1, logfp);
+ fflush(logfp);
+ }
+ break;
+ }
+
+}
+
+
+/*
+ * Display current debug options
+ */
+void
+show_opts(int ch, struct opt_tab *opts)
+{
+ int i;
+ int s = '{';
+
+ fprintf(stderr, "\t[-%c {no}", ch);
+ for (i = 0; opts[i].opt; i++) {
+ fprintf(stderr, "%c%s", s, opts[i].opt);
+ s = ',';
+ }
+ fputs("}]\n", stderr);
+}
+
+
+int
+cmdoption(char *s, struct opt_tab *optb, int *flags)
+{
+ char *p = s;
+ int errs = 0;
+
+ while (p && *p) {
+ int neg;
+ char *opt;
+ struct opt_tab *dp, *dpn = 0;
+
+ s = p;
+ p = strchr(p, ',');
+ if (p)
+ *p = '\0';
+
+ /* check for "no" prefix to options */
+ if (s[0] == 'n' && s[1] == 'o') {
+ opt = s + 2;
+ neg = 1;
+ } else {
+ opt = s;
+ neg = 0;
+ }
+
+ /*
+ * Scan the array of debug options to find the
+ * corresponding flag value. If it is found
+ * then set (or clear) the flag (depending on
+ * whether the option was prefixed with "no").
+ */
+ for (dp = optb; dp->opt; dp++) {
+ if (STREQ(opt, dp->opt))
+ break;
+ if (opt != s && !dpn && STREQ(s, dp->opt))
+ dpn = dp;
+ }
+
+ if (dp->opt || dpn) {
+ if (!dp->opt) {
+ dp = dpn;
+ neg = !neg;
+ }
+ if (neg)
+ *flags &= ~dp->flag;
+ else
+ *flags |= dp->flag;
+ } else {
+ /*
+ * This will log to stderr when parsing the command line
+ * since any -l option will not yet have taken effect.
+ */
+ plog(XLOG_USER, "option \"%s\" not recognised", s);
+ errs++;
+ }
+
+ /*
+ * Put the comma back
+ */
+ if (p)
+ *p++ = ',';
+ }
+
+ return errs;
+}
+
+
+/*
+ * Switch on/off logging options
+ */
+int
+switch_option(char *opt)
+{
+ int xl = xlog_level;
+ int rc = cmdoption(opt, xlog_opt, &xl);
+
+ if (rc) {
+ rc = EINVAL;
+ } else {
+ /*
+ * Keep track of initial log level, and
+ * don't allow options to be turned off.
+ */
+ if (xlog_level_init == ~0)
+ xlog_level_init = xl;
+ else
+ xl |= xlog_level_init;
+ xlog_level = xl;
+ }
+ return rc;
+}
+
+/*
+ * get syslog facility to use.
+ * logfile can be "syslog", "syslog:daemon", "syslog:local7", etc.
+ */
+static int
+get_syslog_facility(const char *logfile)
+{
+ char *facstr;
+
+ /* parse facility string */
+ facstr = strchr(logfile, ':');
+ if (!facstr) /* log file was "syslog" */
+ return LOG_DAEMON;
+ facstr++;
+ if (!facstr || facstr[0] == '\0') { /* log file was "syslog:" */
+ plog(XLOG_WARNING, "null syslog facility, using LOG_DAEMON");
+ return LOG_DAEMON;
+ }
+
+#ifdef LOG_KERN
+ if (STREQ(facstr, "kern"))
+ return LOG_KERN;
+#endif /* not LOG_KERN */
+#ifdef LOG_USER
+ if (STREQ(facstr, "user"))
+ return LOG_USER;
+#endif /* not LOG_USER */
+#ifdef LOG_MAIL
+ if (STREQ(facstr, "mail"))
+ return LOG_MAIL;
+#endif /* not LOG_MAIL */
+#ifdef LOG_DAEMON
+ if (STREQ(facstr, "daemon"))
+ return LOG_DAEMON;
+#endif /* not LOG_DAEMON */
+#ifdef LOG_AUTH
+ if (STREQ(facstr, "auth"))
+ return LOG_AUTH;
+#endif /* not LOG_AUTH */
+#ifdef LOG_SYSLOG
+ if (STREQ(facstr, "syslog"))
+ return LOG_SYSLOG;
+#endif /* not LOG_SYSLOG */
+#ifdef LOG_LPR
+ if (STREQ(facstr, "lpr"))
+ return LOG_LPR;
+#endif /* not LOG_LPR */
+#ifdef LOG_NEWS
+ if (STREQ(facstr, "news"))
+ return LOG_NEWS;
+#endif /* not LOG_NEWS */
+#ifdef LOG_UUCP
+ if (STREQ(facstr, "uucp"))
+ return LOG_UUCP;
+#endif /* not LOG_UUCP */
+#ifdef LOG_CRON
+ if (STREQ(facstr, "cron"))
+ return LOG_CRON;
+#endif /* not LOG_CRON */
+#ifdef LOG_LOCAL0
+ if (STREQ(facstr, "local0"))
+ return LOG_LOCAL0;
+#endif /* not LOG_LOCAL0 */
+#ifdef LOG_LOCAL1
+ if (STREQ(facstr, "local1"))
+ return LOG_LOCAL1;
+#endif /* not LOG_LOCAL1 */
+#ifdef LOG_LOCAL2
+ if (STREQ(facstr, "local2"))
+ return LOG_LOCAL2;
+#endif /* not LOG_LOCAL2 */
+#ifdef LOG_LOCAL3
+ if (STREQ(facstr, "local3"))
+ return LOG_LOCAL3;
+#endif /* not LOG_LOCAL3 */
+#ifdef LOG_LOCAL4
+ if (STREQ(facstr, "local4"))
+ return LOG_LOCAL4;
+#endif /* not LOG_LOCAL4 */
+#ifdef LOG_LOCAL5
+ if (STREQ(facstr, "local5"))
+ return LOG_LOCAL5;
+#endif /* not LOG_LOCAL5 */
+#ifdef LOG_LOCAL6
+ if (STREQ(facstr, "local6"))
+ return LOG_LOCAL6;
+#endif /* not LOG_LOCAL6 */
+#ifdef LOG_LOCAL7
+ if (STREQ(facstr, "local7"))
+ return LOG_LOCAL7;
+#endif /* not LOG_LOCAL7 */
+
+ /* didn't match anything else */
+ plog(XLOG_WARNING, "unknown syslog facility \"%s\", using LOG_DAEMON", facstr);
+ return LOG_DAEMON;
+}
+
+
+/*
+ * Change current logfile
+ */
+int
+switch_to_logfile(char *logfile)
+{
+ FILE *new_logfp = stderr;
+
+ if (logfile) {
+#ifdef HAVE_SYSLOG
+ syslogging = 0;
+#endif /* HAVE_SYSLOG */
+
+ if (STREQ(logfile, "/dev/stderr"))
+ new_logfp = stderr;
+ else if (NSTREQ(logfile, "syslog", strlen("syslog"))) {
+
+#ifdef HAVE_SYSLOG
+ syslogging = 1;
+ new_logfp = stderr;
+ openlog(progname,
+ LOG_PID
+# ifdef LOG_CONS
+ | LOG_CONS
+# endif /* LOG_CONS */
+# ifdef LOG_NOWAIT
+ | LOG_NOWAIT
+# endif /* LOG_NOWAIT */
+# ifdef LOG_DAEMON
+ , get_syslog_facility(logfile)
+# endif /* LOG_DAEMON */
+ );
+#else /* not HAVE_SYSLOG */
+ plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
+#endif /* not HAVE_SYSLOG */
+
+ } else {
+ (void) umask(orig_umask);
+ new_logfp = fopen(logfile, "a");
+ umask(0);
+ }
+ }
+
+ /*
+ * If we couldn't open a new file, then continue using the old.
+ */
+ if (!new_logfp && logfile) {
+ plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
+ return 1;
+ }
+
+ /*
+ * Close the previous file
+ */
+ if (logfp && logfp != stderr)
+ (void) fclose(logfp);
+ logfp = new_logfp;
+
+ return 0;
+}
+
+
+void
+unregister_amq(void)
+{
+#ifdef DEBUG
+ amuDebug(D_AMQ)
+#endif /* DEBUG */
+ /* find which instance of amd to unregister */
+ pmap_unset(get_amd_program_number(), AMQ_VERSION);
+}
+
+
+void
+going_down(int rc)
+{
+ if (foreground) {
+ if (amd_state != Start) {
+ if (amd_state != Done)
+ return;
+ unregister_amq();
+ }
+ }
+ if (foreground) {
+ plog(XLOG_INFO, "Finishing with status %d", rc);
+ } else {
+#ifdef DEBUG
+ dlog("background process exiting with status %d", rc);
+#endif /* DEBUG */
+ }
+
+ exit(rc);
+}
+
+
+/* return the rpc program number under which amd was used */
+int
+get_amd_program_number(void)
+{
+ return amd_program_number;
+}
+
+
+/* set the rpc program number used for amd */
+void
+set_amd_program_number(int program)
+{
+ amd_program_number = program;
+}
+
+
+/*
+ * Release the controlling tty of the process pid.
+ *
+ * Algorithm: try these in order, if available, until one of them
+ * succeeds: setsid(), ioctl(fd, TIOCNOTTY, 0).
+ * Do not use setpgid(): on some OSs it may release the controlling tty,
+ * even if the man page does not mention it, but on other OSs it does not.
+ * Also avoid setpgrp(): it works on some systems, and on others it is
+ * identical to setpgid().
+ */
+void
+amu_release_controlling_tty(void)
+{
+#ifdef TIOCNOTTY
+ int fd;
+#endif /* TIOCNOTTY */
+
+#ifdef HAVE_SETSID
+ if (setsid() < 0) {
+ plog(XLOG_WARNING, "Could not release controlling tty using setsid(): %m");
+ } else {
+ plog(XLOG_INFO, "released controlling tty using setsid()");
+ return;
+ }
+#endif /* HAVE_SETSID */
+
+#ifdef TIOCNOTTY
+ fd = open("/dev/tty", O_RDWR);
+ if (fd < 0) {
+ /* not an error if already no controlling tty */
+ if (errno != ENXIO)
+ plog(XLOG_WARNING, "Could not open controlling tty: %m");
+ } else {
+ if (ioctl(fd, TIOCNOTTY, 0) < 0 && errno != ENOTTY)
+ plog(XLOG_WARNING, "Could not disassociate tty (TIOCNOTTY): %m");
+ else
+ plog(XLOG_INFO, "released controlling tty using ioctl(TIOCNOTTY)");
+ close(fd);
+ }
+ return;
+#endif /* not TIOCNOTTY */
+
+ plog(XLOG_ERROR, "unable to release controlling tty");
+}
OpenPOWER on IntegriCloud