diff options
Diffstat (limited to 'contrib/amd/libamu')
-rw-r--r-- | contrib/amd/libamu/amu.h | 78 | ||||
-rw-r--r-- | contrib/amd/libamu/hasmntopt.c | 119 | ||||
-rw-r--r-- | contrib/amd/libamu/misc_rpc.c | 168 | ||||
-rw-r--r-- | contrib/amd/libamu/mount_fs.c | 892 | ||||
-rw-r--r-- | contrib/amd/libamu/mtab.c | 121 | ||||
-rw-r--r-- | contrib/amd/libamu/nfs_prot_xdr.c | 59 | ||||
-rw-r--r-- | contrib/amd/libamu/util.c | 176 | ||||
-rw-r--r-- | contrib/amd/libamu/wire.c | 404 | ||||
-rw-r--r-- | contrib/amd/libamu/xdr_func.c | 1155 | ||||
-rw-r--r-- | contrib/amd/libamu/xutil.c | 825 |
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"); +} |