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