[comp.sources.unix] v21i092: An Automounter for NFS systems, Part04/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 92
Archive-name: amd/part04

#! /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 4 (of 13)."
# Contents:  amq.x amq_xdr.c clock.c doc/amd.bib doc/nh.doc info_file.c
#   mount_fs.c nfs_prot_svc.c restart.c sched.c
# Wrapped by rsalz@papaya.bbn.com on Tue Apr 10 15:12:02 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'amq.x' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'amq.x'\"
else
echo shar: Extracting \"'amq.x'\" \(4120 characters\)
sed "s/^X//" >'amq.x' <<'END_OF_FILE'
X/*
X * $Id: amq.x,v 5.1.1.1 90/01/11 17:02:14 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 * Protocol description used by the amq program
X */
X
Xconst AMQ_STRLEN = 1024;	/* Maximum length of a pathname */
X
X/*
X * The type dirpath is the pathname of a directory
X */
Xtypedef string amq_string<AMQ_STRLEN>;
X
X/*
X * The type time_type should correspond to the system time_t
X */
Xtypedef long time_type;
X
X/*
X * A tree of what is mounted
X */
Xstruct amq_mount_tree {
X	amq_string	mt_mountinfo;	/* Mounted filesystem */
X	amq_string 	mt_directory;	/* Virtual mount */
X	amq_string 	mt_mountpoint;	/* Mount point */
X	amq_string	mt_type;	/* Filesystem type */
X	time_type	mt_mounttime;	/* Mount time */
X	u_short		mt_mountuid;	/* Mounter */
X	int		mt_getattr;	/* Count of getattrs */
X	int		mt_lookup;	/* Count of lookups */
X	int		mt_readdir;	/* Count of readdirs */
X	int		mt_readlink;	/* Count of readlinks */
X	int		mt_statfs;	/* Count of statfss */
X	amq_mount_tree	*mt_next;	/* Sibling mount tree */
X	amq_mount_tree	*mt_child;	/* Child mount tree */
X};
Xtypedef amq_mount_tree *amq_mount_tree_p;
X
X/*
X * List of mounted filesystems
X */
Xstruct amq_mount_info {
X	amq_string	mi_type;	/* Type of mount */
X	amq_string	mi_mountpt;	/* Mount point */
X	amq_string	mi_mountinfo;	/* Mount info */
X	amq_string	mi_fserver;	/* Fileserver */
X	int		mi_error;	/* Error code */
X	int		mi_refc;	/* References */
X	int		mi_up;		/* Filesystem available */
X};
Xtypedef amq_mount_info amq_mount_info_list<>;
X
X/*
X * A list of mount trees
X */
Xtypedef amq_mount_tree_p amq_mount_tree_list<>;
X
X/*
X * System wide stats
X */
Xstruct amq_mount_stats {
X	int	as_drops;	/* Dropped requests */
X	int	as_stale;	/* Stale NFS handles */
X	int	as_mok;		/* Succesful mounts */
X	int	as_merr;	/* Failed mounts */
X	int	as_uerr;	/* Failed unmounts */
X};
X
Xenum amq_opt {
X	AMOPT_DEBUG=0,
X	AMOPT_LOGFILE=1,
X	AMOPT_XLOG=2,
X	AMOPT_FLUSHMAPC=3
X};
X
Xstruct amq_setopt {
X	amq_opt	as_opt;		/* Option */
X	amq_string as_str;	/* String */
X};
X
Xprogram AMQ_PROGRAM {
X	version AMQ_VERSION {
X		/*
X		 * Does no work. It is made available in all RPC services
X		 * to allow server reponse testing and timing
X		 */
X		void
X		AMQPROC_NULL(void) = 0;
X
X		/*
X		 * Returned the mount tree descending from
X		 * the given directory.  The directory must
X		 * be a top-level mount point of the automounter.
X		 */
X		amq_mount_tree_p
X		AMQPROC_MNTTREE(amq_string) = 1;
X
X		/*
X		 * Force a timeout unmount on the specified directory.
X		 */
X		void
X		AMQPROC_UMNT(amq_string) = 2;
X
X		/*
X		 * Obtain system wide statistics from the automounter
X		 */
X		amq_mount_stats
X		AMQPROC_STATS(void) = 3;
X
X		/*
X		 * Obtain full tree
X		 */
X		amq_mount_tree_list
X		AMQPROC_EXPORT(void) = 4;
X
X		/*
X		 * Control debug options.
X		 * Return status:
X		 *	-1: debug not available
X		 *	 0: everything wonderful
X		 *	>0: number of options not recognised
X		 */
X		int
X		AMQPROC_SETOPT(amq_setopt) = 5;
X
X		/*
X		 * List of mounted filesystems
X		 */
X		amq_mount_info_list
X		AMQPROC_GETMNTFS(void) = 6;
X	} = 1;
X} = 300019;	/* Allocated by Sun, 89/8/29 */
END_OF_FILE
if test 4120 -ne `wc -c <'amq.x'`; then
    echo shar: \"'amq.x'\" unpacked with wrong size!
