[net.sources] release #2, shar 6 of 7

toddb@tekcrl.UUCP (Todd Brunhoff) (03/11/86)

#!/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/h/user.h.diff
#	remote/usr.sys.VAX4.3/machine/trap.c.diff
#	remote/usr.sys.VAX4.3/sys/init_sysent.c.diff
#	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_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/h/user.h.diff
#
if [ -f remote/usr.sys.VAX4.3/h/user.h.diff ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.VAX4.3/h/user.h.diff or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.VAX4.3/h/user.h.diff 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.VAX4.3/h/user.h.diff
XThese changes keep track of the per-process RFS information.
X***************
X*** 121,126
X  	} u_ncache;
X  	struct	nameidata u_nd;
X  
X  	int	u_stack[1];
X  };
X  
X
X--- 121,137 -----
X  	} u_ncache;
X  	struct	nameidata u_nd;
X  
X+ #ifdef REMOTEFS
X+ 	short	u_rmtoffset[2];		/* path offset for local segment */
X+ 	short	u_rmtcdir;		/* system # of remote current dir */
X+ 	long	u_rmtsys;		/* room for 32 systems */
X+ 					/* one bit for each remote system */
X+ #ifdef pyr /* Pyramid */
X+ 	int	*u.u_ap;
X+ #define		u_arg	u_ap
X+ #endif pyr
X+ #endif REMOTEFS
X+ 
X  	int	u_stack[1];
X  };
X  
SHAREOF
chmod 664 remote/usr.sys.VAX4.3/h/user.h.diff
#
# remote/usr.sys.VAX4.3/machine/trap.c.diff
#
if [ -f remote/usr.sys.VAX4.3/machine/trap.c.diff ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.VAX4.3/machine/trap.c.diff or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.VAX4.3/machine/trap.c.diff 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.VAX4.3/machine/trap.c.diff
XThese changes enable syscall() to start up a remote version of a system
Xcall if the normal system call fails with error == EISREMOTE.
X***************
X*** 23,28
X  #ifdef SYSCALLTRACE
X  #include "../sys/syscalls.c"
X  #endif
X  
X  #include "mtpr.h"
X  
X
X--- 23,35 -----
X  #ifdef SYSCALLTRACE
X  #include "../sys/syscalls.c"
X  #endif
X+ #ifdef REMOTEFS
X+ #include "../remote/remotefs.h"
X+ /*
X+  * needed only if EISREMOTE isn't in /usr/include/errno.h
X+  */
X+ #include "../h/errno.h"
X+ #endif REMOTEFS
X  
X  #include "mtpr.h"
X  
X***************
X*** 191,196
X  	register struct proc *p;
X  	int opc;
X  	struct timeval syst;
X  
X  	syst = u.u_ru.ru_stime;
X  	if (!USERMODE(locr0[PS]))
X
X--- 198,212 -----
X  	register struct proc *p;
X  	int opc;
X  	struct timeval syst;
X+ #ifdef REMOTEFS
X+ 	/*
X+ 	 * It is imperative that these declarations come after other register
X+ 	 * declarations, because the (standard) code below depends upon the
X+ 	 * order of allocation.
X+ 	 */
X+ 	extern u_char remote_sysmap[];
X+ 	register long rmt_syscall, runremote, rmt_called, rmt_cnt;
X+ #endif REMOTEFS
X  
X  	syst = u.u_ru.ru_stime;
X  	if (!USERMODE(locr0[PS]))
X***************
X*** 223,228
X  		if (u.u_error == 0 && u.u_eosys != RESTARTSYS)
X  			u.u_error = EINTR;
X  	} else {
X  		u.u_eosys = NORMALRETURN;
X  #ifdef SYSCALLTRACE
X  		if (syscalltrace) {
X
X--- 239,248 -----
X  		if (u.u_error == 0 && u.u_eosys != RESTARTSYS)
X  			u.u_error = EINTR;
X  	} else {
X+ #ifdef REMOTEFS
X+ 		rmt_syscall = remote_sysmap[ code ];
X+ 		rmt_called = FALSE;
X+ 		rmt_cnt = 0;
X  		u.u_eosys = NORMALRETURN;
X  		while (! rmt_called) {
X  			runremote = (rmt_syscall != RSYS_nosys
X***************
X*** 224,229
X  			u.u_error = EINTR;
X  	} else {
X  		u.u_eosys = NORMALRETURN;
X  #ifdef SYSCALLTRACE
X  		if (syscalltrace) {
X  			register int i;
X
X--- 244,265 -----
X  		rmt_called = FALSE;
X  		rmt_cnt = 0;
X  		u.u_eosys = NORMALRETURN;
X+ 		while (! rmt_called) {
X+ 			runremote = (rmt_syscall != RSYS_nosys
X+ 				    && u.u_procp->p_flag & SREMOTE);
X+ 			if (runremote)
X+ 				rmt_called = remote_startup(rmt_cnt,
X+ 					rmt_syscall);
X+ 			if (! rmt_called) {
X+ 				(*callp->sy_call)();
X+ 				if (u.u_error != EISREMOTE)
X+ 					rmt_called = TRUE;
X+ 				else
X+ 					rmt_cnt++;
X+ 			}
X+ 		}
X+ #else REMOTEFS
X+ 		u.u_eosys = NORMALRETURN;
X  #ifdef SYSCALLTRACE
X  		if (syscalltrace) {
X  			register int i;
X***************
X*** 244,249
X  		}
X  #endif
X  		(*(callp->sy_call))();
X  	}
X  	if (u.u_eosys == NORMALRETURN) {
X  		if (u.u_error) {
X
X--- 280,286 -----
X  		}
X  #endif
X  		(*(callp->sy_call))();
X+ #endif REMOTEFS
X  	}
X  	if (u.u_eosys == NORMALRETURN) {
X  		if (u.u_error) {
SHAREOF
chmod 664 remote/usr.sys.VAX4.3/machine/trap.c.diff
#
# remote/usr.sys.VAX4.3/sys/init_sysent.c.diff
#
if [ -f remote/usr.sys.VAX4.3/sys/init_sysent.c.diff ]; then 
	echo -n 'Hit <return> to overwrite remote/usr.sys.VAX4.3/sys/init_sysent.c.diff or ^C to quit' 
	read ans 
	rm -f remote/usr.sys.VAX4.3/sys/init_sysent.c.diff 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/usr.sys.VAX4.3/sys/init_sysent.c.diff
XThese two changes add in the new RFS systems calls, remoteon(), remoteoff()
Xand  remotename().  If the second hunk fails, then you have some system
Xcall numbers that are not in standard 4.2BSD.
X***************
X*** 95,100
X  #define	compat(n, name)	0, nosys
X  #endif
X  
X  /* BEGIN JUNK */
X  #ifdef vax
X  int	resuba();
X
X--- 95,108 -----
X  #define	compat(n, name)	0, nosys
X  #endif
X  
X+ #ifdef REMOTEFS
X+ /*
X+  * remote file sys stuff (toddb@du)
X+  */
X+ int	remoteon(),		/* remote file sys stuff */
X+ 	remoteoff(),
X+ 	remotename();
X+ #endif REMOTEFS
X  /* BEGIN JUNK */
X  #ifdef vax
X  int	resuba();
X***************
X*** 269,274
X  	2, setquota,			/* 148 = quota */
X  	4, qquota,			/* 149 = qquota */
X  	3, getsockname,			/* 150 = getsockname */
X  	0, nosys,			/* 151 = nosys */
X  	0, nosys,			/* 152 = nosys */
X  	0, nosys,			/* 153 = nosys */
X
X--- 277,287 -----
X  	2, setquota,			/* 148 = quota */
X  	4, qquota,			/* 149 = qquota */
X  	3, getsockname,			/* 150 = getsockname */
X+ #ifdef REMOTEFS
X+ 	4, remoteon,			/* 151 = remoteon */
X+ 	1, remoteoff,			/* 152 = remoteoff */
X+ 	4, remotename,			/* 153 = remotename */
X+ #else REMOTEFS
X  	0, nosys,			/* 151 = nosys */
X  	0, nosys,			/* 152 = nosys */
X  	0, nosys,			/* 153 = nosys */
X***************
X*** 272,277
X  	0, nosys,			/* 151 = nosys */
X  	0, nosys,			/* 152 = nosys */
X  	0, nosys,			/* 153 = nosys */
X  	0, nosys,			/* 154 = nosys */
X  };
X  int	nsysent = sizeof (sysent) / sizeof (sysent[0]);
X
X--- 285,291 -----
X  	0, nosys,			/* 151 = nosys */
X  	0, nosys,			/* 152 = nosys */
X  	0, nosys,			/* 153 = nosys */
X+ #endif REMOTEFS
X  	0, nosys,			/* 154 = nosys */
X  };
X  int	nsysent = sizeof (sysent) / sizeof (sysent[0]);
SHAREOF
chmod 664 remote/usr.sys.VAX4.3/sys/init_sysent.c.diff
#
# 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,145 -----
X  	    0, 1, &resid);
X  	if (u.u_error)
X  		goto bad;
X+ #ifdef REMOTEFS
X+ }
X+ else
X+ 	resid = 0;
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--- 198,207 -----
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--- 205,222 -----
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--- 219,225 -----
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--- 312,324 -----
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--- 426,434 -----
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--- 430,436 -----
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--- 437,445 -----
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--- 445,461 -----
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--- 520,530 -----
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/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.2 86/01/25 20:46:02 toddb Exp $
X *
X * $Log:	remotefs.h,v $
X * Revision 2.2  86/01/25  20:46:02  toddb
X * Changed constant for FREMOTE from 08000 (octal???!!!) to 010000.
X * Luckily pcc interpreted it as 010000.
X * 
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		010000	   /* 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.2 86/03/10 12:23:39 toddb Exp $
X *
X * $Log:	rmt_exec.c,v $
X * Revision 2.2  86/03/10  12:23:39  toddb
X * In rmt_exec.c, execinfo gets the file size out of R_RETVAL.  The problem
X * is that it does one too many ntohl() calls; rmt_getmsg already has done
X * a byteswap of the message header, including R_RETVAL.  The test for
X * filesize larger than datasize+textsize+headersize may then fail if the
X * extra swap operation constructs a negative number.  (Dave Johnson@Brown)
X * 
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 = 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