RFS: remote file system (part 6 of 7)

sources-request at panda.UUCP sources-request at panda.UUCP
Fri Jan 10 00:11:10 AEST 1986


Mod.sources:  Volume 3, Issue 82
Submitted by: tektronix!tekcrl!toddb

#!/bin/sh
#
# RFS, a kernel-resident remote file system.  Shar 6 of 7
#
#
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	remote/usr.sys.VAX4.3/sys/kern_exec.c.diff
#	remote/usr.sys.VAX4.3/sys/kern_exit.c.diff
#	remote/usr.sys.VAX4.3/sys/ufs_namei.c.diff
#	remote/usr.sys.VAX4.3/sys/ufs_syscalls.c.diff
#	remote/usr.sys.remote
#	remote/usr.sys.remote/remote_mkdata
#	remote/usr.sys.remote/remotefs.h
#	remote/usr.sys.remote/rmt_data_template
#	remote/usr.sys.remote/rmt_exec.c
#	remote/usr.sys.remote/rmt_final.c
#	remote/usr.sys.remote/rmt_syscall3.c
#
# remote/usr.sys.VAX4.3/sys/kern_exec.c.diff
#
if [ -f remote/usr.sys.VAX4.3/sys/kern_exec.c.diff ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.VAX4.3/sys/kern_exec.c.diff or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.VAX4.3/sys/kern_exec.c.diff 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.VAX4.3/sys/kern_exec.c.diff
XThe following changes implement local execution of an object file that
Xlives on another host.
X***************
X*** 27,32
X  #include "acct.h"
X  #include "exec.h"
X  
X  #ifdef vax
X  #include "../vax/mtpr.h"
X  #endif
X
X--- 27,36 -----
X  #include "acct.h"
X  #include "exec.h"
X  
X+ #ifdef REMOTEFS
X+ #include "../h/errno.h"
X+ #endif REMOTEFS
X+ 
X  #ifdef vax
X  #include "../vax/mtpr.h"
X  #endif
X***************
X*** 55,61
X  	int na, ne, ucp, ap, len, cc;
X  	int indir, uid, gid;
X  	char *sharg;
X! 	struct inode *ip;
X  	swblk_t bno;
X  	char cfname[MAXCOMLEN + 1];
X  #define	SHSIZE	32
X
X--- 59,70 -----
X  	int na, ne, ucp, ap, len, cc;
X  	int indir, uid, gid;
X  	char *sharg;
X! #ifdef REMOTEFS
X! 	struct inode *ip; /* have to take address */
X! 	int	remote = -1;
X! #else REMOTEFS
X! 	register struct inode *ip;
X! #endif REMOTEFS
X  	swblk_t bno;
X  	char cfname[MAXCOMLEN + 1];
X  #define	SHSIZE	32
X***************
X*** 71,76
X  	ndp->ni_segflg = UIO_USERSPACE;
X  	ndp->ni_dirp = ((struct execa *)u.u_ap)->fname;
X  	if ((ip = namei(ndp)) == NULL)
X  		return;
X  	bno = 0;
X  	bp = 0;
X
X--- 80,91 -----
X  	ndp->ni_segflg = UIO_USERSPACE;
X  	ndp->ni_dirp = ((struct execa *)u.u_ap)->fname;
X  	if ((ip = namei(ndp)) == NULL)
X+ #ifdef REMOTEFS
X+ 		if (u.u_error == EISREMOTE)
X+ 			remote = remote_execinfo(&ip, &uid, &gid,
X+ 				&exdata, ((struct execa *)u.u_ap)->fname);
X+ 	if (u.u_error)
X+ #endif REMOTEFS
X  		return;
X  	bno = 0;
X  	bp = 0;
X***************
X*** 75,80
X  	bno = 0;
X  	bp = 0;
X  	indir = 0;
X  	uid = u.u_uid;
X  	gid = u.u_gid;
X  	if (ip->i_mode & ISUID)
X
X--- 90,99 -----
X  	bno = 0;
X  	bp = 0;
X  	indir = 0;
X+ 
X+ #ifdef REMOTEFS
X+ if (remote < 0) {
X+ #endif REMOTEFS
X  	uid = u.u_uid;
X  	gid = u.u_gid;
X  	if (ip->i_mode & ISUID)
X***************
X*** 112,117
X  	    0, 1, &resid);
X  	if (u.u_error)
X  		goto bad;
X  #ifndef lint
X  	if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
X  	    exdata.ex_shell[0] != '#') {
X
X--- 131,143 -----
X  	    0, 1, &resid);
X  	if (u.u_error)
X  		goto bad;
X+ #ifdef REMOTEFS
X+ }
X+ 
X+ remote_again:
X+ 
X+ #endif REMOTEFS
X+ 
X  #ifndef lint
X  	if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
X  	    exdata.ex_shell[0] != '#') {
X***************
X*** 170,176
X  				bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
X  		}
X  		indir = 1;
X! 		iput(ip);
X  		ndp->ni_nameiop = LOOKUP | FOLLOW;
X  		ndp->ni_segflg = UIO_SYSSPACE;
X  		ip = namei(ndp);
X
X--- 196,205 -----
X  				bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
X  		}
X  		indir = 1;
X! #ifdef REMOTEFS
X! 		if (remote < 0)
X! #endif REMOTEFS
X! 			iput(ip);
X  		ndp->ni_nameiop = LOOKUP | FOLLOW;
X  		ndp->ni_segflg = UIO_SYSSPACE;
X  		ip = namei(ndp);
X***************
X*** 174,179
X  		ndp->ni_nameiop = LOOKUP | FOLLOW;
X  		ndp->ni_segflg = UIO_SYSSPACE;
X  		ip = namei(ndp);
X  		if (ip == NULL)
X  			return;
X  		bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname,
X
X--- 203,220 -----
X  		ndp->ni_nameiop = LOOKUP | FOLLOW;
X  		ndp->ni_segflg = UIO_SYSSPACE;
X  		ip = namei(ndp);
X+ #ifdef REMOTEFS
X+ 		if (ip == NULL) {
X+ 			if (u.u_error == EISREMOTE)
X+ 				remote = remote_execinfo(&ip, 0, 0, 0);
X+ 			if (u.u_error)
X+ 				return;
X+ 			if (ip == NULL)
X+ 				goto remote_again;
X+ 		}
X+ 		else
X+ 			remote = -1;
X+ #else REMOTEFS
X  		if (ip == NULL)
X  			return;
X  #endif REMOTEFS
X***************
X*** 176,181
X  		ip = namei(ndp);
X  		if (ip == NULL)
X  			return;
X  		bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname,
X  		    MAXCOMLEN);
X  		cfname[MAXCOMLEN] = '\0';
X
X--- 217,223 -----
X  #else REMOTEFS
X  		if (ip == NULL)
X  			return;
X+ #endif REMOTEFS
X  		bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname,
X  		    MAXCOMLEN);
X  		cfname[MAXCOMLEN] = '\0';
X***************
X*** 268,274
X  		bdwrite(bp);
X  	bp = 0;
X  	nc = (nc + NBPW-1) & ~(NBPW-1);
X! 	getxfile(ip, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid);
X  	if (u.u_error) {
X  badarg:
X  		for (cc = 0; cc < nc; cc += CLSIZE*NBPG) {
X
X--- 310,322 -----
X  		bdwrite(bp);
X  	bp = 0;
X  	nc = (nc + NBPW-1) & ~(NBPW-1);
X! 
X! #ifdef REMOTEFS
X!         getxfile(ip, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid, remote);
X! #else REMOTEFS
X!         getxfile(ip, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid);
X! #endif REMOTEFS
X! 
X  	if (u.u_error) {
X  badarg:
X  		for (cc = 0; cc < nc; cc += CLSIZE*NBPG) {
X***************
X*** 376,381
X  /*
X   * Read in and set up memory for executed file.
X   */
X  getxfile(ip, ep, nargc, uid, gid)
X  	register struct inode *ip;
X  	register struct exec *ep;
X
X--- 424,432 -----
X  /*
X   * Read in and set up memory for executed file.
X   */
X+ #ifdef REMOTEFS
X+ getxfile(ip, ep, nargc, uid, gid, remote)
X+ #else REMOTEFS
X  getxfile(ip, ep, nargc, uid, gid)
X  #endif REMOTEFS
X  	register struct inode *ip;
X***************
X*** 377,382
X   * Read in and set up memory for executed file.
X   */
X  getxfile(ip, ep, nargc, uid, gid)
X  	register struct inode *ip;
X  	register struct exec *ep;
X  	int nargc, uid, gid;
X
X--- 428,434 -----
X  getxfile(ip, ep, nargc, uid, gid, remote)
X  #else REMOTEFS
X  getxfile(ip, ep, nargc, uid, gid)
X+ #endif REMOTEFS
X  	register struct inode *ip;
X  	register struct exec *ep;
X  	int nargc, uid, gid;
X***************
X*** 383,388
X  {
X  	size_t ts, ds, ids, uds, ss;
X  	int pagi;
X  
X  	if (ep->a_magic == 0413)
X  		pagi = SPAGI;
X
X--- 435,443 -----
X  {
X  	size_t ts, ds, ids, uds, ss;
X  	int pagi;
X+ #ifdef REMOTEFS
X+ 	int	oldtextsize;
X+ #endif REMOTEFS
X  
X  	if (ep->a_magic == 0413)
X  		pagi = SPAGI;
X***************
X*** 388,393
X  		pagi = SPAGI;
X  	else
X  		pagi = 0;
X  	if (ip->i_flag & IXMOD) {			/* XXX */
X  		u.u_error = ETXTBSY;
X  		goto bad;
X
X--- 443,459 -----
X  		pagi = SPAGI;
X  	else
X  		pagi = 0;
X+ #ifdef REMOTEFS
X+ 	if (remote >= 0) {
X+ 		/*
X+ 		 * Prevent xalloc() from making a shared or paged text.
X+ 		 */
X+ 		pagi = 0;
X+ 		oldtextsize = ep->a_text;
X+ 		ep->a_data += ep->a_text;
X+ 		ep->a_text = 0;
X+ 	}
X+ #endif REMOTEFS
X  	if (ip->i_flag & IXMOD) {			/* XXX */
X  		u.u_error = ETXTBSY;
X  		goto bad;
X***************
X*** 452,457
X  	u.u_smap = u.u_csmap;
X  	vgetvm(ts, ds, ss);
X  
X  	if (pagi == 0)
X  		u.u_error =
X  		    rdwri(UIO_READ, ip,
X
X--- 518,528 -----
X  	u.u_smap = u.u_csmap;
X  	vgetvm(ts, ds, ss);
X  
X+ #ifdef REMOTEFS
X+ 	if (remote >= 0)
X+ 		u.u_error = remote_execread(remote, oldtextsize, ep);
X+ 	else
X+ #endif REMOTEFS
X  	if (pagi == 0)
X  		u.u_error =
X  		    rdwri(UIO_READ, ip,
SHAREOF
chmod 664 remote/usr.sys.VAX4.3/sys/kern_exec.c.diff
#
# remote/usr.sys.VAX4.3/sys/kern_exit.c.diff
#
if [ -f remote/usr.sys.VAX4.3/sys/kern_exit.c.diff ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.VAX4.3/sys/kern_exit.c.diff or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.VAX4.3/sys/kern_exit.c.diff 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.VAX4.3/sys/kern_exit.c.diff
XThe following changes ensure that upon exit, a process notifies any remote
Xservers that may know about him, that he is indeed dead.
X***************
X*** 23,28
X  #include "mbuf.h"
X  #include "inode.h"
X  #include "syslog.h"
X  
X  /*
X   * Exit system call: pass back caller's arg
X
X--- 23,31 -----
X  #include "mbuf.h"
X  #include "inode.h"
X  #include "syslog.h"
X+ #ifdef REMOTEFS
X+ #include "../remote/remotefs.h"
X+ #endif REMOTEFS
X  
X  /*
X   * Exit system call: pass back caller's arg
X***************
X*** 56,61
X  	vmsizmon();
X  #endif
X  	p = u.u_procp;
X  	p->p_flag &= ~(STRC|SULOCK);
X  	p->p_flag |= SWEXIT;
X  	p->p_sigignore = ~0;
X
X--- 59,71 -----
X  	vmsizmon();
X  #endif
X  	p = u.u_procp;
X+ #ifdef REMOTEFS
X+ 	/*
X+ 	 * First, release our server.
X+ 	 */
X+ 	if (p->p_flag & SREMOTE)
X+ 		remote_exit();
X+ #endif REMOTEFS
X  	p->p_flag &= ~(STRC|SULOCK);
X  	p->p_flag |= SWEXIT;
X  	p->p_sigignore = ~0;
SHAREOF
chmod 664 remote/usr.sys.VAX4.3/sys/kern_exit.c.diff
#
# remote/usr.sys.VAX4.3/sys/ufs_namei.c.diff
#
if [ -f remote/usr.sys.VAX4.3/sys/ufs_namei.c.diff ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.VAX4.3/sys/ufs_namei.c.diff or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.VAX4.3/sys/ufs_namei.c.diff 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.VAX4.3/sys/ufs_namei.c.diff
XThese changes are the primary hook into the operating system for detecting
Xa "remote" file.
X***************
X*** 149,154
X  	int isdotdot;			/* != 0 if current name is ".." */
X  	int flag;			/* op ie, LOOKUP, CREATE, or DELETE */
X  	off_t enduseful;		/* pointer past last used dir slot */
X  
X  	lockparent = ndp->ni_nameiop & LOCKPARENT;
X  	docache = (ndp->ni_nameiop & NOCACHE) ^ NOCACHE;
X
X--- 149,157 -----
X  	int isdotdot;			/* != 0 if current name is ".." */
X  	int flag;			/* op ie, LOOKUP, CREATE, or DELETE */
X  	off_t enduseful;		/* pointer past last used dir slot */
X+ #ifdef REMOTEFS
X+ 	int remote;
X+ #endif
X  
X  	lockparent = ndp->ni_nameiop & LOCKPARENT;
X  	docache = (ndp->ni_nameiop & NOCACHE) ^ NOCACHE;
X***************
X*** 202,207
X  	 * Check accessiblity of directory.
X  	 */
X  	if ((dp->i_mode&IFMT) != IFDIR) {
X  		u.u_error = ENOTDIR;
X  		goto bad;
X  	}
X
X--- 205,226 -----
X  	 * Check accessiblity of directory.
X  	 */
X  	if ((dp->i_mode&IFMT) != IFDIR) {
X+ #ifdef REMOTEFS
X+ 		remote = isremote(dp, cp, nbp->b_un.b_addr);
X+ 		/*
X+ 		 * If it is really local, then start again at the root.
X+ 		 */
X+ 		if (remote < 0) {
X+ 			iput(dp);
X+ 			dp = rootdir;
X+ 			ILOCK(dp);
X+ 			dp->i_count++;
X+ 			fs = dp->i_fs;
X+ 			cp = nbp->b_un.b_addr;
X+ 			goto dirloop2;
X+ 		}
X+ 		else if (! remote)
X+ #endif REMOTEFS
X  		u.u_error = ENOTDIR;
X  		goto bad;
X  	}
X***************
X*** 642,647
X  					u.u_error = EPERM;
X  					goto bad;
X  				}
X  			}
X  		}
X  		nbp->av_forw = freenamebuf;
X
X--- 661,677 -----
X  					u.u_error = EPERM;
X  					goto bad;
X  				}
X+ #ifdef REMOTEFS
X+ 				/*
X+ 				 * don't allow anyone to remove a remote mount
X+ 				 * point.
X+ 				 */
X+ 				if (rmt_host(dp, &i)) {
X+ 					iput(ndp->ni_pdir);
X+ 					u.u_error = EBUSY;
X+ 					goto bad;
X+ 				}
X+ #endif REMOTEFS
X  			}
X  		}
X  		nbp->av_forw = freenamebuf;
SHAREOF
chmod 664 remote/usr.sys.VAX4.3/sys/ufs_namei.c.diff
#
# remote/usr.sys.VAX4.3/sys/ufs_syscalls.c.diff
#
if [ -f remote/usr.sys.VAX4.3/sys/ufs_syscalls.c.diff ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.VAX4.3/sys/ufs_syscalls.c.diff or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.VAX4.3/sys/ufs_syscalls.c.diff 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.VAX4.3/sys/ufs_syscalls.c.diff
XThese changes modify chdirec(), which is called by chroot() and chdir(),
Xso that you can be allowed to do a chdir() to a remote mount point.
XIn addition, the changes ensure that we adjust internal pointers when doing
Xa chdir() OUT of a remote mount point.
X
X***************
X*** 51,56
X  chdirec(ipp)
X  	register struct inode **ipp;
X  {
X  	register struct inode *ip;
X  	struct a {
X  		char	*fname;
X
X--- 51,59 -----
X  chdirec(ipp)
X  	register struct inode **ipp;
X  {
X+ #ifdef REMOTEFS
X+ 	int	i;
X+ #endif REMOTEFS
X  	register struct inode *ip;
X  	struct a {
X  		char	*fname;
X***************
X*** 64,69
X  	if (ip == NULL)
X  		return;
X  	if ((ip->i_mode&IFMT) != IFDIR) {
X  		u.u_error = ENOTDIR;
X  		goto bad;
X  	}
X
X--- 67,77 -----
X  	if (ip == NULL)
X  		return;
X  	if ((ip->i_mode&IFMT) != IFDIR) {
X+ #ifdef REMOTEFS
X+ 		if (rmt_hostdir(ip, &i) != NULL)
X+ 			u.u_error = remotechdir(i);
X+ 		else
X+ #endif REMOTEFS
X  		u.u_error = ENOTDIR;
X  		goto bad;
X  	}
X***************
X*** 69,74
X  	}
X  	if (access(ip, IEXEC))
X  		goto bad;
X  	IUNLOCK(ip);
X  	if (*ipp)
X  		irele(*ipp);
X
X--- 77,85 -----
X  	}
X  	if (access(ip, IEXEC))
X  		goto bad;
X+ #ifdef REMOTEFS
X+ 	remotechdir(-1);
X+ #endif REMOTEFS
X  	IUNLOCK(ip);
X  	if (*ipp)
X  		irele(*ipp);
SHAREOF
chmod 664 remote/usr.sys.VAX4.3/sys/ufs_syscalls.c.diff
#
# remote/usr.sys.remote
#
mkdir remote/usr.sys.remote
chmod 775 remote/usr.sys.remote
#
# remote/usr.sys.remote/remote_mkdata
#
if [ -f remote/usr.sys.remote/remote_mkdata ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.remote/remote_mkdata or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.remote/remote_mkdata 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/remote_mkdata
X#!/bin/sh
X# 
X#  Copyright 1985, Todd Brunhoff.
X# 
X#  This software was written at Tektronix Computer Research Laboratories
X#  as partial fulfillment of a Master's degree at the University of Denver.
X#  This software is not Tektronix proprietary software and should not be
X#  confused with any software product sold by Tektronix.  No warranty is
X#  expressed or implied on the reliability of this software; the author,
X#  the University of Denver, and Tektronix, inc. accept no liability for
X#  any damage done directly or indirectly by this software.  This software
X#  may be copied, modified or used in any way, without fee, provided this
X#  comment remains an unaltered part of the software.
X#
X
Xif [ ! -f "$1" ]
Xthen
X	echo "Usage:"
X	echo "	/lib/cpp -DKERNEL ... ..../init_sysent.c | $0 ..../remotefs.h"
X	exit 1
Xfi
X
XREMOTE=$1
X
X#
X# First, get the complete list of remote system calls and put them
X# into memory for awk.
X#
XMEM=`sed -e '/^#define[ 	]*RSYS_/!d' \
X	-e 's/.*RSYS_\([^ 	]*\)	\([0-9]*\)$/mem[\2]="\1";last=\2;/' \
X	< $REMOTE`
X#
X# Then, compile a list of all system calls from a cpp expanded listing
X# of sys/init_sysent.c which should be on standard input.
X# The only kludge here is that we must change internal names for system
X# calls:
X#      internal	      changed
X#	name		 to
X#     ----------     ----------
X#	rexit		exit
X#	saccess		access
X#
Xsed	-e '1,/^struct[ 	]*sysent[ 	]*sysent[ 	]*\[\]/d' \
X	-e '/^};/,$d' \
X	-e '/^#/d' \
X	-e 's/	*[0-9], *//' \
X	-e 's/,.*//' \
X	-e 's/^rexit$/exit/' \
X	-e 's/^saccess$/access/' \
X	-e '/^[ 	]*$/d' \
X| tail +2 \
X| cat -n \
X| awk '
XBEGIN {
X	'"$MEM"'
X	syscall = 0;
X	column = 0;
X	printf "u_char\tremote_sysmap[] = {\n"
X}
X{
X	while (syscall < $1) {
X		if (column % 2 == 0)
X			printf "\t"
X		printf "%-31s", "RSYS_nosys,"
X		if (column % 2 == 1)
X			printf "\n"
X		syscall++
X		column++
X	}
X
X	if (column % 2 == 0)
X		printf "\t"
X	len = length($2);
X	found = 0;
X	for (i=0; i <= last; i++) {
X		if (mem[ i ] == $2) {
X			found = 1;
X			break;
X		}
X	}
X	if (found) {
X		printf "RSYS_%s,", $2
X		len = 25-len;
X	}
X	else {
X		printf "RSYS_nosys,  /* %s */", $2
X		len = 12 - len;
X	}
X	if (column % 2 == 1)
X		printf "\n"
X	else
X		while (len-- > 0)
X			printf " "
X	column++;
X	syscall++
X} END {
X	if (column % 2 == 0)
X		printf "\n"
X	printf "};\n"
X}'
SHAREOF
chmod 664 remote/usr.sys.remote/remote_mkdata
#
# remote/usr.sys.remote/remotefs.h
#
if [ -f remote/usr.sys.remote/remotefs.h ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.remote/remotefs.h or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.remote/remotefs.h 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/remotefs.h
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Header: remotefs.h,v 2.1 86/01/05 18:17:01 toddb Exp $
X *
X * $Log:	remotefs.h,v $
X * Revision 2.1  86/01/05  18:17:01  toddb
X * Added ifdef'ed constants for pyramids: FREMOTE, SREMOTE and SNOREMOTE.
X * 
X * Revision 2.0  85/12/07  18:17:35  toddb
X * First public release.
X * 
X */
X#ifndef RFSDEBUG
X#define debug0()
X#define debug1()
X#define debug2()
X#define debug3()
X#define debug4()
X#define debug5()
X#define debug6()
X#define debug7()
X#define debug8()
X#define debug9()
X#define debug10()
X#define debug11()
X#define debug12()
X#define debug13()
X#define debug14()
X#define rmt_showmsg()
X#else RFSDEBUG
X/*
X * Each of the debugging macros are defined here.  With this scheme we
X * are able to turn on any portion of the debugging with very little overhead
X * This appears to be better than similar schemes that test if
X * remote_debug <= some-level,  because they force the software into having
X * more and more debug software run as the number gets higher.
X */
Xextern long	remote_debug;
X
X#define debug0	(!(remote_debug&0x00001)) ? 0:rmt_debug /* exec info */
X#define debug1	(!(remote_debug&0x00002)) ? 0:rmt_debug /* startup activity */
X#define debug2	(!(remote_debug&0x00004)) ? 0:rmt_debug /* rmt_copypath() */
X#define debug3	(!(remote_debug&0x00008)) ? 0:rmt_debug /* unused */
X#define debug4	(!(remote_debug&0x00010)) ? 0:rmt_debug /* remote_fork */
X#define debug5	(!(remote_debug&0x00020)) ? 0:rmt_debug /* remote[on|off] */
X#define debug6	(!(remote_debug&0x00040)) ? 0:rmt_debug /* file descriptors */
X#define debug7	(!(remote_debug&0x00080)) ? 0:rmt_debug /* isremote() */
X#define debug8	(!(remote_debug&0x00100)) ? 0:rmt_debug /* file remoteness */
X#define debug9	(!(remote_debug&0x00200)) ? 0:rmt_debug /* connection startup */
X#define debug10	(!(remote_debug&0x00400)) ? 0:rmt_debug /* msg setup */
X#define debug11	(!(remote_debug&0x00800)) ? 0:rmt_debug /* msg exceptions */
X#define debug12	(!(remote_debug&0x01000)) ? 0:rmt_debug /* shutdowns */
X#define debug13	(!(remote_debug&0x02000)) ? 0:rmt_debug /* path translation */
X#define debug14	(!(remote_debug&0x04000)) ? 0:rmt_debug /* chdir() activity */
X#define debug15	(!(remote_debug&0x08000)) ? 0:rmt_debug /* msg content */
X#define debug16	(!(remote_debug&0x10000)) ? 0:rmt_debug /* msg data content */
X#define debug17	(!(remote_debug&0x20000)) ? 0:rmt_debug /* unused */
X#define debug18	(!(remote_debug&0x40000)) ? 0:rmt_debug /* unused */
X#define debug19	(!(remote_debug&0x80000)) ? 0:rmt_debug /* unused */
X
X#endif RFSDEBUG
X
X/*
X * Flags for file structures and proc structures.  These should really be
X * in file.h and proc.h, but are here for now.  Note that you must have
X * the fix in ino_close() if DTYPE_REMOTE is defined as 3.
X */
X#define		DTYPE_REMOTE		3  /* file.h: remote file descriptor */
X#ifdef pyr
X#define		SREMOTE		0x00080000 /* proc.h: activity has occured */
X#define		SNOREMOTE	0x80000000 /* proc.h: disallow remote access */
X#define		FREMOTE		04000	   /* file.h: this is a remote file */
X#endif pyr
X#if vax || magnolia || P4400
X#define		SREMOTE		0x08000000 /* proc.h: activity has occured */
X#define		SNOREMOTE	0x10000000 /* proc.h: disallow remote access */
X#define		FREMOTE		08000	   /* file.h: this is a remote file */
X#endif vax || magnolia || P4400
X
X/*
X * Defines for the name server.
X */
X#define		server_alive(p)					\
X			((p) 					\
X			&& (p)->p_stat != NULL			\
X			&& remote_ns.rn_pid == (p)->p_pid)
X
X#define		NM_SERVER	0	/* register as name server */
X#define		NM_WHATNAME	1	/* what name does the kernel need? */
X#define		NM_NAMEIS	2	/* the name is... */
X#define		NM_DEBUG	3	/* turn on debugging */
X
X/*
X * Some manifest constants.
X */
X#define		TRUE		1
X#define		FALSE		0
X#define		REMOTE_FS_SERVER	"remotefs"
X#define		R_MAXSYS	NREMOTE	/* defined in param.h */
X#define		R_MNTPATHLEN	30
X#define		R_MAXMSG	((MAXPATHLEN * 2) + MLEN)
X#define		R_RETRY		(60*5)	/* retry time for connections */
X
X/*
X * State of the data being sent.
X */
X#define		R_NOTHINGSENT	1
X#define		R_DATANOTSENT	2
X#define		R_MSGNOTRED	3
X#define		R_DATANOTRED	4
X
X/*
X * internal flags passed to rmt_msgfin() and rmt_datafin().
X */
X#define		RFLG_DATAV	0x1	/* data to remotemsg() is a vector */
X#define		RFLG_RD		0x2	/* data to remotemsg() to be read */
X#define		RFLG_WR		0x4	/* data to remotemsg() to be written */
X#define		RFLG_INFO	0x8	/* send message only (don't receive */
X
X/*
X * known indices of data in the message.
X */
X#define		R_PATHOFF	3	/* to server (Offset to 2nd path) */
X#define		R_PATHSTART	4	/* to server start of actual path */
X#define		R_DATA		2	/* to server */
X#define		R_RETVAL	0	/* from server */
X#define		R_EXECUID	1	/* from server (exec setuid) */
X#define		R_EXECGID	2	/* from server (exec setgid) */
X#define		R_EXECREADONLY	3	/* from server (exec text read-only) */
X#define		R_EXECDATA	4	/* from server (start of exec info) */
X
X/*
X * Maximum size for the message arg data in long words.  NOT LONGWORDS!!  This
X * should be the largest of the following three sizes among all machines
X * that will use the remote file system:
X *
X *	sizeof(struct exec) * sizeof(long) + R_EXECDATA * sizeof(long)
X *	(# of stat struct members + 1) * sizeof(long)
X */
X#define		R_MAXARGS	18
X
X/*
X * Maximum and minimum message length in bytes that we will ever need on a
X * receive (big enough for a stat(), lstat() or fstat(), and small enough for
X * a return with no other values.
X */
X#define		R_MINRMSG	(sizeof(struct message)-R_MAXARGS*sizeof(long))
X#define		R_MAXRMSG	(sizeof(struct message))
X
X/*
X * The maximum number of mbufs that we need to send a message with
X * two paths, each 1024 characters long.  This is used only in the user
X * level implementation.
X */
X#define		R_MAXMBUFS	(R_MINRMSG+(MAXPATHLEN*2))/MLEN
X
X/*
X * Here, we describe incomming and outgoing messages.  Note that the number
X * of cells in m_args is only for incomming messages.  An outgoing message
X * may consume much more.
X */
Xstruct message {
X	long	m_totlen;	/* length of total message (including data) */
X	short	m_uid;		/* uid of client */
X	short	m_pid;		/* pid of client */
X	short	m_hdlen;	/* length of header (excluding data) */
X	short	m_syscall;	/* syscall number */
X#define		m_errno m_syscall /* errno (for server) */
X	long	m_args[R_MAXARGS];/* remaining arguments or return values */
X};
X
X/*
X * This structure describes the kernel information kept for each
X * connection to a remote server.
X */
Xstruct remoteinfo {
X	char	r_mntpath[ R_MNTPATHLEN ];	/* path of mount point */
X	u_char		r_close:1;	/* True if connection to be closed */
X	u_char		r_received:1;	/* True if an incomming msg in r_msg */
X	u_char		r_failed:1;	/* connection failed */
X	u_char		r_opening:1;	/* connection in process of opening */
X	u_char		r_refcnt;	/* a reference count of active use */
X	short		r_sender;	/* owner of outgoing data */
X	short		r_recver;	/* owner of incomming data */
X	u_short		r_users;	/* count of users using this */
X	u_short		r_nfile;	/* count of open files */
X	u_short		r_nchdir;	/* count of chdir() to this host */
X	struct mbuf	*r_name;	/* socket address of remote host */
X	struct inode 	*r_mntpt;	/* inode of mount point */
X					/* if null, then global */
X	struct socket	*r_sock;	/* socket with active connection */
X#define	r_age		r_msg.m_totlen	/* used for cacheing name lookups */
X#define	r_openerr	r_msg.m_errno	/* used to relay connection errors */
X	struct message	r_msg;		/* incomming message */
X};
X
Xtypedef int			(*func)();
X
X/*
X * This describes all info associated with each syscall.  Note that while
X * the flag information is available, most syscalls don't reference it
X * because they have the flag hard coded in-line.  It exists for the
X * sake of routines like read and write which cannot hard code the flags
X * very easily.  The follow flag is useful only for system calls that involve
X * pathnames.  The before entry is to tell syscall whether to try to
X * call the remote syscall routine before calling the real system call.
X * The size here make each table entry a
X * power of 2 in size (16 bytes) which the compiler can make faster code for.
X */
Xstruct syscalls {
X	func	sys_gen;
X	func	sys_spec;
X	long	sys_flag;
X	short	sys_follow;
X	short	sys_before;
X};
Xtypedef struct syscalls		syscalls;
X
X/*
X * This structure simply describes the process willing to act as a
X * name server for the remote file system, and the information passing
X * to and from it.
X */
Xstruct nameserver {
X	struct proc	*rn_proc;	/* process registered as nameserver */
X	struct mbuf	*rn_name;	/* input from name server */
X	char		*rn_path;	/* path to translate */
X	short		rn_pathlen;	/* length of path to translate */
X	short		rn_pid;		/* pid of process (for uniqueness) */
X};
X
X/*
X * System calls
X * Note that these have nothing to do with either the vax or magnolia idea
X * of the system calls.  They are simply an index into the systems calls
X * that we are concerned with.
X */
X#define	RSYS_fork	0
X#define	RSYS_read	1
X#define	RSYS_write	2
X#define	RSYS_open	3
X#define	RSYS_close	4
X#define	RSYS_creat	5
X#define	RSYS_link	6
X#define	RSYS_unlink	7
X#define	RSYS_chdir	8
X#define	RSYS_mknod	9
X#define	RSYS_chmod	10
X#define	RSYS_chown	11
X#define	RSYS_stat	12
X#define	RSYS_lseek	13
X#define	RSYS_access	14
X#define	RSYS_lstat	15
X#define	RSYS_dup	16
X#define	RSYS_ioctl	17
X#define	RSYS_symlink	18
X#define	RSYS_readlink	19
X#define	RSYS_fstat	20
X#define	RSYS_dup2	21
X#define	RSYS_fcntl	22
X#define	RSYS_fsync	23
X#define	RSYS_readv	24
X#define	RSYS_writev	25
X#define	RSYS_fchown	26
X#define	RSYS_fchmod	27
X#define	RSYS_rename	28
X#define	RSYS_truncate	29
X#define	RSYS_ftruncate	30
X#define	RSYS_flock	31
X#define	RSYS_mkdir	32
X#define	RSYS_rmdir	33
X#define	RSYS_utimes	34
X#define	RSYS_exit	35
X#define	RSYS_vfork	36
X#define	RSYS_execinfo	37
X#define	RSYS_execread	38
X#define RSYS_execve	39
X#define	RSYS_nosys	40
X#define	RSYS_qlseek	41
X
X/*
X * This macro fills in some of the information needed on every transfer
X * and returns the byte (not longword) offset of the next free byte.
X */
X#define introduce(buf, sysnum)						\
X				((buf)->m_pid = htons(u.u_procp->p_pid),\
X				 (buf)->m_uid = htons(u.u_uid),		\
X				 (buf)->m_syscall = htons(sysnum),	\
X				 (R_MINRMSG))
X#define introduce_1extra(buf, sysnum, x1)				\
X				((buf)->m_pid = htons(u.u_procp->p_pid),\
X				 (buf)->m_uid = htons(u.u_uid),		\
X				 (buf)->m_syscall = htons(sysnum),	\
X				 (buf)->m_args[0] = htonl(x1),		\
X				 (R_MINRMSG + sizeof(long)))
X#define introduce_2extra(buf, sysnum, x1, x2)				\
X				((buf)->m_pid = htons(u.u_procp->p_pid),\
X				 (buf)->m_uid = htons(u.u_uid),		\
X				 (buf)->m_syscall = htons(sysnum),	\
X				 (buf)->m_args[0] = htonl(x1),		\
X				 (buf)->m_args[1] = htonl(x2),		\
X				 (R_MINRMSG + 2*sizeof(long)))
X/*
X * This macro defines whether a host is being used or not.
X * The rmtclearhosts() and rmtcopyhosts() are for expansion if someone
X * wants to use more than 32 hosts.
X */
X#define	rmthostused(rsys)		(u.u_rmtsys  &  (1<<rsys))
X#define	rmtusehost(rsys)		(u.u_rmtsys  |= (1<<rsys))
X#define	rmtunusehost(rsys)		(u.u_rmtsys  &= ~(1<<rsys))
X#define	rmtclearhosts()			(u.u_rmtsys   =  0)
X#define	rmtcopyhosts(dest,hosts)	(dest         =  hosts)
X
X#ifdef pyr
X/*
X * Pyramid changed the name on ctob and btoc
X **/
X#define	ctob(x)	ptob(x)
X#define	btoc(x)	btop(x)
X#endif
SHAREOF
chmod 444 remote/usr.sys.remote/remotefs.h
#
# remote/usr.sys.remote/rmt_data_template
#
if [ -f remote/usr.sys.remote/rmt_data_template ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.remote/rmt_data_template or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.remote/rmt_data_template 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/rmt_data_template
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Header: rmt_data_template,v 2.0 85/12/07 18:19:42 toddb Rel $
X *
X * $Log:	rmt_data_template,v $
X * Revision 2.0  85/12/07  18:19:42  toddb
X * First public release.
X * 
X */
X#include	"../h/errno.h"
X#include	"../h/param.h"
X#include	"../h/mbuf.h"
X#include	"../h/socket.h"
X#include	"../remote/remotefs.h"
X
X
Xextern int
X		rmt_access(),
X		rmt_chdir(),
X		rmt_chmod(),
X		rmt_chown(),
X		rmt_dup(),
X		rmt_dup2(),
X		rmt_error(),
X		remote_exit(),
X		rmt_fcntl(),
X		rmt_flock(),
X		remote_fork(),
X		rmt_fsync(),
X		rmt_ioctl(),
X		rmt_lseek(),
X		rmt_mknod(),
X		rmt_noop(),
X		rmt_onearg(),
X		rmt_open(),
X		rmt_readlink(),
X		rmt_stat(),
X		rmt_truncate(),
X		rmt_utimes(),
X		rmt_execinfo(),
X		rmt_execread(),
X		rmt_execve(),
X		remote_fd(),
X		remote_path1(),
X		remote_path2(),
X		rmt_datafin();
X
X/*
X * This table depends on the order of system calls as defined in
X * sys/sys/init_sysent.c, and our local map in remote_sysmap, which
X * is generated (and appended to this file) by the program mkdata.
X * The latter is a table of indices into remote_syscall[].
X * Remote_syscall[] is a table containing general and specific actions
X * for each system call, whether to follow symbolic links in namei and
X * flags that are passed to rmt_msgfin() and rmt_datafin().
X */
X
Xsyscalls	remote_syscall[] = {
X/*
X * general	specific    flags to	follow	call before
X *			  rmt_fin()   symlinks	real syscall
X */
X{ remote_fork,	rmt_noop,    RFLG_INFO,	FALSE,	TRUE	}, /* RSYS_fork */
X{ remote_fd,	rmt_datafin,  RFLG_RD,	FALSE,	TRUE	}, /* RSYS_read */
X{ remote_fd,	rmt_datafin,  RFLG_WR,	FALSE,	TRUE	}, /* RSYS_write */
X{ remote_path1,	rmt_open,	0,	TRUE,	FALSE	}, /* RSYS_open */
X{ remote_fd,	rmt_onearg,  RFLG_INFO,	FALSE,	TRUE	}, /* RSYS_close */
X{ remote_path1,	rmt_open,	0,	TRUE,	FALSE	}, /* RSYS_creat */
X{ remote_path2,	rmt_noop,	0,	FALSE,	FALSE	}, /* RSYS_link */
X{ remote_path1,	rmt_onearg,	0,	FALSE,	FALSE	}, /* RSYS_unlink */
X{ remote_path1,	rmt_chdir,	0,	TRUE,	FALSE	}, /* RSYS_chdir */
X{ remote_path1,	rmt_mknod,	0,	FALSE,	FALSE	}, /* RSYS_mknod */
X{ remote_path1,	rmt_chmod,	0,	TRUE,	FALSE	}, /* RSYS_chmod */
X{ remote_path1,	rmt_chown,	0,	FALSE,	FALSE	}, /* RSYS_chown */
X{ remote_path1,	rmt_stat,	0,	TRUE,	FALSE	}, /* RSYS_stat */
X{ remote_fd,	rmt_lseek,	0,	FALSE,	TRUE	}, /* RSYS_lseek */
X{ remote_path1,	rmt_access,	0,	FALSE,	FALSE	}, /* RSYS_lstat */
X{ remote_path1,	rmt_stat,	0,	TRUE,	FALSE	}, /* RSYS_access */
X{ remote_fd,	rmt_dup,	0,	FALSE,	TRUE	}, /* RSYS_dup */
X{ remote_fd,	rmt_ioctl,	0,	FALSE,	TRUE	}, /* RSYS_ioctl */
X{ remote_path2,	rmt_noop,	0,	TRUE,	FALSE	}, /* RSYS_symlink */
X{ remote_path1,	rmt_readlink,  RFLG_RD,	FALSE,	FALSE	}, /* RSYS_readlink */
X{ remote_fd,	rmt_stat,	0,	FALSE,	TRUE	}, /* RSYS_fstat */
X{ remote_fd,	rmt_dup2,	0,	FALSE,	TRUE	}, /* RSYS_dup2 */
X{ remote_fd,	rmt_fcntl,	0,	FALSE,	TRUE	}, /* RSYS_fcntl */
X{ remote_fd,	rmt_onearg,  RFLG_INFO,	FALSE,	TRUE	}, /* RSYS_fsync */
X{ remote_fd,	rmt_datafin, RFLG_RD|RFLG_DATAV,
X					FALSE,	TRUE	},/* RSYS_readv */
X{ remote_fd,	rmt_datafin, RFLG_WR|RFLG_DATAV,
X					FALSE,	TRUE	},/* RSYS_writev */
X{ remote_fd,	rmt_chown,	0,	FALSE,	TRUE	}, /* RSYS_fchown */
X{ remote_fd,	rmt_chmod,	0,	FALSE,	TRUE	}, /* RSYS_fchmod */
X{ remote_path2,	rmt_noop,	0,	TRUE,	FALSE	}, /* RSYS_rename */
X{ remote_path1,	rmt_truncate,	0,	TRUE,	FALSE	}, /* RSYS_truncate */
X{ remote_fd,	rmt_truncate,	0,	FALSE,	TRUE	}, /* RSYS_ftruncate */
X{ remote_fd,	rmt_flock,	0,	FALSE,	TRUE	}, /* RSYS_flock */
X{ remote_path1,	rmt_mknod,	0,	FALSE,	FALSE	}, /* RSYS_mkdir */
X{ remote_path1,	rmt_onearg,	0,	FALSE,	FALSE	}, /* RSYS_rmdir */
X{ remote_path1,	rmt_noop,	0,	TRUE,	FALSE	}, /* RSYS_utimes */
X{ remote_exit,	rmt_noop,      RFLG_INFO,FALSE,	TRUE	}, /* RSYS_exit */
X{ remote_fork,	rmt_noop,    RFLG_INFO,	FALSE,	TRUE	}, /* RSYS_vfork */
X{ remote_path1,	rmt_execinfo,	0,	TRUE,	FALSE	}, /* RSYS_execinfo */
X{ rmt_error,	rmt_noop,	0,	FALSE,	FALSE	}, /* RSYS_execread */
X{ remote_path1,	rmt_error,	0,	TRUE,	FALSE	}, /* RSYS_execve */
X{ rmt_error,	rmt_noop,	0,	FALSE,	FALSE	}, /* RSYS_nosys */
X{ rmt_error,	rmt_noop,	0,	FALSE,	FALSE	}, /* RSYS_qlseek */
X};
X
Xstruct remoteinfo	remote_info[ R_MAXSYS ];
Xstruct remoteinfo	*remote_generic;
Xlong			remote_debug;
Xlong			remote_sysindex;
Xlong			remote_maxchunk = (1024*10);
Xstruct mbuf		*remote_path;
Xstruct nameserver	remote_ns;
X
X/*
X * The following list maps all of the actual system call numbers into our
X * idea of the system call numbers.  THIS IS GENERATED AUTOMATICALLY...
X * DO NOT MODIFY!
X */
SHAREOF
chmod 444 remote/usr.sys.remote/rmt_data_template
#
# remote/usr.sys.remote/rmt_exec.c
#
if [ -f remote/usr.sys.remote/rmt_exec.c ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.remote/rmt_exec.c or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.remote/rmt_exec.c 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/rmt_exec.c
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Header: rmt_exec.c,v 2.1 85/12/30 16:45:30 toddb Exp $
X *
X * $Log:	rmt_exec.c,v $
X * Revision 2.1  85/12/30  16:45:30  toddb
X * fixed syntax error for 4.3.
X * 
X * Revision 2.0  85/12/07  18:17:54  toddb
X * First public release.
X * 
X */
X#ifndef pyr /* Pyramid */
X#include	"../machine/reg.h"
X#include	"../machine/pte.h"
X#include	"../machine/psl.h"
X#endif
X
X#include	"../h/param.h"
X#include	"../h/systm.h"
X#include	"../h/map.h"
X#include	"../h/dir.h"
X#include	"../h/user.h"
X#include	"../h/kernel.h"
X#include	"../h/proc.h"
X#include	"../h/file.h"
X#include	"../h/uio.h"
X#include	"../remote/remotefs.h"
X#include	"../h/mbuf.h"
X#include	"../netinet/in.h"
X#include	"../h/vm.h"
X#include	"../h/errno.h"
X#ifdef BSD4_3
X#include	"../h/namei.h"
X#include	"../h/exec.h"
X#else BSD4_3
X#include	"../h/nami.h"
X#endif BSD4_3
X
X#ifdef vax
X#include "../vax/mtpr.h"
X#endif
X
Xextern struct remoteinfo	remote_info[];
Xextern long			remote_sysindex;
Xextern long			remote_maxchunk;
X
X#ifdef magnolia
X#define	DEMAND_PAGED	0513
X#define	SHARED_TEXT	0510
X#else magnolia
X#define	DEMAND_PAGED	0413
X#define	SHARED_TEXT	0410
X#endif magnolia
X
X/*
X * Get execution info for a file that is on a remote system.  At this point
X * we know that the file is remote.  We must send one request to get the
X * header and then if all is ok, we will be asked for the file to be sent over
X * en-masse.
X */
X#ifdef BSD4_3
Xremote_execinfo(ip, auid, agid, pexdata, fname)
X	struct exec	*pexdata;
X#else BSD4_3
Xremote_execinfo(ip, auid, agid, fname)
X#endif BSD4_3
X	register struct inode	**ip;
X	long	*auid, *agid;
X	register char	*fname;
X{
X	long	error,
X		sysindex = remote_sysindex,
X		uid, gid,
X		hdrsize,
X		execsize;
X	struct inode	*namei();
X	struct remoteinfo	*rp = remote_info + remote_sysindex;
X	struct message	*msg;
X
X	u.u_error = 0;
X	error = remote_path1(RSYS_execinfo);
X	if (error) {
X		/*
X		 * Try again if its a local file.
X		 */
X		if (error < 0 && fname) {
X#ifdef BSD4_3
X			struct nameidata *ndp = &u.u_nd;
X
X			ndp->ni_dirp = (caddr_t) fname;
X			if ((*ip = namei(ndp)) == NULL)
X#else BSD4_3
X			u.u_dirp = (caddr_t) fname;
X			if ((*ip = namei(uchar, LOOKUP, 1)) == NULL)
X#endif BSD4_3
X				if (u.u_error == 0 || u.u_error == EISREMOTE)
X					u.u_error = ELOOP;
X			return(remote_sysindex);
X		}
X		else if (error < 0)
X			error = ENOENT;
X		u.u_error = error;
X		return(-1);
X	}
X	/*
X	 * The R_RETVAL cell contains the total size of the file.  So that
X	 * had better be >= the size of the header + size of text + size
X	 * of data.
X	 */
X	msg = &rp->r_msg;
X#ifdef BSD4_3
X	bcopy(msg->m_args+R_EXECDATA,
X		(caddr_t)pexdata, sizeof(struct exec));
X	if (pexdata->a_magic == DEMAND_PAGED)
X		hdrsize = CLBYTES;
X	else
X		hdrsize = sizeof(sizeof(struct exec));
X#else BSD4_3
X	bcopy(msg->m_args+R_EXECDATA,
X		(caddr_t)&u.u_exdata, sizeof (u.u_exdata));
X	if (u.u_exdata.ux_mag == DEMAND_PAGED)
X		hdrsize = CLBYTES;
X	else
X		hdrsize = sizeof(u.u_exdata.Ux_A);
X#endif BSD4_3
X
X	execsize = ntohl(msg->m_args[ R_RETVAL ]);
X	debug0("obj=%d,hrd=%d,error=%d,tx=%d,dat=%d\n",
X		execsize, hdrsize, u.u_error,
X#ifdef BSD4_3
X		pexdata->a_text, pexdata->a_text
X#else BSD4_3
X		u.u_exdata.ux_tsize, u.u_exdata.ux_dsize
X#endif BSD4_3
X		);
X
X#ifdef BSD4_3
X	if (pexdata->a_text + pexdata->a_data + hdrsize > execsize
X	 && *((char *)pexdata) != '#') {
X		error = ENOEXEC;
X		goto bad;
X	}
X#else BSD4_3
X	if (u.u_exdata.ux_tsize + u.u_exdata.ux_dsize + hdrsize > execsize
X	 && u.u_exdata.ux_shell[0] != '#') {
X		error = ENOEXEC;
X		goto bad;
X	}
X#endif BSD4_3
X
X	if ((u.u_procp->p_flag&STRC) && msg->m_args[ R_EXECREADONLY ]) {
X		error = EACCES;
X		goto bad;
X	}
X	if (auid) { /* first time thru for this exec... set uid/gid stuff */
X		uid = ntohl(msg->m_args[ R_EXECUID ]);
X		if (uid < 0)
X			uid = u.u_uid;
X		gid = ntohl(msg->m_args[ R_EXECGID ]);
X		if (gid < 0)
X			gid = u.u_gid;
X		*auid = uid;
X		*agid = gid;
X	}
X	return(sysindex);
X
Xbad:
X	u.u_error = error;
X	return(-1);
X}
X
X/*
X * This is the simple routine that is called by remote_path1 as the
X * specific routine for handling RSYS_execinfo.  remote_execinfo() is
X * called from exec, and remote_execinfo() calls remote_path1() who in
X * turn calls rmt_execinfo().
X */
Xrmt_execinfo(sysindex, m)
X	long	sysindex;
X	struct mbuf	*m;
X{
X	struct message *msg = mtod(m, struct message *);
X#ifdef BSD4_3
X	msg->m_args[0] = htonl(sizeof (struct exec));
X#else BSD4_3
X	msg->m_args[0] = htonl(sizeof (u.u_exdata));
X#endif BSD4_3
X	return (rmt_msgfin(sysindex, m, 0));
X}
X
X/*
X * Read into memory an executable file from a remote system.
X */
X#ifdef BSD4_3
Xremote_execread(sysindex, oldtextsize, ep)
X	register struct exec *ep;
X	register int	sysindex, oldtextsize;
X#else BSD4_3
Xremote_execread(sysindex, oldtextsize)
X	register int	sysindex, oldtextsize;
X#endif BSD4_3
X{
X	struct remoteinfo	*rp = remote_info + sysindex;
X	struct uio auio;
X	struct iovec aiov[2];
X	struct mbuf	*m;
X	struct message	*msg;
X	register long	hdrsize, datasize, textsize, error, len, magic;
X	register struct proc	*p = u.u_procp;
X	long	iovlen;
X
X#ifdef BSD4_3
X	datasize = (int)ep->a_data;
X	magic = ep->a_magic;
X#define HEADERSIZE	sizeof(struct exec);
X#else BSD4_3
X	datasize = (int)u.u_exdata.ux_dsize;
X	magic = u.u_exdata.ux_mag;
X#define HEADERSIZE	sizeof(u.u_exdata.Ux_A);
X#endif BSD4_3
X	if (datasize <= 0) {
X		u.u_error = ENOEXEC;
X		return(-1);
X	}
X
X	/*
X	 * We are guarenteed that at this point the text size is zero.
X	 * But we know what the old text size was passed along for the sake of
X	 * shared-text programs:  the binaries for these do not
X	 * necessarily have the data page-aligned in the file (as we
X	 * assume that demand-paged programs do), but instead,
X	 * it is aligned when it is read in.  We must do the same here.
X	 */
X	if (oldtextsize && magic == SHARED_TEXT) {
X		aiov[0].iov_len = oldtextsize;
X		aiov[1].iov_len = datasize - oldtextsize;
X		iovlen = 2;
X		aiov[0].iov_base = (char *)ctob(tptov(p, 0));
X		aiov[1].iov_base = (char *)ctob(btoc(oldtextsize));
X		debug0("execrd: %d @ %x, %d @ %x ",
X			aiov[0].iov_len, aiov[0].iov_base,
X			aiov[1].iov_len, aiov[1].iov_base);
X	}
X	else {
X		iovlen = 1;
X		aiov[0].iov_base = (char *)ctob(dptov(p, 0)),
X		aiov[0].iov_len = datasize;
X		debug0("execrd: %d @ %x ", aiov[0].iov_len, aiov[0].iov_base);
X	}
X	auio.uio_offset = 0;
X	auio.uio_segflg = 0;
X	if (magic == DEMAND_PAGED)
X		hdrsize = CLBYTES;
X	else
X		hdrsize = HEADERSIZE;
X
X	/*
X	 * Now ask for it in remote_maxchunk size chunks.
X	 */
X	debug0("hdsz=%d, datasz=%d, rd ", hdrsize, datasize);
X	error = 0;
X	while (datasize >= 0) {
X		auio.uio_resid = MIN(datasize, remote_maxchunk);
X		if (auio.uio_resid == 0)
X			datasize = -1;
X		else {
X			if (aiov[0].iov_len <= 0 && iovlen == 2) {
X				aiov[0] = aiov[1];
X				iovlen = 1;
X			}
X			auio.uio_iov = aiov;
X			auio.uio_iovcnt = iovlen;
X			datasize -= auio.uio_resid;
X		}
X		MGET(m, M_WAIT, MT_DATA);
X		if (m == NULL)
X			return(ENOBUFS);
X		msg = mtod(m, struct message *);
X		len = introduce_2extra(msg, RSYS_execread, hdrsize,
X			auio.uio_resid);
X		m->m_len = len;
X		msg->m_hdlen = htons(len);
X		msg->m_totlen = htonl(len);
X#ifdef RFSDEBUG
X		if (auio.uio_resid) {
X			debug0("\n %d: %d@%d", auio.uio_resid,
X				aiov[0].iov_len, aiov[0].iov_base);
X			if (iovlen == 2)
X				debug0(",%d@%d.",
X					aiov[1].iov_len, aiov[1].iov_base);
X		}
X		rmt_showmsg(msg, FALSE);
X#endif RFSDEBUG
X		if (datasize >= 0)
X			error = remoteio(sysindex, &m, &auio, RFLG_RD);
X		else
X			remoteio(sysindex, &m, 0, RFLG_INFO);
X#ifdef RFSDEBUG
X		msg = &rp->r_msg;
X		rmt_showmsg(msg, TRUE);
X#endif RFSDEBUG
X		/*
X		 * If there are any errors, simply send the last
X		 * message: we're all done.
X		 */
X		if (error && datasize >= 0)
X			datasize = 0;
X		else if (error)
X			return(error);
X	}
X
X	debug0("\n");
X	return ( error );
X}
SHAREOF
chmod 444 remote/usr.sys.remote/rmt_exec.c
#
# remote/usr.sys.remote/rmt_final.c
#
if [ -f remote/usr.sys.remote/rmt_final.c ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.remote/rmt_final.c or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.remote/rmt_final.c 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/rmt_final.c
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Header: rmt_final.c,v 2.1 85/12/30 16:51:01 toddb Exp $
X *
X * $Log:	rmt_final.c,v $
X * Revision 2.1  85/12/30  16:51:01  toddb
X * Made rmt_copypath() compatible between 4.2 and 4.3 by adding a c-version
X * of copystr() and copyinstr() for 4.2 versions (copystr() and copyinstr()
X * are assembler routines in 4.3).
X * 
X * Revision 2.0  85/12/07  18:20:12  toddb
X * First public release.
X * 
X */
X#include	"../h/param.h"
X#ifndef pyr /* Pyramid */
X#include	"../machine/pte.h"
X#endif
X#include	"../h/systm.h"
X#include	"../h/map.h"
X#include	"../h/dir.h"
X#include	"../h/user.h"
X#include	"../h/kernel.h"
X#include	"../h/proc.h"
X#include	"../h/mbuf.h"
X#include	"../h/socket.h"
X#include	"../h/file.h"
X#include	"../remote/remotefs.h"
X#include	"../h/errno.h"
X#include	"../netinet/in.h"
X#include	"../h/uio.h"
X
Xextern struct remoteinfo	remote_info[];
X
X/*
X * rmt_msgfin() finalizes the message by adding in the header and total
X * lengths and sending the message.  It returns the return value found in the
X * reply.
X */
Xrmt_msgfin(sysindex, m, flags)
X	long	sysindex, flags;
X	struct mbuf	*m;
X{
X	long	error, len;
X	struct message	*msg = mtod(m, struct message *);
X	struct remoteinfo	*rp = remote_info + sysindex;
X
X	/*
X	 * If the length has been set (by remote_path[12]), then don't
X	 * meddle, otherwise assign it.
X	 */
X	if (msg->m_hdlen == 0)
X		len = m->m_len;
X	else
X		len = msg->m_hdlen;
X	msg->m_hdlen = htons(len);
X	msg->m_totlen = htonl(len);
X		
X	rmt_showmsg(msg, FALSE);
X	error = remoteio(sysindex, &m, 0, flags);
X
X	if (! error) {
X		if ((flags & RFLG_INFO) == 0) {
X			msg = &rp->r_msg;
X			rmt_showmsg(msg, TRUE);
X			if ((error = msg->m_errno) == 0)
X				u.u_r.r_val1 = msg->m_args[R_RETVAL];
X		}
X		else
X			u.u_r.r_val1 = 0;
X	}
X	return ( error );
X}
X
X/*
X * rmt_datafin() finalizes a message and fixes up the header and total
X * lengths (like rmt_msgfin()) and sends a message plus data.  It returns
X * the return value found in the reply.
X */
Xrmt_datafin(sysindex, m, flags)
X	long	sysindex, flags;
X	struct mbuf	*m;
X{
X	register long	i, error, len;
X	struct message	*msg = mtod(m, struct message *);
X	short	syscall = ntohs(msg->m_syscall);
X	struct remoteinfo	*rp = remote_info + sysindex;
X	struct uio auio, *uio;
X	struct iovec aiov[16], *iov = aiov;
X	struct a {
X		long	fd;
X		char	*databuf;
X		long	datalen;
X	} *uap = (struct a *)u.u_ap;
X
X	/*
X	 * Package up the data.
X	 * If the length has been set (by remote_path1 for readlink),
X	 * then don't meddle, otherwise assign it the length of the first
X	 * (and only) mbuf.
X	 */
X	if (msg->m_hdlen == 0)
X		msg->m_hdlen = htons(len = m->m_len);
X	else
X		msg->m_hdlen = htons(len = msg->m_hdlen);
X	if (flags & (RFLG_RD | RFLG_WR)) {
X		uio = &auio;
X		uio->uio_iov = iov;
X		uio->uio_segflg = 0;
X		uio->uio_offset = 0;
X		if (flags & RFLG_DATAV) {
X			uio->uio_iovcnt = uap->datalen;
X			error = copyin((caddr_t)uap->databuf, (caddr_t)iov,
X			    (unsigned)(uap->datalen * sizeof (struct iovec)));
X			if (error)
X				goto done;
X			uio->uio_resid = 0;
X			for (i = 0; i < uio->uio_iovcnt; i++) {
X				if (iov->iov_len < 0) {
X					error = EINVAL;
X					goto done;
X				}
X				uio->uio_resid += iov->iov_len;
X				iov++;
X			}
X		}
X		else {
X			iov->iov_base = uap->databuf;
X			iov->iov_len = uio->uio_resid = uap->datalen;
X			uio->uio_iovcnt = 1;
X		}
X		if (uio->uio_resid < 0) {
X			error = EINVAL;
X			goto done;
X		}
X		if (flags & RFLG_WR)
X			msg->m_totlen = htonl(len + uio->uio_resid);
X		else
X			msg->m_totlen = htonl(len);
X	}
X	else {
X		uio = NULL;
X		msg->m_totlen = htonl(len);
X	}
X	rmt_showmsg(msg, FALSE);
X	error = remoteio(sysindex, &m, uio, flags);
X	m = NULL;
X	if (error)
X		goto done;
X
X	msg = &rp->r_msg;
X	rmt_showmsg(msg, TRUE);
X	if ((error = msg->m_errno) == 0)
X		u.u_r.r_val1 = msg->m_args[R_RETVAL];
Xdone:
X	if (m)
X		m_free(m);
X	return ( error );
X}
X
X/*
X * Copy a path into a string of mbufs.  The source pointer may be in user
X * space, in which case we must use uchar() to copy.  Note that this routine
X * expects 'm' to point to the first mbuf in the current chain:  it will
X * append to the end of the chain, and update the length of the message
X * in msg->m_hdlen.
X */
Xrmt_copypath(psrc, m, copy_from_user)
X	register char	*psrc;
X	register struct mbuf	*m;
X{
X	register char	*pdest;
X	register int	error,
X			totlen,
X			room;
X	register struct mbuf	*m2;
X	struct message	*msg = mtod(m, struct message *);
X	int		copystr(),
X			copyinstr(),
X			got;
X	func		copier = copy_from_user ? copyinstr : copystr;
X
X	/*
X	 * find the end of the mbuf chain.
X	 */
X	while (m->m_next)
X		m = m->m_next;
X	m2 = m;
X	pdest = mtod(m, char *) + m->m_len;
X	totlen = msg->m_hdlen;
X
X	debug2("copy %s path @%x-->%x, len=%d\n",
X		copy_from_user ? "user" : "kernel", psrc, pdest, totlen);
X
X	room = MLEN - m->m_len;
X	for(;;) {
X		got = 0;	/* copy*str adds copied bytes to 'got' */
X		error = (*copier)(psrc, pdest, room, (u_int *)&got);
X		if (error && error != ENOENT)
X			return(error);
X		m2->m_len += got;
X		totlen += got;
X		if (got < room)
X			break;
X		MGET(m, M_WAIT, MT_DATA);
X		if (m == NULL)
X			return(ENOBUFS);
X		m2 = m2->m_next = m;
X		m2->m_len = 0;
X		room = MLEN;
X		pdest = mtod(m2, char *);
X		psrc += got;
X	}
X	msg->m_hdlen = totlen;
X	debug2("len now=%d\n", totlen);
X
X	return(0);
X}
X
X#ifdef BSD4_3
X#else BSD4_3
X/*
X * C version of copyinstr() from 4.3.
X */
Xcopyinstr(src, dest, maxlength, lencopied)
X	register char	*src, *dest;
X	register int	maxlength;
X	register int	*lencopied;
X{
X	register int	c;
X	int		dummy;
X
X	if (!maxlength)
X		return(EFAULT);
X	if (lencopied == NULL)
X		lencopied = &dummy;
X	for(;;) {
X		c = *dest++ = fubyte(src++);
X		if (c == -1) {
X			*(dest-1) = 0;
X			return(EFAULT);
X		}
X		if (--maxlength < 0)
X			return(ENOENT);
X		(*lencopied)++;
X		if (c == 0)
X			return(0);
X	}
X}
X
X/*
X * C version of copystr() from 4.3.
X */
Xcopystr(src, dest, maxlength, lencopied)
X	register char	*src, *dest;
X	register int	maxlength;
X	register int	*lencopied;
X{
X	int		dummy;
X
X	if (!maxlength)
X		return(EFAULT);
X	if (lencopied == NULL)
X		lencopied = &dummy;
X	for(;;) {
X		if (--maxlength < 0)
X			return(ENOENT);
X		(*lencopied)++;
X		if ((*dest++ = *src++) == 0)
X			return(0);
X	}
X}
X#endif BSD4_3
X
X#ifdef RFSDEBUG
X
Xrmt_debug(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
X{
X	printf(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
X}
X
Xrmt_showmsg(msg, fromserver)
X	struct message	*msg;
X	int	fromserver;
X{
X	long	end, len, pid, uid, totlen;
X
X	if ((remote_debug & 0x18000) == 0)
X		return;
X	if (fromserver)
X		len = msg->m_hdlen,
X		totlen = msg->m_totlen,
X		pid = msg->m_pid,
X		uid = msg->m_uid;
X	else
X		len = ntohs(msg->m_hdlen),
X		totlen = ntohl(msg->m_totlen),
X		pid = ntohs(msg->m_pid),
X		uid = ntohs(msg->m_uid);
X	debug15("%s srvr: len=%d,tot=%d,pid=%d,uid=%d",
X		fromserver ? "from" : "to", len, totlen, pid, uid);
X
X	/* round up into long words */
X	len = (len - R_MINRMSG + 3) >> 2;
X	if (fromserver)
X	{
X		debug15(",err=%d,ret=%d",
X			msg->m_errno,
X			msg->m_args[ R_RETVAL ]);
X		end = R_RETVAL+1;
X	}
X	else
X	{
X		debug15(",syscall=%d", htons(msg->m_syscall));
X		end = 0;
X	}
X	for (; end<len; end++)
X		debug16(",0x%x", ntohl(msg->m_args[ end ]));
X	rmt_debug("\n");
X}
X#endif RFSDEBUG
SHAREOF
chmod 444 remote/usr.sys.remote/rmt_final.c
#
# remote/usr.sys.remote/rmt_syscall3.c
#
if [ -f remote/usr.sys.remote/rmt_syscall3.c ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.remote/rmt_syscall3.c or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.remote/rmt_syscall3.c 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.remote/rmt_syscall3.c
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Header: rmt_syscall3.c,v 2.0 85/12/07 18:19:35 toddb Rel $
X *
X * $Log:	rmt_syscall3.c,v $
X * Revision 2.0  85/12/07  18:19:35  toddb
X * First public release.
X * 
X */
X#include	"../h/param.h"
X#ifndef pyr	/* Pyramid */
X#include	"../machine/pte.h"
X#endif
X#include	"../h/systm.h"
X#include	"../h/map.h"
X#include	"../h/dir.h"
X#include	"../h/user.h"
X#include	"../h/kernel.h"
X#include	"../h/proc.h"
X#include	"../h/inode.h"
X#include	"../h/mbuf.h"
X#include	"../h/socket.h"
X#include	"../remote/remotefs.h"
X#include	"../h/file.h"
X#include	"../h/stat.h"
X#include	"../h/errno.h"
X#include	"../netinet/in.h"
X
Xextern long	rmtrw(), rmtioctl(), rmtselect(), rmtclose();
Xstruct 	fileops remoteops =
X	{ rmtrw, rmtioctl, rmtselect, rmtclose };
Xrmtrw()	{ return(0); }
Xrmtioctl()	{ return(0); }
Xrmtselect()	{ return(0); }
Xrmtclose()	{ return(0); }
X
Xextern struct remoteinfo	remote_info[];
Xextern struct remoteinfo	*remote_generic;
X
X/*
X * Remote open()
X */
Xrmt_open (sysindex, m)
X	long	sysindex;
X	struct mbuf	*m;
X{
X	register long	fd, error;
X	register struct message *msg = mtod(m, struct message *);
X	register struct file	*fp;
X	struct file		*falloc();
X	register struct a {
X		char	*path;
X		long	flags,
X			mode;
X	} *uap = (struct a *)u.u_ap;
X
X	/*
X	 * Initialize the file structure.
X	 */
X	if ((fp = falloc()) == NULL)
X		return(-1);
X	fp->f_type = DTYPE_REMOTE;
X	fp->f_ops = &remoteops;
X	fd = u.u_r.r_val1;
X	fp->f_data = (caddr_t)sysindex;
X	fp->f_flag = (uap->mode&FMASK) | FREMOTE;
X	remote_info[ sysindex ].r_nfile++;
X
X	if (ntohs(msg->m_syscall) == RSYS_creat) {
X		uap->mode = uap->flags;
X		uap->flags = FWRITE|FCREAT|FTRUNC;
X		msg->m_syscall = htons(RSYS_open);
X	}
X	msg->m_args[ 0 ] = htonl(uap->flags);
X	msg->m_args[ 1 ] = htonl(uap->mode);
X	msg->m_args[ 2 ] = htonl(fd);
X	msg->m_args[ 3 ] = htonl(u.u_cmask);
X
X	/*
X	 * Now send it.
X	 */
X	error = rmt_msgfin(sysindex, m, 0);
X	if (error)
X		rmt_deallocfd(fd);
X	else {
X		msg = &remote_info[ sysindex ].r_msg;
X		fp->f_offset = msg->m_args[1];
X	}
X	return(error);
X}
X
X/*
X * Remote readlink()
X */
Xrmt_readlink (sysindex, m)
X	long	sysindex;
X	struct mbuf	*m;
X{
X	struct message	*msg = mtod(m, struct message *);
X	struct a {
X		char	*path;
X		char	*buf;
X		long	len;
X	} *uap = (struct a *)u.u_ap;
X
X
X	msg->m_args[ 0 ] = htonl(uap->len);
X	/*
X	 * Now send it.
X	 */
X	return( rmt_datafin(sysindex, m, RFLG_RD) );
X}
X
X/*
X * Remote stat() and lstat() and fstat()
X */
Xrmt_stat (sysindex, m)
X	long	sysindex;
X	struct mbuf	*m;
X{
X	long	error, i;
X	struct message *msg = mtod(m, struct message *);
X	struct remoteinfo *rp = remote_info + sysindex;
X	struct a {
X		long	fd_or_path;
X		struct stat	*statp;
X	} *uap = (struct a *)u.u_ap;
X	struct stat	st;
X
X	if (ntohl(msg->m_syscall) == RSYS_fstat)
X		m->m_len = R_MINRMSG + sizeof(long);
X	if (error = rmt_msgfin(sysindex, m, 0))
X		return( error );
X	msg = &rp->r_msg;
X	i = R_RETVAL + 1;
X	st.st_dev	  = ntohl(msg->m_args[ i++ ]);
X	st.st_ino	  = ntohl(msg->m_args[ i++ ]);
X	st.st_mode	  = ntohl(msg->m_args[ i++ ]);
X	st.st_nlink	  = ntohl(msg->m_args[ i++ ]);
X	st.st_uid	  = ntohl(msg->m_args[ i++ ]);
X	st.st_gid	  = ntohl(msg->m_args[ i++ ]);
X	st.st_rdev	  = ntohl(msg->m_args[ i++ ]);
X	st.st_size	  = ntohl(msg->m_args[ i++ ]);
X	st.st_atime	  = ntohl(msg->m_args[ i++ ]);
X	st.st_mtime	  = ntohl(msg->m_args[ i++ ]);
X	st.st_ctime	  = ntohl(msg->m_args[ i++ ]);
X	st.st_blksize	  = ntohl(msg->m_args[ i++ ]);
X	st.st_blocks 	  = ntohl(msg->m_args[ i++ ]);
X	st.st_spare1 = sysindex+1;
X	st.st_spare2 = 0;
X	st.st_spare3 = 0;
X	st.st_spare4[0] = st.st_spare4[1] = 0;
X	if (msg->m_args[ i ]) { /* this is the remote root */
X		if (rp->r_mntpt == NULL)
X			rp = remote_generic;
X		if (rp && rp->r_mntpt != NULL) {
X			st.st_dev = rp->r_mntpt->i_dev;
X			st.st_ino = rp->r_mntpt->i_number;
X		}
X	}
X	(void)copyout((caddr_t)&st, (caddr_t)uap->statp, sizeof(struct stat));
X	return(0);
X}
X
X/*
X * Remote truncate() and ftrucate()
X */
Xrmt_truncate (sysindex, m)
X	long	sysindex;
X	struct mbuf	*m;
X{
X	long	i = 0;
X	struct message *msg = mtod(m, struct message *);
X	struct a {
X		long	fd_or_path;
X		long	len;
X	} *uap = (struct a *)u.u_ap;
X
X	if (htons(msg->m_syscall) == RSYS_ftruncate)
X		i++;
X	msg->m_args[ i ] = htonl(uap->len);
X	/*
X	 * Now send it.
X	 */
X	return( rmt_msgfin(sysindex, m, 0) );
X}
X
X/*
X * Remote utimes()
X */
Xrmt_utimes (sysindex, m)
X	long	sysindex;
X	struct mbuf	*m;
X{
X	struct message	*msg = mtod(m, struct message *);
X	struct a {
X		char	*path;
X		struct timeval	*timevalp;
X	} *uap = (struct a *)u.u_ap;
X	struct timeval	*tv = uap->timevalp;
X
X	msg->m_args[ 0 ] = htonl(tv[0].tv_sec);
X	msg->m_args[ 1 ] = htonl(tv[0].tv_usec);
X	msg->m_args[ 2 ] = htonl(tv[1].tv_sec);
X	msg->m_args[ 3 ] = htonl(tv[1].tv_usec);
X
X	/*
X	 * Now send it.
X	 */
X	return( rmt_msgfin(sysindex, m, 0) );
X}
SHAREOF
chmod 444 remote/usr.sys.remote/rmt_syscall3.c



More information about the Mod.sources mailing list