fi
# end of 'amq.x'
fi
if test -f 'amq_xdr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'amq_xdr.c'\"
else
echo shar: Extracting \"'amq_xdr.c'\" \(4678 characters\)
sed "s/^X//" >'amq_xdr.c' <<'END_OF_FILE'
X/*
X * $Id: amq_xdr.c,v 5.1.1.1 90/01/11 17:04:23 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
X
Xbool_t
Xxdr_amq_string(xdrs, objp)
X	XDR *xdrs;
X	amq_string *objp;
X{
X	if (!xdr_string(xdrs, objp, AMQ_STRLEN)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_time_type(xdrs, objp)
X	XDR *xdrs;
X	time_type *objp;
X{
X	if (!xdr_long(xdrs, objp)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_amq_mount_tree(xdrs, objp)
X	XDR *xdrs;
X	amq_mount_tree *objp;
X{
X	if (!xdr_amq_string(xdrs, &objp->mt_mountinfo)) {
X		return (FALSE);
X	}
X	if (!xdr_amq_string(xdrs, &objp->mt_directory)) {
X		return (FALSE);
X	}
X	if (!xdr_amq_string(xdrs, &objp->mt_mountpoint)) {
X		return (FALSE);
X	}
X	if (!xdr_amq_string(xdrs, &objp->mt_type)) {
X		return (FALSE);
X	}
X	if (!xdr_time_type(xdrs, &objp->mt_mounttime)) {
X		return (FALSE);
X	}
X	if (!xdr_u_short(xdrs, &objp->mt_mountuid)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->mt_getattr)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->mt_lookup)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->mt_readdir)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->mt_readlink)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->mt_statfs)) {
X		return (FALSE);
X	}
X	if (!xdr_pointer(xdrs, (char **)&objp->mt_next, sizeof(amq_mount_tree), xdr_amq_mount_tree)) {
X		return (FALSE);
X	}
X	if (!xdr_pointer(xdrs, (char **)&objp->mt_child, sizeof(amq_mount_tree), xdr_amq_mount_tree)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_amq_mount_tree_p(xdrs, objp)
X	XDR *xdrs;
X	amq_mount_tree_p *objp;
X{
X	if (!xdr_pointer(xdrs, (char **)objp, sizeof(amq_mount_tree), xdr_amq_mount_tree)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
Xbool_t
Xxdr_amq_mount_info(xdrs, objp)
X	XDR *xdrs;
X	amq_mount_info *objp;
X{
X	if (!xdr_amq_string(xdrs, &objp->mi_type)) {
X		return (FALSE);
X	}
X	if (!xdr_amq_string(xdrs, &objp->mi_mountpt)) {
X		return (FALSE);
X	}
X	if (!xdr_amq_string(xdrs, &objp->mi_mountinfo)) {
X		return (FALSE);
X	}
X	if (!xdr_amq_string(xdrs, &objp->mi_fserver)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->mi_error)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->mi_refc)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->mi_up)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
Xbool_t
Xxdr_amq_mount_info_list(xdrs, objp)
X	XDR *xdrs;
X	amq_mount_info_list *objp;
X{
X	if (!xdr_array(xdrs, (char **)&objp->amq_mount_info_list_val, (u_int *)&objp->amq_mount_info_list_len, ~0, sizeof(amq_mount_info), xdr_amq_mount_info)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
Xbool_t
Xxdr_amq_mount_tree_list(xdrs, objp)
X	XDR *xdrs;
X	amq_mount_tree_list *objp;
X{
X	if (!xdr_array(xdrs, (char **)&objp->amq_mount_tree_list_val, (u_int *)&objp->amq_mount_tree_list_len, ~0, sizeof(amq_mount_tree_p), xdr_amq_mount_tree_p)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_amq_mount_stats(xdrs, objp)
X	XDR *xdrs;
X	amq_mount_stats *objp;
X{
X	if (!xdr_int(xdrs, &objp->as_drops)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->as_stale)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->as_mok)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->as_merr)) {
X		return (FALSE);
X	}
X	if (!xdr_int(xdrs, &objp->as_uerr)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_amq_opt(xdrs, objp)
X	XDR *xdrs;
X	amq_opt *objp;
X{
X	if (!xdr_enum(xdrs, (enum_t *)objp)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
X
X
Xbool_t
Xxdr_amq_setopt(xdrs, objp)
X	XDR *xdrs;
X	amq_setopt *objp;
X{
X	if (!xdr_amq_opt(xdrs, &objp->as_opt)) {
X		return (FALSE);
X	}
X	if (!xdr_amq_string(xdrs, &objp->as_str)) {
X		return (FALSE);
X	}
X	return (TRUE);
X}
X
X
END_OF_FILE
if test 4678 -ne `wc -c <'amq_xdr.c'`; then
    echo shar: \"'amq_xdr.c'\" unpacked with wrong size!
fi
# end of 'amq_xdr.c'
fi
if test -f 'clock.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'clock.c'\"
else
echo shar: Extracting \"'clock.c'\" \(4452 characters\)
sed "s/^X//" >'clock.c' <<'END_OF_FILE'
X/*
X * $Id: clock.c,v 5.1 89/11/17 18:19:50 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 * Callouts.
X *
X * Modelled on kernel object of the same name.
X * See usual references.
X *
X * Use of a heap-based mechanism was rejected:
X * 1.  more complext implementation needed.
X * 2.  not obvious that a list is too slow for amd.
X */
X
X#include "am.h"
X
Xtypedef struct callout callout;
Xstruct callout {
X	callout	*c_next;		/* List of callouts */
X	void	(*c_fn)();		/* Function to call */
X	voidp	c_closure;		/* Closure to pass to call */
X	time_t	c_time;			/* Time of call */
X	int	c_id;			/* Unique identifier */
X};
X
Xstatic callout callouts;		/* List of pending callouts */
Xstatic callout *free_callouts;		/* Cache of free callouts */
Xstatic int nfree_callouts;		/* Number on free list */
Xstatic int callout_id;			/* Next free callout identifier */
Xtime_t next_softclock;			/* Time of next call to softclock() */
X
X/*
X * Number of callout slots we keep on the free list
X */
X#define	CALLOUT_FREE_SLOP	10
X
X/*
X * Assumption: valid id's are non-zero.
X */
X#define	CID_ALLOC()	(++callout_id)
X#define	CID_UNDEF	(0)
X
Xstatic callout *alloc_callout()
X{
X	callout *cp = free_callouts;
X	if (cp) {
X		--nfree_callouts;
X		free_callouts = free_callouts->c_next;
X		return cp;
X	}
X	return ALLOC(callout);
X}
X
Xstatic void free_callout(cp)
Xcallout *cp;
X{
X	if (nfree_callouts > CALLOUT_FREE_SLOP) {
X		free((voidp) cp);
X	} else {
X		cp->c_next = free_callouts;
X		free_callouts = cp;
X		nfree_callouts++;
X	}
X}
X
X/*
X * Schedule a callout.
X *
X * (*fn)(closure) will be called at clocktime() + secs
X */
Xint timeout(secs, fn, closure)
Xunsigned int secs;
Xvoid (*fn)();
Xvoidp closure;
X{
X	callout *cp, *cp2;
X	time_t t = clocktime() + secs;
X
X	/*
X	 * Allocate and fill in a new callout structure
X	 */
X	callout *cpnew = alloc_callout();
X	cpnew->c_closure = closure;
X	cpnew->c_fn = fn;
X	cpnew->c_time = t;
X	cpnew->c_id = CID_ALLOC();
X
X	if (t < next_softclock)
X		next_softclock = t;
X
X	/*
X	 * Find the correct place in the list
X	 */
X	for (cp = &callouts; cp2 = cp->c_next; cp = cp2)
X		if (cp2->c_time >= t)
X			break;
X
X	/*
X	 * And link it in
X	 */
X	cp->c_next = cpnew;
X	cpnew->c_next = cp2;
X
X	/*
X	 * Return callout identifier
X	 */
X	return cpnew->c_id;
X}
X
X/*
X * De-schedule a callout
X */
Xvoid untimeout(id)
Xint id;
X{
X	callout *cp, *cp2;
X	for (cp = &callouts; cp2 = cp->c_next; cp = cp2) {
X		if (cp2->c_id == id) {
X			cp->c_next = cp2->c_next;
X			free_callout(cp2);
X			break;
X		}
X	}
X}
X
X/*
X * Clock handler
X */
Xint softclock()
X{
X	time_t now;
X	callout *cp;
X
X	do {
X		if (task_notify_todo)
X			task_notify();
X
X		now = clocktime();
X
X		/*
X		 * While there are more callouts waiting...
X		 */
X		while ((cp = callouts.c_next) && cp->c_time <= now) {
X			/*
X			 * Extract first from list, save fn & closure and
X			 * unlink callout from list and free.
X			 * Finally call function.
X			 *
X			 * The free is done first because
X			 * it is quite common that the
X			 * function will call timeout()
X			 * and try to allocate a callout
X			 */
X			void (*fn)() = cp->c_fn;
X			voidp closure = cp->c_closure;
X
X			callouts.c_next = cp->c_next;
X			free_callout(cp);
X#ifdef DEBUG
X			/*dlog("Calling %#x(%#x)", fn, closure);*/
X#endif
X			(*fn)(closure);
X		}
X
X	} while (task_notify_todo);
X
X	/*
X	 * Return number of seconds to next event,
X	 * or 0 if there is no event.
X	 */
X	if (cp = callouts.c_next)
X		return cp->c_time - now;
X	return 0;
X}
END_OF_FILE
if test 4452 -ne `wc -c <'clock.c'`; then
    echo shar: \"'clock.c'\" unpacked with wrong size!
