[comp.sources.unix] v21i094: An Automounter for NFS systems, Part06/13

rsalz@uunet.uu.net (Rich Salz) (04/11/90)

Submitted-by: Jan-Simon Pendry <jsp@doc.ic.ac.uk>
Posting-number: Volume 21, Issue 94
Archive-name: amd/part06

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 6 (of 13)."
# Contents:  INSTALL misc_rpc.c nfs_prot_xdr.c nfs_start.c nfs_stubs.c
#   rpc_fwd.c
# Wrapped by rsalz@papaya.bbn.com on Tue Apr 10 15:12:06 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'INSTALL'\"
else
echo shar: Extracting \"'INSTALL'\" \(7869 characters\)
sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
XInstallation Notes for Amd.
X
XNOTE: Please read all of this before starting.
X      It is not very long and may save you time in the long term.
X
X1.  ``Getting started...''
X
XIf you got this release in a shar file then run the shell script Configure in
Xthe top directory.  If you got this release in a tar file then you are all
Xset (though if you feel left out you can type run Configure anyway).
X
X2.  ``Find out what version of UN*X you are running...''
X
XTo install Amd you need a port for your version of UN*X.  In this directory
Xare several files called os-*.h.  One of these should correspond to your
Xversion of UN*X.  Look at the comments at the top of each file to determine
Xwhich one applies to you.  If none of them do, then either no-one has yet
Xdone a port, or your version of UN*X is so braindead that a port is not
Xpossible (e.g. System V without reliable signals).  Run the program "os-type"
Xin the current directory to see whether you and Amd are in agreement about
Xyour operating system type.  The current known operating systems (grouped by
Xarchitecture) are:
X
X	acis43			ACIS 4.3BSD on an IBM RT/PC
X	bsd44			4.4 BSD on a Tahoe (or Vax)
X	concentrix		Concentrix on an Alliant
X	hlh42			4.2 BSD on HLH Orion 1/05
X	hpux			HP-UX 6.* on a HP9000/300
X	riscix			4.3 BSD on an Acorn Archimedes
X	sos3, sos4		SunOS 3.x and 4.* on a Sun-3 and Sun-4
X	u2_2			Ultrix 2.2 (or 2.*?) on a VAX
X	u3_0			Ultrix 3.0 (or 3.*?) on a VAX
X	umax43			4.3 BSD on an Encore Multimax
X	utx32			UTX/32 Rel2.1a on a Gould (not yet complete)
X	xinu43			More/BSD (4.3 BSD) on a VAX or HP9000/300
X
XIf you do define a new operating system type foo, you may care to create a
Xfile called Makefile.foo which defines the special Makefile parameters.
X
X3.  ``Hacking the Makefile...''
X
XSome UN*X programs come with a Makefile which has to be manually configured
Xfor your particular operating system and hardware.  However, Amd tries very
Xhard to determine what type of machine you are using and how best to compile
Xitself.  If this does not work then you will have to find some heuristic
Xwhich can differentiate your configuration.  You may need to edit "arch" and
X"os-type".  If you do make sure your changes can cope if /etc/motd is missing
Xand please send it to the address below.
X
XYou may care to tailor some site specific preferences in "Makefile.com".  The
Xvariables most likely to be changes are at the top.  Any changes are best put
Xin the file Makefile.local (if they are applicable to all operating systems
Xat your site) or Makefile.local.foo (where foo is the OS type as determined
Xin part 1).
X
XAdditionally, some configuration options may be altered in "Makefile.config".
XThis means that you should not need to edit any distributed files apart from
X"Makefile.config".  As a minimum, you should check:
X
X* You are using the correct C compiler.  Amd, as shipped, does not use GCC.
X  Note that using GCC version 1.34 or later (e.g. 1.36) gives structure
X  passing problems with some parts of Sun's RPC library at least on Sun-4's.
X  The current workaround is to use the system CC to compile the part of the
X  automounter that gets hit by this problem.  [[This is not the same problem
X  that is fixed by -fpcc-struct-return.]]  Amd contains no "register"
X  declarations, so using old PCC based code generators is probably bad news.
X
X* The installation directory (ETC) is set up correctly.
X
X* If you are running tests then it may be worth switching on the DEBUG flag
X  which will cause a running commentary to be printed to the log file.
X
X4.  ``Build the executable...''
X
XNow you need to compile the automounter.  To do this you type:
X
X	make
X
XIf you are porting to a new machine you may want to do:
X
X	make OS=foo
X
Xwhere foo is the name of your version of UN*X as determined in part 1, until
Xyou have made the changes to os-type and/or arch.  When the compilation is
Xcomplete you will end up with a program called "arch.foo/Amd".
X
XTry running:
X
X	arch.foo/Amd -v
X
Xand check the output.  It should look something like:
X
X  amd 5.1.1.6 of 90/01/10 17:30:40 Rel5.1c #0: Wed Jan 10 17:38:34 GMT 1990
X  Built by jsp@elsinore.doc.ic.ac.uk for an ibm032 running acis43 (big-endian)
X  Map support for: root, hesiod, error.
X
XMake sure the O/S and architecture types were correctly derived during the
Xbuild.
X
XNOTE: If you are building for Ultrix 2.2 then you *may* need to use the
Xsystem V make (s5make) or GNU make instead of /bin/make.  To do that run:
X
X	make MAKE=s5make
Xor
X	make MAKE=gmake
X
X5.  ``Installation...''
X
XIf you are not just testing Amd, then you can install it by typing:
X
X	make install
X
Xto install "arch.foo/Amd" in "/usr/local/etc/Amd" (or as otherwise
Xmodified in part 2).
X
X6.  ``Update /etc/rpc''
X
XAmq uses Sun RPC to talk to Amd using program number 300019 which has
Xbeen registered with Sun.  Add the following lines to /etc/rpc or your
XYP or Hesiod master:
X
X# Automount control protocol
Xamd	300019	amq
X
X7.  ``Hanging your machine...''
X
XWARNING:  THIS MAY HANG YOUR MACHINE IF YOU GET IT WRONG.
X
XRunning Amd with a carelessly thought out mount map can cause your Amd to
Xenter a deadlock inside the kernel.  For example, attempting to automount a
Xdirectory which is automounted can cause the automounter to issue a mount
Xrequest which will cause the kernel to send an NFS request back to the same
Xautomounter, which is currently stuck in a system call and unable to respond
X- even kill -KILL won't get you out of this one.
X
XThere is nothing you can do to fix it without rebooting your machine, so...
X
XFind a diskless workstation and play with that first before trying this on
Xyour main 200 user service machine (unless you hate your users).  Something
Xlike a diskless Sun-4 is best for development testing - you can compile on a
XSun-4 server and run the binary on the diskless node.  They reboot very fast
Xas well between tests.
X
XNow you can try running Amd.  Please read the documentation in doc/Amd.tex
Xfor more details.  The configuration file "a_master" provides a sample for
Xyou to play with.  Something like:
X
X	./Amd -c 40 -D test,nodaemon /tmp/amnt a_master &
X
Xis good for testing.  Note that Amd will clean up correctly if you send it a
XSIGINT or SIGTERM.  Other signals are either ignored or will blow it away,
Xleaving your machine in a potentially dangerous state - usually a reboot is
Xall that is required to fix it though ;-)
X
XRemember that Amd needs to run as root in order to do mounts/unmounts though
Xit does check this condition somewhere near line one of main().  It will also
Xneed write permission in the working directory if you have built it with
XDEBUG defined.  Watch out for NFS stepping in and mapping root to nobody.
X
X8.  ``Report what happened...''
X
XIf anything interesting happened, eg it didn't work, please report it to me
X-- Jan-Simon Pendry <jsp@doc.ic.ac.uk> -- as detailed in the README file.
X
XKNOWN PROBLEMS - Contact me for more details
X
X* Amd does not work correctly on a DecStation 3100 system running Ultrix 3.1.
X  This is a bug in Ultrix.  Quite how the Ultrix mount command works is a
X  total mystery, but in any case the mount system call does not behave as
X  documented.
X
X* It is reported that amd deadlocks the kernel on a Sequent Symmetry.
X  Obviously this is a kernel bug.
X
X* Amd cannot do hierarchical mounts, ie mount two or more filesystems at
X  once. To do this requires resolving some non-trivial issues.  If you think
X  you know what the semantics should be I would like to hear from you.
X  Remember to consider the general case.  The tree of mounts can be composed
X  of any combination of filesystem types, and/or possibly come from several
X  NFS servers any of which may be down at the time of the mount.
X
X  Once the tree is mounted, how does it get unmounted?  Again, what happens
X  if a fileserver is down, or goes down after one of the other filesystems is
X  unmounted?
X
X$Id: INSTALL,v 5.1.1.2 90/01/11 16:45:44 jsp Exp Locker: jsp $
END_OF_FILE
if test 7869 -ne `wc -c <'INSTALL'`; then
    echo shar: \"'INSTALL'\" unpacked with wrong size!
