home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume3 / rfs / part2 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  61.2 KB

  1. Subject: RFS: remote file system (part 2 of 7)
  2. Newsgroups: mod.sources
  3. Approved: jpn@panda.UUCP
  4.  
  5. Mod.sources:  Volume 3, Issue 78
  6. Submitted by: tektronix!tekcrl!toddb
  7.  
  8. #!/bin/sh
  9. #
  10. # RFS, a kernel-resident remote file system.  Shar 2 of 7
  11. #
  12. #
  13. # This is a shell archive, meaning:
  14. # 1. Remove everything above the #!/bin/sh line.
  15. # 2. Save the resulting text in a file.
  16. # 3. Execute the file with /bin/sh (not csh) to create the files:
  17. #    remote/doc/paper/remotefs
  18. #    remote/doc/remotename.2
  19. #    remote/doc/remoteon.2
  20. #    remote/doc/rfs_server.8
  21. #    remote/doc/rmtmnt.8
  22. #    remote/file.c
  23. #    remote/fileserver.c
  24. #    remote/find.c
  25. #    remote/info.c
  26. #    remote/init.c
  27. #
  28. # remote/doc/paper/remotefs
  29. #
  30. if [ -f remote/doc/paper/remotefs ]; then 
  31.     echo -n 'Hit <return> to overwrite remote/doc/paper/remotefs or ^C to quit' 
  32.     read ans 
  33.     rm -f remote/doc/paper/remotefs 
  34. fi 
  35.  
  36. sed -e 's/^.//' << \SHAREOF > remote/doc/paper/remotefs
  37. X.HS I
  38. X.if "\*(.T"mag" \{\
  39. X.    nr PS 12
  40. X.    nr VS 14
  41. X.\}
  42. X.pl 9.75i
  43. X.TR
  44. X.DR
  45. X.de CN
  46. X..
  47. X.TL
  48. XDesign Considerations for Remote File Systems
  49. X(Extended Abstract)
  50. X.AU
  51. XT. Brunhoff
  52. X.AI
  53. XComputer Environments Group
  54. XApplied Research Group
  55. XTektronix, inc.
  56. X.AB
  57. XThere have been several remote file systems written,
  58. Xincluding one written by the author called \fBRemotefs\fR.
  59. XThis paper covers the design choices
  60. Xthat can be made at several software levels,
  61. Xfrom where the hooks for a remote file system
  62. Xlie in the operating system,
  63. Xon up to the user interface,
  64. Xand reveals those made by \fBRemotefs\fP.
  65. XThe reader should have a strong familiarity
  66. Xwith the 4.2 BSD kernel function \fInamei()\fP,
  67. Xthe concept of mount points,
  68. Xthe system call interface and
  69. Xthe 4.2 BSD socket paradigm.
  70. X.AE
  71. X.SH
  72. XHistory
  73. X.PP
  74. XThe Computer Research Labs within the Applied Research Group
  75. Xhas approximately forty-five internally\-designed workstations,
  76. Xcalled
  77. X.I Magnolias,
  78. Xtwenty newly announced Tektronix 4404 AI workstations,
  79. Xcalled \fIPegasus\fP, a
  80. X.I VAX 11/780
  81. Xand a
  82. X.I VAX 11/750.
  83. XThe Computer Environments Group,
  84. Xwithin the Computer Research Labs
  85. Xcares for most of these machines and the software that runs on them.
  86. X.PP
  87. XAfter porting 4.2 BSD Unix to the
  88. X.I Magnolia,
  89. Xthe amount of software available quickly outgrew
  90. Xthe capacity of its 35-megabyte winchester drives.
  91. XTo alleviate this,
  92. Xthe author designed and began in December of 1984 to write a
  93. Xremote file system based on a implementation paradigm used
  94. Xby K. McKusick in his implementation of the 4.2 BSD file system;
  95. Xi.e., "write it in user-mode to fit in the kernel".
  96. XThis paper is in part
  97. Xabout that implementation,
  98. Xand about design and
  99. Ximplementation in general to achieve a remote (or distributed) file system.
  100. XAt this writing,
  101. Xthe design still lies mostly in the user level,
  102. Xlinked in by the \fBld(1)\fP flag
  103. X\fI\-lremote\fP,
  104. Xwith a few new system calls.\(dg
  105. X.FS \(dg
  106. XThis remote file system,
  107. Xknown simply as \fBRemotefs\fP,
  108. Xshould not be confused with another,
  109. Xmore complete remote file system,
  110. Xcalled \fBDFS\fR.
  111. XThe latter is available on the Tektronix 6000 series workstations.
  112. X.FE
  113. X.NH 1
  114. XChoosing a Springboard for the Software
  115. X.PP
  116. XThe focus of I/O activity on 
  117. X.B UNIX
  118. Xis the inode;
  119. Xeach time a file is open, read, written, locked, closed, etc.,
  120. Xthe inode is referred to.
  121. XThese system calls
  122. Xconverge on the system call interface which dispatches calls to
  123. Xthe appropriate internal routine.
  124. XAny system calls that involve a path name must call \fInamei()\fP
  125. Xfor the inode information, and similarly, any system calls that
  126. Xdeal with file descriptors must refer to the inode information
  127. Xgenerated by an \fIopen()\fP or \fIcreate()\fR.
  128. XOnly then can the data on the disks be accessed.
  129. X.so fig1.\*(.T
  130. X.PP
  131. XFor example, in Figure 1,
  132. X\fIopen()\fP makes a request to the system call interface;
  133. Xthe system call interface determines that the \fIopen()\fP system call must
  134. Xbe executed (the kernel \fIopen()\fP is just a call to \fIcopen()\fP).
  135. X\fICopen()\fP then calls \fInamei()\fP to get the inode information
  136. Xwhich in turn calls the appropriate disk device driver to get the inode
  137. Xfrom the correct disk.
  138. XSubsequent \fIread()\fP
  139. Xor \fIwrite()\fP calls use this information to access the disk.
  140. XIt makes sense to make \fInamei()\fP the focal point for the remote
  141. Xfile system implementation
  142. Xbecause of its critical role.
  143. XBut there are other approaches.
  144. X.NH 2
  145. X\&\.\.\. From the Device Driver
  146. X.PP
  147. XSince \fInamei()\fP gets its information from the
  148. Xdisk via the disk driver,
  149. Xwe have only to
  150. Xreplace the disk driver with a \fIremote\fP disk driver.
  151. XThis remote disk driver would be designed to send requests for disk
  152. Xblocks directly to a remote host to be satisfied
  153. Xfrom a single partition on its own disk.
  154. X.so fig2.\*(.T
  155. X.PP
  156. XNow, following the previous example in Figure 2,
  157. X\fInamei()\fP may instead encounter a mount point while
  158. Xtrying to find an inode for a file,
  159. Xand will get its inode information from the remote disk driver.
  160. XSimilarly,
  161. Xreads and writes
  162. Xrequest blocks from the \fIremote\fP disk driver
  163. Xusing this inode information.
  164. X.PP
  165. XThis is where early implementations put remote file systems.
  166. XIt offers speed and a good deal of portability with
  167. Xthe kernel changes limited to the device driver,
  168. Xbut it limits usefulness because each partition
  169. Xon every remote system must be mounted,
  170. Xand access can only be read\-only.
  171. X.NH 2
  172. X\&\.\.\. In \fInamei()\fP
  173. X.PP
  174. XThere are two ways of checking for ``remoteness''
  175. Xin \fInamei()\fP,
  176. Xbut the key change to \fInamei()\fP is that it must fail in
  177. Xits inode lookup when it encounters a path name component
  178. Xon a remote machine; then it must return with a special error.
  179. XThis \fInamei()\fP failure mechanism will be alluded to later.
  180. X.PP
  181. XOne method, depicted in Figure 3,
  182. Xis to catch any reference to a special
  183. Xsyntax of path name,
  184. Xsuch as \fI/\.\.\|/host/pathname\fP,
  185. X\fI/net/host/pathname\fP
  186. Xor \fI//host/pathname\fP.
  187. XThis is a cue to \fInamei()\fP
  188. Xto return a special error code to the invoking system call.
  189. XIt is then
  190. Xthe responsibility of that system call to send
  191. Xa request to a server on the remote host.
  192. XThis special syntax is very convenient because the
  193. X\fIhost\fP component of the path
  194. Xneed not correspond to some existing ``mount point''.
  195. XHence, hosts can be mounted and unmounted on demand
  196. Xif the implementor cares to take the trouble.
  197. X.so fig3.\*(.T
  198. X.PP
  199. XA second strategy is very similar
  200. Xexcept that it uses a more natural
  201. Xsyntax of \fI/host/pathname\fP
  202. X(without needing symbolic links).
  203. XAn important point is that the host cannot be ``mounted''
  204. Xon a directory,
  205. Xbut rather on a special mount point,
  206. Xor even a plain file.
  207. XThe reason for this is a bit obscure,
  208. Xbut will be clarified shortly.
  209. X.PP
  210. XThe special path names like \fI/\.\.\|/host/pathname\fP
  211. Xor mount points like \fI/host\fP are needed partly because no
  212. XUNIX program should ever find these gateways through normal perusal of
  213. Xa file system.
  214. XImagine how long the command ``\fIfind / -print\fP'' would take
  215. Xif it traversed every remote host as well as itself!
  216. XFor this reason, using a directory for a mount point would
  217. Xnot be appropriate.
  218. X.PP
  219. X\fBRemotefs\fP uses a plain file as a mount point because of some extra
  220. Xbenefits:
  221. Xthe simplicity of the code changes to \fInamei()\fP,
  222. Xand not having to add another file type for \fBUNIX\fP utilities to learn.
  223. XThe path name \fI/host\fP remains a valid local filename,
  224. Xbut \fI/host/\fP or anything longer results in
  225. Xa special case, which \fInamei\fP labels with the error
  226. X\fBENOTDIR\fP
  227. X(See Appendix A).
  228. XIt is this place in the \fBUNIX\fP kernel
  229. Xthat \fBRemotefs\fP detects all remote file references.
  230. X.NH 3
  231. XAn Aside: When to Follow a Symbolic Link in \fINamei()\fP.
  232. X.NH 2
  233. X\&\.\.\. At the User Level.
  234. X.PP
  235. XA slight variation of the above,
  236. Xshown in Figure 4,
  237. Xis to simply place the check for ``remoteness'' in
  238. Xappropriate system calls with in the C runtime library,
  239. X\fIlibc.a\fP.
  240. X(see Appendix B for this list).
  241. XUnfortunately,
  242. Xthis requires the user level software to duplicate
  243. Xwhat \fInamei()\fP does
  244. Xwhenever a system call involving a path name returns the
  245. Xerror \fBENOENT\fR or \fBENOTDIR\fR.
  246. XThis implementation approach is typically slower,
  247. Xbut very portable.
  248. X.so fig4.\*(.T
  249. X.NH 1
  250. XFile Descriptors
  251. X.PP
  252. XOnce an \fIopen()\fP or \fIcreat()\fP has succeeded
  253. Xon the remote host and returned a file descriptor, say \fIi\fP,
  254. Xwe must allocate a real file descriptor, \fIj\fP, on the local machine.
  255. XThis may be done in the kernel or user level code,
  256. Xbut it is most important that the user's idea of the ordinate
  257. Xvalue of \fIj\fP remain inviolate.
  258. X.NH 2
  259. XFile Descriptors Handled at User Level
  260. X.NH 2
  261. XFile Descriptors Handled at Kernel Level
  262. X.NH 2
  263. XInheriting File Descriptors Across a \fIfork()\fP or \fIexec()\fP
  264. X.NH 2
  265. XReading Directories on a Remote Host
  266. X.NH 1
  267. XChanging Directories
  268. X.PP
  269. XImplementing the ability to change
  270. Xdirectories is a big win for any implementation
  271. Xbecause interactive shells will then allow you to
  272. Xperuse directories on remote hosts.
  273. XHowever, inheritance of file descriptors must
  274. Xbe implemented,
  275. Xas explained in section 2.3.
  276. XThe \fIchdir()\fP executing on the remote host
  277. Xdoes nothing special.
  278. XIf it succeeds, all is well.
  279. XBut on the local side,
  280. Xthe software cannot change state (the current
  281. Xworking directory)
  282. Xto match what has occurred on the remote machine.
  283. XInstead,
  284. Xit must simply be remembered it in some way.
  285. X.NH 2
  286. XInterpreting Pathnames
  287. X.PP
  288. XIf the remote file system software lies entirely in user\-level code,
  289. Xthen the only solution is for the software
  290. Xto remember \fIchdir()\fP's path name argument
  291. Xand that the current directory is on a remote host.
  292. XThen when a new path name is passed to a system call,
  293. Xthe software need only to check to see if it is absolute
  294. Xor relative (with or without a leading '/' character, respectively).
  295. XIf it is relative,
  296. Xthen the request must be sent to the remote host.
  297. X.PP
  298. XOn the other hand if the software uses a special
  299. Xmount point like \fI/host\fP,
  300. Xthe kernel can arrange
  301. Xto make the process's working directory inode
  302. Xto be the mount point's inode.
  303. XThis is very convenient because no absolute vs. relative
  304. Xchecks are necessary
  305. Xand nothing need be added to \fInamei()\fP.
  306. XFor example,
  307. Xabsolute path names in a system call will still cause the mechanism
  308. Xto function normally.
  309. XAnd relative path names will immediately fail in \fInamei()\fP
  310. X(remember our key change in section 1.2).
  311. XSee Appendix A.
  312. X.NH 2
  313. XPwd(1) and Changing to ``/\.\.'' on the Remote Host
  314. X.NH 1
  315. XSpecial Problems
  316. X.NH 2
  317. X\fIExec()\fP
  318. X.NH 2
  319. X\fIFork()\fP and \fIvfork()\fP
  320. X.NH 2
  321. X\fISelect()\fP
  322. X.NH 2
  323. XUniqueness of Files Across Hosts
  324. X.NH 1
  325. XPermissions Across Hosts
  326. X.NH 2
  327. XDatabase Model
  328. X.NH 2
  329. XDynamic Model
  330. X.NH 1
  331. XServer Design
  332. X.NH 2
  333. XWhen to \fIfork()\fP
  334. X.NH 2
  335. XHow to Change Uid/Gid permissions
  336. X.NH 2
  337. XFile Descriptor Overload
  338. X.NH 2
  339. XCommunication Model
  340. X.NH 3
  341. XProtocol
  342. X.NH 3
  343. XWho Answers the Phone?
  344. X.NH 3
  345. XSpeed Improvements
  346. X.PP
  347. XImagine
  348. Xa very loose view of the protocol (moving downward):
  349. X.so fig5.\*(.T
  350. XA remote file system implementation
  351. Xhas a decidedly synchronous flavor to it,
  352. Xand for most system calls,
  353. Xnothing else is appropriate.
  354. XBut \fIRead()\fP and \fIwrite()\fP system calls
  355. Xlend themselves very well to optimization,
  356. Xspecifically, lookahead.
  357. X.PP
  358. XA change in the protocol could be made
  359. Xbased on expected requests.
  360. XAfter,
  361. Xsay, two consecutive \fIread()\fP requests
  362. Xon the same file descriptor for the same number of bytes,
  363. Xthe local host could ask the server to continue servicing
  364. Xthe same request until further notice.
  365. XThe response would contain the same information
  366. Xthat would be expected on a normal request,
  367. Xand would, of course,
  368. Xterminate on an error or end\-of\-file.
  369. XThe remote host, could easily detect and recover from a termination
  370. Xof this kind, too.
  371. XThe difficult part would be for the local host to try to stop
  372. Xthe servicing before end\-of\-file.
  373. XSo,
  374. Xour protocol now would be
  375. X.so fig6.\*(.T
  376. XNotice that the responses may continue on beyond
  377. Xthe request to stop,
  378. Xbut the acknowledgment of the request to stop would put
  379. Xthe hosts back in sync.
  380. XThe remote host has only to reset its read pointer
  381. Xback to the point where it had serviced
  382. X\fIn\fP requests,
  383. Xand the local host must read the responses up to and including
  384. Xthe acknowledgment.
  385. X.PP
  386. XThe protocol also may
  387. Xhave to refuse continuation service for file descriptors
  388. Xthat read from devices.
  389. X.PP
  390. X\fIWrite()\fP is similar,
  391. Xbut recovery when the remote host
  392. Xreaches an end\-of\-file or encounters an error
  393. Xwould be much more complicated, and in some cases impossible.
  394. XThe local host,
  395. Xon receipt of a request to stop from the remote host,
  396. Xwould have to not only reset its idea of the write pointer,
  397. Xbut perhaps the read pointer from which the data was gathered
  398. Xto do the write.
  399. XConsidering that the reading may have been done from multiple
  400. Xfiles or the data was transformed in some way,
  401. Xthe remote file system software may not be able to accomplish the task.
  402. XIt appears to be only feasible if the implementor is willing to sacrifice
  403. Xidentical behavior of user\-level software on remote vs. local file
  404. Xsystems.
  405. X.NH 1
  406. XStatus of \fBRemotefs\fP
  407. X.NH 1
  408. XAppendix A
  409. X.so appendixB.out
  410. X.NH 1
  411. XAppendix C
  412. SHAREOF
  413. chmod 664 remote/doc/paper/remotefs
  414. #
  415. # remote/doc/remotename.2
  416. #
  417. if [ -f remote/doc/remotename.2 ]; then 
  418.     echo -n 'Hit <return> to overwrite remote/doc/remotename.2 or ^C to quit' 
  419.     read ans 
  420.     rm -f remote/doc/remotename.2 
  421. fi 
  422.  
  423. sed -e 's/^.//' << \SHAREOF > remote/doc/remotename.2
  424. X.TH REMOTENAME 2 "27 July 1983"
  425. X.UC 4
  426. X.SH NAME
  427. Xremotename \- provide name information to the kernel
  428. X.SH SYNOPSIS
  429. X.nf
  430. X.ft B
  431. X#include <remote/remotefs.h>
  432. X
  433. Xremotename(action, name, namelen, path)
  434. Xlong action;
  435. Xcaddr_t name;
  436. Xlong namelen;
  437. Xchar *path;
  438. X.fi
  439. X.SH DESCRIPTION
  440. X.I Remotename
  441. Xis an interface for an exchange of information with
  442. Xthe kernel about remote hosts.
  443. XThe value of
  444. X.I action,
  445. Xdefined by NM_* symbolic constants in remote/remotefs.h,
  446. Xdetermines what exchange takes place:
  447. X.PP
  448. XNM_SERVER
  449. X.br
  450. XThe current process is registered as the name server for the kernel.
  451. XWhenever the kernel needs a path name translated into
  452. Xan internet address,
  453. Xthe current process will receive the SIGIO signal.
  454. XArguments besides
  455. X.I action
  456. Xare ignored.
  457. XIf there is already a process registered as the name server,
  458. X.I remotename
  459. Xwill fail.
  460. X.PP
  461. XNM_WHATNAME
  462. X.br
  463. XAfter receiving the SIGIO signal,
  464. Xthe registered name server should
  465. Xsupply this action to
  466. X.I remotename
  467. Xalong with a valid
  468. Xcharacter pointer
  469. Xin
  470. X.I name
  471. Xand its length in
  472. X.I namelen.
  473. XThe kernel will copy into that pointer
  474. Xa null\-terminated string of the form "/single-component".
  475. XIt is the name server's job to translate "single-component"
  476. Xinto a valid internet address.
  477. X.PP
  478. XThe kernel obtains the single component from the second component
  479. Xof a path name used in a system call by some user process.
  480. XThe first component of that path name would have been a generic mount
  481. Xpoint.
  482. X.PP
  483. XNM_NAMEIS
  484. X.br
  485. XAfter obtaining a valid internet address,
  486. Xthe registered name server should
  487. Xsupply this action to 
  488. X.I remotename
  489. Xalong with a valid
  490. X.I name
  491. Xand
  492. X.I namelen
  493. Xcontaining the internet address the way that
  494. X.I connect(2)
  495. Xwould expect it,
  496. Xand a
  497. X.I path
  498. Xcontaining the nameserver's opion of what the null-terminated
  499. Xmount point should
  500. Xhave been.
  501. X.PP
  502. XNM_DEBUG
  503. X.br
  504. XTurns on debug level to the value in
  505. X.I system.
  506. X.SH "RETURN VALUE
  507. X.I Remotename
  508. Xreturns 0 if the action occurred, \-1 if
  509. X.I name
  510. Xor
  511. X.I path
  512. Xis an invalid address (when a valid one was expected),
  513. Xor the user is not the super user.
  514. X.SH ERRORS
  515. X.TP 15
  516. X[EPERM]
  517. XThe caller is not the super-user
  518. Xor the calling process is not the registered nameserver.
  519. X.TP 15
  520. X[EINVAL]
  521. X.I Name
  522. Xor
  523. X.I path
  524. Xare not valid addresses (if expected),
  525. X.I namelen
  526. Xis too long or
  527. Xthe
  528. X.I action
  529. Xwas not recognized.
  530. X.TP 15
  531. X[ENOREMOTEFS]
  532. XOn
  533. X.I NM_WHATNAME
  534. Xthere was no pathname for which the kernel needed a internet address.
  535. X.TP 15
  536. X[EBUSY]
  537. XThe calling process is trying to register as the nameserver,
  538. Xbut one already exists.
  539. X.SH "SEE ALSO"
  540. Xremoteon(2), remoteoff(2), rmtmnt(8), rfs_server(8)
  541. X.SH BUGS
  542. X.I NM_DEBUG
  543. Xwill not be recognized unless the kernel is has the debug software
  544. Xcompiled in.
  545. SHAREOF
  546. chmod 664 remote/doc/remotename.2
  547. #
  548. # remote/doc/remoteon.2
  549. #
  550. if [ -f remote/doc/remoteon.2 ]; then 
  551.     echo -n 'Hit <return> to overwrite remote/doc/remoteon.2 or ^C to quit' 
  552.     read ans 
  553.     rm -f remote/doc/remoteon.2 
  554. fi 
  555.  
  556. sed -e 's/^.//' << \SHAREOF > remote/doc/remoteon.2
  557. X.TH REMOTEON 2 "27 July 1983"
  558. X.UC 4
  559. X.SH NAME
  560. Xremoteon, remoteoff \- turn on and off remote file system
  561. X.SH SYNOPSIS
  562. X.nf
  563. X.ft B
  564. Xremoteon(path, pathlen, name, namelen)
  565. Xchar *path;
  566. Xint pathlen;
  567. Xstruct sockaddr *name;
  568. Xint namelen;
  569. X.PP
  570. X.ft B
  571. Xremoteoff(path)
  572. Xchar *path;
  573. X.fi
  574. X.SH DESCRIPTION
  575. X.I Remoteon
  576. Xannounces to the system that the file system
  577. Xstarting with the root, aka "/", on the internet host
  578. X.I name
  579. Xhas been mounted on
  580. Xthe plain file
  581. X.I path;
  582. Xfrom then on, references to any files below
  583. X.I path
  584. Xwill refer to
  585. Xfiles below the root file system on the remote host,
  586. X.I name.
  587. X.I Path
  588. Xis a pointer to a null-terminated string
  589. Xcontaining the appropriate path name,
  590. Xbut for storage purposes in the kernel,
  591. X.I pathlen
  592. Xmust also be provided.
  593. X.I name
  594. Xcan only be a valid internet address (this may be extended later),
  595. Xand
  596. X.I namelen
  597. Xshould be the correct length,
  598. Xnormally
  599. X.I sizeof(struct sockaddr_in).
  600. X.PP
  601. X.I Path
  602. Xmust exist already and be
  603. Xa plain file.
  604. XIts old contents
  605. Xare still accessible while the remote file system
  606. Xis mounted,
  607. Xbut the file cannot be removed.
  608. X.PP
  609. XA special case for
  610. X.I remoteon
  611. Xand
  612. X.I remoteoff
  613. Xis when
  614. X.I path
  615. Xis a null pointer.
  616. XThis tells the kernel to disallow
  617. X.I (remoteoff)
  618. Xor allow
  619. X.I (remoteon)
  620. Xremote access for the current
  621. Xprocess,
  622. Xand is intended primarily for use with a remote file server
  623. Xto prevent remote file system loops.
  624. XBy default,
  625. Xall processes are allowed remote access.
  626. XNote that while only the super-user may turn on or off the remote
  627. Xfile system,
  628. Xany user may turn on and off remote access for himself.
  629. X.PP
  630. X.I Remoteoff
  631. Xannounces to the system that the
  632. X.I path
  633. Xfile is no longer to be a remote mount point.
  634. XCurrently,
  635. Xeven if
  636. X.I remoteoff
  637. Xfails,
  638. Xthe remote file system is marked for closing and
  639. Xno more usage is allowed.
  640. XSystem calls that must be run on the remote system after
  641. Xthis point will fail (return \-1).
  642. X.SH "RETURN VALUE
  643. X.I Remoteon
  644. Xreturns 0 if the action occurred, \-1 if
  645. X.I path
  646. Xis inaccessible,
  647. Xalready a remote mount point, not an appropriate file, if
  648. X.I path
  649. Xdoes not exist,
  650. Xor if there are already too many remote file systems mounted.
  651. X.PP
  652. X.I Remoteoff
  653. Xreturns 0 if the action occurred; \-1 if
  654. Xif the file is inaccessible or
  655. Xdoes not point to a remote file system,
  656. Xor if there are active processes using the remote 
  657. Xfile system.
  658. X.SH ERRORS
  659. X.I Remoteon
  660. Xwill fail when one of the following occurs:
  661. X.TP 15
  662. X[EPERM]
  663. XThe caller is not the super-user.
  664. X.TP 15
  665. X[ENOENT]
  666. X.I Special
  667. Xdoes not exist.
  668. X.TP 15
  669. X[EISDIR]
  670. X.I Path
  671. Xis not a plain file.
  672. X.TP 15
  673. X[EINVAL]
  674. X.I Namelen
  675. Xis too long.
  676. X.TP 15
  677. X[ENOBUFS]
  678. Xthe system is out of mbuf structures.
  679. X.TP 15
  680. X[EFAULT]
  681. X.I Name
  682. Xpoints to a bad address.
  683. X.TP 15
  684. X[ETOOMANYREMOTE]
  685. XThe action would overflow internal tables.
  686. X.TP 15
  687. X[EBUSY]
  688. X.I Path
  689. Xis already a remote mount point.
  690. X.PP
  691. X.I Remoteoff
  692. Xmay fail with one of the following errors:
  693. X.TP 15
  694. X[EPERM]
  695. XThe caller is not the super-user.
  696. X.TP 15
  697. X[ENOENT]
  698. X.I Path
  699. Xdoes not exist.
  700. X.TP 15
  701. X[EBUSY]
  702. XA process is holding a reference to the remote file system.
  703. X.SH "SEE ALSO"
  704. Xrmtmnt(8), rfs_server(8)
  705. SHAREOF
  706. chmod 664 remote/doc/remoteon.2
  707. #
  708. # remote/doc/rfs_server.8
  709. #
  710. if [ -f remote/doc/rfs_server.8 ]; then 
  711.     echo -n 'Hit <return> to overwrite remote/doc/rfs_server.8 or ^C to quit' 
  712.     read ans 
  713.     rm -f remote/doc/rfs_server.8 
  714. fi 
  715.  
  716. sed -e 's/^.//' << \SHAREOF > remote/doc/rfs_server.8
  717. X.TH RFS_SERVER 8  "18 October 1985"
  718. X.UC 4
  719. X.SH NAME
  720. Xrfs_server \- remote file system server and kernel name server
  721. X.SH SYNOPSIS
  722. X.B /etc/rfs_server
  723. X[ -s internet-service ]
  724. X[ -v debug-level ]
  725. X.SH DESCRIPTION
  726. XThis is a server for the remote file system and
  727. Xis intended to be started up in /etc/rc.
  728. X.PP
  729. X.PP
  730. XThe optional flag
  731. X.I \-s
  732. Xand its argument,
  733. X.I internet-service,
  734. Xtells the server to accept calls on the named service
  735. Xport described in /etc/services.
  736. XWithout this argument, 
  737. X.I rfs_server
  738. Xuses the service
  739. X.I remotefs.
  740. X.PP
  741. XThe optional flag
  742. X.I \-v
  743. Xand its argument,
  744. X.I debug-level,
  745. Xstarts up the server with the given initial debug level.
  746. XThe argument should be a hexadecimal number containing one bit
  747. Xfor each class of debug output desired.
  748. X.PP
  749. XThe server maintains three identities,
  750. Xand each can be determined by the current command line using the
  751. X.I ps(1)
  752. Xcommand.
  753. X.PP
  754. XThe first identity is the
  755. X.I sentry
  756. Xof which there can only be one at any time.
  757. XThe command line for this remains unaltered from the way it was started.
  758. XThe function of the
  759. X.I sentry
  760. Xserver is to build a database of all hosts in /etc/hosts,
  761. Xall users and groups in /etc/passwd and /etc/group,
  762. Xand of all users' .rhost files.
  763. XAfter this database has been built,
  764. Xit waits 
  765. Xfor connections from remote hosts.
  766. X.PP
  767. XThe second identity is a
  768. X.I "gateway server"
  769. Xand changes its command line
  770. Xto tell which host it is a
  771. X.I "gateway server"
  772. Xfor.
  773. XThis identity is the child of the
  774. X.I sentry
  775. Xafter the latter receives a connection from a remote host;
  776. Xthere can only be one
  777. X.I "gateway server"
  778. Xfor each remote host.
  779. XThe responsibilities of the
  780. X.I "gateway server"
  781. Xare to service context-free system calls for the remote host,
  782. Xcreate other servers to handle context-sensitive system calls,
  783. Xmaintain complete information about all remote processes being served,
  784. Xand ensure at all times
  785. Xthat only one server has control of the socket file
  786. Xdescriptor to the remote machine being served.
  787. X.PP
  788. XThe third identity is that of a plain
  789. X.I server,
  790. Xand changes its command line to be similar to that
  791. Xof the
  792. X.I "gateway server"
  793. Xexcept that the word
  794. X.I gateway
  795. Xis missing and it identifies its parent process.
  796. XIts responsibilities
  797. Xare to service context-free system calls for the remote host and
  798. Xcreate other servers for remote processes that must inherit
  799. Xcertain context information (e.g. remote current working directories,
  800. Xand open file descriptors).
  801. X.SH "DEBUG LEVELS"
  802. XIt should be noted that the debug option is only useful with
  803. Xa copy of the source code in hand and a server that has been
  804. Xcompiled with the debug software turned on.
  805. XThe current selection of the bits are:
  806. X.PP
  807. X.ta 1i 2.5i 4i
  808. X    0x00000001    process switching
  809. X.br
  810. X    0x00000002    system calls
  811. X.br
  812. X    0x00000004    setuid/setgid, umask
  813. X.br
  814. X    0x00000008    file descriptor allocation
  815. X.br
  816. X    0x00000010    connections
  817. X.br
  818. X    0x00000020    server switching
  819. X.br
  820. X    0x00000040    nameserver
  821. X.br
  822. X    0x00000080    directory nuxi
  823. X.br
  824. X    0x00000100    message in and out
  825. X.br
  826. X    0x00000200    don't fork child for gateway (good for adb)
  827. X.br
  828. X    0x00000400    local/remote file decisions
  829. X.br
  830. X    0x00000800    don't remove log file on exit (except exit on error)
  831. X.br
  832. X    0x00001000    exec information
  833. X.br
  834. X    0x00002000    auto debug for 0x20 (server switching)
  835. X.br
  836. X    0x00004000    parsing messages to gateway
  837. X.PP
  838. XAnother method of setting the debug level in any identity of the
  839. X.I rfs_server
  840. Xis to place the desired hexidecimal level in the file /usr/tmp/rfs_debug
  841. Xand to send the appropiate server signal number 5, aka
  842. X.I SIGTRAP.
  843. XThis method can be used with
  844. X.I sentry
  845. Xservers, any
  846. X.I gateway
  847. Xservers, and any other servers that are marked active.
  848. XIt should not be used on sleeping servers.
  849. X.PP
  850. XIf any server receives SIGILL, SIGSEGV or SIGBUS,
  851. Xit will arrange for its core file to be dumped in /usr/tmp.
  852. X.SH "RESTARTING THE SERVER"
  853. XThe best way to restart the
  854. X.I sentry
  855. Xserver (e.g. installing a new
  856. X.I rfs_server),
  857. Xis to simply run the new server.
  858. XThe new server knows how to examine the previous log file
  859. Xto discover the pid number of the previous server, and kill it.
  860. X.PP
  861. XIf you know that that will fail, then the second best way
  862. Xis to send it the signal
  863. X.I SIGTERM
  864. X.PP
  865. XSending
  866. X.I SIGTERM
  867. Xsignal to a
  868. X.I "gateway server"
  869. Xwill cause it and all of its children to gracefully go away.
  870. X.SH "SEE ALSO"
  871. Xremotename(2),
  872. Xrmtmnt(8).
  873. X.SH BUGS
  874. XProbably.
  875. SHAREOF
  876. chmod 664 remote/doc/rfs_server.8
  877. #
  878. # remote/doc/rmtmnt.8
  879. #
  880. if [ -f remote/doc/rmtmnt.8 ]; then 
  881.     echo -n 'Hit <return> to overwrite remote/doc/rmtmnt.8 or ^C to quit' 
  882.     read ans 
  883.     rm -f remote/doc/rmtmnt.8 
  884. fi 
  885.  
  886. sed -e 's/^.//' << \SHAREOF > remote/doc/rmtmnt.8
  887. X.TH RMTMNT 8  "18 October 1985"
  888. X.UC 4
  889. X.SH NAME
  890. Xrmtmnt \- mount and dismount remote file systems
  891. X.SH SYNOPSIS
  892. X.B /etc/rmtmnt
  893. X[ -s internet-service ] host path
  894. X.PP
  895. X.B /etc/rmtmnt
  896. X-g path
  897. X.PP
  898. X.B /etc/rmtmnt
  899. X-u path
  900. X.PP
  901. X.B /etc/rmtmnt
  902. X.SH DESCRIPTION
  903. XIn the first usage,
  904. X.I rmtmnt
  905. Xannounces to the system that the file system
  906. Xstarting with the root, aka "/", on the internet host named
  907. X.I host
  908. Xhas been mounted on
  909. Xthe plain file
  910. X.I path;
  911. Xfrom now on, references to any files below
  912. X.I path
  913. Xwill refer to
  914. Xfiles below the root file system on the remote host,
  915. X.I host.
  916. XThe file
  917. X.I path
  918. Xmust exist already; it must be a file.
  919. XIt becomes the name of the newly mounted root.
  920. X.PP
  921. XThe optional flag
  922. X.I \-s
  923. Xand argument
  924. X.I internet-service
  925. Xindicates that the kernel should use
  926. Xthe named internet service (defined in /etc/services)
  927. Xwhen connecting to that remote host.
  928. X.PP
  929. XThe second usage with the
  930. X.I -g
  931. Xflag indicates that the mount point is to be "generic".
  932. XBy convention,
  933. Xthe name of this path ought to be
  934. X.I /net,
  935. Xbut may be any valid path name.
  936. XNo specific host is associated with the
  937. Xpath name.
  938. XInstead,
  939. Xthe component following
  940. X.I /net
  941. Xis handed to the nameserver, usually
  942. X.I rfs_server(8),
  943. Xfor translation to an internet address.
  944. XWhen the kernel receives the new address,
  945. Xan implicit mount is made by the kernel.
  946. X.PP
  947. XThe third usage with the
  948. X.I -u
  949. Xflag informs the kernel that the internet host
  950. Xmounted on
  951. X.I path
  952. Xshould be unmounted.
  953. X.PP
  954. XThe last usage,
  955. Xhaving no arguments or flags
  956. Xwill print out a complete status of all current mount points.
  957. X.SH "SEE ALSO"
  958. Xremoteon(2),
  959. Xrfs_server(8).
  960. X.SH BUGS
  961. XImlicit mount points cannot be unmounted.
  962. X.PP
  963. XIf a command which has a current working directory
  964. Xon a remote machine through an
  965. X.I implicit
  966. Xmount point
  967. Xattempts to find the current working directory,
  968. Xit will produce a pathname missing the second component,
  969. Xand, hence, will fail.
  970. XExplicit mount points work fine.
  971. SHAREOF
  972. chmod 664 remote/doc/rmtmnt.8
  973. #
  974. # remote/file.c
  975. #
  976. if [ -f remote/file.c ]; then 
  977.     echo -n 'Hit <return> to overwrite remote/file.c or ^C to quit' 
  978.     read ans 
  979.     rm -f remote/file.c 
  980. fi 
  981.  
  982. sed -e 's/^.//' << \SHAREOF > remote/file.c
  983. X/*
  984. X * Copyright 1985, Todd Brunhoff.
  985. X *
  986. X * This software was written at Tektronix Computer Research Laboratories
  987. X * as partial fulfillment of a Master's degree at the University of Denver.
  988. X * This is not Tektronix proprietary software and should not be
  989. X * confused with any software product sold by Tektronix.  No warranty is
  990. X * expressed or implied on the reliability of this software; the author,
  991. X * the University of Denver, and Tektronix, inc. accept no liability for
  992. X * any damage done directly or indirectly by this software.  This software
  993. X * may be copied, modified or used in any way, without fee, provided this
  994. X * notice remains an unaltered part of the software.
  995. X *
  996. X * $Log:    file.c,v $
  997. X * Revision 2.0  85/12/07  18:21:11  toddb
  998. X * First public release.
  999. X * 
  1000. X */
  1001. Xstatic char    *rcsid = "$Header: file.c,v 2.0 85/12/07 18:21:11 toddb Rel $";
  1002. X#include    "server.h"
  1003. X#include    <errno.h>
  1004. X
  1005. Xextern int    fds_in_use;
  1006. Xextern int    errno;
  1007. X
  1008. X/*
  1009. X * here we allocate a file descriptor to a process and make note of our
  1010. X * total number of open file descriptors.  'fd' is the file descriptor
  1011. X * that the server itself got back, and remotefd is the file descriptor
  1012. X * that the remote process is expecting.
  1013. X */
  1014. Xallocate_fd(fd, proc, remotefd)
  1015. X    register int    fd,
  1016. X            remotefd;
  1017. X    register process    *proc;
  1018. X{
  1019. X    if (fd != -1)
  1020. X    {
  1021. X        proc->p_fds[ remotefd ] = fd;
  1022. X        debug3("allocate local fd %d, remote fd %d\n",
  1023. X            fd, remotefd);
  1024. X        fds_in_use++;
  1025. X        checkfiletype(fd);
  1026. X    }
  1027. X    else
  1028. X        remotefd = -1;
  1029. X    return(remotefd);
  1030. X}
  1031. X
  1032. Xdeallocate_fd(proc, remotefd)
  1033. X    register process    *proc;
  1034. X    register long    remotefd;
  1035. X{
  1036. X    register char    fd;
  1037. X    register long    retval;
  1038. X
  1039. X    if ((unsigned)remotefd >= NOFILE)
  1040. X    {
  1041. X        errno = EBADF;
  1042. X        return(-1);
  1043. X    }
  1044. X    fd = proc->p_fds[ remotefd ];
  1045. X    proc->p_fds[ remotefd ] = -1;
  1046. X    retval = close(fd);
  1047. X    fds_in_use--;
  1048. X    return(retval);
  1049. X}
  1050. SHAREOF
  1051. chmod 444 remote/file.c
  1052. #
  1053. # remote/fileserver.c
  1054. #
  1055. if [ -f remote/fileserver.c ]; then 
  1056.     echo -n 'Hit <return> to overwrite remote/fileserver.c or ^C to quit' 
  1057.     read ans 
  1058.     rm -f remote/fileserver.c 
  1059. fi 
  1060.  
  1061. sed -e 's/^.//' << \SHAREOF > remote/fileserver.c
  1062. X/*
  1063. X * Copyright 1985, Todd Brunhoff.
  1064. X *
  1065. X * This software was written at Tektronix Computer Research Laboratories
  1066. X * as partial fulfillment of a Master's degree at the University of Denver.
  1067. X * This is not Tektronix proprietary software and should not be
  1068. X * confused with any software product sold by Tektronix.  No warranty is
  1069. X * expressed or implied on the reliability of this software; the author,
  1070. X * the University of Denver, and Tektronix, inc. accept no liability for
  1071. X * any damage done directly or indirectly by this software.  This software
  1072. X * may be copied, modified or used in any way, without fee, provided this
  1073. X * notice remains an unaltered part of the software.
  1074. X *
  1075. X * $Log:    fileserver.c,v $
  1076. X * Revision 2.0  85/12/07  18:21:14  toddb
  1077. X * First public release.
  1078. X * 
  1079. X */
  1080. Xstatic char    *rcsid = "$Header: fileserver.c,v 2.0 85/12/07 18:21:14 toddb Rel $";
  1081. X#include <errno.h>
  1082. X#include <stdio.h>
  1083. X#include <ctype.h>
  1084. X#include <signal.h>
  1085. X#include "server.h"
  1086. X#include <sys/file.h>
  1087. X
  1088. Xextern long    errno;
  1089. Xextern long    from_servers;
  1090. Xextern long    to_gateway;
  1091. Xextern long    so_listen;
  1092. Xextern long    blocking_servers;
  1093. Xextern short    gateway_server;
  1094. Xextern short    current_ppid;
  1095. Xextern short    current_pid;
  1096. Xextern short    current_uid;
  1097. Xextern short    current_server;
  1098. Xextern char    mntpt[ MAXPATHLEN ];
  1099. Xextern char    *program;
  1100. Xextern char    *last_argaddr;
  1101. Xextern char    *logfile;
  1102. Xextern char    *service;
  1103. Xextern char    *syscallnames[];
  1104. Xextern boolean    i_am_gateway;
  1105. Xextern boolean    i_am_asleep;
  1106. Xextern boolean    i_have_control;
  1107. Xextern boolean    route_to_gateway;
  1108. Xextern boolean    watch_for_lock;
  1109. Xextern boolean    gateway_needs_control;
  1110. Xextern syscallmap    smap[];
  1111. Xextern process    *wildcard;
  1112. Xextern hosts    *host;
  1113. X
  1114. Xmain(argc, argv)
  1115. X    int argc;
  1116. X    char **argv;
  1117. X{
  1118. X    register hosts    *h;
  1119. X
  1120. X    setopts(argc, argv);
  1121. X    if ((remote_debug & 0x200) == 0 && fork())
  1122. X        exit(0);
  1123. X    current_pid = getpid();
  1124. X    setlogfile();
  1125. X    if ((so_listen = tcppassive()) < 0)
  1126. X        log_fatal("cannot open socket\n");
  1127. X    init();
  1128. X    for (;;)
  1129. X    {
  1130. X        if ((h = tcpaccept(so_listen)) == NULL)
  1131. X            break;
  1132. X        debug4("call on fd %d, portno %d, from host \"%s\"\n",
  1133. X            h->h_cmdfd, h->h_portnum, h->h_names[0]);
  1134. X        dumphost(h);
  1135. X        if (server(h))
  1136. X            exit(0);
  1137. X    }
  1138. X}
  1139. X
  1140. X/*
  1141. X * This is the top lexical level for the server.  We decide here
  1142. X * when to call for a next request and whether we are running the
  1143. X * new format remote fs or not.
  1144. X *
  1145. X * We also decide whether this is a connection from the mount program
  1146. X * on a remote host or not.  If it is, then we just want to assemble the
  1147. X * info that it gives us and not become a child server.
  1148. X */
  1149. X
  1150. Xserver(h)
  1151. X    register hosts    *h;
  1152. X{
  1153. X    long        pipefd[ 2 ];
  1154. X    struct message    msgbuf,
  1155. X            *getmsg();
  1156. X    register struct message    *msg = &msgbuf;
  1157. X    register process    *proc;
  1158. X    register long    cmd, len;
  1159. X
  1160. X    /*
  1161. X     * Get the first message from this connection.
  1162. X     */
  1163. X    alarm(5);
  1164. X    if (! (msg = getmsg(h->h_cmdfd)))
  1165. X    {
  1166. X        log("connection initiation lost to \"%s\"\n", h->h_names[0]);
  1167. X        close(h->h_cmdfd);
  1168. X        h->h_cmdfd = -1;
  1169. X        alarm(0);
  1170. X        return(FALSE);
  1171. X    }
  1172. X    alarm(0);
  1173. X
  1174. X    /*
  1175. X     * may be a special command
  1176. X     */
  1177. X    len = msg->m_hdlen;
  1178. X    if (msg->m_syscall == RSYS_nosys)
  1179. X    {
  1180. X        cmd = msg->m_args[0];
  1181. X        debug5("new client; cmd=%d\n", cmd);
  1182. X        switch(cmd) {
  1183. X        case CMD_SERVICE:
  1184. X            break;
  1185. X        case CMD_MOUNT:
  1186. X            gobble_last_msg(h->h_cmdfd, msg);
  1187. X            getbyteorder(h);
  1188. X            getrusers(h);
  1189. X            return(FALSE);
  1190. X        case CMD_NEEDMOUNT:
  1191. X            sendmount(h);
  1192. X            dont_gobble_msg(msg);
  1193. X            return(FALSE);
  1194. X        default:
  1195. X            log_fatal("unknown server directive = %d\n", cmd);
  1196. X        }
  1197. X    }
  1198. X    else
  1199. X    {
  1200. X        debug5("new client, not mounted by rmtmnt\n");
  1201. X        dont_gobble_msg(msg);
  1202. X        if (!h->h_mounted)
  1203. X            getmount(h);
  1204. X    }
  1205. X
  1206. X    /*
  1207. X     * If we reach this point, then we are to be the gateway server.
  1208. X     * There may ba a server still running.  Kill it.
  1209. X     */
  1210. X    if (h->h_serverpid)
  1211. X        sendsig(h->h_serverpid, SIGTERM);
  1212. X
  1213. X    if ((remote_debug & 0x200) == 0 && vfork())
  1214. X    {
  1215. X        wait(0);
  1216. X        /*
  1217. X         * we are the parent... just return.
  1218. X         */
  1219. X        close(h->h_cmdfd);
  1220. X        h->h_cmdfd = -1;
  1221. X        return(FALSE);
  1222. X    }
  1223. X    else if ((remote_debug & 0x200) == 0 && (h->h_serverpid = fork()))
  1224. X        exit(0);
  1225. X    host = h;
  1226. X    wildcard->p_handler = gateway_server = current_pid = getpid();
  1227. X    set_label("active");
  1228. X    if ((remote_debug & 0x200) == 0)
  1229. X    {
  1230. X        setlogfile();
  1231. X        close(so_listen);
  1232. X    }
  1233. X    if (pipe(pipefd) < 0)
  1234. X        log_fatal("Can't open pipe\n");
  1235. X    from_servers = pipefd[ 0 ];
  1236. X    to_gateway = pipefd[ 1 ];
  1237. X
  1238. X    /*
  1239. X     * Ok, now be a server!
  1240. X     */
  1241. X    for(;;)
  1242. X    {
  1243. X        if (i_am_gateway && ! i_have_control)
  1244. X        {
  1245. X            gateway_listen();
  1246. X            continue;
  1247. X        }
  1248. X        /*
  1249. X         * The gateway may be waiting for control.  Let's see.
  1250. X         */
  1251. X        if (watch_for_lock)
  1252. X            if (gateway_needs_control
  1253. X            || flock(2, LOCK_NB | LOCK_SH) < 0)
  1254. X            {
  1255. X                debug5("gateway wants control\n");
  1256. X                reroute(gateway_server, msg);
  1257. X                continue;
  1258. X            }
  1259. X            else
  1260. X                flock(2, LOCK_UN);
  1261. X            
  1262. X        if ((msg = getmsg(host->h_cmdfd)) == NULL)
  1263. X            break;
  1264. X        proc = change_to_proc(msg);
  1265. X        if (proc == NULL)
  1266. X            continue;
  1267. X
  1268. X        errno = 0;
  1269. X        (*smap[ msg->m_syscall ].s_server)(msg, proc);
  1270. X    }
  1271. X    debug5("done.\n");
  1272. X    if (i_am_gateway)
  1273. X        for (proc = host->h_proclist; proc; proc=proc->p_next)
  1274. X        {
  1275. X            /*
  1276. X             * just hand it to the other server... he'll get eof
  1277. X             */
  1278. X            if (proc->p_handler != current_pid)
  1279. X                sendsig(proc->p_handler, SIGIO);
  1280. X        }
  1281. X    else
  1282. X        say_something(S_EOF, 0);
  1283. X    if ((remote_debug & 0x800) == 0)
  1284. X        unlink(logfile);
  1285. X    return(TRUE);
  1286. X}
  1287. X
  1288. Xsetopts(argc, argv)
  1289. X    register int    argc;
  1290. X    register char    **argv;
  1291. X{
  1292. X    register int    error = FALSE;
  1293. X    register char    **p;
  1294. X    extern char    **environ;
  1295. X
  1296. X    program = argv[0];
  1297. X    last_argaddr = argv[argc-1];
  1298. X    for (argv++, argc--; argc; argv++, argc--)
  1299. X    {
  1300. X        if (**argv != '-')
  1301. X        {
  1302. X            log("arg \"%s\" is unknown\n",
  1303. X                *argv);
  1304. X            error = TRUE;
  1305. X        }
  1306. X        switch(argv[0][1]) {
  1307. X        case 'v':
  1308. X            if (argv[0][2])
  1309. X                remote_debug = atox(argv[0] + 2);
  1310. X            else if (isdigit(argv[1][0]))
  1311. X                argc--, remote_debug = atox(*(++argv));
  1312. X            break;
  1313. X        case 's':
  1314. X            if (argv[0][2])
  1315. X                service = argv[0] + 2;
  1316. X            else
  1317. X                argc--, service = *(++argv);
  1318. X            break;
  1319. X        default:
  1320. X            log("unknown flag = %s\n", *argv);
  1321. X            error = TRUE;
  1322. X        }
  1323. X    }
  1324. X    /*
  1325. X     * Make sure that last_argaddr points to the last possible address
  1326. X     */
  1327. X    p = environ;
  1328. X    while (*p)
  1329. X        p++;
  1330. X    if (p != environ)
  1331. X        p--;
  1332. X    if (*p)
  1333. X        last_argaddr = *p;
  1334. X    last_argaddr = (char *)ctob(btoc(last_argaddr)) - 1;
  1335. X    debug5("program addr=%x, last_argaddr=%x\n", program, last_argaddr);
  1336. X
  1337. X    if (error)
  1338. X        exit(1);
  1339. X}
  1340. X
  1341. X/*
  1342. X * ascii to hex
  1343. X */
  1344. Xatox(buf)
  1345. X    char    *buf;
  1346. X{
  1347. X    register char   *p;
  1348. X    register unsigned       num, nibble;
  1349. X
  1350. X    /*
  1351. X     * now, take it out checking to make sure that the number is
  1352. X     * valid.
  1353. X     */
  1354. X    if (! buf)
  1355. X        return(0);
  1356. X    for(num=0, p = buf; *p; p++)
  1357. X    {
  1358. X        nibble = *p;
  1359. X        if (nibble >= 'A' && nibble <= 'F')
  1360. X            nibble -= 'A' - 10;
  1361. X        else if (nibble >= 'a' && nibble <= 'f')
  1362. X            nibble -= 'a' - 10;
  1363. X        else if (nibble >= '0' && nibble <= '9')
  1364. X            nibble -= '0';
  1365. X        else
  1366. X            return(0);
  1367. X        num = (num << 4) | nibble;
  1368. X    }
  1369. X    return(num);
  1370. X}
  1371. X
  1372. X/*
  1373. X * fork() and give the process on the top of the list to the child.
  1374. X */
  1375. Xbecome_server(msg)
  1376. X    register struct message    *msg;
  1377. X{
  1378. X    register long    pid, i;
  1379. X    register char    *fds;
  1380. X    register process    *proc = host->h_proclist;
  1381. X
  1382. X    /*
  1383. X     * Have to change to uid 0 or we may be refused a fork
  1384. X     */
  1385. X    change_to_uid(0);
  1386. X    i_am_asleep = TRUE;
  1387. X    if (pid = fork()) /* the parent loses control */
  1388. X    {
  1389. X        if (pid < 0)
  1390. X            log_fatal("cannot fork\n");
  1391. X        debug5("new server: pid=%d,mine=%d give him (%d)\n",
  1392. X            pid, current_pid, host->h_proclist->p_pid);
  1393. X        proc->p_handler = pid;
  1394. X        dont_gobble_msg(msg);
  1395. X        slumber(TRUE);
  1396. X        if (i_am_gateway)
  1397. X            current_server = pid;
  1398. X        return(FALSE);
  1399. X    }
  1400. X
  1401. X    /*
  1402. X     * If we got this far, then we are no longer the gateway.  So set
  1403. X     * our pid, etc.  Also, try to dup stderr so that flock will work.
  1404. X     * If we can't do it, we are in big trouble.
  1405. X     */
  1406. X    current_ppid = current_pid;
  1407. X    current_pid = getpid();
  1408. X    if (i_am_gateway)
  1409. X    {
  1410. X        close(from_servers);
  1411. X        if (blocking_servers)
  1412. X        {
  1413. X            watch_for_lock = TRUE;
  1414. X            route_to_gateway = TRUE;
  1415. X        }
  1416. X    }
  1417. X    else
  1418. X        say_something(S_NEWSERVER, proc->p_pid);
  1419. X    i_am_gateway = FALSE;
  1420. X    set_label("active");
  1421. X    wildcard->p_handler = current_pid;
  1422. X    proc->p_handler = current_pid;
  1423. X    if ((i = dup(2)) < 0)
  1424. X        log_fatal("cannot dup(2)\n");
  1425. X    dup2(i, 2);
  1426. X    close(i);
  1427. X    debug5("new server: pid=%d, ppid=%d\n", current_pid, getppid());
  1428. X
  1429. X    return(TRUE);
  1430. X}
  1431. X
  1432. X#ifdef RFSDEBUG
  1433. Xdumphost(h)
  1434. X    register hosts    *h;
  1435. X{
  1436. X    register rusers    *ruser;
  1437. X
  1438. X    if ((remote_debug & 0x10) == 0)
  1439. X        return;
  1440. X    log("host %s, local user = %s, ruser@%x\n",
  1441. X        *h->h_names,
  1442. X        h->h_default_user ? h->h_default_user->u_name : "default",
  1443. X        ruser = h->h_default_ruser);
  1444. X    log("\tr %s(%d)-->%s(%d)\n",
  1445. X        ruser->r_name, ruser->r_uid,
  1446. X        ruser->r_user->u_name, ruser->r_user->u_local_uid);
  1447. X    for(ruser = h->h_rusers; ruser; ruser=ruser->r_next)
  1448. X        log("\tr %s(%d)-->%s(%d)\n",
  1449. X            ruser->r_name, ruser->r_uid,
  1450. X            ruser->r_user->u_name, ruser->r_user->u_local_uid);
  1451. X}
  1452. X#endif RFSDEBUG
  1453. X
  1454. Xset_label(string)
  1455. X    register char    *string;
  1456. X{
  1457. X    char        process_label[ 100 ];
  1458. X    static char    *pend;
  1459. X    static short    pid;
  1460. X    register char    *pfrom, *pto;
  1461. X    register long    i;
  1462. X
  1463. X    if (pid != current_pid)
  1464. X    {
  1465. X        if (i_am_gateway)
  1466. X            sprintf(process_label, "%s gateway server: ",
  1467. X                host->h_names[0]);
  1468. X        else
  1469. X            sprintf(process_label, "%s server via %d: ",
  1470. X                host->h_names[0], pid);
  1471. X        pid = current_pid;
  1472. X        pend = program + strlen(process_label);
  1473. X        strncpy(program, process_label, last_argaddr - program);
  1474. X        pto = pend;
  1475. X        while (pto < last_argaddr)
  1476. X            *pto++ = ' ';
  1477. X    }
  1478. X    pto = pend;
  1479. X    pfrom = string;
  1480. X    while (pto < last_argaddr && *pfrom)
  1481. X        *pto++ = *pfrom++;
  1482. X    for (i=0; pto < last_argaddr && i<10; i++)
  1483. X        *pto++ = ' ';
  1484. X    if (pto <= last_argaddr)
  1485. X        *pto = '\0';
  1486. X}
  1487. SHAREOF
  1488. chmod 444 remote/fileserver.c
  1489. #
  1490. # remote/find.c
  1491. #
  1492. if [ -f remote/find.c ]; then 
  1493.     echo -n 'Hit <return> to overwrite remote/find.c or ^C to quit' 
  1494.     read ans 
  1495.     rm -f remote/find.c 
  1496. fi 
  1497.  
  1498. sed -e 's/^.//' << \SHAREOF > remote/find.c
  1499. X/*
  1500. X * Copyright 1985, Todd Brunhoff.
  1501. X *
  1502. X * This software was written at Tektronix Computer Research Laboratories
  1503. X * as partial fulfillment of a Master's degree at the University of Denver.
  1504. X * This is not Tektronix proprietary software and should not be
  1505. X * confused with any software product sold by Tektronix.  No warranty is
  1506. X * expressed or implied on the reliability of this software; the author,
  1507. X * the University of Denver, and Tektronix, inc. accept no liability for
  1508. X * any damage done directly or indirectly by this software.  This software
  1509. X * may be copied, modified or used in any way, without fee, provided this
  1510. X * notice remains an unaltered part of the software.
  1511. X *
  1512. X * $Log:    find.c,v $
  1513. X * Revision 2.0  85/12/07  18:21:23  toddb
  1514. X * First public release.
  1515. X * 
  1516. X */
  1517. Xstatic char    *rcsid = "$Header: find.c,v 2.0 85/12/07 18:21:23 toddb Rel $";
  1518. X#include    "server.h"
  1519. X#include    <stdio.h>
  1520. X#include    <signal.h>
  1521. X
  1522. Xextern hosts    *hostlist;
  1523. Xextern hosts    *host;
  1524. Xextern users    *userlist;
  1525. Xextern boolean    i_am_gateway;
  1526. Xextern short    current_pid;
  1527. X
  1528. Xprocess *findprocess(pid, uid)
  1529. X    register short    pid;
  1530. X    register short    uid;
  1531. X{
  1532. X    register process    *p;
  1533. X    register rusers    *ruser;
  1534. X
  1535. X    debug0("findproc: ", dumpprocs(host->h_proclist));
  1536. X    for(p = host->h_proclist; p; p=p->p_next)
  1537. X        if (p->p_pid == pid)
  1538. X        {
  1539. X            debug0("found pid %d\n", pid);
  1540. X            /*
  1541. X             * If the user changes uid, then change with him.
  1542. X             */
  1543. X            if (uid >= 0 && uid != p->p_uid)
  1544. X            {
  1545. X                debug2("pid %d changes uid %d->%d\n",
  1546. X                    pid, p->p_uid, uid);
  1547. X                p->p_uid = uid;
  1548. X                if (ruser = findremuid(&host->h_rusers, uid))
  1549. X                    p->p_ruser = ruser;
  1550. X                else
  1551. X                    p->p_ruser = host->h_default_ruser;
  1552. X                debug2(" locally mapped to %s(%d)\n",
  1553. X                    p->p_ruser->r_user->u_name,
  1554. X                    p->p_ruser->r_user->u_local_uid);
  1555. X            }
  1556. X            toplist(&host->h_proclist, p);
  1557. X            return(p);
  1558. X        }
  1559. X    return(NULL);
  1560. X}
  1561. X
  1562. X/*
  1563. X * find the user structure whose name is 'name'.
  1564. X */
  1565. Xusers *findusername(name)
  1566. X    register char    *name;
  1567. X{
  1568. X    register users    *user;
  1569. X
  1570. X    for(user=userlist; user; user=user->u_next)
  1571. X        if (strcmp(user->u_name, name) == 0)
  1572. X        {
  1573. X            toplist(&userlist, user);
  1574. X            return(user);
  1575. X        }
  1576. X    return(NULL);
  1577. X}
  1578. X
  1579. Xhosts *findhostname(name)
  1580. X    register char    *name;
  1581. X{
  1582. X    register hosts    *h;
  1583. X    register int    i;
  1584. X    register char    **hnames;
  1585. X
  1586. X    for(h=hostlist; h; h=h->h_next)
  1587. X        for (i=0, hnames=h->h_names; hnames[ i ]; i++)
  1588. X            if (strcmp(hnames[ i ], name) == 0)
  1589. X            {
  1590. X                toplist(&hostlist, h);
  1591. X                return(h);
  1592. X            }
  1593. X    return(NULL);
  1594. X}
  1595. X
  1596. Xhosts *findhostaddr(addr)
  1597. X    register struct in_addr    *addr;
  1598. X{
  1599. X    register hosts    *h;
  1600. X
  1601. X    debug4("find %s...\n", inet_ntoa(*addr));
  1602. X    for(h=hostlist; h; h=h->h_next)
  1603. X        if (bcmp(addr, &h->h_addr, sizeof(struct in_addr)) == 0)
  1604. X        {
  1605. X            toplist(&hostlist, h);
  1606. X            debug4("\tis %s (%s)\n",
  1607. X                h->h_names[0], inet_ntoa(h->h_addr));
  1608. X            return(h);
  1609. X        }
  1610. X        else
  1611. X            debug4("\tnot %s (%s)\n",
  1612. X                h->h_names[0], inet_ntoa(h->h_addr));
  1613. X    log("no host entry for %s, continuing anyway.\n", inet_ntoa(*addr));
  1614. X    /*
  1615. X     * Kludge up a hosts structure for this guy
  1616. X     */
  1617. X    h = newhost();
  1618. X    h->h_names = newname(NULL, BOGUSHOST);
  1619. X    bcopy(addr, &h->h_addr, sizeof(struct in_addr));
  1620. X    addlist(&hostlist, h);
  1621. X    return(h);
  1622. X}
  1623. X
  1624. Xrusers *findremuid(list, uid)
  1625. X    register rusers    **list;
  1626. X    register int    uid;
  1627. X{
  1628. X    register rusers    *ruser;
  1629. X
  1630. X    for (ruser = *list; ruser; ruser=ruser->r_next)
  1631. X        if (ruser->r_uid == uid)
  1632. X        {
  1633. X            toplist(list, ruser);
  1634. X            return(ruser);
  1635. X        }
  1636. X    return(NULL);
  1637. X}
  1638. X
  1639. X/*
  1640. X * find the ruser structure whose name is 'name'.
  1641. X */
  1642. Xrusers *findrusername(list, name)
  1643. X    register rusers    **list;
  1644. X    register char    *name;
  1645. X{
  1646. X    register rusers    *ruser;
  1647. X
  1648. X    for(ruser = *list; ruser; ruser=ruser->r_next)
  1649. X        if (strcmp(ruser->r_name, name) == 0)
  1650. X        {
  1651. X            toplist(list, ruser);
  1652. X            return(ruser);
  1653. X        }
  1654. X    return(NULL);
  1655. X}
  1656. X
  1657. X#ifdef RFSDEBUG
  1658. Xdumpprocs(p)
  1659. X    register process    *p;
  1660. X{
  1661. X    register long    i, fd;
  1662. X
  1663. X    while(p)
  1664. X    {
  1665. X        log("proc@%x,pid=%d,uid=%d,next@%x,prev@%x,handler=%d\n",
  1666. X            p, p->p_pid, p->p_uid, p->p_next, p->p_prev,
  1667. X            p->p_handler);
  1668. X        log("\t%s(%d)->%s(%d),fds=",
  1669. X            p->p_ruser->r_name, p->p_ruser->r_uid,
  1670. X            p->p_ruser->r_user->u_name,
  1671. X            p->p_ruser->r_user->u_local_uid);
  1672. X        for (i=0; i<NOFILE; i++)
  1673. X            if ((fd = p->p_fds[ i ]) >= 0)
  1674. X                log("%d->%d ", i, fd);
  1675. X        log("\n");
  1676. X        p=p->p_next;
  1677. X    }
  1678. X}
  1679. X#endif RFSDEBUG
  1680. SHAREOF
  1681. chmod 444 remote/find.c
  1682. #
  1683. # remote/info.c
  1684. #
  1685. if [ -f remote/info.c ]; then 
  1686.     echo -n 'Hit <return> to overwrite remote/info.c or ^C to quit' 
  1687.     read ans 
  1688.     rm -f remote/info.c 
  1689. fi 
  1690.  
  1691. sed -e 's/^.//' << \SHAREOF > remote/info.c
  1692. X/*
  1693. X * Copyright 1985, Todd Brunhoff.
  1694. X *
  1695. X * This software was written at Tektronix Computer Research Laboratories
  1696. X * as partial fulfillment of a Master's degree at the University of Denver.
  1697. X * This is not Tektronix proprietary software and should not be
  1698. X * confused with any software product sold by Tektronix.  No warranty is
  1699. X * expressed or implied on the reliability of this software; the author,
  1700. X * the University of Denver, and Tektronix, inc. accept no liability for
  1701. X * any damage done directly or indirectly by this software.  This software
  1702. X * may be copied, modified or used in any way, without fee, provided this
  1703. X * notice remains an unaltered part of the software.
  1704. X *
  1705. X * $Log:    info.c,v $
  1706. X * Revision 2.0  85/12/07  18:21:28  toddb
  1707. X * First public release.
  1708. X * 
  1709. X */
  1710. Xstatic char    *rcsid = "$Header: info.c,v 2.0 85/12/07 18:21:28 toddb Rel $";
  1711. X#include    "server.h"
  1712. X#include    <stdio.h>
  1713. X#include    <sys/wait.h>
  1714. X#include    <sys/file.h>
  1715. X#include    <sys/stat.h>
  1716. X#include    <netdb.h>
  1717. X#include    <errno.h>
  1718. X
  1719. Xextern users    *default_user;
  1720. Xextern hosts    *host;
  1721. Xextern hosts    *thishost;
  1722. Xextern char    byteorder[];
  1723. Xextern char    *logfile;
  1724. Xextern long    serviceport;
  1725. Xextern long    errno;
  1726. Xextern short    current_pid;
  1727. Xextern process    *wildcard;
  1728. Xextern boolean    in_root_directory;
  1729. Xextern boolean    i_am_asleep;
  1730. X
  1731. Xgetbyteorder(h)
  1732. X    register hosts    *h;
  1733. X{
  1734. X    register char    *p;
  1735. X
  1736. X    /*
  1737. X     * Read the byte order info.
  1738. X     */
  1739. X    alarm(5);
  1740. X    p = (char *)h->h_byteorder;
  1741. X    if (read(h->h_cmdfd, p, 4) != 4)
  1742. X    {
  1743. X        log("can't read mount info from \"%s\"\n", h->h_names[0]);
  1744. X        alarm(0);
  1745. X        bzero(p, 4);
  1746. X        close(h->h_cmdfd);
  1747. X        h->h_cmdfd = -1;
  1748. X        return;
  1749. X    }
  1750. X    alarm(0);
  1751. X    if (bcmp(p, byteorder, 4) == 0)
  1752. X        h->h_byteorderok = TRUE;
  1753. X    else
  1754. X        h->h_byteorderok = FALSE;
  1755. X    debug4("byteorder=%d,%d,%d,%d: %s ours\n",
  1756. X        p[0], p[1], p[2], p[3],
  1757. X        h->h_byteorderok ? "same as" : "different than");
  1758. X}
  1759. X
  1760. Xgetrusers(h)
  1761. X    register hosts    *h;
  1762. X{
  1763. X    char    buf[ BUFSIZ ];
  1764. X    register rusers    *ruser;
  1765. X    register FILE    *input;
  1766. X    register char    *p;
  1767. X    register int    uid;
  1768. X
  1769. X    errno = 0;
  1770. X    /*
  1771. X     * Read in the users from the remote host and squirrel them away.
  1772. X     * Actually it is the actual password file from the remote
  1773. X     * host, and we ignore most of the info, and save the user name and
  1774. X     * uid.
  1775. X     */
  1776. X    if ((input = fdopen(h->h_cmdfd, "r")) == NULL)
  1777. X        log_fatal("getrusers: cannot fdopen\n");
  1778. X
  1779. X    alarm(30);
  1780. X    while (fgets(buf, BUFSIZ, input))
  1781. X    {
  1782. X        /*
  1783. X         * First, the user name.
  1784. X         */
  1785. X        for(p=buf; *p && *p != ':'; p++) ;
  1786. X        *p = '\0';
  1787. X
  1788. X        /*
  1789. X         * now the user id number
  1790. X         */
  1791. X        for(p++; *p && *p != ':'; p++) ;
  1792. X        uid = atoi(p+1);
  1793. X
  1794. X        /*
  1795. X         * Now we need to add the info to our database on this remote
  1796. X         * host.  If the user is already present, just update the uid
  1797. X         * number.  If the user is not present, and there is a default
  1798. X         * local user for this remote host, use that.  If not, then
  1799. X         * use the default user entry for this host (where the server
  1800. X         * runs).
  1801. X         */
  1802. X        if (ruser = findrusername(&h->h_rusers, buf))
  1803. X        {
  1804. X            debug2("(existing) ");
  1805. X            ruser->r_uid = uid;
  1806. X        }
  1807. X        else
  1808. X        {
  1809. X            debug2("(new, ");
  1810. X            ruser = newruser();
  1811. X            ruser->r_name = copy(buf);
  1812. X            ruser->r_uid = uid;
  1813. X            if (h->h_default_user)
  1814. X            {
  1815. X                debug2("%s default)", *h->h_names);
  1816. X                ruser->r_user = h->h_default_user;
  1817. X            }
  1818. X            else
  1819. X            {
  1820. X                ruser->r_user = default_user;
  1821. X                debug2("host default)");
  1822. X            }
  1823. X            addlist(&h->h_rusers, ruser);
  1824. X        }
  1825. X        debug2("host %s: user %s (%d) -> local user %s (%d)\n",
  1826. X            h->h_names[ 0 ], ruser->r_name, ruser->r_uid,
  1827. X            ruser->r_user->u_name, ruser->r_user->u_local_uid);
  1828. X    }
  1829. X    fclose(input);
  1830. X    h->h_cmdfd = -1;
  1831. X    alarm(0);
  1832. X    if (errno == EINTR)
  1833. X        log("can't get remote users from \"%s\"\n", h->h_names[0]);
  1834. X}
  1835. X
  1836. X/*
  1837. X * Try to obtain mount information for host 'h'.
  1838. X */
  1839. Xgetmount(h)
  1840. X    register hosts    *h;
  1841. X{
  1842. X    long    savefd = h->h_cmdfd;
  1843. X    struct message    msgbuf;
  1844. X    register struct message    *msg = &msgbuf;
  1845. X    register long    len;
  1846. X
  1847. X    if (thishost == h) /* our own machine */
  1848. X    {
  1849. X        log("we are talking to ourselves\n");
  1850. X        h->h_cmdfd = open("/etc/passwd", O_RDONLY);
  1851. X        bcopy(byteorder, h->h_byteorder, 4);
  1852. X        h->h_byteorderok = TRUE;
  1853. X    }
  1854. X    else
  1855. X    {
  1856. X        if ((h->h_cmdfd = tcpconnect(h)) < 0)
  1857. X            goto done;
  1858. X        len = R_MINRMSG + sizeof(long);
  1859. X        msg->m_hdlen = htons(len);
  1860. X        msg->m_totlen = htonl(len);
  1861. X        msg->m_syscall = htons(RSYS_nosys);
  1862. X        msg->m_args[ 0 ] = htonl(CMD_NEEDMOUNT);
  1863. X        if (!sndmsg(h->h_cmdfd, msg, len, 0, 0))
  1864. X        {
  1865. X            log("can't ask for mount info\n");
  1866. X            close(h->h_cmdfd);
  1867. X            goto done;
  1868. X        }
  1869. X        getbyteorder(h);
  1870. X    }
  1871. X    getrusers(h); /* getrusers() closes the file descriptor */
  1872. Xdone:
  1873. X    h->h_cmdfd = savefd;
  1874. X}
  1875. X
  1876. X/*
  1877. X * Send mount information.  This includes a 4-byte header containing the
  1878. X * byte order for our machine,  followed by /etc/passwd.
  1879. X */
  1880. Xsendmount(h)
  1881. X    register hosts    *h;
  1882. X{
  1883. X    char    buf[ BUFSIZ ];
  1884. X    register long    fd = open("/etc/passwd", O_RDONLY),
  1885. X            cnt;
  1886. X    register char    *p = buf;
  1887. X
  1888. X    write(h->h_cmdfd, byteorder, 4);
  1889. X    while ((cnt = read(fd, p, BUFSIZ)) > 0)
  1890. X        _rmtio(write, h->h_cmdfd, p, cnt);
  1891. X    close(h->h_cmdfd);
  1892. X    h->h_cmdfd = -1;
  1893. X    close(fd);
  1894. X}
  1895. X
  1896. X/*
  1897. X * Mourne the death of any children.
  1898. X */
  1899. Xmourne()
  1900. X{
  1901. X    union wait    status;
  1902. X    char        buf[ BUFSIZ ];
  1903. X    register char    *p = buf;
  1904. X    register long    pid;
  1905. X
  1906. X    while ((pid = wait3(&status, WNOHANG, 0)) > 0)
  1907. X    {
  1908. X        sprintf(p, "server %d found dead", pid);
  1909. X        p += strlen(p);
  1910. X        if (status.w_termsig)
  1911. X            sprintf(p, " by sig #%d", status.w_termsig);
  1912. X        p += strlen(p);
  1913. X        if (status.w_coredump)
  1914. X            sprintf(p, " with core dump", status.w_termsig);
  1915. X        p += strlen(p);
  1916. X        sprintf(p, " exit=%d\n", status.w_retcode);
  1917. X        debug5("%s", buf);
  1918. X        p = buf;
  1919. X    }
  1920. X}
  1921. X
  1922. X/*
  1923. X * Catch signals and only report.
  1924. X */
  1925. Xcatch(sig, code, scp)
  1926. X    register long    sig,
  1927. X            code;
  1928. X    register struct sigcontext    *scp;
  1929. X{
  1930. X    log("caught signal #%d...", sig);
  1931. X    if (sig == SIGILL || sig == SIGSEGV || sig == SIGBUS)
  1932. X    {
  1933. X        change_to_uid(0);
  1934. X        chdir("/usr/tmp");
  1935. X        log("aborting: code=%d, scp=%x, sp=%x, pc=%x, end of scp=%x\n",
  1936. X            code, scp, scp->sc_sp, scp->sc_pc, scp+1);
  1937. X        sendsig(current_pid, SIGEMT);
  1938. X        log_fatal("could not abort\n");
  1939. X    }
  1940. X    else if (sig == SIGTERM) /* quietly go away */
  1941. X    {
  1942. X        /*
  1943. X         * unlink the file only if we are allowed to and if it is
  1944. X         * not the sentry server's logfile.
  1945. X         */
  1946. X        if ((remote_debug & 0x800) == 0 && host != NULL)
  1947. X            unlink(logfile);
  1948. X        cleanup();
  1949. X        log("goodbye.\n");
  1950. X        exit(0);
  1951. X    }
  1952. X    else
  1953. X        log_fatal("exiting\n");
  1954. X}
  1955. X
  1956. X/*
  1957. X * Receive a wakeup call.
  1958. X */
  1959. Xwakeup_call()
  1960. X{
  1961. X    if (! i_am_asleep)
  1962. X    {
  1963. X        log("recieved spurious wakeup call!\n");
  1964. X        return;
  1965. X    }
  1966. X    i_am_asleep = FALSE;
  1967. X}
  1968. X
  1969. X/*
  1970. X * Provide name server function for kernel.  At this point we have just
  1971. X * recieved a SIGURG signal because the kernel wants us to translate a
  1972. X * name.
  1973. X */
  1974. Xnameserver()
  1975. X{
  1976. X#ifdef CANREMOTE
  1977. X    char        path[ BUFSIZ ],
  1978. X            hostname[ BUFSIZ ];
  1979. X    struct sockaddr_in    sinbuf;
  1980. X    register char    *p1, *p2, *name;
  1981. X    register hosts    *h = NULL;
  1982. X    register struct sockaddr_in    *sin;
  1983. X
  1984. X    if (remotename(NM_WHATNAME, 0, BUFSIZ, path) < 0)
  1985. X        return;
  1986. X    /*
  1987. X     * Find the end of the '/' prefix and copy up to the next '/' or
  1988. X     * null character.
  1989. X     */
  1990. X    p1 = path;
  1991. X    while (*p1 == '/')
  1992. X        p1++;
  1993. X    p2 = hostname;
  1994. X    *p2++ = '/';
  1995. X    while (*p1 && *p1 != '/')
  1996. X        *p2++ = *p1++;
  1997. X    *p2 = '\0';
  1998. X
  1999. X    /*
  2000. X     * Now look it up.
  2001. X     */
  2002. X    if (hostname[1])
  2003. X        h = findhostname(hostname+1);
  2004. X    if (h == NULL)
  2005. X    {
  2006. X        debug6("cannot find host for path \"%s\"\n", path);
  2007. X        sin = NULL;
  2008. X    }
  2009. X    else
  2010. X    {
  2011. X        sin = &sinbuf;
  2012. X        debug6("path %s mapped to host %s\n", path, h->h_names[0]);
  2013. X        bzero((char *)sin, sizeof (struct sockaddr_in));
  2014. X        bcopy(&h->h_addr, (char *)&sin->sin_addr,
  2015. X            sizeof(struct in_addr));
  2016. X        sin->sin_family = AF_INET;
  2017. X        sin->sin_port = serviceport;
  2018. X    }
  2019. X    remotename(NM_NAMEIS, sin, sizeof(struct sockaddr_in), hostname);
  2020. X#endif CANREMOTE
  2021. X}
  2022. X
  2023. X/*
  2024. X * Decide if a file is really a local file to the client or not.  We only
  2025. X * look for explicit references like
  2026. X *    name1/name2/../name3 ...
  2027. X * And we then check to see whether name2 is the root directory.  If it is
  2028. X * then we send the request back to the client.
  2029. X */
  2030. Xislocal(msg, type)
  2031. X    register struct message *msg;
  2032. X{
  2033. X    register char    *p;
  2034. X    register boolean    checktwopaths;
  2035. X    register short    syscall = msg->m_syscall;
  2036. X    register long    offset1,
  2037. X            offset2 = -1,
  2038. X            localcnt = 0;
  2039. X    register process    *proc;
  2040. X    char    buf[ BUFSIZ ];
  2041. X
  2042. X    debug10("cwd=%s\n", getwd(buf));
  2043. X    checktwopaths = (type & NEED_2REMOTE);
  2044. X
  2045. X    if (checktwopaths)
  2046. X        p = twopath1addr(msg);
  2047. X    else
  2048. X        p = path1addr(msg);
  2049. X    if ((offset1 = find_dotdot(p)) >= 0)
  2050. X        localcnt++;
  2051. X    if (checktwopaths)
  2052. X        if ((offset2 = find_dotdot(twopath2addr(msg))) >= 0)
  2053. X            localcnt++;
  2054. X    if (localcnt)
  2055. X    {
  2056. X        debug10("%d paths are remote: \"%s\" @ %d, \"%s\" @ %d\n",
  2057. X            localcnt,
  2058. X            checktwopaths ? twopath1addr(msg) : path1addr(msg),
  2059. X            offset1, checktwopaths ? twopath2addr(msg) : "",
  2060. X            offset2);
  2061. X        setup_proc(proc = wildcard, msg->m_uid, msg->m_pid);
  2062. X        proc->p_errno = -1;
  2063. X        proc->p_returnval = offset1;
  2064. X        sendreturn(proc, host->h_cmdfd, NULL, 1, offset2);
  2065. X    }
  2066. X    return(localcnt);
  2067. X}
  2068. X
  2069. X/*
  2070. X * kernel code stolen for speed.
  2071. X */
  2072. Xmyaccess(st, user, perm)
  2073. X    register struct stat    *st;
  2074. X    register long    perm;
  2075. X    register users    *user;
  2076. X{
  2077. X    register long    *gp, i;
  2078. X
  2079. X    perm <<= 6;
  2080. X    if (user->u_local_uid != st->st_uid) {
  2081. X        perm >>= 3;
  2082. X        gp = user->u_local_groups;
  2083. X        for (i=0; i < user->u_numgroups; i++, gp++)
  2084. X            if (st->st_gid == *gp)
  2085. X                goto found;
  2086. X        perm >>= 3;
  2087. Xfound:
  2088. X        ;
  2089. X    }
  2090. X    if ((st->st_mode & perm) != 0)
  2091. X        return (TRUE);
  2092. X    return(FALSE);
  2093. X}
  2094. X
  2095. X/*
  2096. X * look for a component of ".." terminated by a '/' or a null character.
  2097. X * If we find one, examine the previous component to see if it is our
  2098. X * root directory.
  2099. X */
  2100. Xfind_dotdot(path)
  2101. X    register char    *path;
  2102. X{
  2103. X    struct stat    statb;
  2104. X    register char    *p;
  2105. X    register struct stat    *statp = &statb;
  2106. X    register long    retval;
  2107. X    extern struct stat    root;
  2108. X
  2109. X    for (p = path; *p;)
  2110. X    {
  2111. X        while (*p == '/')
  2112. X            p++;
  2113. X        if (p[0] == '.' && p[1] == '.'
  2114. X        && (p[2] == '\0' || p[2] == '/'))
  2115. X        {
  2116. X            if (p == path)
  2117. X                if (in_root_directory)
  2118. X                    return(0);
  2119. X                else
  2120. X                    goto next_component;
  2121. X            *p = '\0'; /* we know it is a '.' */
  2122. X            retval = lstat(path, statp);
  2123. X            *p = '.';
  2124. X            if (retval < 0)
  2125. X                return(retval);
  2126. X            if (isroot(statp))
  2127. X                return(p - path + 1);
  2128. X        }
  2129. Xnext_component:
  2130. X        while (*p && *p != '/')
  2131. X            p++;
  2132. X    }
  2133. X    return(-1);
  2134. X}
  2135. SHAREOF
  2136. chmod 444 remote/info.c
  2137. #
  2138. # remote/init.c
  2139. #
  2140. if [ -f remote/init.c ]; then 
  2141.     echo -n 'Hit <return> to overwrite remote/init.c or ^C to quit' 
  2142.     read ans 
  2143.     rm -f remote/init.c 
  2144. fi 
  2145.  
  2146. sed -e 's/^.//' << \SHAREOF > remote/init.c
  2147. X/*
  2148. X * Copyright 1985, Todd Brunhoff.
  2149. X *
  2150. X * This software was written at Tektronix Computer Research Laboratories
  2151. X * as partial fulfillment of a Master's degree at the University of Denver.
  2152. X * This is not Tektronix proprietary software and should not be
  2153. X * confused with any software product sold by Tektronix.  No warranty is
  2154. X * expressed or implied on the reliability of this software; the author,
  2155. X * the University of Denver, and Tektronix, inc. accept no liability for
  2156. X * any damage done directly or indirectly by this software.  This software
  2157. X * may be copied, modified or used in any way, without fee, provided this
  2158. X * notice remains an unaltered part of the software.
  2159. X *
  2160. X * $Log:    init.c,v $
  2161. X * Revision 2.1  86/01/05  18:13:54  toddb
  2162. X * Added include for sys/stat.h because pyramid machines get upset.
  2163. X * 
  2164. X * Revision 2.0  85/12/07  18:21:37  toddb
  2165. X * First public release.
  2166. X * 
  2167. X */
  2168. Xstatic char    *rcsid = "$Header: init.c,v 2.1 86/01/05 18:13:54 toddb Exp $";
  2169. X#include    "server.h"
  2170. X#include    <stdio.h>
  2171. X#include    <pwd.h>
  2172. X#include    <grp.h>
  2173. X#include    <netdb.h>
  2174. X#include    <fcntl.h>
  2175. X#include    <sys/dir.h>
  2176. X#include    <sys/user.h>
  2177. X#include    <sys/signal.h>
  2178. X#include    <sys/ioctl.h>
  2179. X#include    <sys/stat.h>
  2180. X
  2181. Xextern hosts    *hostlist;
  2182. Xextern hosts    *thishost;
  2183. Xextern users    *userlist;
  2184. Xextern users    *default_user;
  2185. Xextern char    hostname[];
  2186. Xextern char    *service;
  2187. Xextern short    current_uid;
  2188. Xextern short    current_pid;
  2189. Xextern process    *wildcard;
  2190. Xextern struct sigvec    sig_vec;
  2191. Xextern struct sigvec    sig_name;
  2192. Xextern struct sigvec    sig_alarm;
  2193. Xextern struct sigvec    sig_ignore;
  2194. Xextern struct sigvec    sig_continue;
  2195. X#ifdef RFSDEBUG
  2196. Xextern struct sigvec    sig_debug;
  2197. X#endif
  2198. Xextern struct stat    root;
  2199. X
  2200. X/*
  2201. X * Initialize the host tables and user tables.
  2202. X */
  2203. Xinit()
  2204. X{
  2205. X    long    tt;
  2206. X    struct hostent    *gethostent();
  2207. X    struct passwd    *getpwent();
  2208. X    struct group    *getgrent();
  2209. X
  2210. X    /*
  2211. X     * catch signals.
  2212. X     */
  2213. X    sigvec(SIGHUP, &sig_ignore, (struct sigvec *)0);
  2214. X    sigvec(SIGINT, &sig_vec, (struct sigvec *)0);
  2215. X    sigvec(SIGQUIT, &sig_vec, (struct sigvec *)0);
  2216. X    sigvec(SIGILL, &sig_vec, (struct sigvec *)0);
  2217. X#ifdef RFSDEBUG
  2218. X    sigvec(SIGTRAP, &sig_debug, (struct sigvec *)0);
  2219. X#endif RFSDEBUG
  2220. X    /*    SIGIOT        */
  2221. X    /*    SIGEMT        */
  2222. X    /*    SIGFPE        */
  2223. X    /*    SIGKILL        */
  2224. X    sigvec(SIGBUS, &sig_vec, (struct sigvec *)0);
  2225. X    sigvec(SIGSEGV, &sig_vec, (struct sigvec *)0);
  2226. X    sigvec(SIGSYS, &sig_vec, (struct sigvec *)0);
  2227. X    sigvec(SIGPIPE, &sig_vec, (struct sigvec *)0);
  2228. X    sigvec(SIGALRM, &sig_alarm, (struct sigvec *)0);
  2229. X    sigvec(SIGTERM, &sig_vec, (struct sigvec *)0);
  2230. X    sigvec(SIGURG, &sig_name, (struct sigvec *)0);
  2231. X    /*    SIGSTOP        */
  2232. X    /*    SIGTSTP        */
  2233. X    /*    SIGCONT        */
  2234. X    /*    SIGCHLD        */
  2235. X    sigvec(SIGTTIN, &sig_vec, (struct sigvec *)0);
  2236. X    sigvec(SIGTTOU, &sig_vec, (struct sigvec *)0);
  2237. X    sigvec(SIGIO, &sig_continue, (struct sigvec *)0);
  2238. X    sigvec(SIGXCPU, &sig_vec, (struct sigvec *)0);
  2239. X    sigvec(SIGXFSZ, &sig_vec, (struct sigvec *)0);
  2240. X    sigvec(SIGVTALRM, &sig_vec, (struct sigvec *)0);
  2241. X    /*    SIGPROF        */
  2242. X
  2243. X    /*
  2244. X     * set up some important global values, including uid, pid,
  2245. X     * the pipe file descriptors for messages to and from the gateway
  2246. X     * server.  Register as the nameserver.  Get host name.  Get service.
  2247. X     * Get root stat info.
  2248. X     */
  2249. X    if (chdir("/") == -1)
  2250. X        log_fatal("cannot chdir(\"/\")\n");
  2251. X    wildcard = newprocess();
  2252. X    fcntl(2, F_SETFL, FAPPEND);
  2253. X    close(0);
  2254. X    close(1);
  2255. X    change_to_uid(0);
  2256. X    if (gethostname(hostname, HOSTNAMELEN) < 0 || *hostname == '\0')
  2257. X        log_fatal("host name not set!\n");
  2258. X    if (stat("/", &root) < 0)
  2259. X        log_fatal("cannot stat /\n");
  2260. X#ifdef CANREMOTE
  2261. X    if (remotename(NM_SERVER, 0, 0, 0) < 0)
  2262. X        log("cannot register as nameserver\n");
  2263. X    /*
  2264. X     * Turn off remote access, if we have any.
  2265. X     */
  2266. X    remoteoff(NULL);
  2267. X#endif
  2268. X    tt = open("/dev/tty", 2);
  2269. X
  2270. X    if (tt >= 0)
  2271. X    {
  2272. X        ioctl(tt, TIOCNOTTY, 0);
  2273. X        close(tt);
  2274. X    }
  2275. X    setpgrp(0,0);
  2276. X
  2277. X    initusers();
  2278. X    initgroups();
  2279. X    inithosts();
  2280. X    initrhosts();
  2281. X}
  2282. X
  2283. X/*
  2284. X * build the list of users on this host (where the server runs).
  2285. X */
  2286. Xinitusers()
  2287. X{
  2288. X    register struct passwd    *pw;
  2289. X    register users    *user;
  2290. X    char        buf[ BUFSIZ ];
  2291. X    register char    *pbuf = buf;
  2292. X
  2293. X    while(pw = getpwent())
  2294. X    {
  2295. X        if (*pw->pw_dir == '\0' || *pw->pw_name == '\0')
  2296. X        {
  2297. X            log("login \"%s\" has problems, dir=\"%s\"\n",
  2298. X                pw->pw_name, pw->pw_dir);
  2299. X            continue;
  2300. X        }
  2301. X        user = newuser();
  2302. X        user->u_local_uid = pw->pw_uid;
  2303. X        user->u_name = copy( pw->pw_name );
  2304. X        addgroup(user, pw->pw_gid);
  2305. X        user->u_dir = copy( pw->pw_dir );
  2306. X        sprintf(pbuf, "%s/.rhosts", pw->pw_dir);
  2307. X        user->u_rhosts = copy( pbuf );
  2308. X        addlist(&userlist, user);
  2309. X    }
  2310. X    endpwent();
  2311. X    if (user = findusername(DEFAULTUSER))
  2312. X        default_user = user;
  2313. X    else
  2314. X        log_fatal("The user \"%s\" must be in /etc/passwd (%s)\n",
  2315. X            DEFAULTUSER, "for default permissions");
  2316. X}
  2317. X
  2318. X/*
  2319. X * Build the list of groups that each user belongs to.
  2320. X */
  2321. Xinitgroups()
  2322. X{
  2323. X    register struct group    *gr;
  2324. X    register users    *user;
  2325. X    register char    **p;
  2326. X
  2327. X
  2328. X    while(gr = getgrent())
  2329. X    {
  2330. X        for (p = gr->gr_mem; *p; p++)
  2331. X            if (user = findusername(*p))
  2332. X                addgroup(user, gr->gr_gid);
  2333. X            else
  2334. X                log("group %s: bad user=%s\n",
  2335. X                    gr->gr_name, *p);
  2336. X    }
  2337. X    endgrent();
  2338. X}
  2339. X
  2340. X/*
  2341. X * Then build the list of all hosts.
  2342. X */
  2343. Xinithosts()
  2344. X{
  2345. X    register struct hostent    *h;
  2346. X    register rusers    *ruser;
  2347. X    register hosts    *hst;
  2348. X    register users    *user;
  2349. X    register long    i;
  2350. X
  2351. X    while (h = gethostent())
  2352. X    {
  2353. X        hst = newhost();
  2354. X        hst->h_names = newname(hst->h_names, h->h_name);
  2355. X        for (i=0; h->h_aliases[ i ]; i++)
  2356. X            hst->h_names = newname(hst->h_names,
  2357. X                    h->h_aliases[ i ]);
  2358. X
  2359. X        hst->h_addr = *((struct in_addr *)(h->h_addr));
  2360. X        addlist(&hostlist, hst);
  2361. X
  2362. X        /*
  2363. X         * now if there exists a user on this machine having
  2364. X         * the same name as the name of this host (NOT AN
  2365. X         * ALIAS!), then that will be our defaut local user
  2366. X         * to map to.  Be sure that we don't allow a machine
  2367. X         * to be mapped onto a user if the uid is real small:
  2368. X         * e.g. a machine named root, where all its user ids
  2369. X         * become root using the remote fs!
  2370. X         */
  2371. X        user = findusername(hst->h_names[ 0 ]);
  2372. X        if (user && user->u_local_uid <= UID_TOO_LOW)
  2373. X        {
  2374. X            log("host/user %s: uid %d too low for alias\n",
  2375. X                hst->h_names[ 0 ], user->u_local_uid);
  2376. X            user = NULL;
  2377. X        }
  2378. X        else if (user)
  2379. X        {
  2380. X            hst->h_default_user = user;
  2381. X            debug2("default user for host %s (%s) is %s\n",
  2382. X                hst->h_names[ 0 ],
  2383. X                inet_ntoa(hst->h_addr), user->u_name);
  2384. X        }
  2385. X        ruser = hst->h_default_ruser = newruser();
  2386. X        if (user)
  2387. X            ruser->r_user = user;
  2388. X        else
  2389. X            ruser->r_user = default_user;
  2390. X        ruser->r_uid = -1;
  2391. X        ruser->r_name = copy(BOGUSUSER);
  2392. X    }
  2393. X    endhostent();
  2394. X    if ((thishost = findhostname(hostname)) == NULL)
  2395. X        log_fatal("this host (\"%s\") is not in host file\n",
  2396. X            hostname);
  2397. X}
  2398. X
  2399. X/*
  2400. X * Now for each user that has a .rhosts file, assemble the
  2401. X * references and attach them to the appropriate host.
  2402. X */
  2403. Xinitrhosts()
  2404. X{
  2405. X    register hosts    *hst;
  2406. X    register rhost    *rh;
  2407. X    register users    *user;
  2408. X    char        buf[ BUFSIZ ];
  2409. X    register char    *pbuf = buf;
  2410. X
  2411. X    for (user=userlist; user; user=user->u_next)
  2412. X    {
  2413. X        setrhost(user->u_rhosts);
  2414. X        while (rh = getrhostent(pbuf))
  2415. X            if (hst = findhostname(rh->rh_host))
  2416. X                addremoteuser(hst, user, rh->rh_user);
  2417. X        endrhost();
  2418. X    }
  2419. X}
  2420. X
  2421. Xchar    *copy(string)
  2422. X    register char    *string;
  2423. X{
  2424. X    register char    *ret = malloc( strlen(string)+1 );
  2425. X
  2426. X    if (ret == NULL)
  2427. X        log_fatal("cannot allocate space\n");
  2428. X    strcpy(ret, string);
  2429. X    return(ret);
  2430. X}
  2431. X
  2432. X/*
  2433. X * Add a remote user to those recognized on a certain host.
  2434. X */
  2435. Xaddremoteuser(h, user, remoteuser)
  2436. X    register hosts    *h;
  2437. X    register users    *user;
  2438. X    register char    *remoteuser;
  2439. X{
  2440. X    register rusers    *ruser;
  2441. X    register long    old = FALSE;
  2442. X
  2443. X    debug2("\t%s!%s --> %s ", *h->h_names, remoteuser, user->u_name);
  2444. X    if ((ruser = findrusername(&h->h_rusers, remoteuser)) == NULL)
  2445. X    {
  2446. X        debug2("\n");
  2447. X        ruser = newruser();
  2448. X    }
  2449. X    else
  2450. X    {
  2451. X        old = TRUE;
  2452. X        if (strcmp(remoteuser, user->u_name) != 0)
  2453. X        {
  2454. X            debug2("(old, ignored)\n");
  2455. X            return;
  2456. X        }
  2457. X        else
  2458. X            debug2("(old)\n");
  2459. X    }
  2460. X    ruser->r_name = copy(remoteuser);
  2461. X    ruser->r_uid = -1;
  2462. X    ruser->r_user = user;
  2463. X    if (! old)
  2464. X        addlist(&h->h_rusers, ruser);
  2465. X}
  2466. SHAREOF
  2467. chmod 444 remote/init.c
  2468.  
  2469.