home *** CD-ROM | disk | FTP | other *** search
- Subject: RFS: remote file system (part 2 of 7)
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 78
- Submitted by: tektronix!tekcrl!toddb
-
- #!/bin/sh
- #
- # RFS, a kernel-resident remote file system. Shar 2 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/doc/paper/remotefs
- # remote/doc/remotename.2
- # remote/doc/remoteon.2
- # remote/doc/rfs_server.8
- # remote/doc/rmtmnt.8
- # remote/file.c
- # remote/fileserver.c
- # remote/find.c
- # remote/info.c
- # remote/init.c
- #
- # remote/doc/paper/remotefs
- #
- if [ -f remote/doc/paper/remotefs ]; then
- echo -n 'Hit <return> to overwrite remote/doc/paper/remotefs or ^C to quit'
- read ans
- rm -f remote/doc/paper/remotefs
- fi
-
- sed -e 's/^.//' << \SHAREOF > remote/doc/paper/remotefs
- X.HS I
- X.if "\*(.T"mag" \{\
- X. nr PS 12
- X. nr VS 14
- X.\}
- X.pl 9.75i
- X.TR
- X.DR
- X.de CN
- X..
- X.TL
- XDesign Considerations for Remote File Systems
- X(Extended Abstract)
- X.AU
- XT. Brunhoff
- X.AI
- XComputer Environments Group
- XApplied Research Group
- XTektronix, inc.
- X.AB
- XThere have been several remote file systems written,
- Xincluding one written by the author called \fBRemotefs\fR.
- XThis paper covers the design choices
- Xthat can be made at several software levels,
- Xfrom where the hooks for a remote file system
- Xlie in the operating system,
- Xon up to the user interface,
- Xand reveals those made by \fBRemotefs\fP.
- XThe reader should have a strong familiarity
- Xwith the 4.2 BSD kernel function \fInamei()\fP,
- Xthe concept of mount points,
- Xthe system call interface and
- Xthe 4.2 BSD socket paradigm.
- X.AE
- X.SH
- XHistory
- X.PP
- XThe Computer Research Labs within the Applied Research Group
- Xhas approximately forty-five internally\-designed workstations,
- Xcalled
- X.I Magnolias,
- Xtwenty newly announced Tektronix 4404 AI workstations,
- Xcalled \fIPegasus\fP, a
- X.I VAX 11/780
- Xand a
- X.I VAX 11/750.
- XThe Computer Environments Group,
- Xwithin the Computer Research Labs
- Xcares for most of these machines and the software that runs on them.
- X.PP
- XAfter porting 4.2 BSD Unix to the
- X.I Magnolia,
- Xthe amount of software available quickly outgrew
- Xthe capacity of its 35-megabyte winchester drives.
- XTo alleviate this,
- Xthe author designed and began in December of 1984 to write a
- Xremote file system based on a implementation paradigm used
- Xby K. McKusick in his implementation of the 4.2 BSD file system;
- Xi.e., "write it in user-mode to fit in the kernel".
- XThis paper is in part
- Xabout that implementation,
- Xand about design and
- Ximplementation in general to achieve a remote (or distributed) file system.
- XAt this writing,
- Xthe design still lies mostly in the user level,
- Xlinked in by the \fBld(1)\fP flag
- X\fI\-lremote\fP,
- Xwith a few new system calls.\(dg
- X.FS \(dg
- XThis remote file system,
- Xknown simply as \fBRemotefs\fP,
- Xshould not be confused with another,
- Xmore complete remote file system,
- Xcalled \fBDFS\fR.
- XThe latter is available on the Tektronix 6000 series workstations.
- X.FE
- X.NH 1
- XChoosing a Springboard for the Software
- X.PP
- XThe focus of I/O activity on
- X.B UNIX
- Xis the inode;
- Xeach time a file is open, read, written, locked, closed, etc.,
- Xthe inode is referred to.
- XThese system calls
- Xconverge on the system call interface which dispatches calls to
- Xthe appropriate internal routine.
- XAny system calls that involve a path name must call \fInamei()\fP
- Xfor the inode information, and similarly, any system calls that
- Xdeal with file descriptors must refer to the inode information
- Xgenerated by an \fIopen()\fP or \fIcreate()\fR.
- XOnly then can the data on the disks be accessed.
- X.so fig1.\*(.T
- X.PP
- XFor example, in Figure 1,
- X\fIopen()\fP makes a request to the system call interface;
- Xthe system call interface determines that the \fIopen()\fP system call must
- Xbe executed (the kernel \fIopen()\fP is just a call to \fIcopen()\fP).
- X\fICopen()\fP then calls \fInamei()\fP to get the inode information
- Xwhich in turn calls the appropriate disk device driver to get the inode
- Xfrom the correct disk.
- XSubsequent \fIread()\fP
- Xor \fIwrite()\fP calls use this information to access the disk.
- XIt makes sense to make \fInamei()\fP the focal point for the remote
- Xfile system implementation
- Xbecause of its critical role.
- XBut there are other approaches.
- X.NH 2
- X\&\.\.\. From the Device Driver
- X.PP
- XSince \fInamei()\fP gets its information from the
- Xdisk via the disk driver,
- Xwe have only to
- Xreplace the disk driver with a \fIremote\fP disk driver.
- XThis remote disk driver would be designed to send requests for disk
- Xblocks directly to a remote host to be satisfied
- Xfrom a single partition on its own disk.
- X.so fig2.\*(.T
- X.PP
- XNow, following the previous example in Figure 2,
- X\fInamei()\fP may instead encounter a mount point while
- Xtrying to find an inode for a file,
- Xand will get its inode information from the remote disk driver.
- XSimilarly,
- Xreads and writes
- Xrequest blocks from the \fIremote\fP disk driver
- Xusing this inode information.
- X.PP
- XThis is where early implementations put remote file systems.
- XIt offers speed and a good deal of portability with
- Xthe kernel changes limited to the device driver,
- Xbut it limits usefulness because each partition
- Xon every remote system must be mounted,
- Xand access can only be read\-only.
- X.NH 2
- X\&\.\.\. In \fInamei()\fP
- X.PP
- XThere are two ways of checking for ``remoteness''
- Xin \fInamei()\fP,
- Xbut the key change to \fInamei()\fP is that it must fail in
- Xits inode lookup when it encounters a path name component
- Xon a remote machine; then it must return with a special error.
- XThis \fInamei()\fP failure mechanism will be alluded to later.
- X.PP
- XOne method, depicted in Figure 3,
- Xis to catch any reference to a special
- Xsyntax of path name,
- Xsuch as \fI/\.\.\|/host/pathname\fP,
- X\fI/net/host/pathname\fP
- Xor \fI//host/pathname\fP.
- XThis is a cue to \fInamei()\fP
- Xto return a special error code to the invoking system call.
- XIt is then
- Xthe responsibility of that system call to send
- Xa request to a server on the remote host.
- XThis special syntax is very convenient because the
- X\fIhost\fP component of the path
- Xneed not correspond to some existing ``mount point''.
- XHence, hosts can be mounted and unmounted on demand
- Xif the implementor cares to take the trouble.
- X.so fig3.\*(.T
- X.PP
- XA second strategy is very similar
- Xexcept that it uses a more natural
- Xsyntax of \fI/host/pathname\fP
- X(without needing symbolic links).
- XAn important point is that the host cannot be ``mounted''
- Xon a directory,
- Xbut rather on a special mount point,
- Xor even a plain file.
- XThe reason for this is a bit obscure,
- Xbut will be clarified shortly.
- X.PP
- XThe special path names like \fI/\.\.\|/host/pathname\fP
- Xor mount points like \fI/host\fP are needed partly because no
- XUNIX program should ever find these gateways through normal perusal of
- Xa file system.
- XImagine how long the command ``\fIfind / -print\fP'' would take
- Xif it traversed every remote host as well as itself!
- XFor this reason, using a directory for a mount point would
- Xnot be appropriate.
- X.PP
- X\fBRemotefs\fP uses a plain file as a mount point because of some extra
- Xbenefits:
- Xthe simplicity of the code changes to \fInamei()\fP,
- Xand not having to add another file type for \fBUNIX\fP utilities to learn.
- XThe path name \fI/host\fP remains a valid local filename,
- Xbut \fI/host/\fP or anything longer results in
- Xa special case, which \fInamei\fP labels with the error
- X\fBENOTDIR\fP
- X(See Appendix A).
- XIt is this place in the \fBUNIX\fP kernel
- Xthat \fBRemotefs\fP detects all remote file references.
- X.NH 3
- XAn Aside: When to Follow a Symbolic Link in \fINamei()\fP.
- X.NH 2
- X\&\.\.\. At the User Level.
- X.PP
- XA slight variation of the above,
- Xshown in Figure 4,
- Xis to simply place the check for ``remoteness'' in
- Xappropriate system calls with in the C runtime library,
- X\fIlibc.a\fP.
- X(see Appendix B for this list).
- XUnfortunately,
- Xthis requires the user level software to duplicate
- Xwhat \fInamei()\fP does
- Xwhenever a system call involving a path name returns the
- Xerror \fBENOENT\fR or \fBENOTDIR\fR.
- XThis implementation approach is typically slower,
- Xbut very portable.
- X.so fig4.\*(.T
- X.NH 1
- XFile Descriptors
- X.PP
- XOnce an \fIopen()\fP or \fIcreat()\fP has succeeded
- Xon the remote host and returned a file descriptor, say \fIi\fP,
- Xwe must allocate a real file descriptor, \fIj\fP, on the local machine.
- XThis may be done in the kernel or user level code,
- Xbut it is most important that the user's idea of the ordinate
- Xvalue of \fIj\fP remain inviolate.
- X.NH 2
- XFile Descriptors Handled at User Level
- X.NH 2
- XFile Descriptors Handled at Kernel Level
- X.NH 2
- XInheriting File Descriptors Across a \fIfork()\fP or \fIexec()\fP
- X.NH 2
- XReading Directories on a Remote Host
- X.NH 1
- XChanging Directories
- X.PP
- XImplementing the ability to change
- Xdirectories is a big win for any implementation
- Xbecause interactive shells will then allow you to
- Xperuse directories on remote hosts.
- XHowever, inheritance of file descriptors must
- Xbe implemented,
- Xas explained in section 2.3.
- XThe \fIchdir()\fP executing on the remote host
- Xdoes nothing special.
- XIf it succeeds, all is well.
- XBut on the local side,
- Xthe software cannot change state (the current
- Xworking directory)
- Xto match what has occurred on the remote machine.
- XInstead,
- Xit must simply be remembered it in some way.
- X.NH 2
- XInterpreting Pathnames
- X.PP
- XIf the remote file system software lies entirely in user\-level code,
- Xthen the only solution is for the software
- Xto remember \fIchdir()\fP's path name argument
- Xand that the current directory is on a remote host.
- XThen when a new path name is passed to a system call,
- Xthe software need only to check to see if it is absolute
- Xor relative (with or without a leading '/' character, respectively).
- XIf it is relative,
- Xthen the request must be sent to the remote host.
- X.PP
- XOn the other hand if the software uses a special
- Xmount point like \fI/host\fP,
- Xthe kernel can arrange
- Xto make the process's working directory inode
- Xto be the mount point's inode.
- XThis is very convenient because no absolute vs. relative
- Xchecks are necessary
- Xand nothing need be added to \fInamei()\fP.
- XFor example,
- Xabsolute path names in a system call will still cause the mechanism
- Xto function normally.
- XAnd relative path names will immediately fail in \fInamei()\fP
- X(remember our key change in section 1.2).
- XSee Appendix A.
- X.NH 2
- XPwd(1) and Changing to ``/\.\.'' on the Remote Host
- X.NH 1
- XSpecial Problems
- X.NH 2
- X\fIExec()\fP
- X.NH 2
- X\fIFork()\fP and \fIvfork()\fP
- X.NH 2
- X\fISelect()\fP
- X.NH 2
- XUniqueness of Files Across Hosts
- X.NH 1
- XPermissions Across Hosts
- X.NH 2
- XDatabase Model
- X.NH 2
- XDynamic Model
- X.NH 1
- XServer Design
- X.NH 2
- XWhen to \fIfork()\fP
- X.NH 2
- XHow to Change Uid/Gid permissions
- X.NH 2
- XFile Descriptor Overload
- X.NH 2
- XCommunication Model
- X.NH 3
- XProtocol
- X.NH 3
- XWho Answers the Phone?
- X.NH 3
- XSpeed Improvements
- X.PP
- XImagine
- Xa very loose view of the protocol (moving downward):
- X.so fig5.\*(.T
- XA remote file system implementation
- Xhas a decidedly synchronous flavor to it,
- Xand for most system calls,
- Xnothing else is appropriate.
- XBut \fIRead()\fP and \fIwrite()\fP system calls
- Xlend themselves very well to optimization,
- Xspecifically, lookahead.
- X.PP
- XA change in the protocol could be made
- Xbased on expected requests.
- XAfter,
- Xsay, two consecutive \fIread()\fP requests
- Xon the same file descriptor for the same number of bytes,
- Xthe local host could ask the server to continue servicing
- Xthe same request until further notice.
- XThe response would contain the same information
- Xthat would be expected on a normal request,
- Xand would, of course,
- Xterminate on an error or end\-of\-file.
- XThe remote host, could easily detect and recover from a termination
- Xof this kind, too.
- XThe difficult part would be for the local host to try to stop
- Xthe servicing before end\-of\-file.
- XSo,
- Xour protocol now would be
- X.so fig6.\*(.T
- XNotice that the responses may continue on beyond
- Xthe request to stop,
- Xbut the acknowledgment of the request to stop would put
- Xthe hosts back in sync.
- XThe remote host has only to reset its read pointer
- Xback to the point where it had serviced
- X\fIn\fP requests,
- Xand the local host must read the responses up to and including
- Xthe acknowledgment.
- X.PP
- XThe protocol also may
- Xhave to refuse continuation service for file descriptors
- Xthat read from devices.
- X.PP
- X\fIWrite()\fP is similar,
- Xbut recovery when the remote host
- Xreaches an end\-of\-file or encounters an error
- Xwould be much more complicated, and in some cases impossible.
- XThe local host,
- Xon receipt of a request to stop from the remote host,
- Xwould have to not only reset its idea of the write pointer,
- Xbut perhaps the read pointer from which the data was gathered
- Xto do the write.
- XConsidering that the reading may have been done from multiple
- Xfiles or the data was transformed in some way,
- Xthe remote file system software may not be able to accomplish the task.
- XIt appears to be only feasible if the implementor is willing to sacrifice
- Xidentical behavior of user\-level software on remote vs. local file
- Xsystems.
- X.NH 1
- XStatus of \fBRemotefs\fP
- X.NH 1
- XAppendix A
- X.so appendixB.out
- X.NH 1
- XAppendix C
- SHAREOF
- chmod 664 remote/doc/paper/remotefs
- #
- # remote/doc/remotename.2
- #
- if [ -f remote/doc/remotename.2 ]; then
- echo -n 'Hit <return> to overwrite remote/doc/remotename.2 or ^C to quit'
- read ans
- rm -f remote/doc/remotename.2
- fi
-
- sed -e 's/^.//' << \SHAREOF > remote/doc/remotename.2
- X.TH REMOTENAME 2 "27 July 1983"
- X.UC 4
- X.SH NAME
- Xremotename \- provide name information to the kernel
- X.SH SYNOPSIS
- X.nf
- X.ft B
- X#include <remote/remotefs.h>
- X
- Xremotename(action, name, namelen, path)
- Xlong action;
- Xcaddr_t name;
- Xlong namelen;
- Xchar *path;
- X.fi
- X.SH DESCRIPTION
- X.I Remotename
- Xis an interface for an exchange of information with
- Xthe kernel about remote hosts.
- XThe value of
- X.I action,
- Xdefined by NM_* symbolic constants in remote/remotefs.h,
- Xdetermines what exchange takes place:
- X.PP
- XNM_SERVER
- X.br
- XThe current process is registered as the name server for the kernel.
- XWhenever the kernel needs a path name translated into
- Xan internet address,
- Xthe current process will receive the SIGIO signal.
- XArguments besides
- X.I action
- Xare ignored.
- XIf there is already a process registered as the name server,
- X.I remotename
- Xwill fail.
- X.PP
- XNM_WHATNAME
- X.br
- XAfter receiving the SIGIO signal,
- Xthe registered name server should
- Xsupply this action to
- X.I remotename
- Xalong with a valid
- Xcharacter pointer
- Xin
- X.I name
- Xand its length in
- X.I namelen.
- XThe kernel will copy into that pointer
- Xa null\-terminated string of the form "/single-component".
- XIt is the name server's job to translate "single-component"
- Xinto a valid internet address.
- X.PP
- XThe kernel obtains the single component from the second component
- Xof a path name used in a system call by some user process.
- XThe first component of that path name would have been a generic mount
- Xpoint.
- X.PP
- XNM_NAMEIS
- X.br
- XAfter obtaining a valid internet address,
- Xthe registered name server should
- Xsupply this action to
- X.I remotename
- Xalong with a valid
- X.I name
- Xand
- X.I namelen
- Xcontaining the internet address the way that
- X.I connect(2)
- Xwould expect it,
- Xand a
- X.I path
- Xcontaining the nameserver's opion of what the null-terminated
- Xmount point should
- Xhave been.
- X.PP
- XNM_DEBUG
- X.br
- XTurns on debug level to the value in
- X.I system.
- X.SH "RETURN VALUE
- X.I Remotename
- Xreturns 0 if the action occurred, \-1 if
- X.I name
- Xor
- X.I path
- Xis an invalid address (when a valid one was expected),
- Xor the user is not the super user.
- X.SH ERRORS
- X.TP 15
- X[EPERM]
- XThe caller is not the super-user
- Xor the calling process is not the registered nameserver.
- X.TP 15
- X[EINVAL]
- X.I Name
- Xor
- X.I path
- Xare not valid addresses (if expected),
- X.I namelen
- Xis too long or
- Xthe
- X.I action
- Xwas not recognized.
- X.TP 15
- X[ENOREMOTEFS]
- XOn
- X.I NM_WHATNAME
- Xthere was no pathname for which the kernel needed a internet address.
- X.TP 15
- X[EBUSY]
- XThe calling process is trying to register as the nameserver,
- Xbut one already exists.
- X.SH "SEE ALSO"
- Xremoteon(2), remoteoff(2), rmtmnt(8), rfs_server(8)
- X.SH BUGS
- X.I NM_DEBUG
- Xwill not be recognized unless the kernel is has the debug software
- Xcompiled in.
- SHAREOF
- chmod 664 remote/doc/remotename.2
- #
- # remote/doc/remoteon.2
- #
- if [ -f remote/doc/remoteon.2 ]; then
- echo -n 'Hit <return> to overwrite remote/doc/remoteon.2 or ^C to quit'
- read ans
- rm -f remote/doc/remoteon.2
- fi
-
- sed -e 's/^.//' << \SHAREOF > remote/doc/remoteon.2
- X.TH REMOTEON 2 "27 July 1983"
- X.UC 4
- X.SH NAME
- Xremoteon, remoteoff \- turn on and off remote file system
- X.SH SYNOPSIS
- X.nf
- X.ft B
- Xremoteon(path, pathlen, name, namelen)
- Xchar *path;
- Xint pathlen;
- Xstruct sockaddr *name;
- Xint namelen;
- X.PP
- X.ft B
- Xremoteoff(path)
- Xchar *path;
- X.fi
- X.SH DESCRIPTION
- X.I Remoteon
- Xannounces to the system that the file system
- Xstarting with the root, aka "/", on the internet host
- X.I name
- Xhas been mounted on
- Xthe plain file
- X.I path;
- Xfrom then on, references to any files below
- X.I path
- Xwill refer to
- Xfiles below the root file system on the remote host,
- X.I name.
- X.I Path
- Xis a pointer to a null-terminated string
- Xcontaining the appropriate path name,
- Xbut for storage purposes in the kernel,
- X.I pathlen
- Xmust also be provided.
- X.I name
- Xcan only be a valid internet address (this may be extended later),
- Xand
- X.I namelen
- Xshould be the correct length,
- Xnormally
- X.I sizeof(struct sockaddr_in).
- X.PP
- X.I Path
- Xmust exist already and be
- Xa plain file.
- XIts old contents
- Xare still accessible while the remote file system
- Xis mounted,
- Xbut the file cannot be removed.
- X.PP
- XA special case for
- X.I remoteon
- Xand
- X.I remoteoff
- Xis when
- X.I path
- Xis a null pointer.
- XThis tells the kernel to disallow
- X.I (remoteoff)
- Xor allow
- X.I (remoteon)
- Xremote access for the current
- Xprocess,
- Xand is intended primarily for use with a remote file server
- Xto prevent remote file system loops.
- XBy default,
- Xall processes are allowed remote access.
- XNote that while only the super-user may turn on or off the remote
- Xfile system,
- Xany user may turn on and off remote access for himself.
- X.PP
- X.I Remoteoff
- Xannounces to the system that the
- X.I path
- Xfile is no longer to be a remote mount point.
- XCurrently,
- Xeven if
- X.I remoteoff
- Xfails,
- Xthe remote file system is marked for closing and
- Xno more usage is allowed.
- XSystem calls that must be run on the remote system after
- Xthis point will fail (return \-1).
- X.SH "RETURN VALUE
- X.I Remoteon
- Xreturns 0 if the action occurred, \-1 if
- X.I path
- Xis inaccessible,
- Xalready a remote mount point, not an appropriate file, if
- X.I path
- Xdoes not exist,
- Xor if there are already too many remote file systems mounted.
- X.PP
- X.I Remoteoff
- Xreturns 0 if the action occurred; \-1 if
- Xif the file is inaccessible or
- Xdoes not point to a remote file system,
- Xor if there are active processes using the remote
- Xfile system.
- X.SH ERRORS
- X.I Remoteon
- Xwill fail when one of the following occurs:
- X.TP 15
- X[EPERM]
- XThe caller is not the super-user.
- X.TP 15
- X[ENOENT]
- X.I Special
- Xdoes not exist.
- X.TP 15
- X[EISDIR]
- X.I Path
- Xis not a plain file.
- X.TP 15
- X[EINVAL]
- X.I Namelen
- Xis too long.
- X.TP 15
- X[ENOBUFS]
- Xthe system is out of mbuf structures.
- X.TP 15
- X[EFAULT]
- X.I Name
- Xpoints to a bad address.
- X.TP 15
- X[ETOOMANYREMOTE]
- XThe action would overflow internal tables.
- X.TP 15
- X[EBUSY]
- X.I Path
- Xis already a remote mount point.
- X.PP
- X.I Remoteoff
- Xmay fail with one of the following errors:
- X.TP 15
- X[EPERM]
- XThe caller is not the super-user.
- X.TP 15
- X[ENOENT]
- X.I Path
- Xdoes not exist.
- X.TP 15
- X[EBUSY]
- XA process is holding a reference to the remote file system.
- X.SH "SEE ALSO"
- Xrmtmnt(8), rfs_server(8)
- SHAREOF
- chmod 664 remote/doc/remoteon.2
- #
- # remote/doc/rfs_server.8
- #
- if [ -f remote/doc/rfs_server.8 ]; then
- echo -n 'Hit <return> to overwrite remote/doc/rfs_server.8 or ^C to quit'
- read ans
- rm -f remote/doc/rfs_server.8
- fi
-
- sed -e 's/^.//' << \SHAREOF > remote/doc/rfs_server.8
- X.TH RFS_SERVER 8 "18 October 1985"
- X.UC 4
- X.SH NAME
- Xrfs_server \- remote file system server and kernel name server
- X.SH SYNOPSIS
- X.B /etc/rfs_server
- X[ -s internet-service ]
- X[ -v debug-level ]
- X.SH DESCRIPTION
- XThis is a server for the remote file system and
- Xis intended to be started up in /etc/rc.
- X.PP
- X.PP
- XThe optional flag
- X.I \-s
- Xand its argument,
- X.I internet-service,
- Xtells the server to accept calls on the named service
- Xport described in /etc/services.
- XWithout this argument,
- X.I rfs_server
- Xuses the service
- X.I remotefs.
- X.PP
- XThe optional flag
- X.I \-v
- Xand its argument,
- X.I debug-level,
- Xstarts up the server with the given initial debug level.
- XThe argument should be a hexadecimal number containing one bit
- Xfor each class of debug output desired.
- X.PP
- XThe server maintains three identities,
- Xand each can be determined by the current command line using the
- X.I ps(1)
- Xcommand.
- X.PP
- XThe first identity is the
- X.I sentry
- Xof which there can only be one at any time.
- XThe command line for this remains unaltered from the way it was started.
- XThe function of the
- X.I sentry
- Xserver is to build a database of all hosts in /etc/hosts,
- Xall users and groups in /etc/passwd and /etc/group,
- Xand of all users' .rhost files.
- XAfter this database has been built,
- Xit waits
- Xfor connections from remote hosts.
- X.PP
- XThe second identity is a
- X.I "gateway server"
- Xand changes its command line
- Xto tell which host it is a
- X.I "gateway server"
- Xfor.
- XThis identity is the child of the
- X.I sentry
- Xafter the latter receives a connection from a remote host;
- Xthere can only be one
- X.I "gateway server"
- Xfor each remote host.
- XThe responsibilities of the
- X.I "gateway server"
- Xare to service context-free system calls for the remote host,
- Xcreate other servers to handle context-sensitive system calls,
- Xmaintain complete information about all remote processes being served,
- Xand ensure at all times
- Xthat only one server has control of the socket file
- Xdescriptor to the remote machine being served.
- X.PP
- XThe third identity is that of a plain
- X.I server,
- Xand changes its command line to be similar to that
- Xof the
- X.I "gateway server"
- Xexcept that the word
- X.I gateway
- Xis missing and it identifies its parent process.
- XIts responsibilities
- Xare to service context-free system calls for the remote host and
- Xcreate other servers for remote processes that must inherit
- Xcertain context information (e.g. remote current working directories,
- Xand open file descriptors).
- X.SH "DEBUG LEVELS"
- XIt should be noted that the debug option is only useful with
- Xa copy of the source code in hand and a server that has been
- Xcompiled with the debug software turned on.
- XThe current selection of the bits are:
- X.PP
- X.ta 1i 2.5i 4i
- X 0x00000001 process switching
- X.br
- X 0x00000002 system calls
- X.br
- X 0x00000004 setuid/setgid, umask
- X.br
- X 0x00000008 file descriptor allocation
- X.br
- X 0x00000010 connections
- X.br
- X 0x00000020 server switching
- X.br
- X 0x00000040 nameserver
- X.br
- X 0x00000080 directory nuxi
- X.br
- X 0x00000100 message in and out
- X.br
- X 0x00000200 don't fork child for gateway (good for adb)
- X.br
- X 0x00000400 local/remote file decisions
- X.br
- X 0x00000800 don't remove log file on exit (except exit on error)
- X.br
- X 0x00001000 exec information
- X.br
- X 0x00002000 auto debug for 0x20 (server switching)
- X.br
- X 0x00004000 parsing messages to gateway
- X.PP
- XAnother method of setting the debug level in any identity of the
- X.I rfs_server
- Xis to place the desired hexidecimal level in the file /usr/tmp/rfs_debug
- Xand to send the appropiate server signal number 5, aka
- X.I SIGTRAP.
- XThis method can be used with
- X.I sentry
- Xservers, any
- X.I gateway
- Xservers, and any other servers that are marked active.
- XIt should not be used on sleeping servers.
- X.PP
- XIf any server receives SIGILL, SIGSEGV or SIGBUS,
- Xit will arrange for its core file to be dumped in /usr/tmp.
- X.SH "RESTARTING THE SERVER"
- XThe best way to restart the
- X.I sentry
- Xserver (e.g. installing a new
- X.I rfs_server),
- Xis to simply run the new server.
- XThe new server knows how to examine the previous log file
- Xto discover the pid number of the previous server, and kill it.
- X.PP
- XIf you know that that will fail, then the second best way
- Xis to send it the signal
- X.I SIGTERM
- X.PP
- XSending
- X.I SIGTERM
- Xsignal to a
- X.I "gateway server"
- Xwill cause it and all of its children to gracefully go away.
- X.SH "SEE ALSO"
- Xremotename(2),
- Xrmtmnt(8).
- X.SH BUGS
- XProbably.
- SHAREOF
- chmod 664 remote/doc/rfs_server.8
- #
- # remote/doc/rmtmnt.8
- #
- if [ -f remote/doc/rmtmnt.8 ]; then
- echo -n 'Hit <return> to overwrite remote/doc/rmtmnt.8 or ^C to quit'
- read ans
- rm -f remote/doc/rmtmnt.8
- fi
-
- sed -e 's/^.//' << \SHAREOF > remote/doc/rmtmnt.8
- X.TH RMTMNT 8 "18 October 1985"
- X.UC 4
- X.SH NAME
- Xrmtmnt \- mount and dismount remote file systems
- X.SH SYNOPSIS
- X.B /etc/rmtmnt
- X[ -s internet-service ] host path
- X.PP
- X.B /etc/rmtmnt
- X-g path
- X.PP
- X.B /etc/rmtmnt
- X-u path
- X.PP
- X.B /etc/rmtmnt
- X.SH DESCRIPTION
- XIn the first usage,
- X.I rmtmnt
- Xannounces to the system that the file system
- Xstarting with the root, aka "/", on the internet host named
- X.I host
- Xhas been mounted on
- Xthe plain file
- X.I path;
- Xfrom now on, references to any files below
- X.I path
- Xwill refer to
- Xfiles below the root file system on the remote host,
- X.I host.
- XThe file
- X.I path
- Xmust exist already; it must be a file.
- XIt becomes the name of the newly mounted root.
- X.PP
- XThe optional flag
- X.I \-s
- Xand argument
- X.I internet-service
- Xindicates that the kernel should use
- Xthe named internet service (defined in /etc/services)
- Xwhen connecting to that remote host.
- X.PP
- XThe second usage with the
- X.I -g
- Xflag indicates that the mount point is to be "generic".
- XBy convention,
- Xthe name of this path ought to be
- X.I /net,
- Xbut may be any valid path name.
- XNo specific host is associated with the
- Xpath name.
- XInstead,
- Xthe component following
- X.I /net
- Xis handed to the nameserver, usually
- X.I rfs_server(8),
- Xfor translation to an internet address.
- XWhen the kernel receives the new address,
- Xan implicit mount is made by the kernel.
- X.PP
- XThe third usage with the
- X.I -u
- Xflag informs the kernel that the internet host
- Xmounted on
- X.I path
- Xshould be unmounted.
- X.PP
- XThe last usage,
- Xhaving no arguments or flags
- Xwill print out a complete status of all current mount points.
- X.SH "SEE ALSO"
- Xremoteon(2),
- Xrfs_server(8).
- X.SH BUGS
- XImlicit mount points cannot be unmounted.
- X.PP
- XIf a command which has a current working directory
- Xon a remote machine through an
- X.I implicit
- Xmount point
- Xattempts to find the current working directory,
- Xit will produce a pathname missing the second component,
- Xand, hence, will fail.
- XExplicit mount points work fine.
- SHAREOF
- chmod 664 remote/doc/rmtmnt.8
- #
- # remote/file.c
- #
- if [ -f remote/file.c ]; then
- echo -n 'Hit <return> to overwrite remote/file.c or ^C to quit'
- read ans
- rm -f remote/file.c
- fi
-
- sed -e 's/^.//' << \SHAREOF > remote/file.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 * $Log: file.c,v $
- X * Revision 2.0 85/12/07 18:21:11 toddb
- X * First public release.
- X *
- X */
- Xstatic char *rcsid = "$Header: file.c,v 2.0 85/12/07 18:21:11 toddb Rel $";
- X#include "server.h"
- X#include <errno.h>
- X
- Xextern int fds_in_use;
- Xextern int errno;
- X
- X/*
- X * here we allocate a file descriptor to a process and make note of our
- X * total number of open file descriptors. 'fd' is the file descriptor
- X * that the server itself got back, and remotefd is the file descriptor
- X * that the remote process is expecting.
- X */
- Xallocate_fd(fd, proc, remotefd)
- X register int fd,
- X remotefd;
- X register process *proc;
- X{
- X if (fd != -1)
- X {
- X proc->p_fds[ remotefd ] = fd;
- X debug3("allocate local fd %d, remote fd %d\n",
- X fd, remotefd);
- X fds_in_use++;
- X checkfiletype(fd);
- X }
- X else
- X remotefd = -1;
- X return(remotefd);
- X}
- X
- Xdeallocate_fd(proc, remotefd)
- X register process *proc;
- X register long remotefd;
- X{
- X register char fd;
- X register long retval;
- X
- X if ((unsigned)remotefd >= NOFILE)
- X {
- X errno = EBADF;
- X return(-1);
- X }
- X fd = proc->p_fds[ remotefd ];
- X proc->p_fds[ remotefd ] = -1;
- X retval = close(fd);
- X fds_in_use--;
- X return(retval);
- X}
- SHAREOF
- chmod 444 remote/file.c
- #
- # remote/fileserver.c
- #
- if [ -f remote/fileserver.c ]; then
- echo -n 'Hit <return> to overwrite remote/fileserver.c or ^C to quit'
- read ans
- rm -f remote/fileserver.c
- fi
-
- sed -e 's/^.//' << \SHAREOF > remote/fileserver.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 * $Log: fileserver.c,v $
- X * Revision 2.0 85/12/07 18:21:14 toddb
- X * First public release.
- X *
- X */
- Xstatic char *rcsid = "$Header: fileserver.c,v 2.0 85/12/07 18:21:14 toddb Rel $";
- X#include <errno.h>
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <signal.h>
- X#include "server.h"
- X#include <sys/file.h>
- X
- Xextern long errno;
- Xextern long from_servers;
- Xextern long to_gateway;
- Xextern long so_listen;
- Xextern long blocking_servers;
- Xextern short gateway_server;
- Xextern short current_ppid;
- Xextern short current_pid;
- Xextern short current_uid;
- Xextern short current_server;
- Xextern char mntpt[ MAXPATHLEN ];
- Xextern char *program;
- Xextern char *last_argaddr;
- Xextern char *logfile;
- Xextern char *service;
- Xextern char *syscallnames[];
- Xextern boolean i_am_gateway;
- Xextern boolean i_am_asleep;
- Xextern boolean i_have_control;
- Xextern boolean route_to_gateway;
- Xextern boolean watch_for_lock;
- Xextern boolean gateway_needs_control;
- Xextern syscallmap smap[];
- Xextern process *wildcard;
- Xextern hosts *host;
- X
- Xmain(argc, argv)
- X int argc;
- X char **argv;
- X{
- X register hosts *h;
- X
- X setopts(argc, argv);
- X if ((remote_debug & 0x200) == 0 && fork())
- X exit(0);
- X current_pid = getpid();
- X setlogfile();
- X if ((so_listen = tcppassive()) < 0)
- X log_fatal("cannot open socket\n");
- X init();
- X for (;;)
- X {
- X if ((h = tcpaccept(so_listen)) == NULL)
- X break;
- X debug4("call on fd %d, portno %d, from host \"%s\"\n",
- X h->h_cmdfd, h->h_portnum, h->h_names[0]);
- X dumphost(h);
- X if (server(h))
- X exit(0);
- X }
- X}
- X
- X/*
- X * This is the top lexical level for the server. We decide here
- X * when to call for a next request and whether we are running the
- X * new format remote fs or not.
- X *
- X * We also decide whether this is a connection from the mount program
- X * on a remote host or not. If it is, then we just want to assemble the
- X * info that it gives us and not become a child server.
- X */
- X
- Xserver(h)
- X register hosts *h;
- X{
- X long pipefd[ 2 ];
- X struct message msgbuf,
- X *getmsg();
- X register struct message *msg = &msgbuf;
- X register process *proc;
- X register long cmd, len;
- X
- X /*
- X * Get the first message from this connection.
- X */
- X alarm(5);
- X if (! (msg = getmsg(h->h_cmdfd)))
- X {
- X log("connection initiation lost to \"%s\"\n", h->h_names[0]);
- X close(h->h_cmdfd);
- X h->h_cmdfd = -1;
- X alarm(0);
- X return(FALSE);
- X }
- X alarm(0);
- X
- X /*
- X * may be a special command
- X */
- X len = msg->m_hdlen;
- X if (msg->m_syscall == RSYS_nosys)
- X {
- X cmd = msg->m_args[0];
- X debug5("new client; cmd=%d\n", cmd);
- X switch(cmd) {
- X case CMD_SERVICE:
- X break;
- X case CMD_MOUNT:
- X gobble_last_msg(h->h_cmdfd, msg);
- X getbyteorder(h);
- X getrusers(h);
- X return(FALSE);
- X case CMD_NEEDMOUNT:
- X sendmount(h);
- X dont_gobble_msg(msg);
- X return(FALSE);
- X default:
- X log_fatal("unknown server directive = %d\n", cmd);
- X }
- X }
- X else
- X {
- X debug5("new client, not mounted by rmtmnt\n");
- X dont_gobble_msg(msg);
- X if (!h->h_mounted)
- X getmount(h);
- X }
- X
- X /*
- X * If we reach this point, then we are to be the gateway server.
- X * There may ba a server still running. Kill it.
- X */
- X if (h->h_serverpid)
- X sendsig(h->h_serverpid, SIGTERM);
- X
- X if ((remote_debug & 0x200) == 0 && vfork())
- X {
- X wait(0);
- X /*
- X * we are the parent... just return.
- X */
- X close(h->h_cmdfd);
- X h->h_cmdfd = -1;
- X return(FALSE);
- X }
- X else if ((remote_debug & 0x200) == 0 && (h->h_serverpid = fork()))
- X exit(0);
- X host = h;
- X wildcard->p_handler = gateway_server = current_pid = getpid();
- X set_label("active");
- X if ((remote_debug & 0x200) == 0)
- X {
- X setlogfile();
- X close(so_listen);
- X }
- X if (pipe(pipefd) < 0)
- X log_fatal("Can't open pipe\n");
- X from_servers = pipefd[ 0 ];
- X to_gateway = pipefd[ 1 ];
- X
- X /*
- X * Ok, now be a server!
- X */
- X for(;;)
- X {
- X if (i_am_gateway && ! i_have_control)
- X {
- X gateway_listen();
- X continue;
- X }
- X /*
- X * The gateway may be waiting for control. Let's see.
- X */
- X if (watch_for_lock)
- X if (gateway_needs_control
- X || flock(2, LOCK_NB | LOCK_SH) < 0)
- X {
- X debug5("gateway wants control\n");
- X reroute(gateway_server, msg);
- X continue;
- X }
- X else
- X flock(2, LOCK_UN);
- X
- X if ((msg = getmsg(host->h_cmdfd)) == NULL)
- X break;
- X proc = change_to_proc(msg);
- X if (proc == NULL)
- X continue;
- X
- X errno = 0;
- X (*smap[ msg->m_syscall ].s_server)(msg, proc);
- X }
- X debug5("done.\n");
- X if (i_am_gateway)
- X for (proc = host->h_proclist; proc; proc=proc->p_next)
- X {
- X /*
- X * just hand it to the other server... he'll get eof
- X */
- X if (proc->p_handler != current_pid)
- X sendsig(proc->p_handler, SIGIO);
- X }
- X else
- X say_something(S_EOF, 0);
- X if ((remote_debug & 0x800) == 0)
- X unlink(logfile);
- X return(TRUE);
- X}
- X
- Xsetopts(argc, argv)
- X register int argc;
- X register char **argv;
- X{
- X register int error = FALSE;
- X register char **p;
- X extern char **environ;
- X
- X program = argv[0];
- X last_argaddr = argv[argc-1];
- X for (argv++, argc--; argc; argv++, argc--)
- X {
- X if (**argv != '-')
- X {
- X log("arg \"%s\" is unknown\n",
- X *argv);
- X error = TRUE;
- X }
- X switch(argv[0][1]) {
- X case 'v':
- X if (argv[0][2])
- X remote_debug = atox(argv[0] + 2);
- X else if (isdigit(argv[1][0]))
- X argc--, remote_debug = atox(*(++argv));
- X break;
- X case 's':
- X if (argv[0][2])
- X service = argv[0] + 2;
- X else
- X argc--, service = *(++argv);
- X break;
- X default:
- X log("unknown flag = %s\n", *argv);
- X error = TRUE;
- X }
- X }
- X /*
- X * Make sure that last_argaddr points to the last possible address
- X */
- X p = environ;
- X while (*p)
- X p++;
- X if (p != environ)
- X p--;
- X if (*p)
- X last_argaddr = *p;
- X last_argaddr = (char *)ctob(btoc(last_argaddr)) - 1;
- X debug5("program addr=%x, last_argaddr=%x\n", program, last_argaddr);
- X
- X if (error)
- X exit(1);
- X}
- X
- X/*
- X * ascii to hex
- X */
- Xatox(buf)
- X char *buf;
- X{
- X register char *p;
- X register unsigned num, nibble;
- X
- X /*
- X * now, take it out checking to make sure that the number is
- X * valid.
- X */
- X if (! buf)
- X return(0);
- X for(num=0, p = buf; *p; p++)
- X {
- X nibble = *p;
- X if (nibble >= 'A' && nibble <= 'F')
- X nibble -= 'A' - 10;
- X else if (nibble >= 'a' && nibble <= 'f')
- X nibble -= 'a' - 10;
- X else if (nibble >= '0' && nibble <= '9')
- X nibble -= '0';
- X else
- X return(0);
- X num = (num << 4) | nibble;
- X }
- X return(num);
- X}
- X
- X/*
- X * fork() and give the process on the top of the list to the child.
- X */
- Xbecome_server(msg)
- X register struct message *msg;
- X{
- X register long pid, i;
- X register char *fds;
- X register process *proc = host->h_proclist;
- X
- X /*
- X * Have to change to uid 0 or we may be refused a fork
- X */
- X change_to_uid(0);
- X i_am_asleep = TRUE;
- X if (pid = fork()) /* the parent loses control */
- X {
- X if (pid < 0)
- X log_fatal("cannot fork\n");
- X debug5("new server: pid=%d,mine=%d give him (%d)\n",
- X pid, current_pid, host->h_proclist->p_pid);
- X proc->p_handler = pid;
- X dont_gobble_msg(msg);
- X slumber(TRUE);
- X if (i_am_gateway)
- X current_server = pid;
- X return(FALSE);
- X }
- X
- X /*
- X * If we got this far, then we are no longer the gateway. So set
- X * our pid, etc. Also, try to dup stderr so that flock will work.
- X * If we can't do it, we are in big trouble.
- X */
- X current_ppid = current_pid;
- X current_pid = getpid();
- X if (i_am_gateway)
- X {
- X close(from_servers);
- X if (blocking_servers)
- X {
- X watch_for_lock = TRUE;
- X route_to_gateway = TRUE;
- X }
- X }
- X else
- X say_something(S_NEWSERVER, proc->p_pid);
- X i_am_gateway = FALSE;
- X set_label("active");
- X wildcard->p_handler = current_pid;
- X proc->p_handler = current_pid;
- X if ((i = dup(2)) < 0)
- X log_fatal("cannot dup(2)\n");
- X dup2(i, 2);
- X close(i);
- X debug5("new server: pid=%d, ppid=%d\n", current_pid, getppid());
- X
- X return(TRUE);
- X}
- X
- X#ifdef RFSDEBUG
- Xdumphost(h)
- X register hosts *h;
- X{
- X register rusers *ruser;
- X
- X if ((remote_debug & 0x10) == 0)
- X return;
- X log("host %s, local user = %s, ruser@%x\n",
- X *h->h_names,
- X h->h_default_user ? h->h_default_user->u_name : "default",
- X ruser = h->h_default_ruser);
- X log("\tr %s(%d)-->%s(%d)\n",
- X ruser->r_name, ruser->r_uid,
- X ruser->r_user->u_name, ruser->r_user->u_local_uid);
- X for(ruser = h->h_rusers; ruser; ruser=ruser->r_next)
- X log("\tr %s(%d)-->%s(%d)\n",
- X ruser->r_name, ruser->r_uid,
- X ruser->r_user->u_name, ruser->r_user->u_local_uid);
- X}
- X#endif RFSDEBUG
- X
- Xset_label(string)
- X register char *string;
- X{
- X char process_label[ 100 ];
- X static char *pend;
- X static short pid;
- X register char *pfrom, *pto;
- X register long i;
- X
- X if (pid != current_pid)
- X {
- X if (i_am_gateway)
- X sprintf(process_label, "%s gateway server: ",
- X host->h_names[0]);
- X else
- X sprintf(process_label, "%s server via %d: ",
- X host->h_names[0], pid);
- X pid = current_pid;
- X pend = program + strlen(process_label);
- X strncpy(program, process_label, last_argaddr - program);
- X pto = pend;
- X while (pto < last_argaddr)
- X *pto++ = ' ';
- X }
- X pto = pend;
- X pfrom = string;
- X while (pto < last_argaddr && *pfrom)
- X *pto++ = *pfrom++;
- X for (i=0; pto < last_argaddr && i<10; i++)
- X *pto++ = ' ';
- X if (pto <= last_argaddr)
- X *pto = '\0';
- X}
- SHAREOF
- chmod 444 remote/fileserver.c
- #
- # remote/find.c
- #
- if [ -f remote/find.c ]; then
- echo -n 'Hit <return> to overwrite remote/find.c or ^C to quit'
- read ans
- rm -f remote/find.c
- fi
-
- sed -e 's/^.//' << \SHAREOF > remote/find.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 * $Log: find.c,v $
- X * Revision 2.0 85/12/07 18:21:23 toddb
- X * First public release.
- X *
- X */
- Xstatic char *rcsid = "$Header: find.c,v 2.0 85/12/07 18:21:23 toddb Rel $";
- X#include "server.h"
- X#include <stdio.h>
- X#include <signal.h>
- X
- Xextern hosts *hostlist;
- Xextern hosts *host;
- Xextern users *userlist;
- Xextern boolean i_am_gateway;
- Xextern short current_pid;
- X
- Xprocess *findprocess(pid, uid)
- X register short pid;
- X register short uid;
- X{
- X register process *p;
- X register rusers *ruser;
- X
- X debug0("findproc: ", dumpprocs(host->h_proclist));
- X for(p = host->h_proclist; p; p=p->p_next)
- X if (p->p_pid == pid)
- X {
- X debug0("found pid %d\n", pid);
- X /*
- X * If the user changes uid, then change with him.
- X */
- X if (uid >= 0 && uid != p->p_uid)
- X {
- X debug2("pid %d changes uid %d->%d\n",
- X pid, p->p_uid, uid);
- X p->p_uid = uid;
- X if (ruser = findremuid(&host->h_rusers, uid))
- X p->p_ruser = ruser;
- X else
- X p->p_ruser = host->h_default_ruser;
- X debug2(" locally mapped to %s(%d)\n",
- X p->p_ruser->r_user->u_name,
- X p->p_ruser->r_user->u_local_uid);
- X }
- X toplist(&host->h_proclist, p);
- X return(p);
- X }
- X return(NULL);
- X}
- X
- X/*
- X * find the user structure whose name is 'name'.
- X */
- Xusers *findusername(name)
- X register char *name;
- X{
- X register users *user;
- X
- X for(user=userlist; user; user=user->u_next)
- X if (strcmp(user->u_name, name) == 0)
- X {
- X toplist(&userlist, user);
- X return(user);
- X }
- X return(NULL);
- X}
- X
- Xhosts *findhostname(name)
- X register char *name;
- X{
- X register hosts *h;
- X register int i;
- X register char **hnames;
- X
- X for(h=hostlist; h; h=h->h_next)
- X for (i=0, hnames=h->h_names; hnames[ i ]; i++)
- X if (strcmp(hnames[ i ], name) == 0)
- X {
- X toplist(&hostlist, h);
- X return(h);
- X }
- X return(NULL);
- X}
- X
- Xhosts *findhostaddr(addr)
- X register struct in_addr *addr;
- X{
- X register hosts *h;
- X
- X debug4("find %s...\n", inet_ntoa(*addr));
- X for(h=hostlist; h; h=h->h_next)
- X if (bcmp(addr, &h->h_addr, sizeof(struct in_addr)) == 0)
- X {
- X toplist(&hostlist, h);
- X debug4("\tis %s (%s)\n",
- X h->h_names[0], inet_ntoa(h->h_addr));
- X return(h);
- X }
- X else
- X debug4("\tnot %s (%s)\n",
- X h->h_names[0], inet_ntoa(h->h_addr));
- X log("no host entry for %s, continuing anyway.\n", inet_ntoa(*addr));
- X /*
- X * Kludge up a hosts structure for this guy
- X */
- X h = newhost();
- X h->h_names = newname(NULL, BOGUSHOST);
- X bcopy(addr, &h->h_addr, sizeof(struct in_addr));
- X addlist(&hostlist, h);
- X return(h);
- X}
- X
- Xrusers *findremuid(list, uid)
- X register rusers **list;
- X register int uid;
- X{
- X register rusers *ruser;
- X
- X for (ruser = *list; ruser; ruser=ruser->r_next)
- X if (ruser->r_uid == uid)
- X {
- X toplist(list, ruser);
- X return(ruser);
- X }
- X return(NULL);
- X}
- X
- X/*
- X * find the ruser structure whose name is 'name'.
- X */
- Xrusers *findrusername(list, name)
- X register rusers **list;
- X register char *name;
- X{
- X register rusers *ruser;
- X
- X for(ruser = *list; ruser; ruser=ruser->r_next)
- X if (strcmp(ruser->r_name, name) == 0)
- X {
- X toplist(list, ruser);
- X return(ruser);
- X }
- X return(NULL);
- X}
- X
- X#ifdef RFSDEBUG
- Xdumpprocs(p)
- X register process *p;
- X{
- X register long i, fd;
- X
- X while(p)
- X {
- X log("proc@%x,pid=%d,uid=%d,next@%x,prev@%x,handler=%d\n",
- X p, p->p_pid, p->p_uid, p->p_next, p->p_prev,
- X p->p_handler);
- X log("\t%s(%d)->%s(%d),fds=",
- X p->p_ruser->r_name, p->p_ruser->r_uid,
- X p->p_ruser->r_user->u_name,
- X p->p_ruser->r_user->u_local_uid);
- X for (i=0; i<NOFILE; i++)
- X if ((fd = p->p_fds[ i ]) >= 0)
- X log("%d->%d ", i, fd);
- X log("\n");
- X p=p->p_next;
- X }
- X}
- X#endif RFSDEBUG
- SHAREOF
- chmod 444 remote/find.c
- #
- # remote/info.c
- #
- if [ -f remote/info.c ]; then
- echo -n 'Hit <return> to overwrite remote/info.c or ^C to quit'
- read ans
- rm -f remote/info.c
- fi
-
- sed -e 's/^.//' << \SHAREOF > remote/info.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 * $Log: info.c,v $
- X * Revision 2.0 85/12/07 18:21:28 toddb
- X * First public release.
- X *
- X */
- Xstatic char *rcsid = "$Header: info.c,v 2.0 85/12/07 18:21:28 toddb Rel $";
- X#include "server.h"
- X#include <stdio.h>
- X#include <sys/wait.h>
- X#include <sys/file.h>
- X#include <sys/stat.h>
- X#include <netdb.h>
- X#include <errno.h>
- X
- Xextern users *default_user;
- Xextern hosts *host;
- Xextern hosts *thishost;
- Xextern char byteorder[];
- Xextern char *logfile;
- Xextern long serviceport;
- Xextern long errno;
- Xextern short current_pid;
- Xextern process *wildcard;
- Xextern boolean in_root_directory;
- Xextern boolean i_am_asleep;
- X
- Xgetbyteorder(h)
- X register hosts *h;
- X{
- X register char *p;
- X
- X /*
- X * Read the byte order info.
- X */
- X alarm(5);
- X p = (char *)h->h_byteorder;
- X if (read(h->h_cmdfd, p, 4) != 4)
- X {
- X log("can't read mount info from \"%s\"\n", h->h_names[0]);
- X alarm(0);
- X bzero(p, 4);
- X close(h->h_cmdfd);
- X h->h_cmdfd = -1;
- X return;
- X }
- X alarm(0);
- X if (bcmp(p, byteorder, 4) == 0)
- X h->h_byteorderok = TRUE;
- X else
- X h->h_byteorderok = FALSE;
- X debug4("byteorder=%d,%d,%d,%d: %s ours\n",
- X p[0], p[1], p[2], p[3],
- X h->h_byteorderok ? "same as" : "different than");
- X}
- X
- Xgetrusers(h)
- X register hosts *h;
- X{
- X char buf[ BUFSIZ ];
- X register rusers *ruser;
- X register FILE *input;
- X register char *p;
- X register int uid;
- X
- X errno = 0;
- X /*
- X * Read in the users from the remote host and squirrel them away.
- X * Actually it is the actual password file from the remote
- X * host, and we ignore most of the info, and save the user name and
- X * uid.
- X */
- X if ((input = fdopen(h->h_cmdfd, "r")) == NULL)
- X log_fatal("getrusers: cannot fdopen\n");
- X
- X alarm(30);
- X while (fgets(buf, BUFSIZ, input))
- X {
- X /*
- X * First, the user name.
- X */
- X for(p=buf; *p && *p != ':'; p++) ;
- X *p = '\0';
- X
- X /*
- X * now the user id number
- X */
- X for(p++; *p && *p != ':'; p++) ;
- X uid = atoi(p+1);
- X
- X /*
- X * Now we need to add the info to our database on this remote
- X * host. If the user is already present, just update the uid
- X * number. If the user is not present, and there is a default
- X * local user for this remote host, use that. If not, then
- X * use the default user entry for this host (where the server
- X * runs).
- X */
- X if (ruser = findrusername(&h->h_rusers, buf))
- X {
- X debug2("(existing) ");
- X ruser->r_uid = uid;
- X }
- X else
- X {
- X debug2("(new, ");
- X ruser = newruser();
- X ruser->r_name = copy(buf);
- X ruser->r_uid = uid;
- X if (h->h_default_user)
- X {
- X debug2("%s default)", *h->h_names);
- X ruser->r_user = h->h_default_user;
- X }
- X else
- X {
- X ruser->r_user = default_user;
- X debug2("host default)");
- X }
- X addlist(&h->h_rusers, ruser);
- X }
- X debug2("host %s: user %s (%d) -> local user %s (%d)\n",
- X h->h_names[ 0 ], ruser->r_name, ruser->r_uid,
- X ruser->r_user->u_name, ruser->r_user->u_local_uid);
- X }
- X fclose(input);
- X h->h_cmdfd = -1;
- X alarm(0);
- X if (errno == EINTR)
- X log("can't get remote users from \"%s\"\n", h->h_names[0]);
- X}
- X
- X/*
- X * Try to obtain mount information for host 'h'.
- X */
- Xgetmount(h)
- X register hosts *h;
- X{
- X long savefd = h->h_cmdfd;
- X struct message msgbuf;
- X register struct message *msg = &msgbuf;
- X register long len;
- X
- X if (thishost == h) /* our own machine */
- X {
- X log("we are talking to ourselves\n");
- X h->h_cmdfd = open("/etc/passwd", O_RDONLY);
- X bcopy(byteorder, h->h_byteorder, 4);
- X h->h_byteorderok = TRUE;
- X }
- X else
- X {
- X if ((h->h_cmdfd = tcpconnect(h)) < 0)
- X goto done;
- X len = R_MINRMSG + sizeof(long);
- X msg->m_hdlen = htons(len);
- X msg->m_totlen = htonl(len);
- X msg->m_syscall = htons(RSYS_nosys);
- X msg->m_args[ 0 ] = htonl(CMD_NEEDMOUNT);
- X if (!sndmsg(h->h_cmdfd, msg, len, 0, 0))
- X {
- X log("can't ask for mount info\n");
- X close(h->h_cmdfd);
- X goto done;
- X }
- X getbyteorder(h);
- X }
- X getrusers(h); /* getrusers() closes the file descriptor */
- Xdone:
- X h->h_cmdfd = savefd;
- X}
- X
- X/*
- X * Send mount information. This includes a 4-byte header containing the
- X * byte order for our machine, followed by /etc/passwd.
- X */
- Xsendmount(h)
- X register hosts *h;
- X{
- X char buf[ BUFSIZ ];
- X register long fd = open("/etc/passwd", O_RDONLY),
- X cnt;
- X register char *p = buf;
- X
- X write(h->h_cmdfd, byteorder, 4);
- X while ((cnt = read(fd, p, BUFSIZ)) > 0)
- X _rmtio(write, h->h_cmdfd, p, cnt);
- X close(h->h_cmdfd);
- X h->h_cmdfd = -1;
- X close(fd);
- X}
- X
- X/*
- X * Mourne the death of any children.
- X */
- Xmourne()
- X{
- X union wait status;
- X char buf[ BUFSIZ ];
- X register char *p = buf;
- X register long pid;
- X
- X while ((pid = wait3(&status, WNOHANG, 0)) > 0)
- X {
- X sprintf(p, "server %d found dead", pid);
- X p += strlen(p);
- X if (status.w_termsig)
- X sprintf(p, " by sig #%d", status.w_termsig);
- X p += strlen(p);
- X if (status.w_coredump)
- X sprintf(p, " with core dump", status.w_termsig);
- X p += strlen(p);
- X sprintf(p, " exit=%d\n", status.w_retcode);
- X debug5("%s", buf);
- X p = buf;
- X }
- X}
- X
- X/*
- X * Catch signals and only report.
- X */
- Xcatch(sig, code, scp)
- X register long sig,
- X code;
- X register struct sigcontext *scp;
- X{
- X log("caught signal #%d...", sig);
- X if (sig == SIGILL || sig == SIGSEGV || sig == SIGBUS)
- X {
- X change_to_uid(0);
- X chdir("/usr/tmp");
- X log("aborting: code=%d, scp=%x, sp=%x, pc=%x, end of scp=%x\n",
- X code, scp, scp->sc_sp, scp->sc_pc, scp+1);
- X sendsig(current_pid, SIGEMT);
- X log_fatal("could not abort\n");
- X }
- X else if (sig == SIGTERM) /* quietly go away */
- X {
- X /*
- X * unlink the file only if we are allowed to and if it is
- X * not the sentry server's logfile.
- X */
- X if ((remote_debug & 0x800) == 0 && host != NULL)
- X unlink(logfile);
- X cleanup();
- X log("goodbye.\n");
- X exit(0);
- X }
- X else
- X log_fatal("exiting\n");
- X}
- X
- X/*
- X * Receive a wakeup call.
- X */
- Xwakeup_call()
- X{
- X if (! i_am_asleep)
- X {
- X log("recieved spurious wakeup call!\n");
- X return;
- X }
- X i_am_asleep = FALSE;
- X}
- X
- X/*
- X * Provide name server function for kernel. At this point we have just
- X * recieved a SIGURG signal because the kernel wants us to translate a
- X * name.
- X */
- Xnameserver()
- X{
- X#ifdef CANREMOTE
- X char path[ BUFSIZ ],
- X hostname[ BUFSIZ ];
- X struct sockaddr_in sinbuf;
- X register char *p1, *p2, *name;
- X register hosts *h = NULL;
- X register struct sockaddr_in *sin;
- X
- X if (remotename(NM_WHATNAME, 0, BUFSIZ, path) < 0)
- X return;
- X /*
- X * Find the end of the '/' prefix and copy up to the next '/' or
- X * null character.
- X */
- X p1 = path;
- X while (*p1 == '/')
- X p1++;
- X p2 = hostname;
- X *p2++ = '/';
- X while (*p1 && *p1 != '/')
- X *p2++ = *p1++;
- X *p2 = '\0';
- X
- X /*
- X * Now look it up.
- X */
- X if (hostname[1])
- X h = findhostname(hostname+1);
- X if (h == NULL)
- X {
- X debug6("cannot find host for path \"%s\"\n", path);
- X sin = NULL;
- X }
- X else
- X {
- X sin = &sinbuf;
- X debug6("path %s mapped to host %s\n", path, h->h_names[0]);
- X bzero((char *)sin, sizeof (struct sockaddr_in));
- X bcopy(&h->h_addr, (char *)&sin->sin_addr,
- X sizeof(struct in_addr));
- X sin->sin_family = AF_INET;
- X sin->sin_port = serviceport;
- X }
- X remotename(NM_NAMEIS, sin, sizeof(struct sockaddr_in), hostname);
- X#endif CANREMOTE
- X}
- X
- X/*
- X * Decide if a file is really a local file to the client or not. We only
- X * look for explicit references like
- X * name1/name2/../name3 ...
- X * And we then check to see whether name2 is the root directory. If it is
- X * then we send the request back to the client.
- X */
- Xislocal(msg, type)
- X register struct message *msg;
- X{
- X register char *p;
- X register boolean checktwopaths;
- X register short syscall = msg->m_syscall;
- X register long offset1,
- X offset2 = -1,
- X localcnt = 0;
- X register process *proc;
- X char buf[ BUFSIZ ];
- X
- X debug10("cwd=%s\n", getwd(buf));
- X checktwopaths = (type & NEED_2REMOTE);
- X
- X if (checktwopaths)
- X p = twopath1addr(msg);
- X else
- X p = path1addr(msg);
- X if ((offset1 = find_dotdot(p)) >= 0)
- X localcnt++;
- X if (checktwopaths)
- X if ((offset2 = find_dotdot(twopath2addr(msg))) >= 0)
- X localcnt++;
- X if (localcnt)
- X {
- X debug10("%d paths are remote: \"%s\" @ %d, \"%s\" @ %d\n",
- X localcnt,
- X checktwopaths ? twopath1addr(msg) : path1addr(msg),
- X offset1, checktwopaths ? twopath2addr(msg) : "",
- X offset2);
- X setup_proc(proc = wildcard, msg->m_uid, msg->m_pid);
- X proc->p_errno = -1;
- X proc->p_returnval = offset1;
- X sendreturn(proc, host->h_cmdfd, NULL, 1, offset2);
- X }
- X return(localcnt);
- X}
- X
- X/*
- X * kernel code stolen for speed.
- X */
- Xmyaccess(st, user, perm)
- X register struct stat *st;
- X register long perm;
- X register users *user;
- X{
- X register long *gp, i;
- X
- X perm <<= 6;
- X if (user->u_local_uid != st->st_uid) {
- X perm >>= 3;
- X gp = user->u_local_groups;
- X for (i=0; i < user->u_numgroups; i++, gp++)
- X if (st->st_gid == *gp)
- X goto found;
- X perm >>= 3;
- Xfound:
- X ;
- X }
- X if ((st->st_mode & perm) != 0)
- X return (TRUE);
- X return(FALSE);
- X}
- X
- X/*
- X * look for a component of ".." terminated by a '/' or a null character.
- X * If we find one, examine the previous component to see if it is our
- X * root directory.
- X */
- Xfind_dotdot(path)
- X register char *path;
- X{
- X struct stat statb;
- X register char *p;
- X register struct stat *statp = &statb;
- X register long retval;
- X extern struct stat root;
- X
- X for (p = path; *p;)
- X {
- X while (*p == '/')
- X p++;
- X if (p[0] == '.' && p[1] == '.'
- X && (p[2] == '\0' || p[2] == '/'))
- X {
- X if (p == path)
- X if (in_root_directory)
- X return(0);
- X else
- X goto next_component;
- X *p = '\0'; /* we know it is a '.' */
- X retval = lstat(path, statp);
- X *p = '.';
- X if (retval < 0)
- X return(retval);
- X if (isroot(statp))
- X return(p - path + 1);
- X }
- Xnext_component:
- X while (*p && *p != '/')
- X p++;
- X }
- X return(-1);
- X}
- SHAREOF
- chmod 444 remote/info.c
- #
- # remote/init.c
- #
- if [ -f remote/init.c ]; then
- echo -n 'Hit <return> to overwrite remote/init.c or ^C to quit'
- read ans
- rm -f remote/init.c
- fi
-
- sed -e 's/^.//' << \SHAREOF > remote/init.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 * $Log: init.c,v $
- X * Revision 2.1 86/01/05 18:13:54 toddb
- X * Added include for sys/stat.h because pyramid machines get upset.
- X *
- X * Revision 2.0 85/12/07 18:21:37 toddb
- X * First public release.
- X *
- X */
- Xstatic char *rcsid = "$Header: init.c,v 2.1 86/01/05 18:13:54 toddb Exp $";
- X#include "server.h"
- X#include <stdio.h>
- X#include <pwd.h>
- X#include <grp.h>
- X#include <netdb.h>
- X#include <fcntl.h>
- X#include <sys/dir.h>
- X#include <sys/user.h>
- X#include <sys/signal.h>
- X#include <sys/ioctl.h>
- X#include <sys/stat.h>
- X
- Xextern hosts *hostlist;
- Xextern hosts *thishost;
- Xextern users *userlist;
- Xextern users *default_user;
- Xextern char hostname[];
- Xextern char *service;
- Xextern short current_uid;
- Xextern short current_pid;
- Xextern process *wildcard;
- Xextern struct sigvec sig_vec;
- Xextern struct sigvec sig_name;
- Xextern struct sigvec sig_alarm;
- Xextern struct sigvec sig_ignore;
- Xextern struct sigvec sig_continue;
- X#ifdef RFSDEBUG
- Xextern struct sigvec sig_debug;
- X#endif
- Xextern struct stat root;
- X
- X/*
- X * Initialize the host tables and user tables.
- X */
- Xinit()
- X{
- X long tt;
- X struct hostent *gethostent();
- X struct passwd *getpwent();
- X struct group *getgrent();
- X
- X /*
- X * catch signals.
- X */
- X sigvec(SIGHUP, &sig_ignore, (struct sigvec *)0);
- X sigvec(SIGINT, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGQUIT, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGILL, &sig_vec, (struct sigvec *)0);
- X#ifdef RFSDEBUG
- X sigvec(SIGTRAP, &sig_debug, (struct sigvec *)0);
- X#endif RFSDEBUG
- X /* SIGIOT */
- X /* SIGEMT */
- X /* SIGFPE */
- X /* SIGKILL */
- X sigvec(SIGBUS, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGSEGV, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGSYS, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGPIPE, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGALRM, &sig_alarm, (struct sigvec *)0);
- X sigvec(SIGTERM, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGURG, &sig_name, (struct sigvec *)0);
- X /* SIGSTOP */
- X /* SIGTSTP */
- X /* SIGCONT */
- X /* SIGCHLD */
- X sigvec(SIGTTIN, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGTTOU, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGIO, &sig_continue, (struct sigvec *)0);
- X sigvec(SIGXCPU, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGXFSZ, &sig_vec, (struct sigvec *)0);
- X sigvec(SIGVTALRM, &sig_vec, (struct sigvec *)0);
- X /* SIGPROF */
- X
- X /*
- X * set up some important global values, including uid, pid,
- X * the pipe file descriptors for messages to and from the gateway
- X * server. Register as the nameserver. Get host name. Get service.
- X * Get root stat info.
- X */
- X if (chdir("/") == -1)
- X log_fatal("cannot chdir(\"/\")\n");
- X wildcard = newprocess();
- X fcntl(2, F_SETFL, FAPPEND);
- X close(0);
- X close(1);
- X change_to_uid(0);
- X if (gethostname(hostname, HOSTNAMELEN) < 0 || *hostname == '\0')
- X log_fatal("host name not set!\n");
- X if (stat("/", &root) < 0)
- X log_fatal("cannot stat /\n");
- X#ifdef CANREMOTE
- X if (remotename(NM_SERVER, 0, 0, 0) < 0)
- X log("cannot register as nameserver\n");
- X /*
- X * Turn off remote access, if we have any.
- X */
- X remoteoff(NULL);
- X#endif
- X tt = open("/dev/tty", 2);
- X
- X if (tt >= 0)
- X {
- X ioctl(tt, TIOCNOTTY, 0);
- X close(tt);
- X }
- X setpgrp(0,0);
- X
- X initusers();
- X initgroups();
- X inithosts();
- X initrhosts();
- X}
- X
- X/*
- X * build the list of users on this host (where the server runs).
- X */
- Xinitusers()
- X{
- X register struct passwd *pw;
- X register users *user;
- X char buf[ BUFSIZ ];
- X register char *pbuf = buf;
- X
- X while(pw = getpwent())
- X {
- X if (*pw->pw_dir == '\0' || *pw->pw_name == '\0')
- X {
- X log("login \"%s\" has problems, dir=\"%s\"\n",
- X pw->pw_name, pw->pw_dir);
- X continue;
- X }
- X user = newuser();
- X user->u_local_uid = pw->pw_uid;
- X user->u_name = copy( pw->pw_name );
- X addgroup(user, pw->pw_gid);
- X user->u_dir = copy( pw->pw_dir );
- X sprintf(pbuf, "%s/.rhosts", pw->pw_dir);
- X user->u_rhosts = copy( pbuf );
- X addlist(&userlist, user);
- X }
- X endpwent();
- X if (user = findusername(DEFAULTUSER))
- X default_user = user;
- X else
- X log_fatal("The user \"%s\" must be in /etc/passwd (%s)\n",
- X DEFAULTUSER, "for default permissions");
- X}
- X
- X/*
- X * Build the list of groups that each user belongs to.
- X */
- Xinitgroups()
- X{
- X register struct group *gr;
- X register users *user;
- X register char **p;
- X
- X
- X while(gr = getgrent())
- X {
- X for (p = gr->gr_mem; *p; p++)
- X if (user = findusername(*p))
- X addgroup(user, gr->gr_gid);
- X else
- X log("group %s: bad user=%s\n",
- X gr->gr_name, *p);
- X }
- X endgrent();
- X}
- X
- X/*
- X * Then build the list of all hosts.
- X */
- Xinithosts()
- X{
- X register struct hostent *h;
- X register rusers *ruser;
- X register hosts *hst;
- X register users *user;
- X register long i;
- X
- X while (h = gethostent())
- X {
- X hst = newhost();
- X hst->h_names = newname(hst->h_names, h->h_name);
- X for (i=0; h->h_aliases[ i ]; i++)
- X hst->h_names = newname(hst->h_names,
- X h->h_aliases[ i ]);
- X
- X hst->h_addr = *((struct in_addr *)(h->h_addr));
- X addlist(&hostlist, hst);
- X
- X /*
- X * now if there exists a user on this machine having
- X * the same name as the name of this host (NOT AN
- X * ALIAS!), then that will be our defaut local user
- X * to map to. Be sure that we don't allow a machine
- X * to be mapped onto a user if the uid is real small:
- X * e.g. a machine named root, where all its user ids
- X * become root using the remote fs!
- X */
- X user = findusername(hst->h_names[ 0 ]);
- X if (user && user->u_local_uid <= UID_TOO_LOW)
- X {
- X log("host/user %s: uid %d too low for alias\n",
- X hst->h_names[ 0 ], user->u_local_uid);
- X user = NULL;
- X }
- X else if (user)
- X {
- X hst->h_default_user = user;
- X debug2("default user for host %s (%s) is %s\n",
- X hst->h_names[ 0 ],
- X inet_ntoa(hst->h_addr), user->u_name);
- X }
- X ruser = hst->h_default_ruser = newruser();
- X if (user)
- X ruser->r_user = user;
- X else
- X ruser->r_user = default_user;
- X ruser->r_uid = -1;
- X ruser->r_name = copy(BOGUSUSER);
- X }
- X endhostent();
- X if ((thishost = findhostname(hostname)) == NULL)
- X log_fatal("this host (\"%s\") is not in host file\n",
- X hostname);
- X}
- X
- X/*
- X * Now for each user that has a .rhosts file, assemble the
- X * references and attach them to the appropriate host.
- X */
- Xinitrhosts()
- X{
- X register hosts *hst;
- X register rhost *rh;
- X register users *user;
- X char buf[ BUFSIZ ];
- X register char *pbuf = buf;
- X
- X for (user=userlist; user; user=user->u_next)
- X {
- X setrhost(user->u_rhosts);
- X while (rh = getrhostent(pbuf))
- X if (hst = findhostname(rh->rh_host))
- X addremoteuser(hst, user, rh->rh_user);
- X endrhost();
- X }
- X}
- X
- Xchar *copy(string)
- X register char *string;
- X{
- X register char *ret = malloc( strlen(string)+1 );
- X
- X if (ret == NULL)
- X log_fatal("cannot allocate space\n");
- X strcpy(ret, string);
- X return(ret);
- X}
- X
- X/*
- X * Add a remote user to those recognized on a certain host.
- X */
- Xaddremoteuser(h, user, remoteuser)
- X register hosts *h;
- X register users *user;
- X register char *remoteuser;
- X{
- X register rusers *ruser;
- X register long old = FALSE;
- X
- X debug2("\t%s!%s --> %s ", *h->h_names, remoteuser, user->u_name);
- X if ((ruser = findrusername(&h->h_rusers, remoteuser)) == NULL)
- X {
- X debug2("\n");
- X ruser = newruser();
- X }
- X else
- X {
- X old = TRUE;
- X if (strcmp(remoteuser, user->u_name) != 0)
- X {
- X debug2("(old, ignored)\n");
- X return;
- X }
- X else
- X debug2("(old)\n");
- X }
- X ruser->r_name = copy(remoteuser);
- X ruser->r_uid = -1;
- X ruser->r_user = user;
- X if (! old)
- X addlist(&h->h_rusers, ruser);
- X}
- SHAREOF
- chmod 444 remote/init.c
-
-