Relay-Version: version B 2.10.3 beta 11/15/85; site seismo.CSS.GOV Posting-Version: version B 2.10.2 9/3/84; site panda.UUCP Path: seismo!harvard!talcott!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: RFS: remote file system (part 6 of 7) Message-ID: <1281@panda.UUCP> Date: 9 Jan 86 14:11:10 GMT Sender: jpn@panda.UUCP Lines: 2082 Approved: jpn@panda.UUCP 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 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 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 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 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 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 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< 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 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 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 (; endm_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 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