fi
# end of 'clock.c'
fi
if test -f 'doc/amd.bib' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'doc/amd.bib'\"
else
echo shar: Extracting \"'doc/amd.bib'\" \(3898 characters\)
sed "s/^X//" >'doc/amd.bib' <<'END_OF_FILE'
X% $Id: amd.bib,v 5.1 89/11/17 18:24:37 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@inproceedings{usenix:automounter
X	,author =	"Brent Callaghan and Tom Lyon"
X	,month =	"January"
X	,year =		"1989"
X	,title =	"{The Automounter}"
X	,booktitle =    "Usenix Conference Proceedings, {\rm San Diego, California}"
X	,organization = "Usenix Association"
X	,pages =	"43-51"
X}
X
X@inproceedings{mit:hesiod
X	,author =	"Stephen P. Dyer"
X	,title =	"{The {\em Hesiod} Name Server}"
X	,booktitle =	"Usenix Conference Proceedings, {\rm Dallas, Texas}"
X	,year =		"1988"
X	,month =	"February"
X	,organization = "Usenix Association"
X	,pages =	"183--189"
X}
X
X@techreport{mit:rvd
X	,author =	"M. Greenwald and J. V. Sciver"
X	,title =	"{Remote Virtual Disk Protocol Specification}"
X	,year =		"1986"
X	,institution =	"Massachusetts Institute of Technology"
X	,address =	"Cambridge, Massachusetts"
X}
X
X@inbook{bsd:ufs
X	,author =	"Samuel J. Leffler and others"
X	,year =		"1989"
X	,title =	"The Design and Implementation of the 4.3BSD UNIX Operating System"
X	,chapter =	"7"
X	,pages =	"187--223"
X	,publisher =	"Addison-Wesley"
X}
X
X@techreport{rfc:icmp
X	,author =	"J. Postel"
X	,title =	"{Internet Control Message Protocol}"
X	,year =		"1981"
X	,month =	"September"
X	,institution =	"SRI Network Information Center"
X	,address =	"Menlo Park, California"
X	,type =		"RFC"
X	,number =	"792"
X}
X
X@techreport{rfc:ip
X	,author =	"J. Postel"
X	,title =	"{Internet Protocol}"
X	,year =		"1981"
X	,month =	"September"
X	,institution =	"SRI Network Information Center"
X	,address =	"Menlo Park, California"
X	,type =		"RFC"
X	,number =	"791"
X}
X
X@incollection{sun:yp
X	,author =	"{Sun Microsystems}"
X	,year =		"1988"
X	,booktitle =	"System \& Network Administration"
X	,title =	"{The Sun YP Service}"
X	,month =	"May"
X	,chapter =	"14"
X	,pages =	"349--371"
X	,edition =	"First"
X	,publisher =	"Sun Microsystems, Inc"
X	,address =	"Mountain View, California"
X}
X
X@incollection{sun:automount
X	,author =	"{Sun Microsystems}"
X	,year =		"1988"
X	,booktitle =	"SunOS Reference Manual"
X	,title =	"Automount"
X	,month =	"May"
X	,chapter =	"8"
X	,pages =	"1583--1585"
X	,edition =	"First"
X	,publisher =	"Sun Microsystems, Inc"
X	,address =	"Mountain View, California"
X}
X
X@incollection{sun:rpc
X	,author =	"{Sun Microsystems}"
X	,year =		"1988"
X	,booktitle =	"Network Programming"
X	,title =	"{Remote Procedure Calls: Protocol Specification}"
X	,month =	"May"
X	,chapter =	"6"
X	,pages =	"143--163"
X	,edition =	"First"
X	,publisher =	"Sun Microsystems, Inc"
X	,address =	"Mountain View, California"
X}
X
X@incollection{sun:nfs
X	,author =	"{Sun Microsystems}"
X	,year =		"1988"
X	,booktitle =	"Network Programming"
X	,title =	"{Network File System: Version 2 Protocol Specification}"
X	,month =	"May"
X	,chapter =	"7"
X	,pages =	"165--185"
X	,edition =	"First"
X	,publisher =	"Sun Microsystems, Inc"
X	,address =	"Mountain View, California"
X}
END_OF_FILE
if test 3898 -ne `wc -c <'doc/amd.bib'`; then
    echo shar: \"'doc/amd.bib'\" unpacked with wrong size!
