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

  1. Date: Tue, 2 Apr 85 23:39:42 pst
  2. From: decvax!sun!pumpkinseed!blyon (Bob Lyon)
  3. Subject: Sun RPC part 2 of 10
  4.  
  5. mkdir doc; cd doc
  6. echo x - README
  7. sed 's/^X//' >README <<'!Funky!Stuff!'
  8. rpc.prog and rpc.prog2 must be catted together before troffing.
  9. Same goes for xdr.spec and xdr.spec2.
  10. !Funky!Stuff!
  11. echo x - portmap.8c
  12. sed 's/^X//' >portmap.8c <<'!Funky!Stuff!'
  13. X.\" @(#)portmap.8c 1.1 85/02/25 SMI;
  14. X.TH PORTMAP 8C "1 February 1985"
  15. X.SH NAME
  16. portmap \- DARPA port to RPC program number mapper
  17. X.SH SYNOPSIS
  18. X.B /usr/etc/rpc.portmap
  19. X.SH DESCRIPTION
  20. X.I Portmap
  21. is a server that converts RPC program numbers
  22. into DARPA protocol port numbers.
  23. It must be running in order to make RPC calls.
  24. X.PP
  25. When an RPC server is started, it will tell
  26. X.I portmap
  27. what port number it is listening to,
  28. and what RPC program numbers it is prepared to serve.
  29. When a client wishes to make an RPC call to a given program number,
  30. it will first contact
  31. X.I portmap
  32. on the server machine to determine
  33. the port number where RPC packets should be sent.
  34. X.PP
  35. Normally, standard RPC servers are started by
  36. X.IR inetd (8c),
  37. so
  38. X.I portmap
  39. must be started before
  40. X.I inetd
  41. is invoked.
  42. X.SH "SEE ALSO"
  43. servers(5), rpcinfo(8), inetd(8)
  44. X.SH BUGS
  45. If
  46. X.I portmap
  47. crashes, all servers must be restarted.
  48. !Funky!Stuff!
  49. echo x - rpc.spec
  50. sed 's/^X//' >rpc.spec <<'!Funky!Stuff!'
  51. X.OH 'RPC Protocol Spec''Page \\\\n(PN'
  52. X.EH 'Page \\\\n(PN''RPC Protocol Spec'
  53. X.OF 'Sun Microsystems''Release 2.0'
  54. X.EF 'Release 2.0''Sun Microsystems'
  55. X.RP
  56. X.rm DY
  57. X.TL
  58. X.ps 20
  59. Remote Procedure Call
  60. X.sp.5
  61. Protocol Specification 
  62. X.
  63. X.H 1 "Introduction"
  64. X.LP
  65. This document specifies a message protocol used in implementing
  66. Sun's Remote Procedure Call (RPC) package.
  67. The protocol is specified with the
  68. eXternal Data Representation (XDR) language.
  69. X.LP
  70. This document assumes that the reader is familiar with both RPC and XDR.
  71. It does not attempt to justify RPC or its uses.
  72. Also, the casual user of RPC does not need to be
  73. familiar with the information in this document.
  74. X.
  75. X.H 2 "Terminology"
  76. X.LP
  77. The document discusses servers, services,
  78. programs, procedures, clients and versions.
  79. A server is a machine where some number
  80. of network services are implemented.
  81. A service is a collection of one or more remote programs.
  82. A remote program implements one or more remote procedures;
  83. the procedures, their parameters and results are documented
  84. in the specific program's protocol specification
  85. (see Appendix 3 for an example).
  86. Network clients are pieces of software that initiate
  87. remote procedure calls to services.
  88. A server may support more than one version of a remote program
  89. in order to be forward compatible with changing protocols.
  90. X.LP
  91. For example, a network file service may be composed of two programs.
  92. One program may deal with high level applications
  93. such as file system access control and locking.
  94. The other may deal with low-level file I/O,
  95. and have procedures like ``read'' and ``write''.
  96. A client machine of the network file service would call
  97. the procedures associated with the two programs of the service
  98. on behalf of some user on the client machine.
  99. X.H 2 "The RPC Model"
  100. X.LP
  101. The remote procedure call model is similar to
  102. the local procedure call model.
  103. In the local case, the caller places arguments to a procedure
  104. in some well-specified location (such as a result register).
  105. It then transfers control to the procedure,
  106. and eventually gains back control.
  107. At that point, the results of the procedure
  108. are extracted from the well-specified location,
  109. and the caller continues execution.
  110. X.LP
  111. The remote procedure call is similar,
  112. except that one thread of control winds through two processes \(em
  113. one is the caller's process,
  114. the other is a server's process.
  115. That is, the caller process sends a call message
  116. to the server process and waits (blocks) for a reply message.
  117. The call message contains the procedure's parameters,
  118. among other things.
  119. The reply message contains the procedure's results,
  120. among other things.
  121. Once the reply message is received,
  122. the results of the procedure are extracted,
  123. and caller's execution is resumed.
  124. X.LP
  125. On the server side,
  126. a process is dormant awaiting the arrival of a call message.
  127. When one arrives the server process extracts the procedure's parameters,
  128. computes the results, sends a reply message,
  129. and then awaits the next call message.
  130. Note that in this model,
  131. only one of the two processes is active at any given time.
  132. That is, the RPC protocol does not explicitly support
  133. multi-threading of caller or server processes.
  134. X.
  135. X.H 2 "Transports and Semantics"
  136. X.LP
  137. The RPC protocol is independent of transport protocols.
  138. That is, RPC does not care how a message is passed from one process to another.
  139. The protocol only deals with the specification and interpretation of 
  140. messages.
  141. X.LP
  142. Because of transport independence,
  143. the RPC protocol does not attach specific semantics to the
  144. remote procedures or their execution.  Some semantics can be inferred from (but
  145. should be explicitly specified by) the underlying transport protocol.
  146. For example, RPC message passing using UDP/IP is unreliable.
  147. Thus, if the caller retransmits call messages after short time-outs, the only thing he
  148. can infer from no reply message is that the remote procedure was executed
  149. zero or more times (and from a reply message, one or more times).
  150. On the other hand, RPC message passing using TCP/IP is reliable.
  151. No reply message means that the remote procedure was executed at most once,
  152. whereas a reply message means that the remote procedure was exactly once.
  153. (Note:
  154. At Sun, RPC is currently implemented
  155. on top of TCP/IP and UDP/IP transports.)
  156. X.
  157. X.H 2 "Binding and Rendezvous Independence"
  158. X.LP
  159. The act of binding a client to a service is NOT part of
  160. the remote procedure call specification.
  161. This important and necessary function
  162. is left up to some higher level software.
  163. (The software may use RPC itself; see Appendix 3.)
  164. X.LP
  165. Implementors should think of the RPC protocol as the
  166. jump-subroutine instruction (``JSR'') of a network;
  167. the loader (binder) makes JSR useful,
  168. and the loader itself uses JSR to accomplish its task.
  169. Likewise, the network makes RPC useful,
  170. using RPC to accomplish this task.
  171. X.
  172. X.H 2 "Message Authentication"
  173. X.LP
  174. The RPC protocol provides the fields necessary for a client to 
  175. identify himself to a service and vice versa.
  176. Security and access control mechanisms
  177. can be built on top of the message authentication.
  178. X.bp
  179. X.
  180. X.H 1 "Requirements"
  181. X.LP
  182. The RPC protocol must provide for the following:
  183. X.DS
  184. 1.  Unique specification of a procedure to be called.
  185. 2.  Provisions for matching response messages to request messages.
  186. 3.  Provisions for authenticating the caller to service and vice versa.
  187. X.DE
  188. Besides these requirements,
  189. features that detect the following are worth supporting
  190. because of protocol roll-over errors, implementation bugs,
  191. user error, and network administration:
  192. X.DS
  193. 1.  RPC protocol mismatches.
  194. 2.  Remote program protocol version mismatches.
  195. 3.  Protocol errors (like mis-specification of a procedure's parameters).
  196. 4.  Reasons why remote authentication failed.
  197. 5.  Any other reasons why the desired procedure was not called.
  198. X.DE
  199. X.
  200. X.H 2 "Remote Programs and Procedures"
  201. X.LP
  202. The RPC call message has three unsigned fields:
  203. remote program number,
  204. remote program version number,
  205. and remote procedure number.
  206. The three fields uniquely identify the procedure to be called.
  207. Program numbers are administered by some central authority (like Sun).
  208. Once an implementor has a program
  209. number, he can implement his remote program;
  210. the first implementation would
  211. most likely have the version number of 1.
  212. Because most new protocols evolve into better,
  213. stable and mature protocols,
  214. a version field of the call message identifies which version
  215. of the protocol the caller is using.
  216. Version numbers make speaking old and new protocols
  217. through the same server process possible.
  218. X.LP
  219. The procedure number identifies the procedure to be called.
  220. These numbers are documented in
  221. the specific program's protocol specification.
  222. For example, a file service's protocol specification
  223. may state that its procedure number 5 is
  224. X.L read
  225. and procedure number 12 is
  226. X.L write .
  227. X.LP
  228. Just as remote program protocols may change over several versions,
  229. the actual RPC message protocol could also change.
  230. Therefore, the call message also has the RPC version number in it;
  231. this field must be two (2).
  232. X.LP
  233. The reply message to a request message has enough information
  234. to distinguish the following error conditions:
  235. X.IP 1)
  236. The remote implementation of RPC does speak protocol version 2.  The 
  237. lowest and highest supported RPC version numbers are returned.
  238. X.IP 2)
  239. The remote program is not available on the remote system.
  240. X.IP 3)
  241. The remote program does not support the requested version number.
  242. The lowest and highest supported
  243. remote program version numbers are returned.
  244. X.IP 4)
  245. The requested procedure number does not exist
  246. (this is usually a caller side protocol or programming error).
  247. X.IP 5)
  248. The parameters to the remote procedure
  249. appear to be garbage from the server's point of view.
  250. (Again, this is caused by a disagreement about the
  251. protocol between client and service.)
  252. X.
  253. X.H 2 "Authentication"
  254. X.LP
  255. Provisions for authentication of caller to service and vice versa are
  256. provided as a wart on the side of the RPC protocol.  The call message
  257. has two authentication fields, the credentials and verifier.
  258. The reply message has one authentication field,
  259. the response verifier.
  260. The RPC protocol specification defines all three fields
  261. to be the following opaque type:
  262. X.LS
  263. enum auth_flavor {
  264.     AUTH_NULL    = 0,
  265.     AUTH_UNIX    = 1,
  266.     AUTH_SHORT    = 2
  267.     /* and more to be defined */
  268. };
  269. X.sp.5
  270. struct opaque_auth {
  271.     union switch (enum auth_flavor) {
  272.         default: string auth_body<400>;
  273.     };
  274. };
  275. X.LE
  276. In simple English, any 
  277. X.L opaque_auth
  278. structure is an 
  279. X.L auth_flavor
  280. enumeration followed by a counted string,
  281. whose bytes are opaque to the RPC protocol implementation.
  282. X.LP
  283. The interpretation and semantics of the data contained
  284. within the authentication fields is specified by individual,
  285. independent authentication protocol specifications.
  286. Appendix 1 defines three authentication protocols.
  287. X.LP
  288. If authentication parameters were rejected,
  289. the response message contains information stating
  290. why they were rejected.  
  291. X.
  292. X.H 2 "Program Number Assignment"
  293. X.LP
  294. Program numbers are given out in groups of 0x20000000 (536870912)
  295. according to the following chart:
  296. X.LS
  297.        0 - 1fffffff    defined by Sun
  298. 20000000 - 3fffffff    defined by user
  299. 40000000 - 5fffffff    transient
  300. 60000000 - 7fffffff    reserved
  301. 80000000 - 9fffffff    reserved
  302. a0000000 - bfffffff    reserved
  303. c0000000 - dfffffff    reserved
  304. e0000000 - ffffffff    reserved
  305. X.LE
  306. The first group is a range of numbers administered by Sun Microsystems,
  307. and should be identical for all Sun customers.  The second range
  308. is for applications peculiar to a particular customer.
  309. This range is intended primarily for debugging new programs.
  310. When a customer develops an application that might be of general
  311. interest, that application should be given an assigned number
  312. in the first range.  The third group is for applications that
  313. generate program numbers dynamically.  The final groups
  314. are reservered for future use, and should not be used.
  315. X.LP
  316. The exact registration process for Sun defined numbers is yet
  317. to be established.
  318. X.bp
  319. X.
  320. X.H 1 "Other Uses and Abuses of the RPC Protocol"
  321. X.LP
  322. The intended use of this protocol is for calling remote procedures.
  323. That is, each call message is matched with a response message.
  324. However, the protocol itself is a message passing protocol
  325. with which other (non-RPC) protocols can be implemented.
  326. Sun currently uses (abuses) the RPC message protocol for the 
  327. following two (non-RPC) protocols:
  328. batching (or pipelining) and broadcast RPC.
  329. These two protocols are discussed (but not defined) below.
  330. X.
  331. X.H 2 "Batching"
  332. X.LP
  333. Batching allows a client to send an arbitrarily large sequence
  334. of call messages to a server;
  335. batching uses reliable bytes stream protocols (like TCP/IP)
  336. for their transport.
  337. In the case of batching, the client never waits for a reply
  338. from the server and the server does not send replies to batch requests.
  339. A sequence of batch calls is usually terminated by a legitimate
  340. RPC in order to flush the pipeline (with positive acknowledgement).
  341. X.
  342. X.H 2 "Broadcast RPC"
  343. X.LP
  344. In broadcast RPC based protocols,
  345. the client sends an a broadcast packet to
  346. the network and waits for numerous replies.
  347. Broadcast RPC uses unreliable, packet based protocols (like UDP/IP)
  348. as their transports.
  349. Servers that support broadcast protocols only respond
  350. when the request is successfully processed,
  351. and are silent in the face of errors. 
  352. X.
  353. X.H 1 "The RPC Message Protocol"
  354. X.LP
  355. This section defines the RPC message protocol in the XDR data description
  356. language.  The message is defined in a top down style.
  357. Note: This is an XDR specification, not C code.
  358. X.LP
  359. X.LS 0
  360. enum msg_type {
  361.     CALL = 0,
  362.     REPLY = 1
  363. };
  364. X.LE
  365. X.LS 0
  366. /* 
  367.  * A reply to a call message can take on two forms:
  368.  * the message was either accepted or rejected.
  369.  */
  370. enum reply_stat {
  371.     MSG_ACCEPTED = 0,
  372.     MSG_DENIED = 1
  373. };
  374. X.LE
  375. X.LS 0
  376. /*
  377.  * Given that a call message was accepted, the following is the status of
  378.  * an attempt to call a remote procedure.
  379.  */
  380. enum accept_stat {
  381.     SUCCESS = 0,       /* remote procedure was successfully executed */
  382.     PROG_UNAVAIL = 1,  /* remote machine exports the program number */
  383.     PROG_MISMATCH = 2, /* remote machine can't support version number */
  384.     PROC_UNAVAIL = 3,  /* remote program doesn't know about procedure */
  385.     GARBAGE_ARGS = 4   /* remote procedure can't figure out parameters */
  386. };
  387. X.LE
  388. X.LS 0
  389. /*
  390.  * Reasons why a call message was rejected:
  391.  */
  392. enum reject_stat {
  393.     RPC_MISMATCH = 0,  /* RPC version number was not two (2) */
  394.     AUTH_ERROR = 1     /* caller not authenticated on remote machine */
  395. };
  396. X.LE
  397. X.LS 0
  398. /*
  399.  * Why authentication failed:
  400.  */
  401. enum auth_stat {
  402.     AUTH_BADCRED = 1,    /* bogus credentials (seal broken) */
  403.     AUTH_REJECTEDCRED = 2,    /* client should begin new session */
  404.     AUTH_BADVERF = 3,    /* bogus verifier (seal broken) */
  405.     AUTH_REJECTEDVERF = 4,    /* verifier expired or was replayed */
  406.     AUTH_TOOWEAK = 5,    /* rejected due to security reasons */
  407. };
  408. X.LE
  409. X.LS 0
  410. /*
  411.  * The RPC message:
  412.  * All messages start with a transaction identifier, xid,  followed by
  413.  * a two-armed discriminated union.  The union's discriminant is a msg_type
  414.  * which switches to one of the two types of the message.  The xid of a
  415.  * REPLY message always matches that of the initiating CALL message.
  416.  * NB: The xid field is only used for clients matching reply messages with
  417.  * call messages; the service side cannot treat this id as any type of 
  418.  * sequence number. 
  419.  */
  420. struct rpc_msg {
  421.     unsigned    xid;
  422.     union switch (enum msg_type) {
  423.         CALL:    struct call_body;
  424.         REPLY:    struct reply_body;
  425.     };
  426. };
  427. X.LE
  428. X.LS 0
  429. /*
  430.  * Body of an RPC request call:
  431.  * In version 2 of the RPC protocol specification, rpcvers must be equal to 2.
  432.  * The fields prog, vers, and proc specify the remote program, its version,
  433.  * and the procedure within the remote program to be called.  These fields are
  434.  * followed by two authentication parameters, cred (authentication credentials)
  435.  * and verf (authentication verifier).  The authentication parameters are
  436.  * followed * by the parameters to the remote procedure; these parameters are
  437.  * specified by the specific program protocol. 
  438.  */
  439. struct call_body {
  440.     unsigned rpcvers;    /* must be equal to two (2) */
  441.     unsigned prog;
  442.     unsigned vers;
  443.     unsigned proc;
  444.     struct opaque_auth cred;
  445.     struct opaque_auth verf;
  446.     /* procedure specific parameters start here */
  447. };
  448. X.LE
  449. X.LS 0
  450. /* 
  451.  * Body of a reply to an RPC request.
  452.  * The call message was either accepted or rejected.
  453.  */
  454. struct reply_body {
  455.     union switch (enum reply_stat) {
  456.         MSG_ACCEPTED:    struct accepted_reply;
  457.         MSG_DENIED:    struct rejected_reply;
  458.     };
  459. };
  460. X.LE
  461. X.LS 0
  462. /*
  463.  * Reply to an RPC request that was accepted by the server.
  464.  * Note: there could be an error even though the request was accepted.
  465.  * The first field is an authentication verifier which the server generates
  466.  * in order to validate itself to the caller.  It is followed by a union
  467.  * whose discriminant is an enum accept_stat.  The SUCCESS arm of the union is
  468.  * protocol specific.  The PROG_UNAVAIL, PROC_UNAVAIL, and GARBAGE_ARGS arms
  469.  * of the union are void.  The PROG_MISMATCH arm specifies the lowest and
  470.  * highest version numbers of the remote program that are supported by the
  471.  * server.
  472.  */
  473. struct accepted_reply {
  474.     struct opaque_auth    verf;
  475.     union switch (enum accept_stat) {
  476.         SUCCESS: struct {
  477.             /*
  478.              * procedure-specific results start here
  479.              */
  480.         };
  481.         PROG_MISMATCH: struct {
  482.             unsigned low;
  483.             unsigned  high;
  484.         };
  485.         default: struct {
  486.             /*
  487.              * void. Cases include PROG_UNAVAIL,
  488.              * PROC_UNAVAIL, and GARBAGE_ARGS.
  489.              */
  490.         };
  491.     };
  492. };
  493. X.LE
  494. X.LS 0
  495. /*
  496.  * Reply to an RPC request that was rejected by the server.
  497.  * The request can be rejected because of two reasons - either the server is
  498.  * not running a compatible version of the RPC protocol (RPC_MISMATCH), or
  499.  * the server refused to authenticate the caller (AUTH_ERROR).  In the case of
  500.  * an RPC version mismatch, the server returns the lowest and highest supported
  501.  * RPC version numbers. In the case of refused authentication, the failure
  502.  * status is returned.
  503.  */
  504. struct rejected_reply {
  505.     union switch (enum reject_stat) {
  506.         RPC_MISMATCH: struct {
  507.             unsigned low;
  508.             unsigned high;
  509.         };
  510.         AUTH_ERROR: enum auth_stat;
  511.     };
  512. };
  513. X.LE
  514. X.bp
  515. X.
  516. X.H 1 "Appendix 1: Authentication Parameters Specification"
  517. X.LP
  518. As previously stated, authentication parameters are opaque,
  519. but open-ended to the rest of the
  520. RPC protocol.  This section defines some ``flavors'' of authentication 
  521. which have been implemented at (and supported by) Sun.
  522. X.
  523. X.H 2 "Null Authentication"
  524. X.LP
  525. Often calls must be made where the caller does not know who he is and
  526. the server does not care who the caller is.  In this case, the auth_flavor value
  527. (the discriminant of the opaque_auth's union) of the
  528. RPC message's credentials, verifier, and response verifier
  529. is AUTH_NULL (0).
  530. The bytes of the auth_body string are undefined.
  531. It is recommended that the string length be zero.
  532. X.
  533. X.H 2 "UNIX Authentication"
  534. X.LP
  535. The caller of a remote procedure may wish to identify himself as he is
  536. identified on a
  537. X.UX
  538. system.
  539. The value of the 
  540. X.I credential's
  541. discriminant of
  542. an RPC call message is AUTH_UNIX (1).  The bytes of the 
  543. X.I credential's
  544. string
  545. encode the the following (XDR) structure:
  546. X.LS
  547. struct auth_unix {
  548.     unsigned    stamp;
  549.     string        machinename<255>;
  550.     unsigned    uid;
  551.     unsigned    gid;
  552.     unsigned    gids<10>;
  553. };
  554. X.LE
  555. The 
  556. X.L stamp
  557. is an arbitrary id which the caller machine may generate.
  558. The 
  559. X.L machinename
  560. is the name of the caller's machine (like ``krypton'').
  561. The 
  562. X.L uid
  563. is the caller's effective user id.
  564. The 
  565. X.L gid 
  566. is the callers effective group id.
  567. The 
  568. X.L gids
  569. is a counted array of groups
  570. which contain the caller as a member.
  571. The 
  572. X.I verifier
  573. accompanying the credentials should be of AUTH_NULL (defined above).
  574. X.LP
  575. The value of the discriminate of the 
  576. X.I "response verifier"
  577. received in the reply message from the server may be
  578. AUTH_NULL or AUTH_SHORT (2).
  579. In the case of AUTH_SHORT, the bytes of the 
  580. X.I "response verifier" 's
  581. string encode an 
  582. X.L auth_opaque
  583. structure.
  584. This new 
  585. X.L auth_opaque
  586. structure may now be passed to the server
  587. instead of the original AUTH_UNIX flavor credentials.
  588. The server keeps a cache which maps short hand 
  589. X.I auth_opaque
  590. structures (passed back via a AUTH_SHORT style 
  591. X.L "response verifier" )
  592. to the original credentials of the caller.
  593. The caller can save network bandwidth and server cpu cycles
  594. by using the new credentials.
  595. X.LP
  596. The server may flush the short hand 
  597. X.I auth_opaque
  598. structure at any time.
  599. If this happens, the remote procedure call message will be rejected due to an
  600. authentication error.  The reason for the failure will be AUTH_REJECTEDCRED.
  601. At this point, the caller may wish to try the original AUTH_UNIX style of 
  602. credentials.     
  603. X.
  604. X.H 1 "Appendix 2: Record Marking Standard (RM)"
  605. X.LP
  606. When RPC messages are passed on top of a byte stream protocol
  607. (like TCP/IP), it is necessary, or at least desirable,
  608. to delimit one message from another in order to detect
  609. and possibly recover from user protocol errors.
  610. Sun uses this RM/TCP/IP transport for passing
  611. RPC messages on TCP streams.
  612. One RPC message fits into one RM record.
  613. X.LP
  614. A record is composed of one or more record fragments.
  615. A record fragment is a four-byte header followed by 
  616. X.I 0
  617. to 
  618. X.I "2\s-2\u31\d\s+2\-1"
  619. bytes of fragment data.
  620. The bytes encode an unsigned binary number;
  621. as with XDR integers, the byte order is from highest to lowest.
  622. The number encodes two values \(em
  623. a boolean which indicates whether the fragment is the last fragment
  624. of the record (bit value 1 implies the fragment is the last fragment)
  625. and a 31-bit unsigned binary value which is the length in bytes of the 
  626. fragment's data.
  627. The boolean value is the highest-order bit of the header;
  628. the length is the 31 low-order bits.
  629. (Note that this record specification is 
  630. X.I not
  631. in XDR standard form!)
  632. X.
  633. X.H 1 "Appendix 3: Port Mapper Program Protocol"
  634. X.LP
  635. The port mapper program maps RPC program and version numbers
  636. to UDP/IP or TCP/IP port numbers.
  637. This program makes dynamic binding of remote programs possible.
  638. X.LP
  639. This is desirable because the range of reserved port numbers is very small
  640. and the number of potential remote programs is very large.  By running only
  641. the port mapper on a reserved port, the port numbers of other remote programs
  642. can be ascertained by querying the port mapper.
  643. X.
  644. X.H 2 "The Port Mapper RPC Protocol"
  645. X.LP
  646. The protocol is specified by the XDR description language.
  647. X.LP
  648. X.LS 0
  649. Port Mapper RPC Program Number: 100000
  650.     Version Number: 1
  651.     Supported Transports:
  652.         UDP/IP on port 111
  653.         RM/TCP/IP on port 111
  654. X.LE
  655. X.LS 0
  656. /* 
  657.  * Handy transport protocol numbers 
  658.  */
  659. #define IPPROTO_TCP    6    /* protocol number used for rpc/rm/tcp/ip */
  660. #define IPPROTO_UDP    17    /* protocol number used for rpc/udp/ip */
  661. X.LE
  662. X.LS 0
  663. /* Procedures */
  664.  
  665. /*
  666.  * Convention: procedure zero of any protocol takes no parameters
  667.  * and returns no results.
  668.  */
  669. 0. PMAPPROC_NULL () returns ()
  670. X.LE
  671. X.LS 0
  672. /*
  673.  * Procedure 1, setting a mapping:
  674.  * When a program first becomes available on a 
  675.  * machine, it registers itself with the port mapper program on the
  676.  * same machine.  The program passes its program number (prog),
  677.  * version number (vers), transport protocol number (prot),
  678.  * and the port (port) on which it awaits service request.  The 
  679.  * procedure returns success whose value is TRUE if the procedure
  680.  * successfully established the mapping and FALSE otherwise.  The
  681.  * procedure will refuse to establish a mapping if one already exists
  682.  * for the tuple [prog, vers, prot].
  683.  */
  684. 1. PMAPPROC_SET (prog, vers, prot, port) returns (success)
  685.     unsigned prog;
  686.     unsigned vers;
  687.     unsigned prot;
  688.     unsigned port;
  689.     boolean success;
  690. X.LE
  691. X.LS 0
  692. /*
  693.  * Procedure 2, Unsetting a mapping:
  694.  * When a program becomes unavailable, it should unregister itself
  695.  * with the port mapper program on the same machine.  The parameters
  696.  * and results have meanings identical to those of PMAPPROC_SET.
  697.  */
  698. 2. PMAPPROC_UNSET (prog, vers, dummy1, dummy2) returns (success)
  699.     unsigned prog;
  700.     unsigned vers;
  701.     unsigned dummy1;  /* this value is always ignored */
  702.     unsigned dummy2;  /* this value is always ignored */
  703.     boolean success;
  704. X.LE
  705. X.LS 0
  706. /*
  707.  * Procedure 3, looking-up a mapping:
  708.  * Given a program number (prog), version number (vers) and
  709.  * transport protocol number (prot), this procedure returns the port
  710.  * number on which the program is awaiting call requests.  A port
  711.  * value of zeros means that the program has not been registered.
  712.  */
  713. 3. PMAPPROC_GETPORT (prog, vers, prot, dummy) returns (port)
  714.     unsigned prog;
  715.     unsigned vers;
  716.     unsigned prot;
  717.     unsigned dummy;  /* this value is always ignored */
  718.     unsigned port;  /* zero means the program is not registered */
  719. X.LE
  720. X.LS 0
  721. /*
  722.  * Procedure 4, dumping the mappings:
  723.  * This procedure enumerates all entries in the port mapper's database.
  724.  * The procedure takes no parameters and returns a ``list'' of
  725.  * [program, version, prot, port] values.
  726.  */
  727. 4. PMAPPROC_DUMP () returns (maplist)
  728.     struct maplist {
  729.         union switch (boolean) {
  730.             FALSE: struct { /* void, end of list */ };
  731.             TRUE: struct {
  732.                 unsigned prog;
  733.                 unsigned vers;
  734.                 unsigned prot;
  735.                 unsigned port;
  736.                 struct maplist the_rest;
  737.             };
  738.         };
  739.     } maplist;
  740. X.LE
  741. X.LS 0
  742. /*
  743.  * Procedure 5, indirect call routine:
  744.  * The procedures allows a caller to call another remote procedure
  745.  * on the same machine without knowing the remote procedure's port
  746.  * number.  Its intended use is for supporting broadcasts to arbitrary
  747.  * remote programs via the well-known port mapper's port.  The parameters
  748.  * prog, vers, proc, and the bytes of args are the program number,
  749.  * version number, procedure number, and  parameters the the remote
  750.  * procedure.
  751.  * 
  752.  * NB: 
  753.  * 1. This procedure only sends a response if the procedure was
  754.  * successfully executed and is silent (No response) otherwise.
  755.  * 2. The port mapper communicates with the remote program via
  756.  * UDP/IP only.
  757.  * 
  758.  * The procedure returns the port number of the remote program and
  759.  * the bytes of results are the results of the remote procedure.
  760.  */
  761. 5. PMAPPROC_CALLIT (prog, vers, proc, args) returns (port, results)
  762.     unsigned prog;
  763.     unsigned vers;
  764.     unsigned proc;
  765.     string args<>;
  766.     unsigned port;
  767.     string results<>;
  768. X.LE
  769. !Funky!Stuff!
  770. echo x - rpcinfo.8
  771. sed 's/^X//' >rpcinfo.8 <<'!Funky!Stuff!'
  772. X.\" @(#)rpcinfo.8 1.1 85/02/25 SMI;
  773. X.TH RPCINFO 8 "1 February 1985"
  774. X.SH NAME
  775. rpcinfo \- report RPC information
  776. X.SH SYNOPSIS
  777. X.B "rpcinfo \-p"
  778. [ host ]
  779. X.br
  780. X.B "rpcinfo \-u"
  781. host program-number version-number
  782. X.br
  783. X.B "rpcinfo \-t"
  784. host program-number version-number
  785. X.SH DESCRIPTION
  786. X.I Rpcinfo
  787. makes an RPC call to an RPC server and reports what it finds.
  788. X.SH OPTIONS
  789. X.TP
  790. X.B \-p
  791. Probe the portmapper on
  792. X.IR host ,
  793. and print a list of all registered RPC programs.
  794. If 
  795. X.I host
  796. is not specified, it defaults to the value returned by
  797. X.IR hostname (1).
  798. X.TP
  799. X.B \-u
  800. Make an RPC call to procedure 0 of
  801. X.I program-number
  802. using UDP, and report whether a response was received.
  803. X.TP
  804. X.B \-t
  805. Make an RPC call to procedure 0 of
  806. X.I program-number
  807. using TCP, and report whether a response was received.
  808. X.SH "SEE ALSO"
  809. X.I "RPC Reference Manual,"
  810. portmap(8)
  811. !Funky!Stuff!
  812. echo x - tmac.sun
  813. sed 's/^X//' >tmac.sun <<'!Funky!Stuff!'
  814. X.\" @(#)tmac.sun 1.1 84/12/21 SMI; The Sun Macro Package
  815. X.ds // /usr/lib/ms/
  816. X.    \" IZ - initialize (before text begins)
  817. X.de IZ
  818. X.nr FM 1i
  819. X.nr YY -\\n(FMu
  820. X.nr XX 0 1
  821. X.nr IP 0
  822. X.nr PI 4n
  823. X.nr QI 5n
  824. X.nr FI 2n
  825. X.nr I0 \\n(PIu
  826. X.if n .nr PD 1v
  827. X.if t .nr PD .5v
  828. X.if n .nr DD 1v
  829. X.if t .nr DD .5v
  830. X.nr PS 11
  831. X.nr VS 13
  832. X.ps \\n(PS
  833. X.vs \\n(VSp
  834. X.nr dP 1
  835. X.nr dV 1
  836. X.nr ML 3v
  837. X.nr IR 0
  838. X.nr TB 0
  839. X.nr SJ \\n(.j
  840. X.if \\nO .po \\nOu
  841. X.nr PO \\n(.ou
  842. X.nr LL 6.5i
  843. X.ll \\n(LLu
  844. X.lt 6.5i
  845. X.ev 1
  846. X.nr FL 6i
  847. X.ll \\n(FLu
  848. X.ps 8
  849. X.vs 10p
  850. X.ev
  851. X.ds CH - \\\\n(PN -
  852. X.if n .ds CF \\*(DY
  853. X.wh 0 NP
  854. X.wh -\\n(FMu FO
  855. X.ch FO 16i
  856. X.wh -\\n(FMu FX
  857. X.ch FO -\\n(FMu
  858. X.wh -\\n(FMu/2u BT
  859. X..
  860. X.    \" RT - reset (at new paragraph)
  861. X.de RT
  862. X.if !\\n(1T .BG
  863. X.if !\\n(IK .if !\\n(IF .if !\\n(IX .if !\\n(BE .di
  864. X.if \\n(TM .ls 2
  865. X.ce 0
  866. X.ul 0
  867. X.if \\n(QP \{\
  868. X.    ll +\\n(QIu
  869. X.    in -\\n(QIu
  870. X.    nr QP -1
  871. X.\}
  872. X.if \\n(NX<=1 .if !\\n(AJ .ll \\n(LLu
  873. X.if !\\n(IF \{\
  874. X.    ps \\n(PS
  875. X.    if \\n(VS>=40 .vs \\n(VSu
  876. X.    if \\n(VS<=39 .vs \\n(VSp
  877. X.\}
  878. X.if !\\n(IP .nr I0 \\n(PIu
  879. X.if \\n(IP \{\
  880. X.    in -\\n(I\\n(IRu
  881. X.    nr IP -1
  882. X.\}
  883. X.ft 1
  884. X.TA
  885. X.fi
  886. X..
  887. X.    \" TA - set default tabs
  888. X.de TA
  889. X.if n .ta 8n 16n 24n 32n 40n 48n 56n 64n 72n 80n
  890. X.if t .ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n 65n 70n 75n
  891. X..
  892. X.    \" BG - begin (at first paragraph)
  893. X.de BG
  894. X.br
  895. X.nr YE 1
  896. X.di
  897. X.ce 0
  898. X.nr KI 0
  899. X.hy 14
  900. X.nr 1T 1
  901. X.S\\n(ST
  902. X.rm S0 S1 S2 SY TX AX WT RP
  903. X.\"redefs
  904. X.de TL
  905. X.ft 3
  906. X.ce 99
  907. X.sp
  908. X.LG
  909. \\..
  910. X.de AU
  911. X.ft 2
  912. X.if n .ul 0
  913. X.ce 99
  914. X.sp
  915. X.NL
  916. \\..
  917. X.de AI
  918. X.ft 1
  919. X.if n .ul 0
  920. X.ce 99
  921. X.if n .sp
  922. X.if t .sp .5
  923. X.NL
  924. \\..
  925. X.RA
  926. X.rn FJ FS
  927. X.rn FK FE
  928. X.nf
  929. X.ev 1
  930. X.ps \\n(PS-2
  931. X.vs \\n(.s+2p
  932. X.ev
  933. X.if !\\n(KG .nr FP 0
  934. X.nr KG 0
  935. X.if \\n(FP \{\
  936. X.    FS
  937. X.    FG
  938. X.    FE
  939. X.\}
  940. X.br
  941. X.if \\n(TV .if n .sp 2
  942. X.if \\n(TV .if t .sp 1
  943. X.fi
  944. X.ll \\n(LLu
  945. X..
  946. X.       \" RA - redefine abstract
  947. X.de RA
  948. X.de AB
  949. X.br
  950. X.if !\\n(1T .BG
  951. X.ce
  952. X.sp
  953. X.if !\\n(.$ ABSTRACT
  954. X.if \\n(.$ .if !\\$1no \\$1
  955. X.if !\\n(.$ .sp
  956. X.if \\n(.$ .if !\\$1no .sp
  957. X.sp
  958. X.nr AJ 1
  959. X.in +\\n(.lu/12u
  960. X.ll -\\n(.lu/12u
  961. X.RT
  962. X.if \\n(TM .ls 1
  963. \\..
  964. X.de AE
  965. X.nr AJ 0
  966. X.br
  967. X.in 0
  968. X.ll \\n(LLu
  969. X.if \\n(VS>=40 .vs \\n(VSu
  970. X.if \\n(VS<=39 .vs \\n(VSp
  971. X.if \\n(TM .ls 2
  972. \\..
  973. X..
  974. X.       \" RP - released paper format
  975. X.de RP
  976. X.nr ST 2
  977. X.if \\$1no .nr ST 1
  978. X.pn 0
  979. X.br
  980. X..
  981. X.       \" TL - source file for cover sheet
  982. X.de TL
  983. X.rn TL @T
  984. X.so \*(//ms.cov
  985. X.TL
  986. X.rm @T
  987. X..
  988. X.    \" Paragraph Depth
  989. X.de PD
  990. X.if t .nr PD .5v
  991. X.if n .nr PD 1v
  992. X.if !\\$1 .nr PD \\$1v
  993. X..
  994. X.    \" PP - regular paragraph
  995. X.de PP
  996. X.RT
  997. X.if \\n(1T .sp \\n(PDu
  998. X.ne 1.1
  999. X.ti +\\n(PIu
  1000. X..
  1001. X.    \" LP - left paragraph
  1002. X.de LP
  1003. X.RT
  1004. X.if \\n(1T .sp \\n(PDu
  1005. X.ne 1.1
  1006. X.ti \\n(.iu
  1007. X..
  1008. X.    \" IP - indented paragraph
  1009. X.de IP
  1010. X.RT
  1011. X.if \\n(1T .sp \\n(PDu
  1012. X.ne 1.1
  1013. X.if !\\n(IP .nr IP +1
  1014. X.if \\n(.$-1 .nr I\\n(IR \\$2n
  1015. X.in +\\n(I\\n(IRu
  1016. X.ta \\n(I\\n(IRu
  1017. X.if \\n(.$ \{\
  1018. X.ds HT \&\\$1\^\^\^
  1019. X.ti -\\n(I\\n(IRu
  1020. \\*(HT\t\c
  1021. X.if \w\\*(HTu>(\\n(I\\n(IRu) .br
  1022. X.\}
  1023. X..
  1024. X.    \" XP - exdented paragraph
  1025. X.de XP
  1026. X.RT
  1027. X.if \\n(1T .sp \\n(PDu
  1028. X.ne 1.1
  1029. X.if !\\n(IP .nr IP +1
  1030. X.in +\\n(I\\n(IRu
  1031. X.ti -\\n(I\\n(IRu
  1032. X..
  1033. X.    \" QP - quote paragraph
  1034. X.de QP
  1035. X.ti \\n(.iu
  1036. X.RT
  1037. X.if \\n(1T .sp \\n(PDu
  1038. X.ne 1.1
  1039. X.nr QP 1
  1040. X.in +\\n(QIu
  1041. X.ll -\\n(QIu
  1042. X.ti \\n(.iu
  1043. X.if \\n(TM .ls 1
  1044. X..
  1045. X.    \" SH - section header
  1046. X.de SH
  1047. X.ti \\n(.iu
  1048. X.RT
  1049. X.if \\n(1T .sp
  1050. X.RT
  1051. X.ne 3.1
  1052. X.ft B
  1053. X..
  1054. X.    \"                 $1 = C: As Chapter Heading; TOC Entry
  1055. X.    \" UH - UnNumbered $1 = M: As Chapter Heading; no TOC entry
  1056. X.    \"      Headings   $1 = H: Centered Heading; no TOC entry
  1057. X.    \"                 $1 = HC: Centered Heading; TOC Entry
  1058. X.    \"                 $1 = S: Left Adjusted Heading; no TOC entry
  1059. X.    \"                 $1 = SC: Left Adjusted Heading; TOC Entry
  1060. X.    \"                 $1 = CONTENTS: Setup for Table of Contents
  1061. X.    \"                 $1 = INDEX: Setup for Index
  1062. X.    \"                 $1 = TABLES: Setup for List of Tables
  1063. X.    \"                 $1 = FIGURES: Setup for List of Figures
  1064. X.de UH
  1065. X.SH
  1066. X.if '\\$1'C' \{\
  1067. X.ne 1.0i+2v
  1068. X.ad c
  1069. X.ps 18
  1070. X.vs 24
  1071. \\&
  1072. X.sp 0.5i
  1073. \\$2
  1074. X.sp 0.5i
  1075. X.ps
  1076. X.vs
  1077. X.ad b
  1078. X.R
  1079. \}
  1080. X.if '\\$1'M' \{\
  1081. X.ne 1.0i+2v
  1082. X.ad c
  1083. X.ps 18
  1084. X.vs 24
  1085. \\&
  1086. X.sp 0.5i
  1087. \\$2
  1088. X.sp 0.5i
  1089. X.ps
  1090. X.vs
  1091. X.ad b
  1092. X.R
  1093. \}
  1094. X.if '\\$1'H' \{\
  1095. X.ne 0.7i+2v
  1096. X.ad c
  1097. X.if \\n(NS=2 .ft B
  1098. X.if \\n(NS=2 .ps 14p
  1099. X.if \\n(NS=2 .vs 18p
  1100. \\&
  1101. X.sp 0.25i
  1102. \\$2
  1103. X.sp 0.1i
  1104. X.ad b
  1105. X.R \}
  1106. X.if '\\$1'S' \{\
  1107. X.ne 0.2i+2v
  1108. X.if \\n(NS=3 .ft I
  1109. X.if \\n(NS=3 .ps 12p
  1110. X.if \\n(NS=3 .vs 15p
  1111. \\&
  1112. X.sp 0.1i
  1113. \\$2
  1114. X.sp 0.1i
  1115. X.R \}
  1116. X.if '\\$1'HC' \{\
  1117. X.ne 0.7i+2v
  1118. X.ad c
  1119. X.if \\n(NS=2 .ft B
  1120. X.if \\n(NS=2 .ps 14p
  1121. X.if \\n(NS=2 .vs 18p
  1122. \\&
  1123. X.sp 0.25i
  1124. \\$2
  1125. X.sp 0.1i
  1126. X.ad b
  1127. X.R \}
  1128. X.if '\\$1'SC' \{\
  1129. X.ne 0.2i+2v
  1130. X.if \\n(NS=3 .ft I
  1131. X.if \\n(NS=3 .ps 12p
  1132. X.if \\n(NS=3 .vs 15p
  1133. \\&
  1134. X.sp 0.1i
  1135. \\$2
  1136. X.sp 0.1i
  1137. X.R \}
  1138. X.if '\\$1'C'  .if \\n(IK  \!.tm .CE U "\\$2" \\\\n(PN \\n(dT \\n(H1
  1139. X.if '\\$1'C'  .if !\\n(IK .tm .CE U "\\$2" \\n(PN \\n(dT \\n(H1
  1140. X.if '\\$1'HC' .if \\n(IK  \!.tm .CE UH "\\$2" \\\\n(PN \\n(dT \\n(H1
  1141. X.if '\\$1'HC' .if !\\n(IK .tm .CE UH "\\$2" \\n(PN \\n(dT \\n(H1
  1142. X.if '\\$1'SC' .if \\n(IK  \!.tm .CE UH "\\$2" \\\\n(PN \\n(dT \\n(H1
  1143. X.if '\\$1'SC' .if !\\n(IK .tm .CE UH "\\$2" \\n(PN \\n(dT \\n(H1
  1144. X.if '\\$1'CONTENTS' .nr cF 1
  1145. X.if '\\$1'TABLES' .nr cF 1
  1146. X.if '\\$1'FIGURES' .nr cF 1
  1147. X.if '\\$1'INDEX' .nr cF 1
  1148. X.if \\n(cF \{\
  1149. X.LP
  1150. X.EH ''''
  1151. X.OH ''''
  1152. X.EF ''\- \\\\\\\\n(PN \-''
  1153. X.OF ''\- \\\\\\\\n(PN \-''
  1154. X.if \\nP .pn \\nP+1
  1155. X.if \\nP .nr PN \\nP
  1156. X.nf
  1157. X.if '\\$1'CONTENTS' .ds hD Contents
  1158. X.if '\\$1'TABLES' .ds hD Tables
  1159. X.if '\\$1'FIGURES' .ds hD Figures
  1160. X.if '\\$1'INDEX' .ds hD Index
  1161. X.ps 11
  1162. X.nr PS 11
  1163. X.vs 14
  1164. X.nr VS 14
  1165. X.ne 1.0i+2v
  1166. \\&
  1167. X.sp 0.5i
  1168. X.ce
  1169. X.ps 18
  1170. X.vs 24
  1171. X.ft B
  1172. \\*(hD
  1173. X.sp 0.5i
  1174. X.R
  1175. X.ps 11
  1176. X.nr PS 11
  1177. X.vs 14
  1178. X.nr VS 14
  1179. X.af PN i
  1180. X.if !'\\$1'INDEX' \{\
  1181. X.ll -0.5i
  1182. X.in +0.5i \}
  1183. X.if '\\$1'INDEX' \{\
  1184. X.ps 10
  1185. X.nr PS 10
  1186. X.vs 12
  1187. X.nr VS 12
  1188. X.2C\}\}
  1189. X..
  1190. X.    \" SE - Make special entry in the Contents File
  1191. X.de SE
  1192. X.if \\n(IK \!.tm SE \\$1\t\\$2\t\\$3\t\\$4\t\\$5\t\\$6\t\\$7\t\\$8\t\\$9\t\\\\n(PN\t\\n(dT\t\\n(H1
  1193. X.if !\\n(IK .tm SE \\$1\t\\$2\t\\$3\t\\$4\t\\$5\t\\$6\t\\$7\t\\$8\t\\$9\t\\n(PN\t\\n(dT\t\\n(H1
  1194. X..
  1195. X.    \" H - Header - $1=level, $2=text
  1196. X.    \" $1: [1-5]=levels, C=chapter, A=appendix, PA=paperappendix
  1197. X.de H
  1198. X.ti \\n(.iu
  1199. X.RT
  1200. X.if \\n(1T .sp
  1201. X.RT
  1202. X.ne 3.1
  1203. X.ft B
  1204. X.nr NS \\$1
  1205. X.if '\\$1'C' .nr NS 1
  1206. X.if '\\$1'C' .nr dT 1
  1207. X.if '\\$1'A' .nr NS 1
  1208. X.if '\\$1'A' .nr dT 1
  1209. X.if '\\$1'PA' .nr NS 1
  1210. X.if \\n(NS=1 .if !'\\$1'1' .if !'\\$1'PA'\{\
  1211. X.if \\nC .nr H1 \\nC-1
  1212. X.nr C 0
  1213. X.nr T1 0
  1214. X.nr F1 0
  1215. X.bp 1 \}
  1216. X.if '\\$1'A' .if !\\n(aP \{\
  1217. X.nr aP 1
  1218. X.nr H1 0
  1219. X.af H1 A \}
  1220. X.if '\\$1'PA' .if !\\n(aP \{\
  1221. X.nr aP 1
  1222. X.nr H1 0
  1223. X.af H1 A \}
  1224. X.af PN 1
  1225. X.nr H\\n(NS +1
  1226. X.if !\\n(NS-4 .nr H5 0
  1227. X.if !\\n(NS-3 .nr H4 0
  1228. X.if !\\n(NS-2 .nr H3 0
  1229. X.if !\\n(NS-1 .nr H2 0
  1230. X.if \\n(NS=1 .ds MT \\$2
  1231. X.if \\n(NS=1 .if !'\\$1'1' .if !'\\$1'PA'\{\
  1232. X.ad c
  1233. X.ps 18
  1234. X.vs 24
  1235. \\&
  1236. X.sp 0.5i
  1237. X.if '\\$1'C' .ds hS Chapter \\n(H1
  1238. X.if '\\$1'A' .ds hS Appendix \\n(H1
  1239. \\*(hS
  1240. X.sp
  1241. \\$2
  1242. X.sp 0.5i
  1243. X.ps
  1244. X.vs
  1245. X.ad b \}
  1246. X.if \\n(NS>=1 .if !'\\$1'C' .if !'\\$1'A' .if !'\\$1'PA'\{\
  1247. X.sp 10p
  1248. X.ne 33p+20p
  1249. X.ds SN \\n(H1.
  1250. X.if \\n(NS>1 .as SN \\n(H2.
  1251. X.if \\n(NS>2 .as SN \\n(H3.
  1252. X.if \\n(NS>3 .as SN \\n(H4.
  1253. X.if \\n(NS>4 .as SN \\n(H5.
  1254. X.if \\n(NS=1 .ft B
  1255. X.if \\n(NS=1 .ps 16p
  1256. X.if \\n(NS=1 .vs 18p
  1257. X.if \\n(NS=2 .ft B
  1258. X.if \\n(NS=2 .ps 14p
  1259. X.if \\n(NS=2 .vs 18p
  1260. X.if \\n(NS=3 .ft I
  1261. X.if \\n(NS=3 .ps 12p
  1262. X.if \\n(NS=3 .vs 15p
  1263. X.if \\n(NS=4 .ft I
  1264. X.if \\n(NS=4 .ps 11p
  1265. X.if \\n(NS=4 .vs 15p
  1266. X.if \\n(NS=5 .ft R
  1267. X.if \\n(NS=5 .ps \\n(PSp
  1268. X.if \\n(NS=5 .vs \\n(VSp
  1269. X.in +\\w'\\*(SN\\ \\ 'u
  1270. X.ta \\w'\\*(SN\\ \\ 'u
  1271. X.ti -\\w'\\*(SN\\ \\ 'u
  1272. \\*(SN\\ \\ \t\c
  1273. \&\\$2
  1274. X.in
  1275. X.ps
  1276. X.vs
  1277. X.sp 7p \}
  1278. X.if '\\$1'PA'\{\
  1279. X.sp 13p
  1280. X.ne 33p+20p
  1281. X.ft B
  1282. X.ps 16p
  1283. X.vs 18p
  1284. X.in +\\w'\\*(SN\\ \\ 'u
  1285. X.ta \\w'\\*(SN\\ \\ 'u
  1286. X.ti -\\w'\\*(SN\\ \\ 'u
  1287. X.ds SN Appendix \\n(H1.
  1288. X.ti -\\w'\\*(SN\\ \\ 'u
  1289. \\*(SN\\ \\ \t\c
  1290. \&\\$2
  1291. X.in
  1292. X.ps
  1293. X.vs
  1294. X.sp 7p \}
  1295. X.R
  1296. X.if '\\$1'C' .if  \\n(IK \!.tm .CE C "\\$2" \\\\n(PN \\n(dT \\n(H1
  1297. X.if '\\$1'C' .if !\\n(IK .tm .CE C "\\$2" \\n(PN \\n(dT \\n(H1
  1298. X.if '\\$1'A' .if  \\n(IK \!.tm .CE A "\\$2" \\\\n(PN \\n(dT \\n(H1
  1299. X.if '\\$1'A' .if !\\n(IK .tm .CE A "\\$2" \\n(PN \\n(dT \\n(H1
  1300. X.if '\\$1'1' .if  \\n(IK \!.tm .CE N "\\$2" \\\\n(PN \\n(dT \\n(H1
  1301. X.if '\\$1'1' .if !\\n(IK .tm .CE N "\\$2" \\n(PN \\n(dT \\n(H1
  1302. X.if '\\$1'PA' .if  \\n(IK \!.tm .CE N "\\$2" \\\\n(PN \\n(dT \\n(H1
  1303. X.if '\\$1'PA' .if !\\n(IK .tm .CE N "\\$2" \\n(PN \\n(dT \\n(H1
  1304. X.if \\n(NS>1 .if  \\n(IK \!.tm .CE N "\\$2" \\\\n(PN \\n(dT \\n(H1 \\n(H2 \\n(H3 \\n(H4 \\n(H5
  1305. X.if \\n(NS>1 .if !\\n(IK .tm .CE N "\\$2" \\n(PN \\n(dT \\n(H1 \\n(H2 \\n(H3 \\n(H4 \\n(H5
  1306. X..
  1307. X.    \" TN - Table Caption
  1308. X.de TN
  1309. X.nr T1 +1
  1310. X.sp
  1311. X.if \\n(dT  .ds tS Table \\n(H1-\\n(T1: \\$1
  1312. X.if !\\n(dT .ds tS Table \\n(T1: \\$1
  1313. X.ce
  1314. \\*(tS
  1315. X.sp
  1316. X.ie \\n(IK \!.tm .CE T "\\$1" \\\\n(PN \\n(dT \\n(H1 \\n(T1
  1317. X.el .tm .CE T "\\$1" \\n(PN \\n(dT \\n(H1 \\n(T1
  1318. X..
  1319. X.    \" FN - Figure Caption
  1320. X.de FN
  1321. X.nr F1 +1
  1322. X.sp
  1323. X.if \\n(dT  .ds tS Figure \\n(H1-\\n(F1: \\$1
  1324. X.if !\\n(dT .ds tS Figure \\n(F1: \\$1
  1325. X.ce
  1326. \\*(tS
  1327. X.sp
  1328. X.ie \\n(IK \!.tm .CE F "\\$1" \\\\n(PN \\n(dT \\n(H1 \\n(F1
  1329. X.el .tm .CE F "\\$1" \\n(PN \\n(dT \\n(H1 \\n(F1
  1330. X..
  1331. X.    \" CE - table of contents entry
  1332. X.    \" $1 : header type;  $2 : text;  $3 : page number;  $4 : document type
  1333. X.    \" $5 : chapter number;  $6, 7, 8 : additional numbers
  1334. X.de CE
  1335. X.fi
  1336. X.na
  1337. X.nh
  1338. X.rm lS
  1339. X.ds rS \\$3
  1340. X.if !'\\$4'0' .ds rS \\$5-\\$3
  1341. X.if '\\$1'N' .if '\\$6\\$7\\$8\\$9'' .ds rS \fB\\$3\fP
  1342. X.if '\\$1'C' .if !'\\$5'' .if !'\\$5'0' .ds rS \fB\\$5-\\$3\fP
  1343. X.if '\\$1'A' .if !'\\$5'' .if !'\\$5'0' .ds rS \fB\\$5-\\$3\fP
  1344. X.if '\\$1'T' .if '\\$4'0' .ds lS Table \\$6\ \ 
  1345. X.if '\\$1'F' .if '\\$4'0' .ds lS Figure \\$6\ \ 
  1346. X.if '\\$1'T' .if '\\$4'1' .ds lS Table \\$5-\\$6\ \ 
  1347. X.if '\\$1'F' .if '\\$4'1' .ds lS Figure \\$5-\\$6\ \ 
  1348. X.if '\\$1'A' .ds lS \fBAppendix \\$5\fP\ \ 
  1349. X.if '\\$1'C' .ds lS \fBChapter \\$5\fP\ \ 
  1350. X.if '\\$1'N' .ds lS \\$5.\ \ 
  1351. X.if '\\$1'N' .if '\\$6\\$7\\$8\\$9'' .ds lS \fB\\$5.\fP\ \ 
  1352. X.if '\\$1'N' .if !'\\$6'' .if !'\\$6'0' .ds lS "    \\$5.\\$6.\ \ 
  1353. X.if '\\$1'N' .if !'\\$7'' .if !'\\$7'0' .ds lS "        \\$5.\\$6.\\$7.\ \ 
  1354. X.if '\\$1'N' .if !'\\$8'' .if !'\\$8'0' .ds lS "            \\$5.\\$6.\\$7.\\$8.\ \ 
  1355. X.if '\\$1'N' .if !'\\$9'' .if !'\\$9'0' .ds lS "                \\$5.\\$6.\\$7.\\$8.\\$9\ \ 
  1356. X.if '\\$1'N' .if '\\$6\\$7\\$8\\$9'' .ne 3
  1357. X.if '\\$1'U' .ne 3
  1358. X.if '\\$1'A' .ne 3
  1359. X.if '\\$1'C' .ne 3
  1360. X.if '\\$1'N' .if '\\$6\\$7\\$8\\$9'' .sp
  1361. X.if '\\$1'U' .sp
  1362. X.if '\\$1'A' .sp
  1363. X.if '\\$1'C' .sp
  1364. X.\" Reduce line length, save section # width, increase indent:
  1365. X.nr $l \\n(.l \"save line length
  1366. X.ll -8n  \"try 8 ens for now
  1367. X.nr wN \\w\\*(lSu \"wN = width of section number
  1368. X.in +\\n(wNu
  1369. X.\" Output number (lS) and text ($2) with short line length
  1370. X.ti -\\n(wNu  \"don't indent first line
  1371. X.vs \\n(.sp+2p  \"normalize spacing
  1372. X.\" We need at least two lines for this 'moving-backward' hack to work:
  1373. X.ne 2v
  1374. \&\\*(lS\\$2
  1375. X.\"Restore line length and indent
  1376. X.ll
  1377. X.in
  1378. X.\"  Go back to previous line, output leader & page number:
  1379. X.nf  \"leaders only work right in no-fill mode!
  1380. X.\" If last line broke, we have to correct for indent:
  1381. X.if (\\w\\*(lS\\$2u)<=(\\n(.lu-\\n(.iu-8n) .nr wN 0
  1382. X.ll -\\n(wNu
  1383. X.ti +\\n(wNu
  1384. X.ta \\n(.lu-\\n(.iu-5nR \\n(.lu-\\n(.iuR
  1385. X.sp -1v
  1386. X.vs \"(now can restore original vertical spacing)
  1387. \\h'|\\n(.nu+.5n'\s-3\a\s+3\t\\*(rS
  1388. X.\"Restore line length (again):
  1389. X.ll
  1390. X..
  1391. X.    \" NH - numbered header
  1392. X.de NH
  1393. X.SH
  1394. X.nr NS \\$1
  1395. X.if !\\n(.$ .nr NS 1
  1396. X.if !\\n(NS .nr NS 1
  1397. X.nr H\\n(NS +1
  1398. X.if !\\n(NS-4 .nr H5 0
  1399. X.if !\\n(NS-3 .nr H4 0
  1400. X.if !\\n(NS-2 .nr H3 0
  1401. X.if !\\n(NS-1 .nr H2 0
  1402. X.if !\\$1 .if \\n(.$ .nr H1 1
  1403. X.if \\$1S \{\
  1404. X.    nr NS \\n(.$-1
  1405. X.    nr H1 \\$2
  1406. X.    nr H2 \\$3
  1407. X.    nr H3 \\$4
  1408. X.    nr H4 \\$5
  1409. X.    nr H5 \\$6
  1410. X.\}
  1411. X.ds SN \\n(H1.
  1412. X.if \\n(NS-1 .as SN \\n(H2.
  1413. X.if \\n(NS-2 .as SN \\n(H3.
  1414. X.if \\n(NS-3 .as SN \\n(H4.
  1415. X.if \\n(NS-4 .as SN \\n(H5.
  1416. \\*(SN
  1417. X..
  1418. X.    \" LS - listing start
  1419. X.de LS
  1420. X.ie \\$1no .ID \\$2
  1421. X.el .DS I \\$1
  1422. X.nr PQ \\n(.f
  1423. X.ft L
  1424. X.ps -\\n(dP
  1425. X.vs -\\n(dV
  1426. X.nr @ \\w'x'u*8
  1427. X.if \\n(.$ .nr @ \\w'x'u*\\$2
  1428. X.if \\n(.$ .if \\$1no .nr @ \\w'x'u*\\$3
  1429. X.ta \\n@u +\\n@u +\\n@u +\\n@u +\\n@u +\\n@u +\\n@u +\\n@u +\\n@u +\\n@u
  1430. X..
  1431. X.    \" LE - listing end
  1432. X.de LE
  1433. X.ft \\n(PQ
  1434. X.ps \\n(PS
  1435. X.if \\n(VS>=40 .vs \\n(VSu
  1436. X.if \\n(VS<=39 .vs \\n(VSp
  1437. X.DE
  1438. X..
  1439. X.    \" DS - display with keep (L=left I=indent C=center B=block)
  1440. X.de DS
  1441. X.KS
  1442. X.\\$1D \\$2 \\$1
  1443. X.ft 1
  1444. X.ps \\n(PS
  1445. X.if \\n(VS>=40 .vs \\n(VSu
  1446. X.if \\n(VS<=39 .vs \\n(VSp
  1447. X..
  1448. X.de D
  1449. X.ID \\$1
  1450. X..
  1451. X.    \" ID - indented display with no keep
  1452. X.de ID
  1453. X.XD
  1454. X.if t .in +.5i
  1455. X.if n .in +8
  1456. X.if \\n(.$ .if !\\$1I .if !\\$1 \{\
  1457. X.    in \\n(OIu
  1458. X.    in +\\$1n
  1459. X.\}
  1460. X..
  1461. X.    \" LD - left display with no keep
  1462. X.de LD
  1463. X.XD
  1464. X..
  1465. X.    \" CD - centered display with no keep
  1466. X.de CD
  1467. X.XD
  1468. X.ce 999
  1469. X..
  1470. X.    \" XD - real display macro
  1471. X.de XD
  1472. X.nf
  1473. X.nr OI \\n(.i
  1474. X.sp \\n(DDu
  1475. X.if \\n(TM .ls 1
  1476. X..
  1477. X.    \" DE - end display of any kind
  1478. X.de DE
  1479. X.ce 0
  1480. X.if \\n(BD .DF
  1481. X.nr BD 0
  1482. X.in \\n(OIu
  1483. X.KE
  1484. X.if \\n(TM .ls 2
  1485. X.sp \\n(DDu
  1486. X.fi
  1487. X..
  1488. X.    \" BD - block display: center entire block
  1489. X.de BD
  1490. X.XD
  1491. X.nr BD 1
  1492. X.nf
  1493. X.in \\n(OIu
  1494. X.di DD
  1495. X..
  1496. X.    \" DF - finish block display
  1497. X.de DF
  1498. X.di
  1499. X.if \\n(dl>\\n(BD .nr BD \\n(dl
  1500. X.if \\n(BD<\\n(.l .in (\\n(.lu-\\n(BDu)/2u
  1501. X.nr EI \\n(.l-\\n(.i
  1502. X.ta \\n(EIuR
  1503. X.DD
  1504. X.in \\n(OIu
  1505. X..
  1506. X.    \" KS - begin regular keep
  1507. X.de KS
  1508. X.nr KN \\n(.u
  1509. X.if !\\n(IK .if !\\n(IF .KQ
  1510. X.nr IK +1
  1511. X..
  1512. X.    \" KQ - real keep processor
  1513. X.de KQ
  1514. X.br
  1515. X.nr KI \\n(.i
  1516. X.ev 2
  1517. X.TA
  1518. X.br
  1519. X.in \\n(KIu
  1520. X.ps \\n(PS
  1521. X.if \\n(VS>=40 .vs \\n(VSu
  1522. X.if \\n(VS<=39 .vs \\n(VSp
  1523. X.ll \\n(LLu
  1524. X.lt \\n(LTu
  1525. X.if \\n(NX>1 .ll \\n(CWu
  1526. X.if \\n(NX>1 .lt \\n(CWu
  1527. X.di KK
  1528. X.nr TB 0
  1529. X..
  1530. X.    \" KF - begin floating keep
  1531. X.de KF
  1532. X.nr KN \\n(.u
  1533. X.if !\\n(IK .FQ
  1534. X.nr IK +1
  1535. X..
  1536. X.    \" FQ - real floating keep processor
  1537. X.de FQ
  1538. X.nr KI \\n(.i
  1539. X.ev 2
  1540. X.TA
  1541. X.br
  1542. X.in \\n(KIu
  1543. X.ps \\n(PS
  1544. X.if \\n(VS>=40 .vs \\n(VSu
  1545. X.if \\n(VS<=39 .vs \\n(VSp
  1546. X.ll \\n(LLu
  1547. X.lt \\n(LTu
  1548. X.if \\n(NX>1 .ll \\n(CWu
  1549. X.if \\n(NX>1 .lt \\n(CWu
  1550. X.di KK
  1551. X.nr TB 1
  1552. X..
  1553. X.    \" KE - end keep
  1554. X.de KE
  1555. X.if \\n(IK .if !\\n(IK-1 .if !\\n(IF .RQ
  1556. X.if \\n(IK .nr IK -1
  1557. X..
  1558. X.    \" RQ - real keep release
  1559. X.de RQ
  1560. X.br
  1561. X.di
  1562. X.nr NF 0
  1563. X.if \\n(dn-\\n(.t .nr NF 1
  1564. X.if \\n(TC .nr NF 1
  1565. X.if \\n(NF .if !\\n(TB .sp 200
  1566. X.if !\\n(NF .if \\n(TB .nr TB 0
  1567. X.nf
  1568. X.rs
  1569. X.nr TC 5
  1570. X.in 0
  1571. X.ls 1
  1572. X.if !\\n(TB \{\
  1573. X.    ev
  1574. X.    br
  1575. X.    ev 2
  1576. X.    KK
  1577. X.\}
  1578. X.ls
  1579. X.ce 0
  1580. X.if !\\n(TB .rm KK
  1581. X.if \\n(TB .da KJ
  1582. X.if \\n(TB \!.KD \\n(dn
  1583. X.if \\n(TB .KK
  1584. X.if \\n(TB .di
  1585. X.nr TC \\n(TB
  1586. X.if \\n(KN .fi
  1587. X.in
  1588. X.ev
  1589. X..
  1590. X.    \" start picture
  1591. X.de PS
  1592. X.    \" $1 is height, $2 is width in units
  1593. X.if t .sp .3
  1594. X.in (\\n(.lu-\\$2u)/2u
  1595. X.ne \\$1u
  1596. X..
  1597. X.    \" end of picture
  1598. X.de PE
  1599. X.in
  1600. X.if t .sp .6
  1601. X..
  1602. X.    \" KD - keep redivert
  1603. X.de KD
  1604. X.nr KM 0
  1605. X.if \\n(.zKJ .nr KM 1
  1606. X.if \\n(KM \!.KD \\$1
  1607. X.if !\\n(KM .if \\n(.t<\\$1 .di KJ
  1608. X..
  1609. X.    \" EM - end macro (process leftover keep)
  1610. X.de EM
  1611. X.br
  1612. X.if !\\n(TB .if t .wh -1p CM
  1613. X.if \\n(TB \{\
  1614. \&\c
  1615. '    bp
  1616. X.    NP
  1617. X.    ch CM 160
  1618. X.\}
  1619. X..
  1620. X.de XK
  1621. X.nr TD 1
  1622. X.nf
  1623. X.ls 1
  1624. X.in 0
  1625. X.rn KJ KL
  1626. X.KL
  1627. X.rm KL
  1628. X.if \\n(.zKJ .di
  1629. X.nr TB 0
  1630. X.if \\n(.zKJ .nr TB 1
  1631. X.br
  1632. X.in
  1633. X.ls
  1634. X.fi
  1635. X.nr TD 0
  1636. X..
  1637. X.    \" NP - new page
  1638. X.de NP
  1639. X.if !\\n(LT .nr LT \\n(LLu
  1640. X.if \\n(FM+\\n(HM>=\\n(.p \{\
  1641. X.    tm HM + FM longer than page
  1642. X.    ab
  1643. X.\}
  1644. X.\".if t .CM
  1645. X.if !\\n(HM .nr HM 1i
  1646. X.po \\n(POu
  1647. X.nr PF \\n(.f
  1648. X.nr PX \\n(.s
  1649. X.ft 1
  1650. X.ps \\n(PS
  1651. 'sp \\n(HMu/2u
  1652. X.PT
  1653. 'sp |\\n(HMu
  1654. X.HD    \"undefined
  1655. X.ps \\n(PX
  1656. X.ft \\n(PF
  1657. X.nr XX 0 1
  1658. X.nr YY 0-\\n(FMu
  1659. X.ch FO 16i
  1660. X.ch FX 17i
  1661. X.ch FO -\\n(FMu
  1662. X.ch FX \\n(.pu-\\n(FMu
  1663. X.if \\n(MF .FV
  1664. X.nr MF 0
  1665. X.mk
  1666. X.os
  1667. X.ev 1
  1668. X.if !\\n(TD .if \\n(TC<5 .XK
  1669. X.nr TC 0
  1670. X.ev
  1671. X.nr TQ \\n(.i
  1672. X.nr TK \\n(.u
  1673. X.if \\n(IT \{\
  1674. X.    in 0
  1675. X.    nf
  1676. X.    TT
  1677. X.    in \\n(TQu
  1678. X.    if \\n(TK .fi
  1679. X.\}
  1680. X.ns
  1681. X.mk #T
  1682. X.if t .if \\n(.o+\\n(LL>7.54i .tm PO + LL wider than 7.54i
  1683. X..
  1684. X.    \" PT - page titles
  1685. X.de PT
  1686. X.lt \\n(LTu
  1687. X.pc %
  1688. X.nr PN \\n%
  1689. X.nr PT \\n%
  1690. X.if \\n(P1 .nr PT 2
  1691. X.if \\n(PT>1 .if !\\n(EH .if !\\n(OH .tl \\*(LH\\*(CH\\*(RH
  1692. X.if \\n(PT>1 .if \\n(OH .if o .tl \\*(O1
  1693. X.if \\n(PT>1 .if \\n(EH .if e .tl \\*(E2
  1694. X.lt \\n(.lu
  1695. X..
  1696. X.    \" OH - odd page header
  1697. X.de OH
  1698. X.nr OH 1
  1699. X.if !\\n(.$ .nr OH 0
  1700. X.ds O1 \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
  1701. X..
  1702. X.    \" EH - even page header
  1703. X.de EH
  1704. X.nr EH 1
  1705. X.if !\\n(.$ .nr EH 0
  1706. X.ds E2 \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
  1707. X..
  1708. X.    \" P1 - PT on 1st page
  1709. X.de P1
  1710. X.nr P1 1
  1711. X..
  1712. X.    \" FO - footer
  1713. X.de FO
  1714. X.rn FO FZ
  1715. X.if \\n(IT .nr T. 1
  1716. X.if \\n(IT .if !\\n(FC .T# 1
  1717. X.if \\n(IT .br
  1718. X.nr FC +1
  1719. X.if \\n(NX<2 .nr WF 0
  1720. X.nr dn 0
  1721. X.if \\n(FC<=1 .if \\n(XX .XF
  1722. X.rn FZ FO
  1723. X.nr MF 0
  1724. X.if \\n(dn .nr MF 1
  1725. X.if !\\n(WF .nr YY 0-\\n(FMu
  1726. X.if !\\n(WF .ch FO \\n(YYu
  1727. X.if !\\n(dn .nr WF 0
  1728. X.if \\n(FC<=1 .if !\\n(XX \{\
  1729. X.    if \\n(NX>1 .RC
  1730. X.    if \\n(NX<2 'bp
  1731. X.\}
  1732. X.nr FC -1
  1733. X.if \\n(ML .ne \\n(MLu
  1734. X..
  1735. X.    \" BT - bottom title
  1736. X.de BT
  1737. X.nr PF \\n(.f
  1738. X.nr PX \\n(.s
  1739. X.ft 1
  1740. X.ps \\n(PS
  1741. X.lt \\n(LTu
  1742. X.po \\n(POu
  1743. X.if \\n(TM .if \\n(CT \{\
  1744. X.    tl ''\\n(PN''
  1745. X.    nr CT 0
  1746. X.\}
  1747. X.if \\n% .if !\\n(EF .if !\\n(OF .tl \\*(LF\\*(CF\\*(RF
  1748. X.if \\n% .if \\n(OF .if o .tl \\*(O3
  1749. X.if \\n% .if \\n(EF .if e .tl \\*(E4
  1750. X.ft \\n(PF
  1751. X.ps \\n(PX
  1752. X..
  1753. X.    \" OF - odd page footer
  1754. X.de OF
  1755. X.nr OF 1
  1756. X.if !\\n(.$ .nr OF 0
  1757. X.ds O3 \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
  1758. X..
  1759. X.    \" EF - even page footer
  1760. X.de EF
  1761. X.nr EF 1
  1762. X.if !\\n(.$ .nr EF 0
  1763. X.ds E4 \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
  1764. X..
  1765. X.    \" 2C - double column
  1766. X.de 2C
  1767. X.MC
  1768. X..
  1769. X.    \" 1C - single column
  1770. X.de 1C
  1771. X.MC \\n(LLu
  1772. X.hy 14
  1773. X..
  1774. X.    \" MC - multiple columns, arg is col width
  1775. X.de MC
  1776. X.nr L1 \\n(LL*7/15
  1777. X.if \\n(.$ .nr L1 \\$1n
  1778. X.nr NQ \\n(LL/\\n(L1
  1779. X.if \\n(NQ<1 .nr NQ 1
  1780. X.if \\n(NQ>2 .if (\\n(LL%\\n(L1)=0 .nr NQ -1
  1781. X.if !\\n(1T \{\
  1782. X.    BG
  1783. X.    if n .sp 4
  1784. X.    if t .sp 2
  1785. X.\}
  1786. X.if !\\n(NX .nr NX 1
  1787. X.if !\\n(NX=\\n(NQ \{\
  1788. X.    RT
  1789. X.    if \\n(NX>1 .bp
  1790. X.    mk
  1791. X.    nr NC 1
  1792. X.    po \\n(POu
  1793. X.\}
  1794. X.if \\n(NQ>1 .hy 12
  1795. X.nr NX \\n(NQ
  1796. X.nr CW \\n(L1
  1797. X.ll \\n(CWu
  1798. X.nr FL \\n(CWu*11u/12u
  1799. X.if \\n(NX>1 .nr GW (\\n(LL-(\\n(NX*\\n(CW))/(\\n(NX-1)
  1800. X.nr RO \\n(CW+\\n(GW
  1801. X.ns
  1802. X..
  1803. X.de RC
  1804. X.if \\n(NC>=\\n(NX .C2
  1805. X.if \\n(NC<\\n(NX .C1
  1806. X.nr NC \\n(ND
  1807. X.if \\n(iL>0 .if !"\\*(iC"" \{\
  1808. X.if \\n(.i>0 .ti -\\n(.i
  1809. \\*(iC
  1810. X.ti -4 \}
  1811. X..
  1812. X.de C1
  1813. X.rt
  1814. X.po +\\n(ROu
  1815. X.nr ND \\n(NC+1
  1816. X.nr XX 0 1
  1817. X.if \\n(MF .FV
  1818. X.ch FX \\n(.pu-\\n(FMu
  1819. X.ev 1
  1820. X.if \\n(TB .XK
  1821. X.nr TC 0
  1822. X.ev
  1823. X.nr TQ \\n(.i
  1824. X.if \\n(IT .in 0
  1825. X.if \\n(IT .TT
  1826. X.if \\n(IT .in \\n(TQu
  1827. X.mk #T
  1828. X.ns
  1829. X..
  1830. X.de C2
  1831. X.po \\n(POu
  1832. 'bp
  1833. X.nr ND 1
  1834. X..
  1835. X.    \" RS - right shift
  1836. X.de RS
  1837. X.nr IS \\n(IP
  1838. X.RT
  1839. X.nr IP \\n(IS
  1840. X.if \\n(IP .in +\\n(I\\n(IRu
  1841. X.nr IR +1
  1842. X.nr I\\n(IR \\n(PIu
  1843. X.in +\\n(I\\n(IRu
  1844. X..
  1845. X.    \" RE - retreat left
  1846. X.de RE
  1847. X.nr IS \\n(IP
  1848. X.RT
  1849. X.nr IP \\n(IS
  1850. X.if \\n(IR .nr IR -1
  1851. X.if \\n(IP<=0 .in -\\n(I\\n(IRu
  1852. X..
  1853. X.    \" I - italic font
  1854. X.de I
  1855. X.nr PQ \\n(.f
  1856. X.if t .ft 2
  1857. X.ie \\$1 .if n .ul 999
  1858. X.el .if n .ul 1
  1859. X.if t .if !\\$1 \&\f\\n(PQ\\$3\fI\\$1\|\f\\n(PQ\\$2
  1860. X.if n .if \\n(.$=1 \&\\$1
  1861. X.if n .if \\n(.$>2 \&\\$3\c
  1862. X.if n .if \\n(.$>1 \&\\$1\c
  1863. X.if n .if \\n(.$>1 \&\\$2
  1864. X..
  1865. X.    \" B - bold font
  1866. X.de B
  1867. X.nr PQ \\n(.f
  1868. X.if t .ft 3
  1869. X.ie \\$1 .if n .ul 999
  1870. X.el .if n .ul 1
  1871. X.if t .if !\\$1 \&\f\\n(PQ\\$3\fB\\$1\f\\n(PQ\\$2
  1872. X.if n .if \\n(.$=1 \&\\$1
  1873. X.if n .if \\n(.$>2 \&\\$3\c
  1874. X.if n .if \\n(.$>1 \&\\$1\c
  1875. X.if n .if \\n(.$>1 \&\\$2
  1876. X..
  1877. X.    \" R - Roman font
  1878. X.de R
  1879. X.if n .ul 0
  1880. X.ft 1
  1881. X..
  1882. X.    \" L - listing font
  1883. X.de L
  1884. X.if n .ul
  1885. \%\&\\$3\fL\\$1\f1\&\\$2
  1886. X..
  1887. X.    \" LB - bold listing font
  1888. X.de LB
  1889. X.if n .ul
  1890. \%\&\\$3\f(LB\\$1\f1\&\\$2
  1891. X..
  1892. X.    \" UL - underline in troff
  1893. X.de UL
  1894. X.if t \\$1\l'|0\(ul'\\$2
  1895. X.if n .I \\$1 \\$2
  1896. X..
  1897. X.    \" SM - make text small
  1898. X.de SM
  1899. X.ps -2
  1900. X.if !"\\$1"" \\$3\&\\$1\\$2
  1901. X.if !"\\$1"" .ps +2
  1902. X..
  1903. X.    \" LG - larger
  1904. X.de LG
  1905. X.ps +2
  1906. X.if !"\\$1"" \\$3\&\\$1\\$2
  1907. X.if !"\\$1"" .ps -2
  1908. X..
  1909. X.    \" NL - normal
  1910. X.de NL
  1911. X.ps \\n(PS
  1912. X..
  1913. X.    \" combinations of Roman, italic, bold
  1914. X.de RI
  1915. \&\fR\\$1\fI\\$2\^\fR\\$3\fI\\$4\^\fR\\$5\fI\\$6\^\fR\\$7\fI\\$8\^\fR\\$9
  1916. X..
  1917. X.de RB
  1918. \&\fR\\$1\fB\\$2\fR\\$3\fB\\$4\fR\\$5\fB\\$6\fR\\$7\fB\\$8\fR\\$9
  1919. X..
  1920. X.de IR
  1921. \&\fI\\$1\^\fR\\$2\fI\\$3\^\fR\\$4\fI\\$5\^\fR\\$6\fI\\$7\^\fR\\$8\fI\\$9\^\fR
  1922. X..
  1923. X.de IB
  1924. \&\fI\\$1\^\fB\\$2\fI\\$3\^\fB\\$4\fI\\$5\^\fB\\$6\fI\\$7\^\fB\\$8\fI\\$9\^\fR
  1925. X..
  1926. X.de BR
  1927. \&\fB\\$1\fR\\$2\fB\\$3\fR\\$4\fB\\$5\fR\\$6\fB\\$7\fR\\$8\fB\\$9\fR
  1928. X..
  1929. X.de BI
  1930. \&\fB\\$1\fI\\$2\^\fB\\$3\fI\\$4\^\fB\\$5\fI\\$6\^\fB\\$7\fI\\$8\^\fB\\$9\fR
  1931. X..
  1932. X.    \" \** - numbered footnote
  1933. X.ds * \\*([.\\n+*\\*(.]
  1934. X.    \" FJ - replaces FS after cover
  1935. X.de FJ
  1936. 'ce 0
  1937. X.di
  1938. X.ev 1
  1939. X.ll \\n(FLu
  1940. X.da FF
  1941. X.br
  1942. X.if \\n(IF .tm Nested footnote
  1943. X.nr IF 1
  1944. X.if !\\n+(XX-1 .FA
  1945. X.if !\\n(MF .if !\\n(.$ .if \\n* .FP \\n*
  1946. X.if !\\n(MF .if \\n(.$ .FP \\$1 no
  1947. X..
  1948. X.    \" FK - replaces FE after cover
  1949. X.de FK
  1950. X.br
  1951. X.in 0
  1952. X.nr IF 0
  1953. X.di
  1954. X.ev
  1955. X.if !\\n(XX-1 .nr dn +\\n(.v
  1956. X.nr YY -\\n(dn
  1957. X.if !\\n(NX .nr WF 1
  1958. X.if \\n(dl>\\n(CW .nr WF 1
  1959. X.if (\\n(nl+\\n(.v)<=(\\n(.p+\\n(YY) .ch FO \\n(YYu
  1960. X.if (\\n(nl+\\n(.v)>(\\n(.p+\\n(YY) \{\
  1961. X.    if \\n(nl>(\\n(HM+1.5v) .ch FO \\n(nlu+\\n(.vu
  1962. X.    if \\n(nl+\\n(FM+1v>\\n(.p .ch FX \\n(.pu-\\n(FMu+2v
  1963. X.    if \\n(nl<=(\\n(HM+1.5v) .ch FO \\n(HMu+(4u*\\n(.vu)
  1964. X.\}
  1965. X..
  1966. X.    \" FS - begin footnote on cover
  1967. X.de FS
  1968. X.ev 1
  1969. X.br
  1970. X.ll \\n(FLu
  1971. X.da FG
  1972. X.if !\\n(.$ .if \\n* .FP \\n*
  1973. X.if \\n(.$ .FP \\$1 no
  1974. X..
  1975. X.    \" FE - end footnote on cover
  1976. X.de FE
  1977. X.br
  1978. X.di
  1979. X.nr FP \\n(dn
  1980. X.if !\\n(1T .nr KG 1
  1981. X.ev
  1982. X..
  1983. X.    \" FA - print line before footnotes
  1984. X.de FA
  1985. X.in 0
  1986. X.if n _________________________
  1987. X.if t \l'1i'
  1988. X.br
  1989. X..
  1990. X.    \" FP - footnote paragraph
  1991. X.de FP
  1992. X.sp \\n(PDu/2u
  1993. X.if \\n(FF<2 .ti \\n(FIu
  1994. X.if \\n(FF=3 \{\
  1995. X.    in \\n(FIu*2u
  1996. X.    ta \\n(FIu*2u
  1997. X.    ti 0
  1998. X.\}
  1999. X.if !\\n(FF \{\
  2000. X.    ie "\\$2"no" \\$1\0\c
  2001. X.    el \\*([.\\$1\\*(.]\0\c
  2002. X.\}
  2003. X.if \\n(FF .if \\n(FF<3 \{\
  2004. X.    ie "\\$2"no" \\$1\0\c
  2005. X.    el \\$1.\0\c
  2006. X.\}
  2007. X.if \\n(FF=3 \{\
  2008. X.    ie "\\$2"no" \\$1\t\c
  2009. X.    el \\$1.\t\c
  2010. X.\}
  2011. X..
  2012. X.    \" FV - get leftover footnote from previous page
  2013. X.de FV
  2014. X.FS
  2015. X.nf
  2016. X.ls 1
  2017. X.FY
  2018. X.ls
  2019. X.fi
  2020. X.FE
  2021. X..
  2022. X.    \" FX - divert leftover footnote for next page
  2023. X.de FX
  2024. X.if \\n(XX .di FY
  2025. X.if \\n(XX .ns
  2026. X..
  2027. X.    \" XF - actually print footnote
  2028. X.de XF
  2029. X.if \\n(nlu+1v>(\\n(.pu-\\n(FMu) .ch FX \\n(nlu+1.9v
  2030. X.ev 1
  2031. X.nf
  2032. X.ls 1
  2033. X.FF
  2034. X.rm FF
  2035. X.nr XX 0 1
  2036. X.br
  2037. X.ls
  2038. X.di
  2039. X.fi
  2040. X.ev
  2041. X..
  2042. X.    \" TS - source file for tbl
  2043. X.de TS
  2044. X.rn TS @T
  2045. X.so \*(//ms.tbl
  2046. X.TS \\$1 \\$2
  2047. X.rm @T
  2048. X..
  2049. X.    \" EQ - source file for eqn
  2050. X.de EQ
  2051. X.rn EQ @T
  2052. X.so \*(//ms.eqn
  2053. X.EQ \\$1 \\$2
  2054. X.rm @T
  2055. X..
  2056. X.       \" ]- - source file for refer
  2057. X.de ]-
  2058. X.rn ]- @T
  2059. X.so \*(//ms.ref
  2060. X.]-
  2061. X.rm @T
  2062. X..
  2063. X.       \" [< - for refer -s or -e
  2064. X.de ]<
  2065. X.rn ]< @T
  2066. X.so \*(//ms.ref
  2067. X.]<
  2068. X.rm @T
  2069. X..
  2070. X.if \n(.V>19 .ds [. \f1[
  2071. X.if \n(.V>19 .ds .] ]\fP
  2072. X.if \n(.V<20 .ds [. \f1\s-2\v'-.4m'
  2073. X.if \n(.V<20 .ds .] \v'.4m'\s+2\fP
  2074. X.ds <. .
  2075. X.ds <, ,
  2076. X.if n .ds Q \&"
  2077. X.if n .ds U \&"
  2078. X.if n .ds - \%--
  2079. X.if t .ds Q ``
  2080. X.if t .ds U ''
  2081. X.if t .ds - \(em
  2082. X.ds ' \h'\w'e'u/5'\z\'\h'-\w'e'u/5'
  2083. X.ds ` \h'\w'e'u/5'\z\`\h'-\w'e'u/5'
  2084. X.ds ^ \h'\w'o'u/10'\z^\h'-\w'e'u/10'
  2085. X.ds , \h'\w'c'u/5'\z,\h'-\w'e'u/5'
  2086. X.ds : \h'\w'u'u/5'\z"\h'-\w'e'u/5'
  2087. X.ds ~ \h'\w'n'u/10'\z~\h'-\w'e'u/10'
  2088. X.ds C \h'\w'c'u/5'\v'-.6m'\s-4\zv\s+4\v'.6m'\h'-\w'c'u/5'
  2089. X.    \" AM - better accent marks
  2090. X.de AM
  2091. X.so \*(//ms.acc
  2092. X..
  2093. X.       \" TM - thesis mode
  2094. X.de TM
  2095. X.so \*(//ms.ths
  2096. X..
  2097. X.    \" BX - word in a box
  2098. X.de BX
  2099. X.if t \(br\|\\$1\|\(br\l'|0\(rn'\l'|0\(ul'
  2100. X.if n \(br\\kA\|\\$1\|\\kB\(br\v'-1v'\h'|\\nBu'\l'|\\nAu'\v'1v'\l'|\\nAu'
  2101. X..
  2102. X.    \" B1 - source file for boxed text
  2103. X.de B1
  2104. X.rn B1 @T
  2105. X.so \*(//ms.tbl
  2106. X.B1 \\$1
  2107. X.rm @T
  2108. X..
  2109. X.       \" XS - table of contents
  2110. X.de XS
  2111. X.rn XS @T
  2112. X.so \*(//ms.toc
  2113. X.XS \\$1 \\$2
  2114. X.rm @T           
  2115. X..  
  2116. X.    \" IX - Make an Index Entry
  2117. X.de IX
  2118. X.if \\nI .if \\n(dT .if \\n(IK \!.tm .IE\t\\$1\t\\$2\t\\$3\t\\n(H1-\\\\n(PN\t
  2119. X.if \\nI .if \\n(dT .if !\\n(IK .tm .IE\t\\$1\t\\$2\t\\$3\t\\n(H1-\\n(PN\t
  2120. X.if \\nI .if !\\n(dT .if \\n(IK \!.tm .IE\t\\$1\t\\$2\t\\$3\t\\\\n(PN\t
  2121. X.if \\nI .if !\\n(dT .if !\\n(IK .tm .IE\t\\$1\t\\$2\t\\$3\t\\n(PN\t
  2122. X.if !\\nI .if \\n(dT .if \\n(IK \!.tm .IE\tENTRY\t\\$1\t\\$2\t\\$3\t\\$4\t\\$5\t\\$6\t\\n(H1-\\\\n(PN
  2123. X.if !\\nI .if \\n(dT .if !\\n(IK .tm .IE\tENTRY\t\\$1\t\\$2\t\\$3\t\\$4\t\\$5\t\\$6\t\\n(H1-\\n(PN
  2124. X.if !\\nI .if !\\n(dT .if \\n(IK \!.tm .IE\tENTRY\t\\$1\t\\$2\t\\$3\t\\$4\t\\$5\t\\$6\t\\\\n(PN
  2125. X.if !\\nI .if !\\n(dT .if !\\n(IK .tm .IE\tENTRY\t\\$1\t\\$2\t\\$3\t\\$4\t\\$5\t\\$6\t\\n(PN
  2126. X..
  2127. X.    \" IH - Make an Index Header
  2128. X.de IH
  2129. X.if \\n(dT .if \\n(IK \!.tm .IE\tHEADER\t\\$1\t\\$2\t\\$3\t\\$4\t\\n(H1-\\\\n(PN
  2130. X.if \\n(dT .if !\\n(IK .tm .IE\tHEADER\t\\$1\t\\$2\t\\$3\t\\$4\t\\n(H1-\\n(PN
  2131. X.if !\\n(dT .if \\n(IK \!.tm .IE\tHEADER\t\\$1\t\\$2\t\\$3\t\\$4\t\\\\n(PN
  2132. X.if !\\n(dT .if !\\n(IK .tm .IE\tHEADER\t\\$1\t\\$2\t\\$3\t\\$4\t\\n(PN
  2133. X..
  2134. X.    \" UX - UNIX macro
  2135. X.de UX
  2136. X.ie \\n(UX \s-1UNIX\s0\\$1
  2137. X.el \{\
  2138. \s-1UNIX\s0\\$1\(dg
  2139. X.FS
  2140. \(dg \s-1UNIX\s0 is a trademark of Bell Laboratories.
  2141. X.FE
  2142. X.nr UX 1
  2143. X.\}
  2144. X..
  2145. X.\"
  2146. X.\" Here is the SUN normal form macro,
  2147. X.\" which tries to align for the cross grid
  2148. X.\"
  2149. X.de Sn
  2150. X.ta 2i 3i 4i 5i 6i
  2151. X.nr PS 10
  2152. X.nr VS 12
  2153. X.nr LL 5.8i
  2154. X.nr PO +.75i
  2155. X.ps 10
  2156. X.vs 12
  2157. X.ll 5.8i
  2158. X.po +.75i
  2159. X.tl '''
  2160. X..
  2161. X.\"
  2162. X.\" Do a small type display
  2163. X.\"
  2164. X.de Ds
  2165. X.DS
  2166. X.ps 10
  2167. X.vs 12
  2168. X..
  2169. X.de De
  2170. X.DE
  2171. X..
  2172. X.\"
  2173. X.\" These are my memo macros, invoked by using
  2174. X.\" .MM and then specifying the appropriate pieces.
  2175. X.\" Relies on the -ms or -msun macros.
  2176. X.\"
  2177. X.\" .MM -- initialize memo
  2178. X.\" .TO -- Send it to
  2179. X.\" .FR -- From
  2180. X.\" .DA -- String for date
  2181. X.\" .SU -- String for subject
  2182. X.\" .CC -- Carbon Copies
  2183. X.\" .DI -- Distribution List
  2184. X.\" .EC -- End copy list 
  2185. X.\" 
  2186. X.de MM
  2187. X.vs 10p
  2188. X.sp 8v
  2189. X.ll 6.0i
  2190. X.ps 26
  2191. X.br
  2192. X.in +5i
  2193. X.ft 3
  2194. s\|\|u\|\|n
  2195. X.br
  2196. X.ps 12
  2197. X.ft 1
  2198. microsystems
  2199. X.in -5i
  2200. X.br
  2201. X.sp
  2202. X.ps 12
  2203. X..
  2204. X.de TO
  2205. X.mk
  2206. X.ps 9
  2207. To:
  2208. X.ps 11
  2209. X.if t .ti +\w'Subject: 'u
  2210. X.rt
  2211. \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7
  2212. X..
  2213. X.de DA
  2214. X.if t .in +6i
  2215. X.if t .in -\w'\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7'u
  2216. X.if t .in -\w'Date: 'u
  2217. X.if t .rt
  2218. X.if n .sp 
  2219. Date:
  2220. X.if t .br
  2221. X.if t .rt
  2222. X.if t .ti +\w'Date: 'u
  2223. \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7
  2224. X.br
  2225. X.if t .in +w'\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7'u
  2226. X.if t .in +w'Date: 'u
  2227. X.if t .in -6i
  2228. X.sp
  2229. X..
  2230. X.de FR
  2231. X.mk
  2232. X.ps 9
  2233. From:
  2234. X.if t .rt
  2235. X.ps 11
  2236. X.if t .ti +\w'Subject: 'u
  2237. \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7
  2238. X.if t .rt
  2239. X.sp
  2240. X..
  2241. X.de SU
  2242. X.mk
  2243. X.ps 9
  2244. Subject:
  2245. X.if t .rt
  2246. X.ps 11
  2247. X.if t .ti +\w'Subject: 'u
  2248. \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7
  2249. X.if t .rt
  2250. X.sp
  2251. X..
  2252. X.de CC
  2253. X.mk
  2254. X.ps 9
  2255. CC:
  2256. X.ps 11
  2257. X.in +\w'Subject: 'u
  2258. X.if t .rt
  2259. X.nf
  2260. X..
  2261. X.de DI
  2262. X.ps 9
  2263. Distribution
  2264. X.br
  2265. X.mk
  2266. List:
  2267. X.ps 11
  2268. X.in +\w'Subject: 'u
  2269. X.rt
  2270. X.nf
  2271. X..
  2272. X.de EC
  2273. X.sp
  2274. X.in -\w'Subject: 'u
  2275. X.fi
  2276. X.. 
  2277. X.de pp
  2278. X.sp
  2279. X..
  2280. X.\"
  2281. X.\" These are macros for making foils.
  2282. X.\" .Fp invokes the foil package initialization stuff,
  2283. X.\" .Fl gets you a foil, and 
  2284. X.\" .It gets an item
  2285. X.\" .Tl gets a title for the foil
  2286. X.\" .Ip gets a second paragraph in the bullet
  2287. X.\" .Tp gets a text paragraph, not printed on foils
  2288. X.\" .Te ends a text paragraph
  2289. X.\"
  2290. X.de Fp
  2291. X.EF 'Copyright 1984 Sun Micro''Educational Material'
  2292. X.OF 'Copyright 1984 Sun Micro''Educational Material'
  2293. X..
  2294. X.de Fl
  2295. X.bp 1
  2296. X.LP
  2297. X.sp 2
  2298. X.ll 6.5i
  2299. X.nr PS 18
  2300. X.nr VS 21
  2301. X.ps 18
  2302. X.vs 21
  2303. X..
  2304. X.de Tl
  2305. X.ps \\n(PS+10
  2306. X.vs \\n(VS+11
  2307. X.ce 10
  2308. X.ft 3
  2309. \\$1 \\$2 \\$3 
  2310. \\$4 \\$5 \\$6 \\$7
  2311. X.ft 1
  2312. X.ce 0
  2313. X.br
  2314. X.ps \\n(PS
  2315. X.vs \\n(VS
  2316. X..
  2317. X.de Sl
  2318. X.ps \\n(PS+4
  2319. X.vs \\n(VS+5
  2320. \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7
  2321. X.br
  2322. X.ps \\n(PS
  2323. X.vs \\n(VS
  2324. X..
  2325. X.de St
  2326. X.rs
  2327. X.ps \\n(PS+4
  2328. X.vs \\n(VS+5
  2329. \|\|
  2330. X.sp -2
  2331. \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7
  2332. X.sp 2
  2333. X.br
  2334. X.ps \\n(PS
  2335. X.vs \\n(VS
  2336. X..
  2337. X.de It
  2338. X.sp 1
  2339. X.IP \(bu
  2340. X.ps \\n(PS+6 
  2341. X.vs \\n(VS+7
  2342. \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7
  2343. X.sp 1
  2344. X.ps \\n(PS
  2345. X.vs \\n(VS
  2346. X..
  2347. X.de Ip
  2348. X.sp 1
  2349. X..
  2350. X.de Tp
  2351. X.ig Te
  2352. X..
  2353. X.co
  2354. X.if \n(mo-0 .ds MO January
  2355. X.if \n(mo-1 .ds MO February
  2356. X.if \n(mo-2 .ds MO March
  2357. X.if \n(mo-3 .ds MO April
  2358. X.if \n(mo-4 .ds MO May
  2359. X.if \n(mo-5 .ds MO June
  2360. X.if \n(mo-6 .ds MO July
  2361. X.if \n(mo-7 .ds MO August
  2362. X.if \n(mo-8 .ds MO September
  2363. X.if \n(mo-9 .ds MO October
  2364. X.if \n(mo-10 .ds MO November
  2365. X.if \n(mo-11 .ds MO December
  2366. X.ds DY \*(MO \n(dy, 19\n(yr
  2367. X.nr * 0 1
  2368. X.IZ
  2369. X.em EM
  2370. X.rm IZ RA //
  2371. !Funky!Stuff!
  2372.  
  2373. exit
  2374.