fi
# end of 'INSTALL'
fi
if test -f 'misc_rpc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'misc_rpc.c'\"
else
echo shar: Extracting \"'misc_rpc.c'\" \(8404 characters\)
sed "s/^X//" >'misc_rpc.c' <<'END_OF_FILE'
X/*
X * $Id: misc_rpc.c,v 5.1.1.1 90/01/11 17:08:49 jsp Exp Locker: jsp $
X *
X * Copyright (c) 1990 Jan-Simon Pendry
X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Jan-Simon Pendry at Imperial College, London.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Imperial College of Science, Technology and Medicine, London, UK.
X * The names of the College and University may not be used to endorse
X * or promote products derived from this software without specific
X * prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	%W% (Berkeley) %G%
X */
X
X/*
X * Additions to Sun RPC.
X */
X
X#include "am.h"
X
Xvoid rpc_msg_init P((struct rpc_msg *mp, u_long prog, u_long vers, u_long proc));
Xvoid rpc_msg_init(mp, prog, vers, proc)
Xstruct rpc_msg *mp;
Xunsigned long prog, vers, proc;
X{
X	/*
X	 * Initialise the message
X	 */
X	bzero((voidp) mp, sizeof(*mp));
X	mp->rm_xid = 0;
X	mp->rm_direction = CALL;
X	mp->rm_call.cb_rpcvers = RPC_MSG_VERSION;
X	mp->rm_call.cb_prog = prog;
X	mp->rm_call.cb_vers = vers;
X	mp->rm_call.cb_proc = proc;
X}
X
X/*
X * Field reply to call to mountd
X */
Xint pickup_rpc_reply P((voidp pkt, int len, voidp where, xdrproc_t where_xdr));
Xint pickup_rpc_reply(pkt, len, where, where_xdr)
Xvoidp pkt;
Xint len;
Xvoidp where;
Xxdrproc_t where_xdr;
X{
X	XDR reply_xdr;
X	int ok;
X	struct rpc_err err;
X	struct rpc_msg reply_msg;
X	int error = 0;
X
X	/*bzero((voidp) &err, sizeof(err));*/
X	bzero((voidp) &reply_msg, sizeof(reply_msg));
X
X	reply_msg.acpted_rply.ar_results.where = (caddr_t) where;
X	reply_msg.acpted_rply.ar_results.proc = where_xdr;
X
X	xdrmem_create(&reply_xdr, pkt, len, XDR_DECODE);
X
X	ok = xdr_replymsg(&reply_xdr, &reply_msg);
X	if (!ok) {
X		error = EIO;
X		goto drop;
X	}
X	_seterr_reply(&reply_msg, &err);
X	if (err.re_status != RPC_SUCCESS) {
X		error = EIO;
X		goto drop;
X	}
X
Xdrop:
X	if (reply_msg.acpted_rply.ar_verf.oa_base) {
X		reply_xdr.x_op = XDR_FREE;
X		(void)xdr_opaque_auth(&reply_xdr,
X			&reply_msg.acpted_rply.ar_verf);
X	}
X	xdr_destroy(&reply_xdr);
X
X	return error;
X}
X
Xint make_rpc_packet P((char *buf, int buflen, unsigned long proc,
X			struct rpc_msg *mp, voidp arg, xdrproc_t arg_xdr, AUTH *auth));
Xint make_rpc_packet(buf, buflen, proc, mp, arg, arg_xdr, auth)
Xchar *buf;
Xint buflen;
Xunsigned long proc;
Xstruct rpc_msg *mp;
Xvoidp arg;
Xxdrproc_t arg_xdr;
XAUTH *auth;
X{
X	XDR msg_xdr;
X	int len;
X
X	xdrmem_create(&msg_xdr, buf, buflen, XDR_ENCODE);
X	/*
X	 * Basic protocol header
X	 */
X	if (!xdr_callhdr(&msg_xdr, mp))
X		return -EIO;
X	/*
X	 * Called procedure number
X	 */
X	if (!xdr_enum(&msg_xdr, &proc))
X		return -EIO;
X	/*
X	 * Authorization
X	 */
X	if (!AUTH_MARSHALL(auth, &msg_xdr))
X		return -EIO;
X	/*
X	 * Arguments
X	 */
X	if (!(*arg_xdr)(&msg_xdr, arg))
X		return -EIO;
X	/*
X	 * Determine length
X	 */
X	len = xdr_getpos(&msg_xdr);
X	/*
X	 * Throw away xdr
X	 */
X	xdr_destroy(&msg_xdr);
X	return len;
X}
X
X
X#ifdef MISC_RPC
X/*
X * Early RPC seems to be missing these..
X * Extracted from the RPC 3.9 sources as indicated
X */
X
X/* @(#)xdr_reference.c	1.1 87/11/04 3.9 RPCSRC */
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X
X
X/*
X * xdr_pointer():
X *
X * XDR a pointer to a possibly recursive data structure. This
X * differs with xdr_reference in that it can serialize/deserialiaze
X * trees correctly.
X *
X *  What's sent is actually a union:
X *
X *  union object_pointer switch (boolean b) {
X *  case TRUE: object_data data;
X *  case FALSE: void nothing;
X *  }
X *
X * > objpp: Pointer to the pointer to the object.
X * > obj_size: size of the object.
X * > xdr_obj: routine to XDR an object.
X *
X */
Xbool_t
Xxdr_pointer(xdrs,objpp,obj_size,xdr_obj)
X	register XDR *xdrs;
X	char **objpp;
X	u_int obj_size;
X	xdrproc_t xdr_obj;
X{
X
X	bool_t more_data;
X
X	more_data = (*objpp != NULL);
X	if (! xdr_bool(xdrs,&more_data)) {
X		return (FALSE);
X	}
X	if (! more_data) {
X		*objpp = NULL;
X		return (TRUE);
X	}
X	return (xdr_reference(xdrs,objpp,obj_size,xdr_obj));
X}
X
X/* @(#)clnt_perror.c	1.1 87/11/04 3.9 RPCSRC */
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X
Xstruct rpc_errtab {
X	enum clnt_stat status;
X	char *message;
X};
X
Xstatic struct rpc_errtab  rpc_errlist[] = {
X	{ RPC_SUCCESS, 
X		"RPC: Success" }, 
X	{ RPC_CANTENCODEARGS, 
X		"RPC: Can't encode arguments" },
X	{ RPC_CANTDECODERES, 
X		"RPC: Can't decode result" },
X	{ RPC_CANTSEND, 
X		"RPC: Unable to send" },
X	{ RPC_CANTRECV, 
X		"RPC: Unable to receive" },
X	{ RPC_TIMEDOUT, 
X		"RPC: Timed out" },
X	{ RPC_VERSMISMATCH, 
X		"RPC: Incompatible versions of RPC" },
X	{ RPC_AUTHERROR, 
X		"RPC: Authentication error" },
X	{ RPC_PROGUNAVAIL, 
X		"RPC: Program unavailable" },
X	{ RPC_PROGVERSMISMATCH, 
X		"RPC: Program/version mismatch" },
X	{ RPC_PROCUNAVAIL, 
X		"RPC: Procedure unavailable" },
X	{ RPC_CANTDECODEARGS, 
X		"RPC: Server can't decode arguments" },
X	{ RPC_SYSTEMERROR, 
X		"RPC: Remote system error" },
X	{ RPC_UNKNOWNHOST, 
X		"RPC: Unknown host" },
X/*	{ RPC_UNKNOWNPROTO,
X		"RPC: Unknown protocol" },*/
X	{ RPC_PMAPFAILURE, 
X		"RPC: Port mapper failure" },
X	{ RPC_PROGNOTREGISTERED, 
X		"RPC: Program not registered"},
X	{ RPC_FAILED, 
X		"RPC: Failed (unspecified error)"}
X};
X
X
X/*
X * This interface for use by clntrpc
X */
Xchar *
Xclnt_sperrno(stat)
X	enum clnt_stat stat;
X{
X	int i;
X
X	for (i = 0; i < sizeof(rpc_errlist)/sizeof(struct rpc_errtab); i++) {
X		if (rpc_errlist[i].status == stat) {
X			return (rpc_errlist[i].message);
X		}
X	}
X	return ("RPC: (unknown error code)");
X}
X
X#endif /* MISC_RPC */
X
END_OF_FILE
if test 8404 -ne `wc -c <'misc_rpc.c'`; then
    echo shar: \"'misc_rpc.c'\" unpacked with wrong size!