fi
# end of 'doc/amd.bib'
fi
if test -f 'doc/nh.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'doc/nh.doc'\"
else
echo shar: Extracting \"'doc/nh.doc'\" \(4900 characters\)
sed "s/^X//" >'doc/nh.doc' <<'END_OF_FILE'
X% Change page size parameters for A4 paper on LaserWriter,
X% allowing for headers and footers. Define some new macros for headers
X% and footers too.
X%
X% MJW 7 Jan 1987
X%
X% USAGE
X%
X% To enable this use \pagestyle{footers}.
X% This also overrides automatically getting chapter titles in headers, but you
X% could restore this by using \leftmark and \rightmark
X% in your own headers and footers.  These macros are set by \chaptermark (and
X% possibly other things too). In one-sided printing all pages are right ones.
X%
X% One-Sided Printing
X%
X% \setheader{your header}
X% \setfooter{your footer}
X% \setchapterhead{header on first page of a chapter}
X% \setchapterfoot{footer on first page of a chapter}
X%
X% Two-sided Printing
X%
X% \setbothheaders{the left one (even no. pages}{the right one (odd)}
X% \setbothfooters{the left one}{the right one}
X% \setchapterhead{header on first page of a chapter}
X% \setchapterfoot{footer on first page of a chapter}
X%
X% Examples
X%
X% To get a page number use \thepage. Use \hfil to get centring etc.
X% Example \setheader{A\hfil\thepage\hfil B}
X% produces A at the extreme left of the page, the number in the middle
X% and B at the extreme right.
X%
X% The following produces chapter title at top left, page number top right,
X% with a line across the page underneath them,
X% Project 1022(1041) bottom left, Task 19.1 bottom right.
X% Except on the first page of a chapter when the heading is empty, and
X% the footer is as before, but with the page number in the middle.
X% \pagestyle{footers}
X% \setheader{\vbox{\hbox to\hsize{\rightmark\hfil\thepage}\vskip 2pt\hrule}}
X% \setfooter{Project 1022(1041)\hfil Task 19.1}
X% \setchapterfoot{Project 1022(1041)\hfil\thepage \hfil Task 19.1}
X
X\oddsidemargin 16pt % MJW actually get 1/2 inch (=32pt) margin because
X                   % of printer offset. was 1pt
X\evensidemargin 16pt % was 1pt
X\marginparwidth 30pt % these gain 53pt width
X\topmargin 5pt      % gains 26pt height (MJW was 16pt)
X\headheight 14pt      % gains 11pt height (MJW was 1pt)
X\headsep 25pt         % gains 24pt height (MJW was 1pt)
X%\footheight 12 pt   % cannot be changed as number must fit
X\footskip 24pt       % gains 6pt height
X\textheight % 528 + 26 + 11 + 24 + 6 + 55 for luck -16 +32 (heads: -10 -15)
X%           650pt
X%            666pt
X	    641pt
X\textwidth % 360 + 53 + 47 for luck -15 +8
X           453pt
X%\pagestyle{myheadings}
X%\markboth{LEFT}{RIGHT}
X%left = even, right = odd for two-sided
X% everything is right for one-sided
X\def\evenheadline{}\def\oddheadline{}
X\def\evenfootline{}\def\oddfootline{}
X
X% Use these to set headers and footers for two-sided printing.
X\def\setbothheaders#1#2{\def\evenheadline{#1}\def\oddheadline{#2}}
X\def\setbothfooters#1#2{\def\evenfootline{#1}\def\oddfootline{#2}}
X
X% Use these for one-sided printing.
X\def\setheader#1{\def\oddheadline{#1}}\def\setfooter#1{\def\oddfootline{#1}}
X
X% To set footer on first page of a chapter
X\def\setchapterfoot#1{\def\chapterfoot{#1}}
X\def\setchapterhead#1{\def\chapterhead{#1}}
X
X% Initialise footers to the page number.
X\setbothfooters{\hfil\thepage\hfil}{\hfil\thepage\hfil}
X
X% Initialise chapter footer to page number, header empty.
X\setchapterfoot{\hfil\thepage \hfil}
X\setchapterhead{}
X
X% My version of \chapter
X\def\chapter{\clearpage      % Starts new page.
X%  \if@twoside \cleardoublepage
X%  \else\clearpage\fi      % Starts new page.
X   \thispagestyle{chapterpage}     % Page style of chapter page is 'chapterpage'
X   \global\@topnum\z@        % Prevents figures from going at top of page.
X   \@afterindentfalse        % Suppresses indent in first paragraph.  Change
X   \secdef\@chapter\@schapter}   % to \@afterindenttrue to have indent.
X   
X% Style for first page of a chapter
X\def\ps@chapterpage{\let\@mkboth\markboth
X\def\@evenhead{\chapterhead}\def\@oddhead{\chapterhead}
X\def\@evenfoot{\chapterfoot}\def\@oddfoot{\chapterfoot}}
X
X% Style for headers AND footers.
X\if@twoside         % If two-sided printing.
X\def\ps@footers{\let\@mkboth\markboth
X\def\@evenhead{\evenheadline}\def\@oddhead{\oddheadline}
X\def\@evenfoot{\evenfootline}\def\@oddfoot{\oddfootline}
X% Chapter stuff
X\def\chaptermark##1{\markboth{\uppercase{\ifnum \c@secnumdepth >\m@ne
X \@chapapp\ \thechapter. \ \fi ##1}}{}}
X\def\sectionmark##1{\markright{\uppercase{\ifnum \c@secnumdepth >\z@
X   \thesection. \ \fi ##1}}}
X}
X\else               % If one-sided printing.
X\def\ps@footers{\let\@mkboth\markboth
X\def\@evenhead{\evenheadline}\def\@oddhead{\oddheadline}
X\def\@evenfoot{\evenfootline}\def\@oddfoot{\oddfootline}
X% Chapter stuff
X\def\chaptermark##1{\markright{\uppercase{\ifnum \c@secnumdepth >\m@ne
X \@chapapp\ \thechapter. \ \fi ##1}}}
X}
X\fi
X
X% Debugging stuff.
X%\let\markbothorig\markboth
X%\def\markboth#1#2{\typeout{---Markboth: \#1=#1, \#2=#2\newline}
X%  \markbothorig {#1} {#2}}
X%  
X%\let\markrightorig\markright
X%\def\markright#1{\typeout{---Markright: \#1=#1\newline}
X%  \markrightorig {#1}}
END_OF_FILE
if test 4900 -ne `wc -c <'doc/nh.doc'`; then
    echo shar: \"'doc/nh.doc'\" unpacked with wrong size!
fi
# end of 'doc/nh.doc'
fi
if test -f 'info_file.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'info_file.c'\"
else
echo shar: Extracting \"'info_file.c'\" \(4399 characters\)
sed "s/^X//" >'info_file.c' <<'END_OF_FILE'
X/*
X * $Id: info_file.c,v 5.1.1.1 90/01/11 17:07:25 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 * Get info from file
X */
X
X#include "am.h"
X
X#ifdef HAS_FILE_MAPS
X#include <ctype.h>
X#include <sys/stat.h>
X
X#define	MAX_LINE_LEN	2048
X
Xstatic int read_line(buf, size, fp)
Xchar *buf;
Xint size;
XFILE *fp;
X{
X	int done = 0;
X
X	do {
X		while (fgets(buf, size, fp)) {
X			int len = strlen(buf);
X			done += len;
X			if (len > 1 && buf[len-2] == '\\' &&
X					buf[len-1] == '\n') {
X				int ch;
X				buf += len - 2;
X				size -= len - 2;
X				/*
X				 * Skip leading white space on next line
X				 */
X				while ((ch = getc(fp)) != EOF &&
X					isascii(ch) && isspace(ch))
X						;
X				(void) ungetc(ch, fp);
X			} else {
X				return done;
X			}
X		}
X	} while (size > 0 && !feof(fp));
X
X	return done;
X}
X
X/*
X * Try to locate a key in a file
X */
Xstatic int search_or_reload_file(fp, map, key, val, m, fn)
XFILE *fp;
Xchar *map;
Xchar *key;
Xchar **val;
Xmnt_map *m;
Xvoid (*fn) P((mnt_map*, char*, char*));
X{
X	char key_val[MAX_LINE_LEN];
X	int chuck = 0;
X	int line_no = 0;
X
X	while (read_line(key_val, sizeof(key_val), fp)) {
X		char *kp;
X		char *cp;
X		char *hash;
X		int len = strlen(key_val);
X		line_no++;
X
X		/*
X		 * Make sure we got the whole line
X		 */
X		if (key_val[len-1] != '\n') {
X			plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map);
X			chuck = 1;
X		} else {
X			key_val[len-1] = '\0';
X		}
X
X		/*
X		 * Strip comments
X		 */
X		hash = strchr(key_val, '#');
X		if (hash)
X			*hash = '\0';
X
X		/*
X		 * Find start of key
X		 */
X		for (kp = key_val; *kp && isascii(*kp) && isspace(*kp); kp++)
X			;
X
X		/*
X		 * Ignore blank lines
X		 */
X		if (!*kp)
X			goto again;
X
X		/*
X		 * Find end of key
X		 */
X		for (cp = kp; *cp&&(!isascii(*cp)||!isspace(*cp)); cp++)
X			;
X
X		/*
X		 * Check whether key matches
X		 */
X		if (*cp)
X			*cp++ = '\0';
X
X		if ((*key == *kp && strcmp(key, kp) == 0) || fn) {
X			while (*cp && isascii(*cp) && isspace(*cp))
X				cp++;
X			if (*cp) {
X				/*
X				 * Return a copy of the data
X				 */
X				char *dc = strdup(cp);
X				if (fn)
X					(*fn)(m, kp, dc);
X				else
X					*val = dc;
X#ifdef DEBUG
X				dlog("%s returns %s", key, dc);
X#endif
X				if (!fn)
X					return 0;
X			} else {
X				plog(XLOG_USER, "%s: line %d has no value field", map, line_no);
X			}
X		}
X
Xagain:
X		/*
X		 * If the last read didn't get a whole line then
X		 * throw away the remainder before continuing...
X		 */
X		if (chuck) {
X			while (fgets(key_val, sizeof(key_val), fp) &&
X				!strchr(key_val, '\n'))
X					;
X			chuck = 0;
X		}
X	}
X
X	return fn ? 0 : ENOENT;
X}
X
Xint file_init(map)
Xchar *map;
X{
X	FILE *mapf = fopen(map, "r");
X	if (mapf) {
X		(void) fclose(mapf);
X		return 0;
X	}
X	return errno;
X}
X
Xint file_reload(m, map, fn)
Xmnt_map *m;
Xchar *map;
Xvoid (*fn)();
X{
X	FILE *mapf = fopen(map, "r");
X	if (mapf) {
X		int error = search_or_reload_file(mapf, map, 0, 0, m, fn);
X		(void) fclose(mapf);
X		return error;
X	}
X
X	return errno;
X}
X
Xint file_search(m, map, key, pval, tp)
Xmnt_map *m;
Xchar *map;
Xchar *key;
Xchar **pval;
Xtime_t *tp;
X{
X	FILE *mapf = fopen(map, "r");
X	if (mapf) {
X		struct stat stb;
X		int error;
X		error = fstat(fileno(mapf), &stb);
X		if (!error && *tp < stb.st_mtime) {
X			*tp = stb.st_mtime;
X			error = -1;
X		} else {
X			error = search_or_reload_file(mapf, map, key, pval, 0, 0);
X		}
X		(void) fclose(mapf);
X		return error;
X	}
X
X	return errno;
X}
X#endif
END_OF_FILE
if test 4399 -ne `wc -c <'info_file.c'`; then
    echo shar: \"'info_file.c'\" unpacked with wrong size!
fi
# end of 'info_file.c'
fi
if test -f 'mount_fs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mount_fs.c'\"
else
echo shar: Extracting \"'mount_fs.c'\" \(5414 characters\)
sed "s/^X//" >'mount_fs.c' <<'END_OF_FILE'
X/*
X * $Id: mount_fs.c,v 5.1.1.2 90/01/11 17:10:47 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#ifdef NFS_3
Xtypedef nfs_fh fhandle_t;
X#endif
X#include <sys/mount.h>
X
X/*
X * System Vr4 / SunOS 4.1 compatibility
X * - put dev= in the options list
X *
X * From: Brent Callaghan <brent@eng.sun.com>
X */
X#define	MNTINFO_DEV	"dev"
X#include <sys/stat.h>
X
Xint compute_mount_flags(mnt)
Xstruct mntent *mnt;
X{
X	int flags;
X#ifdef NFS_4
X	flags = M_NEWTYPE;
X#else
X	flags = 0;
X#endif
X
X	/*
X	 * Crack basic mount options
X	 */
X	flags |= hasmntopt(mnt, "ro") ? M_RDONLY : 0;
X#ifdef M_CACHE
X	flags |= hasmntopt(mnt, "nocache") ? M_NOCACHE : 0;
X#endif
X#ifdef M_GRPID
X	flags |= hasmntopt(mnt, "grpid") ? M_GRPID : 0;
X#endif
X#ifdef M_MULTI
X	flags |= hasmntopt(mnt, "multi") ? M_MULTI : 0;
X#endif
X#ifdef M_NODEV
X	flags |= hasmntopt(mnt, "nodev") ? M_NODEV : 0;
X#endif
X#ifdef M_NOEXEC
X	flags |= hasmntopt(mnt, "noexec") ? M_NOEXEC : 0;
X#endif
X#ifdef M_NOSUB
X	flags |= hasmntopt(mnt, "nosub") ? M_NOSUB : 0;
X#endif
X#ifdef hpux
X/* HP-UX has an annoying feature of printing error msgs on /dev/console */
X#undef M_NOSUID
X#endif
X#ifdef M_NOSUID
X	flags |= hasmntopt(mnt, "nosuid") ? M_NOSUID : 0;
X#endif
X#ifdef M_SYNC
X	flags |= hasmntopt(mnt, "sync") ? M_SYNC : 0;
X#endif
X
X	return flags;
X}
X
Xint mount_fs(mnt, flags, mnt_data, retry, type)
Xstruct mntent *mnt;
Xint flags;
Xcaddr_t mnt_data;
Xint retry;
XMTYPE_TYPE type;
X{
X	int error = 0;
X	int automount = 0;
X#ifdef MNTINFO_DEV
X	struct stat stb;
X	char *xopts = 0;
X#endif
X
X#ifdef DEBUG
X#ifdef NFS_4
X	dlog("%s fstype %s (%s) flags %#x (%s)",
X		mnt->mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
X#else
X	dlog("%s fstype %d (%s) flags %#x (%s)",
X		mnt->mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
X#endif /* NFS_4 */
X#endif /* DEBUG */
X
X	/*
X	 * Fake some mount table entries for the automounter
X	 */
X	if (STREQ(mnt->mnt_type, MNTTYPE_AUTO)) {
X		automount = 1;
X		mnt->mnt_fsname = pid_fsname;
X		/*
X		 * Try it with the normal name
X		 */
X#ifdef notdef
X		mnt->mnt_type = MNTTYPE_IGNORE;
X#endif
X		mnt->mnt_type = MNTTYPE_NFS;
X		/*
X		 * Background the mount, so that the stat of the
X		 * mountpoint is done in a background process.
X		 */
X		if (background())
X			return 0;
X	}
X
Xagain:
X	clock_valid = 0;
X	error = MOUNT_TRAP(type, mnt, flags, mnt_data);
X	if (error < 0)
X		plog(XLOG_ERROR, "%s: mount: %m", mnt->mnt_dir);
X	if (error < 0 && --retry > 0) {
X		sleep(1);
X		goto again;
X	}
X	if (error < 0) {
X		if (automount)
X			going_down(errno);
X		return errno;
X	}
X
X#ifdef UPDATE_MTAB
X#ifdef MNTINFO_DEV
X	/*
X	 * Add the extra dev= field to the mount table.
X	 */
X	if (stat(mnt->mnt_dir, &stb) == 0) {
X		char *zopts = (char *) xmalloc(strlen(mnt->mnt_opts) + 32);
X		xopts = mnt->mnt_opts;
X		if (sizeof(stb.st_dev) == 2) {
X			/* SunOS 4.1 */
X			sprintf(zopts, "%s,%s=%04lx", xopts, MNTINFO_DEV,
X					(u_long) stb.st_dev & 0xffff);
X		} else {
X			/* System Vr4 */
X			sprintf(zopts, "%s,%s=%08lx", xopts, MNTINFO_DEV,
X					(u_long) stb.st_dev);
X		}
X		mnt->mnt_opts = zopts;
X	}
X#endif /* MNTINFO_DEV */
X
X#ifdef hpux
X	/*
X	 * Yet another gratuitously incompatible change in HP-UX
X	 */
X	mnt->mnt_time = clocktime();
X#endif
X	write_mntent(mnt);
X#ifdef MNTINFO_DEV
X	if (xopts) {
X		free(mnt->mnt_opts);
X		mnt->mnt_opts = xopts;
X	}
X#endif
X#endif /* UPDATE_MTAB */
X
X	/*
X	 * Needed this way since mnt may contain a pointer
X	 * to a local variable in this stack frame.
X	 */
X	if (automount)
X		going_down(0);
X	return 0;
X}
X
X#ifdef NEED_MNTOPT_PARSER
X/*
X * Some systems don't provide these to the user,
X * but amd needs them, so...
X *
X * From: Piete Brooks <pb@cl.cam.ac.uk>
X */
X
X#include <ctype.h>
X
Xstatic char *nextmntopt(p)
Xchar **p;
X{
X	char *cp = *p;
X	char *rp;
X	/*
X	 * Skip past white space
X	 */
X	while (*cp && isspace(*cp))
X		cp++;
X	/*
X	 * Word starts here
X	 */
X	rp = cp;
X	/*
X	 * Scan to send of string or separator
X	 */
X	while (*cp && *cp != ',')
X		cp++;
X	/*
X	 * If separator found the overwrite with nul char.
X	 */
X	if (*cp) {
X		*cp = '\0';
X		cp++;
X	}
X	/*
X	 * Return value for next call
X	 */
X	*p = cp;
X	return rp;
X}
X
Xchar *hasmntopt(mnt, opt)
Xstruct mntent *mnt;
Xchar *opt;
X{
X	char t[MNTMAXSTR];
X	char *f;
X	char *o = t;
X	int l = strlen(opt);
X	strcpy(t, mnt->mnt_opts);
X
X	while (*(f = nextmntopt(&o)))
X		if (strncmp(opt, f, l) == 0)
X			return f - t + mnt->mnt_opts;
X
X	return 0;
X}
X#endif /* NEED_MNTOPT_PARSER */
END_OF_FILE
if test 5414 -ne `wc -c <'mount_fs.c'`; then
    echo shar: \"'mount_fs.c'\" unpacked with wrong size!
fi
# end of 'mount_fs.c'
fi
if test -f 'nfs_prot_svc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nfs_prot_svc.c'\"
else
echo shar: Extracting \"'nfs_prot_svc.c'\" \(4786 characters\)
sed "s/^X//" >'nfs_prot_svc.c' <<'END_OF_FILE'
X/*
X * $Id: nfs_prot_svc.c,v 5.1 89/11/17 18:21:23 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
Xvoid nfs_program_2(rqstp, transp)
Xstruct svc_req *rqstp;
XSVCXPRT *transp;
X{
X	union {
X		nfs_fh nfsproc_getattr_2_arg;
X		sattrargs nfsproc_setattr_2_arg;
X		diropargs nfsproc_lookup_2_arg;
X		nfs_fh nfsproc_readlink_2_arg;
X		readargs nfsproc_read_2_arg;
X		writeargs nfsproc_write_2_arg;
X		createargs nfsproc_create_2_arg;
X		diropargs nfsproc_remove_2_arg;
X		renameargs nfsproc_rename_2_arg;
X		linkargs nfsproc_link_2_arg;
X		symlinkargs nfsproc_symlink_2_arg;
X		createargs nfsproc_mkdir_2_arg;
X		diropargs nfsproc_rmdir_2_arg;
X		readdirargs nfsproc_readdir_2_arg;
X		nfs_fh nfsproc_statfs_2_arg;
X	} argument;
X	char *result;
X	bool_t (*xdr_argument)(), (*xdr_result)();
X	char *(*local)();
X
X	switch (rqstp->rq_proc) {
X	case NFSPROC_NULL:
X		xdr_argument = xdr_void;
X		xdr_result = xdr_void;
X		local = (char *(*)()) nfsproc_null_2;
X		break;
X
X	case NFSPROC_GETATTR:
X		xdr_argument = xdr_nfs_fh;
X		xdr_result = xdr_attrstat;
X		local = (char *(*)()) nfsproc_getattr_2;
X		break;
X
X	case NFSPROC_SETATTR:
X		xdr_argument = xdr_sattrargs;
X		xdr_result = xdr_attrstat;
X		local = (char *(*)()) nfsproc_setattr_2;
X		break;
X
X	case NFSPROC_ROOT:
X		xdr_argument = xdr_void;
X		xdr_result = xdr_void;
X		local = (char *(*)()) nfsproc_root_2;
X		break;
X
X	case NFSPROC_LOOKUP:
X		xdr_argument = xdr_diropargs;
X		xdr_result = xdr_diropres;
X		local = (char *(*)()) nfsproc_lookup_2;
X		break;
X
X	case NFSPROC_READLINK:
X		xdr_argument = xdr_nfs_fh;
X		xdr_result = xdr_readlinkres;
X		local = (char *(*)()) nfsproc_readlink_2;
X		break;
X
X	case NFSPROC_READ:
X		xdr_argument = xdr_readargs;
X		xdr_result = xdr_readres;
X		local = (char *(*)()) nfsproc_read_2;
X		break;
X
X	case NFSPROC_WRITECACHE:
X		xdr_argument = xdr_void;
X		xdr_result = xdr_void;
X		local = (char *(*)()) nfsproc_writecache_2;
X		break;
X
X	case NFSPROC_WRITE:
X		xdr_argument = xdr_writeargs;
X		xdr_result = xdr_attrstat;
X		local = (char *(*)()) nfsproc_write_2;
X		break;
X
X	case NFSPROC_CREATE:
X		xdr_argument = xdr_createargs;
X		xdr_result = xdr_diropres;
X		local = (char *(*)()) nfsproc_create_2;
X		break;
X
X	case NFSPROC_REMOVE:
X		xdr_argument = xdr_diropargs;
X		xdr_result = xdr_nfsstat;
X		local = (char *(*)()) nfsproc_remove_2;
X		break;
X
X	case NFSPROC_RENAME:
X		xdr_argument = xdr_renameargs;
X		xdr_result = xdr_nfsstat;
X		local = (char *(*)()) nfsproc_rename_2;
X		break;
X
X	case NFSPROC_LINK:
X		xdr_argument = xdr_linkargs;
X		xdr_result = xdr_nfsstat;
X		local = (char *(*)()) nfsproc_link_2;
X		break;
X
X	case NFSPROC_SYMLINK:
X		xdr_argument = xdr_symlinkargs;
X		xdr_result = xdr_nfsstat;
X		local = (char *(*)()) nfsproc_symlink_2;
X		break;
X
X	case NFSPROC_MKDIR:
X		xdr_argument = xdr_createargs;
X		xdr_result = xdr_diropres;
X		local = (char *(*)()) nfsproc_mkdir_2;
X		break;
X
X	case NFSPROC_RMDIR:
X		xdr_argument = xdr_diropargs;
X		xdr_result = xdr_nfsstat;
X		local = (char *(*)()) nfsproc_rmdir_2;
X		break;
X
X	case NFSPROC_READDIR:
X		xdr_argument = xdr_readdirargs;
X		xdr_result = xdr_readdirres;
X		local = (char *(*)()) nfsproc_readdir_2;
X		break;
X
X	case NFSPROC_STATFS:
X		xdr_argument = xdr_nfs_fh;
X		xdr_result = xdr_statfsres;
X		local = (char *(*)()) nfsproc_statfs_2;
X		break;
X
X	default:
X		svcerr_noproc(transp);
X		return;
X	}
X	bzero((char *)&argument, sizeof(argument));
X	if (!svc_getargs(transp, xdr_argument, &argument)) {
X		svcerr_decode(transp);
X		return;
X	}
X	result = (*local)(&argument, rqstp);
X	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
X		svcerr_systemerr(transp);
X	}
X	if (!svc_freeargs(transp, xdr_argument, &argument)) {
X		plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_1");
X		going_down(1);
X	}
X}
X
END_OF_FILE
if test 4786 -ne `wc -c <'nfs_prot_svc.c'`; then
    echo shar: \"'nfs_prot_svc.c'\" unpacked with wrong size!
fi
# end of 'nfs_prot_svc.c'
fi
if test -f 'restart.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'restart.c'\"
else
echo shar: Extracting \"'restart.c'\" \(4527 characters\)
sed "s/^X//" >'restart.c' <<'END_OF_FILE'
X/*
X * $Id: restart.c,v 5.1.1.2 90/01/11 17:18:41 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 * Handle an amd restart.
X *
X * Scan through the mount list finding all "interesting" mount points.
X * Next hack up partial data structures and add the mounted file
X * system to the list of known filesystems.  This will leave a
X * dangling reference to that filesystems, so when the filesystem is
X * finally inherited, an extra "free" must be done on it.
X *
X * This module relies on internal details of other components.  If
X * you change something else make *sure* restart() still works.
X */
Xvoid restart()
X{
X	/*
X	 * Read the existing mount table
X	 */
X	mntlist *ml, *mlp;
X
X	/*
X	 * For each entry, find nfs, ufs or auto mounts
X	 * and create a partial am_node to represent it.
X	 */
X	for (mlp = ml = read_mtab("restart"); mlp; mlp = mlp->mnext) {
X		struct mntent *me = mlp->mnt;
X		am_ops *fs_ops = 0;
X		if (STREQ(me->mnt_type, MTAB_TYPE_UFS)) {
X			/*
X			 * UFS entry
X			 */
X			fs_ops = &ufs_ops;
X		} else if (STREQ(me->mnt_type, MTAB_TYPE_NFS)) {
X			/*
X			 * NFS entry, or possibly an Amd entry...
X			 */
X			int au_pid;
X			char *colon = strchr(me->mnt_fsname, ':');
X			if (colon && sscanf(colon, ":(pid%d)", &au_pid) == 1) {
X				plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
X				fs_ops = &sfs_ops;
X			} else {
X				fs_ops = &nfs_ops;
X			}
X#ifdef MTAB_TYPE_MFS
X		} else if (STREQ(me->mnt_type, MTAB_TYPE_MFS)) {
X			/*
X			 * MFS entry.  Fake with a symlink.
X			 */
X			fs_ops = &sfs_ops;
X#endif
X		} else {
X			/*
X			 * Catch everything else with symlinks to
X			 * avoid recursive mounts.  This is debatable...
X			 */
X			fs_ops = &sfs_ops;
X		}
X
X		/*
X		 * If we found something to do
X		 */
X		if (fs_ops) {
X			mntfs *mf;
X			am_opts mo;
X			char *cp;
X			cp = strchr(me->mnt_fsname, ':');
X			/*
X			 * Partially fake up an opts structure
X			 */
X			mo.opt_rhost = 0;
X			mo.opt_rfs = 0;
X			if (cp) {
X				*cp = '\0';
X				mo.opt_rhost = strdup(me->mnt_fsname);
X				mo.opt_rfs = strdup(cp+1);
X				*cp = ':';
X			} else if (fs_ops->ffserver == find_nfs_srvr) {
X				/* 
X				 * Prototype 4.4 BSD used to end up here -
X				 * might as well keep the workaround for now
X				 */
X				plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
X				mo.opt_rhost = strdup(me->mnt_fsname);
X				mo.opt_rfs = strdup("/");
X				me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
X			}
X			mo.opt_fs = me->mnt_dir;
X
X			/*
X			 * Make a new mounted filesystem
X			 */
X			mf = find_mntfs(fs_ops, &mo, me->mnt_dir,
X				me->mnt_fsname, me->mnt_opts);
X			if (mf->mf_refc == 1) {
X				mf->mf_flags |= MFF_RESTART|MFF_MOUNTED;
X				mf->mf_error = 0;	/* Already mounted correctly */
X				/*
X				 * If the restarted type is a link then
X				 * don't time out.
X				 */
X				if (fs_ops == &sfs_ops)
X					mf->mf_flags |= MFF_RSTKEEP;
X				if (fs_ops->fs_init) {
X					/*
X					 * Don't care whether this worked since
X					 * it is checked again when the fs is
X					 * inherited.
X					 */
X					(void) (*fs_ops->fs_init)(mf);
X				}
X
X				plog(XLOG_INFO, "%s restarted fstype %s on %s",
X					me->mnt_fsname, fs_ops->fs_type, me->mnt_dir);
X			} else {
X				/* Something strange happened - two mounts at the same place! */
X				free_mntfs(mf);
X			}
X			/*
X			 * Clean up mo
X			 */
X			if (mo.opt_rhost)
X				free(mo.opt_rhost);
X			if (mo.opt_rfs)
X				free(mo.opt_rfs);
X		}
X	}
X
X	/*
X	 * Free the mount list
X	 */
X	free_mntlist(ml);
X}
END_OF_FILE
if test 4527 -ne `wc -c <'restart.c'`; then
    echo shar: \"'restart.c'\" unpacked with wrong size!
fi
# end of 'restart.c'
fi
if test -f 'sched.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sched.c'\"
else
echo shar: Extracting \"'sched.c'\" \(4945 characters\)
sed "s/^X//" >'sched.c' <<'END_OF_FILE'
X/*
X * $Id: sched.c,v 5.1.1.1 90/01/11 17:19:12 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 * Process scheduler
X */
X
X#include "am.h"
X#include <sys/signal.h>
X#include WAIT
X#include <setjmp.h>
Xextern jmp_buf select_intr;
Xextern int select_intr_valid;
X
Xtypedef struct pjob pjob;
Xstruct pjob {
X	qelem hdr;			/* Linked list */
X	int pid;			/* Process ID of job */
X	cb_fun cb_fun;			/* Callback function */
X	voidp cb_closure;		/* Closure for callback */
X	union wait w;			/* Status filled in by sigchld */
X	voidp wchan;			/* Wait channel */
X};
X
Xextern qelem proc_list_head;
Xqelem proc_list_head = { &proc_list_head, &proc_list_head };
Xextern qelem proc_wait_list;
Xqelem proc_wait_list = { &proc_wait_list, &proc_wait_list };
X
Xint task_notify_todo;
X
Xvoid ins_que(elem, pred)
Xqelem *elem, *pred;
X{
X	qelem *p = pred->q_forw;
X	elem->q_back = pred;
X	elem->q_forw = p;
X	pred->q_forw = elem;
X	p->q_back = elem;
X}
X
Xvoid rem_que(elem)
Xqelem *elem;
X{
X	qelem *p = elem->q_forw;
X	qelem *p2 = elem->q_back;
X	p2->q_forw = p;
X	p->q_back = p2;
X}
X
Xstatic pjob *sched_job(cf, ca)
Xcb_fun cf;
Xvoidp ca;
X{
X	pjob *p = ALLOC(pjob);
X
X	p->cb_fun = cf;
X	p->cb_closure = ca;
X
X	/*
X	 * Now place on wait queue
X	 */
X	ins_que(&p->hdr, &proc_wait_list);
X
X	return p;
X}
X
Xvoid run_task(tf, ta, cf, ca)
Xtask_fun tf;
Xvoidp ta;
Xcb_fun cf;
Xvoidp ca;
X{
X	pjob *p = sched_job(cf, ca);
X	int mask;
X
X	p->wchan = (voidp) p;
X
X	mask = sigblock(sigmask(SIGCHLD));
X
X	if (p->pid = background()) {
X		sigsetmask(mask);
X		return;
X	}
X
X	exit((*tf)(ta));
X	/* firewall... */
X	abort();
X}
X
X/*
X * Schedule a task to be run when woken up
X */
Xvoid sched_task(cf, ca, wchan)
Xcb_fun cf;
Xvoidp ca;
Xvoidp wchan;
X{
X	/*
X	 * Allocate a new task
X	 */
X	pjob *p = sched_job(cf, ca);
X#ifdef DEBUG
X	/*dlog("sleep(%#x)", wchan);*/
X#endif
X	p->wchan = wchan;
X	p->pid = 0;
X	bzero((voidp) &p->w, sizeof(p->w));
X}
X
Xstatic void wakeupjob(p)
Xpjob *p;
X{
X	rem_que(&p->hdr);
X	ins_que(&p->hdr, &proc_list_head);
X	task_notify_todo++;
X}
X
Xvoid wakeup(wchan)
Xvoidp wchan;
X{
X	pjob *p, *p2;
X
X	if (!foreground)
X		return;
X
X#ifdef DEBUG
X	/*dlog("wakeup(%#x)", wchan);*/
X#endif
X	/*
X	 * Can't user ITER() here because
X	 * wakeupjob() juggles the list.
X	 */
X	for (p = FIRST(pjob, &proc_wait_list);
X			p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
X			p = p2) {
X		if (p->wchan == wchan)
X			wakeupjob(p);
X	}
X}
X
Xvoid wakeup_task(rc, term, cl)
Xint rc;
Xint term;
Xvoidp cl;
X{
X	wakeup(cl);
X}
X
X/*ARGSUSED*/
Xvoid sigchld(sig)
Xint sig;
X{
X	union wait w;
X	int pid;
X
X#ifdef SYS5_SIGNALS
X	if ((pid = wait(&w)) > 0) {
X#else
X	while ((pid = wait3(&w, WNOHANG, (union wait *) 0)) > 0) {
X#endif
X		pjob *p, *p2;
X
X		if (WIFSIGNALED(w))
X			plog(XLOG_ERROR, "Process %d exited with signal %d",
X				pid, w.w_termsig);
X#ifdef DEBUG
X		else
X			dlog("Process %d exited with status %d",
X				pid, w.w_retcode);
X#endif
X
X		for (p = FIRST(pjob, &proc_wait_list);
X				p2 = NEXT(pjob, p), p != HEAD(pjob, &proc_wait_list);
X				p = p2) {
X			if (p->pid == pid) {
X				p->w = w;
X				wakeupjob(p);
X				break;
X			}
X		}
X
X#ifdef DEBUG
X		if (p) ; else dlog("can't locate task block for pid %d", pid);
X#endif
X	}
X
X#ifdef SYS5_SIGNALS
X	signal(sig, sigchld);
X#endif
X	if (select_intr_valid)
X		longjmp(select_intr, sigchld);
X}
X
X/*
X * Run any pending tasks.
X * This must be called with SIGCHLD disabled
X */
Xvoid task_notify(P_void)
X{
X	/*
X	 * Keep taking the first item off the list and processing it.
X	 *
X	 * Done this way because the the callback can, quite reasonably,
X	 * queue a new task, so no local reference into the list can be
X	 * held here.
X	 */
X	while (FIRST(pjob, &proc_list_head) != HEAD(pjob, &proc_list_head)) {
X		pjob *p = FIRST(pjob, &proc_list_head);
X		rem_que(&p->hdr);
X		/*
X		 * This job has completed
X		 */
X		--task_notify_todo;
X
X		/*
X		 * Do callback if it exists
X		 */
X		if (p->cb_fun)
X			(*p->cb_fun)(p->w.w_retcode,
X				p->w.w_termsig, p->cb_closure);
X
X		free(p);
X	}
X}
END_OF_FILE
if test 4945 -ne `wc -c <'sched.c'`; then
    echo shar: \"'sched.c'\" unpacked with wrong size!
fi
# end of 'sched.c'
fi
echo shar: End of archive 4 \(of 13\).
cp /dev/null ark4isdone
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.