fi
# end of 'misc_rpc.c'
fi
if test -f 'nfs_prot_xdr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nfs_prot_xdr.c'\"
else
echo shar: Extracting \"'nfs_prot_xdr.c'\" \(9341 characters\)
sed "s/^X//" >'nfs_prot_xdr.c' <<'END_OF_FILE'
X/*
X * $Id: nfs_prot_xdr.c,v 5.1 89/11/17 18:21:28 jsp Exp Locker: jsp $
X *
X * Copyright (c) 1989 Jan-Simon Pendry
X * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
X * Copyright (c) 1989 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Jan-Simon Pendry at Imperial College, London.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Imperial College of Science, Technology and Medicine, London, UK.
X * The names of the College and University may not be used to endorse
X * or promote products derived from this software without specific
X * prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	%W% (Berkeley) %G%
X */
X
X#include "am.h"
X
X
X#ifndef xdr_nfsstat
Xbool_t
Xxdr_nfsstat(xdrs, objp)
X	XDR *xdrs;
X	nfsstat *objp;
X{
X	if (!xdr_enum(xdrs, (enum_t *)objp)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X#endif
X
X
X
X#ifndef xdr_ftype
Xstatic bool_t
Xxdr_ftype(xdrs, objp)
X	XDR *xdrs;
X	ftype *objp;
X{
X	if (!xdr_enum(xdrs, (enum_t *)objp)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X#endif
X
X
X
Xbool_t
Xxdr_nfs_fh(xdrs, objp)
X	XDR *xdrs;
X	nfs_fh *objp;
X{
X	if (!xdr_opaque(xdrs, objp->data, NFS_FHSIZE)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xstatic bool_t
Xxdr_nfstime(xdrs, objp)
X	XDR *xdrs;
X	nfstime *objp;
X{
X	if (!xdr_u_int(xdrs, &objp->seconds)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->useconds)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xstatic bool_t
Xxdr_fattr(xdrs, objp)
X	XDR *xdrs;
X	fattr *objp;
X{
X	if (!xdr_ftype(xdrs, &objp->type)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->mode)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->nlink)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->uid)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->gid)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->size)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->blocksize)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->rdev)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->blocks)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->fsid)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->fileid)) {
X		return (FALSE);
X	}
X	if (!xdr_nfstime(xdrs, &objp->atime)) {
X		return (FALSE);
X	}
X	if (!xdr_nfstime(xdrs, &objp->mtime)) {
X		return (FALSE);
X	}
X	if (!xdr_nfstime(xdrs, &objp->ctime)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xstatic bool_t
Xxdr_sattr(xdrs, objp)
X	XDR *xdrs;
X	sattr *objp;
X{
X	if (!xdr_u_int(xdrs, &objp->mode)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->uid)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->gid)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->size)) {
X		return (FALSE);
X	}
X	if (!xdr_nfstime(xdrs, &objp->atime)) {
X		return (FALSE);
X	}
X	if (!xdr_nfstime(xdrs, &objp->mtime)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xstatic bool_t
Xxdr_filename(xdrs, objp)
X	XDR *xdrs;
X	filename *objp;
X{
X	if (!xdr_string(xdrs, objp, NFS_MAXNAMLEN)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_nfspath(xdrs, objp)
X	XDR *xdrs;
X	nfspath *objp;
X{
X	if (!xdr_string(xdrs, objp, NFS_MAXPATHLEN)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_attrstat(xdrs, objp)
X	XDR *xdrs;
X	attrstat *objp;
X{
X	if (!xdr_nfsstat(xdrs, &objp->status)) {
X		return (FALSE);
X	}
X	switch (objp->status) {
X	case NFS_OK:
X		if (!xdr_fattr(xdrs, &objp->attrstat_u.attributes)) {
X			return (FALSE);
X		}
X		break;
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_sattrargs(xdrs, objp)
X	XDR *xdrs;
X	sattrargs *objp;
X{
X	if (!xdr_nfs_fh(xdrs, &objp->file)) {
X		return (FALSE);
X	}
X	if (!xdr_sattr(xdrs, &objp->attributes)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_diropargs(xdrs, objp)
X	XDR *xdrs;
X	diropargs *objp;
X{
X	if (!xdr_nfs_fh(xdrs, &objp->dir)) {
X		return (FALSE);
X	}
X	if (!xdr_filename(xdrs, &objp->name)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_diropokres(xdrs, objp)
X	XDR *xdrs;
X	diropokres *objp;
X{
X	if (!xdr_nfs_fh(xdrs, &objp->file)) {
X		return (FALSE);
X	}
X	if (!xdr_fattr(xdrs, &objp->attributes)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_diropres(xdrs, objp)
X	XDR *xdrs;
X	diropres *objp;
X{
X	if (!xdr_nfsstat(xdrs, &objp->status)) {
X		return (FALSE);
X	}
X	switch (objp->status) {
X	case NFS_OK:
X		if (!xdr_diropokres(xdrs, &objp->diropres_u.diropres)) {
X			return (FALSE);
X		}
X		break;
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_readlinkres(xdrs, objp)
X	XDR *xdrs;
X	readlinkres *objp;
X{
X	if (!xdr_nfsstat(xdrs, &objp->status)) {
X		return (FALSE);
X	}
X	switch (objp->status) {
X	case NFS_OK:
X		if (!xdr_nfspath(xdrs, &objp->readlinkres_u.data)) {
X			return (FALSE);
X		}
X		break;
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_readargs(xdrs, objp)
X	XDR *xdrs;
X	readargs *objp;
X{
X	if (!xdr_nfs_fh(xdrs, &objp->file)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->offset)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->count)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->totalcount)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_readokres(xdrs, objp)
X	XDR *xdrs;
X	readokres *objp;
X{
X	if (!xdr_fattr(xdrs, &objp->attributes)) {
X		return (FALSE);
X	}
X	if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *)&objp->data.data_len, NFS_MAXDATA)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_readres(xdrs, objp)
X	XDR *xdrs;
X	readres *objp;
X{
X	if (!xdr_nfsstat(xdrs, &objp->status)) {
X		return (FALSE);
X	}
X	switch (objp->status) {
X	case NFS_OK:
X		if (!xdr_readokres(xdrs, &objp->readres_u.reply)) {
X			return (FALSE);
X		}
X		break;
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_writeargs(xdrs, objp)
X	XDR *xdrs;
X	writeargs *objp;
X{
X	if (!xdr_nfs_fh(xdrs, &objp->file)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->beginoffset)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->offset)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->totalcount)) {
X		return (FALSE);
X	}
X	if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *)&objp->data.data_len, NFS_MAXDATA)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_createargs(xdrs, objp)
X	XDR *xdrs;
X	createargs *objp;
X{
X	if (!xdr_diropargs(xdrs, &objp->where)) {
X		return (FALSE);
X	}
X	if (!xdr_sattr(xdrs, &objp->attributes)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_renameargs(xdrs, objp)
X	XDR *xdrs;
X	renameargs *objp;
X{
X	if (!xdr_diropargs(xdrs, &objp->from)) {
X		return (FALSE);
X	}
X	if (!xdr_diropargs(xdrs, &objp->to)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_linkargs(xdrs, objp)
X	XDR *xdrs;
X	linkargs *objp;
X{
X	if (!xdr_nfs_fh(xdrs, &objp->from)) {
X		return (FALSE);
X	}
X	if (!xdr_diropargs(xdrs, &objp->to)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_symlinkargs(xdrs, objp)
X	XDR *xdrs;
X	symlinkargs *objp;
X{
X	if (!xdr_diropargs(xdrs, &objp->from)) {
X		return (FALSE);
X	}
X	if (!xdr_nfspath(xdrs, &objp->to)) {
X		return (FALSE);
X	}
X	if (!xdr_sattr(xdrs, &objp->attributes)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xstatic bool_t
Xxdr_nfscookie(xdrs, objp)
X	XDR *xdrs;
X	nfscookie objp;
X{
X	if (!xdr_opaque(xdrs, objp, NFS_COOKIESIZE)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_readdirargs(xdrs, objp)
X	XDR *xdrs;
X	readdirargs *objp;
X{
X	if (!xdr_nfs_fh(xdrs, &objp->dir)) {
X		return (FALSE);
X	}
X	if (!xdr_nfscookie(xdrs, objp->cookie)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->count)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xstatic bool_t
Xxdr_entry(xdrs, objp)
X	XDR *xdrs;
X	entry *objp;
X{
X	if (!xdr_u_int(xdrs, &objp->fileid)) {
X		return (FALSE);
X	}
X	if (!xdr_filename(xdrs, &objp->name)) {
X		return (FALSE);
X	}
X	if (!xdr_nfscookie(xdrs, objp->cookie)) {
X		return (FALSE);
X	}
X	if (!xdr_pointer(xdrs, (char **)&objp->nextentry, sizeof(entry), xdr_entry)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xstatic bool_t
Xxdr_dirlist(xdrs, objp)
X	XDR *xdrs;
X	dirlist *objp;
X{
X	if (!xdr_pointer(xdrs, (char **)&objp->entries, sizeof(entry), xdr_entry)) {
X		return (FALSE);
X	}
X	if (!xdr_bool(xdrs, &objp->eof)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_readdirres(xdrs, objp)
X	XDR *xdrs;
X	readdirres *objp;
X{
X	if (!xdr_nfsstat(xdrs, &objp->status)) {
X		return (FALSE);
X	}
X	switch (objp->status) {
X	case NFS_OK:
X		if (!xdr_dirlist(xdrs, &objp->readdirres_u.reply)) {
X			return (FALSE);
X		}
X		break;
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_statfsokres(xdrs, objp)
X	XDR *xdrs;
X	statfsokres *objp;
X{
X	if (!xdr_u_int(xdrs, &objp->tsize)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->bsize)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->blocks)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->bfree)) {
X		return (FALSE);
X	}
X	if (!xdr_u_int(xdrs, &objp->bavail)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_statfsres(xdrs, objp)
X	XDR *xdrs;
X	statfsres *objp;
X{
X	if (!xdr_nfsstat(xdrs, &objp->status)) {
X		return (FALSE);
X	}
X	switch (objp->status) {
X	case NFS_OK:
X		if (!xdr_statfsokres(xdrs, &objp->statfsres_u.reply)) {
X			return (FALSE);
X		}
X		break;
X	}
X	return (TRUE);
X}
END_OF_FILE
if test 9341 -ne `wc -c <'nfs_prot_xdr.c'`; then
    echo shar: \"'nfs_prot_xdr.c'\" unpacked with wrong size!
fi
# end of 'nfs_prot_xdr.c'
fi
if test -f 'nfs_start.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nfs_start.c'\"
else
echo shar: Extracting \"'nfs_start.c'\" \(7449 characters\)
sed "s/^X//" >'nfs_start.c' <<'END_OF_FILE'
X/*
X * $Id: nfs_start.c,v 5.1.1.2 90/01/11 17:13:06 jsp Exp Locker: jsp $
X *
X * Copyright (c) 1990 Jan-Simon Pendry
X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Jan-Simon Pendry at Imperial College, London.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Imperial College of Science, Technology and Medicine, London, UK.
X * The names of the College and University may not be used to endorse
X * or promote products derived from this software without specific
X * prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	%W% (Berkeley) %G%
X */
X
X#include "am.h"
X#include "amq.h"
X#include <sys/signal.h>
X#include <setjmp.h>
Xextern jmp_buf select_intr;
Xextern int select_intr_valid;
X
X#ifdef HAS_TFS
X/*
X * Use replacement for RPC/UDP transport
X * so that we do NFS gatewaying.
X */
X#define	svcudp_create svcudp2_create
Xextern SVCXPRT *svcudp2_create P((int));
X#endif
X
Xextern void nfs_program_2();
Xextern void amq_program_1();
X
Xunsigned short nfs_port;
XSVCXPRT *nfsxprt;
X
Xextern int fwd_sock;
X
X#ifndef NFDS
Xstatic int nfds = -1;
X#ifdef FD_SET
X#define	NFDS (nfds < 0 ? nfds = getdtablesize() : nfds)
X#else
X#define NFDS (sizeof(int) * 8)
X#endif
X#endif
X
X#define	MASKED_SIGS	(sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
X
X#ifdef DEBUG
X/*
X * Check that we are not burning resources
X */
Xstatic void checkup(P_void)
X{
X
Xstatic int max_fd = 0;
Xstatic char *max_mem = 0;
X
X	int next_fd = dup(0);
X	extern caddr_t sbrk P((int));
X	caddr_t next_mem = sbrk(0);
X	close(next_fd);
X
X	/*if (max_fd < 0) {
X		max_fd = next_fd;
X	} else*/ if (max_fd < next_fd) {
X		dlog("%d new fds allocated; total is %d",
X			next_fd - max_fd, next_fd);
X		max_fd = next_fd;
X	}
X
X	/*if (max_mem == 0) {
X		max_mem = next_mem;
X	} else*/ if (max_mem < next_mem) {
X		dlog("%#x bytes of memory allocated; total is %#x (%d pages)",
X			next_mem - max_mem,
X			next_mem,
X			((int)next_mem+getpagesize()-1)/getpagesize());
X		max_mem = next_mem;
X	}
X}
X#endif
X
Xstatic int do_select(smask, fds, fdp, tvp)
Xint smask;
Xint fds;
Xint *fdp;
Xstruct timeval *tvp;
X{
X	int sig;
X	int nsel;
X	if (sig = setjmp(select_intr)) {
X		select_intr_valid = 0;
X		/* Got a signal */
X		switch (sig) {
X		case SIGINT:
X		case SIGTERM:
X			amd_state = Finishing;
X			reschedule_timeout_mp();
X			break;
X		}
X		nsel = -1;
X		errno = EINTR;
X	} else {
X		select_intr_valid = 1;
X		/*
X		 * Invalidate the current clock value
X		 */
X		clock_valid = 0;
X		/*
X		 * Allow interrupts.  If a signal
X		 * occurs, then it will cause a longjmp
X		 * up above.
X		 */
X		(void) sigsetmask(smask);
X		/*
X		 * Wait for input
X		 */
X		nsel = select(fds, fdp, (int *) 0, (int *) 0,
X				tvp->tv_sec ? tvp : (struct timeval *) 0);
X
X	}
X
X	(void) sigblock(MASKED_SIGS);
X
X	/*
X	 * Perhaps reload the cache?
X	 */
X	if (do_mapc_reload < clocktime()) {
X		mapc_reload();
X		do_mapc_reload = clocktime() + ONE_HOUR;
X	}
X	return nsel;
X}
X
Xstatic serv_state run_rpc(P_void)
X{
X	int dtbsz = NFDS;
X	int smask = sigblock(MASKED_SIGS);
X
X	next_softclock = clocktime();
X
X	amd_state = Run;
X
X	/*
X	 * Keep on trucking while we are in Run mode.  This state
X	 * is switched to Quit after all the file systems have
X	 * been unmounted.
X	 */
X	while ((int)amd_state <= (int)Finishing) {
X		struct timeval tvv;
X		int nsel;
X		time_t now;
X#ifdef RPC_4
X		fd_set readfds;
X		readfds = svc_fdset;
X		FD_SET(fwd_sock, &readfds);
X#else
X#ifdef FD_SET
X		fd_set readfds;
X		FD_ZERO(&readfds);
X		readfds.fds_bits[0] = svc_fds;
X		FD_SET(fwd_sock, &readfds);
X#else
X		int readfds = svc_fds | (1 << fwd_sock);
X#endif /* FD_SET */
X#endif /* RPC_4 */
X
X#ifdef DEBUG
X		checkup();
X#endif
X
X		/*
X		 * If the full timeout code is not called,
X		 * then recompute the time delta manually.
X		 */
X		now = clocktime();
X
X		if (next_softclock <= now) {
X			if (amd_state == Finishing)
X				umount_exported();
X			tvv.tv_sec = softclock();
X		} else {
X			tvv.tv_sec = next_softclock - now;
X		}
X		tvv.tv_usec = 0;
X
X		if (amd_state == Finishing && last_used_map < 0) {
X			flush_mntfs();
X			amd_state = Quit;
X			break;
X		}
X
X#ifdef DEBUG
X		if (tvv.tv_sec)
X			dlog("Select waits for %ds", tvv.tv_sec);
X		else
X			dlog("Select waits for Godot");
X#endif
X
X		nsel = do_select(smask, dtbsz, &readfds, &tvv);
X
X
X		switch (nsel) {
X		case -1:
X			if (errno == EINTR) {
X#ifdef DEBUG
X				dlog("select interrupted");
X#endif
X				continue;
X			}
X			perror("select");
X			break;
X
X		case 0:
X#ifdef DEBUG
X			/*dlog("select returned 0");*/
X#endif
X			break;
X
X		default:
X#ifdef FD_SET
X			if (FD_ISSET(fwd_sock, &readfds)) {
X				FD_CLR(fwd_sock, &readfds);
X				fwd_reply();
X				--nsel;
X			}
X#else
X			if (readfds & (1 << fwd_sock)) {
X				readfds &= ~(1 << fwd_sock);
X				fwd_reply();
X				--nsel;
X			}
X#endif
X
X			if (nsel) {
X				/*
X				 * Anything left must be a normal
X				 * RPC request.
X				 */
X#ifdef RPC_4
X				svc_getreqset(&readfds);
X#else
X#ifdef FD_SET
X				svc_getreq(readfds.fds_bits[0]);
X#else
X				svc_getreq(readfds);
X#endif
X#endif
X			}
X			break;
X		}
X	}
X
X	(void) sigsetmask(smask);
X
X	if (amd_state == Quit)
X		amd_state = Done;
X
X	return amd_state;
X}
X
Xstatic int bindnfs_port(so)
Xint so;
X{
X	unsigned short port;
X	int error = bind_resv_port(so, &port);
X	if (error == 0)
X		nfs_port = port;
X	return error;
X}
X
Xvoid unregister_amq(P_void)
X{
X#ifdef DEBUG
X	Debug(D_AMQ)
X#endif
X	(void) pmap_unset(AMQ_PROGRAM, AMQ_VERSION);
X}
X
Xint mount_automounter(ppid)
Xint ppid;
X{
X	int so = socket(AF_INET, SOCK_DGRAM, 0);
X	SVCXPRT *amqp;
X	int nmount;
X
X	unregister_amq();
X
X	if (so < 0 || bindnfs_port(so) < 0) {
X		perror("Can't create privileged nfs port");
X		return 1;
X	}
X
X	if ((nfsxprt = svcudp_create(so)) == NULL || 
X			(amqp = svcudp_create(so)) == NULL) {
X		plog(XLOG_FATAL, "cannot create rpc/udp service");
X		return 2;
X	}
X
X	if (!svc_register(nfsxprt, NFS_PROGRAM, NFS_VERSION, nfs_program_2, 0)) {
X		plog(XLOG_FATAL, "unable to register (NFS_PROGRAM, NFS_VERSION, 0)");
X		return 3;
X	}
X
X#ifdef DEBUG
X	Debug(D_AMQ)
X#endif
X	if (!svc_register(amqp, AMQ_PROGRAM, AMQ_VERSION, amq_program_1, IPPROTO_UDP)) {
X		plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM, AMQ_VERSION, udp)");
X		return 3;
X	}
X
X	/*
X	 * Start RPC forwarding
X	 */
X	if (fwd_init() != 0)
X		return 3;
X
X	/*
X	 * Construct the root automount node
X	 */
X	make_root_node();
X
X	/*
X	 * Pick up the pieces from a previous run
X	 * This is likely to (indirectly) need the rpc_fwd package
X	 * so it *must* come after the call to fwd_init().
X	 */
X	if (restart_existing_mounts)
X		restart();
X
X	/*
X	 * Mount the top-level auto-mountpoints
X	 */
X	nmount = mount_exported();
X
X	/*
X	 * Now safe to tell parent that we are up and running
X	 */
X	if (ppid)
X		kill(ppid, SIGQUIT);
X
X	if (nmount == 0) {
X		plog(XLOG_FATAL, "No work to do - quitting");
X		amd_state = Done;
X		return 0;
X	}
X
X	/*
X	 * Start timeout_mp rolling
X	 */
X	reschedule_timeout_mp();
X
X	/*
X	 * Start the server
X	 */
X	if (run_rpc() != Done) {
X		plog(XLOG_FATAL, "run_rpc failed");
X		amd_state = Done;
X	}
X
X	return 0;
X}
END_OF_FILE
if test 7449 -ne `wc -c <'nfs_start.c'`; then
    echo shar: \"'nfs_start.c'\" unpacked with wrong size!
fi
# end of 'nfs_start.c'
fi
if test -f 'nfs_stubs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nfs_stubs.c'\"
else
echo shar: Extracting \"'nfs_stubs.c'\" \(9501 characters\)
sed "s/^X//" >'nfs_stubs.c' <<'END_OF_FILE'
X/*
X * $Id: nfs_stubs.c,v 5.1.1.2 90/01/11 17:14:34 jsp Exp Locker: jsp $
X *
X * Copyright (c) 1990 Jan-Simon Pendry
X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Jan-Simon Pendry at Imperial College, London.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Imperial College of Science, Technology and Medicine, London, UK.
X * The names of the College and University may not be used to endorse
X * or promote products derived from this software without specific
X * prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	%W% (Berkeley) %G%
X */
X
X#include "am.h"
X
X/*
X * Convert from UN*X to NFS error code
X */
X#ifdef NFS_ERROR_MAPPING
XNFS_ERROR_MAPPING
X#define nfs_error(e) \
X        ((nfsstat)((e) > NFS_LOMAP && (e) < NFS_HIMAP ? \
X        nfs_errormap[(e) - NFS_LOMAP] : (e)))
X#else
X#define nfs_error(e) ((nfsstat)(e))
X#endif
X
Xstatic char *do_readlink(mp, error_return)
Xam_node *mp;
Xint *error_return;
X{
X	/*
X	 * If there is a readlink method, then use
X	 * that, otherwise if a link exists use
X	 * that, otherwise use the mount point.
X	 */
X	if (mp->am_mnt->mf_ops->readlink) {
X		int retry = 0;
X		char *ln = (*mp->am_mnt->mf_ops->readlink)(mp, &retry);
X		if (ln == 0)
X			*error_return = retry;
X		/*reschedule_timeout_mp();*/
X		return ln;
X	} else if (mp->am_link) {
X		return mp->am_link;
X	} else {
X		return mp->am_mnt->mf_mount;
X	}
X}
X
X/*ARGSUSED*/
Xvoidp 
Xnfsproc_null_2(argp, rqstp)
Xvoidp argp;
Xstruct svc_req *rqstp;
X{
X	static char res;
X
X	return (voidp) &res;
X}
X
X
X/*ARGSUSED*/
Xstruct attrstat *
Xnfsproc_getattr_2(argp, rqstp)
Xstruct nfs_fh *argp;
Xstruct svc_req *rqstp;
X{
X	static struct attrstat res;
X	am_node *mp;
X	int retry;
X
X#ifdef DEBUG
X	Debug(D_TRACE)
X		plog(XLOG_DEBUG, "gettattr:");
X#endif
X
X	mp = fh_to_mp2(argp, &retry);
X	if (mp == 0) {
Xgetattr_retry:
X		if (retry < 0)
X			return 0;
X		res.status = nfs_error(retry);
X	} else {
X		if (mp->am_mnt->mf_fattr.type == NFLNK) {
X			/*
X			 * Make sure we can read the link
X			 */
X			char *ln = do_readlink(mp, &retry);
X			if (ln == 0)
X				goto getattr_retry;
X			mp->am_mnt->mf_fattr.size = strlen(ln);
X		}
X#ifdef DEBUG
X		Debug(D_TRACE)
X			plog(XLOG_DEBUG, "\tstat(%s), size = %d", mp->am_path, mp->am_mnt->mf_fattr.size);
X#endif
X		mp->am_stats.s_getattr++;
X		return &mp->am_mnt->mf_attr;
X	}
X
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xstruct attrstat *
Xnfsproc_setattr_2(argp, rqstp)
Xstruct sattrargs *argp;
Xstruct svc_req *rqstp;
X{
X	static struct attrstat res;
X
X	if (!fh_to_mp(&argp->file))
X		res.status = nfs_error(ESTALE);
X	else
X		res.status = nfs_error(EROFS);
X
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xvoidp 
Xnfsproc_root_2(argp, rqstp)
Xvoidp argp;
Xstruct svc_req *rqstp;
X{
X	static char res;
X
X	return (voidp)&res;
X}
X
X
X/*ARGSUSED*/
Xstruct diropres *
Xnfsproc_lookup_2(argp, rqstp)
Xstruct diropargs *argp;
Xstruct svc_req *rqstp;
X{
X	static struct diropres res;
X	am_node *mp;
X	int retry;
X
X#ifdef DEBUG
X	Debug(D_TRACE)
X		plog(XLOG_DEBUG, "lookup:");
X#endif
X
X	mp = fh_to_mp2(&argp->dir, &retry);
X	if (mp == 0) {
X		if (retry < 0)
X			return 0;
X		res.status = nfs_error(retry);
X	} else {
X		int error;
X		am_node *ap;
X#ifdef DEBUG
X		Debug(D_TRACE)
X			plog(XLOG_DEBUG, "\tlookuppn(%s, %s)", mp->am_path, argp->name);
X#endif
X		ap = (*mp->am_mnt->mf_ops->lookuppn)(mp, argp->name, &error, VLOOK_CREATE);
X		if (ap == 0) {
X			if (error < 0) {
X#ifdef DEBUG
X				dlog("Not sending RPC reply");
X#endif
X				amd_stats.d_drops++;
X				return 0;
X			}
X			res.status = nfs_error(error);
X		} else {
X#ifdef DEBUG
X			if (ap->am_mnt->mf_fattr.size < 0)
X				dlog("\tERROR: size = %d!", ap->am_mnt->mf_fattr.size);
X#endif
X			mp_to_fh(ap, &res.diropres_u.diropres.file);
X			res.diropres_u.diropres.attributes = ap->am_mnt->mf_fattr;
X			res.status = nfs_error(0);
X		}
X		mp->am_stats.s_lookup++;
X		/*reschedule_timeout_mp();*/
X	}
X
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xstruct readlinkres *
Xnfsproc_readlink_2(argp, rqstp)
Xstruct nfs_fh *argp;
Xstruct svc_req *rqstp;
X{
X	static struct readlinkres res;
X	am_node *mp;
X	int retry;
X
X#ifdef DEBUG
X	Debug(D_TRACE)
X		plog(XLOG_DEBUG, "readlink:");
X#endif
X
X	mp = fh_to_mp2(argp, &retry);
X	if (mp == 0) {
X		if (retry < 0)
X			return 0;
X		res.status = nfs_error(retry);
X	} else {
X		char *ln = do_readlink(mp, &retry);
X		if (ln == 0) {
X			if (retry < 0)
X				return 0;
X			res.status = nfs_error(retry);
X		} else {
X			res.status = NFS_OK;
X		}
X#ifdef DEBUG
X		Debug(D_TRACE)
X			if (ln)
X				plog(XLOG_DEBUG, "\treadlink(%s) = %s", mp->am_path, ln);
X#endif
X		res.readlinkres_u.data = ln;
X		mp->am_stats.s_readlink++;
X	}
X
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xstruct readres *
Xnfsproc_read_2(argp, rqstp)
Xstruct readargs *argp;
Xstruct svc_req *rqstp;
X{
X	static struct readres res;
X
X	bzero((char *)&res, sizeof(res));
X
X	res.status = nfs_error(EACCES);
X
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xvoidp 
Xnfsproc_writecache_2(argp, rqstp)
Xvoidp argp;
Xstruct svc_req *rqstp;
X{
X	static char res;
X
X	return (voidp) &res;
X}
X
X
X/*ARGSUSED*/
Xstruct attrstat *
Xnfsproc_write_2(argp, rqstp)
Xwriteargs *argp;
Xstruct svc_req *rqstp;
X{
X	static struct attrstat res;
X
X	if (!fh_to_mp(&argp->file))
X		res.status = nfs_error(ESTALE);
X	else
X		res.status = nfs_error(EROFS);
X
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xstruct diropres *
Xnfsproc_create_2(argp, rqstp)
Xcreateargs *argp;
Xstruct svc_req *rqstp;
X{
X	static struct diropres res;
X
X	if (!fh_to_mp(&argp->where.dir))
X		res.status = nfs_error(ESTALE);
X	else
X		res.status = nfs_error(EROFS);
X
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xstatic nfsstat *
Xunlink_or_rmdir(argp, rqstp, unlinkp)
Xstruct diropargs *argp;
Xstruct svc_req *rqstp;
X{
X	static nfsstat res;
X	int retry;
X	mntfs *mf;
X	am_node *mp = fh_to_mp3(&argp->dir, &retry, VLOOK_DELETE);
X	if (mp == 0) {
X		if (retry < 0)
X			return 0;
X		res = nfs_error(retry);
X		goto out;
X	}
X	mf = mp->am_mnt;
X	if (mf->mf_fattr.type != NFDIR) {
X		res = nfs_error(ENOTDIR);
X		goto out;
X	}
X#ifdef DEBUG
X	Debug(D_TRACE)
X		plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->name);
X#endif
X	mp = (*mp->am_mnt->mf_ops->lookuppn)(mp, argp->name, &retry, VLOOK_DELETE);
X	if (mp == 0) {
X		/*
X		 * Ignore retries...
X		 */
X		if (retry < 0)
X			retry = 0;
X		/*
X		 * Usual NFS workaround...
X		 */
X		else if (retry == ENOENT)
X			retry = 0;
X		res = nfs_error(retry);
X	} else {
X		forcibly_timeout_mp(mp);
X		res = NFS_OK;
X	}
X
Xout:
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xnfsstat *
Xnfsproc_remove_2(argp, rqstp)
Xstruct diropargs *argp;
Xstruct svc_req *rqstp;
X{
X	return unlink_or_rmdir(argp, rqstp, 1);
X}
X
X/*ARGSUSED*/
Xnfsstat *
Xnfsproc_rename_2(argp, rqstp)
Xrenameargs *argp;
Xstruct svc_req *rqstp;
X{
X	static nfsstat res;
X	if (!fh_to_mp(&argp->from.dir) || !fh_to_mp(&argp->to.dir))
X		res = nfs_error(ESTALE);
X	else
X		res = nfs_error(EROFS);
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xnfsstat *
Xnfsproc_link_2(argp, rqstp)
Xlinkargs *argp;
Xstruct svc_req *rqstp;
X{
X	static nfsstat res;
X	if (!fh_to_mp(&argp->from) || !fh_to_mp(&argp->to.dir))
X		res = nfs_error(ESTALE);
X	else
X		res = nfs_error(EROFS);
X
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xnfsstat *
Xnfsproc_symlink_2(argp, rqstp)
Xsymlinkargs *argp;
Xstruct svc_req *rqstp;
X{
X	static nfsstat res;
X	if (!fh_to_mp(&argp->from.dir))
X		res = nfs_error(ESTALE);
X	else
X		res = nfs_error(EROFS);
X
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xstruct diropres *
Xnfsproc_mkdir_2(argp, rqstp)
Xcreateargs *argp;
Xstruct svc_req *rqstp;
X{
X	static struct diropres res;
X	if (!fh_to_mp(&argp->where.dir))
X		res.status = nfs_error(ESTALE);
X	else
X		res.status = nfs_error(EROFS);
X
X	return &res;
X}
X
X
X/*ARGSUSED*/
Xnfsstat *
Xnfsproc_rmdir_2(argp, rqstp)
Xstruct diropargs *argp;
Xstruct svc_req *rqstp;
X{
X	return unlink_or_rmdir(argp, rqstp, 0);
X}
X
X
X/*ARGSUSED*/
Xstruct readdirres *
Xnfsproc_readdir_2(argp, rqstp)
Xreaddirargs *argp;
Xstruct svc_req *rqstp;
X{
X	static readdirres res;
X	static entry e_res[2];
X	am_node *mp;
X	int retry;
X
X#ifdef DEBUG
X	Debug(D_TRACE)
X		plog(XLOG_DEBUG, "readdir:");
X#endif
X
X	mp = fh_to_mp2(&argp->dir, &retry);
X	if (mp == 0) {
X		if (retry < 0)
X			return 0;
X		res.status = nfs_error(retry);
X	} else {
X#ifdef DEBUG
X		Debug(D_TRACE)
X			plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path);
X#endif
X		res.status = nfs_error((*mp->am_mnt->mf_ops->readdir)(mp, argp->cookie,
X					&res.readdirres_u.reply, e_res));
X		mp->am_stats.s_readdir++;
X	}
X
X	/* XXX - need to take argp->count into account */
X
X	return &res;
X}
X
X/*ARGSUSED*/
Xstruct statfsres *
Xnfsproc_statfs_2(argp, rqstp)
Xstruct nfs_fh *argp;
Xstruct svc_req *rqstp;
X{
X	static statfsres res;
X	am_node *mp;
X	int retry;
X
X#ifdef DEBUG
X	Debug(D_TRACE)
X		plog(XLOG_DEBUG, "statfs:");
X#endif
X
X	mp = fh_to_mp2(argp, &retry);
X	if (mp == 0) {
X		if (retry < 0)
X			return 0;
X		res.status = nfs_error(retry);
X	} else {
X		statfsokres *fp;
X#ifdef DEBUG
X		Debug(D_TRACE)
X			plog(XLOG_DEBUG, "\tstat_fs(%s)", mp->am_path);
X#endif
X		/*
X		 * just return faked up file system information
X		 */
X
X		fp = &res.statfsres_u.reply;
X
X		fp->tsize = 1024;
X		fp->bsize = 4192;
X		fp->blocks = 0;
X		fp->bfree = 0;
X		fp->bavail = 0;
X
X		res.status = NFS_OK;
X		mp->am_stats.s_statfs++;
X	}
X
X	return &res;
X}
END_OF_FILE
if test 9501 -ne `wc -c <'nfs_stubs.c'`; then
    echo shar: \"'nfs_stubs.c'\" unpacked with wrong size!
fi
# end of 'nfs_stubs.c'
fi
if test -f 'rpc_fwd.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rpc_fwd.c'\"
else
echo shar: Extracting \"'rpc_fwd.c'\" \(8861 characters\)
sed "s/^X//" >'rpc_fwd.c' <<'END_OF_FILE'
X/*
X * $Id: rpc_fwd.c,v 5.1 89/11/17 18:22:04 jsp Exp Locker: jsp $
X *
X * Copyright (c) 1989 Jan-Simon Pendry
X * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
X * Copyright (c) 1989 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Jan-Simon Pendry at Imperial College, London.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Imperial College of Science, Technology and Medicine, London, UK.
X * The names of the College and University may not be used to endorse
X * or promote products derived from this software without specific
X * prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	%W% (Berkeley) %G%
X */
X
X/*
X * RPC packet forwarding
X */
X
X#include "am.h"
X#include <sys/ioctl.h>
X#ifndef F_SETFL
X#include <fcntl.h>
X#endif
X#ifndef FNDELAY
X#include <sys/file.h>
X#endif
X
X/*
X * Note that the ID field in the external packet is only
X * ever treated as a 32 bit opaque data object, so there
X * is no need to convert to and from network byte ordering.
X */
X
X/*
X * Each pending reply has an rpc_forward structure
X * associated with it.  These have a 15 second lifespan.
X * If a new structure is required, then an expired
X * one will be re-allocated if available, otherwise a fresh
X * one is allocated.  Whenever a reply is received the
X * structure is discarded.
X */
Xtypedef struct rpc_forward rpc_forward;
Xstruct rpc_forward {
X	qelem	rf_q;		/* Linked list */
X	time_t	rf_ttl;		/* Time to live */
X	u_int	rf_xid;		/* Packet id */
X	u_int	rf_oldid;	/* Original packet id */
X	fwd_fun	rf_fwd;		/* Forwarding function */
X	voidp	rf_ptr;
X	struct sockaddr_in rf_sin;
X};
X
X/*
X * Head of list of pending replies
X */
Xextern qelem rpc_head;
Xqelem rpc_head = { &rpc_head, &rpc_head };
X
Xstatic u_int xid;
X#define	XID_ALLOC()	(xid++)
X
X#define	MAX_PACKET_SIZE	8192	/* Maximum UDP packet size */
X
Xint fwd_sock;
X
X/*
X * Allocate a rely structure
X */
Xstatic rpc_forward *fwd_alloc()
X{
X	time_t now = clocktime();
X	rpc_forward *p = 0, *p2;
X
X#ifdef DEBUG
X	/*dlog("fwd_alloca: rpc_head = %#x", rpc_head.q_forw);*/
X#endif
X	/*
X	 * First search for an existing expired one.
X	 */
X	ITER(p2, rpc_forward, &rpc_head) {
X		if (p2->rf_ttl <= now) {
X			p = p2;
X			break;
X		}
X	}
X
X	/*
X	 * If one couldn't be found then allocate
X	 * a new structure and link it at the
X	 * head of the list.
X	 */
X	if (p) {
X		/*
X		 * Call forwarding function to say that
X		 * this message was junked.
X		 */
X#ifdef DEBUG
X		dlog("Re-using packet forwarding slot - id %#x", p->rf_xid);
X#endif
X		if (p->rf_fwd)
X			(*p->rf_fwd)(0, 0, 0, &p->rf_sin, p->rf_ptr, FALSE);
X		rem_que(&p->rf_q);
X	} else {
X		p = ALLOC(rpc_forward);
X	}
X	ins_que(&p->rf_q, &rpc_head);
X
X	/*
X	 * Set the time to live field
X	 * Timeout in 43 seconds 
X	 */
X	p->rf_ttl = now + 43;
X
X#ifdef DEBUG
X	/*dlog("fwd_alloca: rpc_head = %#x", rpc_head.q_forw);*/
X#endif
X	return p;
X}
X
X/*
X * Free an allocated reply structure.
X * First unlink it from the list, then
X * discard it.
X */
Xstatic void fwd_free(p)
Xrpc_forward *p;
X{
X#ifdef DEBUG
X	/*dlog("fwd_free: rpc_head = %#x", rpc_head.q_forw);*/
X#endif
X	rem_que(&p->rf_q);
X#ifdef DEBUG
X	/*dlog("fwd_free: rpc_head = %#x", rpc_head.q_forw);*/
X#endif
X	free(p);
X}
X
X/*
X * Initialise the RPC forwarder
X */
Xint fwd_init()
X{
X	int on = 1;
X
X	/*
X	 * Create ping socket
X	 */
X	fwd_sock = socket(AF_INET, SOCK_DGRAM, 0);
X	if (fwd_sock < 0) {
X		plog(XLOG_ERROR, "Unable to create RPC forwarding socket: %m");
X		return errno;
X	}
X
X	/*
X	 * Some things we talk to require a priv port - so make one here
X	 */
X	if (bind_resv_port(fwd_sock, (unsigned short *) 0) < 0)
X		plog(XLOG_ERROR, "can't bind privileged port");
X
X	if (fcntl(fwd_sock, F_SETFL, FNDELAY) < 0 &&
X			ioctl(fwd_sock, FIONBIO, &on) < 0) {
X		plog(XLOG_ERROR, "Can't set non-block on forwarding socket: %m");
X		return errno;
X	}
X
X	return 0;
X}
X
X/*
X * Locate a packet in the forwarding list
X */
Xstatic rpc_forward *fwd_locate(id)
Xu_int id;
X{
X	rpc_forward *p;
X
X	ITER(p, rpc_forward, &rpc_head) {
X		if (p->rf_xid == id)
X			return p;
X	}
X
X	return 0;
X}
X
X/*
X * This is called to forward a packet to another
X * RPC server.  The message id is changed and noted
X * so that when a reply appears we can tie it up
X * correctly.  Just matching the reply's source address
X * would not work because it might come from a
X * different address.
X */
Xint fwd_packet(type_id, pkt, len, fwdto, replyto, i, cb)
Xint type_id;
Xvoidp pkt;
Xint len;
Xstruct sockaddr_in *fwdto, *replyto;
Xvoidp i;
Xfwd_fun cb;
X{
X	rpc_forward *p;
X	u_int *pkt_int;
X	int error;
X
X	if ((int)amd_state >= (int)Finishing)
X		return ENOENT;
X
X	/*
X	 * See if the type_id is fully specified.
X	 * If so, then discard any old entries
X	 * for this id.
X	 * Otherwise make sure the type_id is
X	 * fully qualified by allocating an id here.
X	 */
X#ifdef DEBUG
X	switch (type_id & RPC_XID_MASK) {
X	case RPC_XID_PORTMAP: dlog("Sending PORTMAP request"); break;
X	case RPC_XID_MOUNTD: dlog("Sending MOUNTD request %#x", type_id); break;
X	case RPC_XID_NFSPING: dlog("Sending NFS ping"); break;
X	default: dlog("UNKNOWN RPC XID"); break;
X	}
X#endif
X
X	if (type_id & ~RPC_XID_MASK) {
X#ifdef DEBUG
X		/*dlog("Fully qualified rpc type provided");*/
X#endif
X		p = fwd_locate(type_id);
X		if (p) {
X#ifdef DEBUG
X			dlog("Discarding earlier rpc fwd handle");
X#endif
X			fwd_free(p);
X		}
X	} else {
X#ifdef DEBUG
X		dlog("Allocating a new xid...");
X#endif
X		type_id = MK_RPC_XID(type_id, XID_ALLOC());
X	}
X
X	p = fwd_alloc();
X	if (!p)
X		return ENOBUFS;
X
X	error = 0;
X
X	pkt_int = (u_int *) pkt;
X
X	/*
X	 * Get the original packet id
X	 */
X	p->rf_oldid = *pkt_int;
X
X	/*
X	 * Replace with newly allocated id
X	 */
X	p->rf_xid = *pkt_int = type_id;
X
X	/*
X	 * The sendto may fail if, for example, the route
X	 * to a remote host is lost because an intermediate
X	 * gateway has gone down.  Important to fill in the
X	 * rest of "p" otherwise nasty things happen later...
X	 */
X#ifdef DEBUG
X	dlog("Sending packet id %#x to %#08x.%04x", p->rf_xid, ntohl(fwdto->sin_addr.s_addr), ntohs(fwdto->sin_port));
X#endif
X	if (sendto(fwd_sock, (char *) pkt, len, 0,
X			(struct sockaddr *) fwdto, sizeof(*fwdto)) < 0)
X		error = errno;
X
X	/*
X	 * Save callback function and return address
X	 */
X	p->rf_fwd = cb;
X	if (replyto)
X		p->rf_sin = *replyto;
X	else
X		bzero((voidp) &p->rf_sin, sizeof(p->rf_sin));
X	p->rf_ptr = i;
X
X	return error;
X}
X
X/*
X * Called when some data arrives on the forwarding socket
X */
Xvoid fwd_reply()
X{
X	int len;
X#ifdef DYNAMIC_BUFFERS
X	voidp pkt;
X#else
X	u_int pkt[MAX_PACKET_SIZE/sizeof(u_int)+1];
X#endif
X	u_int *pkt_int;
X	int rc;
X	rpc_forward *p;
X	struct sockaddr_in src_addr;
X	int src_addr_len;
X
X	/*
X	 * Determine the length of the packet
X	 */
X#ifdef DYNAMIC_BUFFERS
X	if (ioctl(fwd_sock, FIONREAD, &len) < 0) {
X		plog(XLOG_ERROR, "Error reading packet size: %m");
X		return;
X	}
X
X	/*
X	 * Allocate a buffer
X	 */
X	pkt = (voidp) malloc((unsigned) len);
X	if (!pkt) {
X		plog(XLOG_ERROR, "Out of buffers in fwd_reply");
X		return;
X	}
X#else
X	len = MAX_PACKET_SIZE;
X#endif
X
X	/*
X	 * Read the packet and check for validity
X	 */
Xagain:
X	src_addr_len = sizeof(src_addr);
X	rc = recvfrom(fwd_sock, (char *) pkt, len, 0,
X			(struct sockaddr *) &src_addr, &src_addr_len);
X	if (rc < 0 || src_addr_len != sizeof(src_addr) ||
X			src_addr.sin_family != AF_INET) {
X		if (rc < 0 && errno == EINTR)
X			goto again;
X		plog(XLOG_ERROR, "Error reading RPC reply: %m");
X		goto out;
X	}
X
X#ifdef DYNAMIC_BUFFERS
X	if (rc != len) {
X		plog(XLOG_ERROR, "Short read in fwd_reply");
X		goto out;
X	}
X#endif
X
X	/*
X	 * Do no more work if finishing soon
X	 */
X	if ((int)amd_state >= (int)Finishing)
X		goto out;
X
X	/*
X	 * Find packet reference
X	 */
X	pkt_int = (u_int *) pkt;
X
X#ifdef DEBUG
X	switch (*pkt_int & RPC_XID_MASK) {
X	case RPC_XID_PORTMAP: dlog("Receiving PORTMAP reply"); break;
X	case RPC_XID_MOUNTD: dlog("Receiving MOUNTD reply %#x", *pkt_int); break;
X	case RPC_XID_NFSPING: dlog("Receiving NFS ping %#x", *pkt_int); break;
X	default: dlog("UNKNOWN RPC XID"); break;
X	}
X#endif
X
X	p = fwd_locate(*pkt_int);
X	if (!p) {
X#ifdef DEBUG
X		dlog("Can't forward reply id %#x", *pkt_int);
X#endif
X		goto out;
X	}
X
X	if (p->rf_fwd) {
X		/*
X		 * Put the original message id back
X		 * into the packet.
X		 */
X		*pkt_int = p->rf_oldid;
X
X		/*
X		 * Call forwarding function
X		 */
X		(*p->rf_fwd)(pkt, rc, &src_addr, &p->rf_sin, p->rf_ptr, TRUE);
X	}
X
X	/*
X	 * Free forwarding info
X	 */
X	fwd_free(p);
X
Xout:;
X#ifdef DYNAMIC_BUFFERS
X	/*
X	 * Free the packet
X	 */
X	free(pkt);
X#endif
X}
END_OF_FILE
if test 8861 -ne `wc -c <'rpc_fwd.c'`; then
    echo shar: \"'rpc_fwd.c'\" unpacked with wrong size!
fi
# end of 'rpc_fwd.c'
fi
echo shar: End of archive 6 \(of 13\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 13 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.