summaryrefslogtreecommitdiffstats
path: root/share/doc
diff options
context:
space:
mode:
authoruqs <uqs@FreeBSD.org>2010-12-04 10:11:20 +0000
committeruqs <uqs@FreeBSD.org>2010-12-04 10:11:20 +0000
commit9242c645f81d22058934688725f1fff0bc88cb64 (patch)
treea39140e4d881fbba4f04ac77974bfbb05df9d360 /share/doc
parent06cd6f2bc1f94f941b57ef92ed6445529822669b (diff)
downloadFreeBSD-src-9242c645f81d22058934688725f1fff0bc88cb64.zip
FreeBSD-src-9242c645f81d22058934688725f1fff0bc88cb64.tar.gz
Move most of the remaining USD/PSD/SMM papers into share/doc
Diffstat (limited to 'share/doc')
-rw-r--r--share/doc/psd/12.make/Makefile1
-rw-r--r--share/doc/psd/12.make/stubs9
-rw-r--r--share/doc/psd/12.make/tutorial.ms3747
-rw-r--r--share/doc/psd/18.gprof/Makefile1
-rw-r--r--share/doc/psd/18.gprof/abstract.me66
-rw-r--r--share/doc/psd/18.gprof/gathering.me231
-rw-r--r--share/doc/psd/18.gprof/header.me38
-rw-r--r--share/doc/psd/18.gprof/intro.me81
-rw-r--r--share/doc/psd/18.gprof/postp.me190
-rw-r--r--share/doc/psd/18.gprof/postp1.pic54
-rw-r--r--share/doc/psd/18.gprof/postp2.pic56
-rw-r--r--share/doc/psd/18.gprof/postp3.pic51
-rw-r--r--share/doc/psd/18.gprof/pres1.pic56
-rw-r--r--share/doc/psd/18.gprof/pres2.pic52
-rw-r--r--share/doc/psd/18.gprof/present.me306
-rw-r--r--share/doc/psd/18.gprof/profiling.me115
-rw-r--r--share/doc/psd/18.gprof/refs.me63
-rw-r--r--share/doc/psd/22.rpcgen/Makefile1
-rw-r--r--share/doc/psd/22.rpcgen/rpcgen.ms1301
-rw-r--r--share/doc/psd/22.rpcgen/stubs3
-rw-r--r--share/doc/psd/23.rpc/Makefile1
-rw-r--r--share/doc/psd/23.rpc/rpc.prog.ms2686
-rw-r--r--share/doc/psd/23.rpc/stubs3
-rw-r--r--share/doc/psd/24.xdr/Makefile1
-rw-r--r--share/doc/psd/24.xdr/stubs3
-rw-r--r--share/doc/psd/24.xdr/xdr.nts.ms1968
-rw-r--r--share/doc/psd/25.xdrrfc/Makefile1
-rw-r--r--share/doc/psd/25.xdrrfc/stubs3
-rw-r--r--share/doc/psd/25.xdrrfc/xdr.rfc.ms1060
-rw-r--r--share/doc/psd/26.rpcrfc/Makefile1
-rw-r--r--share/doc/psd/26.rpcrfc/rpc.rfc.ms1304
-rw-r--r--share/doc/psd/26.rpcrfc/stubs3
-rw-r--r--share/doc/psd/27.nfsrpc/Makefile1
-rw-r--r--share/doc/psd/27.nfsrpc/nfs.rfc.ms1374
-rw-r--r--share/doc/psd/27.nfsrpc/stubs3
-rw-r--r--share/doc/smm/02.config/0.t88
-rw-r--r--share/doc/smm/02.config/1.t61
-rw-r--r--share/doc/smm/02.config/2.t188
-rw-r--r--share/doc/smm/02.config/3.t299
-rw-r--r--share/doc/smm/02.config/4.t442
-rw-r--r--share/doc/smm/02.config/5.t271
-rw-r--r--share/doc/smm/02.config/6.t233
-rw-r--r--share/doc/smm/02.config/Makefile1
-rw-r--r--share/doc/smm/02.config/a.t162
-rw-r--r--share/doc/smm/02.config/b.t137
-rw-r--r--share/doc/smm/02.config/c.t109
-rw-r--r--share/doc/smm/02.config/d.t272
-rw-r--r--share/doc/smm/02.config/e.t114
-rw-r--r--share/doc/smm/02.config/spell.ok305
-rw-r--r--share/doc/smm/03.fsck/0.t147
-rw-r--r--share/doc/smm/03.fsck/1.t80
-rw-r--r--share/doc/smm/03.fsck/2.t262
-rw-r--r--share/doc/smm/03.fsck/3.t449
-rw-r--r--share/doc/smm/03.fsck/4.t1421
-rw-r--r--share/doc/smm/03.fsck/Makefile1
-rw-r--r--share/doc/smm/07.lpr/0.t68
-rw-r--r--share/doc/smm/07.lpr/1.t77
-rw-r--r--share/doc/smm/07.lpr/2.t141
-rw-r--r--share/doc/smm/07.lpr/3.t73
-rw-r--r--share/doc/smm/07.lpr/4.t206
-rw-r--r--share/doc/smm/07.lpr/5.t116
-rw-r--r--share/doc/smm/07.lpr/6.t94
-rw-r--r--share/doc/smm/07.lpr/7.t226
-rw-r--r--share/doc/smm/07.lpr/Makefile9
-rw-r--r--share/doc/smm/07.lpr/spell.ok70
-rw-r--r--share/doc/smm/11.timedop/Makefile1
-rw-r--r--share/doc/smm/11.timedop/timed.ms279
-rw-r--r--share/doc/smm/12.timed/Makefile1
-rw-r--r--share/doc/smm/12.timed/date53
-rw-r--r--share/doc/smm/12.timed/loop54
-rw-r--r--share/doc/smm/12.timed/spell.ok34
-rw-r--r--share/doc/smm/12.timed/time53
-rw-r--r--share/doc/smm/12.timed/timed.ms462
-rw-r--r--share/doc/smm/12.timed/unused53
-rw-r--r--share/doc/usd/04.csh/Makefile1
-rw-r--r--share/doc/usd/04.csh/csh.11012
-rw-r--r--share/doc/usd/04.csh/csh.21304
-rw-r--r--share/doc/usd/04.csh/csh.3649
-rw-r--r--share/doc/usd/04.csh/csh.4176
-rw-r--r--share/doc/usd/04.csh/csh.a93
-rw-r--r--share/doc/usd/04.csh/csh.g1719
-rw-r--r--share/doc/usd/04.csh/tabs32
-rw-r--r--share/doc/usd/05.dc/Makefile1
-rw-r--r--share/doc/usd/05.dc/dc753
-rw-r--r--share/doc/usd/06.bc/Makefile1
-rw-r--r--share/doc/usd/06.bc/bc1241
-rw-r--r--share/doc/usd/07.mail/Makefile1
-rw-r--r--share/doc/usd/07.mail/mail0.nr72
-rw-r--r--share/doc/usd/07.mail/mail1.nr92
-rw-r--r--share/doc/usd/07.mail/mail2.nr617
-rw-r--r--share/doc/usd/07.mail/mail3.nr133
-rw-r--r--share/doc/usd/07.mail/mail4.nr437
-rw-r--r--share/doc/usd/07.mail/mail5.nr1042
-rw-r--r--share/doc/usd/07.mail/mail6.nr125
-rw-r--r--share/doc/usd/07.mail/mail7.nr107
-rw-r--r--share/doc/usd/07.mail/mail8.nr75
-rw-r--r--share/doc/usd/07.mail/mail9.nr203
-rw-r--r--share/doc/usd/07.mail/maila.nr33
98 files changed, 31849 insertions, 16 deletions
diff --git a/share/doc/psd/12.make/Makefile b/share/doc/psd/12.make/Makefile
index fdc38a7..b365683 100644
--- a/share/doc/psd/12.make/Makefile
+++ b/share/doc/psd/12.make/Makefile
@@ -4,6 +4,5 @@
VOLUME= psd/12.make
SRCS= stubs tutorial.ms
MACROS= -ms
-SRCDIR= ${.CURDIR}/../../../../usr.bin/make/PSD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/psd/12.make/stubs b/share/doc/psd/12.make/stubs
new file mode 100644
index 0000000..39d8def
--- /dev/null
+++ b/share/doc/psd/12.make/stubs
@@ -0,0 +1,9 @@
+.\" $FreeBSD$
+.\"
+.de Ix
+..
+.de Rd
+..
+.de Rm
+..
+.if n .ftr CR R
diff --git a/share/doc/psd/12.make/tutorial.ms b/share/doc/psd/12.make/tutorial.ms
new file mode 100644
index 0000000..320d5df
--- /dev/null
+++ b/share/doc/psd/12.make/tutorial.ms
@@ -0,0 +1,3747 @@
+.\" Copyright (c) 1988, 1989 by Adam de Boor
+.\" Copyright (c) 1989 by Berkeley Softworks
+.\" Copyright (c) 1988, 1989, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Adam de Boor.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)tutorial.ms 8.1 (Berkeley) 8/18/93
+.\" $FreeBSD$
+.\"
+.EH 'PSD:12-%''PMake \*- A Tutorial'
+.OH 'PMake \*- A Tutorial''PSD:12-%'
+.\" xH is a macro to provide numbered headers that are automatically stuffed
+.\" into a table-of-contents, properly indented, etc. If the first argument
+.\" is numeric, it is taken as the depth for numbering (as for .NH), else
+.\" the default (1) is assumed.
+.\"
+.\" @P The initial paragraph distance.
+.\" @Q The piece of section number to increment (or 0 if none given)
+.\" @R Section header.
+.\" @S Indent for toc entry
+.\" @T Argument to NH (can't use @Q b/c giving 0 to NH resets the counter)
+.de xH
+.NH \\$1
+\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.nr PD .1v
+.XS \\n%
+.ta 0.6i
+\\*(SN \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.XE
+.nr PD .3v
+..
+.ig
+.\" CW is used to place a string in fixed-width or switch to a
+.\" fixed-width font.
+.\" C is a typewriter font for a laserwriter. Use something else if
+.\" you don't have one...
+.de CW
+.ie !\\n(.$ .ft S
+.el \&\\$3\fS\\$1\fP\\$2
+..
+.\" Anything I put in a display I want to be in fixed-width
+.am DS
+.CW
+..
+.\" The stuff in .No produces a little stop sign in the left margin
+.\" that says NOTE in it. Unfortunately, it does cause a break, but
+.\" hey. Can't have everything. In case you're wondering how I came
+.\" up with such weird commands, they came from running grn on a
+.\" gremlin file...
+.de No
+.br
+.ne 0.5i
+.po -0.5i
+.br
+.mk
+.nr g3 \\n(.f
+.nr g4 \\n(.s
+.ig ft
+.sp -1
+.\" .st cf
+\D's -1u'\D't 5u'
+.sp -1
+\h'50u'\D'l 71u 0u'\D'l 50u 50u'\D'l 0u 71u'\D'l -50u 50u'\D'l -71u 0u'\D'l -50u -50u'\D'l 0u -71u'\D'l 50u -50u'
+.sp -1
+\D't 3u'
+.sp -1
+.sp 7u
+\h'53u'\D'p 14 68u 0u 46u 46u 0u 68u -46u 46u -68u 0u -47u -46u 0u -68u 47u -46u'
+.sp -1
+.ft R
+.ps 6
+.nr g8 \\n(.d
+.ds g9 "NOTE
+.sp 74u
+\h'85u'\v'0.85n'\h-\w\\*(g9u/2u\&\\*(g9
+.sp |\\n(g8u
+.sp 166u
+.ig br
+\D't 3u'\D's -1u'
+.br
+.po
+.rt
+.ft \\n(g3
+.ps \\n(g4
+..
+.de Bp
+.ie !\\n(.$ .IP \(bu 2
+.el .IP "\&" 2
+..
+.po +.3i
+.TL
+PMake \*- A Tutorial
+.AU
+Adam de Boor
+.AI
+Berkeley Softworks
+2150 Shattuck Ave, Penthouse
+Berkeley, CA 94704
+adam@bsw.uu.net
+\&...!uunet!bsw!adam
+.FS
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appears in all copies.
+The University of California, Berkeley Softworks, and Adam de Boor make no
+representations about the suitability of this software for any
+purpose. It is provided "as is" without express or implied warranty.
+.FE
+.PP
+.xH 1 Introduction
+.LP
+PMake is a program for creating other programs, or anything else you
+can think of for it to do. The basic idea behind PMake is that, for
+any given system, be it a program or a document or whatever, there
+will be some files that depend on the state of other files (on when
+they were last modified). PMake takes these dependencies, which you
+must specify, and uses them to build whatever it is you want it to
+build.
+.LP
+PMake is almost fully-compatible with Make, with which you may already
+be familiar. PMake's most important feature is its ability to run
+several different jobs at once, making the creation of systems
+considerably faster. It also has a great deal more functionality than
+Make. Throughout the text, whenever something is mentioned that is an
+important difference between PMake and Make (i.e. something that will
+cause a makefile to fail if you don't do something about it), or is
+simply important, it will be flagged with a little sign in the left
+margin, like this:
+.No
+.LP
+This tutorial is divided into three main sections corresponding to basic,
+intermediate and advanced PMake usage. If you already know Make well,
+you will only need to skim chapter 2 (there are some aspects of
+PMake that I consider basic to its use that didn't exist in Make).
+Things in chapter 3 make life much easier, while those in chapter 4
+are strictly for those who know what they are doing. Chapter 5 has
+definitions for the jargon I use and chapter 6 contains possible
+solutions to the problems presented throughout the tutorial.
+.xH 1 The Basics of PMake
+.LP
+PMake takes as input a file that tells a) which files depend on which
+other files to be complete and b) what to do about files that are
+``out-of-date.'' This file is known as a ``makefile'' and is usually
+.Ix 0 def makefile
+kept in the top-most directory of the system to be built. While you
+can call the makefile anything you want, PMake will look for
+.CW Makefile
+and
+.CW makefile
+(in that order) in the current directory if you don't tell it
+otherwise.
+.Ix 0 def makefile default
+To specify a different makefile, use the
+.B \-f
+flag (e.g.
+.CW "pmake -f program.mk" ''). ``
+.Ix 0 ref flags -f
+.Ix 0 ref makefile other
+.LP
+A makefile has four different types of lines in it:
+.RS
+.IP \(bu 2
+File dependency specifications
+.IP \(bu 2
+Creation commands
+.IP \(bu 2
+Variable assignments
+.IP \(bu 2
+Comments, include statements and conditional directives
+.RE
+.LP
+Any line may be continued over multiple lines by ending it with a
+backslash.
+.Ix 0 def "continuation line"
+The backslash, following newline and any initial whitespace
+on the following line are compressed into a single space before the
+input line is examined by PMake.
+.xH 2 Dependency Lines
+.LP
+As mentioned in the introduction, in any system, there are
+dependencies between the files that make up the system. For instance,
+in a program made up of several C source files and one header file,
+the C files will need to be re-compiled should the header file be
+changed. For a document of several chapters and one macro file, the
+chapters will need to be reprocessed if any of the macros changes.
+.Ix 0 def "dependency"
+These are dependencies and are specified by means of dependency lines in
+the makefile.
+.LP
+.Ix 0 def "dependency line"
+On a dependency line, there are targets and sources, separated by a
+one- or two-character operator.
+The targets ``depend'' on the sources and are usually created from
+them.
+.Ix 0 def target
+.Ix 0 def source
+.Ix 0 ref operator
+Any number of targets and sources may be specified on a dependency line.
+All the targets in the line are made to depend on all the sources.
+Targets and sources need not be actual files, but every source must be
+either an actual file or another target in the makefile.
+If you run out of room, use a backslash at the end of the line to continue onto
+the next one.
+.LP
+Any file may be a target and any file may be a source, but the
+relationship between the two (or however many) is determined by the
+``operator'' that separates them.
+.Ix 0 def operator
+Three types of operators exist: one specifies that the datedness of a
+target is determined by the state of its sources, while another
+specifies other files (the sources) that need to be dealt with before
+the target can be re-created. The third operator is very similar to
+the first, with the additional condition that the target is
+out-of-date if it has no sources. These operations are represented by
+the colon, the exclamation point and the double-colon, respectively, and are
+mutually exclusive. Their exact semantics are as follows:
+.IP ":"
+.Ix 0 def operator colon
+.Ix 0 def :
+If a colon is used, a target on the line is considered to be
+``out-of-date'' (and in need of creation) if
+.RS
+.IP \(bu 2
+any of the sources has been modified more recently than the target, or
+.IP \(bu 2
+the target doesn't exist.
+.RE
+.Ix 0 def out-of-date
+.IP "\&"
+Under this operation, steps will be taken to re-create the target only
+if it is found to be out-of-date by using these two rules.
+.IP "!"
+.Ix 0 def operator force
+.Ix 0 def !
+If an exclamation point is used, the target will always be re-created,
+but this will not happen until all of its sources have been examined
+and re-created, if necessary.
+.IP "::"
+.Ix 0 def operator double-colon
+.Ix 0 def ::
+If a double-colon is used, a target is out-of-date if:
+.RS
+.IP \(bu 2
+any of the sources has been modified more recently than the target, or
+.IP \(bu 2
+the target doesn't exist, or
+.IP \(bu 2
+the target has no sources.
+.RE
+.IP "\&"
+If the target is out-of-date according to these rules, it will be re-created.
+This operator also does something else to the targets, but I'll go
+into that in the next section (``Shell Commands'').
+.LP
+Enough words, now for an example. Take that C program I mentioned
+earlier. Say there are three C files
+.CW a.c , (
+.CW b.c
+and
+.CW c.c )
+each of which
+includes the file
+.CW defs.h .
+The dependencies between the files could then be expressed as follows:
+.DS
+program : a.o b.o c.o
+a.o b.o c.o : defs.h
+a.o : a.c
+b.o : b.c
+c.o : c.c
+.DE
+.LP
+You may be wondering at this point, where
+.CW a.o ,
+.CW b.o
+and
+.CW c.o
+came in and why
+.I they
+depend on
+.CW defs.h
+and the C files don't. The reason is quite simple:
+.CW program
+cannot be made by linking together .c files \*- it must be
+made from .o files. Likewise, if you change
+.CW defs.h ,
+it isn't the .c files that need to be re-created, it's the .o files.
+If you think of dependencies in these terms \*- which files (targets)
+need to be created from which files (sources) \*- you should have no problems.
+.LP
+An important thing to notice about the above example, is that all the
+\&.o files appear as targets on more than one line. This is perfectly
+all right: the target is made to depend on all the sources mentioned
+on all the dependency lines. E.g.
+.CW a.o
+depends on both
+.CW defs.h
+and
+.CW a.c .
+.Ix 0 ref dependency
+.No
+.LP
+The order of the dependency lines in the makefile is
+important: the first target on the first dependency line in the
+makefile will be the one that gets made if you don't say otherwise.
+That's why
+.CW program
+comes first in the example makefile, above.
+.LP
+Both targets and sources may contain the standard C-Shell wildcard
+characters
+.CW { , (
+.CW } ,
+.CW * ,
+.CW ? ,
+.CW [ ,
+and
+.CW ] ),
+but the non-curly-brace ones may only appear in the final component
+(the file portion) of the target or source. The characters mean the
+following things:
+.IP \fB{}\fP
+These enclose a comma-separated list of options and cause the pattern
+to be expanded once for each element of the list. Each expansion
+contains a different element. For example,
+.CW src/{whiffle,beep,fish}.c
+expands to the three words
+.CW src/whiffle.c ,
+.CW src/beep.c ,
+and
+.CW src/fish.c .
+These braces may be nested and, unlike the other wildcard characters,
+the resulting words need not be actual files. All other wildcard
+characters are expanded using the files that exist when PMake is
+started.
+.IP \fB*\fP
+This matches zero or more characters of any sort.
+.CW src/*.c
+will expand to the same three words as above as long as
+.CW src
+contains those three files (and no other files that end in
+.CW .c ).
+.IP \fB?\fP
+Matches any single character.
+.IP \fB[]\fP
+This is known as a character class and contains either a list of
+single characters, or a series of character ranges
+.CW a-z , (
+for example means all characters between a and z), or both. It matches
+any single character contained in the list. E.g.
+.CW [A-Za-z]
+will match all letters, while
+.CW [0123456789]
+will match all numbers.
+.xH 2 Shell Commands
+.LP
+``Isn't that nice,'' you say to yourself, ``but how are files
+actually `re-created,' as he likes to spell it?''
+The re-creation is accomplished by commands you place in the makefile.
+These commands are passed to the Bourne shell (better known as
+``/bin/sh'') to be executed and are
+.Ix 0 ref shell
+.Ix 0 ref re-creation
+.Ix 0 ref update
+expected to do what's necessary to update the target file (PMake
+doesn't actually check to see if the target was created. It just
+assumes it's there).
+.Ix 0 ref target
+.LP
+Shell commands in a makefile look a lot like shell commands you would
+type at a terminal, with one important exception: each command in a
+makefile
+.I must
+be preceded by at least one tab.
+.LP
+Each target has associated with it a shell script made up of
+one or more of these shell commands. The creation script for a target
+should immediately follow the dependency line for that target. While
+any given target may appear on more than one dependency line, only one
+of these dependency lines may be followed by a creation script, unless
+the `::' operator was used on the dependency line.
+.Ix 0 ref operator double-colon
+.Ix 0 ref ::
+.No
+.LP
+If the double-colon was used, each dependency line for the target
+may be followed by a shell script. That script will only be executed
+if the target on the associated dependency line is out-of-date with
+respect to the sources on that line, according to the rules I gave
+earlier.
+I'll give you a good example of this later on.
+.LP
+To expand on the earlier makefile, you might add commands as follows:
+.DS
+program : a.o b.o c.o
+ cc a.o b.o c.o \-o program
+a.o b.o c.o : defs.h
+a.o : a.c
+ cc \-c a.c
+b.o : b.c
+ cc \-c b.c
+c.o : c.c
+ cc \-c c.c
+.DE
+.LP
+Something you should remember when writing a makefile is, the
+commands will be executed if the
+.I target
+on the dependency line is out-of-date, not the sources.
+.Ix 0 ref target
+.Ix 0 ref source
+.Ix 0 ref out-of-date
+In this example, the command
+.CW "cc \-c a.c" '' ``
+will be executed if
+.CW a.o
+is out-of-date. Because of the `:' operator,
+.Ix 0 ref :
+.Ix 0 ref operator colon
+this means that should
+.CW a.c
+.I or
+.CW defs.h
+have been modified more recently than
+.CW a.o ,
+the command will be executed
+.CW a.o "\&" (
+will be considered out-of-date).
+.Ix 0 ref out-of-date
+.LP
+Remember how I said the only difference between a makefile shell
+command and a regular shell command was the leading tab? I lied. There
+is another way in which makefile commands differ from regular ones.
+The first two characters after the initial whitespace are treated
+specially.
+If they are any combination of `@' and `\-', they cause PMake to do
+different things.
+.LP
+In most cases, shell commands are printed before they're
+actually executed. This is to keep you informed of what's going on. If
+an `@' appears, however, this echoing is suppressed. In the case of an
+.CW echo
+command, say
+.CW "echo Linking index" ,'' ``
+it would be
+rather silly to see
+.DS
+echo Linking index
+Linking index
+.DE
+.LP
+so PMake allows you to place an `@' before the command
+.CW "@echo Linking index" '') (``
+to prevent the command from being printed.
+.LP
+The other special character is the `\-'. In case you didn't know,
+shell commands finish with a certain ``exit status.'' This status is
+made available by the operating system to whatever program invoked the
+command. Normally this status will be 0 if everything went ok and
+non-zero if something went wrong. For this reason, PMake will consider
+an error to have occurred if one of the shells it invokes returns a non-zero
+status. When it detects an error, PMake's usual action is to abort
+whatever it's doing and exit with a non-zero status itself (any other
+targets that were being created will continue being made, but nothing
+new will be started. PMake will exit after the last job finishes).
+This behavior can be altered, however, by placing a `\-' at the front
+of a command
+.CW "\-mv index index.old" ''), (``
+certain command-line arguments,
+or doing other things, to be detailed later. In such
+a case, the non-zero status is simply ignored and PMake keeps chugging
+along.
+.No
+.LP
+Because all the commands are given to a single shell to execute, such
+things as setting shell variables, changing directories, etc., last
+beyond the command in which they are found. This also allows shell
+compound commands (like
+.CW for
+loops) to be entered in a natural manner.
+Since this could cause problems for some makefiles that depend on
+each command being executed by a single shell, PMake has a
+.B \-B
+.Ix 0 ref compatibility
+.Ix 0 ref flags -B
+flag (it stands for backwards-compatible) that forces each command to
+be given to a separate shell. It also does several other things, all
+of which I discourage since they are now old-fashioned.\|.\|.\|.
+.No
+.LP
+A target's shell script is fed to the shell on its (the shell's) input stream.
+This means that any commands, such as
+.CW ci
+that need to get input from the terminal won't work right \*- they'll
+get the shell's input, something they probably won't find to their
+liking. A simple way around this is to give a command like this:
+.DS
+ci $(SRCS) < /dev/tty
+.DE
+This would force the program's input to come from the terminal. If you
+can't do this for some reason, your only other alternative is to use
+PMake in its fullest compatibility mode. See
+.B Compatibility
+in chapter 4.
+.Ix 0 ref compatibility
+.LP
+.xH 2 Variables
+.LP
+PMake, like Make before it, has the ability to save text in variables
+to be recalled later at your convenience. Variables in PMake are used
+much like variables in the shell and, by tradition, consist of
+all upper-case letters (you don't
+.I have
+to use all upper-case letters.
+In fact there's nothing to stop you from calling a variable
+.CW @^&$%$ .
+Just tradition). Variables are assigned-to using lines of the form
+.Ix 0 def variable assignment
+.DS
+VARIABLE = value
+.DE
+.Ix 0 def variable assignment
+appended-to by
+.DS
+VARIABLE += value
+.DE
+.Ix 0 def variable appending
+.Ix 0 def variable assignment appended
+.Ix 0 def +=
+conditionally assigned-to (if the variable isn't already defined) by
+.DS
+VARIABLE ?= value
+.DE
+.Ix 0 def variable assignment conditional
+.Ix 0 def ?=
+and assigned-to with expansion (i.e. the value is expanded (see below)
+before being assigned to the variable\*-useful for placing a value at
+the beginning of a variable, or other things) by
+.DS
+VARIABLE := value
+.DE
+.Ix 0 def variable assignment expanded
+.Ix 0 def :=
+.LP
+Any whitespace before
+.I value
+is stripped off. When appending, a space is placed between the old
+value and the stuff being appended.
+.LP
+The final way a variable may be assigned to is using
+.DS
+VARIABLE != shell-command
+.DE
+.Ix 0 def variable assignment shell-output
+.Ix 0 def !=
+In this case,
+.I shell-command
+has all its variables expanded (see below) and is passed off to a
+shell to execute. The output of the shell is then placed in the
+variable. Any newlines (other than the final one) are replaced by
+spaces before the assignment is made. This is typically used to find
+the current directory via a line like:
+.DS
+CWD != pwd
+.DE
+.LP
+.B Note:
+this is intended to be used to execute commands that produce small amounts
+of output (e.g. ``pwd''). The implementation is less than intelligent and will
+likely freeze if you execute something that produces thousands of
+bytes of output (8 Kb is the limit on many UNIX systems).
+.LP
+The value of a variable may be retrieved by enclosing the variable
+name in parentheses or curly braces and preceding the whole thing
+with a dollar sign.
+.LP
+For example, to set the variable CFLAGS to the string
+.CW "\-I/sprite/src/lib/libc \-O" ,'' ``
+you would place a line
+.DS
+CFLAGS = \-I/sprite/src/lib/libc \-O
+.DE
+in the makefile and use the word
+.CW "$(CFLAGS)"
+wherever you would like the string
+.CW "\-I/sprite/src/lib/libc \-O"
+to appear. This is called variable expansion.
+.Ix 0 def variable expansion
+.No
+.LP
+Unlike Make, PMake will not expand a variable unless it knows
+the variable exists. E.g. if you have a
+.CW "${i}"
+in a shell command and you have not assigned a value to the variable
+.CW i
+(the empty string is considered a value, by the way), where Make would have
+substituted the empty string, PMake will leave the
+.CW "${i}"
+alone.
+To keep PMake from substituting for a variable it knows, precede the
+dollar sign with another dollar sign.
+(e.g. to pass
+.CW "${HOME}"
+to the shell, use
+.CW "$${HOME}" ).
+This causes PMake, in effect, to expand the
+.CW $
+macro, which expands to a single
+.CW $ .
+For compatibility, Make's style of variable expansion will be used
+if you invoke PMake with any of the compatibility flags (\c
+.B \-V ,
+.B \-B
+or
+.B \-M .
+The
+.B \-V
+flag alters just the variable expansion).
+.Ix 0 ref flags -V
+.Ix 0 ref flags -B
+.Ix 0 ref flags -M
+.Ix 0 ref compatibility
+.LP
+.Ix 0 ref variable expansion
+There are two different times at which variable expansion occurs:
+When parsing a dependency line, the expansion occurs immediately
+upon reading the line. If any variable used on a dependency line is
+undefined, PMake will print a message and exit.
+Variables in shell commands are expanded when the command is
+executed.
+Variables used inside another variable are expanded whenever the outer
+variable is expanded (the expansion of an inner variable has no effect
+on the outer variable. I.e. if the outer variable is used on a dependency
+line and in a shell command, and the inner variable changes value
+between when the dependency line is read and the shell command is
+executed, two different values will be substituted for the outer
+variable).
+.Ix 0 def variable types
+.LP
+Variables come in four flavors, though they are all expanded the same
+and all look about the same. They are (in order of expanding scope):
+.RS
+.IP \(bu 2
+Local variables.
+.Ix 0 ref variable local
+.IP \(bu 2
+Command-line variables.
+.Ix 0 ref variable command-line
+.IP \(bu 2
+Global variables.
+.Ix 0 ref variable global
+.IP \(bu 2
+Environment variables.
+.Ix 0 ref variable environment
+.RE
+.LP
+The classification of variables doesn't matter much, except that the
+classes are searched from the top (local) to the bottom (environment)
+when looking up a variable. The first one found wins.
+.xH 3 Local Variables
+.LP
+.Ix 0 def variable local
+Each target can have as many as seven local variables. These are
+variables that are only ``visible'' within that target's shell script
+and contain such things as the target's name, all of its sources (from
+all its dependency lines), those sources that were out-of-date, etc.
+Four local variables are defined for all targets. They are:
+.RS
+.IP ".TARGET"
+.Ix 0 def variable local .TARGET
+.Ix 0 def .TARGET
+The name of the target.
+.IP ".OODATE"
+.Ix 0 def variable local .OODATE
+.Ix 0 def .OODATE
+The list of the sources for the target that were considered out-of-date.
+The order in the list is not guaranteed to be the same as the order in
+which the dependencies were given.
+.IP ".ALLSRC"
+.Ix 0 def variable local .ALLSRC
+.Ix 0 def .ALLSRC
+The list of all sources for this target in the order in which they
+were given.
+.IP ".PREFIX"
+.Ix 0 def variable local .PREFIX
+.Ix 0 def .PREFIX
+The target without its suffix and without any leading path. E.g. for
+the target
+.CW ../../lib/compat/fsRead.c ,
+this variable would contain
+.CW fsRead .
+.RE
+.LP
+Three other local variables are set only for certain targets under
+special circumstances. These are the ``.IMPSRC,''
+.Ix 0 ref variable local .IMPSRC
+.Ix 0 ref .IMPSRC
+``.ARCHIVE,''
+.Ix 0 ref variable local .ARCHIVE
+.Ix 0 ref .ARCHIVE
+and ``.MEMBER''
+.Ix 0 ref variable local .MEMBER
+.Ix 0 ref .MEMBER
+variables. When they are set and how they are used is described later.
+.LP
+Four of these variables may be used in sources as well as in shell
+scripts.
+.Ix 0 def "dynamic source"
+.Ix 0 def source dynamic
+These are ``.TARGET'', ``.PREFIX'', ``.ARCHIVE'' and ``.MEMBER''. The
+variables in the sources are expanded once for each target on the
+dependency line, providing what is known as a ``dynamic source,''
+.Rd 0
+allowing you to specify several dependency lines at once. For example,
+.DS
+$(OBJS) : $(.PREFIX).c
+.DE
+will create a dependency between each object file and its
+corresponding C source file.
+.xH 3 Command-line Variables
+.LP
+.Ix 0 def variable command-line
+Command-line variables are set when PMake is first invoked by giving a
+variable assignment as one of the arguments. For example,
+.DS
+pmake "CFLAGS = -I/sprite/src/lib/libc -O"
+.DE
+would make
+.CW CFLAGS
+be a command-line variable with the given value. Any assignments to
+.CW CFLAGS
+in the makefile will have no effect, because once it
+is set, there is (almost) nothing you can do to change a command-line
+variable (the search order, you see). Command-line variables may be
+set using any of the four assignment operators, though only
+.CW =
+and
+.CW ?=
+behave as you would expect them to, mostly because assignments to
+command-line variables are performed before the makefile is read, thus
+the values set in the makefile are unavailable at the time.
+.CW +=
+.Ix 0 ref +=
+.Ix 0 ref variable assignment appended
+is the same as
+.CW = ,
+because the old value of the variable is sought only in the scope in
+which the assignment is taking place (for reasons of efficiency that I
+won't get into here).
+.CW :=
+and
+.CW ?=
+.Ix 0 ref :=
+.Ix 0 ref ?=
+.Ix 0 ref variable assignment expanded
+.Ix 0 ref variable assignment conditional
+will work if the only variables used are in the environment.
+.CW !=
+is sort of pointless to use from the command line, since the same
+effect can no doubt be accomplished using the shell's own command
+substitution mechanisms (backquotes and all that).
+.xH 3 Global Variables
+.LP
+.Ix 0 def variable global
+Global variables are those set or appended-to in the makefile.
+There are two classes of global variables: those you set and those PMake sets.
+As I said before, the ones you set can have any name you want them to have,
+except they may not contain a colon or an exclamation point.
+The variables PMake sets (almost) always begin with a
+period and always contain upper-case letters, only. The variables are
+as follows:
+.RS
+.IP .PMAKE
+.Ix 0 def variable global .PMAKE
+.Ix 0 def .PMAKE
+.Ix 0 def variable global MAKE
+.Ix 0 def MAKE
+The name by which PMake was invoked is stored in this variable. For
+compatibility, the name is also stored in the MAKE variable.
+.IP .MAKEFLAGS
+.Ix 0 def variable global .MAKEFLAGS
+.Ix 0 def .MAKEFLAGS variable
+.Ix 0 def variable global MFLAGS
+.Ix 0 def MFLAGS
+All the relevant flags with which PMake was invoked. This does not
+include such things as
+.B \-f
+or variable assignments. Again for compatibility, this value is stored
+in the MFLAGS variable as well.
+.RE
+.LP
+Two other variables, ``.INCLUDES'' and ``.LIBS,'' are covered in the
+section on special targets in chapter 3.
+.Ix 0 ref variable global .INCLUDES
+.Ix 0 ref variable global .LIBS
+.LP
+Global variables may be deleted using lines of the form:
+.Ix 0 def #undef
+.Ix 0 def variable deletion
+.DS
+#undef \fIvariable\fP
+.DE
+The
+.CW # ' `
+must be the first character on the line. Note that this may only be
+done on global variables.
+.xH 3 Environment Variables
+.LP
+.Ix 0 def variable environment
+Environment variables are passed by the shell that invoked PMake and
+are given by PMake to each shell it invokes. They are expanded like
+any other variable, but they cannot be altered in any way.
+.LP
+One special environment variable,
+.CW PMAKE ,
+.Ix 0 def variable environment PMAKE
+is examined by PMake for command-line flags, variable assignments,
+etc., it should always use. This variable is examined before the
+actual arguments to PMake are. In addition, all flags given to PMake,
+either through the
+.CW PMAKE
+variable or on the command line, are placed in this environment
+variable and exported to each shell PMake executes. Thus recursive
+invocations of PMake automatically receive the same flags as the
+top-most one.
+.LP
+Using all these variables, you can compress the sample makefile even more:
+.DS
+OBJS = a.o b.o c.o
+program : $(OBJS)
+ cc $(.ALLSRC) \-o $(.TARGET)
+$(OBJS) : defs.h
+a.o : a.c
+ cc \-c a.c
+b.o : b.c
+ cc \-c b.c
+c.o : c.c
+ cc \-c c.c
+.DE
+.Ix 0 ref variable local .ALLSRC
+.Ix 0 ref .ALLSRC
+.Ix 0 ref variable local .TARGET
+.Ix 0 ref .TARGET
+.Rd 3
+.xH 2 Comments
+.LP
+.Ix 0 def comments
+Comments in a makefile start with a `#' character and extend to the
+end of the line. They may appear
+anywhere you want them, except in a shell command (though the shell
+will treat it as a comment, too). If, for some reason, you need to use the `#'
+in a variable or on a dependency line, put a backslash in front of it.
+PMake will compress the two into a single `#' (Note: this isn't true
+if PMake is operating in full-compatibility mode).
+.Ix 0 ref flags -M
+.Ix 0 ref compatibility
+.xH 2 Parallelism
+.No
+.LP
+PMake was specifically designed to re-create several targets at once,
+when possible. You do not have to do anything special to cause this to
+happen (unless PMake was configured to not act in parallel, in which
+case you will have to make use of the
+.B \-L
+and
+.B \-J
+flags (see below)),
+.Ix 0 ref flags -L
+.Ix 0 ref flags -J
+but you do have to be careful at times.
+.LP
+There are several problems you are likely to encounter. One is
+that some makefiles (and programs) are written in such a way that it is
+impossible for two targets to be made at once. The program
+.CW xstr ,
+for example,
+always modifies the files
+.CW strings
+and
+.CW x.c .
+There is no way to change it. Thus you cannot run two of them at once
+without something being trashed. Similarly, if you have commands
+in the makefile that always send output to the same file, you will not
+be able to make more than one target at once unless you change the
+file you use. You can, for instance, add a
+.CW $$$$
+to the end of the file name to tack on the process ID of the shell
+executing the command (each
+.CW $$
+expands to a single
+.CW $ ,
+thus giving you the shell variable
+.CW $$ ).
+Since only one shell is used for all the
+commands, you'll get the same file name for each command in the
+script.
+.LP
+The other problem comes from improperly-specified dependencies that
+worked in Make because of its sequential, depth-first way of examining
+them. While I don't want to go into depth on how PMake
+works (look in chapter 4 if you're interested), I will warn you that
+files in two different ``levels'' of the dependency tree may be
+examined in a different order in PMake than they were in Make. For
+example, given the makefile
+.DS
+a : b c
+b : d
+.DE
+PMake will examine the targets in the order
+.CW c ,
+.CW d ,
+.CW b ,
+.CW a .
+If the makefile's author expected PMake to abort before making
+.CW c
+if an error occurred while making
+.CW b ,
+or if
+.CW b
+needed to exist before
+.CW c
+was made,
+s/he will be sorely disappointed. The dependencies are
+incomplete, since in both these cases,
+.CW c
+would depend on
+.CW b .
+So watch out.
+.LP
+Another problem you may face is that, while PMake is set up to handle the
+output from multiple jobs in a graceful fashion, the same is not so for input.
+It has no way to regulate input to different jobs,
+so if you use the redirection from
+.CW /dev/tty
+I mentioned earlier, you must be careful not to run two of the jobs at once.
+.xH 2 Writing and Debugging a Makefile
+.LP
+Now you know most of what's in a makefile, what do you do next? There
+are two choices: (1) use one of the uncommonly-available makefile
+generators or (2) write your own makefile (I leave out the third choice of
+ignoring PMake and doing everything by hand as being beyond the bounds
+of common sense).
+.LP
+When faced with the writing of a makefile, it is usually best to start
+from first principles: just what
+.I are
+you trying to do? What do you want the makefile finally to produce?
+.LP
+To begin with a somewhat traditional example, let's say you need to
+write a makefile to create a program,
+.CW expr ,
+that takes standard infix expressions and converts them to prefix form (for
+no readily apparent reason). You've got three source files, in C, that
+make up the program:
+.CW main.c ,
+.CW parse.c ,
+and
+.CW output.c .
+Harking back to my pithy advice about dependency lines, you write the
+first line of the file:
+.DS
+expr : main.o parse.o output.o
+.DE
+because you remember
+.CW expr
+is made from
+.CW .o
+files, not
+.CW .c
+files. Similarly for the
+.CW .o
+files you produce the lines:
+.DS
+main.o : main.c
+parse.o : parse.c
+output.o : output.c
+main.o parse.o output.o : defs.h
+.DE
+.LP
+Great. You've now got the dependencies specified. What you need now is
+commands. These commands, remember, must produce the target on the
+dependency line, usually by using the sources you've listed.
+You remember about local variables? Good, so it should come
+to you as no surprise when you write
+.DS
+expr : main.o parse.o output.o
+ cc -o $(.TARGET) $(.ALLSRC)
+.DE
+Why use the variables? If your program grows to produce postfix
+expressions too (which, of course, requires a name change or two), it
+is one fewer place you have to change the file. You cannot do this for
+the object files, however, because they depend on their corresponding
+source files
+.I and
+.CW defs.h ,
+thus if you said
+.DS
+ cc -c $(.ALLSRC)
+.DE
+you'd get (for
+.CW main.o ):
+.DS
+ cc -c main.c defs.h
+.DE
+which is wrong. So you round out the makefile with these lines:
+.DS
+main.o : main.c
+ cc -c main.c
+parse.o : parse.c
+ cc -c parse.c
+output.o : output.c
+ cc -c output.c
+.DE
+.LP
+The makefile is now complete and will, in fact, create the program you
+want it to without unnecessary compilations or excessive typing on
+your part. There are two things wrong with it, however (aside from it
+being altogether too long, something I'll address in chapter 3):
+.IP 1)
+The string
+.CW "main.o parse.o output.o" '' ``
+is repeated twice, necessitating two changes when you add postfix
+(you were planning on that, weren't you?). This is in direct violation
+of de Boor's First Rule of writing makefiles:
+.QP
+.I
+Anything that needs to be written more than once
+should be placed in a variable.
+.IP "\&"
+I cannot emphasize this enough as being very important to the
+maintenance of a makefile and its program.
+.IP 2)
+There is no way to alter the way compilations are performed short of
+editing the makefile and making the change in all places. This is evil
+and violates de Boor's Second Rule, which follows directly from the
+first:
+.QP
+.I
+Any flags or programs used inside a makefile should be placed in a variable so
+they may be changed, temporarily or permanently, with the greatest ease.
+.LP
+The makefile should more properly read:
+.DS
+OBJS = main.o parse.o output.o
+expr : $(OBJS)
+ $(CC) $(CFLAGS) -o $(.TARGET) $(.ALLSRC)
+main.o : main.c
+ $(CC) $(CFLAGS) -c main.c
+parse.o : parse.c
+ $(CC) $(CFLAGS) -c parse.c
+output.o : output.c
+ $(CC) $(CFLAGS) -c output.c
+$(OBJS) : defs.h
+.DE
+Alternatively, if you like the idea of dynamic sources mentioned in
+section 2.3.1,
+.Rm 0 2.3.1
+.Rd 4
+.Ix 0 ref "dynamic source"
+.Ix 0 ref source dynamic
+you could write it like this:
+.DS
+OBJS = main.o parse.o output.o
+expr : $(OBJS)
+ $(CC) $(CFLAGS) -o $(.TARGET) $(.ALLSRC)
+$(OBJS) : $(.PREFIX).c defs.h
+ $(CC) $(CFLAGS) -c $(.PREFIX).c
+.DE
+These two rules and examples lead to de Boor's First Corollary:
+.QP
+.I
+Variables are your friends.
+.LP
+Once you've written the makefile comes the sometimes-difficult task of
+.Ix 0 ref debugging
+making sure the darn thing works. Your most helpful tool to make sure
+the makefile is at least syntactically correct is the
+.B \-n
+.Ix 0 ref flags -n
+flag, which allows you to see if PMake will choke on the makefile. The
+second thing the
+.B \-n
+flag lets you do is see what PMake would do without it actually doing
+it, thus you can make sure the right commands would be executed were
+you to give PMake its head.
+.LP
+When you find your makefile isn't behaving as you hoped, the first
+question that comes to mind (after ``What time is it, anyway?'') is
+``Why not?'' In answering this, two flags will serve you well:
+.CW "-d m" '' ``
+.Ix 0 ref flags -d
+and
+.CW "-p 2" .'' ``
+.Ix 0 ref flags -p
+The first causes PMake to tell you as it examines each target in the
+makefile and indicate why it is deciding whatever it is deciding. You
+can then use the information printed for other targets to see where
+you went wrong. The
+.CW "-p 2" '' ``
+flag makes PMake print out its internal state when it is done,
+allowing you to see that you forgot to make that one chapter depend on
+that file of macros you just got a new version of. The output from
+.CW "-p 2" '' ``
+is intended to resemble closely a real makefile, but with additional
+information provided and with variables expanded in those commands
+PMake actually printed or executed.
+.LP
+Something to be especially careful about is circular dependencies.
+.Ix 0 def dependency circular
+E.g.
+.DS
+a : b
+b : c d
+d : a
+.DE
+In this case, because of how PMake works,
+.CW c
+is the only thing PMake will examine, because
+.CW d
+and
+.CW a
+will effectively fall off the edge of the universe, making it
+impossible to examine
+.CW b
+(or them, for that matter).
+PMake will tell you (if run in its normal mode) all the targets
+involved in any cycle it looked at (i.e. if you have two cycles in the
+graph (naughty, naughty), but only try to make a target in one of
+them, PMake will only tell you about that one. You'll have to try to
+make the other to find the second cycle). When run as Make, it will
+only print the first target in the cycle.
+.xH 2 Invoking PMake
+.LP
+.Ix 0 ref flags
+.Ix 0 ref arguments
+.Ix 0 ref usage
+PMake comes with a wide variety of flags to choose from.
+They may appear in any order, interspersed with command-line variable
+assignments and targets to create.
+The flags are as follows:
+.IP "\fB\-d\fP \fIwhat\fP"
+.Ix 0 def flags -d
+.Ix 0 ref debugging
+This causes PMake to spew out debugging information that
+may prove useful to you. If you can't
+figure out why PMake is doing what it's doing, you might try using
+this flag. The
+.I what
+parameter is a string of single characters that tell PMake what
+aspects you are interested in. Most of what I describe will make
+little sense to you, unless you've dealt with Make before. Just
+remember where this table is and come back to it as you read on.
+The characters and the information they produce are as follows:
+.RS
+.IP a
+Archive searching and caching.
+.IP c
+Conditional evaluation.
+.IP d
+The searching and caching of directories.
+.IP j
+Various snippets of information related to the running of the multiple
+shells. Not particularly interesting.
+.IP m
+The making of each target: what target is being examined; when it was
+last modified; whether it is out-of-date; etc.
+.IP p
+Makefile parsing.
+.IP r
+Remote execution.
+.IP s
+The application of suffix-transformation rules. (See chapter 3)
+.IP t
+The maintenance of the list of targets.
+.IP v
+Variable assignment.
+.RE
+.IP "\&"
+Of these all, the
+.CW m
+and
+.CW s
+letters will be most useful to you.
+If the
+.B \-d
+is the final argument or the argument from which it would get these
+key letters (see below for a note about which argument would be used)
+begins with a
+.B \- ,
+all of these debugging flags will be set, resulting in massive amounts
+of output.
+.IP "\fB\-f\fP \fImakefile\fP"
+.Ix 0 def flags -f
+Specify a makefile to read different from the standard makefiles
+.CW Makefile "\&" (
+or
+.CW makefile ).
+.Ix 0 ref makefile default
+.Ix 0 ref makefile other
+If
+.I makefile
+is ``\-'', PMake uses the standard input. This is useful for making
+quick and dirty makefiles.\|.\|.
+.Ix 0 ref makefile "quick and dirty"
+.IP \fB\-h\fP
+.Ix 0 def flags -h
+Prints out a summary of the various flags PMake accepts. It can also
+be used to find out what level of concurrency was compiled into the
+version of PMake you are using (look at
+.B \-J
+and
+.B \-L )
+and various other information on how PMake was configured.
+.Ix 0 ref configuration
+.Ix 0 ref makefilesystem
+.IP \fB\-i\fP
+.Ix 0 def flags -i
+If you give this flag, PMake will ignore non-zero status returned
+by any of its shells. It's like placing a `\-' before all the commands
+in the makefile.
+.IP \fB\-k\fP
+.Ix 0 def flags -k
+This is similar to
+.B \-i
+in that it allows PMake to continue when it sees an error, but unlike
+.B \-i ,
+where PMake continues blithely as if nothing went wrong,
+.B \-k
+causes it to recognize the error and only continue work on those
+things that don't depend on the target, either directly or indirectly (through
+depending on something that depends on it), whose creation returned the error.
+The `k' is for ``keep going''.\|.\|.
+.Ix 0 ref target
+.IP \fB\-l\fP
+.Ix 0 def flags -l
+PMake has the ability to lock a directory against other
+people executing it in the same directory (by means of a file called
+``LOCK.make'' that it creates and checks for in the directory). This
+is a Good Thing because two people doing the same thing in the same place
+can be disastrous for the final product (too many cooks and all that).
+Whether this locking is the default is up to your system
+administrator. If locking is on,
+.B \-l
+will turn it off, and vice versa. Note that this locking will not
+prevent \fIyou\fP from invoking PMake twice in the same place \*- if
+you own the lock file, PMake will warn you about it but continue to execute.
+.IP "\fB\-m\fP \fIdirectory\fP"
+.Ix 0 def flags -m
+Tells PMake another place to search for included makefiles via the <...>
+style. Several
+.B \-m
+options can be given to form a search path. If this construct is used the
+default system makefile search path is completely overridden.
+To be explained in chapter 3, section 3.2.
+.Rm 2 3.2
+.IP \fB\-n\fP
+.Ix 0 def flags -n
+This flag tells PMake not to execute the commands needed to update the
+out-of-date targets in the makefile. Rather, PMake will simply print
+the commands it would have executed and exit. This is particularly
+useful for checking the correctness of a makefile. If PMake doesn't do
+what you expect it to, it's a good chance the makefile is wrong.
+.IP "\fB\-p\fP \fInumber\fP"
+.Ix 0 def flags -p
+.Ix 0 ref debugging
+This causes PMake to print its input in a reasonable form, though
+not necessarily one that would make immediate sense to anyone but me. The
+.I number
+is a bitwise-or of 1 and 2 where 1 means it should print the input
+before doing any processing and 2 says it should print it after
+everything has been re-created. Thus
+.CW "\-p 3"
+would print it twice\*-once before processing and once after (you
+might find the difference between the two interesting). This is mostly
+useful to me, but you may find it informative in some bizarre circumstances.
+.IP \fB\-q\fP
+.Ix 0 def flags -q
+If you give PMake this flag, it will not try to re-create anything. It
+will just see if anything is out-of-date and exit non-zero if so.
+.IP \fB\-r\fP
+.Ix 0 def flags -r
+When PMake starts up, it reads a default makefile that tells it what
+sort of system it's on and gives it some idea of what to do if you
+don't tell it anything. I'll tell you about it in chapter 3. If you
+give this flag, PMake won't read the default makefile.
+.IP \fB\-s\fP
+.Ix 0 def flags -s
+This causes PMake to not print commands before they're executed. It
+is the equivalent of putting an `@' before every command in the
+makefile.
+.IP \fB\-t\fP
+.Ix 0 def flags -t
+Rather than try to re-create a target, PMake will simply ``touch'' it
+so as to make it appear up-to-date. If the target didn't exist before,
+it will when PMake finishes, but if the target did exist, it will
+appear to have been updated.
+.IP \fB\-v\fP
+.Ix 0 def flags -v
+This is a mixed-compatibility flag intended to mimic the System V
+version of Make. It is the same as giving
+.B \-B ,
+and
+.B \-V
+as well as turning off directory locking. Targets can still be created
+in parallel, however. This is the mode PMake will enter if it is
+invoked either as
+.CW smake '' ``
+or
+.CW vmake ''. ``
+.IP \fB\-x\fP
+.Ix 0 def flags -x
+This tells PMake it's ok to export jobs to other machines, if they're
+available. It is used when running in Make mode, as exporting in this
+mode tends to make things run slower than if the commands were just
+executed locally.
+.IP \fB\-B\fP
+.Ix 0 ref compatibility
+.Ix 0 def flags -B
+Forces PMake to be as backwards-compatible with Make as possible while
+still being itself.
+This includes:
+.RS
+.IP \(bu 2
+Executing one shell per shell command
+.IP \(bu 2
+Expanding anything that looks even vaguely like a variable, with the
+empty string replacing any variable PMake doesn't know.
+.IP \(bu 2
+Refusing to allow you to escape a `#' with a backslash.
+.IP \(bu 2
+Permitting undefined variables on dependency lines and conditionals
+(see below). Normally this causes PMake to abort.
+.RE
+.IP \fB\-C\fP
+.Ix 0 def flags -C
+This nullifies any and all compatibility mode flags you may have given
+or implied up to the time the
+.B \-C
+is encountered. It is useful mostly in a makefile that you wrote for PMake
+to avoid bad things happening when someone runs PMake as
+.CW make '' ``
+or has things set in the environment that tell it to be compatible.
+.B \-C
+is
+.I not
+placed in the
+.CW PMAKE
+environment variable or the
+.CW .MAKEFLAGS
+or
+.CW MFLAGS
+global variables.
+.Ix 0 ref variable environment PMAKE
+.Ix 0 ref variable global .MAKEFLAGS
+.Ix 0 ref variable global MFLAGS
+.Ix 0 ref .MAKEFLAGS variable
+.Ix 0 ref MFLAGS
+.IP "\fB\-D\fP \fIvariable\fP"
+.Ix 0 def flags -D
+Allows you to define a variable to have
+.CW 1 '' ``
+as its value. The variable is a global variable, not a command-line
+variable. This is useful mostly for people who are used to the C
+compiler arguments and those using conditionals, which I'll get into
+in section 4.3
+.Rm 1 4.3
+.IP "\fB\-I\fP \fIdirectory\fP"
+.Ix 0 def flags -I
+Tells PMake another place to search for included makefiles. Yet
+another thing to be explained in chapter 3 (section 3.2, to be
+precise).
+.Rm 2 3.2
+.IP "\fB\-J\fP \fInumber\fP"
+.Ix 0 def flags -J
+Gives the absolute maximum number of targets to create at once on both
+local and remote machines.
+.IP "\fB\-L\fP \fInumber\fP"
+.Ix 0 def flags -L
+This specifies the maximum number of targets to create on the local
+machine at once. This may be 0, though you should be wary of doing
+this, as PMake may hang until a remote machine becomes available, if
+one is not available when it is started.
+.IP \fB\-M\fP
+.Ix 0 ref compatibility
+.Ix 0 def flags -M
+This is the flag that provides absolute, complete, full compatibility
+with Make. It still allows you to use all but a few of the features of
+PMake, but it is non-parallel. This is the mode PMake enters if you
+call it
+.CW make .'' ``
+.IP \fB\-P\fP
+.Ix 0 def flags -P
+.Ix 0 ref "output control"
+When creating targets in parallel, several shells are executing at
+once, each wanting to write its own two cent's-worth to the screen.
+This output must be captured by PMake in some way in order to prevent
+the screen from being filled with garbage even more indecipherable
+than you usually see. PMake has two ways of doing this, one of which
+provides for much cleaner output and a clear separation between the
+output of different jobs, the other of which provides a more immediate
+response so one can tell what is really happening. The former is done
+by notifying you when the creation of a target starts, capturing the
+output and transferring it to the screen all at once when the job
+finishes. The latter is done by catching the output of the shell (and
+its children) and buffering it until an entire line is received, then
+printing that line preceded by an indication of which job produced
+the output. Since I prefer this second method, it is the one used by
+default. The first method will be used if you give the
+.B \-P
+flag to PMake.
+.IP \fB\-V\fP
+.Ix 0 def flags -V
+As mentioned before, the
+.B \-V
+flag tells PMake to use Make's style of expanding variables,
+substituting the empty string for any variable it doesn't know.
+.IP \fB\-W\fP
+.Ix 0 def flags -W
+There are several times when PMake will print a message at you that is
+only a warning, i.e. it can continue to work in spite of your having
+done something silly (such as forgotten a leading tab for a shell
+command). Sometimes you are well aware of silly things you have done
+and would like PMake to stop bothering you. This flag tells it to shut
+up about anything non-fatal.
+.IP \fB\-X\fP
+.Ix 0 def flags -X
+This flag causes PMake to not attempt to export any jobs to another
+machine.
+.LP
+Several flags may follow a single `\-'. Those flags that require
+arguments take them from successive parameters. E.g.
+.DS
+pmake -fDnI server.mk DEBUG /chip2/X/server/include
+.DE
+will cause PMake to read
+.CW server.mk
+as the input makefile, define the variable
+.CW DEBUG
+as a global variable and look for included makefiles in the directory
+.CW /chip2/X/server/include .
+.xH 2 Summary
+.LP
+A makefile is made of four types of lines:
+.RS
+.IP \(bu 2
+Dependency lines
+.IP \(bu 2
+Creation commands
+.IP \(bu 2
+Variable assignments
+.IP \(bu 2
+Comments, include statements and conditional directives
+.RE
+.LP
+A dependency line is a list of one or more targets, an operator
+.CW : ', (`
+.CW :: ', `
+or
+.CW ! '), `
+and a list of zero or more sources. Sources may contain wildcards and
+certain local variables.
+.LP
+A creation command is a regular shell command preceded by a tab. In
+addition, if the first two characters after the tab (and other
+whitespace) are a combination of
+.CW @ ' `
+or
+.CW - ', `
+PMake will cause the command to not be printed (if the character is
+.CW @ ') `
+or errors from it to be ignored (if
+.CW - '). `
+A blank line, dependency line or variable assignment terminates a
+creation script. There may be only one creation script for each target
+with a
+.CW : ' `
+or
+.CW ! ' `
+operator.
+.LP
+Variables are places to store text. They may be unconditionally
+assigned-to using the
+.CW = ' `
+.Ix 0 ref =
+.Ix 0 ref variable assignment
+operator, appended-to using the
+.CW += ' `
+.Ix 0 ref +=
+.Ix 0 ref variable assignment appended
+operator, conditionally (if the variable is undefined) assigned-to
+with the
+.CW ?= ' `
+.Ix 0 ref ?=
+.Ix 0 ref variable assignment conditional
+operator, and assigned-to with variable expansion with the
+.CW := ' `
+.Ix 0 ref :=
+.Ix 0 ref variable assignment expanded
+operator. The output of a shell command may be assigned to a variable
+using the
+.CW != ' `
+.Ix 0 ref !=
+.Ix 0 ref variable assignment shell-output
+operator. Variables may be expanded (their value inserted) by enclosing
+their name in parentheses or curly braces, preceded by a dollar sign.
+A dollar sign may be escaped with another dollar sign. Variables are
+not expanded if PMake doesn't know about them. There are seven local
+variables:
+.CW .TARGET ,
+.CW .ALLSRC ,
+.CW .OODATE ,
+.CW .PREFIX ,
+.CW .IMPSRC ,
+.CW .ARCHIVE ,
+and
+.CW .MEMBER .
+Four of them
+.CW .TARGET , (
+.CW .PREFIX ,
+.CW .ARCHIVE ,
+and
+.CW .MEMBER )
+may be used to specify ``dynamic sources.''
+.Ix 0 ref "dynamic source"
+.Ix 0 ref source dynamic
+Variables are good. Know them. Love them. Live them.
+.LP
+Debugging of makefiles is best accomplished using the
+.B \-n ,
+.B "\-d m" ,
+and
+.B "\-p 2"
+flags.
+.xH 2 Exercises
+.ce
+\s+4\fBTBA\fP\s0
+.xH 1 Short-cuts and Other Nice Things
+.LP
+Based on what I've told you so far, you may have gotten the impression
+that PMake is just a way of storing away commands and making sure you
+don't forget to compile something. Good. That's just what it is.
+However, the ways I've described have been inelegant, at best, and
+painful, at worst.
+This chapter contains things that make the
+writing of makefiles easier and the makefiles themselves shorter and
+easier to modify (and, occasionally, simpler). In this chapter, I
+assume you are somewhat more
+familiar with Sprite (or UNIX, if that's what you're using) than I did
+in chapter 2, just so you're on your toes.
+So without further ado...
+.xH 2 Transformation Rules
+.LP
+As you know, a file's name consists of two parts: a base name, which
+gives some hint as to the contents of the file, and a suffix, which
+usually indicates the format of the file.
+Over the years, as
+.UX
+has developed,
+naming conventions, with regard to suffixes, have also developed that have
+become almost as incontrovertible as Law. E.g. a file ending in
+.CW .c
+is assumed to contain C source code; one with a
+.CW .o
+suffix is assumed to be a compiled, relocatable object file that may
+be linked into any program; a file with a
+.CW .ms
+suffix is usually a text file to be processed by Troff with the \-ms
+macro package, and so on.
+One of the best aspects of both Make and PMake comes from their
+understanding of how the suffix of a file pertains to its contents and
+their ability to do things with a file based solely on its suffix. This
+ability comes from something known as a transformation rule. A
+transformation rule specifies how to change a file with one suffix
+into a file with another suffix.
+.LP
+A transformation rule looks much like a dependency line, except the
+target is made of two known suffixes stuck together. Suffixes are made
+known to PMake by placing them as sources on a dependency line whose
+target is the special target
+.CW .SUFFIXES .
+E.g.
+.DS
+\&.SUFFIXES : .o .c
+\&.c.o :
+ $(CC) $(CFLAGS) -c $(.IMPSRC)
+.DE
+The creation script attached to the target is used to transform a file with
+the first suffix (in this case,
+.CW .c )
+into a file with the second suffix (here,
+.CW .o ).
+In addition, the target inherits whatever attributes have been applied
+to the transformation rule.
+The simple rule given above says that to transform a C source file
+into an object file, you compile it using
+.CW cc
+with the
+.CW \-c
+flag.
+This rule is taken straight from the system makefile. Many
+transformation rules (and suffixes) are defined there, and I refer you
+to it for more examples (type
+.CW "pmake -h" '' ``
+to find out where it is).
+.LP
+There are several things to note about the transformation rule given
+above:
+.RS
+.IP 1)
+The
+.CW .IMPSRC
+variable.
+.Ix 0 def variable local .IMPSRC
+.Ix 0 def .IMPSRC
+This variable is set to the ``implied source'' (the file from which
+the target is being created; the one with the first suffix), which, in this
+case, is the .c file.
+.IP 2)
+The
+.CW CFLAGS
+variable. Almost all of the transformation rules in the system
+makefile are set up using variables that you can alter in your
+makefile to tailor the rule to your needs. In this case, if you want
+all your C files to be compiled with the
+.B \-g
+flag, to provide information for
+.CW dbx ,
+you would set the
+.CW CFLAGS
+variable to contain
+.CW -g
+.CW "CFLAGS = -g" '') (``
+and PMake would take care of the rest.
+.RE
+.LP
+To give you a quick example, the makefile in 2.3.4
+.Rm 3 2.3.4
+could be changed to this:
+.DS
+OBJS = a.o b.o c.o
+program : $(OBJS)
+ $(CC) -o $(.TARGET) $(.ALLSRC)
+$(OBJS) : defs.h
+.DE
+The transformation rule I gave above takes the place of the 6 lines\**
+.FS
+This is also somewhat cleaner, I think, than the dynamic source
+solution presented in 2.6
+.FE
+.Rm 4 2.6
+.DS
+a.o : a.c
+ cc -c a.c
+b.o : b.c
+ cc -c b.c
+c.o : c.c
+ cc -c c.c
+.DE
+.LP
+Now you may be wondering about the dependency between the
+.CW .o
+and
+.CW .c
+files \*- it's not mentioned anywhere in the new makefile. This is
+because it isn't needed: one of the effects of applying a
+transformation rule is the target comes to depend on the implied
+source. That's why it's called the implied
+.I source .
+.LP
+For a more detailed example. Say you have a makefile like this:
+.DS
+a.out : a.o b.o
+ $(CC) $(.ALLSRC)
+.DE
+and a directory set up like this:
+.DS
+total 4
+-rw-rw-r-- 1 deboor 34 Sep 7 00:43 Makefile
+-rw-rw-r-- 1 deboor 119 Oct 3 19:39 a.c
+-rw-rw-r-- 1 deboor 201 Sep 7 00:43 a.o
+-rw-rw-r-- 1 deboor 69 Sep 7 00:43 b.c
+.DE
+While just typing
+.CW pmake '' ``
+will do the right thing, it's much more informative to type
+.CW "pmake -d s" ''. ``
+This will show you what PMake is up to as it processes the files. In
+this case, PMake prints the following:
+.DS
+Suff_FindDeps (a.out)
+ using existing source a.o
+ applying .o -> .out to "a.o"
+Suff_FindDeps (a.o)
+ trying a.c...got it
+ applying .c -> .o to "a.c"
+Suff_FindDeps (b.o)
+ trying b.c...got it
+ applying .c -> .o to "b.c"
+Suff_FindDeps (a.c)
+ trying a.y...not there
+ trying a.l...not there
+ trying a.c,v...not there
+ trying a.y,v...not there
+ trying a.l,v...not there
+Suff_FindDeps (b.c)
+ trying b.y...not there
+ trying b.l...not there
+ trying b.c,v...not there
+ trying b.y,v...not there
+ trying b.l,v...not there
+--- a.o ---
+cc -c a.c
+--- b.o ---
+cc -c b.c
+--- a.out ---
+cc a.o b.o
+.DE
+.LP
+.CW Suff_FindDeps
+is the name of a function in PMake that is called to check for implied
+sources for a target using transformation rules.
+The transformations it tries are, naturally
+enough, limited to the ones that have been defined (a transformation
+may be defined multiple times, by the way, but only the most recent
+one will be used). You will notice, however, that there is a definite
+order to the suffixes that are tried. This order is set by the
+relative positions of the suffixes on the
+.CW .SUFFIXES
+line \*- the earlier a suffix appears, the earlier it is checked as
+the source of a transformation. Once a suffix has been defined, the
+only way to change its position in the pecking order is to remove all
+the suffixes (by having a
+.CW .SUFFIXES
+dependency line with no sources) and redefine them in the order you
+want. (Previously-defined transformation rules will be automatically
+redefined as the suffixes they involve are re-entered.)
+.LP
+Another way to affect the search order is to make the dependency
+explicit. In the above example,
+.CW a.out
+depends on
+.CW a.o
+and
+.CW b.o .
+Since a transformation exists from
+.CW .o
+to
+.CW .out ,
+PMake uses that, as indicated by the
+.CW "using existing source a.o" '' ``
+message.
+.LP
+The search for a transformation starts from the suffix of the target
+and continues through all the defined transformations, in the order
+dictated by the suffix ranking, until an existing file with the same
+base (the target name minus the suffix and any leading directories) is
+found. At that point, one or more transformation rules will have been
+found to change the one existing file into the target.
+.LP
+For example, ignoring what's in the system makefile for now, say you
+have a makefile like this:
+.DS
+\&.SUFFIXES : .out .o .c .y .l
+\&.l.c :
+ lex $(.IMPSRC)
+ mv lex.yy.c $(.TARGET)
+\&.y.c :
+ yacc $(.IMPSRC)
+ mv y.tab.c $(.TARGET)
+\&.c.o :
+ cc -c $(.IMPSRC)
+\&.o.out :
+ cc -o $(.TARGET) $(.IMPSRC)
+.DE
+and the single file
+.CW jive.l .
+If you were to type
+.CW "pmake -rd ms jive.out" ,'' ``
+you would get the following output for
+.CW jive.out :
+.DS
+Suff_FindDeps (jive.out)
+ trying jive.o...not there
+ trying jive.c...not there
+ trying jive.y...not there
+ trying jive.l...got it
+ applying .l -> .c to "jive.l"
+ applying .c -> .o to "jive.c"
+ applying .o -> .out to "jive.o"
+.DE
+and this is why: PMake starts with the target
+.CW jive.out ,
+figures out its suffix
+.CW .out ) (
+and looks for things it can transform to a
+.CW .out
+file. In this case, it only finds
+.CW .o ,
+so it looks for the file
+.CW jive.o .
+It fails to find it, so it looks for transformations into a
+.CW .o
+file. Again it has only one choice:
+.CW .c .
+So it looks for
+.CW jive.c
+and, as you know, fails to find it. At this point it has two choices:
+it can create the
+.CW .c
+file from either a
+.CW .y
+file or a
+.CW .l
+file. Since
+.CW .y
+came first on the
+.CW .SUFFIXES
+line, it checks for
+.CW jive.y
+first, but can't find it, so it looks for
+.CW jive.l
+and, lo and behold, there it is.
+At this point, it has defined a transformation path as follows:
+.CW .l
+\(->
+.CW .c
+\(->
+.CW .o
+\(->
+.CW .out
+and applies the transformation rules accordingly. For completeness,
+and to give you a better idea of what PMake actually did with this
+three-step transformation, this is what PMake printed for the rest of
+the process:
+.DS
+Suff_FindDeps (jive.o)
+ using existing source jive.c
+ applying .c -> .o to "jive.c"
+Suff_FindDeps (jive.c)
+ using existing source jive.l
+ applying .l -> .c to "jive.l"
+Suff_FindDeps (jive.l)
+Examining jive.l...modified 17:16:01 Oct 4, 1987...up-to-date
+Examining jive.c...non-existent...out-of-date
+--- jive.c ---
+lex jive.l
+\&.\|.\|. meaningless lex output deleted .\|.\|.
+mv lex.yy.c jive.c
+Examining jive.o...non-existent...out-of-date
+--- jive.o ---
+cc -c jive.c
+Examining jive.out...non-existent...out-of-date
+--- jive.out ---
+cc -o jive.out jive.o
+.DE
+.LP
+One final question remains: what does PMake do with targets that have
+no known suffix? PMake simply pretends it actually has a known suffix
+and searches for transformations accordingly.
+The suffix it chooses is the source for the
+.CW .NULL
+.Ix 0 ref .NULL
+target mentioned later. In the system makefile,
+.CW .out
+is chosen as the ``null suffix''
+.Ix 0 def suffix null
+.Ix 0 def "null suffix"
+because most people use PMake to create programs. You are, however,
+free and welcome to change it to a suffix of your own choosing.
+The null suffix is ignored, however, when PMake is in compatibility
+mode (see chapter 4).
+.xH 2 Including Other Makefiles
+.Ix 0 def makefile inclusion
+.Rd 2
+.LP
+Just as for programs, it is often useful to extract certain parts of a
+makefile into another file and just include it in other makefiles
+somehow. Many compilers allow you say something like
+.DS
+#include "defs.h"
+.DE
+to include the contents of
+.CW defs.h
+in the source file. PMake allows you to do the same thing for
+makefiles, with the added ability to use variables in the filenames.
+An include directive in a makefile looks either like this:
+.DS
+#include <file>
+.DE
+or this
+.DS
+#include "file"
+.DE
+The difference between the two is where PMake searches for the file:
+the first way, PMake will look for
+the file only in the system makefile directory (or directories)
+(to find out what that directory is, give PMake the
+.B \-h
+flag).
+.Ix 0 ref flags -h
+The system makefile directory search path can be overridden via the
+.B \-m
+option.
+.Ix 0 ref flags -m
+For files in double-quotes, the search is more complex:
+.RS
+.IP 1)
+The directory of the makefile that's including the file.
+.IP 2)
+The current directory (the one in which you invoked PMake).
+.IP 3)
+The directories given by you using
+.B \-I
+flags, in the order in which you gave them.
+.IP 4)
+Directories given by
+.CW .PATH
+dependency lines (see chapter 4).
+.IP 5)
+The system makefile directory.
+.RE
+.LP
+in that order.
+.LP
+You are free to use PMake variables in the filename\*-PMake will
+expand them before searching for the file. You must specify the
+searching method with either angle brackets or double-quotes
+.I outside
+of a variable expansion. I.e. the following
+.DS
+SYSTEM = <command.mk>
+
+#include $(SYSTEM)
+.DE
+won't work.
+.xH 2 Saving Commands
+.LP
+.Ix 0 def ...
+There may come a time when you will want to save certain commands to
+be executed when everything else is done. For instance: you're
+making several different libraries at one time and you want to create the
+members in parallel. Problem is,
+.CW ranlib
+is another one of those programs that can't be run more than once in
+the same directory at the same time (each one creates a file called
+.CW __.SYMDEF
+into which it stuffs information for the linker to use. Two of them
+running at once will overwrite each other's file and the result will
+be garbage for both parties). You might want a way to save the ranlib
+commands til the end so they can be run one after the other, thus
+keeping them from trashing each other's file. PMake allows you to do
+this by inserting an ellipsis (``.\|.\|.'') as a command between
+commands to be run at once and those to be run later.
+.LP
+So for the
+.CW ranlib
+case above, you might do this:
+.Rd 5
+.DS
+lib1.a : $(LIB1OBJS)
+ rm -f $(.TARGET)
+ ar cr $(.TARGET) $(.ALLSRC)
+ ...
+ ranlib $(.TARGET)
+
+lib2.a : $(LIB2OBJS)
+ rm -f $(.TARGET)
+ ar cr $(.TARGET) $(.ALLSRC)
+ ...
+ ranlib $(.TARGET)
+.DE
+.Ix 0 ref variable local .TARGET
+.Ix 0 ref variable local .ALLSRC
+This would save both
+.DS
+ranlib $(.TARGET)
+.DE
+commands until the end, when they would run one after the other
+(using the correct value for the
+.CW .TARGET
+variable, of course).
+.LP
+Commands saved in this manner are only executed if PMake manages to
+re-create everything without an error.
+.xH 2 Target Attributes
+.LP
+PMake allows you to give attributes to targets by means of special
+sources. Like everything else PMake uses, these sources begin with a
+period and are made up of all upper-case letters. There are various
+reasons for using them, and I will try to give examples for most of
+them. Others you'll have to find uses for yourself. Think of it as ``an
+exercise for the reader.'' By placing one (or more) of these as a source on a
+dependency line, you are ``marking the target(s) with that
+attribute.'' That's just the way I phrase it, so you know.
+.LP
+Any attributes given as sources for a transformation rule are applied
+to the target of the transformation rule when the rule is applied.
+.Ix 0 def attributes
+.Ix 0 ref source
+.Ix 0 ref target
+.nr pw 12
+.IP .DONTCARE \n(pw
+.Ix 0 def attributes .DONTCARE
+.Ix 0 def .DONTCARE
+If a target is marked with this attribute and PMake can't figure out
+how to create it, it will ignore this fact and assume the file isn't
+really needed or actually exists and PMake just can't find it. This may prove
+wrong, but the error will be noted later on, not when PMake tries to create
+the target so marked. This attribute also prevents PMake from
+attempting to touch the target if it is given the
+.B \-t
+flag.
+.Ix 0 ref flags -t
+.IP .EXEC \n(pw
+.Ix 0 def attributes .EXEC
+.Ix 0 def .EXEC
+This attribute causes its shell script to be executed while having no
+effect on targets that depend on it. This makes the target into a sort
+of subroutine. An example. Say you have some LISP files that need to
+be compiled and loaded into a LISP process. To do this, you echo LISP
+commands into a file and execute a LISP with this file as its input
+when everything's done. Say also that you have to load other files
+from another system before you can compile your files and further,
+that you don't want to go through the loading and dumping unless one
+of
+.I your
+files has changed. Your makefile might look a little bit
+like this (remember, this is an educational example, and don't worry
+about the
+.CW COMPILE
+rule, all will soon become clear, grasshopper):
+.DS
+system : init a.fasl b.fasl c.fasl
+ for i in $(.ALLSRC);
+ do
+ echo -n '(load "' >> input
+ echo -n ${i} >> input
+ echo '")' >> input
+ done
+ echo '(dump "$(.TARGET)")' >> input
+ lisp < input
+
+a.fasl : a.l init COMPILE
+b.fasl : b.l init COMPILE
+c.fasl : c.l init COMPILE
+COMPILE : .USE
+ echo '(compile "$(.ALLSRC)")' >> input
+init : .EXEC
+ echo '(load-system)' > input
+.DE
+.Ix 0 ref .USE
+.Ix 0 ref attributes .USE
+.Ix 0 ref variable local .ALLSRC
+.IP "\&"
+.CW .EXEC
+sources, don't appear in the local variables of targets that depend on
+them (nor are they touched if PMake is given the
+.B \-t
+flag).
+.Ix 0 ref flags -t
+Note that all the rules, not just that for
+.CW system ,
+include
+.CW init
+as a source. This is because none of the other targets can be made
+until
+.CW init
+has been made, thus they depend on it.
+.IP .EXPORT \n(pw
+.Ix 0 def attributes .EXPORT
+.Ix 0 def .EXPORT
+This is used to mark those targets whose creation should be sent to
+another machine if at all possible. This may be used by some
+exportation schemes if the exportation is expensive. You should ask
+your system administrator if it is necessary.
+.IP .EXPORTSAME \n(pw
+.Ix 0 def attributes .EXPORTSAME
+.Ix 0 def .EXPORTSAME
+Tells the export system that the job should be exported to a machine
+of the same architecture as the current one. Certain operations (e.g.
+running text through
+.CW nroff )
+can be performed the same on any architecture (CPU and
+operating system type), while others (e.g. compiling a program with
+.CW cc )
+must be performed on a machine with the same architecture. Not all
+export systems will support this attribute.
+.IP .IGNORE \n(pw
+.Ix 0 def attributes .IGNORE
+.Ix 0 def .IGNORE attribute
+Giving a target the
+.CW .IGNORE
+attribute causes PMake to ignore errors from any of the target's commands, as
+if they all had `\-' before them.
+.IP .INVISIBLE \n(pw
+.Ix 0 def attributes .INVISIBLE
+.Ix 0 def .INVISIBLE
+This allows you to specify one target as a source for another without
+the one affecting the other's local variables. Useful if, say, you
+have a makefile that creates two programs, one of which is used to
+create the other, so it must exist before the other is created. You
+could say
+.DS
+prog1 : $(PROG1OBJS) prog2 MAKEINSTALL
+prog2 : $(PROG2OBJS) .INVISIBLE MAKEINSTALL
+.DE
+where
+.CW MAKEINSTALL
+is some complex .USE rule (see below) that depends on the
+.Ix 0 ref .USE
+.CW .ALLSRC
+variable containing the right things. Without the
+.CW .INVISIBLE
+attribute for
+.CW prog2 ,
+the
+.CW MAKEINSTALL
+rule couldn't be applied. This is not as useful as it should be, and
+the semantics may change (or the whole thing go away) in the
+not-too-distant future.
+.IP .JOIN \n(pw
+.Ix 0 def attributes .JOIN
+.Ix 0 def .JOIN
+This is another way to avoid performing some operations in parallel
+while permitting everything else to be done so. Specifically it
+forces the target's shell script to be executed only if one or more of the
+sources was out-of-date. In addition, the target's name,
+in both its
+.CW .TARGET
+variable and all the local variables of any target that depends on it,
+is replaced by the value of its
+.CW .ALLSRC
+variable.
+As an example, suppose you have a program that has four libraries that
+compile in the same directory along with, and at the same time as, the
+program. You again have the problem with
+.CW ranlib
+that I mentioned earlier, only this time it's more severe: you
+can't just put the ranlib off to the end since the program
+will need those libraries before it can be re-created. You can do
+something like this:
+.DS
+program : $(OBJS) libraries
+ cc -o $(.TARGET) $(.ALLSRC)
+
+libraries : lib1.a lib2.a lib3.a lib4.a .JOIN
+ ranlib $(.OODATE)
+.DE
+.Ix 0 ref variable local .TARGET
+.Ix 0 ref variable local .ALLSRC
+.Ix 0 ref variable local .OODATE
+.Ix 0 ref .TARGET
+.Ix 0 ref .ALLSRC
+.Ix 0 ref .OODATE
+In this case, PMake will re-create the
+.CW $(OBJS)
+as necessary, along with
+.CW lib1.a ,
+.CW lib2.a ,
+.CW lib3.a
+and
+.CW lib4.a .
+It will then execute
+.CW ranlib
+on any library that was changed and set
+.CW program 's
+.CW .ALLSRC
+variable to contain what's in
+.CW $(OBJS)
+followed by
+.CW "lib1.a lib2.a lib3.a lib4.a" .'' ``
+In case you're wondering, it's called
+.CW .JOIN
+because it joins together different threads of the ``input graph'' at
+the target marked with the attribute.
+Another aspect of the .JOIN attribute is it keeps the target from
+being created if the
+.B \-t
+flag was given.
+.Ix 0 ref flags -t
+.IP .MAKE \n(pw
+.Ix 0 def attributes .MAKE
+.Ix 0 def .MAKE
+The
+.CW .MAKE
+attribute marks its target as being a recursive invocation of PMake.
+This forces PMake to execute the script associated with the target (if
+it's out-of-date) even if you gave the
+.B \-n
+or
+.B \-t
+flag. By doing this, you can start at the top of a system and type
+.DS
+pmake -n
+.DE
+and have it descend the directory tree (if your makefiles are set up
+correctly), printing what it would have executed if you hadn't
+included the
+.B \-n
+flag.
+.IP .NOEXPORT \n(pw
+.Ix 0 def attributes .NOEXPORT
+.Ix 0 def .NOEXPORT attribute
+If possible, PMake will attempt to export the creation of all targets to
+another machine (this depends on how PMake was configured). Sometimes,
+the creation is so simple, it is pointless to send it to another
+machine. If you give the target the
+.CW .NOEXPORT
+attribute, it will be run locally, even if you've given PMake the
+.B "\-L 0"
+flag.
+.IP .NOTMAIN \n(pw
+.Ix 0 def attributes .NOTMAIN
+.Ix 0 def .NOTMAIN
+Normally, if you do not specify a target to make in any other way,
+PMake will take the first target on the first dependency line of a
+makefile as the target to create. That target is known as the ``Main
+Target'' and is labeled as such if you print the dependencies out
+using the
+.B \-p
+flag.
+.Ix 0 ref flags -p
+Giving a target this attribute tells PMake that the target is
+definitely
+.I not
+the Main Target.
+This allows you to place targets in an included makefile and
+have PMake create something else by default.
+.IP .PRECIOUS \n(pw
+.Ix 0 def attributes .PRECIOUS
+.Ix 0 def .PRECIOUS attribute
+When PMake is interrupted (you type control-C at the keyboard), it
+will attempt to clean up after itself by removing any half-made
+targets. If a target has the
+.CW .PRECIOUS
+attribute, however, PMake will leave it alone. An additional side
+effect of the `::' operator is to mark the targets as
+.CW .PRECIOUS .
+.Ix 0 ref operator double-colon
+.Ix 0 ref ::
+.IP .SILENT \n(pw
+.Ix 0 def attributes .SILENT
+.Ix 0 def .SILENT attribute
+Marking a target with this attribute keeps its commands from being
+printed when they're executed, just as if they had an `@' in front of them.
+.IP .USE \n(pw
+.Ix 0 def attributes .USE
+.Ix 0 def .USE
+By giving a target this attribute, you turn it into PMake's equivalent
+of a macro. When the target is used as a source for another target,
+the other target acquires the commands, sources and attributes (except
+.CW .USE )
+of the source.
+If the target already has commands, the
+.CW .USE
+target's commands are added to the end. If more than one .USE-marked
+source is given to a target, the rules are applied sequentially.
+.IP "\&" \n(pw
+The typical .USE rule (as I call them) will use the sources of the
+target to which it is applied (as stored in the
+.CW .ALLSRC
+variable for the target) as its ``arguments,'' if you will.
+For example, you probably noticed that the commands for creating
+.CW lib1.a
+and
+.CW lib2.a
+in the example in section 3.3
+.Rm 5 3.3
+were exactly the same. You can use the
+.CW .USE
+attribute to eliminate the repetition, like so:
+.DS
+lib1.a : $(LIB1OBJS) MAKELIB
+lib2.a : $(LIB2OBJS) MAKELIB
+
+MAKELIB : .USE
+ rm -f $(.TARGET)
+ ar cr $(.TARGET) $(.ALLSRC)
+ ...
+ ranlib $(.TARGET)
+.DE
+.Ix 0 ref variable local .TARGET
+.Ix 0 ref variable local .ALLSRC
+.IP "\&" \n(pw
+Several system makefiles (not to be confused with The System Makefile)
+make use of these .USE rules to make your
+life easier (they're in the default, system makefile directory...take a look).
+Note that the .USE rule source itself
+.CW MAKELIB ) (
+does not appear in any of the targets's local variables.
+There is no limit to the number of times I could use the
+.CW MAKELIB
+rule. If there were more libraries, I could continue with
+.CW "lib3.a : $(LIB3OBJS) MAKELIB" '' ``
+and so on and so forth.
+.xH 2 Special Targets
+.LP
+As there were in Make, so there are certain targets that have special
+meaning to PMake. When you use one on a dependency line, it is the
+only target that may appear on the left-hand-side of the operator.
+.Ix 0 ref target
+.Ix 0 ref operator
+As for the attributes and variables, all the special targets
+begin with a period and consist of upper-case letters only.
+I won't describe them all in detail because some of them are rather
+complex and I'll describe them in more detail than you'll want in
+chapter 4.
+The targets are as follows:
+.nr pw 10
+.IP .BEGIN \n(pw
+.Ix 0 def .BEGIN
+Any commands attached to this target are executed before anything else
+is done. You can use it for any initialization that needs doing.
+.IP .DEFAULT \n(pw
+.Ix 0 def .DEFAULT
+This is sort of a .USE rule for any target (that was used only as a
+source) that PMake can't figure out any other way to create. It's only
+``sort of'' a .USE rule because only the shell script attached to the
+.CW .DEFAULT
+target is used. The
+.CW .IMPSRC
+variable of a target that inherits
+.CW .DEFAULT 's
+commands is set to the target's own name.
+.Ix 0 ref .IMPSRC
+.Ix 0 ref variable local .IMPSRC
+.IP .END \n(pw
+.Ix 0 def .END
+This serves a function similar to
+.CW .BEGIN ,
+in that commands attached to it are executed once everything has been
+re-created (so long as no errors occurred). It also serves the extra
+function of being a place on which PMake can hang commands you put off
+to the end. Thus the script for this target will be executed before
+any of the commands you save with the ``.\|.\|.''.
+.Ix 0 ref ...
+.IP .EXPORT \n(pw
+The sources for this target are passed to the exportation system compiled
+into PMake. Some systems will use these sources to configure
+themselves. You should ask your system administrator about this.
+.IP .IGNORE \n(pw
+.Ix 0 def .IGNORE target
+.Ix 0 ref .IGNORE attribute
+.Ix 0 ref attributes .IGNORE
+This target marks each of its sources with the
+.CW .IGNORE
+attribute. If you don't give it any sources, then it is like
+giving the
+.B \-i
+flag when you invoke PMake \*- errors are ignored for all commands.
+.Ix 0 ref flags -i
+.IP .INCLUDES \n(pw
+.Ix 0 def .INCLUDES target
+.Ix 0 def variable global .INCLUDES
+.Ix 0 def .INCLUDES variable
+The sources for this target are taken to be suffixes that indicate a
+file that can be included in a program source file.
+The suffix must have already been declared with
+.CW .SUFFIXES
+(see below).
+Any suffix so marked will have the directories on its search path
+(see
+.CW .PATH ,
+below) placed in the
+.CW .INCLUDES
+variable, each preceded by a
+.B \-I
+flag. This variable can then be used as an argument for the compiler
+in the normal fashion. The
+.CW .h
+suffix is already marked in this way in the system makefile.
+.Ix 0 ref makefilesystem
+E.g. if you have
+.DS
+\&.SUFFIXES : .bitmap
+\&.PATH.bitmap : /usr/local/X/lib/bitmaps
+\&.INCLUDES : .bitmap
+.DE
+PMake will place
+.CW "-I/usr/local/X/lib/bitmaps" '' ``
+in the
+.CW .INCLUDES
+variable and you can then say
+.DS
+cc $(.INCLUDES) -c xprogram.c
+.DE
+(Note: the
+.CW .INCLUDES
+variable is not actually filled in until the entire makefile has been read.)
+.IP .INTERRUPT \n(pw
+.Ix 0 def .INTERRUPT
+When PMake is interrupted,
+it will execute the commands in the script for this target, if it
+exists.
+.IP .LIBS \n(pw
+.Ix 0 def .LIBS target
+.Ix 0 def .LIBS variable
+.Ix 0 def variable global .LIBS
+This does for libraries what
+.CW .INCLUDES
+does for include files, except the flag used is
+.B \-L ,
+as required by those linkers that allow you to tell them where to find
+libraries. The variable used is
+.CW .LIBS .
+Be forewarned that PMake may not have been compiled to do this if the
+linker on your system doesn't accept the
+.B \-L
+flag, though the
+.CW .LIBS
+variable will always be defined once the makefile has been read.
+.IP .MAIN \n(pw
+.Ix 0 def .MAIN
+If you didn't give a target (or targets) to create when you invoked
+PMake, it will take the sources of this target as the targets to
+create.
+.IP .MAKEFLAGS \n(pw
+.Ix 0 def .MAKEFLAGS target
+This target provides a way for you to always specify flags for PMake
+when the makefile is used. The flags are just as they would be typed
+to the shell (except you can't use shell variables unless they're in
+the environment),
+though the
+.B \-f
+and
+.B \-r
+flags have no effect.
+.IP .NULL \n(pw
+.Ix 0 def .NULL
+.Ix 0 ref suffix null
+.Ix 0 ref "null suffix"
+This allows you to specify what suffix PMake should pretend a file has
+if, in fact, it has no known suffix. Only one suffix may be so
+designated. The last source on the dependency line is the suffix that
+is used (you should, however, only give one suffix.\|.\|.).
+.IP .PATH \n(pw
+.Ix 0 def .PATH
+If you give sources for this target, PMake will take them as
+directories in which to search for files it cannot find in the current
+directory. If you give no sources, it will clear out any directories
+added to the search path before. Since the effects of this all get
+very complex, I'll leave it til chapter four to give you a complete
+explanation.
+.IP .PATH\fIsuffix\fP \n(pw
+.Ix 0 ref .PATH
+This does a similar thing to
+.CW .PATH ,
+but it does it only for files with the given suffix. The suffix must
+have been defined already. Look at
+.B "Search Paths"
+(section 4.1)
+.Rm 6 4.1
+for more information.
+.IP .PRECIOUS \n(pw
+.Ix 0 def .PRECIOUS target
+.Ix 0 ref .PRECIOUS attribute
+.Ix 0 ref attributes .PRECIOUS
+Similar to
+.CW .IGNORE ,
+this gives the
+.CW .PRECIOUS
+attribute to each source on the dependency line, unless there are no
+sources, in which case the
+.CW .PRECIOUS
+attribute is given to every target in the file.
+.IP .RECURSIVE \n(pw
+.Ix 0 def .RECURSIVE
+.Ix 0 ref attributes .MAKE
+.Ix 0 ref .MAKE
+This target applies the
+.CW .MAKE
+attribute to all its sources. It does nothing if you don't give it any sources.
+.IP .SHELL \n(pw
+.Ix 0 def .SHELL
+PMake is not constrained to only using the Bourne shell to execute
+the commands you put in the makefile. You can tell it some other shell
+to use with this target. Check out
+.B "A Shell is a Shell is a Shell"
+(section 4.4)
+.Rm 7 4.4
+for more information.
+.IP .SILENT \n(pw
+.Ix 0 def .SILENT target
+.Ix 0 ref .SILENT attribute
+.Ix 0 ref attributes .SILENT
+When you use
+.CW .SILENT
+as a target, it applies the
+.CW .SILENT
+attribute to each of its sources. If there are no sources on the
+dependency line, then it is as if you gave PMake the
+.B \-s
+flag and no commands will be echoed.
+.IP .SUFFIXES \n(pw
+.Ix 0 def .SUFFIXES
+This is used to give new file suffixes for PMake to handle. Each
+source is a suffix PMake should recognize. If you give a
+.CW .SUFFIXES
+dependency line with no sources, PMake will forget about all the
+suffixes it knew (this also nukes the null suffix).
+For those targets that need to have suffixes defined, this is how you do it.
+.LP
+In addition to these targets, a line of the form
+.DS
+\fIattribute\fP : \fIsources\fP
+.DE
+applies the
+.I attribute
+to all the targets listed as
+.I sources .
+.xH 2 Modifying Variable Expansion
+.LP
+.Ix 0 def variable expansion modified
+.Ix 0 ref variable expansion
+.Ix 0 def variable modifiers
+Variables need not always be expanded verbatim. PMake defines several
+modifiers that may be applied to a variable's value before it is
+expanded. You apply a modifier by placing it after the variable name
+with a colon between the two, like so:
+.DS
+${\fIVARIABLE\fP:\fImodifier\fP}
+.DE
+Each modifier is a single character followed by something specific to
+the modifier itself.
+You may apply as many modifiers as you want \*- each one is applied to
+the result of the previous and is separated from the previous by
+another colon.
+.LP
+There are seven ways to modify a variable's expansion, most of which
+come from the C shell variable modification characters:
+.RS
+.IP "M\fIpattern\fP"
+.Ix 0 def :M
+.Ix 0 def modifier match
+This is used to select only those words (a word is a series of
+characters that are neither spaces nor tabs) that match the given
+.I pattern .
+The pattern is a wildcard pattern like that used by the shell, where
+.CW *
+means 0 or more characters of any sort;
+.CW ?
+is any single character;
+.CW [abcd]
+matches any single character that is either `a', `b', `c' or `d'
+(there may be any number of characters between the brackets);
+.CW [0-9]
+matches any single character that is between `0' and `9' (i.e. any
+digit. This form may be freely mixed with the other bracket form), and
+`\\' is used to escape any of the characters `*', `?', `[' or `:',
+leaving them as regular characters to match themselves in a word.
+For example, the system makefile
+.CW <makedepend.mk>
+uses
+.CW "$(CFLAGS:M-[ID]*)" '' ``
+to extract all the
+.CW \-I
+and
+.CW \-D
+flags that would be passed to the C compiler. This allows it to
+properly locate include files and generate the correct dependencies.
+.IP "N\fIpattern\fP"
+.Ix 0 def :N
+.Ix 0 def modifier nomatch
+This is identical to
+.CW :M
+except it substitutes all words that don't match the given pattern.
+.IP "S/\fIsearch-string\fP/\fIreplacement-string\fP/[g]"
+.Ix 0 def :S
+.Ix 0 def modifier substitute
+Causes the first occurrence of
+.I search-string
+in the variable to be replaced by
+.I replacement-string ,
+unless the
+.CW g
+flag is given at the end, in which case all occurrences of the string
+are replaced. The substitution is performed on each word in the
+variable in turn. If
+.I search-string
+begins with a
+.CW ^ ,
+the string must match starting at the beginning of the word. If
+.I search-string
+ends with a
+.CW $ ,
+the string must match to the end of the word (these two may be
+combined to force an exact match). If a backslash precedes these two
+characters, however, they lose their special meaning. Variable
+expansion also occurs in the normal fashion inside both the
+.I search-string
+and the
+.I replacement-string ,
+.B except
+that a backslash is used to prevent the expansion of a
+.CW $ ,
+not another dollar sign, as is usual.
+Note that
+.I search-string
+is just a string, not a pattern, so none of the usual
+regular-expression/wildcard characters have any special meaning save
+.CW ^
+and
+.CW $ .
+In the replacement string,
+the
+.CW &
+character is replaced by the
+.I search-string
+unless it is preceded by a backslash.
+You are allowed to use any character except
+colon or exclamation point to separate the two strings. This so-called
+delimiter character may be placed in either string by preceding it
+with a backslash.
+.IP T
+.Ix 0 def :T
+.Ix 0 def modifier tail
+Replaces each word in the variable expansion by its last
+component (its ``tail''). For example, given
+.DS
+OBJS = ../lib/a.o b /usr/lib/libm.a
+TAILS = $(OBJS:T)
+.DE
+the variable
+.CW TAILS
+would expand to
+.CW "a.o b libm.a" .'' ``
+.IP H
+.Ix 0 def :H
+.Ix 0 def modifier head
+This is similar to
+.CW :T ,
+except that every word is replaced by everything but the tail (the
+``head''). Using the same definition of
+.CW OBJS ,
+the string
+.CW "$(OBJS:H)" '' ``
+would expand to
+.CW "../lib /usr/lib" .'' ``
+Note that the final slash on the heads is removed and
+anything without a head is replaced by the empty string.
+.IP E
+.Ix 0 def :E
+.Ix 0 def modifier extension
+.Ix 0 def modifier suffix
+.Ix 0 ref suffix "variable modifier"
+.CW :E
+replaces each word by its suffix (``extension''). So
+.CW "$(OBJS:E)" '' ``
+would give you
+.CW ".o .a" .'' ``
+.IP R
+.Ix 0 def :R
+.Ix 0 def modifier root
+.Ix 0 def modifier base
+This replaces each word by everything but the suffix (the ``root'' of
+the word).
+.CW "$(OBJS:R)" '' ``
+expands to ``
+.CW "../lib/a b /usr/lib/libm" .''
+.RE
+.LP
+In addition, the System V style of substitution is also supported.
+This looks like:
+.DS
+$(\fIVARIABLE\fP:\fIsearch-string\fP=\fIreplacement\fP)
+.DE
+It must be the last modifier in the chain. The search is anchored at
+the end of each word, so only suffixes or whole words may be replaced.
+.xH 2 More on Debugging
+.xH 2 More Exercises
+.IP (3.1)
+You've got a set programs, each of which is created from its own
+assembly-language source file (suffix
+.CW .asm ).
+Each program can be assembled into two versions, one with error-checking
+code assembled in and one without. You could assemble them into files
+with different suffixes
+.CW .eobj \& (
+and
+.CW .obj ,
+for instance), but your linker only understands files that end in
+.CW .obj .
+To top it all off, the final executables
+.I must
+have the suffix
+.CW .exe .
+How can you still use transformation rules to make your life easier
+(Hint: assume the error-checking versions have
+.CW ec
+tacked onto their prefix)?
+.IP (3.2)
+Assume, for a moment or two, you want to perform a sort of
+``indirection'' by placing the name of a variable into another one,
+then you want to get the value of the first by expanding the second
+somehow. Unfortunately, PMake doesn't allow constructs like
+.DS I
+$($(FOO))
+.DE
+What do you do? Hint: no further variable expansion is performed after
+modifiers are applied, thus if you cause a $ to occur in the
+expansion, that's what will be in the result.
+.xH 1 PMake for Gods
+.LP
+This chapter is devoted to those facilities in PMake that allow you to
+do a great deal in a makefile with very little work, as well as do
+some things you couldn't do in Make without a great deal of work (and
+perhaps the use of other programs). The problem with these features,
+is they must be handled with care, or you will end up with a mess.
+.LP
+Once more, I assume a greater familiarity with
+.UX
+or Sprite than I did in the previous two chapters.
+.xH 2 Search Paths
+.Rd 6
+.LP
+PMake supports the dispersal of files into multiple directories by
+allowing you to specify places to look for sources with
+.CW .PATH
+targets in the makefile. The directories you give as sources for these
+targets make up a ``search path.'' Only those files used exclusively
+as sources are actually sought on a search path, the assumption being
+that anything listed as a target in the makefile can be created by the
+makefile and thus should be in the current directory.
+.LP
+There are two types of search paths
+in PMake: one is used for all types of files (including included
+makefiles) and is specified with a plain
+.CW .PATH
+target (e.g.
+.CW ".PATH : RCS" ''), ``
+while the other is specific to a certain type of file, as indicated by
+the file's suffix. A specific search path is indicated by immediately following
+the
+.CW .PATH
+with the suffix of the file. For instance
+.DS
+\&.PATH.h : /sprite/lib/include /sprite/att/lib/include
+.DE
+would tell PMake to look in the directories
+.CW /sprite/lib/include
+and
+.CW /sprite/att/lib/include
+for any files whose suffix is
+.CW .h .
+.LP
+The current directory is always consulted first to see if a file
+exists. Only if it cannot be found there are the directories in the
+specific search path, followed by those in the general search path,
+consulted.
+.LP
+A search path is also used when expanding wildcard characters. If the
+pattern has a recognizable suffix on it, the path for that suffix will
+be used for the expansion. Otherwise the default search path is employed.
+.LP
+When a file is found in some directory other than the current one, all
+local variables that would have contained the target's name
+.CW .ALLSRC , (
+and
+.CW .IMPSRC )
+will instead contain the path to the file, as found by PMake.
+Thus if you have a file
+.CW ../lib/mumble.c
+and a makefile
+.DS
+\&.PATH.c : ../lib
+mumble : mumble.c
+ $(CC) -o $(.TARGET) $(.ALLSRC)
+.DE
+the command executed to create
+.CW mumble
+would be
+.CW "cc -o mumble ../lib/mumble.c" .'' ``
+(As an aside, the command in this case isn't strictly necessary, since
+it will be found using transformation rules if it isn't given. This is because
+.CW .out
+is the null suffix by default and a transformation exists from
+.CW .c
+to
+.CW .out .
+Just thought I'd throw that in.)
+.LP
+If a file exists in two directories on the same search path, the file
+in the first directory on the path will be the one PMake uses. So if
+you have a large system spread over many directories, it would behoove
+you to follow a naming convention that avoids such conflicts.
+.LP
+Something you should know about the way search paths are implemented
+is that each directory is read, and its contents cached, exactly once
+\&\*- when it is first encountered \*- so any changes to the
+directories while PMake is running will not be noted when searching
+for implicit sources, nor will they be found when PMake attempts to
+discover when the file was last modified, unless the file was created in the
+current directory. While people have suggested that PMake should read
+the directories each time, my experience suggests that the caching seldom
+causes problems. In addition, not caching the directories slows things
+down enormously because of PMake's attempts to apply transformation
+rules through non-existent files \*- the number of extra file-system
+searches is truly staggering, especially if many files without
+suffixes are used and the null suffix isn't changed from
+.CW .out .
+.xH 2 Archives and Libraries
+.LP
+.UX
+and Sprite allow you to merge files into an archive using the
+.CW ar
+command. Further, if the files are relocatable object files, you can
+run
+.CW ranlib
+on the archive and get yourself a library that you can link into any
+program you want. The main problem with archives is they double the
+space you need to store the archived files, since there's one copy in
+the archive and one copy out by itself. The problem with libraries is
+you usually think of them as
+.CW -lm
+rather than
+.CW /usr/lib/libm.a
+and the linker thinks they're out-of-date if you so much as look at
+them.
+.LP
+PMake solves the problem with archives by allowing you to tell it to
+examine the files in the archives (so you can remove the individual
+files without having to regenerate them later). To handle the problem
+with libraries, PMake adds an additional way of deciding if a library
+is out-of-date:
+.IP \(bu 2
+If the table of contents is older than the library, or is missing, the
+library is out-of-date.
+.LP
+A library is any target that looks like
+.CW \-l name'' ``
+or that ends in a suffix that was marked as a library using the
+.CW .LIBS
+target.
+.CW .a
+is so marked in the system makefile.
+.LP
+Members of an archive are specified as
+``\fIarchive\fP(\fImember\fP[ \fImember\fP...])''.
+Thus
+.CW libdix.a(window.o) '' ``'
+specifies the file
+.CW window.o
+in the archive
+.CW libdix.a .
+You may also use wildcards to specify the members of the archive. Just
+remember that most the wildcard characters will only find
+.I existing
+files.
+.LP
+A file that is a member of an archive is treated specially. If the
+file doesn't exist, but it is in the archive, the modification time
+recorded in the archive is used for the file when determining if the
+file is out-of-date. When figuring out how to make an archived member target
+(not the file itself, but the file in the archive \*- the
+\fIarchive\fP(\fImember\fP) target), special care is
+taken with the transformation rules, as follows:
+.IP \(bu 2
+\&\fIarchive\fP(\fImember\fP) is made to depend on \fImember\fP.
+.IP \(bu 2
+The transformation from the \fImember\fP's suffix to the
+\fIarchive\fP's suffix is applied to the \fIarchive\fP(\fImember\fP) target.
+.IP \(bu 2
+The \fIarchive\fP(\fImember\fP)'s
+.CW .TARGET
+variable is set to the name of the \fImember\fP if \fImember\fP is
+actually a target, or the path to the member file if \fImember\fP is
+only a source.
+.IP \(bu 2
+The
+.CW .ARCHIVE
+variable for the \fIarchive\fP(\fImember\fP) target is set to the name
+of the \fIarchive\fP.
+.Ix 0 def variable local .ARCHIVE
+.Ix 0 def .ARCHIVE
+.IP \(bu 2
+The
+.CW .MEMBER
+variable is set to the actual string inside the parentheses. In most
+cases, this will be the same as the
+.CW .TARGET
+variable.
+.Ix 0 def variable local .MEMBER
+.Ix 0 def .MEMBER
+.IP \(bu 2
+The \fIarchive\fP(\fImember\fP)'s place in the local variables of the
+targets that depend on it is taken by the value of its
+.CW .TARGET
+variable.
+.LP
+Thus, a program library could be created with the following makefile:
+.DS
+\&.o.a :
+ ...
+ rm -f $(.TARGET:T)
+OBJS = obj1.o obj2.o obj3.o
+libprog.a : libprog.a($(OBJS))
+ ar cru $(.TARGET) $(.OODATE)
+ ranlib $(.TARGET)
+.DE
+This will cause the three object files to be compiled (if the
+corresponding source files were modified after the object file or, if
+that doesn't exist, the archived object file), the out-of-date ones
+archived in
+.CW libprog.a ,
+a table of contents placed in the archive and the newly-archived
+object files to be removed.
+.LP
+All this is used in the
+.CW makelib.mk
+system makefile to create a single library with ease. This makefile
+looks like this:
+.DS
+.SM
+#
+# Rules for making libraries. The object files that make up the library
+# are removed once they are archived.
+#
+# To make several libraries in parallel, you should define the variable
+# "many_libraries". This will serialize the invocations of ranlib.
+#
+# To use, do something like this:
+#
+# OBJECTS = <files in the library>
+#
+# fish.a: fish.a($(OBJECTS)) MAKELIB
+#
+#
+
+#ifndef _MAKELIB_MK
+_MAKELIB_MK =
+
+#include <po.mk>
+
+\&.po.a .o.a :
+ ...
+ rm -f $(.MEMBER)
+
+ARFLAGS ?= crl
+
+#
+# Re-archive the out-of-date members and recreate the library's table of
+# contents using ranlib. If many_libraries is defined, put the ranlib
+# off til the end so many libraries can be made at once.
+#
+MAKELIB : .USE .PRECIOUS
+ ar $(ARFLAGS) $(.TARGET) $(.OODATE)
+#ifndef no_ranlib
+# ifdef many_libraries
+ ...
+# endif many_libraries
+ ranlib $(.TARGET)
+#endif no_ranlib
+
+#endif _MAKELIB_MK
+.DE
+.xH 2 On the Condition...
+.Rd 1
+.LP
+Like the C compiler before it, PMake allows you to configure the makefile,
+based on the current environment, using conditional statements. A
+conditional looks like this:
+.DS
+#if \fIboolean expression\fP
+\fIlines\fP
+#elif \fIanother boolean expression\fP
+\fImore lines\fP
+#else
+\fIstill more lines\fP
+#endif
+.DE
+They may be nested to a maximum depth of 30 and may occur anywhere
+(except in a comment, of course). The
+.CW # '' ``
+must the very first character on the line.
+.LP
+Each
+.I "boolean expression"
+is made up of terms that look like function calls, the standard C
+boolean operators
+.CW && ,
+.CW || ,
+and
+.CW ! ,
+and the standard relational operators
+.CW == ,
+.CW != ,
+.CW > ,
+.CW >= ,
+.CW < ,
+and
+.CW <= ,
+with
+.CW ==
+and
+.CW !=
+being overloaded to allow string comparisons as well.
+.CW &&
+represents logical AND;
+.CW ||
+is logical OR and
+.CW !
+is logical NOT. The arithmetic and string operators take precedence
+over all three of these operators, while NOT takes precedence over
+AND, which takes precedence over OR. This precedence may be
+overridden with parentheses, and an expression may be parenthesized to
+your heart's content. Each term looks like a call on one of four
+functions:
+.nr pw 9
+.Ix 0 def make
+.Ix 0 def conditional make
+.Ix 0 def if make
+.IP make \n(pw
+The syntax is
+.CW make( \fItarget\fP\c
+.CW )
+where
+.I target
+is a target in the makefile. This is true if the given target was
+specified on the command line, or as the source for a
+.CW .MAIN
+target (note that the sources for
+.CW .MAIN
+are only used if no targets were given on the command line).
+.IP defined \n(pw
+.Ix 0 def defined
+.Ix 0 def conditional defined
+.Ix 0 def if defined
+The syntax is
+.CW defined( \fIvariable\fP\c
+.CW )
+and is true if
+.I variable
+is defined. Certain variables are defined in the system makefile that
+identify the system on which PMake is being run.
+.IP exists \n(pw
+.Ix 0 def exists
+.Ix 0 def conditional exists
+.Ix 0 def if exists
+The syntax is
+.CW exists( \fIfile\fP\c
+.CW )
+and is true if the file can be found on the global search path (i.e.
+that defined by
+.CW .PATH
+targets, not by
+.CW .PATH \fIsuffix\fP
+targets).
+.IP empty \n(pw
+.Ix 0 def empty
+.Ix 0 def conditional empty
+.Ix 0 def if empty
+This syntax is much like the others, except the string inside the
+parentheses is of the same form as you would put between parentheses
+when expanding a variable, complete with modifiers and everything. The
+function returns true if the resulting string is empty (NOTE: an undefined
+variable in this context will cause at the very least a warning
+message about a malformed conditional, and at the worst will cause the
+process to stop once it has read the makefile. If you want to check
+for a variable being defined or empty, use the expression
+.CW !defined( \fIvar\fP\c ``
+.CW ") || empty(" \fIvar\fP\c
+.CW ) ''
+as the definition of
+.CW ||
+will prevent the
+.CW empty()
+from being evaluated and causing an error, if the variable is
+undefined). This can be used to see if a variable contains a given
+word, for example:
+.DS
+#if !empty(\fIvar\fP:M\fIword\fP)
+.DE
+.LP
+The arithmetic and string operators may only be used to test the value
+of a variable. The lefthand side must contain the variable expansion,
+while the righthand side contains either a string, enclosed in
+double-quotes, or a number. The standard C numeric conventions (except
+for specifying an octal number) apply to both sides. E.g.
+.DS
+#if $(OS) == 4.3
+
+#if $(MACHINE) == "sun3"
+
+#if $(LOAD_ADDR) < 0xc000
+.DE
+are all valid conditionals. In addition, the numeric value of a
+variable can be tested as a boolean as follows:
+.DS
+#if $(LOAD)
+.DE
+would see if
+.CW LOAD
+contains a non-zero value and
+.DS
+#if !$(LOAD)
+.DE
+would test if
+.CW LOAD
+contains a zero value.
+.LP
+In addition to the bare
+.CW #if ,'' ``
+there are other forms that apply one of the first two functions to each
+term. They are as follows:
+.DS
+ ifdef \fRdefined\fP
+ ifndef \fR!defined\fP
+ ifmake \fRmake\fP
+ ifnmake \fR!make\fP
+.DE
+There are also the ``else if'' forms:
+.CW elif ,
+.CW elifdef ,
+.CW elifndef ,
+.CW elifmake ,
+and
+.CW elifnmake .
+.LP
+For instance, if you wish to create two versions of a program, one of which
+is optimized (the production version) and the other of which is for debugging
+(has symbols for dbx), you have two choices: you can create two
+makefiles, one of which uses the
+.CW \-g
+flag for the compilation, while the other uses the
+.CW \-O
+flag, or you can use another target (call it
+.CW debug )
+to create the debug version. The construct below will take care of
+this for you. I have also made it so defining the variable
+.CW DEBUG
+(say with
+.CW "pmake -D DEBUG" )
+will also cause the debug version to be made.
+.DS
+#if defined(DEBUG) || make(debug)
+CFLAGS += -g
+#else
+CFLAGS += -O
+#endif
+.DE
+There are, of course, problems with this approach. The most glaring
+annoyance is that if you want to go from making a debug version to
+making a production version, you have to remove all the object files,
+or you will get some optimized and some debug versions in the same
+program. Another annoyance is you have to be careful not to make two
+targets that ``conflict'' because of some conditionals in the
+makefile. For instance
+.DS
+#if make(print)
+FORMATTER = ditroff -Plaser_printer
+#endif
+#if make(draft)
+FORMATTER = nroff -Pdot_matrix_printer
+#endif
+.DE
+would wreak havoc if you tried
+.CW "pmake draft print" '' ``
+since you would use the same formatter for each target. As I said,
+this all gets somewhat complicated.
+.xH 2 A Shell is a Shell is a Shell
+.Rd 7
+.LP
+In normal operation, the Bourne Shell (better known as
+.CW sh '') ``
+is used to execute the commands to re-create targets. PMake also allows you
+to specify a different shell for it to use when executing these
+commands. There are several things PMake must know about the shell you
+wish to use. These things are specified as the sources for the
+.CW .SHELL
+.Ix 0 ref .SHELL
+.Ix 0 ref target .SHELL
+target by keyword, as follows:
+.IP "\fBpath=\fP\fIpath\fP"
+PMake needs to know where the shell actually resides, so it can
+execute it. If you specify this and nothing else, PMake will use the
+last component of the path and look in its table of the shells it
+knows and use the specification it finds, if any. Use this if you just
+want to use a different version of the Bourne or C Shell (yes, PMake knows
+how to use the C Shell too).
+.IP "\fBname=\fP\fIname\fP"
+This is the name by which the shell is to be known. It is a single
+word and, if no other keywords are specified (other than
+.B path ),
+it is the name by which PMake attempts to find a specification for
+it (as mentioned above). You can use this if you would just rather use
+the C Shell than the Bourne Shell
+.CW ".SHELL: name=csh" '' (``
+will do it).
+.IP "\fBquiet=\fP\fIecho-off command\fP"
+As mentioned before, PMake actually controls whether commands are
+printed by introducing commands into the shell's input stream. This
+keyword, and the next two, control what those commands are. The
+.B quiet
+keyword is the command used to turn echoing off. Once it is turned
+off, echoing is expected to remain off until the echo-on command is given.
+.IP "\fBecho=\fP\fIecho-on command\fP"
+The command PMake should give to turn echoing back on again.
+.IP "\fBfilter=\fP\fIprinted echo-off command\fP"
+Many shells will echo the echo-off command when it is given. This
+keyword tells PMake in what format the shell actually prints the
+echo-off command. Wherever PMake sees this string in the shell's
+output, it will delete it and any following whitespace, up to and
+including the next newline. See the example at the end of this section
+for more details.
+.IP "\fBechoFlag=\fP\fIflag to turn echoing on\fP"
+Unless a target has been marked
+.CW .SILENT ,
+PMake wants to start the shell running with echoing on. To do this, it
+passes this flag to the shell as one of its arguments. If either this
+or the next flag begins with a `\-', the flags will be passed to the
+shell as separate arguments. Otherwise, the two will be concatenated
+(if they are used at the same time, of course).
+.IP "\fBerrFlag=\fP\fIflag to turn error checking on\fP"
+Likewise, unless a target is marked
+.CW .IGNORE ,
+PMake wishes error-checking to be on from the very start. To this end,
+it will pass this flag to the shell as an argument. The same rules for
+an initial `\-' apply as for the
+.B echoFlag .
+.IP "\fBcheck=\fP\fIcommand to turn error checking on\fP"
+Just as for echo-control, error-control is achieved by inserting
+commands into the shell's input stream. This is the command to make
+the shell check for errors. It also serves another purpose if the
+shell doesn't have error-control as commands, but I'll get into that
+in a minute. Again, once error checking has been turned on, it is
+expected to remain on until it is turned off again.
+.IP "\fBignore=\fP\fIcommand to turn error checking off\fP"
+This is the command PMake uses to turn error checking off. It has
+another use if the shell doesn't do error-control, but I'll tell you
+about that.\|.\|.\|now.
+.IP "\fBhasErrCtl=\fP\fIyes or no\fP"
+This takes a value that is either
+.B yes
+or
+.B no .
+Now you might think that the existence of the
+.B check
+and
+.B ignore
+keywords would be enough to tell PMake if the shell can do
+error-control, but you'd be wrong. If
+.B hasErrCtl
+is
+.B yes ,
+PMake uses the check and ignore commands in a straight-forward manner.
+If this is
+.B no ,
+however, their use is rather different. In this case, the check
+command is used as a template, in which the string
+.B %s
+is replaced by the command that's about to be executed, to produce a
+command for the shell that will echo the command to be executed. The
+ignore command is also used as a template, again with
+.B %s
+replaced by the command to be executed, to produce a command that will
+execute the command to be executed and ignore any error it returns.
+When these strings are used as templates, you must provide newline(s)
+.CW \en '') (``
+in the appropriate place(s).
+.LP
+The strings that follow these keywords may be enclosed in single or
+double quotes (the quotes will be stripped off) and may contain the
+usual C backslash-characters (\en is newline, \er is return, \eb is
+backspace, \e' escapes a single-quote inside single-quotes, \e"
+escapes a double-quote inside double-quotes). Now for an example.
+.LP
+This is actually the contents of the
+.CW <shx.mk>
+system makefile, and causes PMake to use the Bourne Shell in such a
+way that each command is printed as it is executed. That is, if more
+than one command is given on a line, each will be printed separately.
+Similarly, each time the body of a loop is executed, the commands
+within that loop will be printed, etc. The specification runs like
+this:
+.DS
+#
+# This is a shell specification to have the Bourne shell echo
+# the commands just before executing them, rather than when it reads
+# them. Useful if you want to see how variables are being expanded, etc.
+#
+\&.SHELL : path=/bin/sh \e
+ quiet="set -" \e
+ echo="set -x" \e
+ filter="+ set - " \e
+ echoFlag=x \e
+ errFlag=e \e
+ hasErrCtl=yes \e
+ check="set -e" \e
+ ignore="set +e"
+.DE
+.LP
+It tells PMake the following:
+.Bp
+The shell is located in the file
+.CW /bin/sh .
+It need not tell PMake that the name of the shell is
+.CW sh
+as PMake can figure that out for itself (it's the last component of
+the path).
+.Bp
+The command to stop echoing is
+.CW "set -" .
+.Bp
+The command to start echoing is
+.CW "set -x" .
+.Bp
+When the echo off command is executed, the shell will print
+.CW "+ set - "
+(The `+' comes from using the
+.CW \-x
+flag (rather than the
+.CW \-v
+flag PMake usually uses)). PMake will remove all occurrences of this
+string from the output, so you don't notice extra commands you didn't
+put there.
+.Bp
+The flag the Bourne Shell will take to start echoing in this way is
+the
+.CW \-x
+flag. The Bourne Shell will only take its flag arguments concatenated
+as its first argument, so neither this nor the
+.B errFlag
+specification begins with a \-.
+.Bp
+The flag to use to turn error-checking on from the start is
+.CW \-e .
+.Bp
+The shell can turn error-checking on and off, and the commands to do
+so are
+.CW "set +e"
+and
+.CW "set -e" ,
+respectively.
+.LP
+I should note that this specification is for Bourne Shells that are
+not part of Berkeley
+.UX ,
+as shells from Berkeley don't do error control. You can get a similar
+effect, however, by changing the last three lines to be:
+.DS
+ hasErrCtl=no \e
+ check="echo \e"+ %s\e"\en" \e
+ ignore="sh -c '%s || exit 0\en"
+.DE
+.LP
+This will cause PMake to execute the two commands
+.DS
+echo "+ \fIcmd\fP"
+sh -c '\fIcmd\fP || true'
+.DE
+for each command for which errors are to be ignored. (In case you are
+wondering, the thing for
+.CW ignore
+tells the shell to execute another shell without error checking on and
+always exit 0, since the
+.B ||
+causes the
+.CW "exit 0"
+to be executed only if the first command exited non-zero, and if the
+first command exited zero, the shell will also exit zero, since that's
+the last command it executed).
+.xH 2 Compatibility
+.Ix 0 ref compatibility
+.LP
+There are three (well, 3 \(12) levels of backwards-compatibility built
+into PMake. Most makefiles will need none at all. Some may need a
+little bit of work to operate correctly when run in parallel. Each
+level encompasses the previous levels (e.g.
+.B \-B
+(one shell per command) implies
+.B \-V )
+The three levels are described in the following three sections.
+.xH 3 DEFCON 3 \*- Variable Expansion
+.Ix 0 ref compatibility
+.LP
+As noted before, PMake will not expand a variable unless it knows of a
+value for it. This can cause problems for makefiles that expect to
+leave variables undefined except in special circumstances (e.g. if
+more flags need to be passed to the C compiler or the output from a
+text processor should be sent to a different printer). If the
+variables are enclosed in curly braces
+.CW ${PRINTER} ''), (``
+the shell will let them pass. If they are enclosed in parentheses,
+however, the shell will declare a syntax error and the make will come
+to a grinding halt.
+.LP
+You have two choices: change the makefile to define the variables
+(their values can be overridden on the command line, since that's
+where they would have been set if you used Make, anyway) or always give the
+.B \-V
+flag (this can be done with the
+.CW .MAKEFLAGS
+target, if you want).
+.xH 3 DEFCON 2 \*- The Number of the Beast
+.Ix 0 ref compatibility
+.LP
+Then there are the makefiles that expect certain commands, such as
+changing to a different directory, to not affect other commands in a
+target's creation script. You can solve this is either by going
+back to executing one shell per command (which is what the
+.B \-B
+flag forces PMake to do), which slows the process down a good bit and
+requires you to use semicolons and escaped newlines for shell constructs, or
+by changing the makefile to execute the offending command(s) in a subshell
+(by placing the line inside parentheses), like so:
+.DS
+install :: .MAKE
+ (cd src; $(.PMAKE) install)
+ (cd lib; $(.PMAKE) install)
+ (cd man; $(.PMAKE) install)
+.DE
+.Ix 0 ref operator double-colon
+.Ix 0 ref variable global .PMAKE
+.Ix 0 ref .PMAKE
+.Ix 0 ref .MAKE
+.Ix 0 ref attribute .MAKE
+This will always execute the three makes (even if the
+.B \-n
+flag was given) because of the combination of the ``::'' operator and
+the
+.CW .MAKE
+attribute. Each command will change to the proper directory to perform
+the install, leaving the main shell in the directory in which it started.
+.xH 3 "DEFCON 1 \*- Imitation is the Not the Highest Form of Flattery"
+.Ix 0 ref compatibility
+.LP
+The final category of makefile is the one where every command requires
+input, the dependencies are incompletely specified, or you simply
+cannot create more than one target at a time, as mentioned earlier. In
+addition, you may not have the time or desire to upgrade the makefile
+to run smoothly with PMake. If you are the conservative sort, this is
+the compatibility mode for you. It is entered either by giving PMake
+the
+.B \-M
+flag (for Make), or by executing PMake as
+.CW make .'' ``
+In either case, PMake performs things exactly like Make (while still
+supporting most of the nice new features PMake provides). This
+includes:
+.IP \(bu 2
+No parallel execution.
+.IP \(bu 2
+Targets are made in the exact order specified by the makefile. The
+sources for each target are made in strict left-to-right order, etc.
+.IP \(bu 2
+A single Bourne shell is used to execute each command, thus the
+shell's
+.CW $$
+variable is useless, changing directories doesn't work across command
+lines, etc.
+.IP \(bu 2
+If no special characters exist in a command line, PMake will break the
+command into words itself and execute the command directly, without
+executing a shell first. The characters that cause PMake to execute a
+shell are:
+.CW # ,
+.CW = ,
+.CW | ,
+.CW ^ ,
+.CW ( ,
+.CW ) ,
+.CW { ,
+.CW } ,
+.CW ; ,
+.CW & ,
+.CW < ,
+.CW > ,
+.CW * ,
+.CW ? ,
+.CW [ ,
+.CW ] ,
+.CW : ,
+.CW $ ,
+.CW ` ,
+and
+.CW \e .
+You should notice that these are all the characters that are given
+special meaning by the shell (except
+.CW '
+and
+.CW " ,
+which PMake deals with all by its lonesome).
+.IP \(bu 2
+The use of the null suffix is turned off.
+.Ix 0 ref "null suffix"
+.Ix 0 ref suffix null
+.xH 2 The Way Things Work
+.LP
+When PMake reads the makefile, it parses sources and targets into
+nodes in a graph. The graph is directed only in the sense that PMake
+knows which way is up. Each node contains not only links to all its
+parents and children (the nodes that depend on it and those on which
+it depends, respectively), but also a count of the number of its
+children that have already been processed.
+.LP
+The most important thing to know about how PMake uses this graph is
+that the traversal is breadth-first and occurs in two passes.
+.LP
+After PMake has parsed the makefile, it begins with the nodes the user
+has told it to make (either on the command line, or via a
+.CW .MAIN
+target, or by the target being the first in the file not labeled with
+the
+.CW .NOTMAIN
+attribute) placed in a queue. It continues to take the node off the
+front of the queue, mark it as something that needs to be made, pass
+the node to
+.CW Suff_FindDeps
+(mentioned earlier) to find any implicit sources for the node, and
+place all the node's children that have yet to be marked at the end of
+the queue. If any of the children is a
+.CW .USE
+rule, its attributes are applied to the parent, then its commands are
+appended to the parent's list of commands and its children are linked
+to its parent. The parent's unmade children counter is then decremented
+(since the
+.CW .USE
+node has been processed). You will note that this allows a
+.CW .USE
+node to have children that are
+.CW .USE
+nodes and the rules will be applied in sequence.
+If the node has no children, it is placed at the end of
+another queue to be examined in the second pass. This process
+continues until the first queue is empty.
+.LP
+At this point, all the leaves of the graph are in the examination
+queue. PMake removes the node at the head of the queue and sees if it
+is out-of-date. If it is, it is passed to a function that will execute
+the commands for the node asynchronously. When the commands have
+completed, all the node's parents have their unmade children counter
+decremented and, if the counter is then 0, they are placed on the
+examination queue. Likewise, if the node is up-to-date. Only those
+parents that were marked on the downward pass are processed in this
+way. Thus PMake traverses the graph back up to the nodes the user
+instructed it to create. When the examination queue is empty and no
+shells are running to create a target, PMake is finished.
+.LP
+Once all targets have been processed, PMake executes the commands
+attached to the
+.CW .END
+target, either explicitly or through the use of an ellipsis in a shell
+script. If there were no errors during the entire process but there
+are still some targets unmade (PMake keeps a running count of how many
+targets are left to be made), there is a cycle in the graph. PMake does
+a depth-first traversal of the graph to find all the targets that
+weren't made and prints them out one by one.
+.xH 1 Answers to Exercises
+.IP (3.1)
+This is something of a trick question, for which I apologize. The
+trick comes from the UNIX definition of a suffix, which PMake doesn't
+necessarily share. You will have noticed that all the suffixes used in
+this tutorial (and in UNIX in general) begin with a period
+.CW .ms , (
+.CW .c ,
+etc.). Now, PMake's idea of a suffix is more like English's: it's the
+characters at the end of a word. With this in mind, one possible
+.Ix 0 def suffix
+solution to this problem goes as follows:
+.DS I
+\&.SUFFIXES : ec.exe .exe ec.obj .obj .asm
+ec.objec.exe .obj.exe :
+ link -o $(.TARGET) $(.IMPSRC)
+\&.asmec.obj :
+ asm -o $(.TARGET) -DDO_ERROR_CHECKING $(.IMPSRC)
+\&.asm.obj :
+ asm -o $(.TARGET) $(.IMPSRC)
+.DE
+.IP (3.2)
+The trick to this one lies in the ``:='' variable-assignment operator
+and the ``:S'' variable-expansion modifier.
+.Ix 0 ref variable assignment expanded
+.Ix 0 ref variable expansion modified
+.Ix 0 ref modifier substitute
+.Ix 0 ref :S
+.Ix 0 ref :=
+Basically what you want is to take the pointer variable, so to speak,
+and transform it into an invocation of the variable at which it
+points. You might try something like
+.DS I
+$(PTR:S/^/\e$(/:S/$/))
+.DE
+which places
+.CW $( '' ``
+at the front of the variable name and
+.CW ) '' ``
+at the end, thus transforming
+.CW VAR ,'' ``
+for example, into
+.CW $(VAR) ,'' ``
+which is just what we want. Unfortunately (as you know if you've tried
+it), since, as it says in the hint, PMake does no further substitution
+on the result of a modified expansion, that's \fIall\fP you get. The
+solution is to make use of ``:='' to place that string into yet
+another variable, then invoke the other variable directly:
+.DS I
+*PTR := $(PTR:S/^/\e$(/:S/$/)/)
+.DE
+You can then use
+.CW $(*PTR) '' ``
+to your heart's content.
+.de Gp
+.XP
+\&\fB\\$1:\fP
+..
+.xH 1 Glossary of Jargon
+.Gp "attribute"
+A property given to a target that causes PMake to treat it differently.
+.Gp "command script"
+The lines immediately following a dependency line that specify
+commands to execute to create each of the targets on the dependency
+line. Each line in the command script must begin with a tab.
+.Gp "command-line variable"
+A variable defined in an argument when PMake is first executed.
+Overrides all assignments to the same variable name in the makefile.
+.Gp "conditional"
+A construct much like that used in C that allows a makefile to be
+configured on the fly based on the local environment, or on what is being
+made by that invocation of PMake.
+.Gp "creation script"
+Commands used to create a target. See ``command script.''
+.Gp "dependency"
+The relationship between a source and a target. This comes in three
+flavors, as indicated by the operator between the target and the
+source. `:' gives a straight time-wise dependency (if the target is
+older than the source, the target is out-of-date), while `!' provides
+simply an ordering and always considers the target out-of-date. `::'
+is much like `:', save it creates multiple instances of a target each
+of which depends on its own list of sources.
+.Gp "dynamic source"
+This refers to a source that has a local variable invocation in it. It
+allows a single dependency line to specify a different source for each
+target on the line.
+.Gp "global variable"
+Any variable defined in a makefile. Takes precedence over variables
+defined in the environment, but not over command-line or local variables.
+.Gp "input graph"
+What PMake constructs from a makefile. Consists of nodes made of the
+targets in the makefile, and the links between them (the
+dependencies). The links are directed (from source to target) and
+there may not be any cycles (loops) in the graph.
+.Gp "local variable"
+A variable defined by PMake visible only in a target's shell script.
+There are seven local variables, not all of which are defined for
+every target:
+.CW .TARGET ,
+.CW .ALLSRC ,
+.CW .OODATE ,
+.CW .PREFIX ,
+.CW .IMPSRC ,
+.CW .ARCHIVE ,
+and
+.CW .MEMBER .
+.CW .TARGET ,
+.CW .PREFIX ,
+.CW .ARCHIVE ,
+and
+.CW .MEMBER
+may be used on dependency lines to create ``dynamic sources.''
+.Gp "makefile"
+A file that describes how a system is built. If you don't know what it
+is after reading this tutorial.\|.\|.\|.
+.Gp "modifier"
+A letter, following a colon, used to alter how a variable is expanded.
+It has no effect on the variable itself.
+.Gp "operator"
+What separates a source from a target (on a dependency line) and specifies
+the relationship between the two. There are three:
+.CW : ', `
+.CW :: ', `
+and
+.CW ! '. `
+.Gp "search path"
+A list of directories in which a file should be sought. PMake's view
+of the contents of directories in a search path does not change once
+the makefile has been read. A file is sought on a search path only if
+it is exclusively a source.
+.Gp "shell"
+A program to which commands are passed in order to create targets.
+.Gp "source"
+Anything to the right of an operator on a dependency line. Targets on
+the dependency line are usually created from the sources.
+.Gp "special target"
+A target that causes PMake to do special things when it's encountered.
+.Gp "suffix"
+The tail end of a file name. Usually begins with a period,
+.CW .c
+or
+.CW .ms ,
+e.g.
+.Gp "target"
+A word to the left of the operator on a dependency line. More
+generally, any file that PMake might create. A file may be (and often
+is) both a target and a source (what it is depends on how PMake is
+looking at it at the time \*- sort of like the wave/particle duality
+of light, you know).
+.Gp "transformation rule"
+A special construct in a makefile that specifies how to create a file
+of one type from a file of another, as indicated by their suffixes.
+.Gp "variable expansion"
+The process of substituting the value of a variable for a reference to
+it. Expansion may be altered by means of modifiers.
+.Gp "variable"
+A place in which to store text that may be retrieved later. Also used
+to define the local environment. Conditionals exist that test whether
+a variable is defined or not.
+.bp
+.\" Output table of contents last, with an entry for the index, making
+.\" sure to save and restore the last real page number for the index...
+.nr @n \n(PN+1
+.\" We are not generating an index
+.\" .XS \n(@n
+.\" Index
+.\" .XE
+.nr %% \n%
+.PX
+.nr % \n(%%
diff --git a/share/doc/psd/18.gprof/Makefile b/share/doc/psd/18.gprof/Makefile
index 1097072..2a5bed1 100644
--- a/share/doc/psd/18.gprof/Makefile
+++ b/share/doc/psd/18.gprof/Makefile
@@ -10,6 +10,5 @@ USE_SOELIM=
USE_PIC=
USE_TBL=
USE_EQN=
-SRCDIR= ${.CURDIR}/../../../../usr.bin/gprof/PSD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/psd/18.gprof/abstract.me b/share/doc/psd/18.gprof/abstract.me
new file mode 100644
index 0000000..28e8066
--- /dev/null
+++ b/share/doc/psd/18.gprof/abstract.me
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)abstract.me 8.1 (Berkeley) 6/8/93
+.\"
+.sp 1
+\fB\s+2gprof: a Call Graph Execution Profiler\s-2\fP\**
+.(f
+\**This work was supported by grant MCS80-05144
+from the National Science Foundation.
+.)f
+.sp 1
+by
+\fISusan L. Graham\fP
+\fIPeter B. Kessler\fP
+\fIMarshall K. McKusick\fP
+.sp 1
+Computer Science Division
+Electrical Engineering and Computer Science Department
+University of California, Berkeley
+Berkeley, California 94720
+.ce 0
+.sp 1
+.sp 0.5i
+.sh 0 "Abstract"
+.pp
+Large complex programs are composed of many small routines
+that implement abstractions for the routines that call them.
+To be useful, an execution profiler must attribute
+execution time in a way that is significant for the
+logical structure of a program
+as well as for its textual decomposition.
+This data must then be displayed to the user
+in a convenient and informative way.
+The \fBgprof\fP profiler
+accounts for the running time of called routines
+in the running time of the routines that call them.
+The design and use of this profiler is described.
diff --git a/share/doc/psd/18.gprof/gathering.me b/share/doc/psd/18.gprof/gathering.me
new file mode 100644
index 0000000..17130c3
--- /dev/null
+++ b/share/doc/psd/18.gprof/gathering.me
@@ -0,0 +1,231 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)gathering.me 8.1 (Berkeley) 6/8/93
+.\"
+.sh 1 "Gathering Profile Data"
+.pp
+Routine calls or statement executions can be measured by having a
+compiler augment the code at strategic points.
+The additions can be inline increments to counters [Knuth71]
+[Satterthwaite72] [Joy79] or calls to
+monitoring routines [Unix].
+The counter increment overhead is low, and is suitable for
+profiling statements.
+A call of the monitoring routine has an overhead comparable with a
+call of a regular routine, and is therefore only suited
+to profiling on a routine by routine basis.
+However, the monitoring routine solution has certain advantages.
+Whatever counters are needed by the monitoring routine can be
+managed by the monitoring routine itself, rather than being
+distributed around the code.
+In particular, a monitoring routine can easily be called from separately
+compiled programs.
+In addition, different monitoring routines can be linked into the
+program
+being measured
+to assemble different profiling data without having to
+change the compiler or recompile the program.
+We have exploited this approach;
+our compilers for C, Fortran77, and Pascal can insert calls to a
+monitoring routine in the prologue for each routine.
+Use of the monitoring routine requires no planning on part of a
+programmer other than to request that augmented routine
+prologues be produced during compilation.
+.pp
+We are interested in gathering three pieces of information during
+program execution: call counts and execution times for
+each profiled routine, and the arcs of the dynamic call graph
+traversed by this execution of the program.
+By post-processing of this data we can build the dynamic call
+graph for this execution of the program and propagate times along
+the edges of this graph to attribute times for routines to the
+routines that invoke them.
+.pp
+Gathering of the profiling information should not greatly
+interfere with the running of the program.
+Thus, the monitoring routine must not produce trace output each
+time it is invoked.
+The volume of data thus produced would be unmanageably large,
+and the time required to record it would overwhelm the running
+time of most programs.
+Similarly, the monitoring routine can not do the analysis of
+the profiling data (e.g. assembling the call graph, propagating
+times around it, discovering cycles, etc.) during program
+execution.
+Our solution is to gather profiling data in memory during program
+execution and to condense it to a file as the profiled
+program exits.
+This file is then processed by a separate program to produce the
+listing of the profile data.
+An advantage of this approach is that the profile data for
+several executions of a program can be combined by the
+post-processing to provide a profile of many
+executions.
+.pp
+The execution time monitoring consists of three parts.
+The first part allocates and initializes the runtime monitoring data
+structures before the program begins execution.
+The second part is the monitoring routine invoked from the
+prologue of each profiled routine.
+The third part condenses the data structures and writes them
+to a file as the program terminates.
+The monitoring routine is discussed in detail in the following sections.
+.sh 2 "Execution Counts"
+.pp
+The \fBgprof\fP monitoring routine counts the number of times
+each profiled routine is called.
+The monitoring routine also records the arc in the call graph
+that activated the profiled routine.
+The count is associated with the arc in the call graph
+rather than with the routine.
+Call counts for routines can then be determined by summing the counts
+on arcs directed into that routine.
+In a machine-dependent fashion, the monitoring routine notes its
+own return address.
+This address is in the prologue of some profiled routine that is
+the destination of an arc in the dynamic call graph.
+The monitoring routine also discovers the return address for that
+routine, thus identifying the call site, or source of the arc.
+The source of the arc is in the \fIcaller\fP, and the destination is in
+the \fIcallee\fP.
+For example, if a routine A calls a routine B, A is the caller,
+and B is the callee.
+The prologue of B will include a call to the monitoring routine
+that will note the arc from A to B and either initialize or
+increment a counter for that arc.
+.pp
+One can not afford to have the monitoring routine output tracing
+information as each arc is identified.
+Therefore, the monitoring routine maintains a table of all the
+arcs discovered, with counts of the numbers of times each is
+traversed during execution.
+This table is accessed once per routine call.
+Access to it
+must be as fast as possible so as not to overwhelm the time
+required to execute the program.
+.pp
+Our solution is to access the table through a hash table.
+We use the call site as the primary key with the callee
+address being the secondary key.
+Since each call site typically calls only one callee, we can
+reduce (usually to one) the number of minor lookups based on the callee.
+Another alternative would use the callee as the primary key and the
+call site as the secondary key.
+Such an organization has the advantage of associating callers with
+callees, at the expense of longer lookups in the monitoring
+routine.
+We are fortunate to be running in a virtual memory environment,
+and (for the sake of speed) were able to allocate enough space
+for the primary hash table to allow a one-to-one mapping from
+call site addresses to the primary hash table.
+Thus our hash function is trivial to calculate and collisions
+occur only for call sites that call multiple
+destinations (e.g. functional parameters and functional variables).
+A one level hash function using both call site and callee would
+result in an unreasonably large hash table.
+Further, the number of dynamic call sites and callees is not known during
+execution of the profiled program.
+.pp
+Not all callers and callees can be identified by the monitoring
+routine.
+Routines that were compiled without the profiling augmentations
+will not call the monitoring routine as part of their prologue,
+and thus no arcs will be recorded whose destinations are in these
+routines.
+One need not profile all the routines in a program.
+Routines that are not profiled run at full speed.
+Certain routines, notably exception handlers, are invoked by
+non-standard calling sequences.
+Thus the monitoring routine may know the destination of an arc
+(the callee),
+but find it difficult or
+impossible to determine the source of the arc (the caller).
+Often in these cases the apparent source of the arc is not a call
+site at all.
+Such anomalous invocations are declared ``spontaneous''.
+.sh 2 "Execution Times"
+.pp
+The execution times for routines can be gathered in at least two
+ways.
+One method measures the execution time of a routine by measuring
+the elapsed time from routine entry to routine exit.
+Unfortunately, time measurement is complicated on time-sharing
+systems by the time-slicing of the program.
+A second method samples the value of the program counter at some
+interval, and infers execution time from the distribution of the
+samples within the program.
+This technique is particularly suited to time-sharing systems,
+where the time-slicing can serve as the basis for sampling
+the program counter.
+Notice that, whereas the first method could provide exact timings,
+the second is inherently a statistical approximation.
+.pp
+The sampling method need not require support from the operating
+system: all that is needed is the ability to set and respond to
+``alarm clock'' interrupts that run relative to program time.
+It is imperative that the intervals be uniform since the
+sampling of the program counter rather than the duration of the
+interval is the basis of the distribution.
+If sampling is done too often, the interruptions to sample the
+program counter will overwhelm the running of the profiled program.
+On the other hand, the program must run for enough sampled
+intervals that the distribution of the samples accurately
+represents the distribution of time for the execution of the
+program.
+As with routine call tracing, the monitoring routine can not
+afford to output information for each program counter
+sample.
+In our computing environment, the operating system can provide a
+histogram of the location of the program counter at the end of
+each clock tick (1/60th of a second) in which a program runs.
+The histogram is assembled in memory as the program runs.
+This facility is enabled by our monitoring routine.
+We have adjusted the granularity of the histogram so that
+program counter values map one-to-one onto the histogram.
+We make the simplifying assumption that all calls to a specific
+routine require the same amount of time to execute.
+This assumption may disguise that some calls
+(or worse, some call sites) always invoke a routine
+such that its execution is faster (or slower)
+than the average time for that routine.
+.pp
+When the profiled program terminates,
+the arc table and the histogram of
+program counter samples is written to a file.
+The arc table is condensed to consist of the source and destination
+addresses of the arc and the count of the number of times the arc
+was traversed by this execution of the program.
+The recorded histogram consists of counters of the number of
+times the program counter was found to be in each of the ranges covered
+by the histogram.
+The ranges themselves are summarized as a
+lower and upper bound and a step size.
diff --git a/share/doc/psd/18.gprof/header.me b/share/doc/psd/18.gprof/header.me
new file mode 100644
index 0000000..aef606d
--- /dev/null
+++ b/share/doc/psd/18.gprof/header.me
@@ -0,0 +1,38 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)header.me 8.1 (Berkeley) 8/14/93
+.\"
+.\"he 'gprof''Graham, Kessler, McKusick'
+.\"fo 'Draft of \*(td''%'
+.\"ls 2
+.eh 'PSD:18-%''gprof \*- a Call Graph Execution Profiler'
+.oh 'gprof \*- A Call Graph Execution Profiler''PSD:18-%'
diff --git a/share/doc/psd/18.gprof/intro.me b/share/doc/psd/18.gprof/intro.me
new file mode 100644
index 0000000..3a872b2
--- /dev/null
+++ b/share/doc/psd/18.gprof/intro.me
@@ -0,0 +1,81 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)intro.me 8.1 (Berkeley) 6/8/93
+.\"
+.sh 1 "Programs to be Profiled"
+.pp
+Software research environments
+normally include many large programs
+both for production use and for experimental investigation.
+These programs are typically modular,
+in accordance with generally accepted principles
+of good program design.
+Often they consist of numerous small routines
+that implement various abstractions.
+Sometimes such large programs are written
+by one programmer
+who has understood the requirements for
+these abstractions, and has programmed them
+appropriately.
+More frequently the program has
+had multiple authors and has
+evolved over time, changing the demands placed
+on the implementation of the abstractions without
+changing the implementation itself.
+Finally, the program may be assembled from a library
+of abstraction implementations
+unexamined by the programmer.
+.pp
+Once a large program is executable,
+it is often desirable to increase its speed,
+especially if small portions of the program
+are found to dominate its execution time.
+The purpose of the \fBgprof\fP profiling tool is to
+help the user evaluate alternative implementations
+of abstractions.
+We developed this tool in response to our efforts
+to improve a code generator we were writing [Graham82].
+.pp
+The \fBgprof\fP design takes advantage of the fact that the programs
+to be measured are large, structured and hierarchical.
+We provide a profile in which the execution time
+for a set of routines that implement an
+abstraction is collected and charged
+to that abstraction.
+The profile can be used to compare and assess the costs of
+various implementations.
+.pp
+The profiler can be linked into a program without
+special planning by the programmer.
+The overhead for using \fBgprof\fP is low;
+both in terms of added execution time and in the
+volume of profiling information recorded.
diff --git a/share/doc/psd/18.gprof/postp.me b/share/doc/psd/18.gprof/postp.me
new file mode 100644
index 0000000..d71fefb
--- /dev/null
+++ b/share/doc/psd/18.gprof/postp.me
@@ -0,0 +1,190 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)postp.me 8.1 (Berkeley) 6/8/93
+.\"
+.EQ
+delim $$
+gsize 11
+.EN
+.sh 1 "Post Processing"
+.pp
+Having gathered the arcs of the call graph and timing information
+for an execution of the program,
+we are interested in attributing the time for each routine to the
+routines that call it.
+We build a dynamic call graph with arcs from caller to callee,
+and propagate time from descendants to ancestors
+by topologically sorting the call graph.
+Time propagation is performed from the leaves of the
+call graph toward the roots, according to the order
+assigned by a topological numbering algorithm.
+The topological numbering ensures that
+all edges in the graph go from higher numbered nodes to lower
+numbered nodes.
+An example is given in Figure 1.
+If we propagate time from nodes in the
+order assigned by the algorithm,
+execution time can be propagated from descendants to ancestors
+after a single traversal of each arc in the call graph.
+Each parent receives some fraction of a child's time.
+Thus time is charged to the
+caller in addition to being charged to the callee.
+.(z
+.so postp1.pic
+.ce 2
+Topological ordering
+Figure 1.
+.ce 0
+.)z
+.pp
+Let $C sub e$ be the number of calls to some routine,
+$e$, and $C sub e sup r$ be the number of
+calls from a caller $r$ to a callee $e$.
+Since we are assuming each call to a routine takes the
+average amount of time for all calls to that routine,
+the caller is accountable for
+$C sub e sup r / C sub e$
+of the time spent by the callee.
+Let the $S sub e$ be the $selftime$ of a routine, $e$.
+The selftime of a routine can be determined from the
+timing information gathered during profiled program execution.
+The total time, $T sub r$, we wish to account to a routine
+$r$, is then given by the recurrence equation:
+.EQ
+T sub r ~ = ~ {S sub r} ~ + ~
+ sum from {r ~ roman CALLS ~ e}
+ {T sub e times {{C sub e sup r} over {C sub e}}}
+.EN
+where $r ~ roman CALLS ~ e$ is a relation showing all routines
+$e$ called by a routine $r$.
+This relation is easily available from the call graph.
+.pp
+However, if the execution contains recursive calls,
+the call graph has cycles that
+cannot be topologically sorted.
+In these cases, we discover strongly-connected
+components in the call graph,
+treat each such component as a single node,
+and then sort the resulting graph.
+We use a variation of Tarjan's strongly-connected
+components algorithm
+that discovers strongly-connected components as it is assigning
+topological order numbers [Tarjan72].
+.pp
+Time propagation within strongly connected
+components is a problem.
+For example, a self-recursive routine
+(a trivial cycle in the call graph)
+is accountable for all the time it
+uses in all its recursive instantiations.
+In our scheme, this time should be
+shared among its call graph parents.
+The arcs from a routine to itself are of interest,
+but do not participate in time propagation.
+Thus the simple equation for time propagation
+does not work within strongly connected components.
+Time is not propagated from one member of a cycle to another,
+since, by definition, this involves propagating time from a routine
+to itself.
+In addition, children of one member of a cycle
+must be considered children of all members of the cycle.
+Similarly, parents of one member of the cycle must inherit
+all members of the cycle as descendants.
+It is for these reasons that we collapse connected components.
+Our solution collects all members of a cycle together,
+summing the time and call counts for all members.
+All calls into the cycle are made to share the total
+time of the cycle, and all descendants of the cycle
+propagate time into the cycle as a whole.
+Calls among the members of the cycle
+do not propagate any time,
+though they are listed in the call graph profile.
+.pp
+Figure 2 shows a modified version of the call graph of Figure 1,
+in which the nodes labelled 3 and 7 in Figure 1 are mutually
+recursive.
+The topologically sorted graph after the cycle is collapsed is
+given in Figure 3.
+.(z
+.so postp2.pic
+.ce 2
+Cycle to be collapsed.
+Figure 2.
+.ce 0
+.)z
+.(z
+.so postp3.pic
+.ce 2
+Topological numbering after cycle collapsing.
+Figure 3.
+.ce 0
+.)z
+.pp
+Since the technique described above only collects the
+dynamic call graph,
+and the program typically does not call every routine
+on each execution,
+different executions can introduce different cycles in the
+dynamic call graph.
+Since cycles often have a significant effect on time propagation,
+it is desirable to incorporate the static call graph so that cycles
+will have the same members regardless of how the program runs.
+.pp
+The static call graph can be constructed from the source text
+of the program.
+However, discovering the static call graph from the source text
+would require two moderately difficult steps:
+finding the source text for the program
+(which may not be available),
+and scanning and parsing that text,
+which may be in any one of several languages.
+.pp
+In our programming system,
+the static calling information is also contained in the
+executable version of the program,
+which we already have available,
+and which is in language-independent form.
+One can examine the instructions
+in the object program,
+looking for calls to routines, and note which
+routines can be called.
+This technique allows us to add arcs to those already in the
+dynamic call graph.
+If a statically discovered arc already exists in the dynamic call
+graph, no action is required.
+Statically discovered arcs that do not exist in the dynamic call
+graph are added to the graph with a traversal count of zero.
+Thus they are never responsible for any time propagation.
+However, they may affect the structure of the graph.
+Since they may complete strongly connected components,
+the static call graph construction is
+done before topological ordering.
diff --git a/share/doc/psd/18.gprof/postp1.pic b/share/doc/psd/18.gprof/postp1.pic
new file mode 100644
index 0000000..1446092
--- /dev/null
+++ b/share/doc/psd/18.gprof/postp1.pic
@@ -0,0 +1,54 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)postp1.pic 8.1 (Berkeley) 6/8/93
+.\"
+.PS
+circle diam .3i "8"
+circle diam .3i "9" at 1st circle + (2i,0i)
+circle diam .3i "3" at 1st circle + (0.5i,-0.5i)
+circle diam .3i "7" at 2nd circle - (0.5i, 0.5i)
+circle diam .3i "2" at 1st circle - (0i,1i)
+circle diam .3i "5" at 5th circle + (1i,0i)
+circle diam .3i "6" at 2nd circle - (0i,1i)
+circle diam .3i "1" at 3rd circle - (0i,1i)
+circle diam .3i "4" at 4th circle - (0i,1i)
+arrow from 1st circle to 3rd circle chop .15i chop .15i
+arrow from 1st circle to 4th circle chop .15i chop .15i
+arrow from 2nd circle to 4th circle chop .15i chop .15i
+arrow from 3rd circle to 5th circle chop .15i chop .15i
+arrow from 4th circle to 5th circle chop .15i chop .15i
+arrow from 4th circle to 6th circle chop .15i chop .15i
+arrow from 4th circle to 7th circle chop .15i chop .15i
+arrow from 5th circle to 8th circle chop .15i chop .15i
+arrow from 6th circle to 8th circle chop .15i chop .15i
+arrow from 6th circle to 9th circle chop .15i chop .15i
+.PE
diff --git a/share/doc/psd/18.gprof/postp2.pic b/share/doc/psd/18.gprof/postp2.pic
new file mode 100644
index 0000000..3b31736
--- /dev/null
+++ b/share/doc/psd/18.gprof/postp2.pic
@@ -0,0 +1,56 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)postp2.pic 8.1 (Berkeley) 6/8/93
+.\"
+.PS
+circle diam .3i "\(ci"
+circle diam .3i "\(ci" at 1st circle + (2i,0i)
+circle diam .3i "\(bu" at 1st circle + (0.5i,-0.5i)
+circle diam .3i "\(bu" at 2nd circle - (0.5i, 0.5i)
+circle diam .3i "\(ci" at 1st circle - (0i,1i)
+circle diam .3i "\(ci" at 5th circle + (1i,0i)
+circle diam .3i "\(ci" at 2nd circle - (0i,1i)
+circle diam .3i "\(ci" at 3rd circle - (0i,1i)
+circle diam .3i "\(ci" at 4th circle - (0i,1i)
+arrow from 1st circle to 3rd circle chop .15i chop .15i
+arrow from 1st circle to 4th circle chop .15i chop .15i
+arrow from 2nd circle to 4th circle chop .15i chop .15i
+spline -> from 3rd circle right .5i up .075i then right .5i down .075i chop .15i chop .15i
+spline -> from 4th circle left .5i down .075i then left .5i up .075i chop .15i chop .15i
+arrow from 3rd circle to 5th circle chop .15i chop .15i
+arrow from 4th circle to 5th circle chop .15i chop .15i
+arrow from 4th circle to 6th circle chop .15i chop .15i
+arrow from 4th circle to 7th circle chop .15i chop .15i
+arrow from 5th circle to 8th circle chop .15i chop .15i
+arrow from 6th circle to 8th circle chop .15i chop .15i
+arrow from 6th circle to 9th circle chop .15i chop .15i
+.PE
diff --git a/share/doc/psd/18.gprof/postp3.pic b/share/doc/psd/18.gprof/postp3.pic
new file mode 100644
index 0000000..65eb2a7
--- /dev/null
+++ b/share/doc/psd/18.gprof/postp3.pic
@@ -0,0 +1,51 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)postp3.pic 8.1 (Berkeley) 6/8/93
+.\"
+.PS
+circle diam .3i "7"
+circle diam .3i "8" at 1st circle + (2i,0i)
+EL: ellipse wid 1i ht .3i "\fB6\fR\h'.7i'\fB6\fR" at 1st circle + (1i,-0.5i)
+circle diam .3i "2" at 1st circle - (0i,1i)
+circle diam .3i "4" at 3th circle + (1i,0i)
+circle diam .3i "5" at 2nd circle - (0i,1i)
+circle diam .3i "1" at 3rd circle + (0.5i,-0.5i)
+circle diam .3i "3" at 5th circle - (0.5i,0.5i)
+arrow from 1st circle to EL.nw chop .15i chop 0i
+arrow from 2nd circle to EL.ne chop .15i chop 0i
+arrow from EL.sw to 3rd circle chop 0i chop .15i
+arrow from EL.s to 4th circle chop 0i chop .15i
+arrow from EL.se to 5th circle chop 0i chop .15i
+arrow from 3rd circle to 6th circle chop .15i chop .15i
+arrow from 4th circle to 6th circle chop .15i chop .15i
+arrow from 4th circle to 7th circle chop .15i chop .15i
+.PE
diff --git a/share/doc/psd/18.gprof/pres1.pic b/share/doc/psd/18.gprof/pres1.pic
new file mode 100644
index 0000000..0c311a1
--- /dev/null
+++ b/share/doc/psd/18.gprof/pres1.pic
@@ -0,0 +1,56 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)pres1.pic 8.1 (Berkeley) 6/8/93
+.\"
+.PS
+ellipse ht .3i wid .75i "\s-1CALLER1\s+1"
+ellipse ht .3i wid .75i "\s-1CALLER2\s+1" at 1st ellipse + (2i,0i)
+ellipse ht .3i wid .8i "\s-1EXAMPLE\s+1" at 1st ellipse + (1i,-.5i)
+ellipse ht .3i wid .5i "\s-1SUB1\s+1" at 1st ellipse - (0i,1i)
+ellipse ht .3i wid .5i "\s-1SUB2\s+1" at 3rd ellipse - (0i,.5i)
+ellipse ht .3i wid .5i "\s-1SUB3\s+1" at 2nd ellipse - (0i,1i)
+line <- from 1st ellipse up .5i left .5i chop .1875i
+line <- from 1st ellipse up .5i right .5i chop .1875i
+line <- from 2nd ellipse up .5i left .5i chop .1875i
+line <- from 2nd ellipse up .5i right .5i chop .1875i
+arrow from 1st ellipse to 3rd ellipse chop
+arrow from 2nd ellipse to 3rd ellipse chop
+arrow from 3rd ellipse to 4th ellipse chop
+arrow from 3rd ellipse to 5th ellipse chop .15i chop .15i
+arrow from 3rd ellipse to 6th ellipse chop
+arrow from 4th ellipse down .5i left .5i chop .1875i
+arrow from 4th ellipse down .5i right .5i chop .1875i
+arrow from 5th ellipse down .5i left .5i chop .1875i
+arrow from 5th ellipse down .5i right .5i chop .1875i
+arrow from 6th ellipse down .5i left .5i chop .1875i
+arrow from 6th ellipse down .5i right .5i chop .1875i
+.PE
diff --git a/share/doc/psd/18.gprof/pres2.pic b/share/doc/psd/18.gprof/pres2.pic
new file mode 100644
index 0000000..c3a4ea0
--- /dev/null
+++ b/share/doc/psd/18.gprof/pres2.pic
@@ -0,0 +1,52 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)pres2.pic 8.1 (Berkeley) 6/8/93
+.\"
+.PS
+ellipse ht .3i wid .6i "\s-1CALC1\s+1"
+ellipse ht .3i wid .6i "\s-1CALC2\s+1" at 1st ellipse + (.75i,0i)
+ellipse ht .3i wid .6i "\s-1CALC3\s+1" at 1st ellipse + (1.5i,0i)
+ellipse ht .3i wid .8i "\s-1FORMAT1\s+1" at 1st ellipse - (0i,.5i)
+ellipse ht .3i wid .8i "\s-1FORMAT2\s+1" at 3rd ellipse - (0i,.5i)
+ellipse ht .3i wid .75i "\s-1\"WRITE\"\s+1" at 5th ellipse - (.75i,.5i)
+line <- from 1st ellipse up .5i left .4i chop .1825i
+line <- from 1st ellipse up .5i right .4i chop .1825i
+line <- from 2nd ellipse up .5i left .4i chop .1825i
+line <- from 2nd ellipse up .5i right .4i chop .1825i
+line <- from 3rd ellipse up .5i left .4i chop .1825i
+line <- from 3rd ellipse up .5i right .4i chop .1825i
+arrow from 1st ellipse to 4th ellipse chop .15i
+arrow from 2nd ellipse to 5th ellipse chop
+arrow from 3rd ellipse to 5th ellipse chop .15i
+arrow from 4th ellipse to 6th ellipse chop
+arrow from 5th ellipse to 6th ellipse chop
+.PE
diff --git a/share/doc/psd/18.gprof/present.me b/share/doc/psd/18.gprof/present.me
new file mode 100644
index 0000000..1dd7f62
--- /dev/null
+++ b/share/doc/psd/18.gprof/present.me
@@ -0,0 +1,306 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)present.me 8.1 (Berkeley) 6/8/93
+.\"
+.sh 1 "Data Presentation"
+.pp
+The data is presented to the user in two different formats.
+The first presentation simply lists the routines
+without regard to the amount of time their descendants use.
+The second presentation incorporates the call graph of the
+program.
+.sh 2 "The Flat Profile
+.pp
+The flat profile consists of a list of all the routines
+that are called during execution of the program,
+with the count of the number of times they are called
+and the number of seconds of execution time for which they
+are themselves accountable.
+The routines are listed in decreasing order of execution time.
+A list of the routines that are never called during execution of
+the program is also available
+to verify that nothing important is omitted by
+this execution.
+The flat profile gives a quick overview of the routines that are used,
+and shows the routines that are themselves responsible
+for large fractions of the execution time.
+In practice,
+this profile usually shows that no single function
+is overwhelmingly responsible for
+the total time of the program.
+Notice that for this profile,
+the individual times sum to the total execution time.
+.sh 2 "The Call Graph Profile"
+.sz 10
+.(z
+.TS
+box center;
+c c c c c l l
+c c c c c l l
+c c c c c l l
+l n n n c l l.
+ called/total \ \ parents
+index %time self descendants called+self name index
+ called/total \ \ children
+_
+ 0.20 1.20 4/10 \ \ \s-1CALLER1\s+1 [7]
+ 0.30 1.80 6/10 \ \ \s-1CALLER2\s+1 [1]
+[2] 41.5 0.50 3.00 10+4 \s-1EXAMPLE\s+1 [2]
+ 1.50 1.00 20/40 \ \ \s-1SUB1\s+1 <cycle1> [4]
+ 0.00 0.50 1/5 \ \ \s-1SUB2\s+1 [9]
+ 0.00 0.00 0/5 \ \ \s-1SUB3\s+1 [11]
+.TE
+.ce 2
+Profile entry for \s-1EXAMPLE\s+1.
+Figure 4.
+.)z
+.pp
+Ideally, we would like to print the call graph of the program,
+but we are limited by the two-dimensional nature of our output
+devices.
+We cannot assume that a call graph is planar,
+and even if it is, that we can print a planar version of it.
+Instead, we choose to list each routine,
+together with information about
+the routines that are its direct parents and children.
+This listing presents a window into the call graph.
+Based on our experience,
+both parent information and child information
+is important,
+and should be available without searching
+through the output.
+.pp
+The major entries of the call graph profile are the entries from the
+flat profile, augmented by the time propagated to each
+routine from its descendants.
+This profile is sorted by the sum of the time for the routine
+itself plus the time inherited from its descendants.
+The profile shows which of the higher level routines
+spend large portions of the total execution time
+in the routines that they call.
+For each routine, we show the amount of time passed by each child
+to the routine, which includes time for the child itself
+and for the descendants of the child
+(and thus the descendants of the routine).
+We also show the percentage these times represent of the total time
+accounted to the child.
+Similarly, the parents of each routine are listed,
+along with time,
+and percentage of total routine time,
+propagated to each one.
+.pp
+Cycles are handled as single entities.
+The cycle as a whole is shown as though it were a single routine,
+except that members of the cycle are listed in place of the children.
+Although the number of calls of each member
+from within the cycle are shown,
+they do not affect time propagation.
+When a child is a member of a cycle,
+the time shown is the appropriate fraction of the time
+for the whole cycle.
+Self-recursive routines have their calls broken
+down into calls from the outside and self-recursive calls.
+Only the outside calls affect the propagation of time.
+.pp
+The following example is a typical fragment of a call graph.
+.(b
+.so pres1.pic
+.)b
+The entry in the call graph profile listing for this example is
+shown in Figure 4.
+.pp
+The entry is for routine \s-1EXAMPLE\s+1, which has
+the Caller routines as its parents,
+and the Sub routines as its children.
+The reader should keep in mind that all information
+is given \fIwith respect to \s-1EXAMPLE\s+1\fP.
+The index in the first column shows that \s-1EXAMPLE\s+1
+is the second entry in the profile listing.
+The \s-1EXAMPLE\s+1 routine is called ten times, four times by \s-1CALLER1\s+1,
+and six times by \s-1CALLER2\s+1.
+Consequently 40% of \s-1EXAMPLE\s+1's time is propagated to \s-1CALLER1\s+1,
+and 60% of \s-1EXAMPLE\s+1's time is propagated to \s-1CALLER2\s+1.
+The self and descendant fields of the parents
+show the amount of self and descendant time \s-1EXAMPLE\s+1
+propagates to them (but not the time used by
+the parents directly).
+Note that \s-1EXAMPLE\s+1 calls itself recursively four times.
+The routine \s-1EXAMPLE\s+1 calls routine \s-1SUB1\s+1 twenty times, \s-1SUB2\s+1 once,
+and never calls \s-1SUB3\s+1.
+Since \s-1SUB2\s+1 is called a total of five times,
+20% of its self and descendant time is propagated to \s-1EXAMPLE\s+1's
+descendant time field.
+Because \s-1SUB1\s+1 is a member of \fIcycle 1\fR,
+the self and descendant times
+and call count fraction
+are those for the cycle as a whole.
+Since cycle 1 is called a total of forty times
+(not counting calls among members of the cycle),
+it propagates 50% of the cycle's self and descendant
+time to \s-1EXAMPLE\s+1's descendant time field.
+Finally each name is followed by an index that shows
+where on the listing to find the entry for that routine.
+.sh 1 "Using the Profiles"
+.pp
+The profiler is a useful tool for improving
+a set of routines that implement an abstraction.
+It can be helpful in identifying poorly coded routines,
+and in evaluating the new algorithms and code that replace them.
+Taking full advantage of the profiler
+requires a careful examination of the call graph profile,
+and a thorough knowledge of the abstractions underlying
+the program.
+.pp
+The easiest optimization that can be performed
+is a small change
+to a control construct or data structure that improves the
+running time of the program.
+An obvious starting point
+is a routine that is called many times.
+For example, suppose an output
+routine is the only parent
+of a routine that formats the data.
+If this format routine is expanded inline in the
+output routine, the overhead of a function call and
+return can be saved for each datum that needs to be formatted.
+.pp
+The drawback to inline expansion is that the data abstractions
+in the program may become less parameterized,
+hence less clearly defined.
+The profiling will also become less useful since the loss of
+routines will make its output more granular.
+For example,
+if the symbol table functions ``lookup'', ``insert'', and ``delete''
+are all merged into a single parameterized routine,
+it will be impossible to determine the costs
+of any one of these individual functions from the profile.
+.pp
+Further potential for optimization lies in routines that
+implement data abstractions whose total execution
+time is long.
+For example, a lookup routine might be called only a few
+times, but use an inefficient linear search algorithm,
+that might be replaced with a binary search.
+Alternately, the discovery that a rehashing function is being
+called excessively, can lead to a different
+hash function or a larger hash table.
+If the data abstraction function cannot easily be speeded up,
+it may be advantageous to cache its results,
+and eliminate the need to rerun
+it for identical inputs.
+These and other ideas for program improvement are discussed in
+[Bentley81].
+.pp
+This tool is best used in an iterative approach:
+profiling the program,
+eliminating one bottleneck,
+then finding some other part of the program
+that begins to dominate execution time.
+For instance, we have used \fBgprof\fR on itself;
+eliminating, rewriting, and inline expanding routines,
+until reading
+data files (hardly a target for optimization!)
+represents the dominating factor in its execution time.
+.pp
+Certain types of programs are not easily analyzed by \fBgprof\fR.
+They are typified by programs that exhibit a large degree of
+recursion, such as recursive descent compilers.
+The problem is that most of the major routines are grouped
+into a single monolithic cycle.
+As in the symbol table abstraction that is placed
+in one routine,
+it is impossible to distinguish which members of the cycle are
+responsible for the execution time.
+Unfortunately there are no easy modifications to these programs that
+make them amenable to analysis.
+.pp
+A completely different use of the profiler is to analyze the control
+flow of an unfamiliar program.
+If you receive a program from another user that you need to modify
+in some small way,
+it is often unclear where the changes need to be made.
+By running the program on an example and then using \fBgprof\fR,
+you can get a view of the structure of the program.
+.pp
+Consider an example in which you need to change the output format
+of the program.
+For purposes of this example suppose that the call graph
+of the output portion of the program has the following structure:
+.(b
+.so pres2.pic
+.)b
+Initially you look through the \fBgprof\fR
+output for the system call ``\s-1WRITE\s+1''.
+The format routine you will need to change is probably
+among the parents of the ``\s-1WRITE\s+1'' procedure.
+The next step is to look at the profile entry for each
+of parents of ``\s-1WRITE\s+1'',
+in this example either ``\s-1FORMAT1\s+1'' or ``\s-1FORMAT2\s+1'',
+to determine which one to change.
+Each format routine will have one or more parents,
+in this example ``\s-1CALC1\s+1'', ``\s-1CALC2\s+1'', and ``\s-1CALC3\s+1''.
+By inspecting the source code for each of these routines
+you can determine which format routine generates the output that
+you wish to modify.
+Since the \fBgprof\fR entry shows all the
+potential calls to the format routine you intend to change,
+you can determine if your modifications will affect output that
+should be left alone.
+If you desire to change the output of ``\s-1CALC2\s+1'', but not ``\s-1CALC3\s+1'',
+then formatting routine ``\s-1FORMAT2\s+1'' needs to be split
+into two separate routines,
+one of which implements the new format.
+You can then retarget just the call by ``\s-1CALC2\s+1''
+that needs the new format.
+It should be noted that the static call information is particularly
+useful here since the test case you run probably will not
+exercise the entire program.
+.sh 1 "Conclusions"
+.pp
+We have created a profiler that aids in the evaluation
+of modular programs.
+For each routine in the program,
+the profile shows the extent to which that routine
+helps support various abstractions,
+and how that routine uses other abstractions.
+The profile accurately assesses the cost of routines
+at all levels of the program decomposition.
+The profiler is easily used,
+and can be compiled into the program without any prior planning by
+the programmer.
+It adds only five to thirty percent execution overhead to the program
+being profiled,
+produces no additional output until after the program finishes,
+and allows the program to be measured in its actual environment.
+Finally, the profiler runs on a time-sharing system
+using only the normal services provided by the operating system
+and compilers.
diff --git a/share/doc/psd/18.gprof/profiling.me b/share/doc/psd/18.gprof/profiling.me
new file mode 100644
index 0000000..227aedf
--- /dev/null
+++ b/share/doc/psd/18.gprof/profiling.me
@@ -0,0 +1,115 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)profiling.me 8.1 (Berkeley) 6/8/93
+.\"
+.sh 1 "Types of Profiling"
+.pp
+There are several different uses for program profiles,
+and each may require different information from the profiles,
+or different presentation of the information.
+We distinguish two broad categories of profiles:
+those that present counts of statement or routine invocations,
+and those that display timing information about statements
+or routines.
+Counts are typically presented in tabular form,
+often in parallel with a listing of the source code.
+Timing information could be similarly presented;
+but more than one measure of time might be associated with each
+statement or routine.
+For example,
+in the framework used by \fBgprof\fP
+each profiled segment would display two times:
+one for the time used by the segment itself, and another for the
+time inherited from code segments it invokes.
+.pp
+Execution counts are used in many different contexts.
+The exact number of times a routine or statement is activated
+can be used to determine if an algorithm is performing as
+expected.
+Cursory inspection of such counters may show algorithms whose
+complexity is unsuited to the task at hand.
+Careful interpretation of counters can often suggest
+improvements to acceptable algorithms.
+Precise examination can uncover subtle errors in an
+algorithm.
+At this level, profiling counters are similar to
+debugging statements whose purpose is to show the number of times
+a piece of code is executed.
+Another view of such counters is as boolean values.
+One may be interested that a portion of code has executed at
+all, for exhaustive testing, or to check that one implementation
+of an abstraction completely replaces a previous one.
+.pp
+Execution counts are not necessarily proportional to the amount
+of time required to execute the routine or statement.
+Further, the execution time of a routine will not be the same for
+all calls on the routine.
+The criteria for establishing execution time
+must be decided.
+If a routine implements an abstraction by invoking other abstractions,
+the time spent in the routine will not accurately reflect the
+time required by the abstraction it implements.
+Similarly, if an abstraction is implemented by several
+routines the time required by the abstraction will be distributed
+across those routines.
+.pp
+Given the execution time of individual routines,
+\fBgprof\fP accounts to each routine the time spent
+for it by the routines it invokes.
+This accounting is done by assembling a \fIcall graph\fP with nodes that
+are the routines of the program and directed arcs that represent
+calls from call sites to routines.
+We distinguish among three different call graphs for a program.
+The \fIcomplete call graph\fP incorporates all routines and all
+potential arcs,
+including arcs that represent calls to functional parameters
+or functional variables.
+This graph contains the other two graphs as subgraphs.
+The \fIstatic call graph\fP includes all routines and all possible arcs
+that are not calls to functional parameters or variables.
+The \fIdynamic call graph\fP includes only those routines and
+arcs traversed by the profiled execution of the program.
+This graph need not include all routines, nor need it include all
+potential arcs between the routines it covers.
+It may, however, include arcs to functional parameters or
+variables that the static call graph may omit.
+The static call graph can be determined from the (static) program text.
+The dynamic call graph is determined only by profiling an
+execution of the program.
+The complete call graph for a monolithic program could be determined
+by data flow analysis techniques.
+The complete call graph for programs that change
+during execution, by modifying themselves or dynamically loading
+or overlaying code, may never be determinable.
+Both the static call graph and the dynamic call graph are used
+by \fBgprof\fP, but it does not search for the complete call
+graph.
diff --git a/share/doc/psd/18.gprof/refs.me b/share/doc/psd/18.gprof/refs.me
new file mode 100644
index 0000000..580d080
--- /dev/null
+++ b/share/doc/psd/18.gprof/refs.me
@@ -0,0 +1,63 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)refs.me 8.1 (Berkeley) 6/8/93
+.\"
+.sh 1 "References"
+.ls 1
+.ip [Bentley81]
+Bentley, J. L.,
+``Writing Efficient Code'',
+Department of Computer Science,
+Carnegie-Mellon University,
+Pittsburgh, Pennsylvania,
+CMU-CS-81-116, 1981.
+.ip [Graham82]
+Graham, S. L., Henry, R. R., Schulman, R. A.,
+``An Experiment in Table Driven Code Generation'',
+SIGPLAN '82 Symposium on Compiler Construction,
+June, 1982.
+.ip [Joy79]
+Joy, W. N., Graham, S. L., Haley, C. B. ``Berkeley Pascal User's Manual'',
+Version 1.1, Computer Science Division
+University of California, Berkeley, CA. April 1979.
+.ip [Knuth71]
+Knuth, D. E. ``An empirical study of FORTRAN programs'',
+Software - Practice and Experience, 1, 105-133. 1971
+.ip [Satterthwaite72]
+Satterthwaite, E. ``Debugging Tools for High Level Languages'',
+Software - Practice and Experience, 2, 197-217, 1972
+.ip [Tarjan72]
+Tarjan, R. E., ``Depth first search and linear graph algorithm,''
+\fISIAM J. Computing\fP \fB1\fP:2, 146-160, 1972.
+.ip [Unix]
+Unix Programmer's Manual, ``\fBprof\fR command'', section 1,
+Bell Laboratories, Murray Hill, NJ. January 1979.
diff --git a/share/doc/psd/22.rpcgen/Makefile b/share/doc/psd/22.rpcgen/Makefile
index 4c38add..04d4e9e 100644
--- a/share/doc/psd/22.rpcgen/Makefile
+++ b/share/doc/psd/22.rpcgen/Makefile
@@ -4,6 +4,5 @@ VOLUME= psd/22.rpcgen
SRCS= stubs rpcgen.ms
MACROS= -ms
USE_TBL=
-SRCDIR= ${.CURDIR}/../../../../lib/libc/rpc/PSD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/psd/22.rpcgen/rpcgen.ms b/share/doc/psd/22.rpcgen/rpcgen.ms
new file mode 100644
index 0000000..e663e7f
--- /dev/null
+++ b/share/doc/psd/22.rpcgen/rpcgen.ms
@@ -0,0 +1,1301 @@
+.\"
+.\" Must use -- tbl -- for this one
+.\"
+.\" @(#)rpcgen.ms 2.2 88/08/04 4.0 RPCSRC
+.\" $FreeBSD$
+.\"
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH '\fBrpcgen\fP Programming Guide''Page %'
+.EH 'Page %''\fBrpcgen\fP Programming Guide'
+.if \n%=1 .bp
+.SH
+\&\fBrpcgen\fP Programming Guide
+.NH 0
+\&The \fBrpcgen\fP Protocol Compiler
+.IX rpcgen "" \fIrpcgen\fP "" PAGE MAJOR
+.LP
+.IX RPC "" "" \fIrpcgen\fP
+The details of programming applications to use Remote Procedure Calls
+can be overwhelming. Perhaps most daunting is the writing of the XDR
+routines necessary to convert procedure arguments and results into
+their network format and vice-versa.
+.LP
+Fortunately,
+.I rpcgen(1)
+exists to help programmers write RPC applications simply and directly.
+.I rpcgen
+does most of the dirty work, allowing programmers to debug
+the main features of their application, instead of requiring them to
+spend most of their time debugging their network interface code.
+.LP
+.I rpcgen
+is a compiler. It accepts a remote program interface definition written
+in a language, called RPC Language, which is similar to C. It produces a C
+language output which includes stub versions of the client routines, a
+server skeleton, XDR filter routines for both parameters and results, and a
+header file that contains common definitions. The client stubs interface
+with the RPC library and effectively hide the network from their callers.
+The server stub similarly hides the network from the server procedures that
+are to be invoked by remote clients.
+.I rpcgen 's
+output files can be compiled and linked in the usual way. The developer
+writes server procedures\(emin any language that observes Sun calling
+conventions\(emand links them with the server skeleton produced by
+.I rpcgen
+to get an executable server program. To use a remote program, a programmer
+writes an ordinary main program that makes local procedure calls to the
+client stubs produced by
+.I rpcgen .
+Linking this program with
+.I rpcgen 's
+stubs creates an executable program. (At present the main program must be
+written in C).
+.I rpcgen
+options can be used to suppress stub generation and to specify the transport
+to be used by the server stub.
+.LP
+Like all compilers,
+.I rpcgen
+reduces development time
+that would otherwise be spent coding and debugging low-level routines.
+All compilers, including
+.I rpcgen ,
+do this at a small cost in efficiency
+and flexibility. However, many compilers allow escape hatches for
+programmers to mix low-level code with high-level code.
+.I rpcgen
+is no exception. In speed-critical applications, hand-written routines
+can be linked with the
+.I rpcgen
+output without any difficulty. Also, one may proceed by using
+.I rpcgen
+output as a starting point, and then rewriting it as necessary.
+(If you need a discussion of RPC programming without
+.I rpcgen ,
+see the
+.I "Remote Procedure Call Programming Guide)\.
+.NH 1
+\&Converting Local Procedures into Remote Procedures
+.IX rpcgen "local procedures" \fIrpcgen\fP
+.IX rpcgen "remote procedures" \fIrpcgen\fP
+.LP
+Assume an application that runs on a single machine, one which we want
+to convert to run over the network. Here we will demonstrate such a
+conversion by way of a simple example\(ema program that prints a
+message to the console:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * printmsg.c: print a message on the console
+ */
+.ft CW
+#include <stdio.h>
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *message;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <message>\en", argv[0]);
+ exit(1);
+ }
+ message = argv[1];
+
+ if (!printmessage(message)) {
+ fprintf(stderr, "%s: couldn't print your message\en",
+ argv[0]);
+ exit(1);
+ }
+ printf("Message Delivered!\en");
+ exit(0);
+}
+.ft I
+/*
+ * Print a message to the console.
+ * Return a boolean indicating whether the message was actually printed.
+ */
+.ft CW
+printmessage(msg)
+ char *msg;
+{
+ FILE *f;
+
+ f = fopen("/dev/console", "w");
+ if (f == NULL) {
+ return (0);
+ }
+ fprintf(f, "%s\en", msg);
+ fclose(f);
+ return(1);
+}
+.DE
+.LP
+And then, of course:
+.ie t .DS
+.el .DS L
+.ft CW
+example% \fBcc printmsg.c -o printmsg\fP
+example% \fBprintmsg "Hello, there."\fP
+Message delivered!
+example%
+.DE
+.LP
+If
+.I printmessage()
+was turned into a remote procedure,
+then it could be called from anywhere in the network.
+Ideally, one would just like to stick a keyword like
+.I remote
+in front of a
+procedure to turn it into a remote procedure. Unfortunately,
+we have to live within the constraints of the C language, since
+it existed long before RPC did. But even without language
+support, it's not very difficult to make a procedure remote.
+.LP
+In general, it's necessary to figure out what the types are for
+all procedure inputs and outputs. In this case, we have a
+procedure
+.I printmessage()
+which takes a string as input, and returns an integer
+as output. Knowing this, we can write a protocol specification in RPC
+language that describes the remote version of
+.I printmessage ().
+Here it is:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * msg.x: Remote message printing protocol
+ */
+.ft CW
+
+program MESSAGEPROG {
+ version MESSAGEVERS {
+ int PRINTMESSAGE(string) = 1;
+ } = 1;
+} = 99;
+.DE
+.LP
+Remote procedures are part of remote programs, so we actually declared
+an entire remote program here which contains the single procedure
+.I PRINTMESSAGE .
+This procedure was declared to be in version 1 of the
+remote program. No null procedure (procedure 0) is necessary because
+.I rpcgen
+generates it automatically.
+.LP
+Notice that everything is declared with all capital letters. This is
+not required, but is a good convention to follow.
+.LP
+Notice also that the argument type is \*Qstring\*U and not \*Qchar *\*U. This
+is because a \*Qchar *\*U in C is ambiguous. Programmers usually intend it
+to mean a null-terminated string of characters, but it could also
+represent a pointer to a single character or a pointer to an array of
+characters. In RPC language, a null-terminated string is
+unambiguously called a \*Qstring\*U.
+.LP
+There are just two more things to write. First, there is the remote
+procedure itself. Here's the definition of a remote procedure
+to implement the
+.I PRINTMESSAGE
+procedure we declared above:
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * msg_proc.c: implementation of the remote procedure "printmessage"
+ */
+.ft CW
+
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIalways needed\fP */
+#include "msg.h" /* \fIneed this too: msg.h will be generated by rpcgen\fP */
+
+.ft I
+/*
+ * Remote verson of "printmessage"
+ */
+.ft CW
+int *
+printmessage_1(msg)
+ char **msg;
+{
+ static int result; /* \fImust be static!\fP */
+ FILE *f;
+
+ f = fopen("/dev/console", "w");
+ if (f == NULL) {
+ result = 0;
+ return (&result);
+ }
+ fprintf(f, "%s\en", *msg);
+ fclose(f);
+ result = 1;
+ return (&result);
+}
+.vs
+.DE
+.LP
+Notice here that the declaration of the remote procedure
+.I printmessage_1()
+differs from that of the local procedure
+.I printmessage()
+in three ways:
+.IP 1.
+It takes a pointer to a string instead of a string itself. This
+is true of all remote procedures: they always take pointers to their
+arguments rather than the arguments themselves.
+.IP 2.
+It returns a pointer to an integer instead of an integer itself. This is
+also generally true of remote procedures: they always return a pointer
+to their results.
+.IP 3.
+It has an \*Q_1\*U appended to its name. In general, all remote
+procedures called by
+.I rpcgen
+are named by the following rule: the name in the program definition
+(here
+.I PRINTMESSAGE )
+is converted to all
+lower-case letters, an underbar (\*Q_\*U) is appended to it, and
+finally the version number (here 1) is appended.
+.LP
+The last thing to do is declare the main client program that will call
+the remote procedure. Here it is:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * rprintmsg.c: remote version of "printmsg.c"
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIalways needed\fP */
+#include "msg.h" /* \fIneed this too: msg.h will be generated by rpcgen\fP */
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ CLIENT *cl;
+ int *result;
+ char *server;
+ char *message;
+
+ if (argc < 3) {
+ fprintf(stderr, "usage: %s host message\en", argv[0]);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Save values of command line arguments
+ */
+.ft CW
+ server = argv[1];
+ message = argv[2];
+
+.ft I
+ /*
+ * Create client "handle" used for calling \fIMESSAGEPROG\fP on the
+ * server designated on the command line. We tell the RPC package
+ * to use the "tcp" protocol when contacting the server.
+ */
+.ft CW
+ cl = clnt_create(server, MESSAGEPROG, MESSAGEVERS, "tcp");
+ if (cl == NULL) {
+.ft I
+ /*
+ * Couldn't establish connection with server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_pcreateerror(server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Call the remote procedure "printmessage" on the server
+ */
+.ft CW
+ result = printmessage_1(&message, cl);
+ if (result == NULL) {
+.ft I
+ /*
+ * An error occurred while calling the server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_perror(cl, server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Okay, we successfully called the remote procedure.
+ */
+.ft CW
+ if (*result == 0) {
+.ft I
+ /*
+ * Server was unable to print our message.
+ * Print error message and die.
+ */
+.ft CW
+ fprintf(stderr, "%s: %s couldn't print your message\en",
+ argv[0], server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * The message got printed on the server's console
+ */
+.ft CW
+ printf("Message delivered to %s!\en", server);
+}
+.DE
+There are two things to note here:
+.IP 1.
+.IX "client handle, used by rpcgen" "" "client handle, used by \fIrpcgen\fP"
+First a client \*Qhandle\*U is created using the RPC library routine
+.I clnt_create ().
+This client handle will be passed to the stub routines
+which call the remote procedure.
+.IP 2.
+The remote procedure
+.I printmessage_1()
+is called exactly the same way as it is declared in
+.I msg_proc.c
+except for the inserted client handle as the first argument.
+.LP
+Here's how to put all of the pieces together:
+.ie t .DS
+.el .DS L
+.ft CW
+example% \fBrpcgen msg.x\fP
+example% \fBcc rprintmsg.c msg_clnt.c -o rprintmsg\fP
+example% \fBcc msg_proc.c msg_svc.c -o msg_server\fP
+.DE
+Two programs were compiled here: the client program
+.I rprintmsg
+and the server program
+.I msg_server .
+Before doing this though,
+.I rpcgen
+was used to fill in the missing pieces.
+.LP
+Here is what
+.I rpcgen
+did with the input file
+.I msg.x :
+.IP 1.
+It created a header file called
+.I msg.h
+that contained
+.I #define 's
+for
+.I MESSAGEPROG ,
+.I MESSAGEVERS
+and
+.I PRINTMESSAGE
+for use in the other modules.
+.IP 2.
+It created client \*Qstub\*U routines in the
+.I msg_clnt.c
+file. In this case there is only one, the
+.I printmessage_1()
+that was referred to from the
+.I printmsg
+client program. The name of the output file for
+client stub routines is always formed in this way: if the name of the
+input file is
+.I FOO.x ,
+the client stubs output file is called
+.I FOO_clnt.c .
+.IP 3.
+It created the server program which calls
+.I printmessage_1()
+in
+.I msg_proc.c .
+This server program is named
+.I msg_svc.c .
+The rule for naming the server output file is similar to the
+previous one: for an input file called
+.I FOO.x ,
+the output server file is named
+.I FOO_svc.c .
+.LP
+Now we're ready to have some fun. First, copy the server to a
+remote machine and run it. For this example, the
+machine is called \*Qmoon\*U. Server processes are run in the
+background, because they never exit.
+.ie t .DS
+.el .DS L
+.ft CW
+moon% \fBmsg_server &\fP
+.DE
+Then on our local machine (\*Qsun\*U) we can print a message on \*Qmoon\*Us
+console.
+.ie t .DS
+.el .DS L
+.ft CW
+sun% \fBprintmsg moon "Hello, moon."\fP
+.DE
+The message will get printed to \*Qmoon\*Us console. You can print a
+message on anybody's console (including your own) with this program if
+you are able to copy the server to their machine and run it.
+.NH 1
+\&Generating XDR Routines
+.IX RPC "generating XDR routines"
+.LP
+The previous example only demonstrated the automatic generation of
+client and server RPC code.
+.I rpcgen
+may also be used to generate XDR routines, that is, the routines
+necessary to convert local data
+structures into network format and vice-versa. This example presents
+a complete RPC service\(ema remote directory listing service, which uses
+.I rpcgen
+not only to generate stub routines, but also to generate the XDR
+routines. Here is the protocol description file:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * dir.x: Remote directory listing protocol
+ */
+.ft CW
+const MAXNAMELEN = 255; /* \fImaximum length of a directory entry\fP */
+
+typedef string nametype<MAXNAMELEN>; /* \fIa directory entry\fP */
+
+typedef struct namenode *namelist; /* \fIa link in the listing\fP */
+
+.ft I
+/*
+ * A node in the directory listing
+ */
+.ft CW
+struct namenode {
+ nametype name; /* \fIname of directory entry\fP */
+ namelist next; /* \fInext entry\fP */
+};
+
+.ft I
+/*
+ * The result of a READDIR operation.
+ */
+.ft CW
+union readdir_res switch (int errno) {
+case 0:
+ namelist list; /* \fIno error: return directory listing\fP */
+default:
+ void; /* \fIerror occurred: nothing else to return\fP */
+};
+
+.ft I
+/*
+ * The directory program definition
+ */
+.ft CW
+program DIRPROG {
+ version DIRVERS {
+ readdir_res
+ READDIR(nametype) = 1;
+ } = 1;
+} = 76;
+.DE
+.SH
+Note:
+.I
+Types (like
+.I readdir_res
+in the example above) can be defined using
+the \*Qstruct\*U, \*Qunion\*U and \*Qenum\*U keywords, but those keywords
+should not be used in subsequent declarations of variables of those types.
+For example, if you define a union \*Qfoo\*U, you should declare using
+only \*Qfoo\*U and not \*Qunion foo\*U. In fact,
+.I rpcgen
+compiles
+RPC unions into C structures and it is an error to declare them using the
+\*Qunion\*U keyword.
+.LP
+Running
+.I rpcgen
+on
+.I dir.x
+creates four output files. Three are the same as before: header file,
+client stub routines and server skeleton. The fourth are the XDR routines
+necessary for converting the data types we declared into XDR format and
+vice-versa. These are output in the file
+.I dir_xdr.c .
+.LP
+Here is the implementation of the
+.I READDIR
+procedure.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * dir_proc.c: remote readdir implementation
+ */
+.ft CW
+#include <rpc/rpc.h>
+#include <sys/dir.h>
+#include "dir.h"
+
+extern int errno;
+extern char *malloc();
+extern char *strdup();
+
+readdir_res *
+readdir_1(dirname)
+ nametype *dirname;
+{
+ DIR *dirp;
+ struct direct *d;
+ namelist nl;
+ namelist *nlp;
+ static readdir_res res; /* \fImust be static\fP! */
+
+.ft I
+ /*
+ * Open directory
+ */
+.ft CW
+ dirp = opendir(*dirname);
+ if (dirp == NULL) {
+ res.errno = errno;
+ return (&res);
+ }
+
+.ft I
+ /*
+ * Free previous result
+ */
+.ft CW
+ xdr_free(xdr_readdir_res, &res);
+
+.ft I
+ /*
+ * Collect directory entries.
+ * Memory allocated here will be freed by \fIxdr_free\fP
+ * next time \fIreaddir_1\fP is called
+ */
+.ft CW
+ nlp = &res.readdir_res_u.list;
+ while (d = readdir(dirp)) {
+ nl = *nlp = (namenode *) malloc(sizeof(namenode));
+ nl->name = strdup(d->d_name);
+ nlp = &nl->next;
+ }
+ *nlp = NULL;
+
+.ft I
+ /*
+ * Return the result
+ */
+.ft CW
+ res.errno = 0;
+ closedir(dirp);
+ return (&res);
+}
+.vs
+.DE
+Finally, there is the client side program to call the server:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * rls.c: Remote directory listing client
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIalways need this\fP */
+#include "dir.h" /* \fIwill be generated by rpcgen\fP */
+
+extern int errno;
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ CLIENT *cl;
+ char *server;
+ char *dir;
+ readdir_res *result;
+ namelist nl;
+
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s host directory\en",
+ argv[0]);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Remember what our command line arguments refer to
+ */
+.ft CW
+ server = argv[1];
+ dir = argv[2];
+
+.ft I
+ /*
+ * Create client "handle" used for calling \fIMESSAGEPROG\fP on the
+ * server designated on the command line. We tell the RPC package
+ * to use the "tcp" protocol when contacting the server.
+ */
+.ft CW
+ cl = clnt_create(server, DIRPROG, DIRVERS, "tcp");
+ if (cl == NULL) {
+.ft I
+ /*
+ * Couldn't establish connection with server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_pcreateerror(server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Call the remote procedure \fIreaddir\fP on the server
+ */
+.ft CW
+ result = readdir_1(&dir, cl);
+ if (result == NULL) {
+.ft I
+ /*
+ * An error occurred while calling the server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_perror(cl, server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Okay, we successfully called the remote procedure.
+ */
+.ft CW
+ if (result->errno != 0) {
+.ft I
+ /*
+ * A remote system error occurred.
+ * Print error message and die.
+ */
+.ft CW
+ errno = result->errno;
+ perror(dir);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Successfully got a directory listing.
+ * Print it out.
+ */
+.ft CW
+ for (nl = result->readdir_res_u.list; nl != NULL;
+ nl = nl->next) {
+ printf("%s\en", nl->name);
+ }
+ exit(0);
+}
+.DE
+Compile everything, and run.
+.DS
+.ft CW
+sun% \fBrpcgen dir.x\fP
+sun% \fBcc rls.c dir_clnt.c dir_xdr.c -o rls\fP
+sun% \fBcc dir_svc.c dir_proc.c dir_xdr.c -o dir_svc\fP
+
+sun% \fBdir_svc &\fP
+
+moon% \fBrls sun /usr/pub\fP
+\&.
+\&..
+ascii
+eqnchar
+greek
+kbd
+marg8
+tabclr
+tabs
+tabs4
+moon%
+.DE
+.LP
+.IX "debugging with rpcgen" "" "debugging with \fIrpcgen\fP"
+A final note about
+.I rpcgen :
+The client program and the server procedure can be tested together
+as a single program by simply linking them with each other rather
+than with the client and server stubs. The procedure calls will be
+executed as ordinary local procedure calls and the program can be
+debugged with a local debugger such as
+.I dbx .
+When the program is working, the client program can be linked to
+the client stub produced by
+.I rpcgen
+and the server procedures can be linked to the server stub produced
+by
+.I rpcgen .
+.SH
+.I NOTE :
+\fIIf you do this, you may want to comment out calls to RPC library
+routines, and have client-side routines call server routines
+directly.\fP
+.LP
+.NH 1
+\&The C-Preprocessor
+.IX rpcgen "C-preprocessor" \fIrpcgen\fP
+.LP
+The C-preprocessor is run on all input files before they are
+compiled, so all the preprocessor directives are legal within a \*Q.x\*U
+file. Four symbols may be defined, depending upon which output file is
+getting generated. The symbols are:
+.TS
+box tab (&);
+lfI lfI
+lfL l .
+Symbol&Usage
+_
+RPC_HDR&for header-file output
+RPC_XDR&for XDR routine output
+RPC_SVC&for server-skeleton output
+RPC_CLNT&for client stub output
+.TE
+.LP
+Also,
+.I rpcgen
+does a little preprocessing of its own. Any line that
+begins with a percent sign is passed directly into the output file,
+without any interpretation of the line. Here is a simple example that
+demonstrates the preprocessing features.
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * time.x: Remote time protocol
+ */
+.ft CW
+program TIMEPROG {
+ version TIMEVERS {
+ unsigned int TIMEGET(void) = 1;
+ } = 1;
+} = 44;
+
+#ifdef RPC_SVC
+%int *
+%timeget_1()
+%{
+% static int thetime;
+%
+% thetime = time(0);
+% return (&thetime);
+%}
+#endif
+.DE
+The '%' feature is not generally recommended, as there is no guarantee
+that the compiler will stick the output where you intended.
+.NH 1
+\&\fBrpcgen\fP Programming Notes
+.IX rpcgen "other operations" \fIrpcgen\fP
+.sp
+.NH 2
+\&Timeout Changes
+.IX rpcgen "timeout changes" \fIrpcgen\fP
+.LP
+RPC sets a default timeout of 25 seconds for RPC calls when
+.I clnt_create()
+is used. This timeout may be changed using
+.I clnt_control()
+Here is a small code fragment to demonstrate use of
+.I clnt_control ():
+.ID
+struct timeval tv;
+CLIENT *cl;
+.sp .5
+cl = clnt_create("somehost", SOMEPROG, SOMEVERS, "tcp");
+if (cl == NULL) {
+ exit(1);
+}
+tv.tv_sec = 60; /* \fIchange timeout to 1 minute\fP */
+tv.tv_usec = 0;
+clnt_control(cl, CLSET_TIMEOUT, &tv);
+.DE
+.NH 2
+\&Handling Broadcast on the Server Side
+.IX "broadcast RPC"
+.IX rpcgen "broadcast RPC" \fIrpcgen\fP
+.LP
+When a procedure is known to be called via broadcast RPC,
+it is usually wise for the server to not reply unless it can provide
+some useful information to the client. This prevents the network
+from getting flooded by useless replies.
+.LP
+To prevent the server from replying, a remote procedure can
+return NULL as its result, and the server code generated by
+.I rpcgen
+will detect this and not send out a reply.
+.LP
+Here is an example of a procedure that replies only if it
+thinks it is an NFS server:
+.ID
+void *
+reply_if_nfsserver()
+{
+ char notnull; /* \fIjust here so we can use its address\fP */
+.sp .5
+ if (access("/etc/exports", F_OK) < 0) {
+ return (NULL); /* \fIprevent RPC from replying\fP */
+ }
+.ft I
+ /*
+ * return non-null pointer so RPC will send out a reply
+ */
+.ft L
+ return ((void *)&notnull);
+}
+.DE
+Note that if procedure returns type \*Qvoid *\*U, they must return a non-NULL
+pointer if they want RPC to reply for them.
+.NH 2
+\&Other Information Passed to Server Procedures
+.LP
+Server procedures will often want to know more about an RPC call
+than just its arguments. For example, getting authentication information
+is important to procedures that want to implement some level of security.
+This extra information is actually supplied to the server procedure as a
+second argument. Here is an example to demonstrate its use. What we've
+done here is rewrite the previous
+.I printmessage_1()
+procedure to only allow root users to print a message to the console.
+.ID
+int *
+printmessage_1(msg, rq)
+ char **msg;
+ struct svc_req *rq;
+{
+ static in result; /* \fIMust be static\fP */
+ FILE *f;
+ struct suthunix_parms *aup;
+.sp .5
+ aup = (struct authunix_parms *)rq->rq_clntcred;
+ if (aup->aup_uid != 0) {
+ result = 0;
+ return (&result);
+ }
+.sp
+.ft I
+ /*
+ * Same code as before.
+ */
+.ft L
+}
+.DE
+.NH 1
+\&RPC Language
+.IX RPCL
+.IX rpcgen "RPC Language" \fIrpcgen\fP
+.LP
+RPC language is an extension of XDR language. The sole extension is
+the addition of the
+.I program
+type. For a complete description of the XDR language syntax, see the
+.I "External Data Representation Standard: Protocol Specification"
+chapter. For a description of the RPC extensions to the XDR language,
+see the
+.I "Remote Procedure Calls: Protocol Specification"
+chapter.
+.LP
+However, XDR language is so close to C that if you know C, you know most
+of it already. We describe here the syntax of the RPC language,
+showing a few examples along the way. We also show how the various
+RPC and XDR type definitions get compiled into C type definitions in
+the output header file.
+.KS
+.NH 2
+Definitions
+\&
+.IX rpcgen definitions \fIrpcgen\fP
+.LP
+An RPC language file consists of a series of definitions.
+.DS L
+.ft CW
+ definition-list:
+ definition ";"
+ definition ";" definition-list
+.DE
+.KE
+It recognizes five types of definitions.
+.DS L
+.ft CW
+ definition:
+ enum-definition
+ struct-definition
+ union-definition
+ typedef-definition
+ const-definition
+ program-definition
+.DE
+.NH 2
+Structures
+\&
+.IX rpcgen structures \fIrpcgen\fP
+.LP
+An XDR struct is declared almost exactly like its C counterpart. It
+looks like the following:
+.DS L
+.ft CW
+ struct-definition:
+ "struct" struct-ident "{"
+ declaration-list
+ "}"
+
+ declaration-list:
+ declaration ";"
+ declaration ";" declaration-list
+.DE
+As an example, here is an XDR structure to a two-dimensional
+coordinate, and the C structure that it gets compiled into in the
+output header file.
+.DS
+.ft CW
+ struct coord { struct coord {
+ int x; --> int x;
+ int y; int y;
+ }; };
+ typedef struct coord coord;
+.DE
+The output is identical to the input, except for the added
+.I typedef
+at the end of the output. This allows one to use \*Qcoord\*U instead of
+\*Qstruct coord\*U when declaring items.
+.NH 2
+Unions
+\&
+.IX rpcgen unions \fIrpcgen\fP
+.LP
+XDR unions are discriminated unions, and look quite different from C
+unions. They are more analogous to Pascal variant records than they
+are to C unions.
+.DS L
+.ft CW
+ union-definition:
+ "union" union-ident "switch" "(" declaration ")" "{"
+ case-list
+ "}"
+
+ case-list:
+ "case" value ":" declaration ";"
+ "default" ":" declaration ";"
+ "case" value ":" declaration ";" case-list
+.DE
+Here is an example of a type that might be returned as the result of a
+\*Qread data\*U operation. If there is no error, return a block of data.
+Otherwise, don't return anything.
+.DS L
+.ft CW
+ union read_result switch (int errno) {
+ case 0:
+ opaque data[1024];
+ default:
+ void;
+ };
+.DE
+It gets compiled into the following:
+.DS L
+.ft CW
+ struct read_result {
+ int errno;
+ union {
+ char data[1024];
+ } read_result_u;
+ };
+ typedef struct read_result read_result;
+.DE
+Notice that the union component of the output struct has the name as
+the type name, except for the trailing \*Q_u\*U.
+.NH 2
+Enumerations
+\&
+.IX rpcgen enumerations \fIrpcgen\fP
+.LP
+XDR enumerations have the same syntax as C enumerations.
+.DS L
+.ft CW
+ enum-definition:
+ "enum" enum-ident "{"
+ enum-value-list
+ "}"
+
+ enum-value-list:
+ enum-value
+ enum-value "," enum-value-list
+
+ enum-value:
+ enum-value-ident
+ enum-value-ident "=" value
+.DE
+Here is a short example of an XDR enum, and the C enum that it gets
+compiled into.
+.DS L
+.ft CW
+ enum colortype { enum colortype {
+ RED = 0, RED = 0,
+ GREEN = 1, --> GREEN = 1,
+ BLUE = 2 BLUE = 2,
+ }; };
+ typedef enum colortype colortype;
+.DE
+.NH 2
+Typedef
+\&
+.IX rpcgen typedef \fIrpcgen\fP
+.LP
+XDR typedefs have the same syntax as C typedefs.
+.DS L
+.ft CW
+ typedef-definition:
+ "typedef" declaration
+.DE
+Here is an example that defines a
+.I fname_type
+used for declaring
+file name strings that have a maximum length of 255 characters.
+.DS L
+.ft CW
+typedef string fname_type<255>; --> typedef char *fname_type;
+.DE
+.NH 2
+Constants
+\&
+.IX rpcgen constants \fIrpcgen\fP
+.LP
+XDR constants symbolic constants that may be used wherever a
+integer constant is used, for example, in array size specifications.
+.DS L
+.ft CW
+ const-definition:
+ "const" const-ident "=" integer
+.DE
+For example, the following defines a constant
+.I DOZEN
+equal to 12.
+.DS L
+.ft CW
+ const DOZEN = 12; --> #define DOZEN 12
+.DE
+.NH 2
+Programs
+\&
+.IX rpcgen programs \fIrpcgen\fP
+.LP
+RPC programs are declared using the following syntax:
+.DS L
+.ft CW
+ program-definition:
+ "program" program-ident "{"
+ version-list
+ "}" "=" value
+
+ version-list:
+ version ";"
+ version ";" version-list
+
+ version:
+ "version" version-ident "{"
+ procedure-list
+ "}" "=" value
+
+ procedure-list:
+ procedure ";"
+ procedure ";" procedure-list
+
+ procedure:
+ type-ident procedure-ident "(" type-ident ")" "=" value
+.DE
+For example, here is the time protocol, revisited:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * time.x: Get or set the time. Time is represented as number of seconds
+ * since 0:00, January 1, 1970.
+ */
+.ft CW
+program TIMEPROG {
+ version TIMEVERS {
+ unsigned int TIMEGET(void) = 1;
+ void TIMESET(unsigned) = 2;
+ } = 1;
+} = 44;
+.DE
+This file compiles into #defines in the output header file:
+.ie t .DS
+.el .DS L
+.ft CW
+#define TIMEPROG 44
+#define TIMEVERS 1
+#define TIMEGET 1
+#define TIMESET 2
+.DE
+.NH 2
+Declarations
+\&
+.IX rpcgen declarations \fIrpcgen\fP
+.LP
+In XDR, there are only four kinds of declarations.
+.DS L
+.ft CW
+ declaration:
+ simple-declaration
+ fixed-array-declaration
+ variable-array-declaration
+ pointer-declaration
+.DE
+\fB1) Simple declarations\fP are just like simple C declarations.
+.DS L
+.ft CW
+ simple-declaration:
+ type-ident variable-ident
+.DE
+Example:
+.DS L
+.ft CW
+ colortype color; --> colortype color;
+.DE
+\fB2) Fixed-length Array Declarations\fP are just like C array declarations:
+.DS L
+.ft CW
+ fixed-array-declaration:
+ type-ident variable-ident "[" value "]"
+.DE
+Example:
+.DS L
+.ft CW
+ colortype palette[8]; --> colortype palette[8];
+.DE
+\fB3) Variable-Length Array Declarations\fP have no explicit syntax
+in C, so XDR invents its own using angle-brackets.
+.DS L
+.ft CW
+variable-array-declaration:
+ type-ident variable-ident "<" value ">"
+ type-ident variable-ident "<" ">"
+.DE
+The maximum size is specified between the angle brackets. The size may
+be omitted, indicating that the array may be of any size.
+.DS L
+.ft CW
+ int heights<12>; /* \fIat most 12 items\fP */
+ int widths<>; /* \fIany number of items\fP */
+.DE
+Since variable-length arrays have no explicit syntax in C, these
+declarations are actually compiled into \*Qstruct\*Us. For example, the
+\*Qheights\*U declaration gets compiled into the following struct:
+.DS L
+.ft CW
+ struct {
+ u_int heights_len; /* \fI# of items in array\fP */
+ int *heights_val; /* \fIpointer to array\fP */
+ } heights;
+.DE
+Note that the number of items in the array is stored in the \*Q_len\*U
+component and the pointer to the array is stored in the \*Q_val\*U
+component. The first part of each of these component's names is the
+same as the name of the declared XDR variable.
+.LP
+\fB4) Pointer Declarations\fP are made in
+XDR exactly as they are in C. You can't
+really send pointers over the network, but you can use XDR pointers
+for sending recursive data types such as lists and trees. The type is
+actually called \*Qoptional-data\*U, not \*Qpointer\*U, in XDR language.
+.DS L
+.ft CW
+ pointer-declaration:
+ type-ident "*" variable-ident
+.DE
+Example:
+.DS L
+.ft CW
+ listitem *next; --> listitem *next;
+.DE
+.NH 2
+\&Special Cases
+.IX rpcgen "special cases" \fIrpcgen\fP
+.LP
+There are a few exceptions to the rules described above.
+.LP
+.B Booleans:
+C has no built-in boolean type. However, the RPC library does a
+boolean type called
+.I bool_t
+that is either
+.I TRUE
+or
+.I FALSE .
+Things declared as type
+.I bool
+in XDR language are compiled into
+.I bool_t
+in the output header file.
+.LP
+Example:
+.DS L
+.ft CW
+ bool married; --> bool_t married;
+.DE
+.B Strings:
+C has no built-in string type, but instead uses the null-terminated
+\*Qchar *\*U convention. In XDR language, strings are declared using the
+\*Qstring\*U keyword, and compiled into \*Qchar *\*Us in the output header
+file. The maximum size contained in the angle brackets specifies the
+maximum number of characters allowed in the strings (not counting the
+.I NULL
+character). The maximum size may be left off, indicating a string
+of arbitrary length.
+.LP
+Examples:
+.DS L
+.ft CW
+ string name<32>; --> char *name;
+ string longname<>; --> char *longname;
+.DE
+.B "Opaque Data:"
+Opaque data is used in RPC and XDR to describe untyped data, that is,
+just sequences of arbitrary bytes. It may be declared either as a
+fixed or variable length array.
+.DS L
+Examples:
+.ft CW
+ opaque diskblock[512]; --> char diskblock[512];
+
+ opaque filedata<1024>; --> struct {
+ u_int filedata_len;
+ char *filedata_val;
+ } filedata;
+.DE
+.B Voids:
+In a void declaration, the variable is not named. The declaration is
+just \*Qvoid\*U and nothing else. Void declarations can only occur in two
+places: union definitions and program definitions (as the argument or
+result of a remote procedure).
diff --git a/share/doc/psd/22.rpcgen/stubs b/share/doc/psd/22.rpcgen/stubs
new file mode 100644
index 0000000..78b0a2c
--- /dev/null
+++ b/share/doc/psd/22.rpcgen/stubs
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+.\"
+.if t .ftr L CR
diff --git a/share/doc/psd/23.rpc/Makefile b/share/doc/psd/23.rpc/Makefile
index 77849b6..930c677 100644
--- a/share/doc/psd/23.rpc/Makefile
+++ b/share/doc/psd/23.rpc/Makefile
@@ -5,6 +5,5 @@ SRCS= stubs rpc.prog.ms
MACROS= -ms
USE_TBL=
USE_PIC=
-SRCDIR= ${.CURDIR}/../../../../lib/libc/rpc/PSD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/psd/23.rpc/rpc.prog.ms b/share/doc/psd/23.rpc/rpc.prog.ms
new file mode 100644
index 0000000..8b79130
--- /dev/null
+++ b/share/doc/psd/23.rpc/rpc.prog.ms
@@ -0,0 +1,2686 @@
+.\"
+.\" Must use -- tbl and pic -- with this one
+.\"
+.\" @(#)rpc.prog.ms 2.3 88/08/11 4.0 RPCSRC
+.\" $FreeBSD$
+.\"
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.nr OF 0
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'Remote Procedure Call Programming Guide''Page %'
+.EH 'Page %''Remote Procedure Call Programming Guide'
+.SH
+\&Remote Procedure Call Programming Guide
+.nr OF 1
+.IX "Network Programming" "" "" "" PAGE MAJOR
+.IX "RPC Programming Guide"
+.LP
+This document assumes a working knowledge of network theory. It is
+intended for programmers who wish to write network applications using
+remote procedure calls (explained below), and who want to understand
+the RPC mechanisms usually hidden by the
+.I rpcgen(1)
+protocol compiler.
+.I rpcgen
+is described in detail in the previous chapter, the
+.I "\fBrpcgen\fP \fIProgramming Guide\fP".
+.SH
+Note:
+.I
+.IX rpcgen "" \fIrpcgen\fP
+Before attempting to write a network application, or to convert an
+existing non-network application to run over the network, you may want to
+understand the material in this chapter. However, for most applications,
+you can circumvent the need to cope with the details presented here by using
+.I rpcgen .
+The
+.I "Generating XDR Routines"
+section of that chapter contains the complete source for a working RPC
+service\(ema remote directory listing service which uses
+.I rpcgen
+to generate XDR routines as well as client and server stubs.
+.LP
+.LP
+What are remote procedure calls? Simply put, they are the high-level
+communications paradigm used in the operating system.
+RPC presumes the existence of
+low-level networking mechanisms (such as TCP/IP and UDP/IP), and upon them
+it implements a logical client to server communications system designed
+specifically for the support of network applications. With RPC, the client
+makes a procedure call to send a data packet to the server. When the
+packet arrives, the server calls a dispatch routine, performs whatever
+service is requested, sends back the reply, and the procedure call returns
+to the client.
+.NH 0
+\&Layers of RPC
+.IX "layers of RPC"
+.IX "RPC" "layers"
+.LP
+The RPC interface can be seen as being divided into three layers.\**
+.FS
+For a complete specification of the routines in the remote procedure
+call Library, see the
+.I rpc(3N)
+manual page.
+.FE
+.LP
+.I "The Highest Layer:"
+.IX RPC "The Highest Layer"
+The highest layer is totally transparent to the operating system,
+machine and network upon which is is run. It's probably best to
+think of this level as a way of
+.I using
+RPC, rather than as
+a \fIpart of\fP RPC proper. Programmers who write RPC routines
+should (almost) always make this layer available to others by way
+of a simple C front end that entirely hides the networking.
+.LP
+To illustrate, at this level a program can simply make a call to
+.I rnusers (),
+a C routine which returns the number of users on a remote machine.
+The user is not explicitly aware of using RPC \(em they simply
+call a procedure, just as they would call
+.I malloc() .
+.LP
+.I "The Middle Layer:"
+.IX RPC "The Middle Layer"
+The middle layer is really \*QRPC proper.\*U Here, the user doesn't
+need to consider details about sockets, the UNIX system, or other low-level
+implementation mechanisms. They simply make remote procedure calls
+to routines on other machines. The selling point here is simplicity.
+It's this layer that allows RPC to pass the \*Qhello world\*U test \(em
+simple things should be simple. The middle-layer routines are used
+for most applications.
+.LP
+RPC calls are made with the system routines
+.I registerrpc()
+.I callrpc()
+and
+.I svc_run ().
+The first two of these are the most fundamental:
+.I registerrpc()
+obtains a unique system-wide procedure-identification number, and
+.I callrpc()
+actually executes a remote procedure call. At the middle level, a
+call to
+.I rnusers()
+is implemented by way of these two routines.
+.LP
+The middle layer is unfortunately rarely used in serious programming
+due to its inflexibility (simplicity). It does not allow timeout
+specifications or the choice of transport. It allows no UNIX
+process control or flexibility in case of errors. It doesn't support
+multiple kinds of call authentication. The programmer rarely needs
+all these kinds of control, but one or two of them is often necessary.
+.LP
+.I "The Lowest Layer:"
+.IX RPC "The Lowest Layer"
+The lowest layer does allow these details to be controlled by the
+programmer, and for that reason it is often necessary. Programs
+written at this level are also most efficient, but this is rarely a
+real issue \(em since RPC clients and servers rarely generate
+heavy network loads.
+.LP
+Although this document only discusses the interface to C,
+remote procedure calls can be made from any language.
+Even though this document discusses RPC
+when it is used to communicate
+between processes on different machines,
+it works just as well for communication
+between different processes on the same machine.
+.br
+.KS
+.NH 2
+\&The RPC Paradigm
+.IX RPC paradigm
+.LP
+Here is a diagram of the RPC paradigm:
+.LP
+\fBFigure 1-1\fI Network Communication with the Remote Reocedure Call\fR
+.LP
+.PS
+L1: arrow down 1i "client " rjust "program " rjust
+L2: line right 1.5i "\fIcallrpc\fP" "function"
+move up 1.5i; line dotted down 6i; move up 4.5i
+arrow right 1i
+L3: arrow down 1i "invoke " rjust "service " rjust
+L4: arrow right 1.5i "call" "service"
+L5: arrow down 1i " service" ljust " executes" ljust
+L6: arrow left 1.5i "\fIreturn\fP" "answer"
+L7: arrow down 1i "request " rjust "completed " rjust
+L8: line left 1i
+arrow left 1.5i "\fIreturn\fP" "reply"
+L9: arrow down 1i "program " rjust "continues " rjust
+line dashed down from L2 to L9
+line dashed down from L4 to L7
+line dashed up 1i from L3 "service " rjust "daemon " rjust
+arrow dashed down 1i from L8
+move right 1i from L3
+box invis "Machine B"
+move left 1.2i from L2; move down
+box invis "Machine A"
+.PE
+.KE
+.KS
+.NH 1
+\&Higher Layers of RPC
+.NH 2
+\&Highest Layer
+.IX "highest layer of RPC"
+.IX RPC "highest layer"
+.LP
+Imagine you're writing a program that needs to know
+how many users are logged into a remote machine.
+You can do this by calling the RPC library routine
+.I rnusers()
+as illustrated below:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int num;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: rnusers hostname\en");
+ exit(1);
+ }
+ if ((num = rnusers(argv[1])) < 0) {
+ fprintf(stderr, "error: rnusers\en");
+ exit(-1);
+ }
+ printf("%d users on %s\en", num, argv[1]);
+ exit(0);
+}
+.DE
+.KE
+RPC library routines such as
+.I rnusers()
+are in the RPC services library
+.I librpcsvc.a
+Thus, the program above should be compiled with
+.DS
+.ft CW
+% cc \fIprogram.c -lrpcsvc\fP
+.DE
+.I rnusers (),
+like the other RPC library routines, is documented in section 3R
+of the
+.I "System Interface Manual for the Sun Workstation" ,
+the same section which documents the standard Sun RPC services.
+.IX "RPC Services"
+See the
+.I intro(3R)
+manual page for an explanation of the documentation strategy
+for these services and their RPC protocols.
+.LP
+Here are some of the RPC service library routines available to the
+C programmer:
+.LP
+\fBTable 3-3\fI RPC Service Library Routines\fR
+.TS
+box tab (&) ;
+cfI cfI
+lfL l .
+Routine&Description
+_
+.sp .5
+rnusers&Return number of users on remote machine
+rusers&Return information about users on remote machine
+havedisk&Determine if remote machine has disk
+rstats&Get performance data from remote kernel
+rwall&Write to specified remote machines
+yppasswd&Update user password in Yellow Pages
+.TE
+.LP
+Other RPC services \(em for example
+.I ether()
+.I mount
+.I rquota()
+and
+.I spray
+\(em are not available to the C programmer as library routines.
+They do, however,
+have RPC program numbers so they can be invoked with
+.I callrpc()
+which will be discussed in the next section. Most of them also
+have compilable
+.I rpcgen(1)
+protocol description files. (The
+.I rpcgen
+protocol compiler radically simplifies the process of developing
+network applications.
+See the \fBrpcgen\fI Programming Guide\fR
+for detailed information about
+.I rpcgen
+and
+.I rpcgen
+protocol description files).
+.KS
+.NH 2
+\&Intermediate Layer
+.IX "intermediate layer of RPC"
+.IX "RPC" "intermediate layer"
+.LP
+The simplest interface, which explicitly makes RPC calls, uses the
+functions
+.I callrpc()
+and
+.I registerrpc()
+Using this method, the number of remote users can be gotten as follows:
+.ie t .DS
+.el .DS L
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ unsigned long nusers;
+ int stat;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: nusers hostname\en");
+ exit(-1);
+ }
+ if (stat = callrpc(argv[1],
+ RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM,
+ xdr_void, 0, xdr_u_long, &nusers) != 0) {
+ clnt_perrno(stat);
+ exit(1);
+ }
+ printf("%d users on %s\en", nusers, argv[1]);
+ exit(0);
+}
+.DE
+.KE
+Each RPC procedure is uniquely defined by a program number,
+version number, and procedure number. The program number
+specifies a group of related remote procedures, each of
+which has a different procedure number. Each program also
+has a version number, so when a minor change is made to a
+remote service (adding a new procedure, for example), a new
+program number doesn't have to be assigned. When you want
+to call a procedure to find the number of remote users, you
+look up the appropriate program, version and procedure numbers
+in a manual, just as you look up the name of a memory allocator
+when you want to allocate memory.
+.LP
+The simplest way of making remote procedure calls is with the the RPC
+library routine
+.I callrpc()
+It has eight parameters. The first is the name of the remote server
+machine. The next three parameters are the program, version, and procedure
+numbers\(emtogether they identify the procedure to be called.
+The fifth and sixth parameters are an XDR filter and an argument to
+be encoded and passed to the remote procedure.
+The final two parameters are a filter for decoding the results
+returned by the remote procedure and a pointer to the place where
+the procedure's results are to be stored. Multiple arguments and
+results are handled by embedding them in structures. If
+.I callrpc()
+completes successfully, it returns zero; else it returns a nonzero
+value. The return codes (of type
+.IX "enum clnt_stat (in RPC programming)" "" "\fIenum clnt_stat\fP (in RPC programming)"
+cast into an integer) are found in
+.I <rpc/clnt.h> .
+.LP
+Since data types may be represented differently on different machines,
+.I callrpc()
+needs both the type of the RPC argument, as well as
+a pointer to the argument itself (and similarly for the result). For
+.I RUSERSPROC_NUM ,
+the return value is an
+.I "unsigned long"
+so
+.I callrpc()
+has
+.I xdr_u_long()
+as its first return parameter, which says
+that the result is of type
+.I "unsigned long"
+and
+.I &nusers
+as its second return parameter,
+which is a pointer to where the long result will be placed. Since
+.I RUSERSPROC_NUM
+takes no argument, the argument parameter of
+.I callrpc()
+is
+.I xdr_void ().
+.LP
+After trying several times to deliver a message, if
+.I callrpc()
+gets no answer, it returns with an error code.
+The delivery mechanism is UDP,
+which stands for User Datagram Protocol.
+Methods for adjusting the number of retries
+or for using a different protocol require you to use the lower
+layer of the RPC library, discussed later in this document.
+The remote server procedure
+corresponding to the above might look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+.ft CW
+char *
+nuser(indata)
+ char *indata;
+{
+ unsigned long nusers;
+
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and place result in variable \fInusers\fP.
+ */
+.ft CW
+ return((char *)&nusers);
+}
+.DE
+.LP
+It takes one argument, which is a pointer to the input
+of the remote procedure call (ignored in our example),
+and it returns a pointer to the result.
+In the current version of C,
+character pointers are the generic pointers,
+so both the input argument and the return value are cast to
+.I "char *" .
+.LP
+Normally, a server registers all of the RPC calls it plans
+to handle, and then goes into an infinite loop waiting to service requests.
+In this example, there is only a single procedure
+to register, so the main body of the server would look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+
+char *nuser();
+
+main()
+{
+ registerrpc(RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM,
+ nuser, xdr_void, xdr_u_long);
+ svc_run(); /* \fINever returns\fP */
+ fprintf(stderr, "Error: svc_run returned!\en");
+ exit(1);
+}
+.DE
+.LP
+The
+.I registerrpc()
+routine registers a C procedure as corresponding to a
+given RPC procedure number. The first three parameters,
+.I RUSERPROG ,
+.I RUSERSVERS ,
+and
+.I RUSERSPROC_NUM
+are the program, version, and procedure numbers
+of the remote procedure to be registered;
+.I nuser()
+is the name of the local procedure that implements the remote
+procedure; and
+.I xdr_void()
+and
+.I xdr_u_long()
+are the XDR filters for the remote procedure's arguments and
+results, respectively. (Multiple arguments or multiple results
+are passed as structures).
+.LP
+Only the UDP transport mechanism can use
+.I registerrpc()
+thus, it is always safe in conjunction with calls generated by
+.I callrpc() .
+.SH
+.IX "UDP 8K warning"
+Warning: the UDP transport mechanism can only deal with
+arguments and results less than 8K bytes in length.
+.LP
+.LP
+After registering the local procedure, the server program's
+main procedure calls
+.I svc_run (),
+the RPC library's remote procedure dispatcher. It is this
+function that calls the remote procedures in response to RPC
+call messages. Note that the dispatcher takes care of decoding
+remote procedure arguments and encoding results, using the XDR
+filters specified when the remote procedure was registered.
+.NH 2
+\&Assigning Program Numbers
+.IX "program number assignment"
+.IX "assigning program numbers"
+.LP
+Program numbers are assigned in groups of
+.I 0x20000000
+according to the following chart:
+.DS
+.ft CW
+ 0x0 - 0x1fffffff \fRDefined by Sun\fP
+0x20000000 - 0x3fffffff \fRDefined by user\fP
+0x40000000 - 0x5fffffff \fRTransient\fP
+0x60000000 - 0x7fffffff \fRReserved\fP
+0x80000000 - 0x9fffffff \fRReserved\fP
+0xa0000000 - 0xbfffffff \fRReserved\fP
+0xc0000000 - 0xdfffffff \fRReserved\fP
+0xe0000000 - 0xffffffff \fRReserved\fP
+.ft R
+.DE
+Sun Microsystems administers the first group of numbers, which
+should be identical for all Sun customers. If a customer
+develops an application that might be of general interest, that
+application should be given an assigned number in the first
+range. The second group of numbers is reserved for specific
+customer applications. This range is intended primarily for
+debugging new programs. The third group is reserved for
+applications that generate program numbers dynamically. The
+final groups are reserved for future use, and should not be
+used.
+.LP
+To register a protocol specification, send a request by network
+mail to
+.I rpc@sun
+or write to:
+.DS
+RPC Administrator
+Sun Microsystems
+2550 Garcia Ave.
+Mountain View, CA 94043
+.DE
+Please include a compilable
+.I rpcgen
+\*Q.x\*U file describing your protocol.
+You will be given a unique program number in return.
+.IX RPC administration
+.IX administration "of RPC"
+.LP
+The RPC program numbers and protocol specifications
+of standard Sun RPC services can be
+found in the include files in
+.I "/usr/include/rpcsvc" .
+These services, however, constitute only a small subset
+of those which have been registered. The complete list of
+registered programs, as of the time when this manual was
+printed, is:
+.LP
+\fBTable 3-2\fI RPC Registered Programs\fR
+.TS H
+box tab (&) ;
+lfBI lfBI lfBI
+lfL lfL lfI .
+RPC Number&Program&Description
+_
+.TH
+.sp .5
+100000&PMAPPROG&portmapper
+100001&RSTATPROG&remote stats
+100002&RUSERSPROG&remote users
+100003&NFSPROG&nfs
+100004&YPPROG&Yellow Pages
+100005&MOUNTPROG&mount daemon
+100006&DBXPROG&remote dbx
+100007&YPBINDPROG&yp binder
+100008&WALLPROG&shutdown msg
+100009&YPPASSWDPROG&yppasswd server
+100010&ETHERSTATPROG&ether stats
+100011&RQUOTAPROG&disk quotas
+100012&SPRAYPROG&spray packets
+100013&IBM3270PROG&3270 mapper
+100014&IBMRJEPROG&RJE mapper
+100015&SELNSVCPROG&selection service
+100016&RDATABASEPROG&remote database access
+100017&REXECPROG&remote execution
+100018&ALICEPROG&Alice Office Automation
+100019&SCHEDPROG&scheduling service
+100020&LOCKPROG&local lock manager
+100021&NETLOCKPROG&network lock manager
+100022&X25PROG&x.25 inr protocol
+100023&STATMON1PROG&status monitor 1
+100024&STATMON2PROG&status monitor 2
+100025&SELNLIBPROG&selection library
+100026&BOOTPARAMPROG&boot parameters service
+100027&MAZEPROG&mazewars game
+100028&YPUPDATEPROG&yp update
+100029&KEYSERVEPROG&key server
+100030&SECURECMDPROG&secure login
+100031&NETFWDIPROG&nfs net forwarder init
+100032&NETFWDTPROG&nfs net forwarder trans
+100033&SUNLINKMAP_PROG&sunlink MAP
+100034&NETMONPROG&network monitor
+100035&DBASEPROG&lightweight database
+100036&PWDAUTHPROG&password authorization
+100037&TFSPROG&translucent file svc
+100038&NSEPROG&nse server
+100039&NSE_ACTIVATE_PROG&nse activate daemon
+.sp .2i
+150001&PCNFSDPROG&pc passwd authorization
+.sp .2i
+200000&PYRAMIDLOCKINGPROG&Pyramid-locking
+200001&PYRAMIDSYS5&Pyramid-sys5
+200002&CADDS_IMAGE&CV cadds_image
+.sp .2i
+300001&ADT_RFLOCKPROG&ADT file locking
+.TE
+.NH 2
+\&Passing Arbitrary Data Types
+.IX "arbitrary data types"
+.LP
+In the previous example, the RPC call passes a single
+.I "unsigned long"
+RPC can handle arbitrary data structures, regardless of
+different machines' byte orders or structure layout conventions,
+by always converting them to a network standard called
+.I "External Data Representation"
+(XDR) before
+sending them over the wire.
+The process of converting from a particular machine representation
+to XDR format is called
+.I serializing ,
+and the reverse process is called
+.I deserializing .
+The type field parameters of
+.I callrpc()
+and
+.I registerrpc()
+can be a built-in procedure like
+.I xdr_u_long()
+in the previous example, or a user supplied one.
+XDR has these built-in type routines:
+.IX RPC "built-in routines"
+.DS
+.ft CW
+xdr_int() xdr_u_int() xdr_enum()
+xdr_long() xdr_u_long() xdr_bool()
+xdr_short() xdr_u_short() xdr_wrapstring()
+xdr_char() xdr_u_char()
+.DE
+Note that the routine
+.I xdr_string()
+exists, but cannot be used with
+.I callrpc()
+and
+.I registerrpc (),
+which only pass two parameters to their XDR routines.
+.I xdr_wrapstring()
+has only two parameters, and is thus OK. It calls
+.I xdr_string ().
+.LP
+As an example of a user-defined type routine,
+if you wanted to send the structure
+.DS
+.ft CW
+struct simple {
+ int a;
+ short b;
+} simple;
+.DE
+then you would call
+.I callrpc()
+as
+.DS
+.ft CW
+callrpc(hostname, PROGNUM, VERSNUM, PROCNUM,
+ xdr_simple, &simple ...);
+.DE
+where
+.I xdr_simple()
+is written as:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <rpc/rpc.h>
+
+xdr_simple(xdrsp, simplep)
+ XDR *xdrsp;
+ struct simple *simplep;
+{
+ if (!xdr_int(xdrsp, &simplep->a))
+ return (0);
+ if (!xdr_short(xdrsp, &simplep->b))
+ return (0);
+ return (1);
+}
+.DE
+.LP
+An XDR routine returns nonzero (true in the sense of C) if it
+completes successfully, and zero otherwise.
+A complete description of XDR is in the
+.I "XDR Protocol Specification"
+section of this manual, only few implementation examples are
+given here.
+.LP
+In addition to the built-in primitives,
+there are also the prefabricated building blocks:
+.DS
+.ft CW
+xdr_array() xdr_bytes() xdr_reference()
+xdr_vector() xdr_union() xdr_pointer()
+xdr_string() xdr_opaque()
+.DE
+To send a variable array of integers,
+you might package them up as a structure like this
+.DS
+.ft CW
+struct varintarr {
+ int *data;
+ int arrlnth;
+} arr;
+.DE
+and make an RPC call such as
+.DS
+.ft CW
+callrpc(hostname, PROGNUM, VERSNUM, PROCNUM,
+ xdr_varintarr, &arr...);
+.DE
+with
+.I xdr_varintarr()
+defined as:
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_varintarr(xdrsp, arrp)
+ XDR *xdrsp;
+ struct varintarr *arrp;
+{
+ return (xdr_array(xdrsp, &arrp->data, &arrp->arrlnth,
+ MAXLEN, sizeof(int), xdr_int));
+}
+.DE
+This routine takes as parameters the XDR handle,
+a pointer to the array, a pointer to the size of the array,
+the maximum allowable array size,
+the size of each array element,
+and an XDR routine for handling each array element.
+.KS
+.LP
+If the size of the array is known in advance, one can use
+.I xdr_vector (),
+which serializes fixed-length arrays.
+.ie t .DS
+.el .DS L
+.ft CW
+int intarr[SIZE];
+
+xdr_intarr(xdrsp, intarr)
+ XDR *xdrsp;
+ int intarr[];
+{
+ int i;
+
+ return (xdr_vector(xdrsp, intarr, SIZE, sizeof(int),
+ xdr_int));
+}
+.DE
+.KE
+.LP
+XDR always converts quantities to 4-byte multiples when serializing.
+Thus, if either of the examples above involved characters
+instead of integers, each character would occupy 32 bits.
+That is the reason for the XDR routine
+.I xdr_bytes()
+which is like
+.I xdr_array()
+except that it packs characters;
+.I xdr_bytes()
+has four parameters, similar to the first four parameters of
+.I xdr_array ().
+For null-terminated strings, there is also the
+.I xdr_string()
+routine, which is the same as
+.I xdr_bytes()
+without the length parameter.
+On serializing it gets the string length from
+.I strlen (),
+and on deserializing it creates a null-terminated string.
+.LP
+Here is a final example that calls the previously written
+.I xdr_simple()
+as well as the built-in functions
+.I xdr_string()
+and
+.I xdr_reference (),
+which chases pointers:
+.ie t .DS
+.el .DS L
+.ft CW
+struct finalexample {
+ char *string;
+ struct simple *simplep;
+} finalexample;
+
+xdr_finalexample(xdrsp, finalp)
+ XDR *xdrsp;
+ struct finalexample *finalp;
+{
+
+ if (!xdr_string(xdrsp, &finalp->string, MAXSTRLEN))
+ return (0);
+ if (!xdr_reference(xdrsp, &finalp->simplep,
+ sizeof(struct simple), xdr_simple);
+ return (0);
+ return (1);
+}
+.DE
+Note that we could as easily call
+.I xdr_simple()
+here instead of
+.I xdr_reference ().
+.NH 1
+\&Lowest Layer of RPC
+.IX "lowest layer of RPC"
+.IX "RPC" "lowest layer"
+.LP
+In the examples given so far,
+RPC takes care of many details automatically for you.
+In this section, we'll show you how you can change the defaults
+by using lower layers of the RPC library.
+It is assumed that you are familiar with sockets
+and the system calls for dealing with them.
+.LP
+There are several occasions when you may need to use lower layers of
+RPC. First, you may need to use TCP, since the higher layer uses UDP,
+which restricts RPC calls to 8K bytes of data. Using TCP permits calls
+to send long streams of data.
+For an example, see the
+.I TCP
+section below. Second, you may want to allocate and free memory
+while serializing or deserializing with XDR routines.
+There is no call at the higher level to let
+you free memory explicitly.
+For more explanation, see the
+.I "Memory Allocation with XDR"
+section below.
+Third, you may need to perform authentication
+on either the client or server side, by supplying
+credentials or verifying them.
+See the explanation in the
+.I Authentication
+section below.
+.NH 2
+\&More on the Server Side
+.IX RPC "server side"
+.LP
+The server for the
+.I nusers()
+program shown below does the same thing as the one using
+.I registerrpc()
+above, but is written using a lower layer of the RPC package:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+
+main()
+{
+ SVCXPRT *transp;
+ int nuser();
+
+ transp = svcudp_create(RPC_ANYSOCK);
+ if (transp == NULL){
+ fprintf(stderr, "can't create an RPC server\en");
+ exit(1);
+ }
+ pmap_unset(RUSERSPROG, RUSERSVERS);
+ if (!svc_register(transp, RUSERSPROG, RUSERSVERS,
+ nuser, IPPROTO_UDP)) {
+ fprintf(stderr, "can't register RUSER service\en");
+ exit(1);
+ }
+ svc_run(); /* \fINever returns\fP */
+ fprintf(stderr, "should never reach this point\en");
+}
+
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ unsigned long nusers;
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (!svc_sendreply(transp, xdr_void, 0))
+ fprintf(stderr, "can't reply to RPC call\en");
+ return;
+ case RUSERSPROC_NUM:
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and assign it to the variable \fInusers\fP
+ */
+.ft CW
+ if (!svc_sendreply(transp, xdr_u_long, &nusers))
+ fprintf(stderr, "can't reply to RPC call\en");
+ return;
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.DE
+.LP
+First, the server gets a transport handle, which is used
+for receiving and replying to RPC messages.
+.I registerrpc()
+uses
+.I svcudp_create()
+to get a UDP handle.
+If you require a more reliable protocol, call
+.I svctcp_create()
+instead.
+If the argument to
+.I svcudp_create()
+is
+.I RPC_ANYSOCK
+the RPC library creates a socket
+on which to receive and reply to RPC calls. Otherwise,
+.I svcudp_create()
+expects its argument to be a valid socket number.
+If you specify your own socket, it can be bound or unbound.
+If it is bound to a port by the user, the port numbers of
+.I svcudp_create()
+and
+.I clnttcp_create()
+(the low-level client routine) must match.
+.LP
+If the user specifies the
+.I RPC_ANYSOCK
+argument, the RPC library routines will open sockets.
+Otherwise they will expect the user to do so. The routines
+.I svcudp_create()
+and
+.I clntudp_create()
+will cause the RPC library routines to
+.I bind()
+their socket if it is not bound already.
+.LP
+A service may choose to register its port number with the
+local portmapper service. This is done is done by specifying
+a non-zero protocol number in
+.I svc_register ().
+Incidently, a client can discover the server's port number by
+consulting the portmapper on their server's machine. This can
+be done automatically by specifying a zero port number in
+.I clntudp_create()
+or
+.I clnttcp_create ().
+.LP
+After creating an
+.I SVCXPRT ,
+the next step is to call
+.I pmap_unset()
+so that if the
+.I nusers()
+server crashed earlier,
+any previous trace of it is erased before restarting.
+More precisely,
+.I pmap_unset()
+erases the entry for
+.I RUSERSPROG
+from the port mapper's tables.
+.LP
+Finally, we associate the program number for
+.I nusers()
+with the procedure
+.I nuser ().
+The final argument to
+.I svc_register()
+is normally the protocol being used,
+which, in this case, is
+.I IPPROTO_UDP
+Notice that unlike
+.I registerrpc (),
+there are no XDR routines involved
+in the registration process.
+Also, registration is done on the program,
+rather than procedure, level.
+.LP
+The user routine
+.I nuser()
+must call and dispatch the appropriate XDR routines
+based on the procedure number.
+Note that
+two things are handled by
+.I nuser()
+that
+.I registerrpc()
+handles automatically.
+The first is that procedure
+.I NULLPROC
+(currently zero) returns with no results.
+This can be used as a simple test
+for detecting if a remote program is running.
+Second, there is a check for invalid procedure numbers.
+If one is detected,
+.I svcerr_noproc()
+is called to handle the error.
+.KS
+.LP
+The user service routine serializes the results and returns
+them to the RPC caller via
+.I svc_sendreply()
+Its first parameter is the
+.I SVCXPRT
+handle, the second is the XDR routine,
+and the third is a pointer to the data to be returned.
+Not illustrated above is how a server
+handles an RPC program that receives data.
+As an example, we can add a procedure
+.I RUSERSPROC_BOOL
+which has an argument
+.I nusers (),
+and returns
+.I TRUE
+or
+.I FALSE
+depending on whether there are nusers logged on.
+It would look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+case RUSERSPROC_BOOL: {
+ int bool;
+ unsigned nuserquery;
+
+ if (!svc_getargs(transp, xdr_u_int, &nuserquery) {
+ svcerr_decode(transp);
+ return;
+ }
+.ft I
+ /*
+ * Code to set \fInusers\fP = number of users
+ */
+.ft CW
+ if (nuserquery == nusers)
+ bool = TRUE;
+ else
+ bool = FALSE;
+ if (!svc_sendreply(transp, xdr_bool, &bool)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+}
+.DE
+.KE
+.LP
+The relevant routine is
+.I svc_getargs()
+which takes an
+.I SVCXPRT
+handle, the XDR routine,
+and a pointer to where the input is to be placed as arguments.
+.NH 2
+\&Memory Allocation with XDR
+.IX "memory allocation with XDR"
+.IX XDR "memory allocation"
+.LP
+XDR routines not only do input and output,
+they also do memory allocation.
+This is why the second parameter of
+.I xdr_array()
+is a pointer to an array, rather than the array itself.
+If it is
+.I NULL ,
+then
+.I xdr_array()
+allocates space for the array and returns a pointer to it,
+putting the size of the array in the third argument.
+As an example, consider the following XDR routine
+.I xdr_chararr1()
+which deals with a fixed array of bytes with length
+.I SIZE .
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_chararr1(xdrsp, chararr)
+ XDR *xdrsp;
+ char chararr[];
+{
+ char *p;
+ int len;
+
+ p = chararr;
+ len = SIZE;
+ return (xdr_bytes(xdrsp, &p, &len, SIZE));
+}
+.DE
+If space has already been allocated in
+.I chararr ,
+it can be called from a server like this:
+.ie t .DS
+.el .DS L
+.ft CW
+char chararr[SIZE];
+
+svc_getargs(transp, xdr_chararr1, chararr);
+.DE
+If you want XDR to do the allocation,
+you would have to rewrite this routine in the following way:
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_chararr2(xdrsp, chararrp)
+ XDR *xdrsp;
+ char **chararrp;
+{
+ int len;
+
+ len = SIZE;
+ return (xdr_bytes(xdrsp, charrarrp, &len, SIZE));
+}
+.DE
+Then the RPC call might look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+char *arrptr;
+
+arrptr = NULL;
+svc_getargs(transp, xdr_chararr2, &arrptr);
+.ft I
+/*
+ * Use the result here
+ */
+.ft CW
+svc_freeargs(transp, xdr_chararr2, &arrptr);
+.DE
+Note that, after being used, the character array can be freed with
+.I svc_freeargs()
+.I svc_freeargs()
+will not attempt to free any memory if the variable indicating it
+is NULL. For example, in the the routine
+.I xdr_finalexample (),
+given earlier, if
+.I finalp->string
+was NULL, then it would not be freed. The same is true for
+.I finalp->simplep .
+.LP
+To summarize, each XDR routine is responsible
+for serializing, deserializing, and freeing memory.
+When an XDR routine is called from
+.I callrpc()
+the serializing part is used.
+When called from
+.I svc_getargs()
+the deserializer is used.
+And when called from
+.I svc_freeargs()
+the memory deallocator is used. When building simple examples like those
+in this section, a user doesn't have to worry
+about the three modes.
+See the
+.I "External Data Representation: Sun Technical Notes"
+for examples of more sophisticated XDR routines that determine
+which of the three modes they are in and adjust their behavior accordingly.
+.KS
+.NH 2
+\&The Calling Side
+.IX RPC "calling side"
+.LP
+When you use
+.I callrpc()
+you have no control over the RPC delivery
+mechanism or the socket used to transport the data.
+To illustrate the layer of RPC that lets you adjust these
+parameters, consider the following code to call the
+.I nusers
+service:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netdb.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct hostent *hp;
+ struct timeval pertry_timeout, total_timeout;
+ struct sockaddr_in server_addr;
+ int sock = RPC_ANYSOCK;
+ register CLIENT *client;
+ enum clnt_stat clnt_stat;
+ unsigned long nusers;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: nusers hostname\en");
+ exit(-1);
+ }
+ if ((hp = gethostbyname(argv[1])) == NULL) {
+ fprintf(stderr, "can't get addr for %s\en",argv[1]);
+ exit(-1);
+ }
+ pertry_timeout.tv_sec = 3;
+ pertry_timeout.tv_usec = 0;
+ bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
+ hp->h_length);
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = 0;
+ if ((client = clntudp_create(&server_addr, RUSERSPROG,
+ RUSERSVERS, pertry_timeout, &sock)) == NULL) {
+ clnt_pcreateerror("clntudp_create");
+ exit(-1);
+ }
+ total_timeout.tv_sec = 20;
+ total_timeout.tv_usec = 0;
+ clnt_stat = clnt_call(client, RUSERSPROC_NUM, xdr_void,
+ 0, xdr_u_long, &nusers, total_timeout);
+ if (clnt_stat != RPC_SUCCESS) {
+ clnt_perror(client, "rpc");
+ exit(-1);
+ }
+ clnt_destroy(client);
+ close(sock);
+ exit(0);
+}
+.vs
+.DE
+.KE
+The low-level version of
+.I callrpc()
+is
+.I clnt_call()
+which takes a
+.I CLIENT
+pointer rather than a host name. The parameters to
+.I clnt_call()
+are a
+.I CLIENT
+pointer, the procedure number,
+the XDR routine for serializing the argument,
+a pointer to the argument,
+the XDR routine for deserializing the return value,
+a pointer to where the return value will be placed,
+and the time in seconds to wait for a reply.
+.LP
+The
+.I CLIENT
+pointer is encoded with the transport mechanism.
+.I callrpc()
+uses UDP, thus it calls
+.I clntudp_create()
+to get a
+.I CLIENT
+pointer. To get TCP (Transmission Control Protocol), you would use
+.I clnttcp_create() .
+.LP
+The parameters to
+.I clntudp_create()
+are the server address, the program number, the version number,
+a timeout value (between tries), and a pointer to a socket.
+The final argument to
+.I clnt_call()
+is the total time to wait for a response.
+Thus, the number of tries is the
+.I clnt_call()
+timeout divided by the
+.I clntudp_create()
+timeout.
+.LP
+Note that the
+.I clnt_destroy()
+call
+always deallocates the space associated with the
+.I CLIENT
+handle. It closes the socket associated with the
+.I CLIENT
+handle, however, only if the RPC library opened it. It the
+socket was opened by the user, it stays open. This makes it
+possible, in cases where there are multiple client handles
+using the same socket, to destroy one handle without closing
+the socket that other handles are using.
+.LP
+To make a stream connection, the call to
+.I clntudp_create()
+is replaced with a call to
+.I clnttcp_create() .
+.DS
+.ft CW
+clnttcp_create(&server_addr, prognum, versnum, &sock,
+ inputsize, outputsize);
+.DE
+There is no timeout argument; instead, the receive and send buffer
+sizes must be specified. When the
+.I clnttcp_create()
+call is made, a TCP connection is established.
+All RPC calls using that
+.I CLIENT
+handle would use this connection.
+The server side of an RPC call using TCP has
+.I svcudp_create()
+replaced by
+.I svctcp_create() .
+.DS
+.ft CW
+transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+.DE
+The last two arguments to
+.I svctcp_create()
+are send and receive sizes respectively. If `0' is specified for
+either of these, the system chooses a reasonable default.
+.KS
+.NH 1
+\&Other RPC Features
+.IX "RPC" "miscellaneous features"
+.IX "miscellaneous RPC features"
+.LP
+This section discusses some other aspects of RPC
+that are occasionally useful.
+.NH 2
+\&Select on the Server Side
+.IX RPC select() RPC \fIselect()\fP
+.IX select() "" \fIselect()\fP "on the server side"
+.LP
+Suppose a process is processing RPC requests
+while performing some other activity.
+If the other activity involves periodically updating a data structure,
+the process can set an alarm signal before calling
+.I svc_run()
+But if the other activity
+involves waiting on a file descriptor, the
+.I svc_run()
+call won't work.
+The code for
+.I svc_run()
+is as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+void
+svc_run()
+{
+ fd_set readfds;
+ int dtbsz = getdtablesize();
+
+ for (;;) {
+ readfds = svc_fds;
+ switch (select(dtbsz, &readfds, NULL,NULL,NULL)) {
+
+ case -1:
+ if (errno == EINTR)
+ continue;
+ perror("select");
+ return;
+ case 0:
+ break;
+ default:
+ svc_getreqset(&readfds);
+ }
+ }
+}
+.vs
+.DE
+.KE
+.LP
+You can bypass
+.I svc_run()
+and call
+.I svc_getreqset()
+yourself.
+All you need to know are the file descriptors
+of the socket(s) associated with the programs you are waiting on.
+Thus you can have your own
+.I select()
+.IX select() "" \fIselect()\fP
+that waits on both the RPC socket,
+and your own descriptors. Note that
+.I svc_fds()
+is a bit mask of all the file descriptors that RPC is using for
+services. It can change everytime that
+.I any
+RPC library routine is called, because descriptors are constantly
+being opened and closed, for example for TCP connections.
+.NH 2
+\&Broadcast RPC
+.IX "broadcast RPC"
+.IX RPC "broadcast"
+.LP
+The
+.I portmapper
+is a daemon that converts RPC program numbers
+into DARPA protocol port numbers; see the
+.I portmap
+man page. You can't do broadcast RPC without the portmapper.
+Here are the main differences between
+broadcast RPC and normal RPC calls:
+.IP 1.
+Normal RPC expects one answer, whereas
+broadcast RPC expects many answers
+(one or more answer from each responding machine).
+.IP 2.
+Broadcast RPC can only be supported by packet-oriented (connectionless)
+transport protocols like UPD/IP.
+.IP 3.
+The implementation of broadcast RPC
+treats all unsuccessful responses as garbage by filtering them out.
+Thus, if there is a version mismatch between the
+broadcaster and a remote service,
+the user of broadcast RPC never knows.
+.IP 4.
+All broadcast messages are sent to the portmap port.
+Thus, only services that register themselves with their portmapper
+are accessible via the broadcast RPC mechanism.
+.IP 5.
+Broadcast requests are limited in size to the MTU (Maximum Transfer
+Unit) of the local network. For Ethernet, the MTU is 1500 bytes.
+.KS
+.NH 3
+\&Broadcast RPC Synopsis
+.IX "broadcast RPC" synopsis
+.IX "RPC" "broadcast synopsis"
+.ie t .DS
+.el .DS L
+.ft CW
+#include <rpc/pmap_clnt.h>
+ . . .
+enum clnt_stat clnt_stat;
+ . . .
+clnt_stat = clnt_broadcast(prognum, versnum, procnum,
+ inproc, in, outproc, out, eachresult)
+ u_long prognum; /* \fIprogram number\fP */
+ u_long versnum; /* \fIversion number\fP */
+ u_long procnum; /* \fIprocedure number\fP */
+ xdrproc_t inproc; /* \fIxdr routine for args\fP */
+ caddr_t in; /* \fIpointer to args\fP */
+ xdrproc_t outproc; /* \fIxdr routine for results\fP */
+ caddr_t out; /* \fIpointer to results\fP */
+ bool_t (*eachresult)();/* \fIcall with each result gotten\fP */
+.DE
+.KE
+The procedure
+.I eachresult()
+is called each time a valid result is obtained.
+It returns a boolean that indicates
+whether or not the user wants more responses.
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t done;
+ . . .
+done = eachresult(resultsp, raddr)
+ caddr_t resultsp;
+ struct sockaddr_in *raddr; /* \fIAddr of responding machine\fP */
+.DE
+If
+.I done
+is
+.I TRUE ,
+then broadcasting stops and
+.I clnt_broadcast()
+returns successfully.
+Otherwise, the routine waits for another response.
+The request is rebroadcast
+after a few seconds of waiting.
+If no responses come back,
+the routine returns with
+.I RPC_TIMEDOUT .
+.NH 2
+\&Batching
+.IX "batching"
+.IX RPC "batching"
+.LP
+The RPC architecture is designed so that clients send a call message,
+and wait for servers to reply that the call succeeded.
+This implies that clients do not compute
+while servers are processing a call.
+This is inefficient if the client does not want or need
+an acknowledgement for every message sent.
+It is possible for clients to continue computing
+while waiting for a response,
+using RPC batch facilities.
+.LP
+RPC messages can be placed in a \*Qpipeline\*U of calls
+to a desired server; this is called batching.
+Batching assumes that:
+1) each RPC call in the pipeline requires no response from the server,
+and the server does not send a response message; and
+2) the pipeline of calls is transported on a reliable
+byte stream transport such as TCP/IP.
+Since the server does not respond to every call,
+the client can generate new calls in parallel
+with the server executing previous calls.
+Furthermore, the TCP/IP implementation can buffer up
+many call messages, and send them to the server in one
+.I write()
+system call. This overlapped execution
+greatly decreases the interprocess communication overhead of
+the client and server processes,
+and the total elapsed time of a series of calls.
+.LP
+Since the batched calls are buffered,
+the client should eventually do a nonbatched call
+in order to flush the pipeline.
+.LP
+A contrived example of batching follows.
+Assume a string rendering service (like a window system)
+has two similar calls: one renders a string and returns void results,
+while the other renders a string and remains silent.
+The service (using the TCP/IP transport) may look like:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <suntool/windows.h>
+
+void windowdispatch();
+
+main()
+{
+ SVCXPRT *transp;
+
+ transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+ if (transp == NULL){
+ fprintf(stderr, "can't create an RPC server\en");
+ exit(1);
+ }
+ pmap_unset(WINDOWPROG, WINDOWVERS);
+ if (!svc_register(transp, WINDOWPROG, WINDOWVERS,
+ windowdispatch, IPPROTO_TCP)) {
+ fprintf(stderr, "can't register WINDOW service\en");
+ exit(1);
+ }
+ svc_run(); /* \fINever returns\fP */
+ fprintf(stderr, "should never reach this point\en");
+}
+
+void
+windowdispatch(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ char *s = NULL;
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (!svc_sendreply(transp, xdr_void, 0))
+ fprintf(stderr, "can't reply to RPC call\en");
+ return;
+ case RENDERSTRING:
+ if (!svc_getargs(transp, xdr_wrapstring, &s)) {
+ fprintf(stderr, "can't decode arguments\en");
+.ft I
+ /*
+ * Tell caller he screwed up
+ */
+.ft CW
+ svcerr_decode(transp);
+ break;
+ }
+.ft I
+ /*
+ * Code here to render the string \fIs\fP
+ */
+.ft CW
+ if (!svc_sendreply(transp, xdr_void, NULL))
+ fprintf(stderr, "can't reply to RPC call\en");
+ break;
+ case RENDERSTRING_BATCHED:
+ if (!svc_getargs(transp, xdr_wrapstring, &s)) {
+ fprintf(stderr, "can't decode arguments\en");
+.ft I
+ /*
+ * We are silent in the face of protocol errors
+ */
+.ft CW
+ break;
+ }
+.ft I
+ /*
+ * Code here to render string s, but send no reply!
+ */
+.ft CW
+ break;
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+.ft I
+ /*
+ * Now free string allocated while decoding arguments
+ */
+.ft CW
+ svc_freeargs(transp, xdr_wrapstring, &s);
+}
+.DE
+Of course the service could have one procedure
+that takes the string and a boolean
+to indicate whether or not the procedure should respond.
+.LP
+In order for a client to take advantage of batching,
+the client must perform RPC calls on a TCP-based transport
+and the actual calls must have the following attributes:
+1) the result's XDR routine must be zero
+.I NULL ),
+and 2) the RPC call's timeout must be zero.
+.KS
+.LP
+Here is an example of a client that uses batching to render a
+bunch of strings; the batching is flushed when the client gets
+a null string (EOF):
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <suntool/windows.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct hostent *hp;
+ struct timeval pertry_timeout, total_timeout;
+ struct sockaddr_in server_addr;
+ int sock = RPC_ANYSOCK;
+ register CLIENT *client;
+ enum clnt_stat clnt_stat;
+ char buf[1000], *s = buf;
+
+ if ((client = clnttcp_create(&server_addr,
+ WINDOWPROG, WINDOWVERS, &sock, 0, 0)) == NULL) {
+ perror("clnttcp_create");
+ exit(-1);
+ }
+ total_timeout.tv_sec = 0;
+ total_timeout.tv_usec = 0;
+ while (scanf("%s", s) != EOF) {
+ clnt_stat = clnt_call(client, RENDERSTRING_BATCHED,
+ xdr_wrapstring, &s, NULL, NULL, total_timeout);
+ if (clnt_stat != RPC_SUCCESS) {
+ clnt_perror(client, "batched rpc");
+ exit(-1);
+ }
+ }
+
+ /* \fINow flush the pipeline\fP */
+
+ total_timeout.tv_sec = 20;
+ clnt_stat = clnt_call(client, NULLPROC, xdr_void, NULL,
+ xdr_void, NULL, total_timeout);
+ if (clnt_stat != RPC_SUCCESS) {
+ clnt_perror(client, "rpc");
+ exit(-1);
+ }
+ clnt_destroy(client);
+ exit(0);
+}
+.vs
+.DE
+.KE
+Since the server sends no message,
+the clients cannot be notified of any of the failures that may occur.
+Therefore, clients are on their own when it comes to handling errors.
+.LP
+The above example was completed to render
+all of the (2000) lines in the file
+.I /etc/termcap .
+The rendering service did nothing but throw the lines away.
+The example was run in the following four configurations:
+1) machine to itself, regular RPC;
+2) machine to itself, batched RPC;
+3) machine to another, regular RPC; and
+4) machine to another, batched RPC.
+The results are as follows:
+1) 50 seconds;
+2) 16 seconds;
+3) 52 seconds;
+4) 10 seconds.
+Running
+.I fscanf()
+on
+.I /etc/termcap
+only requires six seconds.
+These timings show the advantage of protocols
+that allow for overlapped execution,
+though these protocols are often hard to design.
+.NH 2
+\&Authentication
+.IX "authentication"
+.IX "RPC" "authentication"
+.LP
+In the examples presented so far,
+the caller never identified itself to the server,
+and the server never required an ID from the caller.
+Clearly, some network services, such as a network filesystem,
+require stronger security than what has been presented so far.
+.LP
+In reality, every RPC call is authenticated by
+the RPC package on the server, and similarly,
+the RPC client package generates and sends authentication parameters.
+Just as different transports (TCP/IP or UDP/IP)
+can be used when creating RPC clients and servers,
+different forms of authentication can be associated with RPC clients;
+the default authentication type used as a default is type
+.I none .
+.LP
+The authentication subsystem of the RPC package is open ended.
+That is, numerous types of authentication are easy to support.
+.NH 3
+\&UNIX Authentication
+.IX "UNIX Authentication"
+.IP "\fIThe Client Side\fP"
+.LP
+When a caller creates a new RPC client handle as in:
+.DS
+.ft CW
+clnt = clntudp_create(address, prognum, versnum,
+ wait, sockp)
+.DE
+the appropriate transport instance defaults
+the associate authentication handle to be
+.DS
+.ft CW
+clnt->cl_auth = authnone_create();
+.DE
+The RPC client can choose to use
+.I UNIX
+style authentication by setting
+.I clnt\->cl_auth
+after creating the RPC client handle:
+.DS
+.ft CW
+clnt->cl_auth = authunix_create_default();
+.DE
+This causes each RPC call associated with
+.I clnt
+to carry with it the following authentication credentials structure:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * UNIX style credentials.
+ */
+.ft CW
+struct authunix_parms {
+ u_long aup_time; /* \fIcredentials creation time\fP */
+ char *aup_machname; /* \fIhost name where client is\fP */
+ int aup_uid; /* \fIclient's UNIX effective uid\fP */
+ int aup_gid; /* \fIclient's current group id\fP */
+ u_int aup_len; /* \fIelement length of aup_gids\fP */
+ int *aup_gids; /* \fIarray of groups user is in\fP */
+};
+.DE
+These fields are set by
+.I authunix_create_default()
+by invoking the appropriate system calls.
+Since the RPC user created this new style of authentication,
+the user is responsible for destroying it with:
+.DS
+.ft CW
+auth_destroy(clnt->cl_auth);
+.DE
+This should be done in all cases, to conserve memory.
+.sp
+.IP "\fIThe Server Side\fP"
+.LP
+Service implementors have a harder time dealing with authentication issues
+since the RPC package passes the service dispatch routine a request
+that has an arbitrary authentication style associated with it.
+Consider the fields of a request handle passed to a service dispatch routine:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * An RPC Service request
+ */
+.ft CW
+struct svc_req {
+ u_long rq_prog; /* \fIservice program number\fP */
+ u_long rq_vers; /* \fIservice protocol vers num\fP */
+ u_long rq_proc; /* \fIdesired procedure number\fP */
+ struct opaque_auth rq_cred; /* \fIraw credentials from wire\fP */
+ caddr_t rq_clntcred; /* \fIcredentials (read only)\fP */
+};
+.DE
+The
+.I rq_cred
+is mostly opaque, except for one field of interest:
+the style or flavor of authentication credentials:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * Authentication info. Mostly opaque to the programmer.
+ */
+.ft CW
+struct opaque_auth {
+ enum_t oa_flavor; /* \fIstyle of credentials\fP */
+ caddr_t oa_base; /* \fIaddress of more auth stuff\fP */
+ u_int oa_length; /* \fInot to exceed \fIMAX_AUTH_BYTES */
+};
+.DE
+.IX RPC guarantees
+The RPC package guarantees the following
+to the service dispatch routine:
+.IP 1.
+That the request's
+.I rq_cred
+is well formed. Thus the service implementor may inspect the request's
+.I rq_cred.oa_flavor
+to determine which style of authentication the caller used.
+The service implementor may also wish to inspect the other fields of
+.I rq_cred
+if the style is not one of the styles supported by the RPC package.
+.IP 2.
+That the request's
+.I rq_clntcred
+field is either
+.I NULL
+or points to a well formed structure
+that corresponds to a supported style of authentication credentials.
+Remember that only
+.I unix
+style is currently supported, so (currently)
+.I rq_clntcred
+could be cast to a pointer to an
+.I authunix_parms
+structure. If
+.I rq_clntcred
+is
+.I NULL ,
+the service implementor may wish to inspect the other (opaque) fields of
+.I rq_cred
+in case the service knows about a new type of authentication
+that the RPC package does not know about.
+.LP
+Our remote users service example can be extended so that
+it computes results for all users except UID 16:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ struct authunix_parms *unix_cred;
+ int uid;
+ unsigned long nusers;
+
+.ft I
+ /*
+ * we don't care about authentication for null proc
+ */
+.ft CW
+ if (rqstp->rq_proc == NULLPROC) {
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+ }
+.ft I
+ /*
+ * now get the uid
+ */
+.ft CW
+ switch (rqstp->rq_cred.oa_flavor) {
+ case AUTH_UNIX:
+ unix_cred =
+ (struct authunix_parms *)rqstp->rq_clntcred;
+ uid = unix_cred->aup_uid;
+ break;
+ case AUTH_NULL:
+ default:
+ svcerr_weakauth(transp);
+ return;
+ }
+ switch (rqstp->rq_proc) {
+ case RUSERSPROC_NUM:
+.ft I
+ /*
+ * make sure caller is allowed to call this proc
+ */
+.ft CW
+ if (uid == 16) {
+ svcerr_systemerr(transp);
+ return;
+ }
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and assign it to the variable \fInusers\fP
+ */
+.ft CW
+ if (!svc_sendreply(transp, xdr_u_long, &nusers)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.vs
+.DE
+A few things should be noted here.
+First, it is customary not to check
+the authentication parameters associated with the
+.I NULLPROC
+(procedure number zero).
+Second, if the authentication parameter's type is not suitable
+for your service, you should call
+.I svcerr_weakauth() .
+And finally, the service protocol itself should return status
+for access denied; in the case of our example, the protocol
+does not have such a status, so we call the service primitive
+.I svcerr_systemerr()
+instead.
+.LP
+The last point underscores the relation between
+the RPC authentication package and the services;
+RPC deals only with
+.I authentication
+and not with individual services'
+.I "access control" .
+The services themselves must implement their own access control policies
+and reflect these policies as return statuses in their protocols.
+.NH 2
+\&DES Authentication
+.IX RPC DES
+.IX RPC authentication
+.LP
+UNIX authentication is quite easy to defeat. Instead of using
+.I authunix_create_default (),
+one can call
+.I authunix_create()
+and then modify the RPC authentication handle it returns by filling in
+whatever user ID and hostname they wish the server to think they have.
+DES authentication is thus recommended for people who want more security
+than UNIX authentication offers.
+.LP
+The details of the DES authentication protocol are complicated and
+are not explained here.
+See
+.I "Remote Procedure Calls: Protocol Specification"
+for the details.
+.LP
+In order for DES authentication to work, the
+.I keyserv(8c)
+daemon must be running on both the server and client machines. The
+users on these machines need public keys assigned by the network
+administrator in the
+.I publickey(5)
+database. And, they need to have decrypted their secret keys
+using their login password. This automatically happens when one
+logs in using
+.I login(1) ,
+or can be done manually using
+.I keylogin(1) .
+The
+.I "Network Services"
+chapter
+.\" XXX
+explains more how to setup secure networking.
+.sp
+.IP "\fIClient Side\fP"
+.LP
+If a client wishes to use DES authentication, it must set its
+authentication handle appropriately. Here is an example:
+.DS
+cl->cl_auth =
+ authdes_create(servername, 60, &server_addr, NULL);
+.DE
+The first argument is the network name or \*Qnetname\*U of the owner of
+the server process. Typically, server processes are root processes
+and their netname can be derived using the following call:
+.DS
+char servername[MAXNETNAMELEN];
+
+host2netname(servername, rhostname, NULL);
+.DE
+Here,
+.I rhostname
+is the hostname of the machine the server process is running on.
+.I host2netname()
+fills in
+.I servername
+to contain this root process's netname. If the
+server process was run by a regular user, one could use the call
+.I user2netname()
+instead. Here is an example for a server process with the same user
+ID as the client:
+.DS
+char servername[MAXNETNAMELEN];
+
+user2netname(servername, getuid(), NULL);
+.DE
+The last argument to both of these calls,
+.I user2netname()
+and
+.I host2netname (),
+is the name of the naming domain where the server is located. The
+.I NULL
+used here means \*Quse the local domain name.\*U
+.LP
+The second argument to
+.I authdes_create()
+is a lifetime for the credential. Here it is set to sixty
+seconds. What that means is that the credential will expire 60
+seconds from now. If some mischievous user tries to reuse the
+credential, the server RPC subsystem will recognize that it has
+expired and not grant any requests. If the same mischievous user
+tries to reuse the credential within the sixty second lifetime,
+he will still be rejected because the server RPC subsystem
+remembers which credentials it has already seen in the near past,
+and will not grant requests to duplicates.
+.LP
+The third argument to
+.I authdes_create()
+is the address of the host to synchronize with. In order for DES
+authentication to work, the server and client must agree upon the
+time. Here we pass the address of the server itself, so the
+client and server will both be using the same time: the server's
+time. The argument can be
+.I NULL ,
+which means \*Qdon't bother synchronizing.\*U You should only do this
+if you are sure the client and server are already synchronized.
+.LP
+The final argument to
+.I authdes_create()
+is the address of a DES encryption key to use for encrypting
+timestamps and data. If this argument is
+.I NULL ,
+as it is in this example, a random key will be chosen. The client
+may find out the encryption key being used by consulting the
+.I ah_key
+field of the authentication handle.
+.sp
+.IP "\fIServer Side\fP"
+.LP
+The server side is a lot simpler than the client side. Here is the
+previous example rewritten to use
+.I AUTH_DES
+instead of
+.I AUTH_UNIX :
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <sys/time.h>
+#include <rpc/auth_des.h>
+ . . .
+ . . .
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ struct authdes_cred *des_cred;
+ int uid;
+ int gid;
+ int gidlen;
+ int gidlist[10];
+.ft I
+ /*
+ * we don't care about authentication for null proc
+ */
+.ft CW
+
+ if (rqstp->rq_proc == NULLPROC) {
+ /* \fIsame as before\fP */
+ }
+
+.ft I
+ /*
+ * now get the uid
+ */
+.ft CW
+ switch (rqstp->rq_cred.oa_flavor) {
+ case AUTH_DES:
+ des_cred =
+ (struct authdes_cred *) rqstp->rq_clntcred;
+ if (! netname2user(des_cred->adc_fullname.name,
+ &uid, &gid, &gidlen, gidlist))
+ {
+ fprintf(stderr, "unknown user: %s\en",
+ des_cred->adc_fullname.name);
+ svcerr_systemerr(transp);
+ return;
+ }
+ break;
+ case AUTH_NULL:
+ default:
+ svcerr_weakauth(transp);
+ return;
+ }
+
+.ft I
+ /*
+ * The rest is the same as before
+ */
+.ft CW
+.vs
+.DE
+Note the use of the routine
+.I netname2user (),
+the inverse of
+.I user2netname ():
+it takes a network ID and converts to a unix ID.
+.I netname2user ()
+also supplies the group IDs which we don't use in this example,
+but which may be useful to other UNIX programs.
+.NH 2
+\&Using Inetd
+.IX inetd "" "using \fIinetd\fP"
+.LP
+An RPC server can be started from
+.I inetd
+The only difference from the usual code is that the service
+creation routine should be called in the following form:
+.ie t .DS
+.el .DS L
+.ft CW
+transp = svcudp_create(0); /* \fIFor UDP\fP */
+transp = svctcp_create(0,0,0); /* \fIFor listener TCP sockets\fP */
+transp = svcfd_create(0,0,0); /* \fIFor connected TCP sockets\fP */
+.DE
+since
+.I inet
+passes a socket as file descriptor 0.
+Also,
+.I svc_register()
+should be called as
+.ie t .DS
+.el .DS L
+.ft CW
+svc_register(transp, PROGNUM, VERSNUM, service, 0);
+.DE
+with the final flag as 0,
+since the program would already be registered by
+.I inetd
+Remember that if you want to exit
+from the server process and return control to
+.I inet
+you need to explicitly exit, since
+.I svc_run()
+never returns.
+.LP
+The format of entries in
+.I /etc/inetd.conf
+for RPC services is in one of the following two forms:
+.ie t .DS
+.el .DS L
+.ft CW
+p_name/version dgram rpc/udp wait/nowait user server args
+p_name/version stream rpc/tcp wait/nowait user server args
+.DE
+where
+.I p_name
+is the symbolic name of the program as it appears in
+.I rpc(5) ,
+.I server
+is the program implementing the server,
+and
+.I program
+and
+.I version
+are the program and version numbers of the service.
+For more information, see
+.I inetd.conf(5) .
+.LP
+If the same program handles multiple versions,
+then the version number can be a range,
+as in this example:
+.ie t .DS
+.el .DS L
+.ft CW
+rstatd/1-2 dgram rpc/udp wait root /usr/etc/rpc.rstatd
+.DE
+.NH 1
+\&More Examples
+.sp 1
+.NH 2
+\&Versions
+.IX "versions"
+.IX "RPC" "versions"
+.LP
+By convention, the first version number of program
+.I PROG
+is
+.I PROGVERS_ORIG
+and the most recent version is
+.I PROGVERS
+Suppose there is a new version of the
+.I user
+program that returns an
+.I "unsigned short"
+rather than a
+.I long .
+If we name this version
+.I RUSERSVERS_SHORT
+then a server that wants to support both versions
+would do a double register.
+.ie t .DS
+.el .DS L
+.ft CW
+if (!svc_register(transp, RUSERSPROG, RUSERSVERS_ORIG,
+ nuser, IPPROTO_TCP)) {
+ fprintf(stderr, "can't register RUSER service\en");
+ exit(1);
+}
+if (!svc_register(transp, RUSERSPROG, RUSERSVERS_SHORT,
+ nuser, IPPROTO_TCP)) {
+ fprintf(stderr, "can't register RUSER service\en");
+ exit(1);
+}
+.DE
+Both versions can be handled by the same C procedure:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ unsigned long nusers;
+ unsigned short nusers2;
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+ case RUSERSPROC_NUM:
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and assign it to the variable \fInusers\fP
+ */
+.ft CW
+ nusers2 = nusers;
+ switch (rqstp->rq_vers) {
+ case RUSERSVERS_ORIG:
+ if (!svc_sendreply(transp, xdr_u_long,
+ &nusers)) {
+ fprintf(stderr,"can't reply to RPC call\en");
+ }
+ break;
+ case RUSERSVERS_SHORT:
+ if (!svc_sendreply(transp, xdr_u_short,
+ &nusers2)) {
+ fprintf(stderr,"can't reply to RPC call\en");
+ }
+ break;
+ }
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.vs
+.DE
+.KS
+.NH 2
+\&TCP
+.IX "TCP"
+.LP
+Here is an example that is essentially
+.I rcp.
+The initiator of the RPC
+.I snd
+call takes its standard input and sends it to the server
+.I rcv
+which prints it on standard output.
+The RPC call uses TCP.
+This also illustrates an XDR procedure that behaves differently
+on serialization than on deserialization.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * The xdr routine:
+ * on decode, read from wire, write onto fp
+ * on encode, read from fp, write onto wire
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+xdr_rcp(xdrs, fp)
+ XDR *xdrs;
+ FILE *fp;
+{
+ unsigned long size;
+ char buf[BUFSIZ], *p;
+
+ if (xdrs->x_op == XDR_FREE)/* nothing to free */
+ return 1;
+ while (1) {
+ if (xdrs->x_op == XDR_ENCODE) {
+ if ((size = fread(buf, sizeof(char), BUFSIZ,
+ fp)) == 0 && ferror(fp)) {
+ fprintf(stderr, "can't fread\en");
+ return (1);
+ }
+ }
+ p = buf;
+ if (!xdr_bytes(xdrs, &p, &size, BUFSIZ))
+ return 0;
+ if (size == 0)
+ return 1;
+ if (xdrs->x_op == XDR_DECODE) {
+ if (fwrite(buf, sizeof(char), size,
+ fp) != size) {
+ fprintf(stderr, "can't fwrite\en");
+ return (1);
+ }
+ }
+ }
+}
+.vs
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * The sender routines
+ */
+.ft CW
+#include <stdio.h>
+#include <netdb.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int xdr_rcp();
+ int err;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s servername\en", argv[0]);
+ exit(-1);
+ }
+ if ((err = callrpctcp(argv[1], RCPPROG, RCPPROC,
+ RCPVERS, xdr_rcp, stdin, xdr_void, 0) != 0)) {
+ clnt_perrno(err);
+ fprintf(stderr, "can't make RPC call\en");
+ exit(1);
+ }
+ exit(0);
+}
+
+callrpctcp(host, prognum, procnum, versnum,
+ inproc, in, outproc, out)
+ char *host, *in, *out;
+ xdrproc_t inproc, outproc;
+{
+ struct sockaddr_in server_addr;
+ int socket = RPC_ANYSOCK;
+ enum clnt_stat clnt_stat;
+ struct hostent *hp;
+ register CLIENT *client;
+ struct timeval total_timeout;
+
+ if ((hp = gethostbyname(host)) == NULL) {
+ fprintf(stderr, "can't get addr for '%s'\en", host);
+ return (-1);
+ }
+ bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
+ hp->h_length);
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = 0;
+ if ((client = clnttcp_create(&server_addr, prognum,
+ versnum, &socket, BUFSIZ, BUFSIZ)) == NULL) {
+ perror("rpctcp_create");
+ return (-1);
+ }
+ total_timeout.tv_sec = 20;
+ total_timeout.tv_usec = 0;
+ clnt_stat = clnt_call(client, procnum,
+ inproc, in, outproc, out, total_timeout);
+ clnt_destroy(client);
+ return (int)clnt_stat;
+}
+.vs
+.DE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * The receiving routines
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+main()
+{
+ register SVCXPRT *transp;
+ int rcp_service(), xdr_rcp();
+
+ if ((transp = svctcp_create(RPC_ANYSOCK,
+ BUFSIZ, BUFSIZ)) == NULL) {
+ fprintf("svctcp_create: error\en");
+ exit(1);
+ }
+ pmap_unset(RCPPROG, RCPVERS);
+ if (!svc_register(transp,
+ RCPPROG, RCPVERS, rcp_service, IPPROTO_TCP)) {
+ fprintf(stderr, "svc_register: error\en");
+ exit(1);
+ }
+ svc_run(); /* \fInever returns\fP */
+ fprintf(stderr, "svc_run should never return\en");
+}
+
+rcp_service(rqstp, transp)
+ register struct svc_req *rqstp;
+ register SVCXPRT *transp;
+{
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (svc_sendreply(transp, xdr_void, 0) == 0) {
+ fprintf(stderr, "err: rcp_service");
+ return (1);
+ }
+ return;
+ case RCPPROC_FP:
+ if (!svc_getargs(transp, xdr_rcp, stdout)) {
+ svcerr_decode(transp);
+ return;
+ }
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "can't reply\en");
+ return;
+ }
+ return (0);
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.vs
+.DE
+.NH 2
+\&Callback Procedures
+.IX RPC "callback procedures"
+.LP
+Occasionally, it is useful to have a server become a client,
+and make an RPC call back to the process which is its client.
+An example is remote debugging,
+where the client is a window system program,
+and the server is a debugger running on the remote machine.
+Most of the time,
+the user clicks a mouse button at the debugging window,
+which converts this to a debugger command,
+and then makes an RPC call to the server
+(where the debugger is actually running),
+telling it to execute that command.
+However, when the debugger hits a breakpoint, the roles are reversed,
+and the debugger wants to make an rpc call to the window program,
+so that it can inform the user that a breakpoint has been reached.
+.LP
+In order to do an RPC callback,
+you need a program number to make the RPC call on.
+Since this will be a dynamically generated program number,
+it should be in the transient range,
+.I "0x40000000 - 0x5fffffff" .
+The routine
+.I gettransient()
+returns a valid program number in the transient range,
+and registers it with the portmapper.
+It only talks to the portmapper running on the same machine as the
+.I gettransient()
+routine itself. The call to
+.I pmap_set()
+is a test and set operation,
+in that it indivisibly tests whether a program number
+has already been registered,
+and if it has not, then reserves it. On return, the
+.I sockp
+argument will contain a socket that can be used
+as the argument to an
+.I svcudp_create()
+or
+.I svctcp_create()
+call.
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+
+gettransient(proto, vers, sockp)
+ int proto, vers, *sockp;
+{
+ static int prognum = 0x40000000;
+ int s, len, socktype;
+ struct sockaddr_in addr;
+
+ switch(proto) {
+ case IPPROTO_UDP:
+ socktype = SOCK_DGRAM;
+ break;
+ case IPPROTO_TCP:
+ socktype = SOCK_STREAM;
+ break;
+ default:
+ fprintf(stderr, "unknown protocol type\en");
+ return 0;
+ }
+ if (*sockp == RPC_ANYSOCK) {
+ if ((s = socket(AF_INET, socktype, 0)) < 0) {
+ perror("socket");
+ return (0);
+ }
+ *sockp = s;
+ }
+ else
+ s = *sockp;
+ addr.sin_addr.s_addr = 0;
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ len = sizeof(addr);
+.ft I
+ /*
+ * may be already bound, so don't check for error
+ */
+.ft CW
+ bind(s, &addr, len);
+ if (getsockname(s, &addr, &len)< 0) {
+ perror("getsockname");
+ return (0);
+ }
+ while (!pmap_set(prognum++, vers, proto,
+ ntohs(addr.sin_port))) continue;
+ return (prognum-1);
+}
+.vs
+.DE
+.SH
+Note:
+.I
+The call to
+.I ntohs()
+is necessary to ensure that the port number in
+.I "addr.sin_port" ,
+which is in
+.I network
+byte order, is passed in
+.I host
+byte order (as
+.I pmap_set()
+expects). See the
+.I byteorder(3N)
+man page for more details on the conversion of network
+addresses from network to host byte order.
+.KS
+.LP
+The following pair of programs illustrate how to use the
+.I gettransient()
+routine.
+The client makes an RPC call to the server,
+passing it a transient program number.
+Then the client waits around to receive a callback
+from the server at that program number.
+The server registers the program
+.I EXAMPLEPROG
+so that it can receive the RPC call
+informing it of the callback program number.
+Then at some random time (on receiving an
+.I ALRM
+signal in this example), it sends a callback RPC call,
+using the program number it received earlier.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * client
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+int callback();
+char hostname[256];
+
+main()
+{
+ int x, ans, s;
+ SVCXPRT *xprt;
+
+ gethostname(hostname, sizeof(hostname));
+ s = RPC_ANYSOCK;
+ x = gettransient(IPPROTO_UDP, 1, &s);
+ fprintf(stderr, "client gets prognum %d\en", x);
+ if ((xprt = svcudp_create(s)) == NULL) {
+ fprintf(stderr, "rpc_server: svcudp_create\en");
+ exit(1);
+ }
+.ft I
+ /* protocol is 0 - gettransient does registering
+ */
+.ft CW
+ (void)svc_register(xprt, x, 1, callback, 0);
+ ans = callrpc(hostname, EXAMPLEPROG, EXAMPLEVERS,
+ EXAMPLEPROC_CALLBACK, xdr_int, &x, xdr_void, 0);
+ if ((enum clnt_stat) ans != RPC_SUCCESS) {
+ fprintf(stderr, "call: ");
+ clnt_perrno(ans);
+ fprintf(stderr, "\en");
+ }
+ svc_run();
+ fprintf(stderr, "Error: svc_run shouldn't return\en");
+}
+
+callback(rqstp, transp)
+ register struct svc_req *rqstp;
+ register SVCXPRT *transp;
+{
+ switch (rqstp->rq_proc) {
+ case 0:
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "err: exampleprog\en");
+ return (1);
+ }
+ return (0);
+ case 1:
+ if (!svc_getargs(transp, xdr_void, 0)) {
+ svcerr_decode(transp);
+ return (1);
+ }
+ fprintf(stderr, "client got callback\en");
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "err: exampleprog");
+ return (1);
+ }
+ }
+}
+.vs
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * server
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/signal.h>
+
+char *getnewprog();
+char hostname[256];
+int docallback();
+int pnum; /* \fIprogram number for callback routine\fP */
+
+main()
+{
+ gethostname(hostname, sizeof(hostname));
+ registerrpc(EXAMPLEPROG, EXAMPLEVERS,
+ EXAMPLEPROC_CALLBACK, getnewprog, xdr_int, xdr_void);
+ fprintf(stderr, "server going into svc_run\en");
+ signal(SIGALRM, docallback);
+ alarm(10);
+ svc_run();
+ fprintf(stderr, "Error: svc_run shouldn't return\en");
+}
+
+char *
+getnewprog(pnump)
+ char *pnump;
+{
+ pnum = *(int *)pnump;
+ return NULL;
+}
+
+docallback()
+{
+ int ans;
+
+ ans = callrpc(hostname, pnum, 1, 1, xdr_void, 0,
+ xdr_void, 0);
+ if (ans != 0) {
+ fprintf(stderr, "server: ");
+ clnt_perrno(ans);
+ fprintf(stderr, "\en");
+ }
+}
+.vs
+.DE
diff --git a/share/doc/psd/23.rpc/stubs b/share/doc/psd/23.rpc/stubs
new file mode 100644
index 0000000..78b0a2c
--- /dev/null
+++ b/share/doc/psd/23.rpc/stubs
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+.\"
+.if t .ftr L CR
diff --git a/share/doc/psd/24.xdr/Makefile b/share/doc/psd/24.xdr/Makefile
index 878dca1..8e30711 100644
--- a/share/doc/psd/24.xdr/Makefile
+++ b/share/doc/psd/24.xdr/Makefile
@@ -4,6 +4,5 @@ VOLUME= psd/24.xdr
SRCS= stubs xdr.nts.ms
MACROS= -ms
USE_EQN=
-SRCDIR= ${.CURDIR}/../../../../lib/libc/rpc/PSD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/psd/24.xdr/stubs b/share/doc/psd/24.xdr/stubs
new file mode 100644
index 0000000..78b0a2c
--- /dev/null
+++ b/share/doc/psd/24.xdr/stubs
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+.\"
+.if t .ftr L CR
diff --git a/share/doc/psd/24.xdr/xdr.nts.ms b/share/doc/psd/24.xdr/xdr.nts.ms
new file mode 100644
index 0000000..260c7f3
--- /dev/null
+++ b/share/doc/psd/24.xdr/xdr.nts.ms
@@ -0,0 +1,1968 @@
+.\"
+.\" Must use -- eqn -- with this one
+.\"
+.\" @(#)xdr.nts.ms 2.2 88/08/05 4.0 RPCSRC
+.\" $FreeBSD$
+.\"
+.EQ
+delim $$
+.EN
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'External Data Representation: Sun Technical Notes''Page %'
+.EH 'Page %''External Data Representation: Sun Technical Notes'
+.if \n%=1 .bp
+.SH
+\&External Data Representation: Sun Technical Notes
+.IX XDR "Sun technical notes"
+.LP
+This chapter contains technical notes on Sun's implementation of the
+External Data Representation (XDR) standard, a set of library routines
+that allow a C programmer to describe arbitrary data structures in a
+machinex-independent fashion.
+For a formal specification of the XDR
+standard, see the
+.I "External Data Representation Standard: Protocol Specification".
+XDR is the backbone of Sun's Remote Procedure Call package, in the
+sense that data for remote procedure calls is transmitted using the
+standard. XDR library routines should be used to transmit data
+that is accessed (read or written) by more than one type of machine.\**
+.FS
+.IX XDR "system routines"
+For a compete specification of the system External Data Representation
+routines, see the
+.I xdr(3N)
+manual page.
+.FE
+.LP
+This chapter contains a short tutorial overview of the XDR library
+routines, a guide to accessing currently available XDR streams, and
+information on defining new streams and data types. XDR was designed
+to work across different languages, operating systems, and machine
+architectures. Most users (particularly RPC users) will only need
+the information in the
+.I "Number Filters",
+.I "Floating Point Filters",
+and
+.I "Enumeration Filters"
+sections.
+Programmers wishing to implement RPC and XDR on new machines
+will be interested in the rest of the chapter, as well as the
+.I "External Data Representaiton Standard: Protocol Specification",
+which will be their primary reference.
+.SH
+Note:
+.I
+.I rpcgen
+can be used to write XDR routines even in cases where no RPC calls are
+being made.
+.LP
+On Sun systems,
+C programs that want to use XDR routines
+must include the file
+.I <rpc/rpc.h> ,
+which contains all the necessary interfaces to the XDR system.
+Since the C library
+.I libc.a
+contains all the XDR routines,
+compile as normal.
+.DS
+example% \fBcc\0\fIprogram\fP.c\fI
+.DE
+.ne 3i
+.NH 0
+\&Justification
+.IX XDR justification
+.LP
+Consider the following two programs,
+.I writer :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+.sp .5
+main() /* \fIwriter.c\fP */
+{
+ long i;
+.sp .5
+ for (i = 0; i < 8; i++) {
+ if (fwrite((char *)&i, sizeof(i), 1, stdout) != 1) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ }
+ exit(0);
+}
+.DE
+and
+.I reader :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+.sp .5
+main() /* \fIreader.c\fP */
+{
+ long i, j;
+.sp .5
+ for (j = 0; j < 8; j++) {
+ if (fread((char *)&i, sizeof (i), 1, stdin) != 1) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ printf("%ld ", i);
+ }
+ printf("\en");
+ exit(0);
+}
+.DE
+The two programs appear to be portable, because (a) they pass
+.I lint
+checking, and (b) they exhibit the same behavior when executed
+on two different hardware architectures, a Sun and a VAX.
+.LP
+Piping the output of the
+.I writer
+program to the
+.I reader
+program gives identical results on a Sun or a VAX.
+.DS
+.ft CW
+sun% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+sun%
+
+
+vax% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+vax%
+.DE
+With the advent of local area networks and 4.2BSD came the concept
+of \*Qnetwork pipes\*U \(em a process produces data on one machine,
+and a second process consumes data on another machine.
+A network pipe can be constructed with
+.I writer
+and
+.I reader .
+Here are the results if the first produces data on a Sun,
+and the second consumes data on a VAX.
+.DS
+.ft CW
+sun% \fBwriter | rsh vax reader\fP
+0 16777216 33554432 50331648 67108864 83886080 100663296
+117440512
+sun%
+.DE
+Identical results can be obtained by executing
+.I writer
+on the VAX and
+.I reader
+on the Sun. These results occur because the byte ordering
+of long integers differs between the VAX and the Sun,
+even though word size is the same.
+Note that $16777216$ is $2 sup 24$ \(em
+when four bytes are reversed, the 1 winds up in the 24th bit.
+.LP
+Whenever data is shared by two or more machine types, there is
+a need for portable data. Programs can be made data-portable by
+replacing the
+.I read()
+and
+.I write()
+calls with calls to an XDR library routine
+.I xdr_long() ,
+a filter that knows the standard representation
+of a long integer in its external form.
+Here are the revised versions of
+.I writer :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIxdr is a sub-library of rpc\fP */
+.sp .5
+main() /* \fIwriter.c\fP */
+{
+ XDR xdrs;
+ long i;
+.sp .5
+ xdrstdio_create(&xdrs, stdout, XDR_ENCODE);
+ for (i = 0; i < 8; i++) {
+ if (!xdr_long(&xdrs, &i)) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ }
+ exit(0);
+}
+.DE
+and
+.I reader :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIxdr is a sub-library of rpc\fP */
+.sp .5
+main() /* \fIreader.c\fP */
+{
+ XDR xdrs;
+ long i, j;
+.sp .5
+ xdrstdio_create(&xdrs, stdin, XDR_DECODE);
+ for (j = 0; j < 8; j++) {
+ if (!xdr_long(&xdrs, &i)) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ printf("%ld ", i);
+ }
+ printf("\en");
+ exit(0);
+}
+.DE
+The new programs were executed on a Sun,
+on a VAX, and from a Sun to a VAX;
+the results are shown below.
+.DS
+.ft CW
+sun% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+sun%
+
+vax% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+vax%
+
+sun% \fBwriter | rsh vax reader\fP
+0 1 2 3 4 5 6 7
+sun%
+.DE
+.SH
+Note:
+.I
+.IX XDR "portable data"
+Integers are just the tip of the portable-data iceberg. Arbitrary
+data structures present portability problems, particularly with
+respect to alignment and pointers. Alignment on word boundaries
+may cause the size of a structure to vary from machine to machine.
+And pointers, which are very convenient to use, have no meaning
+outside the machine where they are defined.
+.LP
+.NH 1
+\&A Canonical Standard
+.IX XDR "canonical standard"
+.LP
+XDR's approach to standardizing data representations is
+.I canonical .
+That is, XDR defines a single byte order (Big Endian), a single
+floating-point representation (IEEE), and so on. Any program running on
+any machine can use XDR to create portable data by translating its
+local representation to the XDR standard representations; similarly, any
+program running on any machine can read portable data by translating the
+XDR standard representaions to its local equivalents. The single standard
+completely decouples programs that create or send portable data from those
+that use or receive portable data. The advent of a new machine or a new
+language has no effect upon the community of existing portable data creators
+and users. A new machine joins this community by being \*Qtaught\*U how to
+convert the standard representations and its local representations; the
+local representations of other machines are irrelevant. Conversely, to
+existing programs running on other machines, the local representations of
+the new machine are also irrelevant; such programs can immediately read
+portable data produced by the new machine because such data conforms to the
+canonical standards that they already understand.
+.LP
+There are strong precedents for XDR's canonical approach. For example,
+TCP/IP, UDP/IP, XNS, Ethernet, and, indeed, all protocols below layer five
+of the ISO model, are canonical protocols. The advantage of any canonical
+approach is simplicity; in the case of XDR, a single set of conversion
+routines is written once and is never touched again. The canonical approach
+has a disadvantage, but it is unimportant in real-world data transfer
+applications. Suppose two Little-Endian machines are transferring integers
+according to the XDR standard. The sending machine converts the integers
+from Little-Endian byte order to XDR (Big-Endian) byte order; the receiving
+machine performs the reverse conversion. Because both machines observe the
+same byte order, their conversions are unnecessary. The point, however, is
+not necessity, but cost as compared to the alternative.
+.LP
+The time spent converting to and from a canonical representation is
+insignificant, especially in networking applications. Most of the time
+required to prepare a data structure for transfer is not spent in conversion
+but in traversing the elements of the data structure. To transmit a tree,
+for example, each leaf must be visited and each element in a leaf record must
+be copied to a buffer and aligned there; storage for the leaf may have to be
+deallocated as well. Similarly, to receive a tree, storage must be
+allocated for each leaf, data must be moved from the buffer to the leaf and
+properly aligned, and pointers must be constructed to link the leaves
+together. Every machine pays the cost of traversing and copying data
+structures whether or not conversion is required. In networking
+applications, communications overhead\(emthe time required to move the data
+down through the sender's protocol layers, across the network and up through
+the receiver's protocol layers\(emdwarfs conversion overhead.
+.NH 1
+\&The XDR Library
+.IX "XDR" "library"
+.LP
+The XDR library not only solves data portability problems, it also
+allows you to write and read arbitrary C constructs in a consistent,
+specified, well-documented manner. Thus, it can make sense to use the
+library even when the data is not shared among machines on a network.
+.LP
+The XDR library has filter routines for
+strings (null-terminated arrays of bytes),
+structures, unions, and arrays, to name a few.
+Using more primitive routines,
+you can write your own specific XDR routines
+to describe arbitrary data structures,
+including elements of arrays, arms of unions,
+or objects pointed at from other structures.
+The structures themselves may contain arrays of arbitrary elements,
+or pointers to other structures.
+.LP
+Let's examine the two programs more closely.
+There is a family of XDR stream creation routines
+in which each member treats the stream of bits differently.
+In our example, data is manipulated using standard I/O routines,
+so we use
+.I xdrstdio_create ().
+.IX xdrstdio_create() "" "\fIxdrstdio_create()\fP"
+The parameters to XDR stream creation routines
+vary according to their function.
+In our example,
+.I xdrstdio_create()
+takes a pointer to an XDR structure that it initializes,
+a pointer to a
+.I FILE
+that the input or output is performed on, and the operation.
+The operation may be
+.I XDR_ENCODE
+for serializing in the
+.I writer
+program, or
+.I XDR_DECODE
+for deserializing in the
+.I reader
+program.
+.LP
+Note: RPC users never need to create XDR streams;
+the RPC system itself creates these streams,
+which are then passed to the users.
+.LP
+The
+.I xdr_long()
+.IX xdr_long() "" "\fIxdr_long()\fP"
+primitive is characteristic of most XDR library
+primitives and all client XDR routines.
+First, the routine returns
+.I FALSE
+(0) if it fails, and
+.I TRUE
+(1) if it succeeds.
+Second, for each data type,
+.I xxx ,
+there is an associated XDR routine of the form:
+.DS
+.ft CW
+xdr_xxx(xdrs, xp)
+ XDR *xdrs;
+ xxx *xp;
+{
+}
+.DE
+In our case,
+.I xxx
+is long, and the corresponding XDR routine is
+a primitive,
+.I xdr_long() .
+The client could also define an arbitrary structure
+.I xxx
+in which case the client would also supply the routine
+.I xdr_xxx (),
+describing each field by calling XDR routines
+of the appropriate type.
+In all cases the first parameter,
+.I xdrs
+can be treated as an opaque handle,
+and passed to the primitive routines.
+.LP
+XDR routines are direction independent;
+that is, the same routines are called to serialize or deserialize data.
+This feature is critical to software engineering of portable data.
+The idea is to call the same routine for either operation \(em
+this almost guarantees that serialized data can also be deserialized.
+One routine is used by both producer and consumer of networked data.
+This is implemented by always passing the address
+of an object rather than the object itself \(em
+only in the case of deserialization is the object modified.
+This feature is not shown in our trivial example,
+but its value becomes obvious when nontrivial data structures
+are passed among machines.
+If needed, the user can obtain the
+direction of the XDR operation.
+See the
+.I "XDR Operation Directions"
+section below for details.
+.LP
+Let's look at a slightly more complicated example.
+Assume that a person's gross assets and liabilities
+are to be exchanged among processes.
+Also assume that these values are important enough
+to warrant their own data type:
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers {
+ long g_assets;
+ long g_liabilities;
+};
+.DE
+The corresponding XDR routine describing this structure would be:
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t /* \fITRUE is success, FALSE is failure\fP */
+xdr_gnumbers(xdrs, gp)
+ XDR *xdrs;
+ struct gnumbers *gp;
+{
+ if (xdr_long(xdrs, &gp->g_assets) &&
+ xdr_long(xdrs, &gp->g_liabilities))
+ return(TRUE);
+ return(FALSE);
+}
+.DE
+Note that the parameter
+.I xdrs
+is never inspected or modified;
+it is only passed on to the subcomponent routines.
+It is imperative to inspect the return value of each XDR routine call,
+and to give up immediately and return
+.I FALSE
+if the subroutine fails.
+.LP
+This example also shows that the type
+.I bool_t
+is declared as an integer whose only values are
+.I TRUE
+(1) and
+.I FALSE
+(0). This document uses the following definitions:
+.ie t .DS
+.el .DS L
+.ft CW
+#define bool_t int
+#define TRUE 1
+#define FALSE 0
+.DE
+.LP
+Keeping these conventions in mind,
+.I xdr_gnumbers()
+can be rewritten as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_gnumbers(xdrs, gp)
+ XDR *xdrs;
+ struct gnumbers *gp;
+{
+ return(xdr_long(xdrs, &gp->g_assets) &&
+ xdr_long(xdrs, &gp->g_liabilities));
+}
+.DE
+This document uses both coding styles.
+.NH 1
+\&XDR Library Primitives
+.IX "library primitives for XDR"
+.IX XDR "library primitives"
+.LP
+This section gives a synopsis of each XDR primitive.
+It starts with basic data types and moves on to constructed data types.
+Finally, XDR utilities are discussed.
+The interface to these primitives
+and utilities is defined in the include file
+.I <rpc/xdr.h> ,
+automatically included by
+.I <rpc/rpc.h> .
+.NH 2
+\&Number Filters
+.IX "XDR library" "number filters"
+.LP
+The XDR library provides primitives to translate between numbers
+and their corresponding external representations.
+Primitives cover the set of numbers in:
+.DS
+.ft CW
+[signed, unsigned] * [short, int, long]
+.DE
+.ne 2i
+Specifically, the eight primitives are:
+.DS
+.ft CW
+bool_t xdr_char(xdrs, cp)
+ XDR *xdrs;
+ char *cp;
+.sp .5
+bool_t xdr_u_char(xdrs, ucp)
+ XDR *xdrs;
+ unsigned char *ucp;
+.sp .5
+bool_t xdr_int(xdrs, ip)
+ XDR *xdrs;
+ int *ip;
+.sp .5
+bool_t xdr_u_int(xdrs, up)
+ XDR *xdrs;
+ unsigned *up;
+.sp .5
+bool_t xdr_long(xdrs, lip)
+ XDR *xdrs;
+ long *lip;
+.sp .5
+bool_t xdr_u_long(xdrs, lup)
+ XDR *xdrs;
+ u_long *lup;
+.sp .5
+bool_t xdr_short(xdrs, sip)
+ XDR *xdrs;
+ short *sip;
+.sp .5
+bool_t xdr_u_short(xdrs, sup)
+ XDR *xdrs;
+ u_short *sup;
+.DE
+The first parameter,
+.I xdrs ,
+is an XDR stream handle.
+The second parameter is the address of the number
+that provides data to the stream or receives data from it.
+All routines return
+.I TRUE
+if they complete successfully, and
+.I FALSE
+otherwise.
+.NH 2
+\&Floating Point Filters
+.IX "XDR library" "floating point filters"
+.LP
+The XDR library also provides primitive routines
+for C's floating point types:
+.DS
+.ft CW
+bool_t xdr_float(xdrs, fp)
+ XDR *xdrs;
+ float *fp;
+.sp .5
+bool_t xdr_double(xdrs, dp)
+ XDR *xdrs;
+ double *dp;
+.DE
+The first parameter,
+.I xdrs
+is an XDR stream handle.
+The second parameter is the address
+of the floating point number that provides data to the stream
+or receives data from it.
+Both routines return
+.I TRUE
+if they complete successfully, and
+.I FALSE
+otherwise.
+.LP
+Note: Since the numbers are represented in IEEE floating point,
+routines may fail when decoding a valid IEEE representation
+into a machine-specific representation, or vice-versa.
+.NH 2
+\&Enumeration Filters
+.IX "XDR library" "enumeration filters"
+.LP
+The XDR library provides a primitive for generic enumerations.
+The primitive assumes that a C
+.I enum
+has the same representation inside the machine as a C integer.
+The boolean type is an important instance of the
+.I enum .
+The external representation of a boolean is always
+.I TRUE
+(1) or
+.I FALSE
+(0).
+.DS
+.ft CW
+#define bool_t int
+#define FALSE 0
+#define TRUE 1
+.sp .5
+#define enum_t int
+.sp .5
+bool_t xdr_enum(xdrs, ep)
+ XDR *xdrs;
+ enum_t *ep;
+.sp .5
+bool_t xdr_bool(xdrs, bp)
+ XDR *xdrs;
+ bool_t *bp;
+.DE
+The second parameters
+.I ep
+and
+.I bp
+are addresses of the associated type that provides data to, or
+receives data from, the stream
+.I xdrs .
+.NH 2
+\&No Data
+.IX "XDR library" "no data"
+.LP
+Occasionally, an XDR routine must be supplied to the RPC system,
+even when no data is passed or required.
+The library provides such a routine:
+.DS
+.ft CW
+bool_t xdr_void(); /* \fIalways returns TRUE\fP */
+.DE
+.NH 2
+\&Constructed Data Type Filters
+.IX "XDR library" "constructed data type filters"
+.LP
+Constructed or compound data type primitives
+require more parameters and perform more complicated functions
+then the primitives discussed above.
+This section includes primitives for
+strings, arrays, unions, and pointers to structures.
+.LP
+Constructed data type primitives may use memory management.
+In many cases, memory is allocated when deserializing data with
+.I XDR_DECODE
+Therefore, the XDR package must provide means to deallocate memory.
+This is done by an XDR operation,
+.I XDR_FREE
+To review, the three XDR directional operations are
+.I XDR_ENCODE ,
+.I XDR_DECODE
+and
+.I XDR_FREE .
+.NH 3
+\&Strings
+.IX "XDR library" "strings"
+.LP
+In C, a string is defined as a sequence of bytes
+terminated by a null byte,
+which is not considered when calculating string length.
+However, when a string is passed or manipulated,
+a pointer to it is employed.
+Therefore, the XDR library defines a string to be a
+.I "char *"
+and not a sequence of characters.
+The external representation of a string is drastically different
+from its internal representation.
+Externally, strings are represented as
+sequences of ASCII characters,
+while internally, they are represented with character pointers.
+Conversion between the two representations
+is accomplished with the routine
+.I xdr_string ():
+.IX xdr_string() "" \fIxdr_string()\fP
+.DS
+.ft CW
+bool_t xdr_string(xdrs, sp, maxlength)
+ XDR *xdrs;
+ char **sp;
+ u_int maxlength;
+.DE
+The first parameter
+.I xdrs
+is the XDR stream handle.
+The second parameter
+.I sp
+is a pointer to a string (type
+.I "char **" .
+The third parameter
+.I maxlength
+specifies the maximum number of bytes allowed during encoding or decoding.
+its value is usually specified by a protocol. For example, a protocol
+specification may say that a file name may be no longer than 255 characters.
+.LP
+The routine returns
+.I FALSE
+if the number of characters exceeds
+.I maxlength ,
+and
+.I TRUE
+if it doesn't.
+.SH
+Keep
+.I maxlength
+small. If it is too big you can blow the heap, since
+.I xdr_string()
+will call
+.I malloc()
+for space.
+.LP
+The behavior of
+.I xdr_string()
+.IX xdr_string() "" \fIxdr_string()\fP
+is similar to the behavior of other routines
+discussed in this section. The direction
+.I XDR_ENCODE
+is easiest to understand. The parameter
+.I sp
+points to a string of a certain length;
+if the string does not exceed
+.I maxlength ,
+the bytes are serialized.
+.LP
+The effect of deserializing a string is subtle.
+First the length of the incoming string is determined;
+it must not exceed
+.I maxlength .
+Next
+.I sp
+is dereferenced; if the the value is
+.I NULL ,
+then a string of the appropriate length is allocated and
+.I *sp
+is set to this string.
+If the original value of
+.I *sp
+is non-null, then the XDR package assumes
+that a target area has been allocated,
+which can hold strings no longer than
+.I maxlength .
+In either case, the string is decoded into the target area.
+The routine then appends a null character to the string.
+.LP
+In the
+.I XDR_FREE
+operation, the string is obtained by dereferencing
+.I sp .
+If the string is not
+.I NULL ,
+it is freed and
+.I *sp
+is set to
+.I NULL .
+In this operation,
+.I xdr_string()
+ignores the
+.I maxlength
+parameter.
+.NH 3
+\&Byte Arrays
+.IX "XDR library" "byte arrays"
+.LP
+Often variable-length arrays of bytes are preferable to strings.
+Byte arrays differ from strings in the following three ways:
+1) the length of the array (the byte count) is explicitly
+located in an unsigned integer,
+2) the byte sequence is not terminated by a null character, and
+3) the external representation of the bytes is the same as their
+internal representation.
+The primitive
+.I xdr_bytes()
+.IX xdr_bytes() "" \fIxdr_bytes()\fP
+converts between the internal and external
+representations of byte arrays:
+.DS
+.ft CW
+bool_t xdr_bytes(xdrs, bpp, lp, maxlength)
+ XDR *xdrs;
+ char **bpp;
+ u_int *lp;
+ u_int maxlength;
+.DE
+The usage of the first, second and fourth parameters
+are identical to the first, second and third parameters of
+.I xdr_string (),
+respectively.
+The length of the byte area is obtained by dereferencing
+.I lp
+when serializing;
+.I *lp
+is set to the byte length when deserializing.
+.NH 3
+\&Arrays
+.IX "XDR library" "arrays"
+.LP
+The XDR library package provides a primitive
+for handling arrays of arbitrary elements.
+The
+.I xdr_bytes()
+routine treats a subset of generic arrays,
+in which the size of array elements is known to be 1,
+and the external description of each element is built-in.
+The generic array primitive,
+.I xdr_array() ,
+.IX xdr_array() "" \fIxdr_array()\fP
+requires parameters identical to those of
+.I xdr_bytes()
+plus two more:
+the size of array elements,
+and an XDR routine to handle each of the elements.
+This routine is called to encode or decode
+each element of the array.
+.DS
+.ft CW
+bool_t
+xdr_array(xdrs, ap, lp, maxlength, elementsiz, xdr_element)
+ XDR *xdrs;
+ char **ap;
+ u_int *lp;
+ u_int maxlength;
+ u_int elementsiz;
+ bool_t (*xdr_element)();
+.DE
+The parameter
+.I ap
+is the address of the pointer to the array.
+If
+.I *ap
+is
+.I NULL
+when the array is being deserialized,
+XDR allocates an array of the appropriate size and sets
+.I *ap
+to that array.
+The element count of the array is obtained from
+.I *lp
+when the array is serialized;
+.I *lp
+is set to the array length when the array is deserialized.
+The parameter
+.I maxlength
+is the maximum number of elements that the array is allowed to have;
+.I elementsiz
+is the byte size of each element of the array
+(the C function
+.I sizeof()
+can be used to obtain this value).
+The
+.I xdr_element()
+.IX xdr_element() "" \fIxdr_element()\fP
+routine is called to serialize, deserialize, or free
+each element of the array.
+.br
+.LP
+Before defining more constructed data types, it is appropriate to
+present three examples.
+.LP
+.I "Example A:"
+.br
+A user on a networked machine can be identified by
+(a) the machine name, such as
+.I krypton :
+see the
+.I gethostname
+man page; (b) the user's UID: see the
+.I geteuid
+man page; and (c) the group numbers to which the user belongs:
+see the
+.I getgroups
+man page. A structure with this information and its associated
+XDR routine could be coded like this:
+.ie t .DS
+.el .DS L
+.ft CW
+struct netuser {
+ char *nu_machinename;
+ int nu_uid;
+ u_int nu_glen;
+ int *nu_gids;
+};
+#define NLEN 255 /* \fImachine names < 256 chars\fP */
+#define NGRPS 20 /* \fIuser can't be in > 20 groups\fP */
+.sp .5
+bool_t
+xdr_netuser(xdrs, nup)
+ XDR *xdrs;
+ struct netuser *nup;
+{
+ return(xdr_string(xdrs, &nup->nu_machinename, NLEN) &&
+ xdr_int(xdrs, &nup->nu_uid) &&
+ xdr_array(xdrs, &nup->nu_gids, &nup->nu_glen,
+ NGRPS, sizeof (int), xdr_int));
+}
+.DE
+.LP
+.I "Example B:"
+.br
+A party of network users could be implemented
+as an array of
+.I netuser
+structure.
+The declaration and its associated XDR routines
+are as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+struct party {
+ u_int p_len;
+ struct netuser *p_nusers;
+};
+#define PLEN 500 /* \fImax number of users in a party\fP */
+.sp .5
+bool_t
+xdr_party(xdrs, pp)
+ XDR *xdrs;
+ struct party *pp;
+{
+ return(xdr_array(xdrs, &pp->p_nusers, &pp->p_len, PLEN,
+ sizeof (struct netuser), xdr_netuser));
+}
+.DE
+.LP
+.I "Example C:"
+.br
+The well-known parameters to
+.I main ,
+.I argc
+and
+.I argv
+can be combined into a structure.
+An array of these structures can make up a history of commands.
+The declarations and XDR routines might look like:
+.ie t .DS
+.el .DS L
+.ft CW
+struct cmd {
+ u_int c_argc;
+ char **c_argv;
+};
+#define ALEN 1000 /* \fIargs cannot be > 1000 chars\fP */
+#define NARGC 100 /* \fIcommands cannot have > 100 args\fP */
+
+struct history {
+ u_int h_len;
+ struct cmd *h_cmds;
+};
+#define NCMDS 75 /* \fIhistory is no more than 75 commands\fP */
+
+bool_t
+xdr_wrap_string(xdrs, sp)
+ XDR *xdrs;
+ char **sp;
+{
+ return(xdr_string(xdrs, sp, ALEN));
+}
+.DE
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_cmd(xdrs, cp)
+ XDR *xdrs;
+ struct cmd *cp;
+{
+ return(xdr_array(xdrs, &cp->c_argv, &cp->c_argc, NARGC,
+ sizeof (char *), xdr_wrap_string));
+}
+.DE
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_history(xdrs, hp)
+ XDR *xdrs;
+ struct history *hp;
+{
+ return(xdr_array(xdrs, &hp->h_cmds, &hp->h_len, NCMDS,
+ sizeof (struct cmd), xdr_cmd));
+}
+.DE
+The most confusing part of this example is that the routine
+.I xdr_wrap_string()
+is needed to package the
+.I xdr_string()
+routine, because the implementation of
+.I xdr_array()
+only passes two parameters to the array element description routine;
+.I xdr_wrap_string()
+supplies the third parameter to
+.I xdr_string ().
+.LP
+By now the recursive nature of the XDR library should be obvious.
+Let's continue with more constructed data types.
+.NH 3
+\&Opaque Data
+.IX "XDR library" "opaque data"
+.LP
+In some protocols, handles are passed from a server to client.
+The client passes the handle back to the server at some later time.
+Handles are never inspected by clients;
+they are obtained and submitted.
+That is to say, handles are opaque.
+The
+.I xdr_opaque()
+.IX xdr_opaque() "" \fIxdr_opaque()\fP
+primitive is used for describing fixed sized, opaque bytes.
+.DS
+.ft CW
+bool_t xdr_opaque(xdrs, p, len)
+ XDR *xdrs;
+ char *p;
+ u_int len;
+.DE
+The parameter
+.I p
+is the location of the bytes;
+.I len
+is the number of bytes in the opaque object.
+By definition, the actual data
+contained in the opaque object are not machine portable.
+.NH 3
+\&Fixed Sized Arrays
+.IX "XDR library" "fixed sized arrays"
+.LP
+The XDR library provides a primitive,
+.I xdr_vector (),
+for fixed-length arrays.
+.ie t .DS
+.el .DS L
+.ft CW
+#define NLEN 255 /* \fImachine names must be < 256 chars\fP */
+#define NGRPS 20 /* \fIuser belongs to exactly 20 groups\fP */
+.sp .5
+struct netuser {
+ char *nu_machinename;
+ int nu_uid;
+ int nu_gids[NGRPS];
+};
+.sp .5
+bool_t
+xdr_netuser(xdrs, nup)
+ XDR *xdrs;
+ struct netuser *nup;
+{
+ int i;
+.sp .5
+ if (!xdr_string(xdrs, &nup->nu_machinename, NLEN))
+ return(FALSE);
+ if (!xdr_int(xdrs, &nup->nu_uid))
+ return(FALSE);
+ if (!xdr_vector(xdrs, nup->nu_gids, NGRPS, sizeof(int),
+ xdr_int)) {
+ return(FALSE);
+ }
+ return(TRUE);
+}
+.DE
+.NH 3
+\&Discriminated Unions
+.IX "XDR library" "discriminated unions"
+.LP
+The XDR library supports discriminated unions.
+A discriminated union is a C union and an
+.I enum_t
+value that selects an \*Qarm\*U of the union.
+.DS
+.ft CW
+struct xdr_discrim {
+ enum_t value;
+ bool_t (*proc)();
+};
+.sp .5
+bool_t xdr_union(xdrs, dscmp, unp, arms, defaultarm)
+ XDR *xdrs;
+ enum_t *dscmp;
+ char *unp;
+ struct xdr_discrim *arms;
+ bool_t (*defaultarm)(); /* \fImay equal NULL\fP */
+.DE
+First the routine translates the discriminant of the union located at
+.I *dscmp .
+The discriminant is always an
+.I enum_t .
+Next the union located at
+.I *unp
+is translated.
+The parameter
+.I arms
+is a pointer to an array of
+.I xdr_discrim
+structures.
+Each structure contains an ordered pair of
+.I [value,proc] .
+If the union's discriminant is equal to the associated
+.I value ,
+then the
+.I proc
+is called to translate the union.
+The end of the
+.I xdr_discrim
+structure array is denoted by a routine of value
+.I NULL
+(0). If the discriminant is not found in the
+.I arms
+array, then the
+.I defaultarm
+procedure is called if it is non-null;
+otherwise the routine returns
+.I FALSE .
+.LP
+.I "Example D:"
+Suppose the type of a union may be integer,
+character pointer (a string), or a
+.I gnumbers
+structure.
+Also, assume the union and its current type
+are declared in a structure.
+The declaration is:
+.ie t .DS
+.el .DS L
+.ft CW
+enum utype { INTEGER=1, STRING=2, GNUMBERS=3 };
+.sp .5
+struct u_tag {
+ enum utype utype; /* \fIthe union's discriminant\fP */
+ union {
+ int ival;
+ char *pval;
+ struct gnumbers gn;
+ } uval;
+};
+.DE
+The following constructs and XDR procedure (de)serialize
+the discriminated union:
+.ie t .DS
+.el .DS L
+.ft CW
+struct xdr_discrim u_tag_arms[4] = {
+ { INTEGER, xdr_int },
+ { GNUMBERS, xdr_gnumbers }
+ { STRING, xdr_wrap_string },
+ { __dontcare__, NULL }
+ /* \fIalways terminate arms with a NULL xdr_proc\fP */
+}
+.sp .5
+bool_t
+xdr_u_tag(xdrs, utp)
+ XDR *xdrs;
+ struct u_tag *utp;
+{
+ return(xdr_union(xdrs, &utp->utype, &utp->uval,
+ u_tag_arms, NULL));
+}
+.DE
+The routine
+.I xdr_gnumbers()
+was presented above in
+.I "The XDR Library"
+section.
+.I xdr_wrap_string()
+was presented in example C.
+The default
+.I arm
+parameter to
+.I xdr_union()
+(the last parameter) is
+.I NULL
+in this example. Therefore the value of the union's discriminant
+may legally take on only values listed in the
+.I u_tag_arms
+array. This example also demonstrates that
+the elements of the arm's array do not need to be sorted.
+.LP
+It is worth pointing out that the values of the discriminant
+may be sparse, though in this example they are not.
+It is always good
+practice to assign explicitly integer values to each element of the
+discriminant's type.
+This practice both documents the external
+representation of the discriminant and guarantees that different
+C compilers emit identical discriminant values.
+.LP
+Exercise: Implement
+.I xdr_union()
+using the other primitives in this section.
+.NH 3
+\&Pointers
+.IX "XDR library" "pointers"
+.LP
+In C it is often convenient to put pointers
+to another structure within a structure.
+The
+.I xdr_reference()
+.IX xdr_reference() "" \fIxdr_reference()\fP
+primitive makes it easy to serialize, deserialize, and free
+these referenced structures.
+.DS
+.ft CW
+bool_t xdr_reference(xdrs, pp, size, proc)
+ XDR *xdrs;
+ char **pp;
+ u_int ssize;
+ bool_t (*proc)();
+.DE
+.LP
+Parameter
+.I pp
+is the address of
+the pointer to the structure;
+parameter
+.I ssize
+is the size in bytes of the structure (use the C function
+.I sizeof()
+to obtain this value); and
+.I proc
+is the XDR routine that describes the structure.
+When decoding data, storage is allocated if
+.I *pp
+is
+.I NULL .
+.LP
+There is no need for a primitive
+.I xdr_struct()
+to describe structures within structures,
+because pointers are always sufficient.
+.LP
+Exercise: Implement
+.I xdr_reference()
+using
+.I xdr_array ().
+Warning:
+.I xdr_reference()
+and
+.I xdr_array()
+are NOT interchangeable external representations of data.
+.LP
+.I "Example E:"
+Suppose there is a structure containing a person's name
+and a pointer to a
+.I gnumbers
+structure containing the person's gross assets and liabilities.
+The construct is:
+.DS
+.ft CW
+struct pgn {
+ char *name;
+ struct gnumbers *gnp;
+};
+.DE
+The corresponding XDR routine for this structure is:
+.DS
+.ft CW
+bool_t
+xdr_pgn(xdrs, pp)
+ XDR *xdrs;
+ struct pgn *pp;
+{
+ if (xdr_string(xdrs, &pp->name, NLEN) &&
+ xdr_reference(xdrs, &pp->gnp,
+ sizeof(struct gnumbers), xdr_gnumbers))
+ return(TRUE);
+ return(FALSE);
+}
+.DE
+.IX "pointer semantics and XDR"
+.I "Pointer Semantics and XDR"
+.LP
+In many applications, C programmers attach double meaning to
+the values of a pointer. Typically the value
+.I NULL
+(or zero) means data is not needed,
+yet some application-specific interpretation applies.
+In essence, the C programmer is encoding
+a discriminated union efficiently
+by overloading the interpretation of the value of a pointer.
+For instance, in example E a
+.I NULL
+pointer value for
+.I gnp
+could indicate that
+the person's assets and liabilities are unknown.
+That is, the pointer value encodes two things:
+whether or not the data is known;
+and if it is known, where it is located in memory.
+Linked lists are an extreme example of the use
+of application-specific pointer interpretation.
+.LP
+The primitive
+.I xdr_reference()
+.IX xdr_reference() "" \fIxdr_reference()\fP
+cannot and does not attach any special
+meaning to a null-value pointer during serialization.
+That is, passing an address of a pointer whose value is
+.I NULL
+to
+.I xdr_reference()
+when serialing data will most likely cause a memory fault and, on the UNIX
+system, a core dump.
+.LP
+.I xdr_pointer()
+correctly handles
+.I NULL
+pointers. For more information about its use, see
+the
+.I "Linked Lists"
+topics below.
+.LP
+.I Exercise:
+After reading the section on
+.I "Linked Lists" ,
+return here and extend example E so that
+it can correctly deal with
+.I NULL
+pointer values.
+.LP
+.I Exercise:
+Using the
+.I xdr_union (),
+.I xdr_reference()
+and
+.I xdr_void()
+primitives, implement a generic pointer handling primitive
+that implicitly deals with
+.I NULL
+pointers. That is, implement
+.I xdr_pointer ().
+.NH 2
+\&Non-filter Primitives
+.IX "XDR" "non-filter primitives"
+.LP
+XDR streams can be manipulated with
+the primitives discussed in this section.
+.DS
+.ft CW
+u_int xdr_getpos(xdrs)
+ XDR *xdrs;
+.sp .5
+bool_t xdr_setpos(xdrs, pos)
+ XDR *xdrs;
+ u_int pos;
+.sp .5
+xdr_destroy(xdrs)
+ XDR *xdrs;
+.DE
+The routine
+.I xdr_getpos()
+.IX xdr_getpos() "" \fIxdr_getpos()\fP
+returns an unsigned integer
+that describes the current position in the data stream.
+Warning: In some XDR streams, the returned value of
+.I xdr_getpos()
+is meaningless;
+the routine returns a \-1 in this case
+(though \-1 should be a legitimate value).
+.LP
+The routine
+.I xdr_setpos()
+.IX xdr_setpos() "" \fIxdr_setpos()\fP
+sets a stream position to
+.I pos .
+Warning: In some XDR streams, setting a position is impossible;
+in such cases,
+.I xdr_setpos()
+will return
+.I FALSE .
+This routine will also fail if the requested position is out-of-bounds.
+The definition of bounds varies from stream to stream.
+.LP
+The
+.I xdr_destroy()
+.IX xdr_destroy() "" \fIxdr_destroy()\fP
+primitive destroys the XDR stream.
+Usage of the stream
+after calling this routine is undefined.
+.NH 2
+\&XDR Operation Directions
+.IX XDR "operation directions"
+.IX "direction of XDR operations"
+.LP
+At times you may wish to optimize XDR routines by taking
+advantage of the direction of the operation \(em
+.I XDR_ENCODE
+.I XDR_DECODE
+or
+.I XDR_FREE
+The value
+.I xdrs->x_op
+always contains the direction of the XDR operation.
+Programmers are not encouraged to take advantage of this information.
+Therefore, no example is presented here. However, an example in the
+.I "Linked Lists"
+topic below, demonstrates the usefulness of the
+.I xdrs->x_op
+field.
+.NH 2
+\&XDR Stream Access
+.IX "XDR" "stream access"
+.LP
+An XDR stream is obtained by calling the appropriate creation routine.
+These creation routines take arguments that are tailored to the
+specific properties of the stream.
+.LP
+Streams currently exist for (de)serialization of data to or from
+standard I/O
+.I FILE
+streams, TCP/IP connections and UNIX files, and memory.
+.NH 3
+\&Standard I/O Streams
+.IX "XDR" "standard I/O streams"
+.LP
+XDR streams can be interfaced to standard I/O using the
+.I xdrstdio_create()
+.IX xdrstdio_create() "" \fIxdrstdio_create()\fP
+routine as follows:
+.DS
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIxdr streams part of rpc\fP */
+.sp .5
+void
+xdrstdio_create(xdrs, fp, x_op)
+ XDR *xdrs;
+ FILE *fp;
+ enum xdr_op x_op;
+.DE
+The routine
+.I xdrstdio_create()
+initializes an XDR stream pointed to by
+.I xdrs .
+The XDR stream interfaces to the standard I/O library.
+Parameter
+.I fp
+is an open file, and
+.I x_op
+is an XDR direction.
+.NH 3
+\&Memory Streams
+.IX "XDR" "memory streams"
+.LP
+Memory streams allow the streaming of data into or out of
+a specified area of memory:
+.DS
+.ft CW
+#include <rpc/rpc.h>
+.sp .5
+void
+xdrmem_create(xdrs, addr, len, x_op)
+ XDR *xdrs;
+ char *addr;
+ u_int len;
+ enum xdr_op x_op;
+.DE
+The routine
+.I xdrmem_create()
+.IX xdrmem_create() "" \fIxdrmem_create()\fP
+initializes an XDR stream in local memory.
+The memory is pointed to by parameter
+.I addr ;
+parameter
+.I len
+is the length in bytes of the memory.
+The parameters
+.I xdrs
+and
+.I x_op
+are identical to the corresponding parameters of
+.I xdrstdio_create ().
+Currently, the UDP/IP implementation of RPC uses
+.I xdrmem_create ().
+Complete call or result messages are built in memory before calling the
+.I sendto()
+system routine.
+.NH 3
+\&Record (TCP/IP) Streams
+.IX "XDR" "record (TCP/IP) streams"
+.LP
+A record stream is an XDR stream built on top of
+a record marking standard that is built on top of the
+UNIX file or 4.2 BSD connection interface.
+.DS
+.ft CW
+#include <rpc/rpc.h> /* \fIxdr streams part of rpc\fP */
+.sp .5
+xdrrec_create(xdrs,
+ sendsize, recvsize, iohandle, readproc, writeproc)
+ XDR *xdrs;
+ u_int sendsize, recvsize;
+ char *iohandle;
+ int (*readproc)(), (*writeproc)();
+.DE
+The routine
+.I xdrrec_create()
+provides an XDR stream interface that allows for a bidirectional,
+arbitrarily long sequence of records.
+The contents of the records are meant to be data in XDR form.
+The stream's primary use is for interfacing RPC to TCP connections.
+However, it can be used to stream data into or out of normal
+UNIX files.
+.LP
+The parameter
+.I xdrs
+is similar to the corresponding parameter described above.
+The stream does its own data buffering similar to that of standard I/O.
+The parameters
+.I sendsize
+and
+.I recvsize
+determine the size in bytes of the output and input buffers, respectively;
+if their values are zero (0), then predetermined defaults are used.
+When a buffer needs to be filled or flushed, the routine
+.I readproc()
+or
+.I writeproc()
+is called, respectively.
+The usage and behavior of these
+routines are similar to the UNIX system calls
+.I read()
+and
+.I write ().
+However,
+the first parameter to each of these routines is the opaque parameter
+.I iohandle .
+The other two parameters
+.I buf ""
+and
+.I nbytes )
+and the results
+(byte count) are identical to the system routines.
+If
+.I xxx
+is
+.I readproc()
+or
+.I writeproc (),
+then it has the following form:
+.DS
+.ft CW
+.ft I
+/*
+ * returns the actual number of bytes transferred.
+ * -1 is an error
+ */
+.ft CW
+int
+xxx(iohandle, buf, len)
+ char *iohandle;
+ char *buf;
+ int nbytes;
+.DE
+The XDR stream provides means for delimiting records in the byte stream.
+The implementation details of delimiting records in a stream are
+discussed in the
+.I "Advanced Topics"
+topic below.
+The primitives that are specific to record streams are as follows:
+.DS
+.ft CW
+bool_t
+xdrrec_endofrecord(xdrs, flushnow)
+ XDR *xdrs;
+ bool_t flushnow;
+.sp .5
+bool_t
+xdrrec_skiprecord(xdrs)
+ XDR *xdrs;
+.sp .5
+bool_t
+xdrrec_eof(xdrs)
+ XDR *xdrs;
+.DE
+The routine
+.I xdrrec_endofrecord()
+.IX xdrrec_endofrecord() "" \fIxdrrec_endofrecord()\fP
+causes the current outgoing data to be marked as a record.
+If the parameter
+.I flushnow
+is
+.I TRUE ,
+then the stream's
+.I writeproc
+will be called; otherwise,
+.I writeproc
+will be called when the output buffer has been filled.
+.LP
+The routine
+.I xdrrec_skiprecord()
+.IX xdrrec_skiprecord() "" \fIxdrrec_skiprecord()\fP
+causes an input stream's position to be moved past
+the current record boundary and onto the
+beginning of the next record in the stream.
+.LP
+If there is no more data in the stream's input buffer,
+then the routine
+.I xdrrec_eof()
+.IX xdrrec_eof() "" \fIxdrrec_eof()\fP
+returns
+.I TRUE .
+That is not to say that there is no more data
+in the underlying file descriptor.
+.NH 2
+\&XDR Stream Implementation
+.IX "XDR" "stream implementation"
+.IX "stream implementation in XDR"
+.LP
+This section provides the abstract data types needed
+to implement new instances of XDR streams.
+.NH 3
+\&The XDR Object
+.IX "XDR" "object"
+.LP
+The following structure defines the interface to an XDR stream:
+.ie t .DS
+.el .DS L
+.ft CW
+enum xdr_op { XDR_ENCODE=0, XDR_DECODE=1, XDR_FREE=2 };
+.sp .5
+typedef struct {
+ enum xdr_op x_op; /* \fIoperation; fast added param\fP */
+ struct xdr_ops {
+ bool_t (*x_getlong)(); /* \fIget long from stream\fP */
+ bool_t (*x_putlong)(); /* \fIput long to stream\fP */
+ bool_t (*x_getbytes)(); /* \fIget bytes from stream\fP */
+ bool_t (*x_putbytes)(); /* \fIput bytes to stream\fP */
+ u_int (*x_getpostn)(); /* \fIreturn stream offset\fP */
+ bool_t (*x_setpostn)(); /* \fIreposition offset\fP */
+ caddr_t (*x_inline)(); /* \fIptr to buffered data\fP */
+ VOID (*x_destroy)(); /* \fIfree private area\fP */
+ } *x_ops;
+ caddr_t x_public; /* \fIusers' data\fP */
+ caddr_t x_private; /* \fIpointer to private data\fP */
+ caddr_t x_base; /* \fIprivate for position info\fP */
+ int x_handy; /* \fIextra private word\fP */
+} XDR;
+.DE
+The
+.I x_op
+field is the current operation being performed on the stream.
+This field is important to the XDR primitives,
+but should not affect a stream's implementation.
+That is, a stream's implementation should not depend
+on this value.
+The fields
+.I x_private ,
+.I x_base ,
+and
+.I x_handy
+are private to the particular
+stream's implementation.
+The field
+.I x_public
+is for the XDR client and should never be used by
+the XDR stream implementations or the XDR primitives.
+.I x_getpostn() ,
+.I x_setpostn()
+and
+.I x_destroy()
+are macros for accessing operations. The operation
+.I x_inline()
+takes two parameters:
+an XDR *, and an unsigned integer, which is a byte count.
+The routine returns a pointer to a piece of
+the stream's internal buffer.
+The caller can then use the buffer segment for any purpose.
+From the stream's point of view, the bytes in the
+buffer segment have been consumed or put.
+The routine may return
+.I NULL
+if it cannot return a buffer segment of the requested size.
+(The
+.I x_inline()
+routine is for cycle squeezers.
+Use of the resulting buffer is not data-portable.
+Users are encouraged not to use this feature.)
+.LP
+The operations
+.I x_getbytes()
+and
+.I x_putbytes()
+blindly get and put sequences of bytes
+from or to the underlying stream;
+they return
+.I TRUE
+if they are successful, and
+.I FALSE
+otherwise. The routines have identical parameters (replace
+.I xxx ):
+.DS
+.ft CW
+bool_t
+xxxbytes(xdrs, buf, bytecount)
+ XDR *xdrs;
+ char *buf;
+ u_int bytecount;
+.DE
+The operations
+.I x_getlong()
+and
+.I x_putlong()
+receive and put
+long numbers from and to the data stream.
+It is the responsibility of these routines
+to translate the numbers between the machine representation
+and the (standard) external representation.
+The UNIX primitives
+.I htonl()
+and
+.I ntohl()
+can be helpful in accomplishing this.
+The higher-level XDR implementation assumes that
+signed and unsigned long integers contain the same number of bits,
+and that nonnegative integers
+have the same bit representations as unsigned integers.
+The routines return
+.I TRUE
+if they succeed, and
+.I FALSE
+otherwise. They have identical parameters:
+.DS
+.ft CW
+bool_t
+xxxlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+.DE
+Implementors of new XDR streams must make an XDR structure
+(with new operation routines) available to clients,
+using some kind of create routine.
+.NH 1
+\&Advanced Topics
+.IX XDR "advanced topics"
+.LP
+This section describes techniques for passing data structures that
+are not covered in the preceding sections. Such structures include
+linked lists (of arbitrary lengths). Unlike the simpler examples
+covered in the earlier sections, the following examples are written
+using both the XDR C library routines and the XDR data description
+language.
+The
+.I "External Data Representation Standard: Protocol Specification"
+describes this
+language in complete detail.
+.NH 2
+\&Linked Lists
+.IX XDR "linked lists"
+.LP
+The last example in the
+.I Pointers
+topic earlier in this chapter
+presented a C data structure and its associated XDR
+routines for an individual's gross assets and liabilities.
+The example is duplicated below:
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers {
+ long g_assets;
+ long g_liabilities;
+};
+.sp .5
+bool_t
+xdr_gnumbers(xdrs, gp)
+ XDR *xdrs;
+ struct gnumbers *gp;
+{
+ if (xdr_long(xdrs, &(gp->g_assets)))
+ return(xdr_long(xdrs, &(gp->g_liabilities)));
+ return(FALSE);
+}
+.DE
+.LP
+Now assume that we wish to implement a linked list of such information.
+A data structure could be constructed as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers_node {
+ struct gnumbers gn_numbers;
+ struct gnumbers_node *gn_next;
+};
+.sp .5
+typedef struct gnumbers_node *gnumbers_list;
+.DE
+.LP
+The head of the linked list can be thought of as the data object;
+that is, the head is not merely a convenient shorthand for a
+structure. Similarly the
+.I gn_next
+field is used to indicate whether or not the object has terminated.
+Unfortunately, if the object continues, the
+.I gn_next
+field is also the address of where it continues. The link addresses
+carry no useful information when the object is serialized.
+.LP
+The XDR data description of this linked list is described by the
+recursive declaration of
+.I gnumbers_list :
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers {
+ int g_assets;
+ int g_liabilities;
+};
+.sp .5
+struct gnumbers_node {
+ gnumbers gn_numbers;
+ gnumbers_node *gn_next;
+};
+.DE
+.LP
+In this description, the boolean indicates whether there is more data
+following it. If the boolean is
+.I FALSE ,
+then it is the last data field of the structure. If it is
+.I TRUE ,
+then it is followed by a gnumbers structure and (recursively) by a
+.I gnumbers_list .
+Note that the C declaration has no boolean explicitly declared in it
+(though the
+.I gn_next
+field implicitly carries the information), while the XDR data
+description has no pointer explicitly declared in it.
+.LP
+Hints for writing the XDR routines for a
+.I gnumbers_list
+follow easily from the XDR description above. Note how the primitive
+.I xdr_pointer()
+is used to implement the XDR union above.
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_gnumbers_node(xdrs, gn)
+ XDR *xdrs;
+ gnumbers_node *gn;
+{
+ return(xdr_gnumbers(xdrs, &gn->gn_numbers) &&
+ xdr_gnumbers_list(xdrs, &gp->gn_next));
+}
+.sp .5
+bool_t
+xdr_gnumbers_list(xdrs, gnp)
+ XDR *xdrs;
+ gnumbers_list *gnp;
+{
+ return(xdr_pointer(xdrs, gnp,
+ sizeof(struct gnumbers_node),
+ xdr_gnumbers_node));
+}
+.DE
+.LP
+The unfortunate side effect of XDR'ing a list with these routines
+is that the C stack grows linearly with respect to the number of
+node in the list. This is due to the recursion. The following
+routine collapses the above two mutually recursive into a single,
+non-recursive one.
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_gnumbers_list(xdrs, gnp)
+ XDR *xdrs;
+ gnumbers_list *gnp;
+{
+ bool_t more_data;
+ gnumbers_list *nextp;
+.sp .5
+ for (;;) {
+ more_data = (*gnp != NULL);
+ if (!xdr_bool(xdrs, &more_data)) {
+ return(FALSE);
+ }
+ if (! more_data) {
+ break;
+ }
+ if (xdrs->x_op == XDR_FREE) {
+ nextp = &(*gnp)->gn_next;
+ }
+ if (!xdr_reference(xdrs, gnp,
+ sizeof(struct gnumbers_node), xdr_gnumbers)) {
+
+ return(FALSE);
+ }
+ gnp = (xdrs->x_op == XDR_FREE) ?
+ nextp : &(*gnp)->gn_next;
+ }
+ *gnp = NULL;
+ return(TRUE);
+}
+.DE
+.LP
+The first task is to find out whether there is more data or not,
+so that this boolean information can be serialized. Notice that
+this statement is unnecessary in the
+.I XDR_DECODE
+case, since the value of more_data is not known until we
+deserialize it in the next statement.
+.LP
+The next statement XDR's the more_data field of the XDR union.
+Then if there is truly no more data, we set this last pointer to
+.I NULL
+to indicate the end of the list, and return
+.I TRUE
+because we are done. Note that setting the pointer to
+.I NULL
+is only important in the
+.I XDR_DECODE
+case, since it is already
+.I NULL
+in the
+.I XDR_ENCODE
+and
+XDR_FREE
+cases.
+.LP
+Next, if the direction is
+.I XDR_FREE ,
+the value of
+.I nextp
+is set to indicate the location of the next pointer in the list.
+We do this now because we need to dereference gnp to find the
+location of the next item in the list, and after the next
+statement the storage pointed to by
+.I gnp
+will be freed up and no be longer valid. We can't do this for all
+directions though, because in the
+.I XDR_DECODE
+direction the value of
+.I gnp
+won't be set until the next statement.
+.LP
+Next, we XDR the data in the node using the primitive
+.I xdr_reference ().
+.I xdr_reference()
+is like
+.I xdr_pointer()
+which we used before, but it does not
+send over the boolean indicating whether there is more data.
+We use it instead of
+.I xdr_pointer()
+because we have already XDR'd this information ourselves. Notice
+that the xdr routine passed is not the same type as an element
+in the list. The routine passed is
+.I xdr_gnumbers (),
+for XDR'ing gnumbers, but each element in the list is actually of
+type
+.I gnumbers_node .
+We don't pass
+.I xdr_gnumbers_node()
+because it is recursive, and instead use
+.I xdr_gnumbers()
+which XDR's all of the non-recursive part. Note that this trick
+will work only if the
+.I gn_numbers
+field is the first item in each element, so that their addresses
+are identical when passed to
+.I xdr_reference ().
+.LP
+Finally, we update
+.I gnp
+to point to the next item in the list. If the direction is
+.I XDR_FREE ,
+we set it to the previously saved value, otherwise we can
+dereference
+.I gnp
+to get the proper value. Though harder to understand than the
+recursive version, this non-recursive routine is far less likely
+to blow the C stack. It will also run more efficiently since
+a lot of procedure call overhead has been removed. Most lists
+are small though (in the hundreds of items or less) and the
+recursive version should be sufficient for them.
+.EQ
+delim off
+.EN
diff --git a/share/doc/psd/25.xdrrfc/Makefile b/share/doc/psd/25.xdrrfc/Makefile
index 105135e..7045d45 100644
--- a/share/doc/psd/25.xdrrfc/Makefile
+++ b/share/doc/psd/25.xdrrfc/Makefile
@@ -4,6 +4,5 @@ VOLUME= psd/25.xdrrfc
SRCS= stubs xdr.rfc.ms
MACROS= -ms
USE_TBL=
-SRCDIR= ${.CURDIR}/../../../../lib/libc/rpc/PSD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/psd/25.xdrrfc/stubs b/share/doc/psd/25.xdrrfc/stubs
new file mode 100644
index 0000000..78b0a2c
--- /dev/null
+++ b/share/doc/psd/25.xdrrfc/stubs
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+.\"
+.if t .ftr L CR
diff --git a/share/doc/psd/25.xdrrfc/xdr.rfc.ms b/share/doc/psd/25.xdrrfc/xdr.rfc.ms
new file mode 100644
index 0000000..480a339
--- /dev/null
+++ b/share/doc/psd/25.xdrrfc/xdr.rfc.ms
@@ -0,0 +1,1060 @@
+.\"
+.\" Must use -- tbl -- with this one
+.\"
+.\" @(#)xdr.rfc.ms 2.2 88/08/05 4.0 RPCSRC
+.\" $FreeBSD$
+.\"
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'External Data Representation Standard''Page %'
+.EH 'Page %''External Data Representation Standard'
+.if \n%=1 .bp
+.SH
+\&External Data Representation Standard: Protocol Specification
+.IX "External Data Representation"
+.IX XDR RFC
+.IX XDR "protocol specification"
+.LP
+.NH 0
+\&Status of this Standard
+.nr OF 1
+.IX XDR "RFC status"
+.LP
+Note: This chapter specifies a protocol that Sun Microsystems, Inc., and
+others are using. It has been designated RFC1014 by the ARPA Network
+Information Center.
+.NH 1
+Introduction
+\&
+.LP
+XDR is a standard for the description and encoding of data. It is
+useful for transferring data between different computer
+architectures, and has been used to communicate data between such
+diverse machines as the Sun Workstation, VAX, IBM-PC, and Cray.
+XDR fits into the ISO presentation layer, and is roughly analogous in
+purpose to X.409, ISO Abstract Syntax Notation. The major difference
+between these two is that XDR uses implicit typing, while X.409 uses
+explicit typing.
+.LP
+XDR uses a language to describe data formats. The language can only
+be used only to describe data; it is not a programming language.
+This language allows one to describe intricate data formats in a
+concise manner. The alternative of using graphical representations
+(itself an informal language) quickly becomes incomprehensible when
+faced with complexity. The XDR language itself is similar to the C
+language [1], just as Courier [4] is similar to Mesa. Protocols such
+as Sun RPC (Remote Procedure Call) and the NFS (Network File System)
+use XDR to describe the format of their data.
+.LP
+The XDR standard makes the following assumption: that bytes (or
+octets) are portable, where a byte is defined to be 8 bits of data.
+A given hardware device should encode the bytes onto the various
+media in such a way that other hardware devices may decode the bytes
+without loss of meaning. For example, the Ethernet standard
+suggests that bytes be encoded in "little-endian" style [2], or least
+significant bit first.
+.NH 2
+\&Basic Block Size
+.IX XDR "basic block size"
+.IX XDR "block size"
+.LP
+The representation of all items requires a multiple of four bytes (or
+32 bits) of data. The bytes are numbered 0 through n-1. The bytes
+are read or written to some byte stream such that byte m always
+precedes byte m+1. If the n bytes needed to contain the data are not
+a multiple of four, then the n bytes are followed by enough (0 to 3)
+residual zero bytes, r, to make the total byte count a multiple of 4.
+.LP
+We include the familiar graphic box notation for illustration and
+comparison. In most illustrations, each box (delimited by a plus
+sign at the 4 corners and vertical bars and dashes) depicts a byte.
+Ellipses (...) between boxes show zero or more additional bytes where
+required.
+.ie t .DS
+.el .DS L
+\fIA Block\fP
+
+\f(CW+--------+--------+...+--------+--------+...+--------+
+| byte 0 | byte 1 |...|byte n-1| 0 |...| 0 |
++--------+--------+...+--------+--------+...+--------+
+|<-----------n bytes---------->|<------r bytes------>|
+|<-----------n+r (where (n+r) mod 4 = 0)>----------->|\fP
+
+.DE
+.NH 1
+\&XDR Data Types
+.IX XDR "data types"
+.IX "XDR data types"
+.LP
+Each of the sections that follow describes a data type defined in the
+XDR standard, shows how it is declared in the language, and includes
+a graphic illustration of its encoding.
+.LP
+For each data type in the language we show a general paradigm
+declaration. Note that angle brackets (< and >) denote
+variable length sequences of data and square brackets ([ and ]) denote
+fixed-length sequences of data. "n", "m" and "r" denote integers.
+For the full language specification and more formal definitions of
+terms such as "identifier" and "declaration", refer to
+.I "The XDR Language Specification" ,
+below.
+.LP
+For some data types, more specific examples are included.
+A more extensive example of a data description is in
+.I "An Example of an XDR Data Description"
+below.
+.NH 2
+\&Integer
+.IX XDR integer
+.LP
+An XDR signed integer is a 32-bit datum that encodes an integer in
+the range [-2147483648,2147483647]. The integer is represented in
+two's complement notation. The most and least significant bytes are
+0 and 3, respectively. Integers are declared as follows:
+.ie t .DS
+.el .DS L
+\fIInteger\fP
+
+\f(CW(MSB) (LSB)
++-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |
++-------+-------+-------+-------+
+<------------32 bits------------>\fP
+.DE
+.NH 2
+\&Unsigned Integer
+.IX XDR "unsigned integer"
+.IX XDR "integer, unsigned"
+.LP
+An XDR unsigned integer is a 32-bit datum that encodes a nonnegative
+integer in the range [0,4294967295]. It is represented by an
+unsigned binary number whose most and least significant bytes are 0
+and 3, respectively. An unsigned integer is declared as follows:
+.ie t .DS
+.el .DS L
+\fIUnsigned Integer\fP
+
+\f(CW(MSB) (LSB)
++-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |
++-------+-------+-------+-------+
+<------------32 bits------------>\fP
+.DE
+.NH 2
+\&Enumeration
+.IX XDR enumeration
+.LP
+Enumerations have the same representation as signed integers.
+Enumerations are handy for describing subsets of the integers.
+Enumerated data is declared as follows:
+.ft CW
+.DS
+enum { name-identifier = constant, ... } identifier;
+.DE
+For example, the three colors red, yellow, and blue could be
+described by an enumerated type:
+.DS
+.ft CW
+enum { RED = 2, YELLOW = 3, BLUE = 5 } colors;
+.DE
+It is an error to encode as an enum any other integer than those that
+have been given assignments in the enum declaration.
+.NH 2
+\&Boolean
+.IX XDR boolean
+.LP
+Booleans are important enough and occur frequently enough to warrant
+their own explicit type in the standard. Booleans are declared as
+follows:
+.DS
+.ft CW
+bool identifier;
+.DE
+This is equivalent to:
+.DS
+.ft CW
+enum { FALSE = 0, TRUE = 1 } identifier;
+.DE
+.NH 2
+\&Hyper Integer and Unsigned Hyper Integer
+.IX XDR "hyper integer"
+.IX XDR "integer, hyper"
+.LP
+The standard also defines 64-bit (8-byte) numbers called hyper
+integer and unsigned hyper integer. Their representations are the
+obvious extensions of integer and unsigned integer defined above.
+They are represented in two's complement notation. The most and
+least significant bytes are 0 and 7, respectively. Their
+declarations:
+.ie t .DS
+.el .DS L
+\fIHyper Integer\fP
+\fIUnsigned Hyper Integer\fP
+
+\f(CW(MSB) (LSB)
++-------+-------+-------+-------+-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |byte 4 |byte 5 |byte 6 |byte 7 |
++-------+-------+-------+-------+-------+-------+-------+-------+
+<----------------------------64 bits---------------------------->\fP
+.DE
+.NH 2
+\&Floating-point
+.IX XDR "integer, floating point"
+.IX XDR "floating-point integer"
+.LP
+The standard defines the floating-point data type "float" (32 bits or
+4 bytes). The encoding used is the IEEE standard for normalized
+single-precision floating-point numbers [3]. The following three
+fields describe the single-precision floating-point number:
+.RS
+.IP \fBS\fP:
+The sign of the number. Values 0 and 1 represent positive and
+negative, respectively. One bit.
+.IP \fBE\fP:
+The exponent of the number, base 2. 8 bits are devoted to this
+field. The exponent is biased by 127.
+.IP \fBF\fP:
+The fractional part of the number's mantissa, base 2. 23 bits
+are devoted to this field.
+.RE
+.LP
+Therefore, the floating-point number is described by:
+.DS
+(-1)**S * 2**(E-Bias) * 1.F
+.DE
+It is declared as follows:
+.ie t .DS
+.el .DS L
+\fISingle-Precision Floating-Point\fP
+
+\f(CW+-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |
+S| E | F |
++-------+-------+-------+-------+
+1|<- 8 ->|<-------23 bits------>|
+<------------32 bits------------>\fP
+.DE
+Just as the most and least significant bytes of a number are 0 and 3,
+the most and least significant bits of a single-precision floating-
+point number are 0 and 31. The beginning bit (and most significant
+bit) offsets of S, E, and F are 0, 1, and 9, respectively. Note that
+these numbers refer to the mathematical positions of the bits, and
+NOT to their actual physical locations (which vary from medium to
+medium).
+.LP
+The IEEE specifications should be consulted concerning the encoding
+for signed zero, signed infinity (overflow), and denormalized numbers
+(underflow) [3]. According to IEEE specifications, the "NaN" (not a
+number) is system dependent and should not be used externally.
+.NH 2
+\&Double-precision Floating-point
+.IX XDR "integer, double-precision floating point"
+.IX XDR "double-precision floating-point integer"
+.LP
+The standard defines the encoding for the double-precision floating-
+point data type "double" (64 bits or 8 bytes). The encoding used is
+the IEEE standard for normalized double-precision floating-point
+numbers [3]. The standard encodes the following three fields, which
+describe the double-precision floating-point number:
+.RS
+.IP \fBS\fP:
+The sign of the number. Values 0 and 1 represent positive and
+negative, respectively. One bit.
+.IP \fBE\fP:
+The exponent of the number, base 2. 11 bits are devoted to this
+field. The exponent is biased by 1023.
+.IP \fBF\fP:
+The fractional part of the number's mantissa, base 2. 52 bits
+are devoted to this field.
+.RE
+.LP
+Therefore, the floating-point number is described by:
+.DS
+(-1)**S * 2**(E-Bias) * 1.F
+.DE
+It is declared as follows:
+.ie t .DS
+.el .DS L
+\fIDouble-Precision Floating-Point\fP
+
+\f(CW+------+------+------+------+------+------+------+------+
+|byte 0|byte 1|byte 2|byte 3|byte 4|byte 5|byte 6|byte 7|
+S| E | F |
++------+------+------+------+------+------+------+------+
+1|<--11-->|<-----------------52 bits------------------->|
+<-----------------------64 bits------------------------->\fP
+.DE
+Just as the most and least significant bytes of a number are 0 and 3,
+the most and least significant bits of a double-precision floating-
+point number are 0 and 63. The beginning bit (and most significant
+bit) offsets of S, E , and F are 0, 1, and 12, respectively. Note
+that these numbers refer to the mathematical positions of the bits,
+and NOT to their actual physical locations (which vary from medium to
+medium).
+.LP
+The IEEE specifications should be consulted concerning the encoding
+for signed zero, signed infinity (overflow), and denormalized numbers
+(underflow) [3]. According to IEEE specifications, the "NaN" (not a
+number) is system dependent and should not be used externally.
+.NH 2
+\&Fixed-length Opaque Data
+.IX XDR "fixed-length opaque data"
+.IX XDR "opaque data, fixed length"
+.LP
+At times, fixed-length uninterpreted data needs to be passed among
+machines. This data is called "opaque" and is declared as follows:
+.DS
+.ft CW
+opaque identifier[n];
+.DE
+where the constant n is the (static) number of bytes necessary to
+contain the opaque data. If n is not a multiple of four, then the n
+bytes are followed by enough (0 to 3) residual zero bytes, r, to make
+the total byte count of the opaque object a multiple of four.
+.ie t .DS
+.el .DS L
+\fIFixed-Length Opaque\fP
+
+\f(CW0 1 ...
++--------+--------+...+--------+--------+...+--------+
+| byte 0 | byte 1 |...|byte n-1| 0 |...| 0 |
++--------+--------+...+--------+--------+...+--------+
+|<-----------n bytes---------->|<------r bytes------>|
+|<-----------n+r (where (n+r) mod 4 = 0)------------>|\fP
+.DE
+.NH 2
+\&Variable-length Opaque Data
+.IX XDR "variable-length opaque data"
+.IX XDR "opaque data, variable length"
+.LP
+The standard also provides for variable-length (counted) opaque data,
+defined as a sequence of n (numbered 0 through n-1) arbitrary bytes
+to be the number n encoded as an unsigned integer (as described
+below), and followed by the n bytes of the sequence.
+.LP
+Byte m of the sequence always precedes byte m+1 of the sequence, and
+byte 0 of the sequence always follows the sequence's length (count).
+enough (0 to 3) residual zero bytes, r, to make the total byte count
+a multiple of four. Variable-length opaque data is declared in the
+following way:
+.DS
+.ft CW
+opaque identifier<m>;
+.DE
+or
+.DS
+.ft CW
+opaque identifier<>;
+.DE
+The constant m denotes an upper bound of the number of bytes that the
+sequence may contain. If m is not specified, as in the second
+declaration, it is assumed to be (2**32) - 1, the maximum length.
+The constant m would normally be found in a protocol specification.
+For example, a filing protocol may state that the maximum data
+transfer size is 8192 bytes, as follows:
+.DS
+.ft CW
+opaque filedata<8192>;
+.DE
+This can be illustrated as follows:
+.ie t .DS
+.el .DS L
+\fIVariable-Length Opaque\fP
+
+\f(CW0 1 2 3 4 5 ...
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+| length n |byte0|byte1|...| n-1 | 0 |...| 0 |
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+|<-------4 bytes------->|<------n bytes------>|<---r bytes--->|
+|<----n+r (where (n+r) mod 4 = 0)---->|\fP
+.DE
+.LP
+It is an error to encode a length greater than the maximum
+described in the specification.
+.NH 2
+\&String
+.IX XDR string
+.LP
+The standard defines a string of n (numbered 0 through n-1) ASCII
+bytes to be the number n encoded as an unsigned integer (as described
+above), and followed by the n bytes of the string. Byte m of the
+string always precedes byte m+1 of the string, and byte 0 of the
+string always follows the string's length. If n is not a multiple of
+four, then the n bytes are followed by enough (0 to 3) residual zero
+bytes, r, to make the total byte count a multiple of four. Counted
+byte strings are declared as follows:
+.DS
+.ft CW
+string object<m>;
+.DE
+or
+.DS
+.ft CW
+string object<>;
+.DE
+The constant m denotes an upper bound of the number of bytes that a
+string may contain. If m is not specified, as in the second
+declaration, it is assumed to be (2**32) - 1, the maximum length.
+The constant m would normally be found in a protocol specification.
+For example, a filing protocol may state that a file name can be no
+longer than 255 bytes, as follows:
+.DS
+.ft CW
+string filename<255>;
+.DE
+Which can be illustrated as:
+.ie t .DS
+.el .DS L
+\fIA String\fP
+
+\f(CW0 1 2 3 4 5 ...
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+| length n |byte0|byte1|...| n-1 | 0 |...| 0 |
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+|<-------4 bytes------->|<------n bytes------>|<---r bytes--->|
+|<----n+r (where (n+r) mod 4 = 0)---->|\fP
+.DE
+.LP
+It is an error to encode a length greater than the maximum
+described in the specification.
+.NH 2
+\&Fixed-length Array
+.IX XDR "fixed-length array"
+.IX XDR "array, fixed length"
+.LP
+Declarations for fixed-length arrays of homogeneous elements are in
+the following form:
+.DS
+.ft CW
+type-name identifier[n];
+.DE
+Fixed-length arrays of elements numbered 0 through n-1 are encoded by
+individually encoding the elements of the array in their natural
+order, 0 through n-1. Each element's size is a multiple of four
+bytes. Though all elements are of the same type, the elements may
+have different sizes. For example, in a fixed-length array of
+strings, all elements are of type "string", yet each element will
+vary in its length.
+.ie t .DS
+.el .DS L
+\fIFixed-Length Array\fP
+
+\f(CW+---+---+---+---+---+---+---+---+...+---+---+---+---+
+| element 0 | element 1 |...| element n-1 |
++---+---+---+---+---+---+---+---+...+---+---+---+---+
+|<--------------------n elements------------------->|\fP
+.DE
+.NH 2
+\&Variable-length Array
+.IX XDR "variable-length array"
+.IX XDR "array, variable length"
+.LP
+Counted arrays provide the ability to encode variable-length arrays
+of homogeneous elements. The array is encoded as the element count n
+(an unsigned integer) followed by the encoding of each of the array's
+elements, starting with element 0 and progressing through element n-
+1. The declaration for variable-length arrays follows this form:
+.DS
+.ft CW
+type-name identifier<m>;
+.DE
+or
+.DS
+.ft CW
+type-name identifier<>;
+.DE
+The constant m specifies the maximum acceptable element count of an
+array; if m is not specified, as in the second declaration, it is
+assumed to be (2**32) - 1.
+.ie t .DS
+.el .DS L
+\fICounted Array\fP
+
+\f(CW0 1 2 3
++--+--+--+--+--+--+--+--+--+--+--+--+...+--+--+--+--+
+| n | element 0 | element 1 |...|element n-1|
++--+--+--+--+--+--+--+--+--+--+--+--+...+--+--+--+--+
+|<-4 bytes->|<--------------n elements------------->|\fP
+.DE
+It is an error to encode a value of n that is greater than the
+maximum described in the specification.
+.NH 2
+\&Structure
+.IX XDR structure
+.LP
+Structures are declared as follows:
+.DS
+.ft CW
+struct {
+ component-declaration-A;
+ component-declaration-B;
+ \&...
+} identifier;
+.DE
+The components of the structure are encoded in the order of their
+declaration in the structure. Each component's size is a multiple of
+four bytes, though the components may be different sizes.
+.ie t .DS
+.el .DS L
+\fIStructure\fP
+
+\f(CW+-------------+-------------+...
+| component A | component B |...
++-------------+-------------+...\fP
+.DE
+.NH 2
+\&Discriminated Union
+.IX XDR "discriminated union"
+.IX XDR union discriminated
+.LP
+A discriminated union is a type composed of a discriminant followed
+by a type selected from a set of prearranged types according to the
+value of the discriminant. The type of discriminant is either "int",
+"unsigned int", or an enumerated type, such as "bool". The component
+types are called "arms" of the union, and are preceded by the value
+of the discriminant which implies their encoding. Discriminated
+unions are declared as follows:
+.DS
+.ft CW
+union switch (discriminant-declaration) {
+ case discriminant-value-A:
+ arm-declaration-A;
+ case discriminant-value-B:
+ arm-declaration-B;
+ \&...
+ default: default-declaration;
+} identifier;
+.DE
+Each "case" keyword is followed by a legal value of the discriminant.
+The default arm is optional. If it is not specified, then a valid
+encoding of the union cannot take on unspecified discriminant values.
+The size of the implied arm is always a multiple of four bytes.
+.LP
+The discriminated union is encoded as its discriminant followed by
+the encoding of the implied arm.
+.ie t .DS
+.el .DS L
+\fIDiscriminated Union\fP
+
+\f(CW0 1 2 3
++---+---+---+---+---+---+---+---+
+| discriminant | implied arm |
++---+---+---+---+---+---+---+---+
+|<---4 bytes--->|\fP
+.DE
+.NH 2
+\&Void
+.IX XDR void
+.LP
+An XDR void is a 0-byte quantity. Voids are useful for describing
+operations that take no data as input or no data as output. They are
+also useful in unions, where some arms may contain data and others do
+not. The declaration is simply as follows:
+.DS
+.ft CW
+void;
+.DE
+Voids are illustrated as follows:
+.ie t .DS
+.el .DS L
+\fIVoid\fP
+
+\f(CW ++
+ ||
+ ++
+--><-- 0 bytes\fP
+.DE
+.NH 2
+\&Constant
+.IX XDR constant
+.LP
+The data declaration for a constant follows this form:
+.DS
+.ft CW
+const name-identifier = n;
+.DE
+"const" is used to define a symbolic name for a constant; it does not
+declare any data. The symbolic constant may be used anywhere a
+regular constant may be used. For example, the following defines a
+symbolic constant DOZEN, equal to 12.
+.DS
+.ft CW
+const DOZEN = 12;
+.DE
+.NH 2
+\&Typedef
+.IX XDR typedef
+.LP
+"typedef" does not declare any data either, but serves to define new
+identifiers for declaring data. The syntax is:
+.DS
+.ft CW
+typedef declaration;
+.DE
+The new type name is actually the variable name in the declaration
+part of the typedef. For example, the following defines a new type
+called "eggbox" using an existing type called "egg":
+.DS
+.ft CW
+typedef egg eggbox[DOZEN];
+.DE
+Variables declared using the new type name have the same type as the
+new type name would have in the typedef, if it was considered a
+variable. For example, the following two declarations are equivalent
+in declaring the variable "fresheggs":
+.DS
+.ft CW
+eggbox fresheggs;
+egg fresheggs[DOZEN];
+.DE
+When a typedef involves a struct, enum, or union definition, there is
+another (preferred) syntax that may be used to define the same type.
+In general, a typedef of the following form:
+.DS
+.ft CW
+typedef <<struct, union, or enum definition>> identifier;
+.DE
+may be converted to the alternative form by removing the "typedef"
+part and placing the identifier after the "struct", "union", or
+"enum" keyword, instead of at the end. For example, here are the two
+ways to define the type "bool":
+.DS
+.ft CW
+typedef enum { /* \fIusing typedef\fP */
+ FALSE = 0,
+ TRUE = 1
+ } bool;
+
+enum bool { /* \fIpreferred alternative\fP */
+ FALSE = 0,
+ TRUE = 1
+ };
+.DE
+The reason this syntax is preferred is one does not have to wait
+until the end of a declaration to figure out the name of the new
+type.
+.NH 2
+\&Optional-data
+.IX XDR "optional data"
+.IX XDR "data, optional"
+.LP
+Optional-data is one kind of union that occurs so frequently that we
+give it a special syntax of its own for declaring it. It is declared
+as follows:
+.DS
+.ft CW
+type-name *identifier;
+.DE
+This is equivalent to the following union:
+.DS
+.ft CW
+union switch (bool opted) {
+ case TRUE:
+ type-name element;
+ case FALSE:
+ void;
+} identifier;
+.DE
+It is also equivalent to the following variable-length array
+declaration, since the boolean "opted" can be interpreted as the
+length of the array:
+.DS
+.ft CW
+type-name identifier<1>;
+.DE
+Optional-data is not so interesting in itself, but it is very useful
+for describing recursive data-structures such as linked-lists and
+trees. For example, the following defines a type "stringlist" that
+encodes lists of arbitrary length strings:
+.DS
+.ft CW
+struct *stringlist {
+ string item<>;
+ stringlist next;
+};
+.DE
+It could have been equivalently declared as the following union:
+.DS
+.ft CW
+union stringlist switch (bool opted) {
+ case TRUE:
+ struct {
+ string item<>;
+ stringlist next;
+ } element;
+ case FALSE:
+ void;
+};
+.DE
+or as a variable-length array:
+.DS
+.ft CW
+struct stringlist<1> {
+ string item<>;
+ stringlist next;
+};
+.DE
+Both of these declarations obscure the intention of the stringlist
+type, so the optional-data declaration is preferred over both of
+them. The optional-data type also has a close correlation to how
+recursive data structures are represented in high-level languages
+such as Pascal or C by use of pointers. In fact, the syntax is the
+same as that of the C language for pointers.
+.NH 2
+\&Areas for Future Enhancement
+.IX XDR futures
+.LP
+The XDR standard lacks representations for bit fields and bitmaps,
+since the standard is based on bytes. Also missing are packed (or
+binary-coded) decimals.
+.LP
+The intent of the XDR standard was not to describe every kind of data
+that people have ever sent or will ever want to send from machine to
+machine. Rather, it only describes the most commonly used data-types
+of high-level languages such as Pascal or C so that applications
+written in these languages will be able to communicate easily over
+some medium.
+.LP
+One could imagine extensions to XDR that would let it describe almost
+any existing protocol, such as TCP. The minimum necessary for this
+are support for different block sizes and byte-orders. The XDR
+discussed here could then be considered the 4-byte big-endian member
+of a larger XDR family.
+.NH 1
+\&Discussion
+.sp 2
+.NH 2
+\&Why a Language for Describing Data?
+.IX XDR language
+.LP
+There are many advantages in using a data-description language such
+as XDR versus using diagrams. Languages are more formal than
+diagrams and lead to less ambiguous descriptions of data.
+Languages are also easier to understand and allow one to think of
+other issues instead of the low-level details of bit-encoding.
+Also, there is a close analogy between the types of XDR and a
+high-level language such as C or Pascal. This makes the
+implementation of XDR encoding and decoding modules an easier task.
+Finally, the language specification itself is an ASCII string that
+can be passed from machine to machine to perform on-the-fly data
+interpretation.
+.NH 2
+\&Why Only one Byte-Order for an XDR Unit?
+.IX XDR "byte order"
+.LP
+Supporting two byte-orderings requires a higher level protocol for
+determining in which byte-order the data is encoded. Since XDR is
+not a protocol, this can't be done. The advantage of this, though,
+is that data in XDR format can be written to a magnetic tape, for
+example, and any machine will be able to interpret it, since no
+higher level protocol is necessary for determining the byte-order.
+.NH 2
+\&Why does XDR use Big-Endian Byte-Order?
+.LP
+Yes, it is unfair, but having only one byte-order means you have to
+be unfair to somebody. Many architectures, such as the Motorola
+68000 and IBM 370, support the big-endian byte-order.
+.NH 2
+\&Why is the XDR Unit Four Bytes Wide?
+.LP
+There is a tradeoff in choosing the XDR unit size. Choosing a small
+size such as two makes the encoded data small, but causes alignment
+problems for machines that aren't aligned on these boundaries. A
+large size such as eight means the data will be aligned on virtually
+every machine, but causes the encoded data to grow too big. We chose
+four as a compromise. Four is big enough to support most
+architectures efficiently, except for rare machines such as the
+eight-byte aligned Cray. Four is also small enough to keep the
+encoded data restricted to a reasonable size.
+.NH 2
+\&Why must Variable-Length Data be Padded with Zeros?
+.IX XDR "variable-length data"
+.LP
+It is desirable that the same data encode into the same thing on all
+machines, so that encoded data can be meaningfully compared or
+checksummed. Forcing the padded bytes to be zero ensures this.
+.NH 2
+\&Why is there No Explicit Data-Typing?
+.LP
+Data-typing has a relatively high cost for what small advantages it
+may have. One cost is the expansion of data due to the inserted type
+fields. Another is the added cost of interpreting these type fields
+and acting accordingly. And most protocols already know what type
+they expect, so data-typing supplies only redundant information.
+However, one can still get the benefits of data-typing using XDR. One
+way is to encode two things: first a string which is the XDR data
+description of the encoded data, and then the encoded data itself.
+Another way is to assign a value to all the types in XDR, and then
+define a universal type which takes this value as its discriminant
+and for each value, describes the corresponding data type.
+.NH 1
+\&The XDR Language Specification
+.IX XDR language
+.sp 1
+.NH 2
+\&Notational Conventions
+.IX "XDR language" notation
+.LP
+This specification uses an extended Backus-Naur Form notation for
+describing the XDR language. Here is a brief description of the
+notation:
+.IP 1.
+The characters
+.I | ,
+.I ( ,
+.I ) ,
+.I [ ,
+.I ] ,
+.I " ,
+and
+.I *
+are special.
+.IP 2.
+Terminal symbols are strings of any characters surrounded by
+double quotes.
+.IP 3.
+Non-terminal symbols are strings of non-special characters.
+.IP 4.
+Alternative items are separated by a vertical bar ("\fI|\fP").
+.IP 5.
+Optional items are enclosed in brackets.
+.IP 6.
+Items are grouped together by enclosing them in parentheses.
+.IP 7.
+A
+.I *
+following an item means 0 or more occurrences of that item.
+.LP
+For example, consider the following pattern:
+.DS L
+"a " "very" (", " " very")* [" cold " "and"] " rainy " ("day" | "night")
+.DE
+.LP
+An infinite number of strings match this pattern. A few of them
+are:
+.DS
+"a very rainy day"
+"a very, very rainy day"
+"a very cold and rainy day"
+"a very, very, very cold and rainy night"
+.DE
+.NH 2
+\&Lexical Notes
+.IP 1.
+Comments begin with '/*' and terminate with '*/'.
+.IP 2.
+White space serves to separate items and is otherwise ignored.
+.IP 3.
+An identifier is a letter followed by an optional sequence of
+letters, digits or underbar ('_'). The case of identifiers is
+not ignored.
+.IP 4.
+A constant is a sequence of one or more decimal digits,
+optionally preceded by a minus-sign ('-').
+.NH 2
+\&Syntax Information
+.IX "XDR language" syntax
+.DS
+.ft CW
+declaration:
+ type-specifier identifier
+ | type-specifier identifier "[" value "]"
+ | type-specifier identifier "<" [ value ] ">"
+ | "opaque" identifier "[" value "]"
+ | "opaque" identifier "<" [ value ] ">"
+ | "string" identifier "<" [ value ] ">"
+ | type-specifier "*" identifier
+ | "void"
+.DE
+.DS
+.ft CW
+value:
+ constant
+ | identifier
+
+type-specifier:
+ [ "unsigned" ] "int"
+ | [ "unsigned" ] "hyper"
+ | "float"
+ | "double"
+ | "bool"
+ | enum-type-spec
+ | struct-type-spec
+ | union-type-spec
+ | identifier
+.DE
+.DS
+.ft CW
+enum-type-spec:
+ "enum" enum-body
+
+enum-body:
+ "{"
+ ( identifier "=" value )
+ ( "," identifier "=" value )*
+ "}"
+.DE
+.DS
+.ft CW
+struct-type-spec:
+ "struct" struct-body
+
+struct-body:
+ "{"
+ ( declaration ";" )
+ ( declaration ";" )*
+ "}"
+.DE
+.DS
+.ft CW
+union-type-spec:
+ "union" union-body
+
+union-body:
+ "switch" "(" declaration ")" "{"
+ ( "case" value ":" declaration ";" )
+ ( "case" value ":" declaration ";" )*
+ [ "default" ":" declaration ";" ]
+ "}"
+
+constant-def:
+ "const" identifier "=" constant ";"
+.DE
+.DS
+.ft CW
+type-def:
+ "typedef" declaration ";"
+ | "enum" identifier enum-body ";"
+ | "struct" identifier struct-body ";"
+ | "union" identifier union-body ";"
+
+definition:
+ type-def
+ | constant-def
+
+specification:
+ definition *
+.DE
+.NH 3
+\&Syntax Notes
+.IX "XDR language" syntax
+.LP
+.IP 1.
+The following are keywords and cannot be used as identifiers:
+"bool", "case", "const", "default", "double", "enum", "float",
+"hyper", "opaque", "string", "struct", "switch", "typedef", "union",
+"unsigned" and "void".
+.IP 2.
+Only unsigned constants may be used as size specifications for
+arrays. If an identifier is used, it must have been declared
+previously as an unsigned constant in a "const" definition.
+.IP 3.
+Constant and type identifiers within the scope of a specification
+are in the same name space and must be declared uniquely within this
+scope.
+.IP 4.
+Similarly, variable names must be unique within the scope of
+struct and union declarations. Nested struct and union declarations
+create new scopes.
+.IP 5.
+The discriminant of a union must be of a type that evaluates to
+an integer. That is, "int", "unsigned int", "bool", an enumerated
+type or any typedefed type that evaluates to one of these is legal.
+Also, the case values must be one of the legal values of the
+discriminant. Finally, a case value may not be specified more than
+once within the scope of a union declaration.
+.NH 1
+\&An Example of an XDR Data Description
+.LP
+Here is a short XDR data description of a thing called a "file",
+which might be used to transfer files from one machine to another.
+.ie t .DS
+.el .DS L
+.ft CW
+
+const MAXUSERNAME = 32; /*\fI max length of a user name \fP*/
+const MAXFILELEN = 65535; /*\fI max length of a file \fP*/
+const MAXNAMELEN = 255; /*\fI max length of a file name \fP*/
+
+.ft I
+/*
+ * Types of files:
+ */
+.ft CW
+
+enum filekind {
+ TEXT = 0, /*\fI ascii data \fP*/
+ DATA = 1, /*\fI raw data \fP*/
+ EXEC = 2 /*\fI executable \fP*/
+};
+
+.ft I
+/*
+ * File information, per kind of file:
+ */
+.ft CW
+
+union filetype switch (filekind kind) {
+ case TEXT:
+ void; /*\fI no extra information \fP*/
+ case DATA:
+ string creator<MAXNAMELEN>; /*\fI data creator \fP*/
+ case EXEC:
+ string interpretor<MAXNAMELEN>; /*\fI program interpretor \fP*/
+};
+
+.ft I
+/*
+ * A complete file:
+ */
+.ft CW
+
+struct file {
+ string filename<MAXNAMELEN>; /*\fI name of file \fP*/
+ filetype type; /*\fI info about file \fP*/
+ string owner<MAXUSERNAME>; /*\fI owner of file \fP*/
+ opaque data<MAXFILELEN>; /*\fI file data \fP*/
+};
+.DE
+.LP
+Suppose now that there is a user named "john" who wants to store
+his lisp program "sillyprog" that contains just the data "(quit)".
+His file would be encoded as follows:
+.TS
+box tab (&) ;
+lfI lfI lfI lfI
+rfL rfL rfL l .
+Offset&Hex Bytes&ASCII&Description
+_
+0&00 00 00 09&....&Length of filename = 9
+4&73 69 6c 6c&sill&Filename characters
+8&79 70 72 6f&ypro& ... and more characters ...
+12&67 00 00 00&g...& ... and 3 zero-bytes of fill
+16&00 00 00 02&....&Filekind is EXEC = 2
+20&00 00 00 04&....&Length of interpretor = 4
+24&6c 69 73 70&lisp&Interpretor characters
+28&00 00 00 04&....&Length of owner = 4
+32&6a 6f 68 6e&john&Owner characters
+36&00 00 00 06&....&Length of file data = 6
+40&28 71 75 69&(qui&File data bytes ...
+44&74 29 00 00&t)..& ... and 2 zero-bytes of fill
+.TE
+.NH 1
+\&References
+.LP
+[1] Brian W. Kernighan & Dennis M. Ritchie, "The C Programming
+Language", Bell Laboratories, Murray Hill, New Jersey, 1978.
+.LP
+[2] Danny Cohen, "On Holy Wars and a Plea for Peace", IEEE Computer,
+October 1981.
+.LP
+[3] "IEEE Standard for Binary Floating-Point Arithmetic", ANSI/IEEE
+Standard 754-1985, Institute of Electrical and Electronics
+Engineers, August 1985.
+.LP
+[4] "Courier: The Remote Procedure Call Protocol", XEROX
+Corporation, XSIS 038112, December 1981.
diff --git a/share/doc/psd/26.rpcrfc/Makefile b/share/doc/psd/26.rpcrfc/Makefile
index 79214f1..3ffdc27 100644
--- a/share/doc/psd/26.rpcrfc/Makefile
+++ b/share/doc/psd/26.rpcrfc/Makefile
@@ -4,6 +4,5 @@ VOLUME= psd/26.rpcrfc
SRCS= stubs rpc.rfc.ms
MACROS= -ms
USE_TBL=
-SRCDIR= ${.CURDIR}/../../../../lib/libc/rpc/PSD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/psd/26.rpcrfc/rpc.rfc.ms b/share/doc/psd/26.rpcrfc/rpc.rfc.ms
new file mode 100644
index 0000000..9a948bd
--- /dev/null
+++ b/share/doc/psd/26.rpcrfc/rpc.rfc.ms
@@ -0,0 +1,1304 @@
+.\"
+.\" Must use -- tbl -- with this one
+.\"
+.\" @(#)rpc.rfc.ms 2.2 88/08/05 4.0 RPCSRC
+.\" $FreeBSD$
+.\"
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'Remote Procedure Calls: Protocol Specification''Page %'
+.EH 'Page %''Remote Procedure Calls: Protocol Specification'
+.if \n%=1 .bp
+.SH
+\&Remote Procedure Calls: Protocol Specification
+.LP
+.NH 0
+\&Status of this Memo
+.LP
+Note: This chapter specifies a protocol that Sun Microsystems, Inc.,
+and others are using.
+It has been designated RFC1050 by the ARPA Network
+Information Center.
+.LP
+.NH 1
+\&Introduction
+.LP
+This chapter specifies a message protocol used in implementing
+Sun's Remote Procedure Call (RPC) package. (The message protocol is
+specified with the External Data Representation (XDR) language.
+See the
+.I "External Data Representation Standard: Protocol Specification"
+for the details. Here, we assume that the reader is familiar
+with XDR and do not attempt to justify it or its uses). The paper
+by Birrell and Nelson [1] is recommended as an excellent background
+to and justification of RPC.
+.NH 2
+\&Terminology
+.LP
+This chapter discusses servers, services, programs, procedures,
+clients, and versions. A server is a piece of software where network
+services are implemented. A network service is a collection of one
+or more remote programs. A remote program implements one or more
+remote procedures; the procedures, their parameters, and results are
+documented in the specific program's protocol specification (see the
+\fIPort Mapper Program Protocol\fP\, below, for an example). Network
+clients are pieces of software that initiate remote procedure calls
+to services. A server may support more than one version of a remote
+program in order to be forward compatible with changing protocols.
+.LP
+For example, a network file service may be composed of two programs.
+One program may deal with high-level applications such as file system
+access control and locking. The other may deal with low-level file
+IO and have procedures like "read" and "write". A client machine of
+the network file service would call the procedures associated with
+the two programs of the service on behalf of some user on the client
+machine.
+.NH 2
+\&The RPC Model
+.LP
+The remote procedure call model is similar to the local procedure
+call model. In the local case, the caller places arguments to a
+procedure in some well-specified location (such as a result
+register). It then transfers control to the procedure, and
+eventually gains back control. At that point, the results of the
+procedure are extracted from the well-specified location, and the
+caller continues execution.
+.LP
+The remote procedure call is similar, in that one thread of control
+logically winds through two processes\(emone is the caller's process,
+the other is a server's process. That is, the caller process sends a
+call message to the server process and waits (blocks) for a reply
+message. The call message contains the procedure's parameters, among
+other things. The reply message contains the procedure's results,
+among other things. Once the reply message is received, the results
+of the procedure are extracted, and caller's execution is resumed.
+.LP
+On the server side, a process is dormant awaiting the arrival of a
+call message. When one arrives, the server process extracts the
+procedure's parameters, computes the results, sends a reply message,
+and then awaits the next call message.
+.LP
+Note that in this model, only one of the two processes is active at
+any given time. However, this model is only given as an example.
+The RPC protocol makes no restrictions on the concurrency model
+implemented, and others are possible. For example, an implementation
+may choose to have RPC calls be asynchronous, so that the client may
+do useful work while waiting for the reply from the server. Another
+possibility is to have the server create a task to process an
+incoming request, so that the server can be free to receive other
+requests.
+.NH 2
+\&Transports and Semantics
+.LP
+The RPC protocol is independent of transport protocols. That is, RPC
+does not care how a message is passed from one process to another.
+The protocol deals only with specification and interpretation of
+messages.
+.LP
+It is important to point out that RPC does not try to implement any
+kind of reliability and that the application must be aware of the
+type of transport protocol underneath RPC. If it knows it is running
+on top of a reliable transport such as TCP/IP[6], then most of the
+work is already done for it. On the other hand, if it is running on
+top of an unreliable transport such as UDP/IP[7], it must implement
+is own retransmission and time-out policy as the RPC layer does not
+provide this service.
+.LP
+Because of transport independence, the RPC protocol does not attach
+specific semantics to the remote procedures or their execution.
+Semantics can be inferred from (but should be explicitly specified
+by) the underlying transport protocol. For example, consider RPC
+running on top of an unreliable transport such as UDP/IP. If an
+application retransmits RPC messages after short time-outs, the only
+thing it can infer if it receives no reply is that the procedure was
+executed zero or more times. If it does receive a reply, then it can
+infer that the procedure was executed at least once.
+.LP
+A server may wish to remember previously granted requests from a
+client and not regrant them in order to insure some degree of
+execute-at-most-once semantics. A server can do this by taking
+advantage of the transaction ID that is packaged with every RPC
+request. The main use of this transaction is by the client RPC layer
+in matching replies to requests. However, a client application may
+choose to reuse its previous transaction ID when retransmitting a
+request. The server application, knowing this fact, may choose to
+remember this ID after granting a request and not regrant requests
+with the same ID in order to achieve some degree of
+execute-at-most-once semantics. The server is not allowed to examine
+this ID in any other way except as a test for equality.
+.LP
+On the other hand, if using a reliable transport such as TCP/IP, the
+application can infer from a reply message that the procedure was
+executed exactly once, but if it receives no reply message, it cannot
+assume the remote procedure was not executed. Note that even if a
+connection-oriented protocol like TCP is used, an application still
+needs time-outs and reconnection to handle server crashes.
+.LP
+There are other possibilities for transports besides datagram- or
+connection-oriented protocols. For example, a request-reply protocol
+such as VMTP[2] is perhaps the most natural transport for RPC.
+.SH
+.I
+NOTE: At Sun, RPC is currently implemented on top of both TCP/IP
+and UDP/IP transports.
+.LP
+.NH 2
+\&Binding and Rendezvous Independence
+.LP
+The act of binding a client to a service is NOT part of the remote
+procedure call specification. This important and necessary function
+is left up to some higher-level software. (The software may use RPC
+itself\(emsee the \fIPort Mapper Program Protocol\fP\, below).
+.LP
+Implementors should think of the RPC protocol as the jump-subroutine
+instruction ("JSR") of a network; the loader (binder) makes JSR
+useful, and the loader itself uses JSR to accomplish its task.
+Likewise, the network makes RPC useful, using RPC to accomplish this
+task.
+.NH 2
+\&Authentication
+.LP
+The RPC protocol provides the fields necessary for a client to
+identify itself to a service and vice-versa. Security and access
+control mechanisms can be built on top of the message authentication.
+Several different authentication protocols can be supported. A field
+in the RPC header indicates which protocol is being used. More
+information on specific authentication protocols can be found in the
+\fIAuthentication Protocols\fP\,
+below.
+.KS
+.NH 1
+\&RPC Protocol Requirements
+.LP
+The RPC protocol must provide for the following:
+.IP 1.
+Unique specification of a procedure to be called.
+.IP 2.
+Provisions for matching response messages to request messages.
+.KE
+.IP 3.
+Provisions for authenticating the caller to service and vice-versa.
+.LP
+Besides these requirements, features that detect the following are
+worth supporting because of protocol roll-over errors, implementation
+bugs, user error, and network administration:
+.IP 1.
+RPC protocol mismatches.
+.IP 2.
+Remote program protocol version mismatches.
+.IP 3.
+Protocol errors (such as misspecification of a procedure's parameters).
+.IP 4.
+Reasons why remote authentication failed.
+.IP 5.
+Any other reasons why the desired procedure was not called.
+.NH 2
+\&Programs and Procedures
+.LP
+The RPC call message has three unsigned fields: remote program
+number, remote program version number, and remote procedure number.
+The three fields uniquely identify the procedure to be called.
+Program numbers are administered by some central authority (like
+Sun). Once an implementor has a program number, he can implement his
+remote program; the first implementation would most likely have the
+version number of 1. Because most new protocols evolve into better,
+stable, and mature protocols, a version field of the call message
+identifies which version of the protocol the caller is using.
+Version numbers make speaking old and new protocols through the same
+server process possible.
+.LP
+The procedure number identifies the procedure to be called. These
+numbers are documented in the specific program's protocol
+specification. For example, a file service's protocol specification
+may state that its procedure number 5 is "read" and procedure number
+12 is "write".
+.LP
+Just as remote program protocols may change over several versions,
+the actual RPC message protocol could also change. Therefore, the
+call message also has in it the RPC version number, which is always
+equal to two for the version of RPC described here.
+.LP
+The reply message to a request message has enough information to
+distinguish the following error conditions:
+.IP 1.
+The remote implementation of RPC does speak protocol version 2.
+The lowest and highest supported RPC version numbers are returned.
+.IP 2.
+The remote program is not available on the remote system.
+.IP 3.
+The remote program does not support the requested version number.
+The lowest and highest supported remote program version numbers are
+returned.
+.IP 4.
+The requested procedure number does not exist. (This is usually a
+caller side protocol or programming error.)
+.IP 5.
+The parameters to the remote procedure appear to be garbage from the
+server's point of view. (Again, this is usually caused by a
+disagreement about the protocol between client and service.)
+.NH 2
+\&Authentication
+.LP
+Provisions for authentication of caller to service and vice-versa are
+provided as a part of the RPC protocol. The call message has two
+authentication fields, the credentials and verifier. The reply
+message has one authentication field, the response verifier. The RPC
+protocol specification defines all three fields to be the following
+opaque type:
+.DS
+.ft CW
+.vs 11
+enum auth_flavor {
+ AUTH_NULL = 0,
+ AUTH_UNIX = 1,
+ AUTH_SHORT = 2,
+ AUTH_DES = 3
+ /* \fIand more to be defined\fP */
+};
+
+struct opaque_auth {
+ auth_flavor flavor;
+ opaque body<400>;
+};
+.DE
+.LP
+In simple English, any
+.I opaque_auth
+structure is an
+.I auth_flavor
+enumeration followed by bytes which are opaque to the RPC protocol
+implementation.
+.LP
+The interpretation and semantics of the data contained within the
+authentication fields is specified by individual, independent
+authentication protocol specifications. (See
+\fIAuthentication Protocols\fP\,
+below, for definitions of the various authentication protocols.)
+.LP
+If authentication parameters were rejected, the response message
+contains information stating why they were rejected.
+.NH 2
+\&Program Number Assignment
+.LP
+Program numbers are given out in groups of
+.I 0x20000000
+(decimal 536870912) according to the following chart:
+.TS
+box tab (&) ;
+lfI lfI
+rfL cfI .
+Program Numbers&Description
+_
+.sp .5
+0 - 1fffffff&Defined by Sun
+20000000 - 3fffffff&Defined by user
+40000000 - 5fffffff&Transient
+60000000 - 7fffffff&Reserved
+80000000 - 9fffffff&Reserved
+a0000000 - bfffffff&Reserved
+c0000000 - dfffffff&Reserved
+e0000000 - ffffffff&Reserved
+.TE
+.LP
+The first group is a range of numbers administered by Sun
+Microsystems and should be identical for all sites. The second range
+is for applications peculiar to a particular site. This range is
+intended primarily for debugging new programs. When a site develops
+an application that might be of general interest, that application
+should be given an assigned number in the first range. The third
+group is for applications that generate program numbers dynamically.
+The final groups are reserved for future use, and should not be used.
+.NH 2
+\&Other Uses of the RPC Protocol
+.LP
+The intended use of this protocol is for calling remote procedures.
+That is, each call message is matched with a response message.
+However, the protocol itself is a message-passing protocol with which
+other (non-RPC) protocols can be implemented. Sun currently uses, or
+perhaps abuses, the RPC message protocol for the following two
+(non-RPC) protocols: batching (or pipelining) and broadcast RPC.
+These two protocols are discussed but not defined below.
+.NH 3
+\&Batching
+.LP
+Batching allows a client to send an arbitrarily large sequence of
+call messages to a server; batching typically uses reliable byte
+stream protocols (like TCP/IP) for its transport. In the case of
+batching, the client never waits for a reply from the server, and the
+server does not send replies to batch requests. A sequence of batch
+calls is usually terminated by a legitimate RPC in order to flush the
+pipeline (with positive acknowledgement).
+.NH 3
+\&Broadcast RPC
+.LP
+In broadcast RPC-based protocols, the client sends a broadcast packet
+to the network and waits for numerous replies. Broadcast RPC uses
+unreliable, packet-based protocols (like UDP/IP) as its transports.
+Servers that support broadcast protocols only respond when the
+request is successfully processed, and are silent in the face of
+errors. Broadcast RPC uses the Port Mapper RPC service to achieve
+its semantics. See the \fIPort Mapper Program Protocol\fP\, below,
+for more information.
+.KS
+.NH 1
+\&The RPC Message Protocol
+.LP
+This section defines the RPC message protocol in the XDR data
+description language. The message is defined in a top-down style.
+.ie t .DS
+.el .DS L
+.ft CW
+enum msg_type {
+ CALL = 0,
+ REPLY = 1
+};
+
+.ft I
+/*
+* A reply to a call message can take on two forms:
+* The message was either accepted or rejected.
+*/
+.ft CW
+enum reply_stat {
+ MSG_ACCEPTED = 0,
+ MSG_DENIED = 1
+};
+
+.ft I
+/*
+* Given that a call message was accepted, the following is the
+* status of an attempt to call a remote procedure.
+*/
+.ft CW
+enum accept_stat {
+ SUCCESS = 0, /* \fIRPC executed successfully \fP*/
+ PROG_UNAVAIL = 1, /* \fIremote hasn't exported program \fP*/
+ PROG_MISMATCH = 2, /* \fIremote can't support version # \fP*/
+ PROC_UNAVAIL = 3, /* \fIprogram can't support procedure \fP*/
+ GARBAGE_ARGS = 4 /* \fIprocedure can't decode params \fP*/
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Reasons why a call message was rejected:
+*/
+.ft CW
+enum reject_stat {
+ RPC_MISMATCH = 0, /* \fIRPC version number != 2 \fP*/
+ AUTH_ERROR = 1 /* \fIremote can't authenticate caller \fP*/
+};
+
+.ft I
+/*
+* Why authentication failed:
+*/
+.ft CW
+enum auth_stat {
+ AUTH_BADCRED = 1, /* \fIbad credentials \fP*/
+ AUTH_REJECTEDCRED = 2, /* \fIclient must begin new session \fP*/
+ AUTH_BADVERF = 3, /* \fIbad verifier \fP*/
+ AUTH_REJECTEDVERF = 4, /* \fIverifier expired or replayed \fP*/
+ AUTH_TOOWEAK = 5 /* \fIrejected for security reasons \fP*/
+};
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* The RPC message:
+* All messages start with a transaction identifier, xid,
+* followed by a two-armed discriminated union. The union's
+* discriminant is a msg_type which switches to one of the two
+* types of the message. The xid of a \fIREPLY\fP message always
+* matches that of the initiating \fICALL\fP message. NB: The xid
+* field is only used for clients matching reply messages with
+* call messages or for servers detecting retransmissions; the
+* service side cannot treat this id as any type of sequence
+* number.
+*/
+.ft CW
+struct rpc_msg {
+ unsigned int xid;
+ union switch (msg_type mtype) {
+ case CALL:
+ call_body cbody;
+ case REPLY:
+ reply_body rbody;
+ } body;
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Body of an RPC request call:
+* In version 2 of the RPC protocol specification, rpcvers must
+* be equal to 2. The fields prog, vers, and proc specify the
+* remote program, its version number, and the procedure within
+* the remote program to be called. After these fields are two
+* authentication parameters: cred (authentication credentials)
+* and verf (authentication verifier). The two authentication
+* parameters are followed by the parameters to the remote
+* procedure, which are specified by the specific program
+* protocol.
+*/
+.ft CW
+struct call_body {
+ unsigned int rpcvers; /* \fImust be equal to two (2) \fP*/
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int proc;
+ opaque_auth cred;
+ opaque_auth verf;
+ /* \fIprocedure specific parameters start here \fP*/
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Body of a reply to an RPC request:
+* The call message was either accepted or rejected.
+*/
+.ft CW
+union reply_body switch (reply_stat stat) {
+ case MSG_ACCEPTED:
+ accepted_reply areply;
+ case MSG_DENIED:
+ rejected_reply rreply;
+} reply;
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Reply to an RPC request that was accepted by the server:
+* there could be an error even though the request was accepted.
+* The first field is an authentication verifier that the server
+* generates in order to validate itself to the caller. It is
+* followed by a union whose discriminant is an enum
+* accept_stat. The \fISUCCESS\fP arm of the union is protocol
+* specific. The \fIPROG_UNAVAIL\fP, \fIPROC_UNAVAIL\fP, and \fIGARBAGE_ARGP\fP
+* arms of the union are void. The \fIPROG_MISMATCH\fP arm specifies
+* the lowest and highest version numbers of the remote program
+* supported by the server.
+*/
+.ft CW
+struct accepted_reply {
+ opaque_auth verf;
+ union switch (accept_stat stat) {
+ case SUCCESS:
+ opaque results[0];
+ /* \fIprocedure-specific results start here\fP */
+ case PROG_MISMATCH:
+ struct {
+ unsigned int low;
+ unsigned int high;
+ } mismatch_info;
+ default:
+.ft I
+ /*
+ * Void. Cases include \fIPROG_UNAVAIL, PROC_UNAVAIL\fP,
+ * and \fIGARBAGE_ARGS\fP.
+ */
+.ft CW
+ void;
+ } reply_data;
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Reply to an RPC request that was rejected by the server:
+* The request can be rejected for two reasons: either the
+* server is not running a compatible version of the RPC
+* protocol (\fIRPC_MISMATCH\fP), or the server refuses to
+* authenticate the caller (\fIAUTH_ERROR\fP). In case of an RPC
+* version mismatch, the server returns the lowest and highest
+* supported RPC version numbers. In case of refused
+* authentication, failure status is returned.
+*/
+.ft CW
+union rejected_reply switch (reject_stat stat) {
+ case RPC_MISMATCH:
+ struct {
+ unsigned int low;
+ unsigned int high;
+ } mismatch_info;
+ case AUTH_ERROR:
+ auth_stat stat;
+};
+.DE
+.NH 1
+\&Authentication Protocols
+.LP
+As previously stated, authentication parameters are opaque, but
+open-ended to the rest of the RPC protocol. This section defines
+some "flavors" of authentication implemented at (and supported by)
+Sun. Other sites are free to invent new authentication types, with
+the same rules of flavor number assignment as there is for program
+number assignment.
+.NH 2
+\&Null Authentication
+.LP
+Often calls must be made where the caller does not know who he is or
+the server does not care who the caller is. In this case, the flavor
+value (the discriminant of the \fIopaque_auth\fP's union) of the RPC
+message's credentials, verifier, and response verifier is
+.I AUTH_NULL .
+The bytes of the opaque_auth's body are undefined.
+It is recommended that the opaque length be zero.
+.NH 2
+\&UNIX Authentication
+.LP
+The caller of a remote procedure may wish to identify himself as he
+is identified on a UNIX system. The value of the credential's
+discriminant of an RPC call message is
+.I AUTH_UNIX .
+The bytes of
+the credential's opaque body encode the following structure:
+.DS
+.ft CW
+struct auth_unix {
+ unsigned int stamp;
+ string machinename<255>;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int gids<10>;
+};
+.DE
+The
+.I stamp
+is an arbitrary ID which the caller machine may
+generate. The
+.I machinename
+is the name of the caller's machine (like "krypton"). The
+.I uid
+is the caller's effective user ID. The
+.I gid
+is the caller's effective group ID. The
+.I gids
+is a
+counted array of groups which contain the caller as a member. The
+verifier accompanying the credentials should be of
+.I AUTH_NULL
+(defined above).
+.LP
+The value of the discriminant of the response verifier received in
+the reply message from the server may be
+.I AUTH_NULL
+or
+.I AUTH_SHORT .
+In the case of
+.I AUTH_SHORT ,
+the bytes of the response verifier's string encode an opaque
+structure. This new opaque structure may now be passed to the server
+instead of the original
+.I AUTH_UNIX
+flavor credentials. The server keeps a cache which maps shorthand
+opaque structures (passed back by way of an
+.I AUTH_SHORT
+style response verifier) to the original credentials of the caller.
+The caller can save network bandwidth and server cpu cycles by using
+the new credentials.
+.LP
+The server may flush the shorthand opaque structure at any time. If
+this happens, the remote procedure call message will be rejected due
+to an authentication error. The reason for the failure will be
+.I AUTH_REJECTEDCRED .
+At this point, the caller may wish to try the original
+.I AUTH_UNIX
+style of credentials.
+.KS
+.NH 2
+\&DES Authentication
+.LP
+UNIX authentication suffers from two major problems:
+.IP 1.
+The naming is too UNIX-system oriented.
+.IP 2.
+There is no verifier, so credentials can easily be faked.
+.LP
+DES authentication attempts to fix these two problems.
+.KE
+.NH 3
+\&Naming
+.LP
+The first problem is handled by addressing the caller by a simple
+string of characters instead of by an operating system specific
+integer. This string of characters is known as the "netname" or
+network name of the caller. The server is not allowed to interpret
+the contents of the caller's name in any other way except to
+identify the caller. Thus, netnames should be unique for every
+caller in the internet.
+.LP
+It is up to each operating system's implementation of DES
+authentication to generate netnames for its users that insure this
+uniqueness when they call upon remote servers. Operating systems
+already know how to distinguish users local to their systems. It is
+usually a simple matter to extend this mechanism to the network.
+For example, a UNIX user at Sun with a user ID of 515 might be
+assigned the following netname: "unix.515@sun.com". This netname
+contains three items that serve to insure it is unique. Going
+backwards, there is only one naming domain called "sun.com" in the
+internet. Within this domain, there is only one UNIX user with
+user ID 515. However, there may be another user on another
+operating system, for example VMS, within the same naming domain
+that, by coincidence, happens to have the same user ID. To insure
+that these two users can be distinguished we add the operating
+system name. So one user is "unix.515@sun.com" and the other is
+"vms.515@sun.com".
+.LP
+The first field is actually a naming method rather than an
+operating system name. It just happens that today there is almost
+a one-to-one correspondence between naming methods and operating
+systems. If the world could agree on a naming standard, the first
+field could be the name of that standard, instead of an operating
+system name.
+.LP
+.NH 3
+\&DES Authentication Verifiers
+.LP
+Unlike UNIX authentication, DES authentication does have a verifier
+so the server can validate the client's credential (and
+vice-versa). The contents of this verifier is primarily an
+encrypted timestamp. The server can decrypt this timestamp, and if
+it is close to what the real time is, then the client must have
+encrypted it correctly. The only way the client could encrypt it
+correctly is to know the "conversation key" of the RPC session. And
+if the client knows the conversation key, then it must be the real
+client.
+.LP
+The conversation key is a DES [5] key which the client generates
+and notifies the server of in its first RPC call. The conversation
+key is encrypted using a public key scheme in this first
+transaction. The particular public key scheme used in DES
+authentication is Diffie-Hellman [3] with 192-bit keys. The
+details of this encryption method are described later.
+.LP
+The client and the server need the same notion of the current time
+in order for all of this to work. If network time synchronization
+cannot be guaranteed, then client can synchronize with the server
+before beginning the conversation, perhaps by consulting the
+Internet Time Server (TIME[4]).
+.LP
+The way a server determines if a client timestamp is valid is
+somewhat complicated. For any other transaction but the first, the
+server just checks for two things:
+.IP 1.
+the timestamp is greater than the one previously seen from the
+same client.
+.IP 2.
+the timestamp has not expired.
+.LP
+A timestamp is expired if the server's time is later than the sum
+of the client's timestamp plus what is known as the client's
+"window". The "window" is a number the client passes (encrypted)
+to the server in its first transaction. You can think of it as a
+lifetime for the credential.
+.LP
+This explains everything but the first transaction. In the first
+transaction, the server checks only that the timestamp has not
+expired. If this was all that was done though, then it would be
+quite easy for the client to send random data in place of the
+timestamp with a fairly good chance of succeeding. As an added
+check, the client sends an encrypted item in the first transaction
+known as the "window verifier" which must be equal to the window
+minus 1, or the server will reject the credential.
+.LP
+The client too must check the verifier returned from the server to
+be sure it is legitimate. The server sends back to the client the
+encrypted timestamp it received from the client, minus one second.
+If the client gets anything different than this, it will reject it.
+.LP
+.NH 3
+\&Nicknames and Clock Synchronization
+.LP
+After the first transaction, the server's DES authentication
+subsystem returns in its verifier to the client an integer
+"nickname" which the client may use in its further transactions
+instead of passing its netname, encrypted DES key and window every
+time. The nickname is most likely an index into a table on the
+server which stores for each client its netname, decrypted DES key
+and window.
+.LP
+Though they originally were synchronized, the client's and server's
+clocks can get out of sync again. When this happens the client RPC
+subsystem most likely will get back
+.I RPC_AUTHERROR
+at which point it should resynchronize.
+.LP
+A client may still get the
+.I RPC_AUTHERROR
+error even though it is
+synchronized with the server. The reason is that the server's
+nickname table is a limited size, and it may flush entries whenever
+it wants. A client should resend its original credential in this
+case and the server will give it a new nickname. If a server
+crashes, the entire nickname table gets flushed, and all clients
+will have to resend their original credentials.
+.KS
+.NH 3
+\&DES Authentication Protocol (in XDR language)
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* There are two kinds of credentials: one in which the client uses
+* its full network name, and one in which it uses its "nickname"
+* (just an unsigned integer) given to it by the server. The
+* client must use its fullname in its first transaction with the
+* server, in which the server will return to the client its
+* nickname. The client may use its nickname in all further
+* transactions with the server. There is no requirement to use the
+* nickname, but it is wise to use it for performance reasons.
+*/
+.ft CW
+enum authdes_namekind {
+ ADN_FULLNAME = 0,
+ ADN_NICKNAME = 1
+};
+
+.ft I
+/*
+* A 64-bit block of encrypted DES data
+*/
+.ft CW
+typedef opaque des_block[8];
+
+.ft I
+/*
+* Maximum length of a network user's name
+*/
+.ft CW
+const MAXNETNAMELEN = 255;
+
+.ft I
+/*
+* A fullname contains the network name of the client, an encrypted
+* conversation key and the window. The window is actually a
+* lifetime for the credential. If the time indicated in the
+* verifier timestamp plus the window has past, then the server
+* should expire the request and not grant it. To insure that
+* requests are not replayed, the server should insist that
+* timestamps are greater than the previous one seen, unless it is
+* the first transaction. In the first transaction, the server
+* checks instead that the window verifier is one less than the
+* window.
+*/
+.ft CW
+struct authdes_fullname {
+string name<MAXNETNAMELEN>; /* \fIname of client \f(CW*/
+des_block key; /* \fIPK encrypted conversation key \f(CW*/
+unsigned int window; /* \fIencrypted window \f(CW*/
+};
+
+.ft I
+/*
+* A credential is either a fullname or a nickname
+*/
+.ft CW
+union authdes_cred switch (authdes_namekind adc_namekind) {
+ case ADN_FULLNAME:
+ authdes_fullname adc_fullname;
+ case ADN_NICKNAME:
+ unsigned int adc_nickname;
+};
+
+.ft I
+/*
+* A timestamp encodes the time since midnight, January 1, 1970.
+*/
+.ft CW
+struct timestamp {
+ unsigned int seconds; /* \fIseconds \fP*/
+ unsigned int useconds; /* \fIand microseconds \fP*/
+};
+
+.ft I
+/*
+* Verifier: client variety
+* The window verifier is only used in the first transaction. In
+* conjunction with a fullname credential, these items are packed
+* into the following structure before being encrypted:
+*
+* \f(CWstruct {\fP
+* \f(CWadv_timestamp; \fP-- one DES block
+* \f(CWadc_fullname.window; \fP-- one half DES block
+* \f(CWadv_winverf; \fP-- one half DES block
+* \f(CW}\fP
+* This structure is encrypted using CBC mode encryption with an
+* input vector of zero. All other encryptions of timestamps use
+* ECB mode encryption.
+*/
+.ft CW
+struct authdes_verf_clnt {
+ timestamp adv_timestamp; /* \fIencrypted timestamp \fP*/
+ unsigned int adv_winverf; /* \fIencrypted window verifier \fP*/
+};
+
+.ft I
+/*
+* Verifier: server variety
+* The server returns (encrypted) the same timestamp the client
+* gave it minus one second. It also tells the client its nickname
+* to be used in future transactions (unencrypted).
+*/
+.ft CW
+struct authdes_verf_svr {
+timestamp adv_timeverf; /* \fIencrypted verifier \fP*/
+unsigned int adv_nickname; /* \fInew nickname for client \fP*/
+};
+.DE
+.KE
+.NH 3
+\&Diffie-Hellman Encryption
+.LP
+In this scheme, there are two constants,
+.I BASE
+and
+.I MODULUS .
+The
+particular values Sun has chosen for these for the DES
+authentication protocol are:
+.ie t .DS
+.el .DS L
+.ft CW
+const BASE = 3;
+const MODULUS =
+ "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"; /* \fIhex \fP*/
+.DE
+.ft R
+The way this scheme works is best explained by an example. Suppose
+there are two people "A" and "B" who want to send encrypted
+messages to each other. So, A and B both generate "secret" keys at
+random which they do not reveal to anyone. Let these keys be
+represented as SK(A) and SK(B). They also publish in a public
+directory their "public" keys. These keys are computed as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+PK(A) = ( BASE ** SK(A) ) mod MODULUS
+PK(B) = ( BASE ** SK(B) ) mod MODULUS
+.DE
+.ft R
+The "**" notation is used here to represent exponentiation. Now,
+both A and B can arrive at the "common" key between them,
+represented here as CK(A, B), without revealing their secret keys.
+.LP
+A computes:
+.ie t .DS
+.el .DS L
+.ft CW
+CK(A, B) = ( PK(B) ** SK(A)) mod MODULUS
+.DE
+.ft R
+while B computes:
+.ie t .DS
+.el .DS L
+.ft CW
+CK(A, B) = ( PK(A) ** SK(B)) mod MODULUS
+.DE
+.ft R
+These two can be shown to be equivalent:
+.ie t .DS
+.el .DS L
+.ft CW
+(PK(B) ** SK(A)) mod MODULUS = (PK(A) ** SK(B)) mod MODULUS
+.DE
+.ft R
+We drop the "mod MODULUS" parts and assume modulo arithmetic to
+simplify things:
+.ie t .DS
+.el .DS L
+.ft CW
+PK(B) ** SK(A) = PK(A) ** SK(B)
+.DE
+.ft R
+Then, replace PK(B) by what B computed earlier and likewise for
+PK(A).
+.ie t .DS
+.el .DS L
+.ft CW
+((BASE ** SK(B)) ** SK(A) = (BASE ** SK(A)) ** SK(B)
+.DE
+.ft R
+which leads to:
+.ie t .DS
+.el .DS L
+.ft CW
+BASE ** (SK(A) * SK(B)) = BASE ** (SK(A) * SK(B))
+.DE
+.ft R
+This common key CK(A, B) is not used to encrypt the timestamps used
+in the protocol. Rather, it is used only to encrypt a conversation
+key which is then used to encrypt the timestamps. The reason for
+doing this is to use the common key as little as possible, for fear
+that it could be broken. Breaking the conversation key is a far
+less serious offense, since conversations are relatively
+short-lived.
+.LP
+The conversation key is encrypted using 56-bit DES keys, yet the
+common key is 192 bits. To reduce the number of bits, 56 bits are
+selected from the common key as follows. The middle-most 8-bytes
+are selected from the common key, and then parity is added to the
+lower order bit of each byte, producing a 56-bit key with 8 bits of
+parity.
+.KS
+.NH 1
+\&Record Marking Standard
+.LP
+When RPC messages are passed on top of a byte stream protocol (like
+TCP/IP), it is necessary, or at least desirable, to delimit one
+message from another in order to detect and possibly recover from
+user protocol errors. This is called record marking (RM). Sun uses
+this RM/TCP/IP transport for passing RPC messages on TCP streams.
+One RPC message fits into one RM record.
+.LP
+A record is composed of one or more record fragments. A record
+fragment is a four-byte header followed by 0 to (2**31) - 1 bytes of
+fragment data. The bytes encode an unsigned binary number; as with
+XDR integers, the byte order is from highest to lowest. The number
+encodes two values\(ema boolean which indicates whether the fragment
+is the last fragment of the record (bit value 1 implies the fragment
+is the last fragment) and a 31-bit unsigned binary value which is the
+length in bytes of the fragment's data. The boolean value is the
+highest-order bit of the header; the length is the 31 low-order bits.
+(Note that this record specification is NOT in XDR standard form!)
+.KE
+.KS
+.NH 1
+\&The RPC Language
+.LP
+Just as there was a need to describe the XDR data-types in a formal
+language, there is also need to describe the procedures that operate
+on these XDR data-types in a formal language as well. We use the RPC
+Language for this purpose. It is an extension to the XDR language.
+The following example is used to describe the essence of the
+language.
+.NH 2
+\&An Example Service Described in the RPC Language
+.LP
+Here is an example of the specification of a simple ping program.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+* Simple ping program
+*/
+.ft CW
+program PING_PROG {
+ /* \fILatest and greatest version\fP */
+ version PING_VERS_PINGBACK {
+ void
+ PINGPROC_NULL(void) = 0;
+
+.ft I
+ /*
+ * Ping the caller, return the round-trip time
+ * (in microseconds). Returns -1 if the operation
+ * timed out.
+ */
+.ft CW
+ int
+ PINGPROC_PINGBACK(void) = 1;
+} = 2;
+
+.ft I
+/*
+* Original version
+*/
+.ft CW
+version PING_VERS_ORIG {
+ void
+ PINGPROC_NULL(void) = 0;
+ } = 1;
+} = 1;
+
+const PING_VERS = 2; /* \fIlatest version \fP*/
+.vs
+.DE
+.KE
+.LP
+The first version described is
+.I PING_VERS_PINGBACK
+with two procedures,
+.I PINGPROC_NULL
+and
+.I PINGPROC_PINGBACK .
+.I PINGPROC_NULL
+takes no arguments and returns no results, but it is useful for
+computing round-trip times from the client to the server and back
+again. By convention, procedure 0 of any RPC protocol should have
+the same semantics, and never require any kind of authentication.
+The second procedure is used for the client to have the server do a
+reverse ping operation back to the client, and it returns the amount
+of time (in microseconds) that the operation used. The next version,
+.I PING_VERS_ORIG ,
+is the original version of the protocol
+and it does not contain
+.I PINGPROC_PINGBACK
+procedure. It is useful
+for compatibility with old client programs, and as this program
+matures it may be dropped from the protocol entirely.
+.KS
+.NH 2
+\&The RPC Language Specification
+.LP
+The RPC language is identical to the XDR language, except for the
+added definition of a
+.I program-def
+described below.
+.DS
+.ft CW
+program-def:
+ "program" identifier "{"
+ version-def
+ version-def *
+ "}" "=" constant ";"
+
+version-def:
+ "version" identifier "{"
+ procedure-def
+ procedure-def *
+ "}" "=" constant ";"
+
+procedure-def:
+ type-specifier identifier "(" type-specifier ")"
+ "=" constant ";"
+.DE
+.KE
+.NH 2
+\&Syntax Notes
+.IP 1.
+The following keywords are added and cannot be used as
+identifiers: "program" and "version";
+.IP 2.
+A version name cannot occur more than once within the scope of
+a program definition. Nor can a version number occur more than once
+within the scope of a program definition.
+.IP 3.
+A procedure name cannot occur more than once within the scope
+of a version definition. Nor can a procedure number occur more than
+once within the scope of version definition.
+.IP 4.
+Program identifiers are in the same name space as constant and
+type identifiers.
+.IP 5.
+Only unsigned constants can be assigned to programs, versions
+and procedures.
+.NH 1
+\&Port Mapper Program Protocol
+.LP
+The port mapper program maps RPC program and version numbers to
+transport-specific port numbers. This program makes dynamic binding
+of remote programs possible.
+.LP
+This is desirable because the range of reserved port numbers is very
+small and the number of potential remote programs is very large. By
+running only the port mapper on a reserved port, the port numbers of
+other remote programs can be ascertained by querying the port mapper.
+.LP
+The port mapper also aids in broadcast RPC. A given RPC program will
+usually have different port number bindings on different machines, so
+there is no way to directly broadcast to all of these programs. The
+port mapper, however, does have a fixed port number. So, to
+broadcast to a given program, the client actually sends its message
+to the port mapper located at the broadcast address. Each port
+mapper that picks up the broadcast then calls the local service
+specified by the client. When the port mapper gets the reply from
+the local service, it sends the reply on back to the client.
+.KS
+.NH 2
+\&Port Mapper Protocol Specification (in RPC Language)
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+const PMAP_PORT = 111; /* \fIportmapper port number \fP*/
+
+.ft I
+/*
+* A mapping of (program, version, protocol) to port number
+*/
+.ft CW
+struct mapping {
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int prot;
+ unsigned int port;
+};
+
+.ft I
+/*
+* Supported values for the "prot" field
+*/
+.ft CW
+const IPPROTO_TCP = 6; /* \fIprotocol number for TCP/IP \fP*/
+const IPPROTO_UDP = 17; /* \fIprotocol number for UDP/IP \fP*/
+
+.ft I
+/*
+* A list of mappings
+*/
+.ft CW
+struct *pmaplist {
+ mapping map;
+ pmaplist next;
+};
+.vs
+.DE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+* Arguments to callit
+*/
+.ft CW
+struct call_args {
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int proc;
+ opaque args<>;
+};
+
+.ft I
+/*
+* Results of callit
+*/
+.ft CW
+struct call_result {
+ unsigned int port;
+ opaque res<>;
+};
+.vs
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+* Port mapper procedures
+*/
+.ft CW
+program PMAP_PROG {
+ version PMAP_VERS {
+ void
+ PMAPPROC_NULL(void) = 0;
+
+ bool
+ PMAPPROC_SET(mapping) = 1;
+
+ bool
+ PMAPPROC_UNSET(mapping) = 2;
+
+ unsigned int
+ PMAPPROC_GETPORT(mapping) = 3;
+
+ pmaplist
+ PMAPPROC_DUMP(void) = 4;
+
+ call_result
+ PMAPPROC_CALLIT(call_args) = 5;
+ } = 2;
+} = 100000;
+.vs
+.DE
+.NH 2
+\&Port Mapper Operation
+.LP
+The portmapper program currently supports two protocols (UDP/IP and
+TCP/IP). The portmapper is contacted by talking to it on assigned
+port number 111 (SUNRPC [8]) on either of these protocols. The
+following is a description of each of the portmapper procedures:
+.IP \fBPMAPPROC_NULL:\fP
+This procedure does no work. By convention, procedure zero of any
+protocol takes no parameters and returns no results.
+.IP \fBPMAPPROC_SET:\fP
+When a program first becomes available on a machine, it registers
+itself with the port mapper program on the same machine. The program
+passes its program number "prog", version number "vers", transport
+protocol number "prot", and the port "port" on which it awaits
+service request. The procedure returns a boolean response whose
+value is
+.I TRUE
+if the procedure successfully established the mapping and
+.I FALSE
+otherwise. The procedure refuses to establish
+a mapping if one already exists for the tuple "(prog, vers, prot)".
+.IP \fBPMAPPROC_UNSET:\fP
+When a program becomes unavailable, it should unregister itself with
+the port mapper program on the same machine. The parameters and
+results have meanings identical to those of
+.I PMAPPROC_SET .
+The protocol and port number fields of the argument are ignored.
+.IP \fBPMAPPROC_GETPORT:\fP
+Given a program number "prog", version number "vers", and transport
+protocol number "prot", this procedure returns the port number on
+which the program is awaiting call requests. A port value of zeros
+means the program has not been registered. The "port" field of the
+argument is ignored.
+.IP \fBPMAPPROC_DUMP:\fP
+This procedure enumerates all entries in the port mapper's database.
+The procedure takes no parameters and returns a list of program,
+version, protocol, and port values.
+.IP \fBPMAPPROC_CALLIT:\fP
+This procedure allows a caller to call another remote procedure on
+the same machine without knowing the remote procedure's port number.
+It is intended for supporting broadcasts to arbitrary remote programs
+via the well-known port mapper's port. The parameters "prog",
+"vers", "proc", and the bytes of "args" are the program number,
+version number, procedure number, and parameters of the remote
+procedure.
+.LP
+.B Note:
+.RS
+.IP 1.
+This procedure only sends a response if the procedure was
+successfully executed and is silent (no response) otherwise.
+.IP 2.
+The port mapper communicates with the remote program using UDP/IP
+only.
+.RE
+.LP
+The procedure returns the remote program's port number, and the bytes
+of results are the results of the remote procedure.
+.bp
+.NH 1
+\&References
+.LP
+[1] Birrell, Andrew D. & Nelson, Bruce Jay; "Implementing Remote
+Procedure Calls"; XEROX CSL-83-7, October 1983.
+.LP
+[2] Cheriton, D.; "VMTP: Versatile Message Transaction Protocol",
+Preliminary Version 0.3; Stanford University, January 1987.
+.LP
+[3] Diffie & Hellman; "New Directions in Cryptography"; IEEE
+Transactions on Information Theory IT-22, November 1976.
+.LP
+[4] Harrenstien, K.; "Time Server", RFC 738; Information Sciences
+Institute, October 1977.
+.LP
+[5] National Bureau of Standards; "Data Encryption Standard"; Federal
+Information Processing Standards Publication 46, January 1977.
+.LP
+[6] Postel, J.; "Transmission Control Protocol - DARPA Internet
+Program Protocol Specification", RFC 793; Information Sciences
+Institute, September 1981.
+.LP
+[7] Postel, J.; "User Datagram Protocol", RFC 768; Information Sciences
+Institute, August 1980.
+.LP
+[8] Reynolds, J. & Postel, J.; "Assigned Numbers", RFC 923; Information
+Sciences Institute, October 1984.
diff --git a/share/doc/psd/26.rpcrfc/stubs b/share/doc/psd/26.rpcrfc/stubs
new file mode 100644
index 0000000..78b0a2c
--- /dev/null
+++ b/share/doc/psd/26.rpcrfc/stubs
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+.\"
+.if t .ftr L CR
diff --git a/share/doc/psd/27.nfsrpc/Makefile b/share/doc/psd/27.nfsrpc/Makefile
index 5904787..c9d4f23 100644
--- a/share/doc/psd/27.nfsrpc/Makefile
+++ b/share/doc/psd/27.nfsrpc/Makefile
@@ -4,6 +4,5 @@ VOLUME= psd/27.nfsrfc
SRCS= stubs nfs.rfc.ms
MACROS= -ms
USE_TBL=
-SRCDIR= ${.CURDIR}/../../../../lib/libc/rpc/PSD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/psd/27.nfsrpc/nfs.rfc.ms b/share/doc/psd/27.nfsrpc/nfs.rfc.ms
new file mode 100644
index 0000000..13d7619
--- /dev/null
+++ b/share/doc/psd/27.nfsrpc/nfs.rfc.ms
@@ -0,0 +1,1374 @@
+.\"
+.\" Must use -- tbl -- with this one
+.\"
+.\" @(#)nfs.rfc.ms 2.2 88/08/05 4.0 RPCSRC
+.\" $FreeBSD$
+.\"
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'Network File System: Version 2 Protocol Specification''Page %'
+.EH 'Page %''Network File System: Version 2 Protocol Specification'
+.if \n%=1 .bp
+.SH
+\&Network File System: Version 2 Protocol Specification
+.IX NFS "" "" "" PAGE MAJOR
+.IX "Network File System" "" "" "" PAGE MAJOR
+.IX NFS "version-2 protocol specification"
+.IX "Network File System" "version-2 protocol specification"
+.LP
+.NH 0
+\&Status of this Standard
+.LP
+Note: This document specifies a protocol that Sun Microsystems, Inc.,
+and others are using. It specifies it in standard ARPA RFC form.
+.NH 1
+\&Introduction
+.IX NFS introduction
+.LP
+The Sun Network Filesystem (NFS) protocol provides transparent remote
+access to shared filesystems over local area networks. The NFS
+protocol is designed to be machine, operating system, network architecture,
+and transport protocol independent. This independence is
+achieved through the use of Remote Procedure Call (RPC) primitives
+built on top of an External Data Representation (XDR). Implementations
+exist for a variety of machines, from personal computers to
+supercomputers.
+.LP
+The supporting mount protocol allows the server to hand out remote
+access privileges to a restricted set of clients. It performs the
+operating system-specific functions that allow, for example, to
+attach remote directory trees to some local file system.
+.NH 2
+\&Remote Procedure Call
+.IX "Remote Procedure Call"
+.LP
+Sun's remote procedure call specification provides a procedure-
+oriented interface to remote services. Each server supplies a
+program that is a set of procedures. NFS is one such "program".
+The combination of host address, program number, and procedure
+number specifies one remote service procedure. RPC does not depend
+on services provided by specific protocols, so it can be used with
+any underlying transport protocol. See the
+.I "Remote Procedure Calls: Protocol Specification"
+chapter of this manual.
+.NH 2
+\&External Data Representation
+.IX "External Data Representation"
+.LP
+The External Data Representation (XDR) standard provides a common
+way of representing a set of data types over a network.
+The NFS
+Protocol Specification is written using the RPC data description
+language.
+For more information, see the
+.I " External Data Representation Standard: Protocol Specification."
+Sun provides implementations of XDR and
+RPC, but NFS does not require their use. Any software that
+provides equivalent functionality can be used, and if the encoding
+is exactly the same it can interoperate with other implementations
+of NFS.
+.NH 2
+\&Stateless Servers
+.IX "stateless servers"
+.IX servers stateless
+.LP
+The NFS protocol is stateless. That is, a server does not need to
+maintain any extra state information about any of its clients in
+order to function correctly. Stateless servers have a distinct
+advantage over stateful servers in the event of a failure. With
+stateless servers, a client need only retry a request until the
+server responds; it does not even need to know that the server has
+crashed, or the network temporarily went down. The client of a
+stateful server, on the other hand, needs to either detect a server
+crash and rebuild the server's state when it comes back up, or
+cause client operations to fail.
+.LP
+This may not sound like an important issue, but it affects the
+protocol in some unexpected ways. We feel that it is worth a bit
+of extra complexity in the protocol to be able to write very simple
+servers that do not require fancy crash recovery.
+.LP
+On the other hand, NFS deals with objects such as files and
+directories that inherently have state -- what good would a file be
+if it did not keep its contents intact? The goal is to not
+introduce any extra state in the protocol itself. Another way to
+simplify recovery is by making operations "idempotent" whenever
+possible (so that they can potentially be repeated).
+.NH 1
+\&NFS Protocol Definition
+.IX NFS "protocol definition"
+.IX NFS protocol
+.LP
+Servers have been known to change over time, and so can the
+protocol that they use. So RPC provides a version number with each
+RPC request. This RFC describes version two of the NFS protocol.
+Even in the second version, there are various obsolete procedures
+and parameters, which will be removed in later versions. An RFC
+for version three of the NFS protocol is currently under
+preparation.
+.NH 2
+\&File System Model
+.IX filesystem model
+.LP
+NFS assumes a file system that is hierarchical, with directories as
+all but the bottom-level files. Each entry in a directory (file,
+directory, device, etc.) has a string name. Different operating
+systems may have restrictions on the depth of the tree or the names
+used, as well as using different syntax to represent the "pathname",
+which is the concatenation of all the "components" (directory and
+file names) in the name. A "file system" is a tree on a single
+server (usually a single disk or physical partition) with a specified
+"root". Some operating systems provide a "mount" operation to make
+all file systems appear as a single tree, while others maintain a
+"forest" of file systems. Files are unstructured streams of
+uninterpreted bytes. Version 3 of NFS uses a slightly more general
+file system model.
+.LP
+NFS looks up one component of a pathname at a time. It may not be
+obvious why it does not just take the whole pathname, traipse down
+the directories, and return a file handle when it is done. There are
+several good reasons not to do this. First, pathnames need
+separators between the directory components, and different operating
+systems use different separators. We could define a Network Standard
+Pathname Representation, but then every pathname would have to be
+parsed and converted at each end. Other issues are discussed in
+\fINFS Implementation Issues\fP below.
+.LP
+Although files and directories are similar objects in many ways,
+different procedures are used to read directories and files. This
+provides a network standard format for representing directories. The
+same argument as above could have been used to justify a procedure
+that returns only one directory entry per call. The problem is
+efficiency. Directories can contain many entries, and a remote call
+to return each would be just too slow.
+.NH 2
+\&RPC Information
+.IX NFS "RPC information"
+.IP \fIAuthentication\fP
+The NFS service uses
+.I AUTH_UNIX ,
+.I AUTH_DES ,
+or
+.I AUTH_SHORT
+style
+authentication, except in the NULL procedure where
+.I AUTH_NONE
+is also allowed.
+.IP "\fITransport Protocols\fP"
+NFS currently is supported on UDP/IP only.
+.IP "\fIPort Number\fP"
+The NFS protocol currently uses the UDP port number 2049. This is
+not an officially assigned port, so later versions of the protocol
+use the \*QPortmapping\*U facility of RPC.
+.NH 2
+\&Sizes of XDR Structures
+.IX "XDR structure sizes"
+.LP
+These are the sizes, given in decimal bytes, of various XDR
+structures used in the protocol:
+.DS
+/* \fIThe maximum number of bytes of data in a READ or WRITE request\fP */
+const MAXDATA = 8192;
+
+/* \fIThe maximum number of bytes in a pathname argument\fP */
+const MAXPATHLEN = 1024;
+
+/* \fIThe maximum number of bytes in a file name argument\fP */
+const MAXNAMLEN = 255;
+
+/* \fIThe size in bytes of the opaque "cookie" passed by READDIR\fP */
+const COOKIESIZE = 4;
+
+/* \fIThe size in bytes of the opaque file handle\fP */
+const FHSIZE = 32;
+.DE
+.NH 2
+\&Basic Data Types
+.IX "NFS data types"
+.IX NFS "basic data types"
+.LP
+The following XDR definitions are basic structures and types used
+in other structures described further on.
+.KS
+.NH 3
+\&stat
+.IX "NFS data types" stat "" \fIstat\fP
+.DS
+enum stat {
+ NFS_OK = 0,
+ NFSERR_PERM=1,
+ NFSERR_NOENT=2,
+ NFSERR_IO=5,
+ NFSERR_NXIO=6,
+ NFSERR_ACCES=13,
+ NFSERR_EXIST=17,
+ NFSERR_NODEV=19,
+ NFSERR_NOTDIR=20,
+ NFSERR_ISDIR=21,
+ NFSERR_FBIG=27,
+ NFSERR_NOSPC=28,
+ NFSERR_ROFS=30,
+ NFSERR_NAMETOOLONG=63,
+ NFSERR_NOTEMPTY=66,
+ NFSERR_DQUOT=69,
+ NFSERR_STALE=70,
+ NFSERR_WFLUSH=99
+};
+.DE
+.KE
+.LP
+The
+.I stat
+type is returned with every procedure's results. A
+value of
+.I NFS_OK
+indicates that the call completed successfully and
+the results are valid. The other values indicate some kind of
+error occurred on the server side during the servicing of the
+procedure. The error values are derived from UNIX error numbers.
+.IP \fBNFSERR_PERM\fP:
+Not owner. The caller does not have correct ownership
+to perform the requested operation.
+.IP \fBNFSERR_NOENT\fP:
+No such file or directory. The file or directory
+specified does not exist.
+.IP \fBNFSERR_IO\fP:
+Some sort of hard error occurred when the operation was
+in progress. This could be a disk error, for example.
+.IP \fBNFSERR_NXIO\fP:
+No such device or address.
+.IP \fBNFSERR_ACCES\fP:
+Permission denied. The caller does not have the
+correct permission to perform the requested operation.
+.IP \fBNFSERR_EXIST\fP:
+File exists. The file specified already exists.
+.IP \fBNFSERR_NODEV\fP:
+No such device.
+.IP \fBNFSERR_NOTDIR\fP:
+Not a directory. The caller specified a
+non-directory in a directory operation.
+.IP \fBNFSERR_ISDIR\fP:
+Is a directory. The caller specified a directory in
+a non- directory operation.
+.IP \fBNFSERR_FBIG\fP:
+File too large. The operation caused a file to grow
+beyond the server's limit.
+.IP \fBNFSERR_NOSPC\fP:
+No space left on device. The operation caused the
+server's filesystem to reach its limit.
+.IP \fBNFSERR_ROFS\fP:
+Read-only filesystem. Write attempted on a read-only filesystem.
+.IP \fBNFSERR_NAMETOOLONG\fP:
+File name too long. The file name in an operation was too long.
+.IP \fBNFSERR_NOTEMPTY\fP:
+Directory not empty. Attempted to remove a
+directory that was not empty.
+.IP \fBNFSERR_DQUOT\fP:
+Disk quota exceeded. The client's disk quota on the
+server has been exceeded.
+.IP \fBNFSERR_STALE\fP:
+The "fhandle" given in the arguments was invalid.
+That is, the file referred to by that file handle no longer exists,
+or access to it has been revoked.
+.IP \fBNFSERR_WFLUSH\fP:
+The server's write cache used in the
+.I WRITECACHE
+call got flushed to disk.
+.LP
+.KS
+.NH 3
+\&ftype
+.IX "NFS data types" ftype "" \fIftype\fP
+.DS
+enum ftype {
+ NFNON = 0,
+ NFREG = 1,
+ NFDIR = 2,
+ NFBLK = 3,
+ NFCHR = 4,
+ NFLNK = 5
+};
+.DE
+.KE
+The enumeration
+.I ftype
+gives the type of a file. The type
+.I NFNON
+indicates a non-file,
+.I NFREG
+is a regular file,
+.I NFDIR
+is a directory,
+.I NFBLK
+is a block-special device,
+.I NFCHR
+is a character-special device, and
+.I NFLNK
+is a symbolic link.
+.KS
+.NH 3
+\&fhandle
+.IX "NFS data types" fhandle "" \fIfhandle\fP
+.DS
+typedef opaque fhandle[FHSIZE];
+.DE
+.KE
+The
+.I fhandle
+is the file handle passed between the server and the client.
+All file operations are done using file handles to refer to a file or
+directory. The file handle can contain whatever information the server
+needs to distinguish an individual file.
+.KS
+.NH 3
+\&timeval
+.IX "NFS data types" timeval "" \fItimeval\fP
+.DS
+struct timeval {
+ unsigned int seconds;
+ unsigned int useconds;
+};
+.DE
+.KE
+The
+.I timeval
+structure is the number of seconds and microseconds
+since midnight January 1, 1970, Greenwich Mean Time. It is used to
+pass time and date information.
+.KS
+.NH 3
+\&fattr
+.IX "NFS data types" fattr "" \fIfattr\fP
+.DS
+struct fattr {
+ ftype type;
+ unsigned int mode;
+ unsigned int nlink;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int size;
+ unsigned int blocksize;
+ unsigned int rdev;
+ unsigned int blocks;
+ unsigned int fsid;
+ unsigned int fileid;
+ timeval atime;
+ timeval mtime;
+ timeval ctime;
+};
+.DE
+.KE
+The
+.I fattr
+structure contains the attributes of a file; "type" is the type of
+the file; "nlink" is the number of hard links to the file (the number
+of different names for the same file); "uid" is the user
+identification number of the owner of the file; "gid" is the group
+identification number of the group of the file; "size" is the size in
+bytes of the file; "blocksize" is the size in bytes of a block of the
+file; "rdev" is the device number of the file if it is type
+.I NFCHR
+or
+.I NFBLK ;
+"blocks" is the number of blocks the file takes up on disk; "fsid" is
+the file system identifier for the filesystem containing the file;
+"fileid" is a number that uniquely identifies the file within its
+filesystem; "atime" is the time when the file was last accessed for
+either read or write; "mtime" is the time when the file data was last
+modified (written); and "ctime" is the time when the status of the
+file was last changed. Writing to the file also changes "ctime" if
+the size of the file changes.
+.LP
+"mode" is the access mode encoded as a set of bits. Notice that the
+file type is specified both in the mode bits and in the file type.
+This is really a bug in the protocol and will be fixed in future
+versions. The descriptions given below specify the bit positions
+using octal numbers.
+.TS
+box tab (&) ;
+cfI cfI
+lfL l .
+Bit&Description
+_
+0040000&This is a directory; "type" field should be NFDIR.
+0020000&This is a character special file; "type" field should be NFCHR.
+0060000&This is a block special file; "type" field should be NFBLK.
+0100000&This is a regular file; "type" field should be NFREG.
+0120000&This is a symbolic link file; "type" field should be NFLNK.
+0140000&This is a named socket; "type" field should be NFNON.
+0004000&Set user id on execution.
+0002000&Set group id on execution.
+0001000&Save swapped text even after use.
+0000400&Read permission for owner.
+0000200&Write permission for owner.
+0000100&Execute and search permission for owner.
+0000040&Read permission for group.
+0000020&Write permission for group.
+0000010&Execute and search permission for group.
+0000004&Read permission for others.
+0000002&Write permission for others.
+0000001&Execute and search permission for others.
+.TE
+.KS
+Notes:
+.IP
+The bits are the same as the mode bits returned by the
+.I stat(2)
+system call in the UNIX system. The file type is specified both in
+the mode bits and in the file type. This is fixed in future
+versions.
+.IP
+The "rdev" field in the attributes structure is an operating system
+specific device specifier. It will be removed and generalized in
+the next revision of the protocol.
+.KE
+.LP
+.KS
+.NH 3
+\&sattr
+.IX "NFS data types" sattr "" \fIsattr\fP
+.DS
+struct sattr {
+ unsigned int mode;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int size;
+ timeval atime;
+ timeval mtime;
+};
+.DE
+.KE
+The
+.I sattr
+structure contains the file attributes which can be set
+from the client. The fields are the same as for
+.I fattr
+above. A "size" of zero means the file should be truncated.
+A value of -1 indicates a field that should be ignored.
+.LP
+.KS
+.NH 3
+\&filename
+.IX "NFS data types" filename "" \fIfilename\fP
+.DS
+typedef string filename<MAXNAMLEN>;
+.DE
+.KE
+The type
+.I filename
+is used for passing file names or pathname components.
+.LP
+.KS
+.NH 3
+\&path
+.IX "NFS data types" path "" \fIpath\fP
+.DS
+typedef string path<MAXPATHLEN>;
+.DE
+.KE
+The type
+.I path
+is a pathname. The server considers it as a string
+with no internal structure, but to the client it is the name of a
+node in a filesystem tree.
+.LP
+.KS
+.NH 3
+\&attrstat
+.IX "NFS data types" attrstat "" \fIattrstat\fP
+.DS
+union attrstat switch (stat status) {
+ case NFS_OK:
+ fattr attributes;
+ default:
+ void;
+};
+.DE
+.KE
+The
+.I attrstat
+structure is a common procedure result. It contains
+a "status" and, if the call succeeded, it also contains the
+attributes of the file on which the operation was done.
+.LP
+.KS
+.NH 3
+\&diropargs
+.IX "NFS data types" diropargs "" \fIdiropargs\fP
+.DS
+struct diropargs {
+ fhandle dir;
+ filename name;
+};
+.DE
+.KE
+The
+.I diropargs
+structure is used in directory operations. The
+"fhandle" "dir" is the directory in which to find the file "name".
+A directory operation is one in which the directory is affected.
+.LP
+.KS
+.NH 3
+\&diropres
+.IX "NFS data types" diropres "" \fIdiropres\fP
+.DS
+union diropres switch (stat status) {
+ case NFS_OK:
+ struct {
+ fhandle file;
+ fattr attributes;
+ } diropok;
+ default:
+ void;
+};
+.DE
+.KE
+The results of a directory operation are returned in a
+.I diropres
+structure. If the call succeeded, a new file handle "file" and the
+"attributes" associated with that file are returned along with the
+"status".
+.NH 2
+\&Server Procedures
+.IX "NFS server procedures" "" "" "" PAGE MAJOR
+.LP
+The protocol definition is given as a set of procedures with
+arguments and results defined using the RPC language. A brief
+description of the function of each procedure should provide enough
+information to allow implementation.
+.LP
+All of the procedures in the NFS protocol are assumed to be
+synchronous. When a procedure returns to the client, the client
+can assume that the operation has completed and any data associated
+with the request is now on stable storage. For example, a client
+.I WRITE
+request may cause the server to update data blocks,
+filesystem information blocks (such as indirect blocks), and file
+attribute information (size and modify times). When the
+.I WRITE
+returns to the client, it can assume that the write is safe, even
+in case of a server crash, and it can discard the data written.
+This is a very important part of the statelessness of the server.
+If the server waited to flush data from remote requests, the client
+would have to save those requests so that it could resend them in
+case of a server crash.
+.ie t .DS
+.el .DS L
+
+.ft I
+/*
+* Remote file service routines
+*/
+.ft CW
+program NFS_PROGRAM {
+ version NFS_VERSION {
+ void NFSPROC_NULL(void) = 0;
+ attrstat NFSPROC_GETATTR(fhandle) = 1;
+ attrstat NFSPROC_SETATTR(sattrargs) = 2;
+ void NFSPROC_ROOT(void) = 3;
+ diropres NFSPROC_LOOKUP(diropargs) = 4;
+ readlinkres NFSPROC_READLINK(fhandle) = 5;
+ readres NFSPROC_READ(readargs) = 6;
+ void NFSPROC_WRITECACHE(void) = 7;
+ attrstat NFSPROC_WRITE(writeargs) = 8;
+ diropres NFSPROC_CREATE(createargs) = 9;
+ stat NFSPROC_REMOVE(diropargs) = 10;
+ stat NFSPROC_RENAME(renameargs) = 11;
+ stat NFSPROC_LINK(linkargs) = 12;
+ stat NFSPROC_SYMLINK(symlinkargs) = 13;
+ diropres NFSPROC_MKDIR(createargs) = 14;
+ stat NFSPROC_RMDIR(diropargs) = 15;
+ readdirres NFSPROC_READDIR(readdirargs) = 16;
+ statfsres NFSPROC_STATFS(fhandle) = 17;
+ } = 2;
+} = 100003;
+.DE
+.KS
+.NH 3
+\&Do Nothing
+.IX "NFS server procedures" NFSPROC_NULL() "" \fINFSPROC_NULL()\fP
+.DS
+void
+NFSPROC_NULL(void) = 0;
+.DE
+.KE
+This procedure does no work. It is made available in all RPC
+services to allow server response testing and timing.
+.KS
+.NH 3
+\&Get File Attributes
+.IX "NFS server procedures" NFSPROC_GETATTR() "" \fINFSPROC_GETATTR()\fP
+.DS
+attrstat
+NFSPROC_GETATTR (fhandle) = 1;
+.DE
+.KE
+If the reply status is
+.I NFS_OK ,
+then the reply attributes contains
+the attributes for the file given by the input fhandle.
+.KS
+.NH 3
+\&Set File Attributes
+.IX "NFS server procedures" NFSPROC_SETATTR() "" \fINFSPROC_SETATTR()\fP
+.DS
+struct sattrargs {
+ fhandle file;
+ sattr attributes;
+ };
+
+attrstat
+NFSPROC_SETATTR (sattrargs) = 2;
+.DE
+.KE
+The "attributes" argument contains fields which are either -1 or
+are the new value for the attributes of "file". If the reply
+status is
+.I NFS_OK ,
+then the reply attributes have the attributes of
+the file after the "SETATTR" operation has completed.
+.LP
+Note: The use of -1 to indicate an unused field in "attributes" is
+changed in the next version of the protocol.
+.KS
+.NH 3
+\&Get Filesystem Root
+.IX "NFS server procedures" NFSPROC_ROOT "" \fINFSPROC_ROOT\fP
+.DS
+void
+NFSPROC_ROOT(void) = 3;
+.DE
+.KE
+Obsolete. This procedure is no longer used because finding the
+root file handle of a filesystem requires moving pathnames between
+client and server. To do this right we would have to define a
+network standard representation of pathnames. Instead, the
+function of looking up the root file handle is done by the
+.I MNTPROC_MNT()
+procedure. (See the
+.I "Mount Protocol Definition"
+later in this chapter for details).
+.KS
+.NH 3
+\&Look Up File Name
+.IX "NFS server procedures" NFSPROC_LOOKUP() "" \fINFSPROC_LOOKUP()\fP
+.DS
+diropres
+NFSPROC_LOOKUP(diropargs) = 4;
+.DE
+.KE
+If the reply "status" is
+.I NFS_OK ,
+then the reply "file" and reply
+"attributes" are the file handle and attributes for the file "name"
+in the directory given by "dir" in the argument.
+.KS
+.NH 3
+\&Read From Symbolic Link
+.IX "NFS server procedures" NFSPROC_READLINK() "" \fINFSPROC_READLINK()\fP
+.DS
+union readlinkres switch (stat status) {
+ case NFS_OK:
+ path data;
+ default:
+ void;
+};
+
+readlinkres
+NFSPROC_READLINK(fhandle) = 5;
+.DE
+.KE
+If "status" has the value
+.I NFS_OK ,
+then the reply "data" is the data in
+the symbolic link given by the file referred to by the fhandle argument.
+.LP
+Note: since NFS always parses pathnames on the client, the
+pathname in a symbolic link may mean something different (or be
+meaningless) on a different client or on the server if a different
+pathname syntax is used.
+.KS
+.NH 3
+\&Read From File
+.IX "NFS server procedures" NFSPROC_READ "" \fINFSPROC_READ\fP
+.DS
+struct readargs {
+ fhandle file;
+ unsigned offset;
+ unsigned count;
+ unsigned totalcount;
+};
+
+union readres switch (stat status) {
+ case NFS_OK:
+ fattr attributes;
+ opaque data<NFS_MAXDATA>;
+ default:
+ void;
+};
+
+readres
+NFSPROC_READ(readargs) = 6;
+.DE
+.KE
+Returns up to "count" bytes of "data" from the file given by
+"file", starting at "offset" bytes from the beginning of the file.
+The first byte of the file is at offset zero. The file attributes
+after the read takes place are returned in "attributes".
+.LP
+Note: The argument "totalcount" is unused, and is removed in the
+next protocol revision.
+.KS
+.NH 3
+\&Write to Cache
+.IX "NFS server procedures" NFSPROC_WRITECACHE() "" \fINFSPROC_WRITECACHE()\fP
+.DS
+void
+NFSPROC_WRITECACHE(void) = 7;
+.DE
+.KE
+To be used in the next protocol revision.
+.KS
+.NH 3
+\&Write to File
+.IX "NFS server procedures" NFSPROC_WRITE() "" \fINFSPROC_WRITE()\fP
+.DS
+struct writeargs {
+ fhandle file;
+ unsigned beginoffset;
+ unsigned offset;
+ unsigned totalcount;
+ opaque data<NFS_MAXDATA>;
+};
+
+attrstat
+NFSPROC_WRITE(writeargs) = 8;
+.DE
+.KE
+Writes "data" beginning "offset" bytes from the beginning of
+"file". The first byte of the file is at offset zero. If the
+reply "status" is NFS_OK, then the reply "attributes" contains the
+attributes of the file after the write has completed. The write
+operation is atomic. Data from this call to
+.I WRITE
+will not be mixed with data from another client's calls.
+.LP
+Note: The arguments "beginoffset" and "totalcount" are ignored and
+are removed in the next protocol revision.
+.KS
+.NH 3
+\&Create File
+.IX "NFS server procedures" NFSPROC_CREATE() "" \fINFSPROC_CREATE()\fP
+.DS
+struct createargs {
+ diropargs where;
+ sattr attributes;
+};
+
+diropres
+NFSPROC_CREATE(createargs) = 9;
+.DE
+.KE
+The file "name" is created in the directory given by "dir". The
+initial attributes of the new file are given by "attributes". A
+reply "status" of NFS_OK indicates that the file was created, and
+reply "file" and reply "attributes" are its file handle and
+attributes. Any other reply "status" means that the operation
+failed and no file was created.
+.LP
+Note: This routine should pass an exclusive create flag, meaning
+"create the file only if it is not already there".
+.KS
+.NH 3
+\&Remove File
+.IX "NFS server procedures" NFSPROC_REMOVE() "" \fINFSPROC_REMOVE()\fP
+.DS
+stat
+NFSPROC_REMOVE(diropargs) = 10;
+.DE
+.KE
+The file "name" is removed from the directory given by "dir". A
+reply of NFS_OK means the directory entry was removed.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Rename File
+.IX "NFS server procedures" NFSPROC_RENAME() "" \fINFSPROC_RENAME()\fP
+.DS
+struct renameargs {
+ diropargs from;
+ diropargs to;
+};
+
+stat
+NFSPROC_RENAME(renameargs) = 11;
+.DE
+.KE
+The existing file "from.name" in the directory given by "from.dir"
+is renamed to "to.name" in the directory given by "to.dir". If the
+reply is
+.I NFS_OK ,
+the file was renamed. The
+RENAME
+operation is
+atomic on the server; it cannot be interrupted in the middle.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Create Link to File
+.IX "NFS server procedures" NFSPROC_LINK() "" \fINFSPROC_LINK()\fP
+.DS
+struct linkargs {
+ fhandle from;
+ diropargs to;
+};
+
+stat
+NFSPROC_LINK(linkargs) = 12;
+.DE
+.KE
+Creates the file "to.name" in the directory given by "to.dir",
+which is a hard link to the existing file given by "from". If the
+return value is
+.I NFS_OK ,
+a link was created. Any other return value
+indicates an error, and the link was not created.
+.LP
+A hard link should have the property that changes to either of the
+linked files are reflected in both files. When a hard link is made
+to a file, the attributes for the file should have a value for
+"nlink" that is one greater than the value before the link.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Create Symbolic Link
+.IX "NFS server procedures" NFSPROC_SYMLINK() "" \fINFSPROC_SYMLINK()\fP
+.DS
+struct symlinkargs {
+ diropargs from;
+ path to;
+ sattr attributes;
+};
+
+stat
+NFSPROC_SYMLINK(symlinkargs) = 13;
+.DE
+.KE
+Creates the file "from.name" with ftype
+.I NFLNK
+in the directory
+given by "from.dir". The new file contains the pathname "to" and
+has initial attributes given by "attributes". If the return value
+is
+.I NFS_OK ,
+a link was created. Any other return value indicates an
+error, and the link was not created.
+.LP
+A symbolic link is a pointer to another file. The name given in
+"to" is not interpreted by the server, only stored in the newly
+created file. When the client references a file that is a symbolic
+link, the contents of the symbolic link are normally transparently
+reinterpreted as a pathname to substitute. A
+.I READLINK
+operation returns the data to the client for interpretation.
+.LP
+Note: On UNIX servers the attributes are never used, since
+symbolic links always have mode 0777.
+.KS
+.NH 3
+\&Create Directory
+.IX "NFS server procedures" NFSPROC_MKDIR() "" \fINFSPROC_MKDIR()\fP
+.DS
+diropres
+NFSPROC_MKDIR (createargs) = 14;
+.DE
+.KE
+The new directory "where.name" is created in the directory given by
+"where.dir". The initial attributes of the new directory are given
+by "attributes". A reply "status" of NFS_OK indicates that the new
+directory was created, and reply "file" and reply "attributes" are
+its file handle and attributes. Any other reply "status" means
+that the operation failed and no directory was created.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Remove Directory
+.IX "NFS server procedures" NFSPROC_RMDIR() "" \fINFSPROC_RMDIR()\fP
+.DS
+stat
+NFSPROC_RMDIR(diropargs) = 15;
+.DE
+.KE
+The existing empty directory "name" in the directory given by "dir"
+is removed. If the reply is
+.I NFS_OK ,
+the directory was removed.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Read From Directory
+.IX "NFS server procedures" NFSPROC_READDIR() "" \fINFSPROC_READDIR()\fP
+.DS
+struct readdirargs {
+ fhandle dir;
+ nfscookie cookie;
+ unsigned count;
+};
+
+struct entry {
+ unsigned fileid;
+ filename name;
+ nfscookie cookie;
+ entry *nextentry;
+};
+
+union readdirres switch (stat status) {
+ case NFS_OK:
+ struct {
+ entry *entries;
+ bool eof;
+ } readdirok;
+ default:
+ void;
+};
+
+readdirres
+NFSPROC_READDIR (readdirargs) = 16;
+.DE
+.KE
+Returns a variable number of directory entries, with a total size
+of up to "count" bytes, from the directory given by "dir". If the
+returned value of "status" is
+.I NFS_OK ,
+then it is followed by a
+variable number of "entry"s. Each "entry" contains a "fileid"
+which consists of a unique number to identify the file within a
+filesystem, the "name" of the file, and a "cookie" which is an
+opaque pointer to the next entry in the directory. The cookie is
+used in the next
+.I READDIR
+call to get more entries starting at a
+given point in the directory. The special cookie zero (all bits
+zero) can be used to get the entries starting at the beginning of
+the directory. The "fileid" field should be the same number as the
+"fileid" in the the attributes of the file. (See the
+.I "Basic Data Types"
+section.)
+The "eof" flag has a value of
+.I TRUE
+if there are no more entries in the directory.
+.KS
+.NH 3
+\&Get Filesystem Attributes
+.IX "NFS server procedures" NFSPROC_STATFS() "" \fINFSPROC_STATFS()\fP
+.DS
+union statfsres (stat status) {
+ case NFS_OK:
+ struct {
+ unsigned tsize;
+ unsigned bsize;
+ unsigned blocks;
+ unsigned bfree;
+ unsigned bavail;
+ } info;
+ default:
+ void;
+};
+
+statfsres
+NFSPROC_STATFS(fhandle) = 17;
+.DE
+.KE
+If the reply "status" is
+.I NFS_OK ,
+then the reply "info" gives the
+attributes for the filesystem that contains file referred to by the
+input fhandle. The attribute fields contain the following values:
+.IP tsize:
+The optimum transfer size of the server in bytes. This is
+the number of bytes the server would like to have in the
+data part of READ and WRITE requests.
+.IP bsize:
+The block size in bytes of the filesystem.
+.IP blocks:
+The total number of "bsize" blocks on the filesystem.
+.IP bfree:
+The number of free "bsize" blocks on the filesystem.
+.IP bavail:
+The number of "bsize" blocks available to non-privileged users.
+.LP
+Note: This call does not work well if a filesystem has variable
+size blocks.
+.NH 1
+\&NFS Implementation Issues
+.IX NFS implementation
+.LP
+The NFS protocol is designed to be operating system independent, but
+since this version was designed in a UNIX environment, many
+operations have semantics similar to the operations of the UNIX file
+system. This section discusses some of the implementation-specific
+semantic issues.
+.NH 2
+\&Server/Client Relationship
+.IX NFS "server/client relationship"
+.LP
+The NFS protocol is designed to allow servers to be as simple and
+general as possible. Sometimes the simplicity of the server can be a
+problem, if the client wants to implement complicated filesystem
+semantics.
+.LP
+For example, some operating systems allow removal of open files. A
+process can open a file and, while it is open, remove it from the
+directory. The file can be read and written as long as the process
+keeps it open, even though the file has no name in the filesystem.
+It is impossible for a stateless server to implement these semantics.
+The client can do some tricks such as renaming the file on remove,
+and only removing it on close. We believe that the server provides
+enough functionality to implement most file system semantics on the
+client.
+.LP
+Every NFS client can also potentially be a server, and remote and
+local mounted filesystems can be freely intermixed. This leads to
+some interesting problems when a client travels down the directory
+tree of a remote filesystem and reaches the mount point on the server
+for another remote filesystem. Allowing the server to follow the
+second remote mount would require loop detection, server lookup, and
+user revalidation. Instead, we decided not to let clients cross a
+server's mount point. When a client does a LOOKUP on a directory on
+which the server has mounted a filesystem, the client sees the
+underlying directory instead of the mounted directory. A client can
+do remote mounts that match the server's mount points to maintain the
+server's view.
+.LP
+.NH 2
+\&Pathname Interpretation
+.IX NFS "pathname interpretation"
+.LP
+There are a few complications to the rule that pathnames are always
+parsed on the client. For example, symbolic links could have
+different interpretations on different clients. Another common
+problem for non-UNIX implementations is the special interpretation of
+the pathname ".." to mean the parent of a given directory. The next
+revision of the protocol uses an explicit flag to indicate the parent
+instead.
+.NH 2
+\&Permission Issues
+.IX NFS "permission issues"
+.LP
+The NFS protocol, strictly speaking, does not define the permission
+checking used by servers. However, it is expected that a server
+will do normal operating system permission checking using
+.I AUTH_UNIX
+style authentication as the basis of its protection mechanism. The
+server gets the client's effective "uid", effective "gid", and groups
+on each call and uses them to check permission. There are various
+problems with this method that can been resolved in interesting ways.
+.LP
+Using "uid" and "gid" implies that the client and server share the
+same "uid" list. Every server and client pair must have the same
+mapping from user to "uid" and from group to "gid". Since every
+client can also be a server, this tends to imply that the whole
+network shares the same "uid/gid" space.
+.I AUTH_DES
+(and the next
+revision of the NFS protocol) uses string names instead of numbers,
+but there are still complex problems to be solved.
+.LP
+Another problem arises due to the usually stateful open operation.
+Most operating systems check permission at open time, and then check
+that the file is open on each read and write request. With stateless
+servers, the server has no idea that the file is open and must do
+permission checking on each read and write call. On a local
+filesystem, a user can open a file and then change the permissions so
+that no one is allowed to touch it, but will still be able to write
+to the file because it is open. On a remote filesystem, by contrast,
+the write would fail. To get around this problem, the server's
+permission checking algorithm should allow the owner of a file to
+access it regardless of the permission setting.
+.LP
+A similar problem has to do with paging in from a file over the
+network. The operating system usually checks for execute permission
+before opening a file for demand paging, and then reads blocks from
+the open file. The file may not have read permission, but after it
+is opened it doesn't matter. An NFS server can not tell the
+difference between a normal file read and a demand page-in read. To
+make this work, the server allows reading of files if the "uid" given
+in the call has execute or read permission on the file.
+.LP
+In most operating systems, a particular user (on the user ID zero)
+has access to all files no matter what permission and ownership they
+have. This "super-user" permission may not be allowed on the server,
+since anyone who can become super-user on their workstation could
+gain access to all remote files. The UNIX server by default maps
+user id 0 to -2 before doing its access checking. This works except
+for NFS root filesystems, where super-user access cannot be avoided.
+.NH 2
+\&Setting RPC Parameters
+.IX NFS "setting RPC parameters"
+.LP
+Various file system parameters and options should be set at mount
+time. The mount protocol is described in the appendix below. For
+example, "Soft" mounts as well as "Hard" mounts are usually both
+provided. Soft mounted file systems return errors when RPC
+operations fail (after a given number of optional retransmissions),
+while hard mounted file systems continue to retransmit forever.
+Clients and servers may need to keep caches of recent operations to
+help avoid problems with non-idempotent operations.
+.NH 1
+\&Mount Protocol Definition
+.IX "mount protocol" "" "" "" PAGE MAJOR
+.sp 1
+.NH 2
+\&Introduction
+.IX "mount protocol" introduction
+.LP
+The mount protocol is separate from, but related to, the NFS
+protocol. It provides operating system specific services to get the
+NFS off the ground -- looking up server path names, validating user
+identity, and checking access permissions. Clients use the mount
+protocol to get the first file handle, which allows them entry into a
+remote filesystem.
+.LP
+The mount protocol is kept separate from the NFS protocol to make it
+easy to plug in new access checking and validation methods without
+changing the NFS server protocol.
+.LP
+Notice that the protocol definition implies stateful servers because
+the server maintains a list of client's mount requests. The mount
+list information is not critical for the correct functioning of
+either the client or the server. It is intended for advisory use
+only, for example, to warn possible clients when a server is going
+down.
+.LP
+Version one of the mount protocol is used with version two of the NFS
+protocol. The only connecting point is the
+.I fhandle
+structure, which is the same for both protocols.
+.NH 2
+\&RPC Information
+.IX "mount protocol" "RPC information"
+.IP \fIAuthentication\fP
+The mount service uses
+.I AUTH_UNIX
+and
+.I AUTH_DES
+style authentication only.
+.IP "\fITransport Protocols\fP"
+The mount service is currently supported on UDP/IP only.
+.IP "\fIPort Number\fP"
+Consult the server's portmapper, described in the chapter
+.I "Remote Procedure Calls: Protocol Specification",
+to find the port number on which the mount service is registered.
+.NH 2
+\&Sizes of XDR Structures
+.IX "mount protocol" "XDR structure sizes"
+.LP
+These are the sizes, given in decimal bytes, of various XDR
+structures used in the protocol:
+.DS
+/* \fIThe maximum number of bytes in a pathname argument\fP */
+const MNTPATHLEN = 1024;
+
+/* \fIThe maximum number of bytes in a name argument\fP */
+const MNTNAMLEN = 255;
+
+/* \fIThe size in bytes of the opaque file handle\fP */
+const FHSIZE = 32;
+.DE
+.NH 2
+\&Basic Data Types
+.IX "mount protocol" "basic data types"
+.IX "mount data types"
+.LP
+This section presents the data types used by the mount protocol.
+In many cases they are similar to the types used in NFS.
+.KS
+.NH 3
+\&fhandle
+.IX "mount data types" fhandle "" \fIfhandle\fP
+.DS
+typedef opaque fhandle[FHSIZE];
+.DE
+.KE
+The type
+.I fhandle
+is the file handle that the server passes to the
+client. All file operations are done using file handles to refer
+to a file or directory. The file handle can contain whatever
+information the server needs to distinguish an individual file.
+.LP
+This is the same as the "fhandle" XDR definition in version 2 of
+the NFS protocol; see
+.I "Basic Data Types"
+in the definition of the NFS protocol, above.
+.KS
+.NH 3
+\&fhstatus
+.IX "mount data types" fhstatus "" \fIfhstatus\fP
+.DS
+union fhstatus switch (unsigned status) {
+ case 0:
+ fhandle directory;
+ default:
+ void;
+};
+.DE
+.KE
+The type
+.I fhstatus
+is a union. If a "status" of zero is returned,
+the call completed successfully, and a file handle for the
+"directory" follows. A non-zero status indicates some sort of
+error. In this case the status is a UNIX error number.
+.KS
+.NH 3
+\&dirpath
+.IX "mount data types" dirpath "" \fIdirpath\fP
+.DS
+typedef string dirpath<MNTPATHLEN>;
+.DE
+.KE
+The type
+.I dirpath
+is a server pathname of a directory.
+.KS
+.NH 3
+\&name
+.IX "mount data types" name "" \fIname\fP
+.DS
+typedef string name<MNTNAMLEN>;
+.DE
+.KE
+The type
+.I name
+is an arbitrary string used for various names.
+.NH 2
+\&Server Procedures
+.IX "mount server procedures"
+.LP
+The following sections define the RPC procedures supplied by a
+mount server.
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Protocol description for the mount program
+*/
+.ft CW
+
+program MOUNTPROG {
+.ft I
+/*
+* Version 1 of the mount protocol used with
+* version 2 of the NFS protocol.
+*/
+.ft CW
+ version MOUNTVERS {
+ void MOUNTPROC_NULL(void) = 0;
+ fhstatus MOUNTPROC_MNT(dirpath) = 1;
+ mountlist MOUNTPROC_DUMP(void) = 2;
+ void MOUNTPROC_UMNT(dirpath) = 3;
+ void MOUNTPROC_UMNTALL(void) = 4;
+ exportlist MOUNTPROC_EXPORT(void) = 5;
+ } = 1;
+} = 100005;
+.DE
+.KS
+.NH 3
+\&Do Nothing
+.IX "mount server procedures" MNTPROC_NULL() "" \fIMNTPROC_NULL()\fP
+.DS
+void
+MNTPROC_NULL(void) = 0;
+.DE
+.KE
+This procedure does no work. It is made available in all RPC
+services to allow server response testing and timing.
+.KS
+.NH 3
+\&Add Mount Entry
+.IX "mount server procedures" MNTPROC_MNT() "" \fIMNTPROC_MNT()\fP
+.DS
+fhstatus
+MNTPROC_MNT(dirpath) = 1;
+.DE
+.KE
+If the reply "status" is 0, then the reply "directory" contains the
+file handle for the directory "dirname". This file handle may be
+used in the NFS protocol. This procedure also adds a new entry to
+the mount list for this client mounting "dirname".
+.KS
+.NH 3
+\&Return Mount Entries
+.IX "mount server procedures" MNTPROC_DUMP() "" \fIMNTPROC_DUMP()\fP
+.DS
+struct *mountlist {
+ name hostname;
+ dirpath directory;
+ mountlist nextentry;
+};
+
+mountlist
+MNTPROC_DUMP(void) = 2;
+.DE
+.KE
+Returns the list of remote mounted filesystems. The "mountlist"
+contains one entry for each "hostname" and "directory" pair.
+.KS
+.NH 3
+\&Remove Mount Entry
+.IX "mount server procedures" MNTPROC_UMNT() "" \fIMNTPROC_UMNT()\fP
+.DS
+void
+MNTPROC_UMNT(dirpath) = 3;
+.DE
+.KE
+Removes the mount list entry for the input "dirpath".
+.KS
+.NH 3
+\&Remove All Mount Entries
+.IX "mount server procedures" MNTPROC_UMNTALL() "" \fIMNTPROC_UMNTALL()\fP
+.DS
+void
+MNTPROC_UMNTALL(void) = 4;
+.DE
+.KE
+Removes all of the mount list entries for this client.
+.KS
+.NH 3
+\&Return Export List
+.IX "mount server procedures" MNTPROC_EXPORT() "" \fIMNTPROC_EXPORT()\fP
+.DS
+struct *groups {
+ name grname;
+ groups grnext;
+};
+
+struct *exportlist {
+ dirpath filesys;
+ groups groups;
+ exportlist next;
+};
+
+exportlist
+MNTPROC_EXPORT(void) = 5;
+.DE
+.KE
+Returns a variable number of export list entries. Each entry
+contains a filesystem name and a list of groups that are allowed to
+import it. The filesystem name is in "filesys", and the group name
+is in the list "groups".
+.LP
+Note: The exportlist should contain
+more information about the status of the filesystem, such as a
+read-only flag.
diff --git a/share/doc/psd/27.nfsrpc/stubs b/share/doc/psd/27.nfsrpc/stubs
new file mode 100644
index 0000000..78b0a2c
--- /dev/null
+++ b/share/doc/psd/27.nfsrpc/stubs
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+.\"
+.if t .ftr L CR
diff --git a/share/doc/smm/02.config/0.t b/share/doc/smm/02.config/0.t
new file mode 100644
index 0000000..ae5bf77
--- /dev/null
+++ b/share/doc/smm/02.config/0.t
@@ -0,0 +1,88 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)0.t 8.1 (Berkeley) 7/5/93
+.\"
+.bd S B 3
+.de UX
+.ie \\n(GA>0 \\$2UNIX\\$1
+.el \{\
+.if n \\$2UNIX\\$1*
+.if t \\$2UNIX\\$1\\f1\(dg\\fP
+.FS
+.if n *UNIX
+.if t \(dgUNIX
+.ie \\$3=1 is a Footnote of Bell Laboratories.
+.el is a Trademark of Bell Laboratories.
+.FE
+.nr GA 1\}
+..
+.de BR
+\fB\\$1\fP\\$2
+..
+.TL
+Building 4.4BSD Kernels with Config
+.AU
+Samuel J. Leffler and Michael J. Karels
+.AI
+Computer Systems Research Group
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, California 94720
+.de IR
+\fI\\$1\fP\\$2
+..
+.de DT
+.TA 8 16 24 32 40 48 56 64 72 80
+..
+.AB
+.PP
+This document describes the use of
+\fIconfig\fP\|(8) to configure and create bootable
+4.4BSD system images.
+It discusses the structure of system
+configuration files and how to configure
+systems with non-standard hardware configurations.
+Sections describing the preferred way to
+add new code to the system and how the system's autoconfiguration
+process operates are included. An appendix
+contains a summary of the rules used by the system
+in calculating the size of system data structures,
+and also indicates some of the standard system size
+limitations (and how to change them).
+Other configuration options are also listed.
+.sp
+.LP
+Revised July 5, 1993
+.AE
+.LP
+.OH 'Building 4.4BSD Kernels with Config''SMM:2-%'
+.EH 'SMM:2-%''Building 4.4BSD Kernels with Config'
diff --git a/share/doc/smm/02.config/1.t b/share/doc/smm/02.config/1.t
new file mode 100644
index 0000000..453041b
--- /dev/null
+++ b/share/doc/smm/02.config/1.t
@@ -0,0 +1,61 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)1.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH Introduction
+.ne 2i
+.sp 3
+.NH
+INTRODUCTION
+.PP
+.I Config
+is a tool used in building 4.4BSD system images (the UNIX kernel).
+It takes a file describing a system's tunable parameters and
+hardware support, and generates a collection
+of files which are then used to build a copy of UNIX appropriate
+to that configuration.
+.I Config
+simplifies system maintenance by isolating system dependencies
+in a single, easy to understand, file.
+.PP
+This document describes the content and
+format of system configuration
+files and the rules which must be followed when creating
+these files. Example configuration files are constructed
+and discussed.
+.PP
+Later sections suggest guidelines to be used in modifying
+system source and explain some of the inner workings of the
+autoconfiguration process. Appendix D summarizes the rules
+used in calculating the most important system data structures
+and indicates some inherent system data structure size
+limitations (and how to go about modifying them).
diff --git a/share/doc/smm/02.config/2.t b/share/doc/smm/02.config/2.t
new file mode 100644
index 0000000..34e6b63
--- /dev/null
+++ b/share/doc/smm/02.config/2.t
@@ -0,0 +1,188 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)2.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Configuration File Contents
+.ne 2i
+.NH
+CONFIGURATION FILE CONTENTS
+.PP
+A system configuration must include at least the following
+pieces of information:
+.IP \(bu 3
+machine type
+.IP \(bu 3
+cpu type
+.IP \(bu 3
+system identification
+.IP \(bu 3
+timezone
+.IP \(bu 3
+maximum number of users
+.IP \(bu 3
+location of the root file system
+.IP \(bu 3
+available hardware
+.PP
+.I Config
+allows multiple system images to be generated from a single
+configuration description. Each system image is configured
+for identical hardware, but may have different locations for the root
+file system and, possibly, other system devices.
+.NH 2
+Machine type
+.PP
+The
+.I "machine type"
+indicates if the system is going to operate on a DEC VAX-11\(dg computer,
+.FS
+\(dg DEC, VAX, UNIBUS, MASSBUS and MicroVAX are trademarks of Digital
+Equipment Corporation.
+.FE
+or some other machine on which 4.4BSD operates. The machine type
+is used to locate certain data files which are machine specific, and
+also to select rules used in constructing the resultant
+configuration files.
+.NH 2
+Cpu type
+.PP
+The
+.I "cpu type"
+indicates which, of possibly many, cpu's the system is to operate on.
+For example, if the system is being configured for a VAX-11, it could
+be running on a VAX 8600, VAX-11/780, VAX-11/750, VAX-11/730 or MicroVAX II.
+(Other VAX cpu types, including the 8650, 785 and 725, are configured using
+the cpu designation for compatible machines introduced earlier.)
+Specifying
+more than one cpu type implies that the system should be configured to run
+on any of the cpu's specified. For some types of machines this is not
+possible and
+.I config
+will print a diagnostic indicating such.
+.NH 2
+System identification
+.PP
+The
+.I "system identification"
+is a moniker attached to the system, and often the machine on which the
+system is to run. For example, at Berkeley we have machines named Ernie
+(Co-VAX), Kim (No-VAX), and so on. The system identifier selected is used to
+create a global C ``#define'' which may be used to isolate system dependent
+pieces of code in the kernel. For example, Ernie's Varian driver used
+to be special cased because its interrupt vectors were wired together. The
+code in the driver which understood how to handle this non-standard hardware
+configuration was conditionally compiled in only if the system
+was for Ernie.
+.PP
+The system identifier ``GENERIC'' is given to a system which
+will run on any cpu of a particular machine type; it should not
+otherwise be used for a system identifier.
+.NH 2
+Timezone
+.PP
+The timezone in which the system is to run is used to define the
+information returned by the \fIgettimeofday\fP\|(2)
+system call. This value is specified as the number of hours east
+or west of GMT. Negative numbers indicate a value east of GMT.
+The timezone specification may also indicate the
+type of daylight savings time rules to be applied.
+.NH 2
+Maximum number of users
+.PP
+The system allocates many system data structures at boot time
+based on the maximum number of users the system will support.
+This number is normally between 8 and 40, depending
+on the hardware and expected job mix. The rules
+used to calculate system data structures are discussed in
+Appendix D.
+.NH 2
+Root file system location
+.PP
+When the system boots it must know the location of
+the root of the file system
+tree. This location and the part(s) of the disk(s) to be used
+for paging and swapping must be specified in order to create
+a complete configuration description.
+.I Config
+uses many rules to calculate default locations for these items;
+these are described in Appendix B.
+.PP
+When a generic system is configured, the root file system is left
+undefined until the system is booted. In this case, the root file
+system need not be specified, only that the system is a generic system.
+.NH 2
+Hardware devices
+.PP
+When the system boots it goes through an
+.I autoconfiguration
+phase. During this period, the system searches for all
+those hardware devices
+which the system builder has indicated might be present. This probing
+sequence requires certain pieces of information such as register
+addresses, bus interconnects, etc. A system's hardware may be configured
+in a very flexible manner or be specified without any flexibility
+whatsoever. Most people do not configure hardware devices into the
+system unless they are currently present on the machine, expect
+them to be present in the near future, or are simply guarding
+against a hardware
+failure somewhere else at the site (it is often wise to configure in
+extra disks in case an emergency requires moving one off a machine which
+has hardware problems).
+.PP
+The specification of hardware devices usually occupies the majority of
+the configuration file. As such, a large portion of this document will
+be spent understanding it. Section 6.3 contains a description of
+the autoconfiguration process, as it applies to those planning to
+write, or modify existing, device drivers.
+.NH 2
+Pseudo devices
+.PP
+Several system facilities are configured in a manner like that used
+for hardware devices although they are not associated with specific hardware.
+These system options are configured as
+.IR pseudo-devices .
+Some pseudo devices allow an optional parameter that sets the limit
+on the number of instances of the device that are active simultaneously.
+.NH 2
+System options
+.PP
+Other than the mandatory pieces of information described above, it
+is also possible to include various optional system facilities
+or to modify system behavior and/or limits.
+For example, 4.4BSD can be configured to support binary compatibility for
+programs built under 4.3BSD. Also, optional support is provided
+for disk quotas and tracing the performance of the virtual memory
+subsystem. Any optional facilities to be configured into
+the system are specified in the configuration file. The resultant
+files generated by
+.I config
+will automatically include the necessary pieces of the system.
diff --git a/share/doc/smm/02.config/3.t b/share/doc/smm/02.config/3.t
new file mode 100644
index 0000000..e0b6234
--- /dev/null
+++ b/share/doc/smm/02.config/3.t
@@ -0,0 +1,299 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)3.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "System Building Process
+.ne 2i
+.NH
+SYSTEM BUILDING PROCESS
+.PP
+In this section we consider the steps necessary to build a bootable system
+image. We assume the system source is located in the ``/sys'' directory
+and that, initially, the system is being configured from source code.
+.PP
+Under normal circumstances there are 5 steps in building a system.
+.IP 1) 3
+Create a configuration file for the system.
+.IP 2) 3
+Make a directory for the system to be constructed in.
+.IP 3) 3
+Run
+.I config
+on the configuration file to generate the files required
+to compile and load the system image.
+.IP 4)
+Construct the source code interdependency rules for the
+configured system with
+.I make depend
+using
+.IR make (1).
+.IP 5)
+Compile and load the system with
+.IR make .
+.PP
+Steps 1 and 2 are usually done only once. When a system configuration
+changes it usually suffices to just run
+.I config
+on the modified configuration file, rebuild the source code dependencies,
+and remake the system. Sometimes,
+however, configuration dependencies may not be noticed in which case
+it is necessary to clean out the relocatable object files saved
+in the system's directory; this will be discussed later.
+.NH 2
+Creating a configuration file
+.PP
+Configuration files normally reside in the directory ``/sys/conf''.
+A configuration file is most easily constructed by copying an
+existing configuration file and modifying it. The 4.4BSD distribution
+contains a number of configuration files for machines at Berkeley;
+one may be suitable or, in worst case, a copy
+of the generic configuration file may be edited.
+.PP
+The configuration file must have the same name as the directory in
+which the configured system is to be built.
+Further,
+.I config
+assumes this directory is located in the parent directory of
+the directory in which it
+is run. For example, the generic
+system has a configuration file ``/sys/conf/GENERIC'' and an accompanying
+directory named ``/sys/GENERIC''.
+Although it is not required that the system sources and configuration
+files reside in ``/sys,'' the configuration and compilation procedure
+depends on the relative locations of directories within that hierarchy,
+as most of the system code and the files created by
+.I config
+use pathnames of the form ``../''.
+If the system files are not located in ``/sys,''
+it is desirable to make a symbolic link there for use in installation
+of other parts of the system that share files with the kernel.
+.PP
+When building the configuration file, be sure to include the items
+described in section 2. In particular, the machine type,
+cpu type, timezone, system identifier, maximum users, and root device
+must be specified. The specification of the hardware present may take
+a bit of work; particularly if your hardware is configured at non-standard
+places (e.g. device registers located at funny places or devices not
+supported by the system). Section 4 of this document
+gives a detailed description of the configuration file syntax,
+section 5 explains some sample configuration files, and
+section 6 discusses how to add new devices to
+the system. If the devices to be configured are not already
+described in one of the existing configuration files you should check
+the manual pages in section 4 of the UNIX Programmers Manual. For each
+supported device, the manual page synopsis entry gives a
+sample configuration line.
+.PP
+Once the configuration file is complete, run it through
+.I config
+and look for any errors. Never try and use a system which
+.I config
+has complained about; the results are unpredictable.
+For the most part,
+.IR config 's
+error diagnostics are self explanatory. It may be the case that
+the line numbers given with the error messages are off by one.
+.PP
+A successful run of
+.I config
+on your configuration file will generate a number of files in
+the configuration directory. These files are:
+.IP \(bu 3
+A file to be used by \fImake\fP\|(1)
+in compiling and loading the system,
+.IR Makefile .
+.IP \(bu 3
+One file for each possible system image for this machine,
+.IR swapxxx.c ,
+where
+.I xxx
+is the name of the system image,
+which describes where swapping, the root file system, and other
+miscellaneous system devices are located.
+.IP \(bu 3
+A collection of header files, one per possible device the
+system supports, which define the hardware configured.
+.IP \(bu 3
+A file containing the I/O configuration tables used by the system
+during its
+.I autoconfiguration
+phase,
+.IR ioconf.c .
+.IP \(bu 3
+An assembly language file of interrupt vectors which
+connect interrupts from the machine's external buses to the main
+system path for handling interrupts,
+and a file that contains counters and names for the interrupt vectors.
+.PP
+Unless you have reason to doubt
+.IR config ,
+or are curious how the system's autoconfiguration scheme
+works, you should never have to look at any of these files.
+.NH 2
+Constructing source code dependencies
+.PP
+When
+.I config
+is done generating the files needed to compile and link your system it
+will terminate with a message of the form ``Don't forget to run make depend''.
+This is a reminder that you should change over to the configuration
+directory for the system just configured and type ``make depend''
+to build the rules used by
+.I make
+to recognize interdependencies in the system source code.
+This will insure that any changes to a piece of the system
+source code will result in the proper modules being recompiled
+the next time
+.I make
+is run.
+.PP
+This step is particularly important if your site makes changes
+to the system include files. The rules generated specify which source code
+files are dependent on which include files. Without these rules,
+.I make
+will not recognize when it must rebuild modules
+due to the modification of a system header file.
+The dependency rules are generated by a pass of the C preprocessor
+and reflect the global system options.
+This step must be repeated when the configuration file is changed
+and
+.I config
+is used to regenerate the system makefile.
+.NH 2
+Building the system
+.PP
+The makefile constructed by
+.I config
+should allow a new system to be rebuilt by simply typing ``make image-name''.
+For example, if you have named your bootable system image ``kernel'',
+then ``make kernel''
+will generate a bootable image named ``kernel''. Alternate system image names
+are used when the root file system location and/or swapping configuration
+is done in more than one way. The makefile which
+.I config
+creates has entry points for each system image defined in
+the configuration file.
+Thus, if you have configured ``kernel'' to be a system with the root file
+system on an ``hp'' device and ``hkkernel'' to be a system with the root
+file system on an ``hk'' device, then ``make kernel hkkernel'' will generate
+binary images for each.
+As the system will generally use the disk from which it is loaded
+as the root filesystem, separate system images are only required
+to support different swap configurations.
+.PP
+Note that the name of a bootable image is different from the system
+identifier. All bootable images are configured for the same system;
+only the information about the root file system and paging devices differ.
+(This is described in more detail in section 4.)
+.PP
+The last step in the system building process is to rearrange certain commonly
+used symbols in the symbol table of the system image; the makefile
+generated by
+.I config
+does this automatically for you.
+This is advantageous for programs such as
+\fInetstat\fP\|(1) and \fIvmstat\fP\|(1),
+which run much faster when the symbols they need are located at
+the front of the symbol table.
+Remember also that many programs expect
+the currently executing system to be named ``/kernel''. If you install
+a new system and name it something other than ``/kernel'', many programs
+are likely to give strange results.
+.NH 2
+Sharing object modules
+.PP
+If you have many systems which are all built on a single machine
+there are at least two approaches to saving time in building system
+images. The best way is to have a single system image which is run on
+all machines. This is attractive since it minimizes disk space used
+and time required to rebuild systems after making changes. However,
+it is often the case that one or more systems will require a separately
+configured system image. This may be due to limited memory (building
+a system with many unused device drivers can be expensive), or to
+configuration requirements (one machine may be a development machine
+where disk quotas are not needed, while another is a production machine
+where they are), etc. In these cases it is possible
+for common systems to share relocatable object modules which are not
+configuration dependent; most of the modules in the directory ``/sys/sys''
+are of this sort.
+.PP
+To share object modules, a generic system should be built. Then, for
+each system configure the system as before, but before recompiling and
+linking the system, type ``make links'' in the system compilation directory.
+This will cause the system
+to be searched for source modules which are safe to share between systems
+and generate symbolic links in the current directory to the appropriate
+object modules in the directory ``../GENERIC''. A shell script,
+``makelinks'' is generated with this request and may be checked for
+correctness. The file ``/sys/conf/defines'' contains a list of symbols
+which we believe are safe to ignore when checking the source code
+for modules which may be shared. Note that this list includes the definitions
+used to conditionally compile in the virtual memory tracing facilities, and
+the trace point support used only rarely (even at Berkeley).
+It may be necessary
+to modify this file to reflect local needs. Note further that
+interdependencies which are not directly visible
+in the source code are not caught. This means that if you place
+per-system dependencies in an include file, they will not be recognized
+and the shared code may be selected in an unexpected fashion.
+.NH 2
+Building profiled systems
+.PP
+It is simple to configure a system which will automatically
+collect profiling information as it operates. The profiling data
+may be collected with \fIkgmon\fP\|(8) and processed with
+\fIgprof\fP\|(1)
+to obtain information regarding the system's operation. Profiled
+systems maintain histograms of the program counter as well as the
+number of invocations of each routine. The \fIgprof\fP
+command will also generate a dynamic call graph of the executing
+system and propagate time spent in each routine along the arcs
+of the call graph (consult the \fIgprof\fP documentation for elaboration).
+The program counter sampling can be driven by the system clock, or
+if you have an alternate real time clock, this can be used. The
+latter is highly recommended, as use of the system clock will result
+in statistical anomalies, and time spent in the clock routine will
+not be accurately attributed.
+.PP
+To configure a profiled system, the
+.B \-p
+option should be supplied to \fIconfig\fP.
+A profiled system is about 5-10% larger in its text space due to
+the calls to count the subroutine invocations. When the system
+executes, the profiling data is stored in a buffer which is 1.2
+times the size of the text space. The overhead for running a
+profiled system varies; under normal load we see anywhere from 5-25%
+of the system time spent in the profiling code.
+.PP
+Note that systems configured for profiling should not be shared as
+described above unless all the other shared systems are also to be
+profiled.
diff --git a/share/doc/smm/02.config/4.t b/share/doc/smm/02.config/4.t
new file mode 100644
index 0000000..7498185
--- /dev/null
+++ b/share/doc/smm/02.config/4.t
@@ -0,0 +1,442 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)4.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Configuration File Syntax
+.ne 2i
+.NH
+CONFIGURATION FILE SYNTAX
+.PP
+In this section we consider the specific rules used in writing
+a configuration file. A complete grammar for the input language
+can be found in Appendix A and may be of use if you should have
+problems with syntax errors.
+.PP
+A configuration file is broken up into three logical pieces:
+.IP \(bu 3
+configuration parameters global to all system images
+specified in the configuration file,
+.IP \(bu 3
+parameters specific to each
+system image to be generated, and
+.IP \(bu 3
+device specifications.
+.NH 2
+Global configuration parameters
+.PP
+The global configuration parameters are the type of machine,
+cpu types, options, timezone, system identifier, and maximum users.
+Each is specified with a separate line in the configuration file.
+.IP "\fBmachine\fP \fItype\fP"
+.br
+The system is to run on the machine type specified. No more than
+one machine type can appear in the configuration file. Legal values
+are
+.B vax
+and
+\fBsun\fP.
+.IP "\fBcpu\fP ``\fItype\fP''"
+.br
+This system is to run on the cpu type specified.
+More than one cpu type specification
+can appear in a configuration file.
+Legal types for a
+.B vax
+machine are
+\fBVAX8600\fP, \fBVAX780\fP, \fBVAX750\fP,
+\fBVAX730\fP
+and
+\fBVAX630\fP (MicroVAX II).
+The 8650 is listed as an 8600, the 785 as a 780, and a 725 as a 730.
+.IP "\fBoptions\fP \fIoptionlist\fP"
+.br
+Compile the listed optional code into the system.
+Options in this list are separated by commas.
+Possible options are listed at the top of the generic makefile.
+A line of the form ``options FUNNY,HAHA'' generates global ``#define''s
+\-DFUNNY \-DHAHA in the resultant makefile.
+An option may be given a value by following its name with ``\fB=\fP'',
+then the value enclosed in (double) quotes.
+The following are major options are currently in use:
+COMPAT (include code for compatibility with 4.1BSD binaries),
+INET (Internet communication protocols),
+NS (Xerox NS communication protocols),
+and
+QUOTA (enable disk quotas).
+Other kernel options controlling system sizes and limits
+are listed in Appendix D;
+options for the network are found in Appendix E.
+There are additional options which are associated with certain
+peripheral devices; those are listed in the Synopsis section
+of the manual page for the device.
+.IP "\fBmakeoptions\fP \fIoptionlist\fP"
+.br
+Options that are used within the system makefile
+and evaluated by
+.I make
+are listed as
+.IR makeoptions .
+Options are listed with their values with the form
+``makeoptions name=value,name2=value2.''
+The values must be enclosed in double quotes if they include numerals
+or begin with a dash.
+.IP "\fBtimezone\fP \fInumber\fP [ \fBdst\fP [ \fInumber\fP ] ]"
+.br
+Specifies the timezone used by the system. This is measured in the
+number of hours your timezone is west of GMT.
+EST is 5 hours west of GMT, PST is 8. Negative numbers
+indicate hours east of GMT. If you specify
+\fBdst\fP, the system will operate under daylight savings time.
+An optional integer or floating point number may be included
+to specify a particular daylight saving time correction algorithm;
+the default value is 1, indicating the United States.
+Other values are: 2 (Australian style), 3 (Western European),
+4 (Middle European), and 5 (Eastern European). See
+\fIgettimeofday\fP\|(2) and \fIctime\fP\|(3) for more information.
+.IP "\fBident\fP \fIname\fP"
+.br
+This system is to be known as
+.IR name .
+This is usually a cute name like ERNIE (short for Ernie Co-Vax) or
+VAXWELL (for Vaxwell Smart).
+This value is defined for use in conditional compilation,
+and is also used to locate an optional list of source files specific
+to this system.
+.IP "\fBmaxusers\fP \fInumber\fP"
+.br
+The maximum expected number of simultaneously active user on this system is
+.IR number .
+This number is used to size several system data structures.
+.NH 2
+System image parameters
+.PP
+Multiple bootable images may be specified in a single configuration
+file. The systems will have the same global configuration parameters
+and devices, but the location of the root file system and other
+system specific devices may be different. A system image is specified
+with a ``config'' line:
+.IP
+\fBconfig\fP\ \fIsysname\fP\ \fIconfig-clauses\fP
+.LP
+The
+.I sysname
+field is the name given to the loaded system image; almost everyone
+names their standard system image ``kernel''. The configuration clauses
+are one or more specifications indicating where the root file system
+is located and the number and location of paging devices.
+The device used by the system to process argument lists during
+.IR execve (2)
+calls may also be specified, though in practice this is almost
+always selected by
+.I config
+using one of its rules for selecting default locations for
+system devices.
+.PP
+A configuration clause is one of the following
+.IP
+.nf
+\fBroot\fP [ \fBon\fP ] \fIroot-device\fP
+\fBswap\fP [ \fBon\fP ] \fIswap-device\fP [ \fBand\fP \fIswap-device\fP ] ...
+\fBdumps\fP [ \fBon\fP ] \fIdump-device\fP
+\fBargs\fP [ \fBon\fP ] \fIarg-device\fP
+.LP
+(the ``on'' is optional.) Multiple configuration clauses
+are separated by white space;
+.I config
+allows specifications to be continued across multiple lines
+by beginning the continuation line with a tab character.
+The ``root'' clause specifies where the root file system
+is located, the ``swap'' clause indicates swapping and paging
+area(s), the ``dumps'' clause can be used to force system dumps
+to be taken on a particular device, and the ``args'' clause
+can be used to specify that argument list processing for
+.I execve
+should be done on a particular device.
+.PP
+The device names supplied in the clauses may be fully specified
+as a device, unit, and file system partition; or underspecified
+in which case
+.I config
+will use builtin rules to select default unit numbers and file
+system partitions. The defaulting rules are a bit complicated
+as they are dependent on the overall system configuration.
+For example, the swap area need not be specified at all if
+the root device is specified; in this case the swap area is
+placed in the ``b'' partition of the same disk where the root
+file system is located. Appendix B contains a complete list
+of the defaulting rules used in selecting system configuration
+devices.
+.PP
+The device names are translated to the
+appropriate major and minor device
+numbers on a per-machine basis. A file,
+``/sys/conf/devices.machine'' (where ``machine''
+is the machine type specified in the configuration file),
+is used to map a device name to its major block device number.
+The minor device number is calculated using the standard
+disk partitioning rules: on unit 0, partition ``a'' is minor device
+0, partition ``b'' is minor device 1, and so on; for units
+other than 0, add 8 times the unit number to get the minor
+device.
+.PP
+If the default mapping of device name to major/minor device
+number is incorrect for your configuration, it can be replaced
+by an explicit specification of the major/minor device.
+This is done by substituting
+.IP
+\fBmajor\fP \fIx\fP \fBminor\fP \fIy\fP
+.LP
+where the device name would normally be found. For example,
+.IP
+.nf
+\fBconfig\fP kernel \fBroot\fP \fBon\fP \fBmajor\fP 99 \fBminor\fP 1
+.fi
+.PP
+Normally, the areas configured for swap space are sized by the system
+at boot time. If a non-standard size is to be used for one
+or more swap areas (less than the full partition),
+this can also be specified. To do this, the
+device name specified for a swap area should have a ``size''
+specification appended. For example,
+.IP
+.nf
+\fBconfig\fP kernel \fBroot\fP \fBon\fP hp0 \fBswap\fP \fBon\fP hp0b \fBsize\fP 1200
+.fi
+.LP
+would force swapping to be done in partition ``b'' of ``hp0'' and
+the swap partition size would be set to 1200 sectors. A swap area
+sized larger than the associated disk partition is trimmed to the
+partition size.
+.PP
+To create a generic configuration, only the clause ``swap generic''
+should be specified; any extra clauses will cause an error.
+.NH 2
+Device specifications
+.PP
+Each device attached to a machine must be specified
+to
+.I config
+so that the system generated will know to probe for it during
+the autoconfiguration process carried out at boot time. Hardware
+specified in the configuration need not actually be present on
+the machine where the generated system is to be run. Only the
+hardware actually found at boot time will be used by the system.
+.PP
+The specification of hardware devices in the configuration file
+parallels the interconnection hierarchy of the machine to be
+configured. On the VAX, this means that a configuration file must
+indicate what MASSBUS and UNIBUS adapters are present, and to
+which \fInexi\fP they might be connected.*
+.FS
+* While VAX-11/750's and VAX-11/730 do not actually have
+nexi, the system treats them as having
+.I "simulated nexi"
+to simplify device configuration.
+.FE
+Similarly, devices
+and controllers must be indicated as possibly being connected
+to one or more adapters. A device description may provide a
+complete definition of the possible configuration parameters
+or it may leave certain parameters undefined and make the system
+probe for all the possible values. The latter allows a single
+device configuration list to match many possible physical
+configurations. For example, a disk may be indicated as present
+at UNIBUS adapter 0, or at any UNIBUS adapter which the system
+locates at boot time. The latter scheme, termed
+.IR wildcarding ,
+allows more flexibility in the physical configuration of a system;
+if a disk must be moved around for some reason, the system will
+still locate it at the alternate location.
+.PP
+A device specification takes one of the following forms:
+.IP
+.nf
+\fBmaster\fP \fIdevice-name\fP \fIdevice-info\fP
+\fBcontroller\fP \fIdevice-name\fP \fIdevice-info\fP [ \fIinterrupt-spec\fP ]
+\fBdevice\fP \fIdevice-name\fP \fIdevice-info\fP \fIinterrupt-spec\fP
+\fBdisk\fP \fIdevice-name\fP \fIdevice-info\fP
+\fBtape\fP \fIdevice-name\fP \fIdevice-info\fP
+.fi
+.LP
+A ``master'' is a MASSBUS tape controller; a ``controller'' is a
+disk controller, a UNIBUS tape controller, a MASSBUS adapter, or
+a UNIBUS adapter. A ``device'' is an autonomous device which
+connects directly to a UNIBUS adapter (as opposed to something
+like a disk which connects through a disk controller). ``Disk''
+and ``tape'' identify disk drives and tape drives connected to
+a ``controller'' or ``master.''
+.PP
+The
+.I device-name
+is one of the standard device names, as
+indicated in section 4 of the UNIX Programmers Manual,
+concatenated with the
+.I logical
+unit number to be assigned the device (the
+.I logical
+unit number may be different than the
+.I physical
+unit number indicated on the front of something
+like a disk; the
+.I logical
+unit number is used to refer to the UNIX device, not
+the physical unit number). For example, ``hp0'' is logical
+unit 0 of a MASSBUS storage device, even though it might
+be physical unit 3 on MASSBUS adapter 1.
+.PP
+The
+.I device-info
+clause specifies how the hardware is
+connected in the interconnection hierarchy. On the VAX,
+UNIBUS and MASSBUS adapters are connected to the internal
+system bus through
+a \fInexus\fP.
+Thus, one of the following
+specifications would be used:
+.IP
+.ta 1.5i 2.5i 4.0i
+.nf
+\fBcontroller\fP mba0 \fBat\fP \fBnexus\fP \fIx\fP
+\fBcontroller\fP uba0 \fBat\fP \fBnexus\fP \fIx\fP
+.fi
+.LP
+To tie a controller to a specific nexus, ``x'' would be supplied
+as the number of that nexus; otherwise ``x'' may be specified as
+``?'', in which
+case the system will probe all nexi present looking
+for the specified controller.
+.PP
+The remaining interconnections on the VAX are:
+.IP \(bu 3
+a controller
+may be connected to another controller (e.g. a disk controller attached
+to a UNIBUS adapter),
+.IP \(bu 3
+a master is always attached to a controller (a MASSBUS adapter),
+.IP \(bu 3
+a tape is always attached to a master (for MASSBUS
+tape drives),
+.IP \(bu 3
+a disk is always attached to a controller, and
+.IP \(bu 3
+devices
+are always attached to controllers (e.g. UNIBUS controllers attached
+to UNIBUS adapters).
+.LP
+The following lines give an example of each of these interconnections:
+.IP
+.ta 1.5i 2.5i 4.0i
+.nf
+\fBcontroller\fP hk0 \fBat\fP uba0 ...
+\fBmaster\fP ht0 \fBat\fP mba0 ...
+\fBdisk\fP hp0 \fBat\fP mba0 ...
+\fBtape\fP tu0 \fBat\fP ht0 ...
+\fBdisk\fP rk1 \fBat\fP hk0 ...
+\fBdevice\fP dz0 \fBat\fP uba0 ...
+.fi
+.LP
+Any piece of hardware which may be connected to a specific
+controller may also be wildcarded across multiple controllers.
+.PP
+The final piece of information needed by the system to configure
+devices is some indication of where or how a device will interrupt.
+For tapes and disks, simply specifying the \fIslave\fP or \fIdrive\fP
+number is sufficient to locate the control status register for the
+device.
+\fIDrive\fP numbers may be wildcarded
+on MASSBUS devices, but not on disks on a UNIBUS controller.
+For controllers, the control status register must be
+given explicitly, as well the number of interrupt vectors used and
+the names of the routines to which they should be bound.
+Thus the example lines given above might be completed as:
+.IP
+.ta 1.5i 2.5i 4.0i
+.nf
+\fBcontroller\fP hk0 \fBat\fP uba0 \fBcsr\fP 0177440 \fBvector\fP rkintr
+\fBmaster\fP ht0 \fBat\fP mba0 \fBdrive\fP 0
+\fBdisk\fP hp0 \fBat\fP mba0 \fBdrive\fP ?
+\fBtape\fP tu0 \fBat\fP ht0 \fBslave\fP 0
+\fBdisk\fP rk1 \fBat\fP hk0 \fBdrive\fP 1
+\fBdevice\fP dz0 \fBat\fP uba0 \fBcsr\fP 0160100 \fBvector\fP dzrint dzxint
+.fi
+.PP
+Certain device drivers require extra information passed to them
+at boot time to tailor their operation to the actual hardware present.
+The line printer driver, for example, needs to know how many columns
+are present on each non-standard line printer (i.e. a line printer
+with other than 80 columns). The drivers for the terminal multiplexors
+need to know which lines are attached to modem lines so that no one will
+be allowed to use them unless a connection is present. For this reason,
+one last parameter may be specified to a
+.IR device ,
+a
+.I flags
+field. It has the syntax
+.IP
+\fBflags\fP \fInumber\fP
+.LP
+and is usually placed after the
+.I csr
+specification. The
+.I number
+is passed directly to the associated driver. The manual pages
+in section 4 should be consulted to determine how each driver
+uses this value (if at all).
+Communications interface drivers commonly use the flags
+to indicate whether modem control signals are in use.
+.PP
+The exact syntax for each specific device is given in the Synopsis
+section of its manual page in section 4 of the manual.
+.NH 2
+Pseudo-devices
+.PP
+A number of drivers and software subsystems
+are treated like device drivers without any associated hardware.
+To include any of these pieces, a ``pseudo-device'' specification
+must be used. A specification for a pseudo device takes the form
+.IP
+.DT
+.nf
+\fBpseudo-device\fP \fIdevice-name\fP [ \fIhowmany\fP ]
+.fi
+.PP
+Examples of pseudo devices are
+\fBpty\fP, the pseudo terminal driver (where the optional
+.I howmany
+value indicates the number of pseudo terminals to configure, 32 default),
+and \fBloop\fP, the software loopback network pseudo-interface.
+Other pseudo devices for the network include
+\fBimp\fP (required when a CSS or ACC imp is configured)
+and \fBether\fP (used by the Address Resolution Protocol
+on 10 Mb/sec Ethernets).
+More information on configuring each of these can also be found
+in section 4 of the manual.
diff --git a/share/doc/smm/02.config/5.t b/share/doc/smm/02.config/5.t
new file mode 100644
index 0000000..81f2a52
--- /dev/null
+++ b/share/doc/smm/02.config/5.t
@@ -0,0 +1,271 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)5.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Sample Configuration Files
+.ne 2i
+.NH
+SAMPLE CONFIGURATION FILES
+.PP
+In this section we will consider how to configure a
+sample VAX-11/780 system on which the hardware can be
+reconfigured to guard against various hardware mishaps.
+We then study the rules needed to configure a VAX-11/750
+to run in a networking environment.
+.NH 2
+VAX-11/780 System
+.PP
+Our VAX-11/780 is configured with hardware
+recommended in the document ``Hints on Configuring a VAX for 4.2BSD''
+(this is one of the high-end configurations).
+Table 1 lists the pertinent hardware to be configured.
+.DS B
+.TS
+box;
+l | l | l | l | l
+l | l | l | l | l.
+Item Vendor Connection Name Reference
+_
+cpu DEC VAX780
+MASSBUS controller Emulex nexus ? mba0 hp(4)
+disk Fujitsu mba0 hp0
+disk Fujitsu mba0 hp1
+MASSBUS controller Emulex nexus ? mba1
+disk Fujitsu mba1 hp2
+disk Fujitsu mba1 hp3
+UNIBUS adapter DEC nexus ?
+tape controller Emulex uba0 tm0 tm(4)
+tape drive Kennedy tm0 te0
+tape drive Kennedy tm0 te1
+terminal multiplexor Emulex uba0 dh0 dh(4)
+terminal multiplexor Emulex uba0 dh1
+terminal multiplexor Emulex uba0 dh2
+.TE
+.DE
+.ce
+Table 1. VAX-11/780 Hardware support.
+.LP
+We will call this machine ANSEL and construct a configuration
+file one step at a time.
+.PP
+The first step is to fill in the global configuration parameters.
+The machine is a VAX, so the
+.I "machine type"
+is ``vax''. We will assume this system will
+run only on this one processor, so the
+.I "cpu type"
+is ``VAX780''. The options are empty since this is going to
+be a ``vanilla'' VAX. The system identifier, as mentioned before,
+is ``ANSEL,'' and the maximum number of users we plan to support is
+about 40. Thus the beginning of the configuration file looks like
+this:
+.DS
+.ta 1.5i 2.5i 4.0i
+#
+# ANSEL VAX (a picture perfect machine)
+#
+machine vax
+cpu VAX780
+timezone 8 dst
+ident ANSEL
+maxusers 40
+.DE
+.PP
+To this we must then add the specifications for three
+system images. The first will be our standard system with the
+root on ``hp0'' and swapping on the same drive as the root.
+The second will have the root file system in the same location,
+but swap space interleaved among drives on each controller.
+Finally, the third will be a generic system,
+to allow us to boot off any of the four disk drives.
+.DS
+.ta 1.5i 2.5i
+config kernel root on hp0
+config hpkernel root on hp0 swap on hp0 and hp2
+config genkernel swap generic
+.DE
+.PP
+Finally, the hardware must be specified. Let us first just try
+transcribing the information from Table 1.
+.DS
+.ta 1.5i 2.5i 4.0i
+controller mba0 at nexus ?
+disk hp0 at mba0 disk 0
+disk hp1 at mba0 disk 1
+controller mba1 at nexus ?
+disk hp2 at mba1 disk 2
+disk hp3 at mba1 disk 3
+controller uba0 at nexus ?
+controller tm0 at uba0 csr 0172520 vector tmintr
+tape te0 at tm0 drive 0
+tape te1 at tm0 drive 1
+device dh0 at uba0 csr 0160020 vector dhrint dhxint
+device dm0 at uba0 csr 0170500 vector dmintr
+device dh1 at uba0 csr 0160040 vector dhrint dhxint
+device dh2 at uba0 csr 0160060 vector dhrint dhxint
+.DE
+.LP
+(Oh, I forgot to mention one panel of the terminal multiplexor
+has modem control, thus the ``dm0'' device.)
+.PP
+This will suffice, but leaves us with little flexibility. Suppose
+our first disk controller were to break. We would like to recable the
+drives normally on the second controller so that all our disks could
+still be used without reconfiguring the system. To do this we wildcard
+the MASSBUS adapter connections and also the slave numbers. Further,
+we wildcard the UNIBUS adapter connections in case we decide some time
+in the future to purchase another adapter to offload the single UNIBUS
+we currently have. The revised device specifications would then be:
+.DS
+.ta 1.5i 2.5i 4.0i
+controller mba0 at nexus ?
+disk hp0 at mba? disk ?
+disk hp1 at mba? disk ?
+controller mba1 at nexus ?
+disk hp2 at mba? disk ?
+disk hp3 at mba? disk ?
+controller uba0 at nexus ?
+controller tm0 at uba? csr 0172520 vector tmintr
+tape te0 at tm0 drive 0
+tape te1 at tm0 drive 1
+device dh0 at uba? csr 0160020 vector dhrint dhxint
+device dm0 at uba? csr 0170500 vector dmintr
+device dh1 at uba? csr 0160040 vector dhrint dhxint
+device dh2 at uba? csr 0160060 vector dhrint dhxint
+.DE
+.LP
+The completed configuration file for ANSEL is shown in Appendix C.
+.NH 2
+VAX-11/750 with network support
+.PP
+Our VAX-11/750 system will be located on two 10Mb/s Ethernet
+local area networks and also the DARPA Internet. The system
+will have a MASSBUS drive for the root file system and two
+UNIBUS drives. Paging is interleaved among all three drives.
+We have sold our standard DEC terminal multiplexors since this
+machine will be accessed solely through the network. This
+machine is not intended to have a large user community, it
+does not have a great deal of memory. First the global parameters:
+.DS
+.ta 1.5i 2.5i 4.0i
+#
+# UCBVAX (Gateway to the world)
+#
+machine vax
+cpu "VAX780"
+cpu "VAX750"
+ident UCBVAX
+timezone 8 dst
+maxusers 32
+options INET
+options NS
+.DE
+.PP
+The multiple cpu types allow us to replace UCBVAX with a
+more powerful cpu without reconfiguring the system. The
+value of 32 given for the maximum number of users is done to
+force the system data structures to be over-allocated. That
+is desirable on this machine because, while it is not expected
+to support many users, it is expected to perform a great deal
+of work.
+The ``INET'' indicates that we plan to use the
+DARPA standard Internet protocols on this machine,
+and ``NS'' also includes support for Xerox NS protocols.
+Note that unlike 4.2BSD configuration files,
+the network protocol options do not require corresponding pseudo devices.
+.PP
+The system images and disks are configured next.
+.DS
+.ta 1.5i 2.5i 4.0i
+config kernel root on hp swap on hp and rk0 and rk1
+config upkernel root on up
+config hkkernel root on hk swap on rk0 and rk1
+
+controller mba0 at nexus ?
+controller uba0 at nexus ?
+disk hp0 at mba? drive 0
+disk hp1 at mba? drive 1
+controller sc0 at uba? csr 0176700 vector upintr
+disk up0 at sc0 drive 0
+disk up1 at sc0 drive 1
+controller hk0 at uba? csr 0177440 vector rkintr
+disk rk0 at hk0 drive 0
+disk rk1 at hk0 drive 1
+.DE
+.PP
+UCBVAX requires heavy interleaving of its paging area to keep up
+with all the mail traffic it handles. The limiting factor on this
+system's performance is usually the number of disk arms, as opposed
+to memory or cpu cycles. The extra UNIBUS controller, ``sc0'',
+is in case the MASSBUS controller breaks and a spare controller
+must be installed (most of our old UNIBUS controllers have been
+replaced with the newer MASSBUS controllers, so we have a number
+of these around as spares).
+.PP
+Finally, we add in the network devices.
+Pseudo terminals are needed to allow users to
+log in across the network (remember the only hardwired terminal
+is the console).
+The software loopback device is used for on-machine communications.
+The connection to the Internet is through
+an IMP, this requires yet another
+.I pseudo-device
+(in addition to the actual hardware device used by the
+IMP software). And, finally, there are the two Ethernet devices.
+These use a special protocol, the Address Resolution Protocol (ARP),
+to map between Internet and Ethernet addresses. Thus, yet another
+.I pseudo-device
+is needed. The additional device specifications are show below.
+.DS
+.ta 1.5i 2.5i 4.0i
+pseudo-device pty
+pseudo-device loop
+pseudo-device imp
+device acc0 at uba? csr 0167600 vector accrint accxint
+pseudo-device ether
+device ec0 at uba? csr 0164330 vector ecrint eccollide ecxint
+device il0 at uba? csr 0164000 vector ilrint ilcint
+.DE
+.LP
+The completed configuration file for UCBVAX is shown in Appendix C.
+.NH 2
+Miscellaneous comments
+.PP
+It should be noted in these examples that neither system was
+configured to use disk quotas or the 4.1BSD compatibility mode.
+To use these optional facilities, and others, we would probably
+clean out our current configuration, reconfigure the system, then
+recompile and relink the system image(s). This could, of course,
+be avoided by figuring out which relocatable object files are
+affected by the reconfiguration, then reconfiguring and recompiling
+only those files affected by the configuration change. This technique
+should be used carefully.
diff --git a/share/doc/smm/02.config/6.t b/share/doc/smm/02.config/6.t
new file mode 100644
index 0000000..49f6e91
--- /dev/null
+++ b/share/doc/smm/02.config/6.t
@@ -0,0 +1,233 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)6.t 8.1 (Berkeley) 6/8/93
+.\" $FreeBSD$
+.\"
+.\".ds RH "Adding New Devices
+.ne 2i
+.NH
+ADDING NEW SYSTEM SOFTWARE
+.PP
+This section is not for the novice, it describes
+some of the inner workings of the configuration process as
+well as the pertinent parts of the system autoconfiguration process.
+It is intended to give
+those people who intend to install new device drivers and/or
+other system facilities sufficient information to do so in the
+manner which will allow others to easily share the changes.
+.PP
+This section is broken into four parts:
+.IP \(bu 3
+general guidelines to be followed in modifying system code,
+.IP \(bu 3
+how to add non-standard system facilities to 4.4BSD,
+.IP \(bu 3
+how to add a device driver to 4.4BSD, and
+.NH 2
+Modifying system code
+.PP
+If you wish to make site-specific modifications to the system
+it is best to bracket them with
+.DS
+#ifdef SITENAME
+\&...
+#endif
+.DE
+to allow your source to be easily distributed to others, and
+also to simplify \fIdiff\fP\|(1) listings. If you choose not
+to use a source code control system (e.g. SCCS, RCS), and
+perhaps even if you do, it is
+recommended that you save the old code with something
+of the form:
+.DS
+#ifndef SITENAME
+\&...
+#endif
+.DE
+We try to isolate our site-dependent code in individual files
+which may be configured with pseudo-device specifications.
+.PP
+Indicate machine-specific code with ``#ifdef vax'' (or other machine,
+as appropriate).
+4.4BSD underwent extensive work to make it extremely portable to
+machines with similar architectures\- you may someday find
+yourself trying to use a single copy of the source code on
+multiple machines.
+.NH 2
+Adding non-standard system facilities
+.PP
+This section considers the work needed to augment
+.IR config 's
+data base files for non-standard system facilities.
+.I Config
+uses a set of files that list the source modules that may be required
+when building a system.
+The data bases are taken from the directory in which
+.I config
+is run, normally /sys/conf.
+Three such files may be used:
+.IR files ,
+.IR files .machine,
+and
+.IR files .ident.
+The first is common to all systems,
+the second contains files unique to a single machine type,
+and the third is an optional list of modules for use on a specific machine.
+This last file may override specifications in the first two.
+The format of the
+.I files
+file has grown somewhat complex over time. Entries are normally of
+the form
+.IP
+.nf
+.DT
+\fIdir/source.c\fP \fItype\fP \fIoption-list\fP \fImodifiers\fP
+.LP
+for example,
+.IP
+.nf
+.DT
+\fIvaxuba/foo.c\fP \fBoptional\fP foo \fBdevice-driver\fP
+.LP
+The
+.I type
+is one of
+.B standard
+or
+.BR optional .
+Files marked as standard are included in all system configurations.
+Optional file specifications include a list of one or more system
+options that together require the inclusion of this module.
+The options in the list may be either names of devices that may
+be in the configuration file,
+or the names of system options that may be defined.
+An optional file may be listed multiple times with different options;
+if all of the options for any of the entries are satisfied,
+the module is included.
+.PP
+If a file is specified as a
+.IR device-driver ,
+any special compilation options for device drivers will be invoked.
+On the VAX this results in the use of the
+.B \-i
+option for the C optimizer. This is required when pointer references
+are made to memory locations in the VAX I/O address space.
+.PP
+Two other optional keywords modify the usage of the file.
+.I Config
+understands that certain files are used especially for
+kernel profiling. These files are indicated in the
+.I files
+files with a
+.I profiling-routine
+keyword. For example, the current profiling subroutines
+are sequestered off in a separate file with the following
+entry:
+.IP
+.nf
+.DT
+\fIsys/subr_mcount.c\fP \fBoptional\fP \fBprofiling-routine\fP
+.fi
+.LP
+The
+.I profiling-routine
+keyword forces
+.I config
+not to compile the source file with the
+.B \-pg
+option.
+.PP
+The second keyword which can be of use is the
+.I config-dependent
+keyword. This causes
+.I config
+to compile the indicated module with the global configuration
+parameters. This allows certain modules, such as
+.I machdep.c
+to size system data structures based on the maximum number
+of users configured for the system.
+.NH 2
+Adding device drivers to 4.4BSD
+.PP
+The I/O system and
+.I config
+have been designed to easily allow new device support to be added.
+The system source directories are organized as follows:
+.DS
+.TS
+lw(1.0i) l.
+/sys/h machine independent include files
+/sys/sys machine-independent system source files
+/sys/conf site configuration files and basic templates
+/sys/net network-protocol-independent, but network-related code
+/sys/netinet DARPA Internet code
+/sys/netimp IMP support code
+/sys/netns Xerox NS code
+/sys/vax VAX-specific mainline code
+/sys/vaxif VAX network interface code
+/sys/vaxmba VAX MASSBUS device drivers and related code
+/sys/vaxuba VAX UNIBUS device drivers and related code
+.TE
+.DE
+.PP
+Existing block and character device drivers for the VAX
+reside in ``/sys/vax'', ``/sys/vaxmba'', and ``/sys/vaxuba''. Network
+interface drivers reside in ``/sys/vaxif''. Any new device
+drivers should be placed in the appropriate source code directory
+and named so as not to conflict with existing devices.
+Normally, definitions for things like device registers are placed in
+a separate file in the same directory. For example, the ``dh''
+device driver is named ``dh.c'' and its associated include file is
+named ``dhreg.h''.
+.PP
+Once the source for the device driver has been placed in a directory,
+the file ``/sys/conf/files.machine'', and possibly
+``/sys/conf/devices.machine'' should be modified. The
+.I files
+files in the conf directory contain a line for each C source or binary-only
+file in the system. Those files which are machine independent are
+located in ``/sys/conf/files,'' while machine specific files
+are in ``/sys/conf/files.machine.'' The ``devices.machine'' file
+is used to map device names to major block device numbers. If the device
+driver being added provides support for a new disk
+you will want to modify this file (the format is obvious).
+.PP
+In addition to including the driver in the
+.I files
+file, it must also be added to the device configuration tables. These
+are located in ``/sys/vax/conf.c'', or similar for machines other than
+the VAX. If you don't understand what to add to this file, you should
+study an entry for an existing driver.
+Remember that the position in the
+device table specifies the major device number.
+The block major number is needed in the ``devices.machine'' file
+if the device is a disk.
diff --git a/share/doc/smm/02.config/Makefile b/share/doc/smm/02.config/Makefile
index 26ed70a..716eeda 100644
--- a/share/doc/smm/02.config/Makefile
+++ b/share/doc/smm/02.config/Makefile
@@ -5,6 +5,5 @@ VOLUME= smm/02.config
SRCS= 0.t 1.t 2.t 3.t 4.t 5.t 6.t a.t b.t c.t d.t e.t
MACROS= -ms
USE_TBL=
-SRCDIR= ${.CURDIR}/../../../../usr.sbin/config/SMM.doc
.include <bsd.doc.mk>
diff --git a/share/doc/smm/02.config/a.t b/share/doc/smm/02.config/a.t
new file mode 100644
index 0000000..dfcb954
--- /dev/null
+++ b/share/doc/smm/02.config/a.t
@@ -0,0 +1,162 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)a.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Configuration File Grammar
+.bp
+.LG
+.B
+.ce
+APPENDIX A. CONFIGURATION FILE GRAMMAR
+.sp
+.R
+.NL
+.PP
+The following grammar is a compressed form of the actual
+\fIyacc\fP\|(1) grammar used by
+.I config
+to parse configuration files.
+Terminal symbols are shown all in upper case, literals
+are emboldened; optional clauses are enclosed in brackets, ``[''
+and ``]''; zero or more instantiations are denoted with ``*''.
+.sp
+.nf
+.DT
+Configuration ::= [ Spec \fB;\fP ]*
+
+Spec ::= Config_spec
+ | Device_spec
+ | \fBtrace\fP
+ | /* lambda */
+
+/* configuration specifications */
+
+Config_spec ::= \fBmachine\fP ID
+ | \fBcpu\fP ID
+ | \fBoptions\fP Opt_list
+ | \fBident\fP ID
+ | System_spec
+ | \fBtimezone\fP [ \fB\-\fP ] NUMBER [ \fBdst\fP [ NUMBER ] ]
+ | \fBtimezone\fP [ \fB\-\fP ] FPNUMBER [ \fBdst\fP [ NUMBER ] ]
+ | \fBmaxusers\fP NUMBER
+
+/* system configuration specifications */
+
+System_spec ::= \fBconfig\fP ID System_parameter [ System_parameter ]*
+
+System_parameter ::= swap_spec | root_spec | dump_spec | arg_spec
+
+swap_spec ::= \fBswap\fP [ \fBon\fP ] swap_dev [ \fBand\fP swap_dev ]*
+
+swap_dev ::= dev_spec [ \fBsize\fP NUMBER ]
+
+root_spec ::= \fBroot\fP [ \fBon\fP ] dev_spec
+
+dump_spec ::= \fBdumps\fP [ \fBon\fP ] dev_spec
+
+arg_spec ::= \fBargs\fP [ \fBon\fP ] dev_spec
+
+dev_spec ::= dev_name | major_minor
+
+major_minor ::= \fBmajor\fP NUMBER \fBminor\fP NUMBER
+
+dev_name ::= ID [ NUMBER [ ID ] ]
+
+/* option specifications */
+
+Opt_list ::= Option [ \fB,\fP Option ]*
+
+Option ::= ID [ \fB=\fP Opt_value ]
+
+Opt_value ::= ID | NUMBER
+
+Mkopt_list ::= Mkoption [ \fB,\fP Mkoption ]*
+
+Mkoption ::= ID \fB=\fP Opt_value
+
+/* device specifications */
+
+Device_spec ::= \fBdevice\fP Dev_name Dev_info Int_spec
+ | \fBmaster\fP Dev_name Dev_info
+ | \fBdisk\fP Dev_name Dev_info
+ | \fBtape\fP Dev_name Dev_info
+ | \fBcontroller\fP Dev_name Dev_info [ Int_spec ]
+ | \fBpseudo-device\fP Dev [ NUMBER ]
+
+Dev_name ::= Dev NUMBER
+
+Dev ::= \fBuba\fP | \fBmba\fP | ID
+
+Dev_info ::= Con_info [ Info ]*
+
+Con_info ::= \fBat\fP Dev NUMBER
+ | \fBat\fP \fBnexus\fP NUMBER
+
+Info ::= \fBcsr\fP NUMBER
+ | \fBdrive\fP NUMBER
+ | \fBslave\fP NUMBER
+ | \fBflags\fP NUMBER
+
+Int_spec ::= \fBvector\fP ID [ ID ]*
+ | \fBpriority\fP NUMBER
+.fi
+.sp
+.SH
+Lexical Conventions
+.LP
+The terminal symbols are loosely defined as:
+.IP ID
+.br
+One or more alphabetics, either upper or lower case, and underscore,
+``_''.
+.IP NUMBER
+.br
+Approximately the C language specification for an integer number.
+That is, a leading ``0x'' indicates a hexadecimal value,
+a leading ``0'' indicates an octal value, otherwise the number is
+expected to be a decimal value. Hexadecimal numbers may use either
+upper or lower case alphabetics.
+.IP FPNUMBER
+.br
+A floating point number without exponent. That is a number of the
+form ``nnn.ddd'', where the fractional component is optional.
+.LP
+In special instances a question mark, ``?'', can be substituted for
+a ``NUMBER'' token. This is used to effect wildcarding in device
+interconnection specifications.
+.LP
+Comments in configuration files are indicated by a ``#'' character
+at the beginning of the line; the remainder of the line is discarded.
+.LP
+A specification
+is interpreted as a continuation of the previous line
+if the first character of the line is tab.
diff --git a/share/doc/smm/02.config/b.t b/share/doc/smm/02.config/b.t
new file mode 100644
index 0000000..901a009
--- /dev/null
+++ b/share/doc/smm/02.config/b.t
@@ -0,0 +1,137 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)b.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Device Defaulting Rules
+.bp
+.LG
+.B
+.ce
+APPENDIX B. RULES FOR DEFAULTING SYSTEM DEVICES
+.sp
+.R
+.NL
+.PP
+When \fIconfig\fP processes a ``config'' rule which does
+not fully specify the location of the root file system,
+paging area(s), device for system dumps, and device for
+argument list processing it applies a set of rules to
+define those values left unspecified. The following list
+of rules are used in defaulting system devices.
+.IP 1) 3
+If a root device is not specified, the swap
+specification must indicate a ``generic'' system is to be built.
+.IP 2) 3
+If the root device does not specify a unit number, it
+defaults to unit 0.
+.IP 3) 3
+If the root device does not include a partition specification,
+it defaults to the ``a'' partition.
+.IP 4) 3
+If no swap area is specified, it defaults to the ``b''
+partition of the root device.
+.IP 5) 3
+If no device is specified for processing argument lists, the
+first swap partition is selected.
+.IP 6) 3
+If no device is chosen for system dumps, the first swap
+partition is selected (see below to find out where dumps are
+placed within the partition).
+.PP
+The following table summarizes the default partitions selected
+when a device specification is incomplete, e.g. ``hp0''.
+.DS
+.TS
+l l.
+Type Partition
+_
+root ``a''
+swap ``b''
+args ``b''
+dumps ``b''
+.TE
+.DE
+.SH
+Multiple swap/paging areas
+.PP
+When multiple swap partitions are specified, the system treats the
+first specified as a ``primary'' swap area which is always used.
+The remaining partitions are then interleaved into the paging
+system at the time a
+.IR swapon (2)
+system call is made. This is normally done at boot time with
+a call to
+.IR swapon (8)
+from the /etc/rc file.
+.SH
+System dumps
+.PP
+System dumps are automatically taken after a system crash,
+provided the device driver for the ``dumps'' device supports
+this. The dump contains the contents of memory, but not
+the swap areas. Normally the dump device is a disk in
+which case the information is copied to a location at the
+back of the partition. The dump is placed in the back of the
+partition because the primary swap and dump device are commonly
+the same device and this allows the system to be rebooted without
+immediately overwriting the saved information. When a dump has
+occurred, the system variable \fIdumpsize\fP
+is set to a non-zero value indicating the size (in bytes) of
+the dump. The \fIsavecore\fP\|(8)
+program then copies the information from the dump partition to
+a file in a ``crash'' directory and also makes a copy of the
+system which was running at the time of the crash (usually
+``/kernel''). The offset to the system dump is defined in the
+system variable \fIdumplo\fP (a sector offset from
+the front of the dump partition). The
+.I savecore
+program operates by reading the contents of \fIdumplo\fP, \fIdumpdev\fP,
+and \fIdumpmagic\fP from /dev/kmem, then comparing the value
+of \fIdumpmagic\fP read from /dev/kmem to that located in
+corresponding location in the dump area of the dump partition.
+If a match is found,
+.I savecore
+assumes a crash occurred and reads \fIdumpsize\fP from the dump area
+of the dump partition. This value is then used in copying the
+system dump. Refer to
+\fIsavecore\fP\|(8)
+for more information about its operation.
+.PP
+The value \fIdumplo\fP is calculated to be
+.DS
+\fIdumpdev-size\fP \- \fImemsize\fP
+.DE
+where \fIdumpdev-size\fP is the size of the disk partition
+where system dumps are to be placed, and
+\fImemsize\fP is the size of physical memory.
+If the disk partition is not large enough to hold a full
+dump, \fIdumplo\fP is set to 0 (the start of the partition).
diff --git a/share/doc/smm/02.config/c.t b/share/doc/smm/02.config/c.t
new file mode 100644
index 0000000..67b63ec
--- /dev/null
+++ b/share/doc/smm/02.config/c.t
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)c.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Sample Config Files
+.bp
+.LG
+.B
+.ce
+APPENDIX C. SAMPLE CONFIGURATION FILES
+.sp
+.R
+.NL
+.PP
+The following configuration files are developed in section 5;
+they are included here for completeness.
+.sp 2
+.nf
+.ta 1.5i 2.5i 4.0i
+#
+# ANSEL VAX (a picture perfect machine)
+#
+machine vax
+cpu VAX780
+timezone 8 dst
+ident ANSEL
+maxusers 40
+
+config kernel root on hp0
+config hpkernel root on hp0 swap on hp0 and hp2
+config genkernel swap generic
+
+controller mba0 at nexus ?
+disk hp0 at mba? disk ?
+disk hp1 at mba? disk ?
+controller mba1 at nexus ?
+disk hp2 at mba? disk ?
+disk hp3 at mba? disk ?
+controller uba0 at nexus ?
+controller tm0 at uba? csr 0172520 vector tmintr
+tape te0 at tm0 drive 0
+tape te1 at tm0 drive 1
+device dh0 at uba? csr 0160020 vector dhrint dhxint
+device dm0 at uba? csr 0170500 vector dmintr
+device dh1 at uba? csr 0160040 vector dhrint dhxint
+device dh2 at uba? csr 0160060 vector dhrint dhxint
+.bp
+#
+# UCBVAX - Gateway to the world
+#
+machine vax
+cpu "VAX780"
+cpu "VAX750"
+ident UCBVAX
+timezone 8 dst
+maxusers 32
+options INET
+options NS
+
+config kernel root on hp swap on hp and rk0 and rk1
+config upkernel root on up
+config hkkernel root on hk swap on rk0 and rk1
+
+controller mba0 at nexus ?
+controller uba0 at nexus ?
+disk hp0 at mba? drive 0
+disk hp1 at mba? drive 1
+controller sc0 at uba? csr 0176700 vector upintr
+disk up0 at sc0 drive 0
+disk up1 at sc0 drive 1
+controller hk0 at uba? csr 0177440 vector rkintr
+disk rk0 at hk0 drive 0
+disk rk1 at hk0 drive 1
+pseudo-device pty
+pseudo-device loop
+pseudo-device imp
+device acc0 at uba? csr 0167600 vector accrint accxint
+pseudo-device ether
+device ec0 at uba? csr 0164330 vector ecrint eccollide ecxint
+device il0 at uba? csr 0164000 vector ilrint ilcint
diff --git a/share/doc/smm/02.config/d.t b/share/doc/smm/02.config/d.t
new file mode 100644
index 0000000..db9ab80
--- /dev/null
+++ b/share/doc/smm/02.config/d.t
@@ -0,0 +1,272 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)d.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Data Structure Sizing Rules
+.bp
+.LG
+.B
+.ce
+APPENDIX D. VAX KERNEL DATA STRUCTURE SIZING RULES
+.sp
+.R
+.NL
+.PP
+Certain system data structures are sized at compile time
+according to the maximum number of simultaneous users expected,
+while others are calculated at boot time based on the
+physical resources present, e.g. memory. This appendix lists
+both sets of rules and also includes some hints on changing
+built-in limitations on certain data structures.
+.SH
+Compile time rules
+.PP
+The file \fI/sys/conf\|/param.c\fP contains the definitions of
+almost all data structures sized at compile time. This file
+is copied into the directory of each configured system to allow
+configuration-dependent rules and values to be maintained.
+(Each copy normally depends on the copy in /sys/conf,
+and global modifications cause the file to be recopied unless
+the makefile is modified.)
+The rules implied by its contents are summarized below (here
+MAXUSERS refers to the value defined in the configuration file
+in the ``maxusers'' rule).
+Most limits are computed at compile time and stored in global variables
+for use by other modules; they may generally be patched in the system
+binary image before rebooting to test new values.
+.IP \fBnproc\fP
+.br
+The maximum number of processes which may be running at any time.
+It is referred to in other calculations as NPROC and is defined to be
+.DS
+20 + 8 * MAXUSERS
+.DE
+.IP \fBntext\fP
+.br
+The maximum number of active shared text segments.
+The constant is intended to allow for network servers and common commands
+that remain in the table.
+It is defined as
+.DS
+36 + MAXUSERS.
+.DE
+.IP \fBninode\fP
+.br
+The maximum number of files in the file system which may be
+active at any time. This includes files in use by users, as
+well as directory files being read or written by the system
+and files associated with bound sockets in the UNIX IPC domain.
+It is defined as
+.DS
+(NPROC + 16 + MAXUSERS) + 32
+.DE
+.IP \fBnfile\fP
+.br
+The number of ``file table'' structures. One file
+table structure is used for each open, unshared, file descriptor.
+Multiple file descriptors may reference a single file table
+entry when they are created through a \fIdup\fP call, or as the
+result of a \fIfork\fP. This is defined to be
+.DS
+16 * (NPROC + 16 + MAXUSERS) / 10 + 32
+.DE
+.IP \fBncallout\fP
+.br
+The number of ``callout'' structures. One callout
+structure is used per internal system event handled with
+a timeout. Timeouts are used for terminal delays,
+watchdog routines in device drivers, protocol timeout processing, etc.
+This is defined as
+.DS
+16 + NPROC
+.DE
+.IP \fBnclist\fP
+.br
+The number of ``c-list'' structures. C-list structures are
+used in terminal I/O, and currently each holds 60 characters.
+Their number is defined as
+.DS
+60 + 12 * MAXUSERS
+.DE
+.IP \fBnmbclusters\fP
+.br
+The maximum number of pages which may be allocated by the network.
+This is defined as 256 (a quarter megabyte of memory) in /sys/h/mbuf.h.
+In practice, the network rarely uses this much memory. It starts off
+by allocating 8 kilobytes of memory, then requesting more as
+required. This value represents an upper bound.
+.IP \fBnquota\fP
+.br
+The number of ``quota'' structures allocated. Quota structures
+are present only when disc quotas are configured in the system. One
+quota structure is kept per user. This is defined to be
+.DS
+(MAXUSERS * 9) / 7 + 3
+.DE
+.IP \fBndquot\fP
+.br
+The number of ``dquot'' structures allocated. Dquot structures
+are present only when disc quotas are configured in the system.
+One dquot structure is required per user, per active file system quota.
+That is, when a user manipulates a file on a file system on which
+quotas are enabled, the information regarding the user's quotas on
+that file system must be in-core. This information is cached, so
+that not all information must be present in-core all the time.
+This is defined as
+.DS
+NINODE + (MAXUSERS * NMOUNT) / 4
+.DE
+where NMOUNT is the maximum number of mountable file systems.
+.LP
+In addition to the above values, the system page tables (used to
+map virtual memory in the kernel's address space) are sized at
+compile time by the SYSPTSIZE definition in the file /sys/vax/vmparam.h.
+This is defined to be
+.DS
+20 + MAXUSERS
+.DE
+pages of page tables.
+Its definition affects
+the size of many data structures allocated at boot time because
+it constrains the amount of virtual memory which may be addressed
+by the running system. This is often the limiting factor
+in the size of the buffer cache, in which case a message is printed
+when the system configures at boot time.
+.SH
+Run-time calculations
+.PP
+The most important data structures sized at run-time are those used in
+the buffer cache. Allocation is done by allocating physical memory
+(and system virtual memory) immediately after the system
+has been started up; look in the file /sys/vax/machdep.c.
+The amount of physical memory which may be allocated to the buffer
+cache is constrained by the size of the system page tables, among
+other things. While the system may calculate
+a large amount of memory to be allocated to the buffer cache,
+if the system page
+table is too small to map this physical
+memory into the virtual address space
+of the system, only as much as can be mapped will be used.
+.PP
+The buffer cache is comprised of a number of ``buffer headers''
+and a pool of pages attached to these headers. Buffer headers
+are divided into two categories: those used for swapping and
+paging, and those used for normal file I/O. The system tries
+to allocate 10% of the first two megabytes and 5% of the remaining
+available physical memory for the buffer
+cache (where \fIavailable\fP does not count that space occupied by
+the system's text and data segments). If this results in fewer
+than 16 pages of memory allocated, then 16 pages are allocated.
+This value is kept in the initialized variable \fIbufpages\fP
+so that it may be patched in the binary image (to allow tuning
+without recompiling the system),
+or the default may be overridden with a configuration-file option.
+For example, the option \fBoptions BUFPAGES="3200"\fP
+causes 3200 pages (3.2M bytes) to be used by the buffer cache.
+A sufficient number of file I/O buffer headers are then allocated
+to allow each to hold 2 pages each.
+Each buffer maps 8K bytes.
+If the number of buffer pages is larger than can be mapped
+by the buffer headers, the number of pages is reduced.
+The number of buffer headers allocated
+is stored in the global variable \fInbuf\fP,
+which may be patched before the system is booted.
+The system option \fBoptions NBUF="1000"\fP forces the allocation
+of 1000 buffer headers.
+Half as many swap I/O buffer headers as file I/O buffers
+are allocated,
+but no more than 256.
+.SH
+System size limitations
+.PP
+As distributed, the sum of the virtual sizes of the core-resident
+processes is limited to 256M bytes. The size of the text
+segment of a single process is currently limited to 6M bytes.
+It may be increased to no greater than the data segment size limit
+(see below) by redefining MAXTSIZ.
+This may be done with a configuration file option,
+e.g. \fBoptions MAXTSIZ="(10*1024*1024)"\fP
+to set the limit to 10 million bytes.
+Other per-process limits discussed here may be changed with similar options
+with names given in parentheses.
+Soft, user-changeable limits are set to 512K bytes for stack (DFLSSIZ)
+and 6M bytes for the data segment (DFLDSIZ) by default;
+these may be increased up to the hard limit
+with the \fIsetrlimit\fP\|(2) system call.
+The data and stack segment size hard limits are set by a system configuration
+option to one of 17M, 33M or 64M bytes.
+One of these sizes is chosen based on the definition of MAXDSIZ;
+with no option, the limit is 17M bytes; with an option
+\fBoptions MAXDSIZ="(32*1024*1024)"\fP (or any value between 17M and 33M),
+the limit is increased to 33M bytes, and values larger than 33M
+result in a limit of 64M bytes.
+You must be careful in doing this that you have adequate paging space.
+As normally configured , the system has 16M or 32M bytes per paging area,
+depending on disk size.
+The best way to get more space is to provide multiple, thereby
+interleaved, paging areas.
+Increasing the virtual memory limits results in interleaving of
+swap space in larger sections (from 500K bytes to 1M or 2M bytes).
+.PP
+By default, the virtual memory system allocates enough memory
+for system page tables mapping user page tables
+to allow 256 megabytes of simultaneous active virtual memory.
+That is, the sum of the virtual memory sizes of all (completely- or partially-)
+resident processes can not exceed this limit.
+If the limit is exceeded, some process(es) must be swapped out.
+To increase the amount of resident virtual space possible,
+you can alter the constant USRPTSIZE (in
+/sys/vax/vmparam.h).
+Each page of system page tables allows 8 megabytes of user virtual memory.
+.PP
+Because the file system block numbers are stored in
+page table \fIpg_blkno\fP
+entries, the maximum size of a file system is limited to
+2^24 1024 byte blocks. Thus no file system can be larger than 8 gigabytes.
+.PP
+The number of mountable file systems is set at 20 by the definition
+of NMOUNT in /sys/h/param.h.
+This should be sufficient; if not, the value can be increased up to 255.
+If you have many disks, it makes sense to make some of
+them single file systems, and the paging areas don't count in this total.
+.PP
+The limit to the number of files that a process may have open simultaneously
+is set to 64.
+This limit is set by the NOFILE definition in /sys/h/param.h.
+It may be increased arbitrarily, with the caveat that the user structure
+expands by 5 bytes for each file, and thus UPAGES (/sys/vax/machparam.h)
+must be increased accordingly.
+.PP
+The amount of physical memory is currently limited to 64 Mb
+by the size of the index fields in the core-map (/sys/h/cmap.h).
+The limit may be increased by following instructions in that file
+to enlarge those fields.
diff --git a/share/doc/smm/02.config/e.t b/share/doc/smm/02.config/e.t
new file mode 100644
index 0000000..0a9505b
--- /dev/null
+++ b/share/doc/smm/02.config/e.t
@@ -0,0 +1,114 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)e.t 8.1 (Berkeley) 6/8/93
+.\"
+.\".ds RH "Network configuration options
+.bp
+.LG
+.B
+.ce
+APPENDIX E. NETWORK CONFIGURATION OPTIONS
+.sp
+.R
+.NL
+.PP
+The network support in the kernel is self-configuring
+according to the protocol support options (INET and NS) and the network
+hardware discovered during autoconfiguration.
+There are several changes that may be made to customize network behavior
+due to local restrictions.
+Within the Internet protocol routines, the following options
+set in the system configuration file are supported:
+.IP \fBGATEWAY\fP
+.br
+The machine is to be used as a gateway.
+This option currently makes only minor changes.
+First, the size of the network routing hash table is increased.
+Secondly, machines that have only a single hardware network interface
+will not forward IP packets; without this option, they will also refrain
+from sending any error indication to the source of unforwardable packets.
+Gateways with only a single interface are assumed to have missing
+or broken interfaces, and will return ICMP unreachable errors to hosts
+sending them packets to be forwarded.
+.IP \fBTCP_COMPAT_42\fP
+.br
+This option forces the system to limit its initial TCP sequence numbers
+to positive numbers.
+Without this option, 4.4BSD systems may have problems with TCP connections
+to 4.2BSD systems that connect but never transfer data.
+The problem is a bug in the 4.2BSD TCP.
+.IP \fBIPFORWARDING\fP
+.br
+Normally, 4.4BSD machines with multiple network interfaces
+will forward IP packets received that should be resent to another host.
+If the line ``options IPFORWARDING="0"'' is in the system configuration
+file, IP packet forwarding will be disabled.
+.IP \fBIPSENDREDIRECTS\fP
+.br
+When forwarding IP packets, 4.4BSD IP will note when a packet is forwarded
+using the same interface on which it arrived.
+When this is noted, if the source machine is on the directly-attached
+network, an ICMP redirect is sent to the source host.
+If the packet was forwarded using a route to a host or to a subnet,
+a host redirect is sent, otherwise a network redirect is sent.
+The generation of redirects may be inhibited with the configuration
+option ``options IPSENDREDIRECTS="0".''
+.br
+.IP \fBSUBNETSARELOCAL\fP
+TCP calculates a maximum segment size to use for each connection,
+and sends no datagrams larger than that size.
+This size will be no larger than that supported on the outgoing
+interface.
+Furthermore, if the destination is not on the local network,
+the size will be no larger than 576 bytes.
+For this test, other subnets of a directly-connected subnetted
+network are considered to be local unless the line
+``options SUBNETSARELOCAL="0"'' is used in the system configuration file.
+.LP
+The following options are supported by the Xerox NS protocols:
+.IP \fBNSIP\fP
+.br
+This option allows NS IDP datagrams to be encapsulated in Internet IP
+packets for transmission to a collaborating NSIP host.
+This may be used to pass IDP packets through IP-only link layer networks.
+See
+.IR nsip (4P)
+for details.
+.IP \fBTHREEWAYSHAKE\fP
+.br
+The NS Sequenced Packet Protocol does not require a three-way handshake
+before considering a connection to be in the established state.
+(A three-way handshake consists of a connection request, an acknowledgement
+of the request along with a symmetrical opening indication,
+and then an acknowledgement of the reciprocal opening packet.)
+This option forces a three-way handshake before data may be transmitted
+on Sequenced Packet sockets.
diff --git a/share/doc/smm/02.config/spell.ok b/share/doc/smm/02.config/spell.ok
new file mode 100644
index 0000000..dfc5df1
--- /dev/null
+++ b/share/doc/smm/02.config/spell.ok
@@ -0,0 +1,305 @@
+# $FreeBSD$
+ACC
+ANSEL
+ARP
+Autoconfiguration
+BUFPAGES
+CANTWAIT
+CH
+COMPAT
+CSS
+Co
+Config
+Config''SMM:2
+DCLR
+DFLDSIZ
+DFLSSIZ
+DFUNNY
+DHAHA
+DMA
+Dev
+Dquot
+ECC
+EMULEX
+Emulex
+Ethernet
+FPNUMBER
+FUNNY,HAHA
+HAVEBDP
+ICMP
+IDP
+IE
+INET
+IP
+IPC
+IPFORWARDING
+IPL
+IPSENDREDIRECTS
+Info
+Karels
+LH
+Leffler
+MASSBUS
+MAXDSIZ
+MAXTSIZ
+Makefile
+Mb
+MicroVAX
+Mkopt
+Mkoption
+NBUF
+NEED16
+NEEDBDP
+NINODE
+NMOUNT
+NOFILE
+NPROC
+NS
+NSC
+NSIP
+NUP
+PST
+RCS
+RDY
+RH
+RK07
+RK611
+SCCS
+SITENAME
+SMM:2
+SUBNETSARELOCAL
+SYSPTSIZE
+TCP
+THREEWAYSHAKE
+Timezone
+UCBVAX
+UDP
+UNIBUS
+UPAGES
+UPCS2
+USRPTSIZE
+VAX
+VAX630
+VAX730
+VAX750
+VAX780
+VAX8600
+VAXWELL
+VAXen
+Vax
+Vaxwell
+acc0
+accrint
+accxint
+addr
+arg
+args
+assym.s
+autoconfiguration
+autoconfigure
+autoconfigured
+backpointer
+badaddr
+blkno
+br
+br5
+buf
+bufpages
+buses
+caddr
+callout
+catchall
+cmap.h
+cmd
+conf
+conf.c
+config
+csr
+ct.c
+ctlr
+cvec
+datagrams
+define''s
+dev
+devices.machine
+dgo
+dh.c
+dh0
+dh1
+dh2
+dhreg.h
+dhrint
+dhxint
+dinfo
+dk
+dk.h
+dm0
+dmintr
+dname
+dquot
+dst
+dumpdev
+dumplo
+dumpmagic
+dumpsize
+dz.c
+dz0
+dzrint
+dzxint
+ec0
+eccollide
+ecrint
+ecxint
+endif
+es
+files.machine
+filesystem
+foo
+foo.c
+genkernel
+gettimeofday
+gigabytes
+gprof
+hardwired
+hd
+hk
+hk0
+hkkernel
+howmany
+hp0
+hp0b
+hp1
+hp2
+hp3
+hpkernel
+ht0
+hz
+ident
+ifdef
+ifndef
+il0
+ilcint
+ilrint
+info
+intr
+ioconf.c
+kgmon
+linterrs
+loopback
+machdep.c
+machparam.h
+makefile
+makelinks
+makeoptions
+maxusers
+mba
+mba0
+mba1
+mbuf.h
+mcount.c
+memsize
+minfo
+mname
+moniker
+mspw
+nbuf
+ncallout
+nclist
+ndquot
+ndrive
+netimp
+netinet
+netns
+netstat
+nexi
+nexus
+nfile
+ninode
+nmbclusters
+nnn.ddd
+nproc
+nquota
+nsip
+ntext
+optionlist
+param.c
+param.h
+pathnames
+pg
+physaddr
+pty
+rc
+reg
+rk.c
+rk0
+rk1
+rkintr
+savecore
+sc
+sc0
+sc1
+scdriver
+setrlimit
+sizeof
+softc
+source.c
+subr
+swapxxx.c
+sysname
+te0
+te1
+timezone
+tm0
+tmintr
+tu0
+uba
+uba.c
+uba0
+ubago
+uballoc
+ubamem
+ubanum
+ubareg.h
+ubarelse
+ubavar.h
+ubglue.s
+ubinfo
+ud
+ui
+um
+up.c
+up0
+up1
+up2
+upaddr
+upattach
+upba
+upcs1
+upcs2
+updevice
+updgo
+updinfo
+updtab
+upintr
+upip
+upmaptype
+upminfo
+upprobe
+upslave
+upstd
+upkernel
+upwatch
+upwstart
+value,name2
+value2
+vax
+vaxif
+vaxmba
+vaxuba
+vmparam.h
+kernel
+wildcard
+wildcarded
+wildcarding
+xclu
+xxx
diff --git a/share/doc/smm/03.fsck/0.t b/share/doc/smm/03.fsck/0.t
new file mode 100644
index 0000000..5fe189d
--- /dev/null
+++ b/share/doc/smm/03.fsck/0.t
@@ -0,0 +1,147 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\" @(#)0.t 8.1 (Berkeley) 6/8/93
+.\"
+.if n .ND
+.TL
+Fsck_ffs \- The UNIX\(dg File System Check Program
+.EH 'SMM:3-%''The \s-2UNIX\s+2 File System Check Program'
+.OH 'The \s-2UNIX\s+2 File System Check Program''SMM:3-%'
+.AU
+Marshall Kirk McKusick
+.AI
+Computer Systems Research Group
+Computer Science Division
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, CA 94720
+.AU
+T. J. Kowalski
+.AI
+Bell Laboratories
+Murray Hill, New Jersey 07974
+.AB
+.FS
+\(dgUNIX is a trademark of Bell Laboratories.
+.FE
+.FS
+This work was done under grants from
+the National Science Foundation under grant MCS80-05144,
+and the Defense Advance Research Projects Agency (DoD) under
+Arpa Order No. 4031 monitored by Naval Electronic System Command under
+Contract No. N00039-82-C-0235.
+.FE
+This document reflects the use of
+.I fsck_ffs
+with the 4.2BSD and 4.3BSD file system organization. This
+is a revision of the
+original paper written by
+T. J. Kowalski.
+.PP
+File System Check Program (\fIfsck_ffs\fR)
+is an interactive file system check and repair program.
+.I Fsck_ffs
+uses the redundant structural information in the
+UNIX file system to perform several consistency checks.
+If an inconsistency is detected, it is reported
+to the operator, who may elect to fix or ignore
+each inconsistency.
+These inconsistencies result from the permanent interruption
+of the file system updates, which are performed every
+time a file is modified.
+Unless there has been a hardware failure,
+.I fsck_ffs
+is able to repair corrupted file systems
+using procedures based upon the order in which UNIX honors
+these file system update requests.
+.PP
+The purpose of this document is to describe the normal updating
+of the file system,
+to discuss the possible causes of file system corruption,
+and to present the corrective actions implemented
+by
+.I fsck_ffs.
+Both the program and the interaction between the
+program and the operator are described.
+.sp 2
+.LP
+Revised October 7, 1996
+.AE
+.LP
+.bp
+.ce
+.B "TABLE OF CONTENTS"
+.LP
+.sp 1
+.nf
+.B "1. Introduction"
+.LP
+.sp .5v
+.nf
+.B "2. Overview of the file system
+2.1. Superblock
+2.2. Summary Information
+2.3. Cylinder groups
+2.4. Fragments
+2.5. Updates to the file system
+.LP
+.sp .5v
+.nf
+.B "3. Fixing corrupted file systems
+3.1. Detecting and correcting corruption
+3.2. Super block checking
+3.3. Free block checking
+3.4. Checking the inode state
+3.5. Inode links
+3.6. Inode data size
+3.7. Checking the data associated with an inode
+3.8. File system connectivity
+.LP
+.sp .5v
+.nf
+.B Acknowledgements
+.LP
+.sp .5v
+.nf
+.B References
+.LP
+.sp .5v
+.nf
+.B "4. Appendix A
+4.1. Conventions
+4.2. Initialization
+4.3. Phase 1 - Check Blocks and Sizes
+4.4. Phase 1b - Rescan for more Dups
+4.5. Phase 2 - Check Pathnames
+4.6. Phase 3 - Check Connectivity
+4.7. Phase 4 - Check Reference Counts
+4.8. Phase 5 - Check Cyl groups
+4.9. Cleanup
+.ds RH Introduction
+.bp
diff --git a/share/doc/smm/03.fsck/1.t b/share/doc/smm/03.fsck/1.t
new file mode 100644
index 0000000..3098b49
--- /dev/null
+++ b/share/doc/smm/03.fsck/1.t
@@ -0,0 +1,80 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\" @(#)1.t 8.1 (Berkeley) 6/5/93
+.\"
+.ds RH Introduction
+.NH
+Introduction
+.PP
+This document reflects the use of
+.I fsck_ffs
+with the 4.2BSD and 4.3BSD file system organization. This
+is a revision of the
+original paper written by
+T. J. Kowalski.
+.PP
+When a UNIX
+operating system is brought up, a consistency
+check of the file systems should always be performed.
+This precautionary measure helps to insure
+a reliable environment for file storage on disk.
+If an inconsistency is discovered,
+corrective action must be taken.
+.I Fsck_ffs
+runs in two modes.
+Normally it is run non-interactively by the system after
+a normal boot.
+When running in this mode,
+it will only make changes to the file system that are known
+to always be correct.
+If an unexpected inconsistency is found
+.I fsck_ffs
+will exit with a non-zero exit status,
+leaving the system running single-user.
+Typically the operator then runs
+.I fsck_ffs
+interactively.
+When running in this mode,
+each problem is listed followed by a suggested corrective action.
+The operator must decide whether or not the suggested correction
+should be made.
+.PP
+The purpose of this memo is to dispel the
+mystique surrounding
+file system inconsistencies.
+It first describes the updating of the file system
+(the calm before the storm) and
+then describes file system corruption (the storm).
+Finally,
+the set of deterministic corrective actions
+used by
+.I fsck_ffs
+(the Coast Guard
+to the rescue) is presented.
+.ds RH Overview of the File System
diff --git a/share/doc/smm/03.fsck/2.t b/share/doc/smm/03.fsck/2.t
new file mode 100644
index 0000000..b294a6a
--- /dev/null
+++ b/share/doc/smm/03.fsck/2.t
@@ -0,0 +1,262 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\" @(#)2.t 8.1 (Berkeley) 6/5/93
+.\"
+.ds RH Overview of the file system
+.NH
+Overview of the file system
+.PP
+The file system is discussed in detail in [Mckusick84];
+this section gives a brief overview.
+.NH 2
+Superblock
+.PP
+A file system is described by its
+.I "super-block" .
+The super-block is built when the file system is created (\c
+.I newfs (8))
+and never changes.
+The super-block
+contains the basic parameters of the file system,
+such as the number of data blocks it contains
+and a count of the maximum number of files.
+Because the super-block contains critical data,
+.I newfs
+replicates it to protect against catastrophic loss.
+The
+.I "default super block"
+always resides at a fixed offset from the beginning
+of the file system's disk partition.
+The
+.I "redundant super blocks"
+are not referenced unless a head crash
+or other hard disk error causes the default super-block
+to be unusable.
+The redundant blocks are sprinkled throughout the disk partition.
+.PP
+Within the file system are files.
+Certain files are distinguished as directories and contain collections
+of pointers to files that may themselves be directories.
+Every file has a descriptor associated with it called an
+.I "inode".
+The inode contains information describing ownership of the file,
+time stamps indicating modification and access times for the file,
+and an array of indices pointing to the data blocks for the file.
+In this section,
+we assume that the first 12 blocks
+of the file are directly referenced by values stored
+in the inode structure itself\(dg.
+.FS
+\(dgThe actual number may vary from system to system, but is usually in
+the range 5-13.
+.FE
+The inode structure may also contain references to indirect blocks
+containing further data block indices.
+In a file system with a 4096 byte block size, a singly indirect
+block contains 1024 further block addresses,
+a doubly indirect block contains 1024 addresses of further single indirect
+blocks,
+and a triply indirect block contains 1024 addresses of further doubly indirect
+blocks (the triple indirect block is never needed in practice).
+.PP
+In order to create files with up to
+2\(ua32 bytes,
+using only two levels of indirection,
+the minimum size of a file system block is 4096 bytes.
+The size of file system blocks can be any power of two
+greater than or equal to 4096.
+The block size of the file system is maintained in the super-block,
+so it is possible for file systems of different block sizes
+to be accessible simultaneously on the same system.
+The block size must be decided when
+.I newfs
+creates the file system;
+the block size cannot be subsequently
+changed without rebuilding the file system.
+.NH 2
+Summary information
+.PP
+Associated with the super block is non replicated
+.I "summary information" .
+The summary information changes
+as the file system is modified.
+The summary information contains
+the number of blocks, fragments, inodes and directories in the file system.
+.NH 2
+Cylinder groups
+.PP
+The file system partitions the disk into one or more areas called
+.I "cylinder groups".
+A cylinder group is comprised of one or more consecutive
+cylinders on a disk.
+Each cylinder group includes inode slots for files, a
+.I "block map"
+describing available blocks in the cylinder group,
+and summary information describing the usage of data blocks
+within the cylinder group.
+A fixed number of inodes is allocated for each cylinder group
+when the file system is created.
+The current policy is to allocate one inode for each 2048
+bytes of disk space;
+this is expected to be far more inodes than will ever be needed.
+.PP
+All the cylinder group bookkeeping information could be
+placed at the beginning of each cylinder group.
+However if this approach were used,
+all the redundant information would be on the top platter.
+A single hardware failure that destroyed the top platter
+could cause the loss of all copies of the redundant super-blocks.
+Thus the cylinder group bookkeeping information
+begins at a floating offset from the beginning of the cylinder group.
+The offset for
+the
+.I "i+1" st
+cylinder group is about one track further
+from the beginning of the cylinder group
+than it was for the
+.I "i" th
+cylinder group.
+In this way,
+the redundant
+information spirals down into the pack;
+any single track, cylinder,
+or platter can be lost without losing all copies of the super-blocks.
+Except for the first cylinder group,
+the space between the beginning of the cylinder group
+and the beginning of the cylinder group information stores data.
+.NH 2
+Fragments
+.PP
+To avoid waste in storing small files,
+the file system space allocator divides a single
+file system block into one or more
+.I "fragments".
+The fragmentation of the file system is specified
+when the file system is created;
+each file system block can be optionally broken into
+2, 4, or 8 addressable fragments.
+The lower bound on the size of these fragments is constrained
+by the disk sector size;
+typically 512 bytes is the lower bound on fragment size.
+The block map associated with each cylinder group
+records the space availability at the fragment level.
+Aligned fragments are examined
+to determine block availability.
+.PP
+On a file system with a block size of 4096 bytes
+and a fragment size of 1024 bytes,
+a file is represented by zero or more 4096 byte blocks of data,
+and possibly a single fragmented block.
+If a file system block must be fragmented to obtain
+space for a small amount of data,
+the remainder of the block is made available for allocation
+to other files.
+For example,
+consider an 11000 byte file stored on
+a 4096/1024 byte file system.
+This file uses two full size blocks and a 3072 byte fragment.
+If no fragments with at least 3072 bytes
+are available when the file is created,
+a full size block is split yielding the necessary 3072 byte
+fragment and an unused 1024 byte fragment.
+This remaining fragment can be allocated to another file, as needed.
+.NH 2
+Updates to the file system
+.PP
+Every working day hundreds of files
+are created, modified, and removed.
+Every time a file is modified,
+the operating system performs a
+series of file system updates.
+These updates, when written on disk, yield a consistent file system.
+The file system stages
+all modifications of critical information;
+modification can
+either be completed or cleanly backed out after a crash.
+Knowing the information that is first written to the file system,
+deterministic procedures can be developed to
+repair a corrupted file system.
+To understand this process,
+the order that the update
+requests were being honored must first be understood.
+.PP
+When a user program does an operation to change the file system,
+such as a
+.I write ,
+the data to be written is copied into an internal
+.I "in-core"
+buffer in the kernel.
+Normally, the disk update is handled asynchronously;
+the user process is allowed to proceed even though
+the data has not yet been written to the disk.
+The data,
+along with the inode information reflecting the change,
+is eventually written out to disk.
+The real disk write may not happen until long after the
+.I write
+system call has returned.
+Thus at any given time, the file system,
+as it resides on the disk,
+lags the state of the file system represented by the in-core information.
+.PP
+The disk information is updated to reflect the in-core information
+when the buffer is required for another use,
+when a
+.I sync (2)
+is done (at 30 second intervals) by
+.I "/etc/update" "(8),"
+or by manual operator intervention with the
+.I sync (8)
+command.
+If the system is halted without writing out the in-core information,
+the file system on the disk will be in an inconsistent state.
+.PP
+If all updates are done asynchronously, several serious
+inconsistencies can arise.
+One inconsistency is that a block may be claimed by two inodes.
+Such an inconsistency can occur when the system is halted before
+the pointer to the block in the old inode has been cleared
+in the copy of the old inode on the disk,
+and after the pointer to the block in the new inode has been written out
+to the copy of the new inode on the disk.
+Here,
+there is no deterministic method for deciding
+which inode should really claim the block.
+A similar problem can arise with a multiply claimed inode.
+.PP
+The problem with asynchronous inode updates
+can be avoided by doing all inode deallocations synchronously.
+Consequently,
+inodes and indirect blocks are written to the disk synchronously
+(\fIi.e.\fP the process blocks until the information is
+really written to disk)
+when they are being deallocated.
+Similarly inodes are kept consistent by synchronously
+deleting, adding, or changing directory entries.
+.ds RH Fixing corrupted file systems
diff --git a/share/doc/smm/03.fsck/3.t b/share/doc/smm/03.fsck/3.t
new file mode 100644
index 0000000..522a222
--- /dev/null
+++ b/share/doc/smm/03.fsck/3.t
@@ -0,0 +1,449 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\" @(#)3.t 8.1 (Berkeley) 6/5/93
+.\"
+.ds RH Fixing corrupted file systems
+.NH
+Fixing corrupted file systems
+.PP
+A file system
+can become corrupted in several ways.
+The most common of these ways are
+improper shutdown procedures
+and hardware failures.
+.PP
+File systems may become corrupted during an
+.I "unclean halt" .
+This happens when proper shutdown
+procedures are not observed,
+physically write-protecting a mounted file system,
+or a mounted file system is taken off-line.
+The most common operator procedural failure is forgetting to
+.I sync
+the system before halting the CPU.
+.PP
+File systems may become further corrupted if proper startup
+procedures are not observed, e.g.,
+not checking a file system for inconsistencies,
+and not repairing inconsistencies.
+Allowing a corrupted file system to be used (and, thus, to be modified
+further) can be disastrous.
+.PP
+Any piece of hardware can fail at any time.
+Failures
+can be as subtle as a bad block
+on a disk pack, or as blatant as a non-functional disk-controller.
+.NH 2
+Detecting and correcting corruption
+.PP
+Normally
+.I fsck_ffs
+is run non-interactively.
+In this mode it will only fix
+corruptions that are expected to occur from an unclean halt.
+These actions are a proper subset of the actions that
+.I fsck_ffs
+will take when it is running interactively.
+Throughout this paper we assume that
+.I fsck_ffs
+is being run interactively,
+and all possible errors can be encountered.
+When an inconsistency is discovered in this mode,
+.I fsck_ffs
+reports the inconsistency for the operator to
+chose a corrective action.
+.PP
+A quiescent\(dd
+.FS
+\(dd I.e., unmounted and not being written on.
+.FE
+file system may be checked for structural integrity
+by performing consistency checks on the
+redundant data intrinsic to a file system.
+The redundant data is either read from
+the file system,
+or computed from other known values.
+The file system
+.B must
+be in a quiescent state when
+.I fsck_ffs
+is run,
+since
+.I fsck_ffs
+is a multi-pass program.
+.PP
+In the following sections,
+we discuss methods to discover inconsistencies
+and possible corrective actions
+for the cylinder group blocks, the inodes, the indirect blocks, and
+the data blocks containing directory entries.
+.NH 2
+Super-block checking
+.PP
+The most commonly corrupted item in a file system
+is the summary information
+associated with the super-block.
+The summary information is prone to corruption
+because it is modified with every change to the file
+system's blocks or inodes,
+and is usually corrupted
+after an unclean halt.
+.PP
+The super-block is checked for inconsistencies
+involving file-system size, number of inodes,
+free-block count, and the free-inode count.
+The file-system size must be larger than the
+number of blocks used by the super-block
+and the number of blocks used by the list of inodes.
+The file-system size and layout information
+are the most critical pieces of information for
+.I fsck_ffs .
+While there is no way to actually check these sizes,
+since they are statically determined by
+.I newfs ,
+.I fsck_ffs
+can check that these sizes are within reasonable bounds.
+All other file system checks require that these sizes be correct.
+If
+.I fsck_ffs
+detects corruption in the static parameters of the default super-block,
+.I fsck_ffs
+requests the operator to specify the location of an alternate super-block.
+.NH 2
+Free block checking
+.PP
+.I Fsck_ffs
+checks that all the blocks
+marked as free in the cylinder group block maps
+are not claimed by any files.
+When all the blocks have been initially accounted for,
+.I fsck_ffs
+checks that
+the number of free blocks
+plus the number of blocks claimed by the inodes
+equals the total number of blocks in the file system.
+.PP
+If anything is wrong with the block allocation maps,
+.I fsck_ffs
+will rebuild them,
+based on the list it has computed of allocated blocks.
+.PP
+The summary information associated with the super-block
+counts the total number of free blocks within the file system.
+.I Fsck_ffs
+compares this count to the
+number of free blocks it found within the file system.
+If the two counts do not agree, then
+.I fsck_ffs
+replaces the incorrect count in the summary information
+by the actual free-block count.
+.PP
+The summary information
+counts the total number of free inodes within the file system.
+.I Fsck_ffs
+compares this count to the number
+of free inodes it found within the file system.
+If the two counts do not agree, then
+.I fsck_ffs
+replaces the incorrect count in the
+summary information by the actual free-inode count.
+.NH 2
+Checking the inode state
+.PP
+An individual inode is not as likely to be corrupted as
+the allocation information.
+However, because of the great number of active inodes,
+a few of the inodes are usually corrupted.
+.PP
+The list of inodes in the file system
+is checked sequentially starting with inode 2
+(inode 0 marks unused inodes;
+inode 1 is saved for future generations)
+and progressing through the last inode in the file system.
+The state of each inode is checked for
+inconsistencies involving format and type,
+link count,
+duplicate blocks,
+bad blocks,
+and inode size.
+.PP
+Each inode contains a mode word.
+This mode word describes the type and state of the inode.
+Inodes must be one of six types:
+regular inode, directory inode, symbolic link inode,
+special block inode, special character inode, or socket inode.
+Inodes may be found in one of three allocation states:
+unallocated, allocated, and neither unallocated nor allocated.
+This last state suggests an incorrectly formated inode.
+An inode can get in this state if
+bad data is written into the inode list.
+The only possible corrective action is for
+.I fsck_ffs
+is to clear the inode.
+.NH 2
+Inode links
+.PP
+Each inode counts the
+total number of directory entries
+linked to the inode.
+.I Fsck_ffs
+verifies the link count of each inode
+by starting at the root of the file system,
+and descending through the directory structure.
+The actual link count for each inode
+is calculated during the descent.
+.PP
+If the stored link count is non-zero and the actual
+link count is zero,
+then no directory entry appears for the inode.
+If this happens,
+.I fsck_ffs
+will place the disconnected file in the
+.I lost+found
+directory.
+If the stored and actual link counts are non-zero and unequal,
+a directory entry may have been added or removed without the inode being
+updated.
+If this happens,
+.I fsck_ffs
+replaces the incorrect stored link count by the actual link count.
+.PP
+Each inode contains a list,
+or pointers to
+lists (indirect blocks),
+of all the blocks claimed by the inode.
+Since indirect blocks are owned by an inode,
+inconsistencies in indirect blocks directly
+affect the inode that owns it.
+.PP
+.I Fsck_ffs
+compares each block number claimed by an inode
+against a list of already allocated blocks.
+If another inode already claims a block number,
+then the block number is added to a list of
+.I "duplicate blocks" .
+Otherwise, the list of allocated blocks
+is updated to include the block number.
+.PP
+If there are any duplicate blocks,
+.I fsck_ffs
+will perform a partial second
+pass over the inode list
+to find the inode of the duplicated block.
+The second pass is needed,
+since without examining the files associated with
+these inodes for correct content,
+not enough information is available
+to determine which inode is corrupted and should be cleared.
+If this condition does arise
+(only hardware failure will cause it),
+then the inode with the earliest
+modify time is usually incorrect,
+and should be cleared.
+If this happens,
+.I fsck_ffs
+prompts the operator to clear both inodes.
+The operator must decide which one should be kept
+and which one should be cleared.
+.PP
+.I Fsck_ffs
+checks the range of each block number claimed by an inode.
+If the block number is
+lower than the first data block in the file system,
+or greater than the last data block,
+then the block number is a
+.I "bad block number" .
+Many bad blocks in an inode are usually caused by
+an indirect block that was not written to the file system,
+a condition which can only occur if there has been a hardware failure.
+If an inode contains bad block numbers,
+.I fsck_ffs
+prompts the operator to clear it.
+.NH 2
+Inode data size
+.PP
+Each inode contains a count of the number of data blocks
+that it contains.
+The number of actual data blocks
+is the sum of the allocated data blocks
+and the indirect blocks.
+.I Fsck_ffs
+computes the actual number of data blocks
+and compares that block count against
+the actual number of blocks the inode claims.
+If an inode contains an incorrect count
+.I fsck_ffs
+prompts the operator to fix it.
+.PP
+Each inode contains a thirty-two bit size field.
+The size is the number of data bytes
+in the file associated with the inode.
+The consistency of the byte size field is roughly checked
+by computing from the size field the maximum number of blocks
+that should be associated with the inode,
+and comparing that expected block count against
+the actual number of blocks the inode claims.
+.NH 2
+Checking the data associated with an inode
+.PP
+An inode can directly or indirectly
+reference three kinds of data blocks.
+All referenced blocks must be the same kind.
+The three types of data blocks are:
+plain data blocks, symbolic link data blocks, and directory data blocks.
+Plain data blocks
+contain the information stored in a file;
+symbolic link data blocks
+contain the path name stored in a link.
+Directory data blocks contain directory entries.
+.I Fsck_ffs
+can only check the validity of directory data blocks.
+.PP
+Each directory data block is checked for
+several types of inconsistencies.
+These inconsistencies include
+directory inode numbers pointing to unallocated inodes,
+directory inode numbers that are greater than
+the number of inodes in the file system,
+incorrect directory inode numbers for ``\fB.\fP'' and ``\fB..\fP'',
+and directories that are not attached to the file system.
+If the inode number in a directory data block
+references an unallocated inode,
+then
+.I fsck_ffs
+will remove that directory entry.
+Again,
+this condition can only arise when there has been a hardware failure.
+.PP
+.I Fsck_ffs
+also checks for directories with unallocated blocks (holes).
+Such directories should never be created.
+When found,
+.I fsck_ffs
+will prompt the user to adjust the length of the offending directory
+which is done by shortening the size of the directory to the end of the
+last allocated block preceding the hole.
+Unfortunately, this means that another Phase 1 run has to be done.
+.I Fsck_ffs
+will remind the user to rerun fsck_ffs after repairing a
+directory containing an unallocated block.
+.PP
+If a directory entry inode number references
+outside the inode list, then
+.I fsck_ffs
+will remove that directory entry.
+This condition occurs if bad data is written into a directory data block.
+.PP
+The directory inode number entry for ``\fB.\fP''
+must be the first entry in the directory data block.
+The inode number for ``\fB.\fP''
+must reference itself;
+e.g., it must equal the inode number
+for the directory data block.
+The directory inode number entry
+for ``\fB..\fP'' must be
+the second entry in the directory data block.
+Its value must equal the inode number for the
+parent of the directory entry
+(or the inode number of the directory
+data block if the directory is the
+root directory).
+If the directory inode numbers are
+incorrect,
+.I fsck_ffs
+will replace them with the correct values.
+If there are multiple hard links to a directory,
+the first one encountered is considered the real parent
+to which ``\fB..\fP'' should point;
+\fIfsck_ffs\fP recommends deletion for the subsequently discovered names.
+.NH 2
+File system connectivity
+.PP
+.I Fsck_ffs
+checks the general connectivity of the file system.
+If directories are not linked into the file system, then
+.I fsck_ffs
+links the directory back into the file system in the
+.I lost+found
+directory.
+This condition only occurs when there has been a hardware failure.
+.ds RH "References"
+.SH
+\s+2Acknowledgements\s0
+.PP
+I thank Bill Joy, Sam Leffler, Robert Elz and Dennis Ritchie
+for their suggestions and help in implementing the new file system.
+Thanks also to Robert Henry for his editorial input to
+get this document together.
+Finally we thank our sponsors,
+the National Science Foundation under grant MCS80-05144,
+and the Defense Advance Research Projects Agency (DoD) under
+Arpa Order No. 4031 monitored by Naval Electronic System Command under
+Contract No. N00039-82-C-0235. (Kirk McKusick, July 1983)
+.PP
+I would like to thank Larry A. Wehr for advice that lead
+to the first version of
+.I fsck_ffs
+and Rick B. Brandt for adapting
+.I fsck_ffs
+to
+UNIX/TS. (T. Kowalski, July 1979)
+.sp 2
+.SH
+\s+2References\s0
+.LP
+.IP [Dolotta78] 20
+Dolotta, T. A., and Olsson, S. B. eds.,
+.I "UNIX User's Manual, Edition 1.1\^" ,
+January 1978.
+.IP [Joy83] 20
+Joy, W., Cooper, E., Fabry, R., Leffler, S., McKusick, M., and Mosher, D.
+4.2BSD System Manual,
+.I "University of California at Berkeley" ,
+.I "Computer Systems Research Group Technical Report"
+#4, 1982.
+.IP [McKusick84] 20
+McKusick, M., Joy, W., Leffler, S., and Fabry, R.
+A Fast File System for UNIX,
+\fIACM Transactions on Computer Systems 2\fP, 3.
+pp. 181-197, August 1984.
+.IP [Ritchie78] 20
+Ritchie, D. M., and Thompson, K.,
+The UNIX Time-Sharing System,
+.I "The Bell System Technical Journal"
+.B 57 ,
+6 (July-August 1978, Part 2), pp. 1905-29.
+.IP [Thompson78] 20
+Thompson, K.,
+UNIX Implementation,
+.I "The Bell System Technical Journal\^"
+.B 57 ,
+6 (July-August 1978, Part 2), pp. 1931-46.
+.ds RH Appendix A \- Fsck_ffs Error Conditions
+.bp
diff --git a/share/doc/smm/03.fsck/4.t b/share/doc/smm/03.fsck/4.t
new file mode 100644
index 0000000..353fab3
--- /dev/null
+++ b/share/doc/smm/03.fsck/4.t
@@ -0,0 +1,1421 @@
+.\" Copyright (c) 1982, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\" @(#)4.t 8.1 (Berkeley) 6/5/93
+.\"
+.ds RH Appendix A \- Fsck_ffs Error Conditions
+.NH
+Appendix A \- Fsck_ffs Error Conditions
+.NH 2
+Conventions
+.PP
+.I Fsck_ffs
+is
+a multi-pass file system check program.
+Each file system pass invokes a different Phase of the
+.I fsck_ffs
+program.
+After the initial setup,
+.I fsck_ffs
+performs successive Phases over each file system,
+checking blocks and sizes,
+path-names,
+connectivity,
+reference counts,
+and the map of free blocks,
+(possibly rebuilding it),
+and performs some cleanup.
+.LP
+Normally
+.I fsck_ffs
+is run non-interactively to
+.I preen
+the file systems after an unclean halt.
+While preen'ing a file system,
+it will only fix corruptions that are expected
+to occur from an unclean halt.
+These actions are a proper subset of the actions that
+.I fsck_ffs
+will take when it is running interactively.
+Throughout this appendix many errors have several options
+that the operator can take.
+When an inconsistency is detected,
+.I fsck_ffs
+reports the error condition to the operator.
+If a response is required,
+.I fsck_ffs
+prints a prompt message and
+waits for a response.
+When preen'ing most errors are fatal.
+For those that are expected,
+the response taken is noted.
+This appendix explains the meaning of each error condition,
+the possible responses, and the related error conditions.
+.LP
+The error conditions are organized by the
+.I Phase
+of the
+.I fsck_ffs
+program in which they can occur.
+The error conditions that may occur
+in more than one Phase
+will be discussed in initialization.
+.NH 2
+Initialization
+.PP
+Before a file system check can be performed, certain
+tables have to be set up and certain files opened.
+This section concerns itself with the opening of files and
+the initialization of tables.
+This section lists error conditions resulting from
+command line options,
+memory requests,
+opening of files,
+status of files,
+file system size checks,
+and creation of the scratch file.
+All the initialization errors are fatal
+when the file system is being preen'ed.
+.sp
+.LP
+.B "\fIC\fP option?"
+.br
+\fIC\fP is not a legal option to
+.I fsck_ffs ;
+legal options are \-b, \-c, \-y, \-n, and \-p.
+.I Fsck_ffs
+terminates on this error condition.
+See the
+.I fsck_ffs (8)
+manual entry for further detail.
+.sp
+.LP
+.B "cannot alloc NNN bytes for blockmap"
+.br
+.B "cannot alloc NNN bytes for freemap"
+.br
+.B "cannot alloc NNN bytes for statemap"
+.br
+.B "cannot alloc NNN bytes for lncntp"
+.br
+.I Fsck_ffs 's
+request for memory for its virtual
+memory tables failed.
+This should never happen.
+.I Fsck_ffs
+terminates on this error condition.
+See a guru.
+.sp
+.LP
+.B "Can't open checklist file: \fIF\fP"
+.br
+The file system checklist file
+\fIF\fP (usually
+.I /etc/fstab )
+can not be opened for reading.
+.I Fsck_ffs
+terminates on this error condition.
+Check access modes of \fIF\fP.
+.sp
+.LP
+.B "Can't stat root"
+.br
+.I Fsck_ffs 's
+request for statistics about the root directory ``/'' failed.
+This should never happen.
+.I Fsck_ffs
+terminates on this error condition.
+See a guru.
+.sp
+.LP
+.B "Can't stat \fIF\fP"
+.br
+.B "Can't make sense out of name \fIF\fP"
+.br
+.I Fsck_ffs 's
+request for statistics about the file system \fIF\fP failed.
+When running manually,
+it ignores this file system
+and continues checking the next file system given.
+Check access modes of \fIF\fP.
+.sp
+.LP
+.B "Can't open \fIF\fP"
+.br
+.I Fsck_ffs 's
+request attempt to open the file system \fIF\fP failed.
+When running manually, it ignores this file system
+and continues checking the next file system given.
+Check access modes of \fIF\fP.
+.sp
+.LP
+.B "\fIF\fP: (NO WRITE)"
+.br
+Either the \-n flag was specified or
+.I fsck_ffs 's
+attempt to open the file system \fIF\fP for writing failed.
+When running manually,
+all the diagnostics are printed out,
+but no modifications are attempted to fix them.
+.sp
+.LP
+.B "file is not a block or character device; OK"
+.br
+You have given
+.I fsck_ffs
+a regular file name by mistake.
+Check the type of the file specified.
+.LP
+Possible responses to the OK prompt are:
+.IP YES
+ignore this error condition.
+.IP NO
+ignore this file system and continues checking
+the next file system given.
+.sp
+.LP
+.B "UNDEFINED OPTIMIZATION IN SUPERBLOCK (SET TO DEFAULT)"
+.br
+The superblock optimization parameter is neither OPT_TIME
+nor OPT_SPACE.
+.LP
+Possible responses to the SET TO DEFAULT prompt are:
+.IP YES
+The superblock is set to request optimization to minimize
+running time of the system.
+(If optimization to minimize disk space utilization is
+desired, it can be set using \fItunefs\fP(8).)
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "IMPOSSIBLE MINFREE=\fID\fP IN SUPERBLOCK (SET TO DEFAULT)"
+.br
+The superblock minimum space percentage is greater than 99%
+or less then 0%.
+.LP
+Possible responses to the SET TO DEFAULT prompt are:
+.IP YES
+The minfree parameter is set to 10%.
+(If some other percentage is desired,
+it can be set using \fItunefs\fP(8).)
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "IMPOSSIBLE INTERLEAVE=\fID\fP IN SUPERBLOCK (SET TO DEFAULT)"
+.br
+The file system interleave is less than or equal to zero.
+.LP
+Possible responses to the SET TO DEFAULT prompt are:
+.IP YES
+The interleave parameter is set to 1.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "IMPOSSIBLE NPSECT=\fID\fP IN SUPERBLOCK (SET TO DEFAULT)"
+.br
+The number of physical sectors per track is less than the number
+of usable sectors per track.
+.LP
+Possible responses to the SET TO DEFAULT prompt are:
+.IP YES
+The npsect parameter is set to the number of usable sectors per track.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+One of the following messages will appear:
+.br
+.B "MAGIC NUMBER WRONG"
+.br
+.B "NCG OUT OF RANGE"
+.br
+.B "CPG OUT OF RANGE"
+.br
+.B "NCYL DOES NOT JIVE WITH NCG*CPG"
+.br
+.B "SIZE PREPOSTEROUSLY LARGE"
+.br
+.B "TRASHED VALUES IN SUPER BLOCK"
+.br
+and will be followed by the message:
+.br
+.B "\fIF\fP: BAD SUPER BLOCK: \fIB\fP"
+.br
+.B "USE -b OPTION TO FSCK_FFS TO SPECIFY LOCATION OF AN ALTERNATE"
+.br
+.B "SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck_ffs(8)."
+.br
+The super block has been corrupted.
+An alternative super block must be selected from among those
+listed by
+.I newfs
+(8) when the file system was created.
+For file systems with a blocksize less than 32K,
+specifying \-b 32 is a good first choice.
+.sp
+.LP
+.B "INTERNAL INCONSISTENCY: \fIM\fP"
+.br
+.I Fsck_ffs 's
+has had an internal panic, whose message is specified as \fIM\fP.
+This should never happen.
+See a guru.
+.sp
+.LP
+.B "CAN NOT SEEK: BLK \fIB\fP (CONTINUE)"
+.br
+.I Fsck_ffs 's
+request for moving to a specified block number \fIB\fP in
+the file system failed.
+This should never happen.
+See a guru.
+.LP
+Possible responses to the CONTINUE prompt are:
+.IP YES
+attempt to continue to run the file system check.
+Often,
+however the problem will persist.
+This error condition will not allow a complete check of the file system.
+A second run of
+.I fsck_ffs
+should be made to re-check this file system.
+If the block was part of the virtual memory buffer
+cache,
+.I fsck_ffs
+will terminate with the message ``Fatal I/O error''.
+.IP NO
+terminate the program.
+.sp
+.LP
+.B "CAN NOT READ: BLK \fIB\fP (CONTINUE)"
+.br
+.I Fsck_ffs 's
+request for reading a specified block number \fIB\fP in
+the file system failed.
+This should never happen.
+See a guru.
+.LP
+Possible responses to the CONTINUE prompt are:
+.IP YES
+attempt to continue to run the file system check.
+It will retry the read and print out the message:
+.br
+.B "THE FOLLOWING SECTORS COULD NOT BE READ: \fIN\fP"
+.br
+where \fIN\fP indicates the sectors that could not be read.
+If
+.I fsck_ffs
+ever tries to write back one of the blocks on which the read failed
+it will print the message:
+.br
+.B "WRITING ZERO'ED BLOCK \fIN\fP TO DISK"
+.br
+where \fIN\fP indicates the sector that was written with zero's.
+If the disk is experiencing hardware problems, the problem will persist.
+This error condition will not allow a complete check of the file system.
+A second run of
+.I fsck_ffs
+should be made to re-check this file system.
+If the block was part of the virtual memory buffer
+cache,
+.I fsck_ffs
+will terminate with the message ``Fatal I/O error''.
+.IP NO
+terminate the program.
+.sp
+.LP
+.B "CAN NOT WRITE: BLK \fIB\fP (CONTINUE)"
+.br
+.I Fsck_ffs 's
+request for writing a specified block number \fIB\fP
+in the file system failed.
+The disk is write-protected;
+check the write protect lock on the drive.
+If that is not the problem, see a guru.
+.LP
+Possible responses to the CONTINUE prompt are:
+.IP YES
+attempt to continue to run the file system check.
+The write operation will be retried with the failed blocks
+indicated by the message:
+.br
+.B "THE FOLLOWING SECTORS COULD NOT BE WRITTEN: \fIN\fP"
+.br
+where \fIN\fP indicates the sectors that could not be written.
+If the disk is experiencing hardware problems, the problem will persist.
+This error condition will not allow a complete check of the file system.
+A second run of
+.I fsck_ffs
+should be made to re-check this file system.
+If the block was part of the virtual memory buffer
+cache,
+.I fsck_ffs
+will terminate with the message ``Fatal I/O error''.
+.IP NO
+terminate the program.
+.sp
+.LP
+.B "bad inode number DDD to ginode"
+.br
+An internal error has attempted to read non-existent inode \fIDDD\fP.
+This error causes
+.I fsck_ffs
+to exit.
+See a guru.
+.NH 2
+Phase 1 \- Check Blocks and Sizes
+.PP
+This phase concerns itself with
+the inode list.
+This section lists error conditions resulting from
+checking inode types,
+setting up the zero-link-count table,
+examining inode block numbers for bad or duplicate blocks,
+checking inode size,
+and checking inode format.
+All errors in this phase except
+.B "INCORRECT BLOCK COUNT"
+and
+.B "PARTIALLY TRUNCATED INODE"
+are fatal if the file system is being preen'ed.
+.sp
+.LP
+.B "UNKNOWN FILE TYPE I=\fII\fP (CLEAR)"
+.br
+The mode word of the inode \fII\fP indicates that the inode is not a
+special block inode, special character inode, socket inode, regular inode,
+symbolic link, or directory inode.
+.LP
+Possible responses to the CLEAR prompt are:
+.IP YES
+de-allocate inode \fII\fP by zeroing its contents.
+This will always invoke the UNALLOCATED error condition in Phase 2
+for each directory entry pointing to this inode.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "PARTIALLY TRUNCATED INODE I=\fII\fP (SALVAGE)"
+.br
+.I Fsck_ffs
+has found inode \fII\fP whose size is shorter than the number of
+blocks allocated to it.
+This condition should only occur if the system crashes while in the
+midst of truncating a file.
+When preen'ing the file system,
+.I fsck_ffs
+completes the truncation to the specified size.
+.LP
+Possible responses to SALVAGE are:
+.IP YES
+complete the truncation to the size specified in the inode.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "LINK COUNT TABLE OVERFLOW (CONTINUE)"
+.br
+An internal table for
+.I fsck_ffs
+containing allocated inodes with a link count of
+zero cannot allocate more memory.
+Increase the virtual memory for
+.I fsck_ffs .
+.LP
+Possible responses to the CONTINUE prompt are:
+.IP YES
+continue with the program.
+This error condition will not allow a complete check of the file system.
+A second run of
+.I fsck_ffs
+should be made to re-check this file system.
+If another allocated inode with a zero link count is found,
+this error condition is repeated.
+.IP NO
+terminate the program.
+.sp
+.LP
+.B "\fIB\fP BAD I=\fII\fP"
+.br
+Inode \fII\fP contains block number \fIB\fP with a number
+lower than the number of the first data block in the file system or
+greater than the number of the last block
+in the file system.
+This error condition may invoke the
+.B "EXCESSIVE BAD BLKS"
+error condition in Phase 1 (see next paragraph) if
+inode \fII\fP has too many block numbers outside the file system range.
+This error condition will always invoke the
+.B "BAD/DUP"
+error condition in Phase 2 and Phase 4.
+.sp
+.LP
+.B "EXCESSIVE BAD BLKS I=\fII\fP (CONTINUE)"
+.br
+There is more than a tolerable number (usually 10) of blocks with a number
+lower than the number of the first data block in the file system or greater than
+the number of last block in the file system associated with inode \fII\fP.
+.LP
+Possible responses to the CONTINUE prompt are:
+.IP YES
+ignore the rest of the blocks in this inode
+and continue checking with the next inode in the file system.
+This error condition will not allow a complete check of the file system.
+A second run of
+.I fsck_ffs
+should be made to re-check this file system.
+.IP NO
+terminate the program.
+.sp
+.LP
+.B "BAD STATE DDD TO BLKERR"
+.br
+An internal error has scrambled
+.I fsck_ffs 's
+state map to have the impossible value \fIDDD\fP.
+.I Fsck_ffs
+exits immediately.
+See a guru.
+.sp
+.LP
+.B "\fIB\fP DUP I=\fII\fP"
+.br
+Inode \fII\fP contains block number \fIB\fP that is already claimed by
+another inode.
+This error condition may invoke the
+.B "EXCESSIVE DUP BLKS"
+error condition in Phase 1 if
+inode \fII\fP has too many block numbers claimed by other inodes.
+This error condition will always invoke Phase 1b and the
+.B "BAD/DUP"
+error condition in Phase 2 and Phase 4.
+.sp
+.LP
+.B "EXCESSIVE DUP BLKS I=\fII\fP (CONTINUE)"
+.br
+There is more than a tolerable number (usually 10) of blocks claimed by other
+inodes.
+.LP
+Possible responses to the CONTINUE prompt are:
+.IP YES
+ignore the rest of the blocks in this inode
+and continue checking with the next inode in the file system.
+This error condition will not allow a complete check of the file system.
+A second run of
+.I fsck_ffs
+should be made to re-check this file system.
+.IP NO
+terminate the program.
+.sp
+.LP
+.B "DUP TABLE OVERFLOW (CONTINUE)"
+.br
+An internal table in
+.I fsck_ffs
+containing duplicate block numbers cannot allocate any more space.
+Increase the amount of virtual memory available to
+.I fsck_ffs .
+.LP
+Possible responses to the CONTINUE prompt are:
+.IP YES
+continue with the program.
+This error condition will not allow a complete check of the file system.
+A second run of
+.I fsck_ffs
+should be made to re-check this file system.
+If another duplicate block is found, this error condition will repeat.
+.IP NO
+terminate the program.
+.sp
+.LP
+.B "PARTIALLY ALLOCATED INODE I=\fII\fP (CLEAR)"
+.br
+Inode \fII\fP is neither allocated nor unallocated.
+.LP
+Possible responses to the CLEAR prompt are:
+.IP YES
+de-allocate inode \fII\fP by zeroing its contents.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "INCORRECT BLOCK COUNT I=\fII\fP (\fIX\fP should be \fIY\fP) (CORRECT)"
+.br
+The block count for inode \fII\fP is \fIX\fP blocks,
+but should be \fIY\fP blocks.
+When preen'ing the count is corrected.
+.LP
+Possible responses to the CORRECT prompt are:
+.IP YES
+replace the block count of inode \fII\fP with \fIY\fP.
+.IP NO
+ignore this error condition.
+.NH 2
+Phase 1B: Rescan for More Dups
+.PP
+When a duplicate block is found in the file system, the file system is
+rescanned to find the inode that previously claimed that block.
+This section lists the error condition when the duplicate block is found.
+.sp
+.LP
+.B "\fIB\fP DUP I=\fII\fP"
+.br
+Inode \fII\fP contains block number \fIB\fP that
+is already claimed by another inode.
+This error condition will always invoke the
+.B "BAD/DUP"
+error condition in Phase 2.
+You can determine which inodes have overlapping blocks by examining
+this error condition and the DUP error condition in Phase 1.
+.NH 2
+Phase 2 \- Check Pathnames
+.PP
+This phase concerns itself with removing directory entries
+pointing to
+error conditioned inodes
+from Phase 1 and Phase 1b.
+This section lists error conditions resulting from
+root inode mode and status,
+directory inode pointers in range,
+and directory entries pointing to bad inodes,
+and directory integrity checks.
+All errors in this phase are fatal if the file system is being preen'ed,
+except for directories not being a multiple of the blocks size
+and extraneous hard links.
+.sp
+.LP
+.B "ROOT INODE UNALLOCATED (ALLOCATE)"
+.br
+The root inode (usually inode number 2) has no allocate mode bits.
+This should never happen.
+.LP
+Possible responses to the ALLOCATE prompt are:
+.IP YES
+allocate inode 2 as the root inode.
+The files and directories usually found in the root will be recovered
+in Phase 3 and put into
+.I lost+found .
+If the attempt to allocate the root fails,
+.I fsck_ffs
+will exit with the message:
+.br
+.B "CANNOT ALLOCATE ROOT INODE" .
+.IP NO
+.I fsck_ffs
+will exit.
+.sp
+.LP
+.B "ROOT INODE NOT DIRECTORY (REALLOCATE)"
+.br
+The root inode (usually inode number 2)
+is not directory inode type.
+.LP
+Possible responses to the REALLOCATE prompt are:
+.IP YES
+clear the existing contents of the root inode
+and reallocate it.
+The files and directories usually found in the root will be recovered
+in Phase 3 and put into
+.I lost+found .
+If the attempt to allocate the root fails,
+.I fsck_ffs
+will exit with the message:
+.br
+.B "CANNOT ALLOCATE ROOT INODE" .
+.IP NO
+.I fsck_ffs
+will then prompt with
+.B "FIX"
+.LP
+Possible responses to the FIX prompt are:
+.IP YES
+replace the root inode's type to be a directory.
+If the root inode's data blocks are not directory blocks,
+many error conditions will be produced.
+.IP NO
+terminate the program.
+.sp
+.LP
+.B "DUPS/BAD IN ROOT INODE (REALLOCATE)"
+.br
+Phase 1 or Phase 1b have found duplicate blocks
+or bad blocks in the root inode (usually inode number 2) for the file system.
+.LP
+Possible responses to the REALLOCATE prompt are:
+.IP YES
+clear the existing contents of the root inode
+and reallocate it.
+The files and directories usually found in the root will be recovered
+in Phase 3 and put into
+.I lost+found .
+If the attempt to allocate the root fails,
+.I fsck_ffs
+will exit with the message:
+.br
+.B "CANNOT ALLOCATE ROOT INODE" .
+.IP NO
+.I fsck_ffs
+will then prompt with
+.B "CONTINUE" .
+.LP
+Possible responses to the CONTINUE prompt are:
+.IP YES
+ignore the
+.B "DUPS/BAD"
+error condition in the root inode and
+attempt to continue to run the file system check.
+If the root inode is not correct,
+then this may result in many other error conditions.
+.IP NO
+terminate the program.
+.sp
+.LP
+.B "NAME TOO LONG \fIF\fP"
+.br
+An excessively long path name has been found.
+This usually indicates loops in the file system name space.
+This can occur if the super user has made circular links to directories.
+The offending links must be removed (by a guru).
+.sp
+.LP
+.B "I OUT OF RANGE I=\fII\fP NAME=\fIF\fP (REMOVE)"
+.br
+A directory entry \fIF\fP has an inode number \fII\fP that is greater than
+the end of the inode list.
+.LP
+Possible responses to the REMOVE prompt are:
+.IP YES
+the directory entry \fIF\fP is removed.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "UNALLOCATED I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP \fItype\fP=\fIF\fP (REMOVE)"
+.br
+A directory or file entry \fIF\fP points to an unallocated inode \fII\fP.
+The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, modify time \fIT\fP,
+and name \fIF\fP are printed.
+.LP
+Possible responses to the REMOVE prompt are:
+.IP YES
+the directory entry \fIF\fP is removed.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "DUP/BAD I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP \fItype\fP=\fIF\fP (REMOVE)"
+.br
+Phase 1 or Phase 1b have found duplicate blocks or bad blocks
+associated with directory or file entry \fIF\fP, inode \fII\fP.
+The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, modify time \fIT\fP,
+and directory name \fIF\fP are printed.
+.LP
+Possible responses to the REMOVE prompt are:
+.IP YES
+the directory entry \fIF\fP is removed.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "ZERO LENGTH DIRECTORY I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (REMOVE)"
+.br
+A directory entry \fIF\fP has a size \fIS\fP that is zero.
+The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, modify time \fIT\fP,
+and directory name \fIF\fP are printed.
+.LP
+Possible responses to the REMOVE prompt are:
+.IP YES
+the directory entry \fIF\fP is removed;
+this will always invoke the BAD/DUP error condition in Phase 4.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "DIRECTORY TOO SHORT I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)"
+.br
+A directory \fIF\fP has been found whose size \fIS\fP
+is less than the minimum size directory.
+The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, modify time \fIT\fP,
+and directory name \fIF\fP are printed.
+.LP
+Possible responses to the FIX prompt are:
+.IP YES
+increase the size of the directory to the minimum directory size.
+.IP NO
+ignore this directory.
+.sp
+.LP
+.B "DIRECTORY \fIF\fP LENGTH \fIS\fP NOT MULTIPLE OF \fIB\fP (ADJUST)
+.br
+A directory \fIF\fP has been found with size \fIS\fP that is not
+a multiple of the directory blocksize \fIB\fP.
+.LP
+Possible responses to the ADJUST prompt are:
+.IP YES
+the length is rounded up to the appropriate block size.
+This error can occur on 4.2BSD file systems.
+Thus when preen'ing the file system only a warning is printed
+and the directory is adjusted.
+.IP NO
+ignore the error condition.
+.sp
+.LP
+.B "DIRECTORY CORRUPTED I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (SALVAGE)"
+.br
+A directory with an inconsistent internal state has been found.
+.LP
+Possible responses to the FIX prompt are:
+.IP YES
+throw away all entries up to the next directory boundary (usually 512-byte)
+boundary.
+This drastic action can throw away up to 42 entries,
+and should be taken only after other recovery efforts have failed.
+.IP NO
+skip up to the next directory boundary and resume reading,
+but do not modify the directory.
+.sp
+.LP
+.B "BAD INODE NUMBER FOR `.' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)"
+.br
+A directory \fII\fP has been found whose inode number for `.' does
+does not equal \fII\fP.
+.LP
+Possible responses to the FIX prompt are:
+.IP YES
+change the inode number for `.' to be equal to \fII\fP.
+.IP NO
+leave the inode number for `.' unchanged.
+.sp
+.LP
+.B "MISSING `.' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)"
+.br
+A directory \fII\fP has been found whose first entry is unallocated.
+.LP
+Possible responses to the FIX prompt are:
+.IP YES
+build an entry for `.' with inode number equal to \fII\fP.
+.IP NO
+leave the directory unchanged.
+.sp
+.LP
+.B "MISSING `.' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP"
+.br
+.B "CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS \fIF\fP"
+.br
+A directory \fII\fP has been found whose first entry is \fIF\fP.
+.I Fsck_ffs
+cannot resolve this problem.
+The file system should be mounted and the offending entry \fIF\fP
+moved elsewhere.
+The file system should then be unmounted and
+.I fsck_ffs
+should be run again.
+.sp
+.LP
+.B "MISSING `.' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP"
+.br
+.B "CANNOT FIX, INSUFFICIENT SPACE TO ADD `.'"
+.br
+A directory \fII\fP has been found whose first entry is not `.'.
+.I Fsck_ffs
+cannot resolve this problem as it should never happen.
+See a guru.
+.sp
+.LP
+.B "EXTRA `.' ENTRY I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)"
+.br
+A directory \fII\fP has been found that has more than one entry for `.'.
+.LP
+Possible responses to the FIX prompt are:
+.IP YES
+remove the extra entry for `.'.
+.IP NO
+leave the directory unchanged.
+.sp
+.LP
+.B "BAD INODE NUMBER FOR `..' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)"
+.br
+A directory \fII\fP has been found whose inode number for `..' does
+does not equal the parent of \fII\fP.
+.LP
+Possible responses to the FIX prompt are:
+.IP YES
+change the inode number for `..' to be equal to the parent of \fII\fP
+(``\fB..\fP'' in the root inode points to itself).
+.IP NO
+leave the inode number for `..' unchanged.
+.sp
+.LP
+.B "MISSING `..' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)"
+.br
+A directory \fII\fP has been found whose second entry is unallocated.
+.LP
+Possible responses to the FIX prompt are:
+.IP YES
+build an entry for `..' with inode number equal to the parent of \fII\fP
+(``\fB..\fP'' in the root inode points to itself).
+.IP NO
+leave the directory unchanged.
+.sp
+.LP
+.B "MISSING `..' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP"
+.br
+.B "CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS \fIF\fP"
+.br
+A directory \fII\fP has been found whose second entry is \fIF\fP.
+.I Fsck_ffs
+cannot resolve this problem.
+The file system should be mounted and the offending entry \fIF\fP
+moved elsewhere.
+The file system should then be unmounted and
+.I fsck_ffs
+should be run again.
+.sp
+.LP
+.B "MISSING `..' I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP"
+.br
+.B "CANNOT FIX, INSUFFICIENT SPACE TO ADD `..'"
+.br
+A directory \fII\fP has been found whose second entry is not `..'.
+.I Fsck_ffs
+cannot resolve this problem.
+The file system should be mounted and the second entry in the directory
+moved elsewhere.
+The file system should then be unmounted and
+.I fsck_ffs
+should be run again.
+.sp
+.LP
+.B "EXTRA `..' ENTRY I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP DIR=\fIF\fP (FIX)"
+.br
+A directory \fII\fP has been found that has more than one entry for `..'.
+.LP
+Possible responses to the FIX prompt are:
+.IP YES
+remove the extra entry for `..'.
+.IP NO
+leave the directory unchanged.
+.sp
+.LP
+.B "\fIN\fP IS AN EXTRANEOUS HARD LINK TO A DIRECTORY \fID\fP (REMOVE)
+.br
+.I Fsck_ffs
+has found a hard link, \fIN\fP, to a directory, \fID\fP.
+When preen'ing the extraneous links are ignored.
+.LP
+Possible responses to the REMOVE prompt are:
+.IP YES
+delete the extraneous entry, \fIN\fP.
+.IP NO
+ignore the error condition.
+.sp
+.LP
+.B "BAD INODE \fIS\fP TO DESCEND"
+.br
+An internal error has caused an impossible state \fIS\fP to be passed to the
+routine that descends the file system directory structure.
+.I Fsck_ffs
+exits.
+See a guru.
+.sp
+.LP
+.B "BAD RETURN STATE \fIS\fP FROM DESCEND"
+.br
+An internal error has caused an impossible state \fIS\fP to be returned
+from the routine that descends the file system directory structure.
+.I Fsck_ffs
+exits.
+See a guru.
+.sp
+.LP
+.B "BAD STATE \fIS\fP FOR ROOT INODE"
+.br
+An internal error has caused an impossible state \fIS\fP to be assigned
+to the root inode.
+.I Fsck_ffs
+exits.
+See a guru.
+.NH 2
+Phase 3 \- Check Connectivity
+.PP
+This phase concerns itself with the directory connectivity seen in
+Phase 2.
+This section lists error conditions resulting from
+unreferenced directories,
+and missing or full
+.I lost+found
+directories.
+.sp
+.LP
+.B "UNREF DIR I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP (RECONNECT)"
+.br
+The directory inode \fII\fP was not connected to a directory entry
+when the file system was traversed.
+The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, and
+modify time \fIT\fP of directory inode \fII\fP are printed.
+When preen'ing, the directory is reconnected if its size is non-zero,
+otherwise it is cleared.
+.LP
+Possible responses to the RECONNECT prompt are:
+.IP YES
+reconnect directory inode \fII\fP to the file system in the
+directory for lost files (usually \fIlost+found\fP).
+This may invoke the
+.I lost+found
+error condition in Phase 3
+if there are problems connecting directory inode \fII\fP to \fIlost+found\fP.
+This may also invoke the CONNECTED error condition in Phase 3 if the link
+was successful.
+.IP NO
+ignore this error condition.
+This will always invoke the UNREF error condition in Phase 4.
+.sp
+.LP
+.B "NO lost+found DIRECTORY (CREATE)"
+.br
+There is no
+.I lost+found
+directory in the root directory of the file system;
+When preen'ing
+.I fsck_ffs
+tries to create a \fIlost+found\fP directory.
+.LP
+Possible responses to the CREATE prompt are:
+.IP YES
+create a \fIlost+found\fP directory in the root of the file system.
+This may raise the message:
+.br
+.B "NO SPACE LEFT IN / (EXPAND)"
+.br
+See below for the possible responses.
+Inability to create a \fIlost+found\fP directory generates the message:
+.br
+.B "SORRY. CANNOT CREATE lost+found DIRECTORY"
+.br
+and aborts the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+.IP NO
+abort the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+.sp
+.LP
+.B "lost+found IS NOT A DIRECTORY (REALLOCATE)"
+.br
+The entry for
+.I lost+found
+is not a directory.
+.LP
+Possible responses to the REALLOCATE prompt are:
+.IP YES
+allocate a directory inode, and change \fIlost+found\fP to reference it.
+The previous inode reference by the \fIlost+found\fP name is not cleared.
+Thus it will either be reclaimed as an UNREF'ed inode or have its
+link count ADJUST'ed later in this Phase.
+Inability to create a \fIlost+found\fP directory generates the message:
+.br
+.B "SORRY. CANNOT CREATE lost+found DIRECTORY"
+.br
+and aborts the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+.IP NO
+abort the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+.sp
+.LP
+.B "NO SPACE LEFT IN /lost+found (EXPAND)"
+.br
+There is no space to add another entry to the
+.I lost+found
+directory in the root directory
+of the file system.
+When preen'ing the
+.I lost+found
+directory is expanded.
+.LP
+Possible responses to the EXPAND prompt are:
+.IP YES
+the
+.I lost+found
+directory is expanded to make room for the new entry.
+If the attempted expansion fails
+.I fsck_ffs
+prints the message:
+.br
+.B "SORRY. NO SPACE IN lost+found DIRECTORY"
+.br
+and aborts the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+Clean out unnecessary entries in
+.I lost+found .
+This error is fatal if the file system is being preen'ed.
+.IP NO
+abort the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+.sp
+.LP
+.B "DIR I=\fII1\fP CONNECTED. PARENT WAS I=\fII2\fP"
+.br
+This is an advisory message indicating a directory inode \fII1\fP was
+successfully connected to the
+.I lost+found
+directory.
+The parent inode \fII2\fP of the directory inode \fII1\fP is
+replaced by the inode number of the
+.I lost+found
+directory.
+.sp
+.LP
+.B "DIRECTORY \fIF\fP LENGTH \fIS\fP NOT MULTIPLE OF \fIB\fP (ADJUST)
+.br
+A directory \fIF\fP has been found with size \fIS\fP that is not
+a multiple of the directory blocksize \fIB\fP
+(this can reoccur in Phase 3 if it is not adjusted in Phase 2).
+.LP
+Possible responses to the ADJUST prompt are:
+.IP YES
+the length is rounded up to the appropriate block size.
+This error can occur on 4.2BSD file systems.
+Thus when preen'ing the file system only a warning is printed
+and the directory is adjusted.
+.IP NO
+ignore the error condition.
+.sp
+.LP
+.B "BAD INODE \fIS\fP TO DESCEND"
+.br
+An internal error has caused an impossible state \fIS\fP to be passed to the
+routine that descends the file system directory structure.
+.I Fsck_ffs
+exits.
+See a guru.
+.NH 2
+Phase 4 \- Check Reference Counts
+.PP
+This phase concerns itself with the link count information
+seen in Phase 2 and Phase 3.
+This section lists error conditions resulting from
+unreferenced files,
+missing or full
+.I lost+found
+directory,
+incorrect link counts for files, directories, symbolic links, or special files,
+unreferenced files, symbolic links, and directories,
+and bad or duplicate blocks in files, symbolic links, and directories.
+All errors in this phase are correctable if the file system is being preen'ed
+except running out of space in the \fIlost+found\fP directory.
+.sp
+.LP
+.B "UNREF FILE I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP (RECONNECT)"
+.br
+Inode \fII\fP was not connected to a directory entry
+when the file system was traversed.
+The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, and
+modify time \fIT\fP of inode \fII\fP are printed.
+When preen'ing the file is cleared if either its size or its
+link count is zero,
+otherwise it is reconnected.
+.LP
+Possible responses to the RECONNECT prompt are:
+.IP YES
+reconnect inode \fII\fP to the file system in the directory for
+lost files (usually \fIlost+found\fP).
+This may invoke the
+.I lost+found
+error condition in Phase 4
+if there are problems connecting inode \fII\fP to
+.I lost+found .
+.IP NO
+ignore this error condition.
+This will always invoke the CLEAR error condition in Phase 4.
+.sp
+.LP
+.B "(CLEAR)"
+.br
+The inode mentioned in the immediately previous error condition can not be
+reconnected.
+This cannot occur if the file system is being preen'ed,
+since lack of space to reconnect files is a fatal error.
+.LP
+Possible responses to the CLEAR prompt are:
+.IP YES
+de-allocate the inode mentioned in the immediately previous error condition by zeroing its contents.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "NO lost+found DIRECTORY (CREATE)"
+.br
+There is no
+.I lost+found
+directory in the root directory of the file system;
+When preen'ing
+.I fsck_ffs
+tries to create a \fIlost+found\fP directory.
+.LP
+Possible responses to the CREATE prompt are:
+.IP YES
+create a \fIlost+found\fP directory in the root of the file system.
+This may raise the message:
+.br
+.B "NO SPACE LEFT IN / (EXPAND)"
+.br
+See below for the possible responses.
+Inability to create a \fIlost+found\fP directory generates the message:
+.br
+.B "SORRY. CANNOT CREATE lost+found DIRECTORY"
+.br
+and aborts the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+.IP NO
+abort the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+.sp
+.LP
+.B "lost+found IS NOT A DIRECTORY (REALLOCATE)"
+.br
+The entry for
+.I lost+found
+is not a directory.
+.LP
+Possible responses to the REALLOCATE prompt are:
+.IP YES
+allocate a directory inode, and change \fIlost+found\fP to reference it.
+The previous inode reference by the \fIlost+found\fP name is not cleared.
+Thus it will either be reclaimed as an UNREF'ed inode or have its
+link count ADJUST'ed later in this Phase.
+Inability to create a \fIlost+found\fP directory generates the message:
+.br
+.B "SORRY. CANNOT CREATE lost+found DIRECTORY"
+.br
+and aborts the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+.IP NO
+abort the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+.sp
+.LP
+.B "NO SPACE LEFT IN /lost+found (EXPAND)"
+.br
+There is no space to add another entry to the
+.I lost+found
+directory in the root directory
+of the file system.
+When preen'ing the
+.I lost+found
+directory is expanded.
+.LP
+Possible responses to the EXPAND prompt are:
+.IP YES
+the
+.I lost+found
+directory is expanded to make room for the new entry.
+If the attempted expansion fails
+.I fsck_ffs
+prints the message:
+.br
+.B "SORRY. NO SPACE IN lost+found DIRECTORY"
+.br
+and aborts the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+Clean out unnecessary entries in
+.I lost+found .
+This error is fatal if the file system is being preen'ed.
+.IP NO
+abort the attempt to linkup the lost inode.
+This will always invoke the UNREF error condition in Phase 4.
+.sp
+.LP
+.B "LINK COUNT \fItype\fP I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP COUNT=\fIX\fP SHOULD BE \fIY\fP (ADJUST)"
+.br
+The link count for inode \fII\fP,
+is \fIX\fP but should be \fIY\fP.
+The owner \fIO\fP, mode \fIM\fP, size \fIS\fP, and modify time \fIT\fP
+are printed.
+When preen'ing the link count is adjusted unless the number of references
+is increasing, a condition that should never occur unless precipitated
+by a hardware failure.
+When the number of references is increasing under preen mode,
+.I fsck_ffs
+exits with the message:
+.br
+.B "LINK COUNT INCREASING"
+.LP
+Possible responses to the ADJUST prompt are:
+.IP YES
+replace the link count of file inode \fII\fP with \fIY\fP.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "UNREF \fItype\fP I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP (CLEAR)"
+.br
+Inode \fII\fP, was not connected to a directory entry when the
+file system was traversed.
+The owner \fIO\fP, mode \fIM\fP, size \fIS\fP,
+and modify time \fIT\fP of inode \fII\fP
+are printed.
+When preen'ing,
+this is a file that was not connected because its size or link count was zero,
+hence it is cleared.
+.LP
+Possible responses to the CLEAR prompt are:
+.IP YES
+de-allocate inode \fII\fP by zeroing its contents.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "BAD/DUP \fItype\fP I=\fII\fP OWNER=\fIO\fP MODE=\fIM\fP SIZE=\fIS\fP MTIME=\fIT\fP (CLEAR)"
+.br
+Phase 1 or Phase 1b have found duplicate blocks
+or bad blocks associated with
+inode \fII\fP.
+The owner \fIO\fP, mode \fIM\fP, size \fIS\fP,
+and modify time \fIT\fP of inode \fII\fP
+are printed.
+This error cannot arise when the file system is being preen'ed,
+as it would have caused a fatal error earlier.
+.LP
+Possible responses to the CLEAR prompt are:
+.IP YES
+de-allocate inode \fII\fP by zeroing its contents.
+.IP NO
+ignore this error condition.
+.NH 2
+Phase 5 - Check Cyl groups
+.PP
+This phase concerns itself with the free-block and used-inode maps.
+This section lists error conditions resulting from
+allocated blocks in the free-block maps,
+free blocks missing from free-block maps,
+and the total free-block count incorrect.
+It also lists error conditions resulting from
+free inodes in the used-inode maps,
+allocated inodes missing from used-inode maps,
+and the total used-inode count incorrect.
+.sp
+.LP
+.B "CG \fIC\fP: BAD MAGIC NUMBER"
+.br
+The magic number of cylinder group \fIC\fP is wrong.
+This usually indicates that the cylinder group maps have been destroyed.
+When running manually the cylinder group is marked as needing
+to be reconstructed.
+This error is fatal if the file system is being preen'ed.
+.sp
+.LP
+.B "BLK(S) MISSING IN BIT MAPS (SALVAGE)"
+.br
+A cylinder group block map is missing some free blocks.
+During preen'ing the maps are reconstructed.
+.LP
+Possible responses to the SALVAGE prompt are:
+.IP YES
+reconstruct the free block map.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "SUMMARY INFORMATION BAD (SALVAGE)"
+.br
+The summary information was found to be incorrect.
+When preen'ing,
+the summary information is recomputed.
+.LP
+Possible responses to the SALVAGE prompt are:
+.IP YES
+reconstruct the summary information.
+.IP NO
+ignore this error condition.
+.sp
+.LP
+.B "FREE BLK COUNT(S) WRONG IN SUPERBLOCK (SALVAGE)"
+.br
+The superblock free block information was found to be incorrect.
+When preen'ing,
+the superblock free block information is recomputed.
+.LP
+Possible responses to the SALVAGE prompt are:
+.IP YES
+reconstruct the superblock free block information.
+.IP NO
+ignore this error condition.
+.NH 2
+Cleanup
+.PP
+Once a file system has been checked, a few cleanup functions are performed.
+This section lists advisory messages about
+the file system
+and modify status of the file system.
+.sp
+.LP
+.B "\fIV\fP files, \fIW\fP used, \fIX\fP free (\fIY\fP frags, \fIZ\fP blocks)"
+.br
+This is an advisory message indicating that
+the file system checked contained
+\fIV\fP files using
+\fIW\fP fragment sized blocks leaving
+\fIX\fP fragment sized blocks free in the file system.
+The numbers in parenthesis breaks the free count down into
+\fIY\fP free fragments and
+\fIZ\fP free full sized blocks.
+.sp
+.LP
+.B "***** REBOOT UNIX *****"
+.br
+This is an advisory message indicating that
+the root file system has been modified by
+.I fsck_ffs.
+If UNIX is not rebooted immediately,
+the work done by
+.I fsck_ffs
+may be undone by the in-core copies of tables
+UNIX keeps.
+When preen'ing,
+.I fsck_ffs
+will exit with a code of 4.
+The standard auto-reboot script distributed with 4.3BSD
+interprets an exit code of 4 by issuing a reboot system call.
+.sp
+.LP
+.B "***** FILE SYSTEM WAS MODIFIED *****"
+.br
+This is an advisory message indicating that
+the current file system was modified by
+.I fsck_ffs.
+If this file system is mounted or is the current root file system,
+.I fsck_ffs
+should be halted and UNIX rebooted.
+If UNIX is not rebooted immediately,
+the work done by
+.I fsck_ffs
+may be undone by the in-core copies of tables
+UNIX keeps.
diff --git a/share/doc/smm/03.fsck/Makefile b/share/doc/smm/03.fsck/Makefile
index fbdc009..88d1ec3 100644
--- a/share/doc/smm/03.fsck/Makefile
+++ b/share/doc/smm/03.fsck/Makefile
@@ -4,6 +4,5 @@
VOLUME= smm/03.fsck
SRCS= 0.t 1.t 2.t 3.t 4.t
MACROS= -ms
-SRCDIR= ${.CURDIR}/../../../../sbin/fsck_ffs/SMM.doc
.include <bsd.doc.mk>
diff --git a/share/doc/smm/07.lpr/0.t b/share/doc/smm/07.lpr/0.t
new file mode 100644
index 0000000..65ecd4e
--- /dev/null
+++ b/share/doc/smm/07.lpr/0.t
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)0.t 8.1 (Berkeley) 6/8/93
+.\"
+.if n .ND
+.TL
+4.3BSD Line Printer Spooler Manual
+.EH 'SMM:7-%''4.3BSD Line Printer Spooler Manual'
+.OH '4.3BSD Line Printer Spooler Manual''SMM:7-%'
+.AU
+Ralph Campbell
+.AI
+Computer Systems Research Group
+Computer Science Division
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, CA 94720
+.AB
+.FS
+* UNIX is a trademark of Bell Laboratories.
+.FE
+This document describes the structure and installation procedure
+for the line printer spooling system
+developed for the 4.3BSD version
+of the UNIX* operating system.
+.de D?
+.ie \\n(.$>1 Revised \\$1 \\$2 \\$3
+.el DRAFT of \n(mo/\n(dy/\n(yr
+..
+.sp 2
+.LP
+.D? June 8, 1993
+.AE
+.de IR
+\fI\\$1\fP\\$2
+..
+.de DT
+.TA 8 16 24 32 40 48 56 64 72 80
+..
diff --git a/share/doc/smm/07.lpr/1.t b/share/doc/smm/07.lpr/1.t
new file mode 100644
index 0000000..1d34e9e
--- /dev/null
+++ b/share/doc/smm/07.lpr/1.t
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)1.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Overview
+.PP
+The line printer system supports:
+.IP \(bu 3
+multiple printers,
+.IP \(bu 3
+multiple spooling queues,
+.IP \(bu 3
+both local and remote
+printers, and
+.IP \(bu 3
+printers attached via serial lines that require
+line initialization such as the baud rate.
+.LP
+Raster output devices
+such as a Varian or Versatec, and laser printers such as an Imagen,
+are also supported by the line printer system.
+.PP
+The line printer system consists mainly of the
+following files and commands:
+.DS
+.TS
+l l.
+/etc/printcap printer configuration and capability data base
+/usr/lib/lpd line printer daemon, does all the real work
+/usr/ucb/lpr program to enter a job in a printer queue
+/usr/ucb/lpq spooling queue examination program
+/usr/ucb/lprm program to delete jobs from a queue
+/etc/lpc program to administer printers and spooling queues
+/dev/printer socket on which lpd listens
+.TE
+.DE
+The file /etc/printcap is a master data base describing line
+printers directly attached to a machine and, also, printers
+accessible across a network. The manual page entry
+.IR printcap (5)
+provides the authoritative definition of
+the format of this data base, as well as
+specifying default values for important items
+such as the directory in which spooling is performed.
+This document introduces some of the
+information that may be placed
+.IR printcap .
diff --git a/share/doc/smm/07.lpr/2.t b/share/doc/smm/07.lpr/2.t
new file mode 100644
index 0000000..9da2ae2
--- /dev/null
+++ b/share/doc/smm/07.lpr/2.t
@@ -0,0 +1,141 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)2.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Commands
+.NH 2
+lpd \- line printer daemon
+.PP
+The program
+.IR lpd (8),
+usually invoked at boot time from the /etc/rc file, acts as
+a master server for coordinating and controlling
+the spooling queues configured in the printcap file.
+When
+.I lpd
+is started it makes a single pass through the
+.I printcap
+database restarting any printers that have jobs.
+In normal operation
+.I lpd
+listens for service requests on multiple sockets,
+one in the UNIX domain (named ``/dev/printer'') for
+local requests, and one in the Internet domain
+(under the ``printer'' service specification)
+for requests for printer access from off machine;
+see \fIsocket\fP\|(2) and \fIservices\fP\|(5)
+for more information on sockets and service
+specifications, respectively.
+.I Lpd
+spawns a copy of itself to process the request; the master daemon
+continues to listen for new requests.
+.PP
+Clients communicate with
+.I lpd
+using a simple transaction oriented protocol.
+Authentication of remote clients is done based
+on the ``privilege port'' scheme employed by
+\fIrshd\fP\|(8C) and \fIrcmd\fP\|(3X).
+The following table shows the requests
+understood by
+.IR lpd .
+In each request the first byte indicates the
+``meaning'' of the request, followed by the name
+of the printer to which it should be applied. Additional
+qualifiers may follow, depending on the request.
+.DS
+.TS
+l l.
+Request Interpretation
+_
+^Aprinter\en check the queue for jobs and print any found
+^Bprinter\en receive and queue a job from another machine
+^Cprinter [users ...] [jobs ...]\en return short list of current queue state
+^Dprinter [users ...] [jobs ...]\en return long list of current queue state
+^Eprinter person [users ...] [jobs ...]\en remove jobs from a queue
+.TE
+.DE
+.PP
+The \fIlpr\fP\|(1) command
+is used by users to enter a print job in a local queue and to notify
+the local
+.I lpd
+that there are new jobs in the spooling area.
+.I Lpd
+either schedules the job to be printed locally, or if
+printing remotely, attempts to forward
+the job to the appropriate machine.
+If the printer cannot be opened or the destination
+machine is unreachable, the job will remain queued until it is
+possible to complete the work.
+.NH 2
+lpq \- show line printer queue
+.PP
+The \fIlpq\fP\|(1)
+program works recursively backwards displaying the queue of the machine with
+the printer and then the queue(s) of the machine(s) that lead to it.
+.I Lpq
+has two forms of output: in the default, short, format it
+gives a single line of output per queued job; in the long
+format it shows the list of files, and their sizes, that
+comprise a job.
+.NH 2
+lprm \- remove jobs from a queue
+.PP
+The \fIlprm\fP\|(1) command deletes jobs from a spooling
+queue. If necessary, \fIlprm\fP will first kill off a
+running daemon that is servicing the queue and restart
+it after the required files are removed. When removing
+jobs destined for a remote printer, \fIlprm\fP acts
+similarly to \fIlpq\fP except it first checks locally
+for jobs to remove and then
+tries to remove files in queues off-machine.
+.NH 2
+lpc \- line printer control program
+.PP
+The
+.IR lpc (8)
+program is used by the system administrator to control the
+operation of the line printer system.
+For each line printer configured in /etc/printcap,
+.I lpc
+may be used to:
+.IP \(bu
+disable or enable a printer,
+.IP \(bu
+disable or enable a printer's spooling queue,
+.IP \(bu
+rearrange the order of jobs in a spooling queue,
+.IP \(bu
+find the status of printers, and their associated
+spooling queues and printer daemons.
diff --git a/share/doc/smm/07.lpr/3.t b/share/doc/smm/07.lpr/3.t
new file mode 100644
index 0000000..8c950a9
--- /dev/null
+++ b/share/doc/smm/07.lpr/3.t
@@ -0,0 +1,73 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)3.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Access control
+.PP
+The printer system maintains protected spooling areas so that
+users cannot circumvent printer accounting or
+remove files other than their own.
+The strategy used to maintain protected
+spooling areas is as follows:
+.IP \(bu 3
+The spooling area is writable only by a \fIdaemon\fP user
+and \fIdaemon\fP group.
+.IP \(bu 3
+The \fIlpr\fP program runs set-user-id to \fIroot\fP and
+set-group-id to group \fIdaemon\fP. The \fIroot\fP access permits
+reading any file required. Accessibility is verified
+with an \fIaccess\fP\|(2) call. The group ID
+is used in setting up proper ownership of files
+in the spooling area for \fIlprm\fP.
+.IP \(bu 3
+Control files in a spooling area are made with \fIdaemon\fP
+ownership and group ownership \fIdaemon\fP. Their mode is 0660.
+This insures control files are not modified by a user
+and that no user can remove files except through \fIlprm\fP.
+.IP \(bu 3
+The spooling programs,
+\fIlpd\fP, \fIlpq\fP, and \fIlprm\fP run set-user-id to \fIroot\fP
+and set-group-id to group \fIdaemon\fP to access spool files and printers.
+.IP \(bu 3
+The printer server, \fIlpd\fP,
+uses the same verification procedures as \fIrshd\fP\|(8C)
+in authenticating remote clients. The host on which a client
+resides must be present in the file /etc/hosts.equiv or /etc/hosts.lpd and
+the request message must come from a reserved port number.
+.PP
+In practice, none of \fIlpd\fP, \fIlpq\fP, or
+\fIlprm\fP would have to run as user \fIroot\fP if remote
+spooling were not supported. In previous incarnations of
+the printer system \fIlpd\fP ran set-user-id to \fIdaemon\fP,
+set-group-id to group \fIspooling\fP, and \fIlpq\fP and \fIlprm\fP ran
+set-group-id to group \fIspooling\fP.
diff --git a/share/doc/smm/07.lpr/4.t b/share/doc/smm/07.lpr/4.t
new file mode 100644
index 0000000..8800bc0
--- /dev/null
+++ b/share/doc/smm/07.lpr/4.t
@@ -0,0 +1,206 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)4.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Setting up
+.PP
+The 4.3BSD release comes with the necessary programs
+installed and with the default line printer queue
+created. If the system must be modified, the
+makefile in the directory /usr/src/usr.lib/lpr
+should be used in recompiling and reinstalling
+the necessary programs.
+.PP
+The real work in setting up is to create the
+.I printcap
+file and any printer filters for printers not supported
+in the distribution system.
+.NH 2
+Creating a printcap file
+.PP
+The
+.I printcap
+database contains one or more entries per printer.
+A printer should have a separate spooling directory;
+otherwise, jobs will be printed on
+different printers depending on which printer daemon starts first.
+This section describes how to create entries for printers that do not
+conform to the default printer description (an LP-11 style interface to a
+standard, band printer).
+.NH 3
+Printers on serial lines
+.PP
+When a printer is connected via a serial communication line
+it must have the proper baud rate and terminal modes set.
+The following example is for a DecWriter III printer connected
+locally via a 1200 baud serial line.
+.DS
+.DT
+lp|LA-180 DecWriter III:\e
+ :lp=/dev/lp:br#1200:fs#06320:\e
+ :tr=\ef:of=/usr/lib/lpf:lf=/usr/adm/lpd-errs:
+.DE
+The
+.B lp
+entry specifies the file name to open for output. Here it could
+be left out since ``/dev/lp'' is the default.
+The
+.B br
+entry sets the baud rate for the tty line and the
+.B fs
+entry sets CRMOD, no parity, and XTABS (see \fItty\fP\|(4)).
+The
+.B tr
+entry indicates that a form-feed should be printed when the queue
+empties so the paper can be torn off without turning the printer off-line and
+pressing form feed.
+The
+.B of
+entry specifies the filter program
+.I lpf
+should be used for printing the files;
+more will be said about filters later.
+The last entry causes errors
+to be written to the file ``/usr/adm/lpd-errs''
+instead of the console. Most errors from \fIlpd\fP are logged using
+\fIsyslogd\fP\|(8) and will not be logged in the specified file. The
+filters should use \fIsyslogd\fP to report errors; only those that
+write to standard error output will end up with errors in the \fBlf\fP file.
+(Occasionally errors sent to standard error output have not appeared
+in the log file; the use of \fIsyslogd\fP is highly recommended.)
+.NH 3
+Remote printers
+.PP
+Printers that reside on remote hosts should have an empty
+.B lp
+entry.
+For example, the following printcap entry would send output to the printer
+named ``lp'' on the machine ``ucbvax''.
+.DS
+.DT
+lp|default line printer:\e
+ :lp=:rm=ucbvax:rp=lp:sd=/usr/spool/vaxlpd:
+.DE
+The
+.B rm
+entry is the name of the remote machine to connect to; this name must
+be a known host name for a machine on the network.
+The
+.B rp
+capability indicates
+the name of the printer on the remote machine is ``lp'';
+here it could be left out since this is the default value.
+The
+.B sd
+entry specifies ``/usr/spool/vaxlpd''
+as the spooling directory instead of the
+default value of ``/usr/spool/lpd''.
+.NH 2
+Output filters
+.PP
+Filters are used to handle device dependencies and to
+do accounting functions. The output filtering of
+.B of
+is used when accounting is
+not being done or when all text data must be passed through a filter.
+It is not intended to do accounting since it is started only once,
+all text files are filtered through it, and no provision is made for passing
+owners' login name, identifying the beginning and ending of jobs, etc.
+The other filters (if specified) are started for each file
+printed and do accounting if there is an
+.B af
+entry.
+If entries for both
+.B of
+and other filters are specified,
+the output filter is used only to print the banner page;
+it is then stopped to allow other filters access to the printer.
+An example of a printer that requires output filters
+is the Benson-Varian.
+.DS
+.DT
+va|varian|Benson-Varian:\e
+ :lp=/dev/va0:sd=/usr/spool/vad:of=/usr/lib/vpf:\e
+ :tf=/usr/lib/rvcat:mx#2000:pl#58:px=2112:py=1700:tr=\ef:
+.DE
+The
+.B tf
+entry specifies ``/usr/lib/rvcat'' as the filter to be
+used in printing \fItroff\fP\|(1) output.
+This filter is needed to set the device into print mode
+for text, and plot mode for printing
+.I troff
+files and raster images (see \fIva\fP\|(4V)).
+Note that the page length is set to 58 lines by the
+.B pl
+entry for 8.5" by 11" fan-fold paper.
+To enable accounting, the varian entry would be
+augmented with an
+.B af
+filter as shown below.
+.DS
+.DT
+va|varian|Benson-Varian:\e
+ :lp=/dev/va0:sd=/usr/spool/vad:of=/usr/lib/vpf:\e
+ :if=/usr/lib/vpf:tf=/usr/lib/rvcat:af=/usr/adm/vaacct:\e
+ :mx#2000:pl#58:px=2112:py=1700:tr=\ef:
+.DE
+.NH 2
+Access Control
+.PP
+Local access to printer queues is controlled with the
+.B rg
+printcap entry.
+.DS
+ :rg=lprgroup:
+.DE
+Users must be in the group
+.I lprgroup
+to submit jobs to the specified printer.
+The default is to allow all users access.
+Note that once the files are in the local queue, they can be printed
+locally or forwarded to another host depending on the configuration.
+.PP
+Remote access is controlled by listing the hosts in either the file
+/etc/hosts.equiv or /etc/hosts.lpd, one host per line. Note that
+.IR rsh (1)
+and
+.IR rlogin (1)
+use /etc/hosts.equiv to determine which hosts are equivalent for allowing logins
+without passwords. The file /etc/hosts.lpd is only used to control
+which hosts have line printer access.
+Remote access can be further restricted to only allow remote users with accounts
+on the local host to print jobs by using the \fBrs\fP printcap entry.
+.DS
+ :rs:
+.DE
diff --git a/share/doc/smm/07.lpr/5.t b/share/doc/smm/07.lpr/5.t
new file mode 100644
index 0000000..137a342
--- /dev/null
+++ b/share/doc/smm/07.lpr/5.t
@@ -0,0 +1,116 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)5.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Output filter specifications
+.PP
+The filters supplied with 4.3BSD
+handle printing and accounting for most common
+line printers, the Benson-Varian, the wide (36") and
+narrow (11") Versatec printer/plotters. For other devices or accounting
+methods, it may be necessary to create a new filter.
+.PP
+Filters are spawned by \fIlpd\fP
+with their standard input the data to be printed, and standard output
+the printer. The standard error is attached to the
+.B lf
+file for logging errors or \fIsyslogd\fP may be used for logging errors.
+A filter must return a 0 exit
+code if there were no errors, 1 if the job should be reprinted,
+and 2 if the job should be thrown away.
+When \fIlprm\fP
+sends a kill signal to the \fIlpd\fP process controlling
+printing, it sends a SIGINT signal
+to all filters and descendents of filters.
+This signal can be trapped by filters that need
+to do cleanup operations such as
+deleting temporary files.
+.PP
+Arguments passed to a filter depend on its type.
+The
+.B of
+filter is called with the following arguments.
+.DS
+\fIfilter\fP \fB\-w\fPwidth \fB\-l\fPlength
+.DE
+The \fIwidth\fP and \fIlength\fP values come from the
+.B pw
+and
+.B pl
+entries in the printcap database.
+The
+.B if
+filter is passed the following parameters.
+.DS
+\fIfilter\fP [\|\fB\-c\fP\|] \fB\-w\fPwidth \fB\-l\fPlength \fB\-i\fPindent \fB\-n\fP login \fB\-h\fP host accounting_file
+.DE
+The
+.B \-c
+flag is optional, and only supplied when control characters
+are to be passed uninterpreted to the printer (when using the
+.B \-l
+option of
+.I lpr
+to print the file).
+The
+.B \-w
+and
+.B \-l
+parameters are the same as for the
+.B of
+filter.
+The
+.B \-n
+and
+.B \-h
+parameters specify the login name and host name of the job owner.
+The last argument is the name of the accounting file from
+.IR printcap .
+.PP
+All other filters are called with the following arguments:
+.DS
+\fIfilter\fP \fB\-x\fPwidth \fB\-y\fPlength \fB\-n\fP login \fB\-h\fP host accounting_file
+.DE
+The
+.B \-x
+and
+.B \-y
+options specify the horizontal and vertical page
+size in pixels (from the
+.B px
+and
+.B py
+entries in the printcap file).
+The rest of the arguments are the same as for the
+.B if
+filter.
diff --git a/share/doc/smm/07.lpr/6.t b/share/doc/smm/07.lpr/6.t
new file mode 100644
index 0000000..7087790
--- /dev/null
+++ b/share/doc/smm/07.lpr/6.t
@@ -0,0 +1,94 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)6.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Line printer Administration
+.PP
+The
+.I lpc
+program provides local control over line printer activity.
+The major commands and their intended use will be described.
+The command format and remaining commands are described in
+.IR lpc (8).
+.LP
+\fBabort\fP and \fBstart\fP
+.IP
+.I Abort
+terminates an active spooling daemon on the local host immediately and
+then disables printing (preventing new daemons from being started by
+.IR lpr ).
+This is normally used to forcibly restart a hung line printer daemon
+(i.e., \fIlpq\fP reports that there is a daemon present but nothing is
+happening). It does not remove any jobs from the queue
+(use the \fIlprm\fP command instead).
+.I Start
+enables printing and requests \fIlpd\fP to start printing jobs.
+.LP
+\fBenable\fP and \fBdisable\fP
+.IP
+\fIEnable\fP and \fIdisable\fP allow spooling in the local queue to be
+turned on/off.
+This will allow/prevent
+.I lpr
+from putting new jobs in the spool queue. It is frequently convenient
+to turn spooling off while testing new line printer filters since the
+.I root
+user can still use
+.I lpr
+to put jobs in the queue but no one else can.
+The other main use is to prevent users from putting jobs in the queue
+when the printer is expected to be unavailable for a long time.
+.LP
+\fBrestart\fP
+.IP
+.I Restart
+allows ordinary users to restart printer daemons when
+.I lpq
+reports that there is no daemon present.
+.LP
+\fBstop\fP
+.IP
+.I Stop
+halts a spooling daemon after the current job completes;
+this also disables printing. This is a clean way to shutdown a
+printer to do maintenance, etc. Note that users can still enter jobs in a
+spool queue while a printer is
+.IR stopped .
+.LP
+\fBtopq\fP
+.IP
+.I Topq
+places jobs at the top of a printer queue. This can be used
+to reorder high priority jobs since
+.I lpr
+only provides first-come-first-serve ordering of jobs.
diff --git a/share/doc/smm/07.lpr/7.t b/share/doc/smm/07.lpr/7.t
new file mode 100644
index 0000000..a6f6bea
--- /dev/null
+++ b/share/doc/smm/07.lpr/7.t
@@ -0,0 +1,226 @@
+.\" Copyright (c) 1983, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)7.t 8.1 (Berkeley) 6/8/93
+.\"
+.NH 1
+Troubleshooting
+.PP
+There are several messages that may be generated by the
+the line printer system. This section
+categorizes the most common and explains the cause
+for their generation. Where the message implies a failure,
+directions are given to remedy the problem.
+.PP
+In the examples below, the name
+.I printer
+is the name of the printer from the
+.I printcap
+database.
+.NH 2
+LPR
+.SH
+lpr: \fIprinter\fP\|: unknown printer
+.IP
+The
+.I printer
+was not found in the
+.I printcap
+database. Usually this is a typing mistake; however, it may indicate
+a missing or incorrect entry in the /etc/printcap file.
+.SH
+lpr: \fIprinter\fP\|: jobs queued, but cannot start daemon.
+.IP
+The connection to
+.I lpd
+on the local machine failed.
+This usually means the printer server started at
+boot time has died or is hung. Check the local socket
+/dev/printer to be sure it still exists (if it does not exist,
+there is no
+.I lpd
+process running).
+Usually it is enough to get a super-user to type the following to
+restart
+.IR lpd .
+.DS
+% /usr/lib/lpd
+.DE
+You can also check the state of the master printer daemon with the following.
+.DS
+% ps l`cat /usr/spool/lpd.lock`
+.DE
+.IP
+Another possibility is that the
+.I lpr
+program is not set-user-id to \fIroot\fP, set-group-id to group \fIdaemon\fP.
+This can be checked with
+.DS
+% ls \-lg /usr/ucb/lpr
+.DE
+.SH
+lpr: \fIprinter\fP\|: printer queue is disabled
+.IP
+This means the queue was turned off with
+.DS
+% lpc disable \fIprinter\fP
+.DE
+to prevent
+.I lpr
+from putting files in the queue. This is normally
+done by the system manager when a printer is
+going to be down for a long time. The
+printer can be turned back on by a super-user with
+.IR lpc .
+.NH 2
+LPQ
+.SH
+waiting for \fIprinter\fP to become ready (offline ?)
+.IP
+The printer device could not be opened by the daemon.
+This can happen for several reasons,
+the most common is that the printer is turned off-line.
+This message can also be generated if the printer is out
+of paper, the paper is jammed, etc.
+The actual reason is dependent on the meaning
+of error codes returned by system device driver.
+Not all printers supply enough information
+to distinguish when a printer is off-line or having
+trouble (e.g. a printer connected through a serial line).
+Another possible cause of this message is
+some other process, such as an output filter,
+has an exclusive open on the device. Your only recourse
+here is to kill off the offending program(s) and
+restart the printer with
+.IR lpc .
+.SH
+\fIprinter\fP is ready and printing
+.IP
+The
+.I lpq
+program checks to see if a daemon process exists for
+.I printer
+and prints the file \fIstatus\fP located in the spooling directory.
+If the daemon is hung, a super user can use
+.I lpc
+to abort the current daemon and start a new one.
+.SH
+waiting for \fIhost\fP to come up
+.IP
+This implies there is a daemon trying to connect to the remote
+machine named
+.I host
+to send the files in the local queue.
+If the remote machine is up,
+.I lpd
+on the remote machine is probably dead or
+hung and should be restarted as mentioned for
+.IR lpr .
+.SH
+sending to \fIhost\fP
+.IP
+The files should be in the process of being transferred to the remote
+.IR host .
+If not, the local daemon should be aborted and started with
+.IR lpc .
+.SH
+Warning: \fIprinter\fP is down
+.IP
+The printer has been marked as being unavailable with
+.IR lpc .
+.SH
+Warning: no daemon present
+.IP
+The \fIlpd\fP process overseeing
+the spooling queue, as specified in the ``lock'' file
+in that directory, does not exist. This normally occurs
+only when the daemon has unexpectedly died.
+The error log file for the printer and the \fIsyslogd\fP logs
+should be checked for a
+diagnostic from the deceased process.
+To restart an \fIlpd\fP, use
+.DS
+% lpc restart \fIprinter\fP
+.DE
+.SH
+no space on remote; waiting for queue to drain
+.IP
+This implies that there is insufficient disk space on the remote.
+If the file is large enough, there will never be enough space on
+the remote (even after the queue on the remote is empty). The solution here
+is to move the spooling queue or make more free space on the remote.
+.NH 2
+LPRM
+.SH
+lprm: \fIprinter\fP\|: cannot restart printer daemon
+.IP
+This case is the same as when
+.I lpr
+prints that the daemon cannot be started.
+.NH 2
+LPD
+.PP
+The
+.I lpd
+program can log many different messages using \fIsyslogd\fP\|(8).
+Most of these messages are about files that can not
+be opened and usually imply that the
+.I printcap
+file or the protection modes of the files are
+incorrect. Files may also be inaccessible if people
+manually manipulate the line printer system (i.e. they
+bypass the
+.I lpr
+program).
+.PP
+In addition to messages generated by
+.IR lpd ,
+any of the filters that
+.I lpd
+spawns may log messages using \fIsyslogd\fP or to the error log file
+(the file specified in the \fBlf\fP entry in \fIprintcap\fP\|).
+.NH 2
+LPC
+.PP
+.SH
+couldn't start printer
+.IP
+This case is the same as when
+.I lpr
+reports that the daemon cannot be started.
+.SH
+cannot examine spool directory
+.IP
+Error messages beginning with ``cannot ...'' are usually because of
+incorrect ownership or protection mode of the lock file, spooling
+directory or the
+.I lpc
+program.
diff --git a/share/doc/smm/07.lpr/Makefile b/share/doc/smm/07.lpr/Makefile
new file mode 100644
index 0000000..20455e1
--- /dev/null
+++ b/share/doc/smm/07.lpr/Makefile
@@ -0,0 +1,9 @@
+# From: @(#)Makefile 8.1 (Berkeley) 6/8/93
+# $FreeBSD$
+
+VOLUME= smm/07.lpd
+SRCS= 0.t 1.t 2.t 3.t 4.t 5.t 6.t 7.t
+MACROS= -ms
+USE_TBL=
+
+.include <bsd.doc.mk>
diff --git a/share/doc/smm/07.lpr/spell.ok b/share/doc/smm/07.lpr/spell.ok
new file mode 100644
index 0000000..bf31319
--- /dev/null
+++ b/share/doc/smm/07.lpr/spell.ok
@@ -0,0 +1,70 @@
+Aprinter
+Bprinter
+CRMOD
+Cprinter
+DecWriter
+Dprinter
+Eprinter
+LPC
+LPD
+Lpd
+Manual''SMM:5
+SIGINT
+SMM:5
+Topq
+XTABS
+adm
+af
+br
+daemon
+daemons
+dev
+f:of
+fs
+hosts.equiv
+hosts.lpd
+lf
+lg
+lib
+lp:br
+lp:sd
+lpc
+lpd
+lpd.lock
+lpf
+lpf:lf
+lprgroup
+makefile
+mx
+offline
+pl
+printcap
+pw
+py
+rc
+rcmd
+rg
+rlogin
+rp
+rs
+rsh
+rshd
+rvcat
+rvcat:af
+rvcat:mx
+sd
+src
+syslogd
+tf
+topq
+ucb
+ucbvax
+ucbvax:rp
+usr.lib
+va0:sd
+vaacct
+vad:of
+varian
+vaxlpd
+vpf
+vpf:tf
diff --git a/share/doc/smm/11.timedop/Makefile b/share/doc/smm/11.timedop/Makefile
index ad09e78..aec9918 100644
--- a/share/doc/smm/11.timedop/Makefile
+++ b/share/doc/smm/11.timedop/Makefile
@@ -4,6 +4,5 @@
VOLUME= smm/11.timedop
SRCS= timed.ms
MACROS= -ms
-SRCDIR= ${.CURDIR}/../../../../usr.sbin/timed/SMM.doc/timedop
.include <bsd.doc.mk>
diff --git a/share/doc/smm/11.timedop/timed.ms b/share/doc/smm/11.timedop/timed.ms
new file mode 100644
index 0000000..feea0b5
--- /dev/null
+++ b/share/doc/smm/11.timedop/timed.ms
@@ -0,0 +1,279 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)timed.ms 8.1 (Berkeley) 6/8/93
+.\"
+.TL
+Timed Installation and Operation Guide
+.AU
+Riccardo Gusella, Stefano Zatti, James M. Bloom
+.AI
+Computer Systems Research Group
+Computer Science Division
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, CA 94720
+.AU
+Kirk Smith
+.AI
+Engineering Computer Network
+Department of Electrical Engineering
+Purdue University
+West Lafayette, IN 47906
+.FS
+This work was sponsored by the Defense Advanced Research Projects Agency
+(DoD), monitored by the Naval Electronics Systems
+Command under contract No. N00039-84-C-0089, and by the CSELT
+Corporation of Italy.
+The views and conclusions contained in this document are those of the
+authors and should not be interpreted as representing official policies,
+either expressed or implied, of the Defense Research Projects Agency,
+of the US Government, or of CSELT.
+.FE
+.LP
+.EH 'SMM:11-%''Timed Installation and Operation'
+.OH 'Timed Installation and Operation''SMM:11-%'
+.SH
+Introduction
+.PP
+The clock synchronization service for
+the UNIX 4.3BSD operating system is composed of a collection of
+time daemons (\fItimed\fP) running on the machines in a local
+area network.
+The algorithms implemented by the service is based on a master-slave scheme.
+The time daemons communicate with each other using the
+\fITime Synchronization Protocol\fP (TSP) which
+is built on the DARPA UDP protocol and described in detail in [4].
+.PP
+A time daemon has a twofold function.
+First, it supports the synchronization of the clocks
+of the various hosts in a local area network.
+Second, it starts (or takes part in) the election that occurs
+among slave time daemons when, for any reason, the master disappears.
+The synchronization mechanism and the election procedure
+employed by the program \fItimed\fP are described
+in other documents [1,2,3].
+The next paragraphs are a brief overview of how the time daemon works.
+This document is mainly concerned with the administrative and technical
+issues of running \fItimed\fP at a particular site.
+.PP
+A \fImaster time daemon\fP measures the time
+differences between the clock of the machine on which it
+is running and those of all other machines.
+The master computes the \fInetwork time\fP as the average of the
+times provided by nonfaulty clocks.\**
+.FS
+A clock is considered to be faulty when its value
+is more than a small specified
+interval apart from the majority of the clocks
+of the other machines [1,2].
+.FE
+It then sends to each \fIslave time daemon\fP the
+correction that should be performed on the clock of its machine.
+This process is repeated periodically.
+Since the correction is expressed as a time difference rather than an
+absolute time, transmission delays do not interfere with
+the accuracy of the synchronization.
+When a machine comes up and joins the network,
+it starts a slave time daemon which
+will ask the master for the correct time and will reset the machine's clock
+before any user activity can begin.
+The time daemons are able to maintain a single network time in spite of
+the drift of clocks away from each other.
+The present implementation keeps processor clocks synchronized
+within 20 milliseconds.
+.PP
+To ensure that the service provided is continuous and reliable,
+it is necessary to implement an election algorithm to elect a
+new master should the machine running the current master crash, the master
+terminate (for example, because of a run-time error), or
+the network be partitioned.
+Under our algorithm, slaves are able to realize when the master has
+stopped functioning and to elect a new master from among themselves.
+It is important to note that, since the failure of the master results
+only in a gradual divergence of clock values, the election
+need not occur immediately.
+.PP
+The machines that are gateways between distinct local area
+networks require particular care.
+A time daemon on such machines may act as a \fIsubmaster\fP.
+This artifact depends on the current inability of
+transmission protocols to broadcast a message on a network
+other than the one to which the broadcasting machine is connected.
+The submaster appears as a slave on one network, and as a master
+on one or more of the other networks to which it is connected.
+.PP
+A submaster classifies each network as one of three types.
+A \fIslave network\fP is a network on which the submaster acts as a slave.
+There can only be one slave network.
+A \fImaster network\fP is a network on which the submaster acts as a master.
+An \fIignored network\fP is any other network which already has a valid master.
+The submaster tries periodically to become master on an ignored
+network, but gives up immediately if a master already exists.
+.SH
+Guidelines
+.PP
+While the synchronization algorithm is quite general, the election
+one, requiring a broadcast mechanism, puts constraints on
+the kind of network on which time daemons can run.
+The time daemon will only work on networks with broadcast capability
+augmented with point-to-point links.
+Machines that are only connected to point-to-point,
+non-broadcast networks may not use the time daemon.
+.PP
+If we exclude submasters, there will normally be, at most, one master time
+daemon in a local area internetwork.
+During an election, only one of the slave time daemons
+will become the new master.
+However, because of the characteristics of its machine,
+a slave can be prevented from becoming the master.
+Therefore, a subset of machines must be designated as potential
+master time daemons.
+A master time daemon will require CPU resources
+proportional to the number of slaves, in general, more than
+a slave time daemon, so it may be advisable to limit master time
+daemons to machines with more powerful processors or lighter loads.
+Also, machines with inaccurate clocks should not be used as masters.
+This is a purely administrative decision: an organization may
+well allow all of its machines to run master time daemons.
+.PP
+At the administrative level, a time daemon on a machine
+with multiple network interfaces, may be told to ignore all
+but one network or to ignore one network.
+This is done with the \fI\-n network\fP and \fI\-i network\fP
+options respectively at start-up time.
+Typically, the time daemon would be instructed to ignore all but
+the networks belonging to the local administrative control.
+.PP
+There are some limitations to the current
+implementation of the time daemon.
+It is expected that these limitations will be removed in future releases.
+The constant NHOSTS in /usr/src/etc/timed/globals.h limits the
+maximum number of machines that may be directly controlled by one
+master time daemon.
+The current maximum is 29 (NHOSTS \- 1).
+The constant must be changed and the program recompiled if a site wishes to
+run \fItimed\fP on a larger (inter)network.
+.PP
+In addition, there is a \fIpathological situation\fP to
+be avoided at all costs, that might occur when
+time daemons run on multiply-connected local area networks.
+In this case, as we have seen, time daemons running on gateway machines
+will be submasters and they will act on some of those
+networks as master time daemons.
+Consider machines A and B that are both gateways between
+networks X and Y.
+If time daemons were started on both A and B without constraints, it would be
+possible for submaster time daemon A to be a slave on network X
+and the master on network Y, while submaster time daemon B is a slave on
+network Y and the master on network X.
+This \fIloop\fP of master time daemons will not function properly
+or guarantee a unique time on both networks, and will cause
+the submasters to use large amounts of system resources in the form
+of network bandwidth and CPU time.
+In fact, this kind of \fIloop\fP can also be generated with more
+than two master time daemons,
+when several local area networks are interconnected.
+.SH
+Installation
+.PP
+In order to start the time daemon on a given machine,
+the following lines should be
+added to the \fIlocal daemons\fP section in the file \fI/etc/rc.local\fP:
+.sp 2
+.in 1i
+.nf
+if [ -f /etc/timed ]; then
+ /etc/timed \fIflags\fP & echo -n ' timed' >/dev/console
+fi
+.fi
+.in -1i
+.sp
+.LP
+In any case, they must appear after the network
+is configured via ifconfig(8).
+.PP
+Also, the file \fI/etc/services\fP should contain the following
+line:
+.sp 2
+.ti 1i
+timed 525/udp timeserver
+.sp
+.LP
+The \fIflags\fP are:
+.IP "-n network" 13
+to consider the named network.
+.IP "-i network"
+to ignore the named network.
+.IP -t
+to place tracing information in \fI/usr/adm/timed.log\fP.
+.IP -M
+to allow this time daemon to become a master.
+A time daemon run without this option will be forced in the state of
+slave during an election.
+.SH
+Daily Operation
+.PP
+\fITimedc(8)\fP is used to control the operation of the time daemon.
+It may be used to:
+.IP \(bu
+measure the differences between machines' clocks,
+.IP \(bu
+find the location where the master \fItimed\fP is running,
+.IP \(bu
+cause election timers on several machines to expire at the same time,
+.IP \(bu
+enable or disable tracing of messages received by \fItimed\fP.
+.LP
+See the manual page on \fItimed\fP\|(8) and \fItimedc\fP\|(8)
+for more detailed information.
+.PP
+The \fIdate(1)\fP command can be used to set the network date.
+In order to set the time on a single machine, the \fI-n\fP flag
+can be given to date(1).
+.bp
+.SH
+References
+.IP 1.
+R. Gusella and S. Zatti,
+\fITEMPO: A Network Time Controller for Distributed Berkeley UNIX System\fP,
+USENIX Summer Conference Proceedings, Salt Lake City, June 1984.
+.IP 2.
+R. Gusella and S. Zatti, \fIClock Synchronization in a Local Area Network\fP,
+University of California, Berkeley, Technical Report, \fIto appear\fP.
+.IP 3.
+R. Gusella and S. Zatti,
+\fIAn Election Algorithm for a Distributed Clock Synchronization Program\fP,
+University of California, Berkeley, CS Technical Report #275, Dec. 1985.
+.IP 4.
+R. Gusella and S. Zatti,
+\fIThe Berkeley UNIX 4.3BSD Time Synchronization Protocol\fP,
+UNIX Programmer's Manual, 4.3 Berkeley Software Distribution, Volume 2c.
diff --git a/share/doc/smm/12.timed/Makefile b/share/doc/smm/12.timed/Makefile
index 1d9ed5c..f844568 100644
--- a/share/doc/smm/12.timed/Makefile
+++ b/share/doc/smm/12.timed/Makefile
@@ -7,6 +7,5 @@ EXTRA= date loop time unused
MACROS= -ms
USE_SOELIM=
USE_TBL=
-SRCDIR= ${.CURDIR}/../../../../usr.sbin/timed/SMM.doc/timed
.include <bsd.doc.mk>
diff --git a/share/doc/smm/12.timed/date b/share/doc/smm/12.timed/date
new file mode 100644
index 0000000..e4e4d58
--- /dev/null
+++ b/share/doc/smm/12.timed/date
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)date 8.1 (Berkeley) 6/8/93
+.\"
+.ft B
+.TS
+center;
+ce | ce | ce | ce
+| c | c | c | s |
+| c s s s |.
+Byte 1 Byte 2 Byte 3 Byte 4
+=
+Type Version No. Sequence No.
+_
+Seconds of Time to Set
+_
+Microseconds of Time to Set
+_
+Machine Name
+_
+\&. . .
+_
+.TE
+.ft R
diff --git a/share/doc/smm/12.timed/loop b/share/doc/smm/12.timed/loop
new file mode 100644
index 0000000..11ccb4d
--- /dev/null
+++ b/share/doc/smm/12.timed/loop
@@ -0,0 +1,54 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)loop 8.1 (Berkeley) 6/8/93
+.\"
+.ft B
+.TS
+center;
+ce | ce | ce | ce
+| c | c | c | s |
+| c | c s s |
+| c s s s |.
+Byte 1 Byte 2 Byte 3 Byte 4
+=
+Type Version No. Sequence No.
+_
+Hop Count ( unused )
+_
+( unused )
+_
+Machine Name
+_
+\&. . .
+_
+.TE
+.ft R
diff --git a/share/doc/smm/12.timed/spell.ok b/share/doc/smm/12.timed/spell.ok
new file mode 100644
index 0000000..8ecfe15
--- /dev/null
+++ b/share/doc/smm/12.timed/spell.ok
@@ -0,0 +1,34 @@
+ACK
+ADJTIME
+Adjtime
+CS
+CSELT
+Candidature
+DATEACK
+DoD
+Gusella
+MASTERACK
+MASTERREQ
+MASTERUP
+MSITE
+MSITEREQ
+Protocol''SMM:22
+Riccardo
+SETDATE
+SETDATEREQ
+SETTIME
+SLAVEUP
+SMM:22
+Stefano
+TRACEOFF
+TRACEON
+TSP
+Timedc
+UDP
+USENIX
+Zatti
+candidature
+ce
+daemon
+daemons
+timedc
diff --git a/share/doc/smm/12.timed/time b/share/doc/smm/12.timed/time
new file mode 100644
index 0000000..619d171
--- /dev/null
+++ b/share/doc/smm/12.timed/time
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)time 8.1 (Berkeley) 6/8/93
+.\"
+.ft B
+.TS
+center;
+ce | ce | ce | ce
+| c | c | c | s |
+| c s s s |.
+Byte 1 Byte 2 Byte 3 Byte 4
+=
+Type Version No. Sequence No.
+_
+Seconds of Adjustment
+_
+Microseconds of Adjustment
+_
+Machine Name
+_
+\&. . .
+_
+.TE
+.ft R
diff --git a/share/doc/smm/12.timed/timed.ms b/share/doc/smm/12.timed/timed.ms
new file mode 100644
index 0000000..412399a
--- /dev/null
+++ b/share/doc/smm/12.timed/timed.ms
@@ -0,0 +1,462 @@
+.\" $FreeBSD$
+.\"
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)timed.ms 8.1 (Berkeley) 6/8/93
+.\"
+.TL
+The Berkeley
+.UX
+.br
+Time Synchronization Protocol
+.AU
+Riccardo Gusella, Stefano Zatti, and James M. Bloom
+.AI
+Computer Systems Research Group
+Computer Science Division
+Department of Electrical Engineering and Computer Science
+University of California, Berkeley
+Berkeley, CA 94720
+.FS
+This work was sponsored by the Defense Advanced Research Projects Agency
+(DoD), monitored by the Naval Electronics Systems
+Command under contract No. N00039-84-C-0089, and by the Italian CSELT
+Corporation.
+The views and conclusions contained in this document are those of the
+authors and should not be interpreted as representing official policies,
+either expressed or implied, of the Defense Research Projects Agency,
+of the US Government, or of CSELT.
+.FE
+.LP
+.OH 'The Berkeley UNIX Time Synchronization Protocol''SMM:12-%'
+.EH 'SMM:12-%''The Berkeley UNIX Time Synchronization Protocol'
+.SH
+Introduction
+.PP
+The Time Synchronization Protocol (TSP)
+has been designed for specific use by the program \fItimed\fP,
+a local area network clock synchronizer for
+the UNIX 4.3BSD operating
+system.
+Timed is built on the DARPA UDP protocol [4] and
+is based on a master slave scheme.
+.PP
+TSP serves a dual purpose.
+First, it supports messages for the synchronization of the clocks
+of the various hosts in a local area network.
+Second, it supports messages for the election that occurs
+among slave time daemons when, for any reason, the master disappears.
+The synchronization mechanism and the election procedure
+employed by the program timed are described
+in other documents [1,2,3].
+.PP
+Briefly, the synchronization software, which works in a
+local area network, consists of a collection of \fItime daemons\fP
+(one per machine) and is based on a master-slave
+structure.
+The present implementation keeps processor clocks synchronized
+within 20 milliseconds.
+A \fImaster time daemon\fP measures the time
+difference between the clock of the machine on which it
+is running and those of all other machines. The current implementation
+uses ICMP \fITime Stamp Requests\fP [5] to measure the clock difference
+between machines.
+The master computes the \fInetwork time\fP as the average of the
+times provided by nonfaulty clocks.\**
+.FS
+A clock is considered to be faulty when its value
+is more than a small specified
+interval apart from the majority of the clocks
+of the machines on the same network.
+See [1,2] for more details.
+.FE
+It then sends to each \fIslave time daemon\fP the
+correction that should be performed on the clock of its machine.
+This process is repeated periodically.
+Since the correction is expressed as a time difference rather than an
+absolute time, transmission delays do not interfere with synchronization.
+When a machine comes up and joins the network,
+it starts a slave time daemon, which
+will ask the master for the correct time and will reset the machine's clock
+before any user activity can begin.
+The time daemons therefore maintain a single network time in spite of
+the drift of clocks away from each other.
+.PP
+Additionally, a time daemon on gateway machines may run as
+a \fIsubmaster\fP.
+A submaster time daemon functions as a slave on one network that
+already has a master and as master on other networks.
+In addition, a submaster is responsible for propagating broadcast
+packets from one network to the other.
+.PP
+To ensure that service provided is continuous and reliable,
+it is necessary to implement an election algorithm that will elect a
+new master should the machine running the current master crash, the master
+terminate (for example, because of a run-time error), or the network be
+partitioned.
+Under our algorithm, slaves are able to realize when the master has
+stopped functioning and to elect a new master from among themselves.
+It is important to note that since the failure of the master results
+only in a gradual divergence of clock values, the election
+need not occur immediately.
+.PP
+All the communication occurring among time daemons uses the TSP
+protocol.
+While some messages need not be sent in a reliable way,
+most communication in TSP requires reliability not provided by the underlying
+protocol.
+Reliability is achieved by the use of acknowledgements, sequence numbers, and
+retransmission when message losses occur.
+When a message that requires acknowledgment is not acknowledged after
+multiple attempts,
+the time daemon that has sent the message will assume that the
+addressee is down.
+This document will not describe the details of how reliability is
+implemented, but will only point out when
+a message type requires a reliable transport mechanism.
+.PP
+The message format in TSP is the same for all message types;
+however, in some instances, one or more fields are not used.
+The next section describes the message format.
+The following sections describe
+in detail the different message types, their use and the contents
+of each field. NOTE: The message format is likely to change in
+future versions of timed.
+.sp 2
+.SH
+Message Format
+.PP
+All fields are based upon 8-bit bytes. Fields should be sent in
+network byte order if they are more than one byte long.
+The structure of a TSP message is the following:
+.IP 1)
+A one byte message type.
+.IP 2)
+A one byte version number, specifying the protocol version which the
+message uses.
+.IP 3)
+A two byte sequence number to be used for recognizing duplicate messages
+that occur when messages are retransmitted.
+.IP 4)
+Eight bytes of packet specific data. This field contains two 4 byte time
+values, a one byte hop count, or may be unused depending on the type
+of the packet.
+.IP 5)
+A zero-terminated string of up to 256 \s-2ASCII\s+2 characters with the name of
+the machine sending the message.
+.PP
+The following charts describe the message types,
+show their fields, and explain their usages.
+For the purpose of the following discussion, a time daemon can
+be considered to be in
+one of three states: slave, master, or candidate for election to master.
+Also, the term \fIbroadcast\fP refers to
+the sending of a message to all active time daemons.
+.sp 1
+.SH
+Adjtime Message
+.so time
+.LP
+Type: TSP_ADJTIME (1)
+.sp 1
+.PP
+The master sends this message to a slave to communicate
+the difference between
+the clock of the slave and
+the network time the master has just computed.
+The slave will accordingly
+adjust the time of its machine.
+This message requires an acknowledgment.
+.sp 1
+.SH
+Acknowledgment Message
+.so unused
+.LP
+Type: TSP_ACK (2)
+.sp 1
+.PP
+Both the master and the slaves use this message for
+acknowledgment only.
+It is used in several different contexts, for example
+in reply to an Adjtime message.
+.sp 1
+.SH
+Master Request Message
+.so unused
+.LP
+Type: TSP_MASTERREQ (3)
+.sp 1
+.PP
+A newly-started time daemon broadcasts this message to
+locate a master. No other action is implied by this packet.
+It requires a Master Acknowledgment.
+.sp 1
+.SH
+Master Acknowledgement
+.so unused
+.LP
+Type: TSP_MASTERACK (4)
+.sp 1
+.PP
+The master sends this message to acknowledge the Master Request message
+and the Conflict Resolution Message.
+.sp 1
+.SH
+Set Network Time Message
+.so date
+.LP
+Type: TSP_SETTIME (5)
+.sp 1
+.PP
+The master sends this message to slave time daemons to set their time.
+This packet is sent to newly started time daemons and when the network
+date is changed.
+It contains the master's time as an approximation of the network time.
+It requires an acknowledgment.
+The next
+synchronization round will eliminate the small time difference
+caused by the random delay in the communication channel.
+.sp 1
+.SH
+Master Active Message
+.so unused
+.LP
+Type: TSP_MASTERUP (6)
+.sp 1
+.PP
+The master broadcasts this message to
+solicit the names of the active slaves.
+Slaves will reply with a Slave Active message.
+.sp 1
+.SH
+Slave Active Message
+.so unused
+.LP
+Type: TSP_SLAVEUP (7)
+.sp 1
+.PP
+A slave sends this message to the master in answer to a Master Active message.
+This message is also sent when a new slave starts up to inform the master that
+it wants to be synchronized.
+.sp 1
+.SH
+Master Candidature Message
+.so unused
+.LP
+Type: TSP_ELECTION (8)
+.sp 1
+.PP
+A slave eligible to become a master broadcasts this message when its election
+timer expires.
+The message declares that the slave wishes to become the new master.
+.sp 1
+.SH
+Candidature Acceptance Message
+.so unused
+.LP
+Type: TSP_ACCEPT (9)
+.sp 1
+.PP
+A slave sends this message to accept the candidature of the time daemon
+that has broadcast an Election message.
+The candidate will add the slave's name to the list of machines that it
+will control should it become the master.
+.sp 1
+.SH
+Candidature Rejection Message
+.so unused
+.LP
+Type: TSP_REFUSE (10)
+.sp 1
+.PP
+After a slave accepts the candidature of a time daemon, it will reply
+to any election messages from other slaves
+with this message.
+This rejects any candidature other than the first received.
+.sp 1
+.SH
+Multiple Master Notification Message
+.so unused
+.LP
+Type: TSP_CONFLICT (11)
+.sp 1
+.PP
+When two or more masters reply to a Master Request message, the slave
+uses this message to inform one of them that more than one master exists.
+.sp 1
+.SH
+Conflict Resolution Message
+.so unused
+.LP
+Type: TSP_RESOLVE (12)
+.sp 1
+.PP
+A master which has been informed of the existence of other masters
+broadcasts this message to determine who the other masters are.
+.sp 1
+.SH
+Quit Message
+.so unused
+.LP
+Type: TSP_QUIT (13)
+.sp 1
+.PP
+This message is sent by the master in three different contexts:
+1) to a candidate that broadcasts a Master Candidature message,
+2) to another master when notified of its existence,
+3) to another master if a loop is detected.
+In all cases, the recipient time daemon will become a slave.
+This message requires an acknowledgement.
+.sp 1
+.SH
+Set Date Message
+.so date
+.LP
+Type: TSP_SETDATE (22)
+.sp 1
+.PP
+The program \fIdate\fP\|(1) sends this message to the local time daemon
+when a super-user wants to set the network date.
+If the local time daemon is the master, it will set the date;
+if it is a slave, it will communicate the desired date to the master.
+.sp 1
+.SH
+Set Date Request Message
+.so date
+.LP
+Type: TSP_SETDATEREQ (23)
+.sp 1
+.PP
+A slave that has received a Set Date message will communicate the
+desired date to the master using this message.
+.sp 1
+.SH
+Set Date Acknowledgment Message
+.so unused
+.LP
+Type: TSP_DATEACK (16)
+.sp 1
+.PP
+The master sends this message to a slave in acknowledgment of a
+Set Date Request Message.
+The same message is sent by the local time daemon to the program
+\fIdate(1)\fP to confirm that the network date has been set by the
+master.
+.sp 1
+.SH
+Start Tracing Message
+.so unused
+.LP
+Type: TSP_TRACEON (17)
+.sp 1
+.PP
+The controlling program \fItimedc\fP sends this message to the local
+time daemon to start the recording in a system file of
+all messages received.
+.sp 1
+.SH
+Stop Tracing Message
+.so unused
+.LP
+Type: TSP_TRACEOFF (18)
+.sp 1
+.PP
+\fITimedc\fP sends this message to the local
+time daemon to stop the recording of
+messages received.
+.sp 1
+.SH
+Master Site Message
+.so unused
+.LP
+Type: TSP_MSITE (19)
+.sp 1
+.PP
+\fITimedc\fP sends this message to the local time daemon to find out
+where the master is running.
+.sp 1
+.SH
+Remote Master Site Message
+.so unused
+.LP
+Type: TSP_MSITEREQ (20)
+.sp 1
+.PP
+A local time daemon broadcasts this message to find the location
+of the master.
+It then uses the Acknowledgement message to
+communicate this location to \fItimedc\fP.
+.sp 1
+.SH
+Test Message
+.so unused
+.LP
+Type: TSP_TEST (21)
+.sp 1
+.PP
+For testing purposes, \fItimedc\fP sends this message to a slave
+to cause its election timer to expire. NOTE: \fItimed\fP
+is not normally compiled to support this.
+.sp 1
+.SH
+.SH
+Loop Detection Message
+.so loop
+.LP
+Type: TSP_LOOP (24)
+.sp 1
+.PP
+This packet is initiated by all masters occasionally to attempt to detect loops.
+All submasters forward this packet onto the networks over which they are master.
+If a master receives a packet it sent out initially,
+it knows that a loop exists and tries to correct the problem.
+.SH
+References
+.IP 1.
+R. Gusella and S. Zatti,
+\fITEMPO: A Network Time Controller for Distributed Berkeley UNIX System\fP,
+USENIX Summer Conference Proceedings, Salt Lake City, June 1984.
+.IP 2.
+R. Gusella and S. Zatti, \fIClock Synchronization in a Local Area Network\fP,
+University of California, Berkeley, Technical Report, \fIto appear\fP.
+.IP 3.
+R. Gusella and S. Zatti,
+\fIAn Election Algorithm for a Distributed Clock Synchronization Program\fP,
+University of California, Berkeley, CS Technical Report #275, Dec. 1985.
+.IP 4.
+Postel, J., \fIUser Datagram Protocol\fP, RFC 768.
+Network Information Center, SRI International, Menlo Park, California,
+August 1980.
+.IP 5.
+Postel, J., \fIInternet Control Message Protocol\fP, RFC 792.
+Network Information Center, SRI International, Menlo Park, California,
+September 1981.
diff --git a/share/doc/smm/12.timed/unused b/share/doc/smm/12.timed/unused
new file mode 100644
index 0000000..adadfc3
--- /dev/null
+++ b/share/doc/smm/12.timed/unused
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1986, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)unused 8.1 (Berkeley) 6/8/93
+.\"
+.ft B
+.TS
+center;
+ce | ce | ce | ce
+| c | c | c | s |
+| c s s s |.
+Byte 1 Byte 2 Byte 3 Byte 4
+=
+Type Version No. Sequence No.
+_
+( unused )
+_
+( unused )
+_
+Machine Name
+_
+\&. . .
+_
+.TE
+.ft R
diff --git a/share/doc/usd/04.csh/Makefile b/share/doc/usd/04.csh/Makefile
index d22a7b9..5606b8f 100644
--- a/share/doc/usd/04.csh/Makefile
+++ b/share/doc/usd/04.csh/Makefile
@@ -5,6 +5,5 @@ VOLUME= usd/04.csh
SRCS= tabs csh.1 csh.2 csh.3 csh.4 csh.a csh.g
MACROS= -ms
USE_SOELIM=
-SRCDIR= ${.CURDIR}/../../../../bin/csh/USD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/usd/04.csh/csh.1 b/share/doc/usd/04.csh/csh.1
new file mode 100644
index 0000000..915cb23
--- /dev/null
+++ b/share/doc/usd/04.csh/csh.1
@@ -0,0 +1,1012 @@
+.\"-
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)csh.1 8.1 (Berkeley) 6/8/93
+.\" $FreeBSD$
+.\"
+.EH 'USD:4-%''An Introduction to the C shell'
+.OH 'An Introduction to the C shell''USD:4-%'
+.\".RP
+.TL
+An Introduction to the C shell
+.AU
+William Joy
+(revised for 4.3BSD by Mark Seiden)
+.AI
+Computer Science Division
+.br
+Department of Electrical Engineering and Computer Science
+.br
+University of California, Berkeley
+.br
+Berkeley, California 94720
+.AB
+.I Csh
+is a new command language interpreter for
+.UX
+systems.
+It incorporates good features of other shells and a
+.I history
+mechanism similar to the
+.I redo
+of \s-2INTERLISP\s0.
+While incorporating many features of other shells which make
+writing shell programs (shell scripts) easier,
+most of the features unique to
+.I csh
+are designed more for the interactive \s-2UNIX\s0 user.
+.PP
+\s-2UNIX\s0
+users who have read a general introduction to the system
+will find a valuable basic explanation of the shell here.
+Simple terminal interaction with
+.I csh
+is possible after reading just the first section of this document.
+The second section describes the shell's capabilities which you can
+explore after you have begun to become acquainted with the shell.
+Later sections introduce features which are useful, but not necessary
+for all users of the shell.
+.PP
+Additional information includes an appendix listing special characters of the shell
+and a glossary of terms and commands introduced in this manual.
+.AE
+.SH
+.if n .ND
+Introduction
+.PP
+A
+.I shell
+is a command language interpreter.
+.I Csh
+is the name of one particular command interpreter on
+\s-2UNIX\s0.
+The primary purpose of
+.I csh
+is to translate command lines typed at a terminal into
+system actions, such as invocation of other programs.
+.I Csh
+is a user program just like any you might write.
+Hopefully,
+.I csh
+will be a very useful program for you
+in interacting with the \s-2UNIX\s0 system.
+.PP
+In addition to this document, you will want to refer to a copy
+of the \s-2UNIX\s0 User Reference Manual.
+The
+.I csh
+documentation in section 1 of the manual provides a full description of all
+features of the shell and is the definitive reference for questions
+about the shell.
+.PP
+Many words in this document are shown in
+.I italics.
+These are important words;
+names of commands, and words which have special meaning in discussing
+the shell and \s-2UNIX\s0.
+Many of the words are defined in a glossary at the end of this document.
+If you don't know what is meant by a word, you should look
+for it in the glossary.
+.SH
+Acknowledgements
+.PP
+Numerous people have provided good input about previous versions
+of
+.I csh
+and aided in its debugging and in the debugging of its documentation.
+I would especially like to thank Michael Ubell
+who made the crucial observation that history commands could be
+done well over the word structure of input text, and implemented
+a prototype history mechanism in an older version of the shell.
+Eric Allman has also provided a large number of useful comments on the
+shell, helping to unify those concepts which are present and to identify
+and eliminate useless and marginally useful features.
+Mike O'Brien suggested the pathname hashing
+mechanism which speeds command execution.
+Jim Kulp added the job control and directory stack primitives and
+added their documentation to this introduction.
+.br
+.bp
+.NH
+Terminal usage of the shell
+.NH 2
+The basic notion of commands
+.PP
+A
+.I shell
+in
+\s-2UNIX\s0
+acts mostly as a medium through which other
+.I programs
+are invoked.
+While it has a set of
+.I builtin
+functions which it performs directly,
+most commands cause execution of programs that are, in fact,
+external to the shell.
+The shell is thus distinguished from the command interpreters of other
+systems both by the fact that it is just a user program, and by the fact
+that it is used almost exclusively as a mechanism for invoking other programs.
+.PP
+.I Commands
+in the \s-2UNIX\s0 system consist of a list of strings or
+.I words
+interpreted as a
+.I "command name"
+followed by
+.I arguments.
+Thus the command
+.DS
+mail bill
+.DE
+consists of two words.
+The first word
+.I mail
+names the command to be executed, in this case the
+mail program which sends messages to other users.
+The shell uses the name of the command in attempting to execute it for you.
+It will look in a number of
+.I directories
+for a file with the name
+.I mail
+which is expected to contain the mail program.
+.PP
+The rest of the words of the command are given as
+.I arguments
+to the command itself when it is executed.
+In this case we specified also the argument
+.I bill
+which is interpreted by the
+.I mail
+program to be the name of a user to whom mail is to be sent.
+In normal terminal usage we might use the
+.I mail
+command as follows.
+.DS
+% mail bill
+I have a question about the csh documentation.
+My document seems to be missing page 5.
+Does a page five exist?
+ Bill
+EOT
+%
+.DE
+.PP
+Here we typed a message to send to
+.I bill
+and ended this message with a ^D which sent an end-of-file to
+the mail program.
+(Here and throughout this document, the notation ``^\fIx\fR''
+is to be read ``control-\fIx\fR'' and represents the striking of the \fIx\fR
+key while the control key is held down.)
+The mail program
+then echoed the characters `EOT' and transmitted our message.
+The characters `% ' were printed before and after the mail command
+by the shell to indicate that input was needed.
+.PP
+After typing the `% ' prompt the shell was reading command input from
+our terminal.
+We typed a complete command `mail bill'.
+The shell then executed the
+.I mail
+program with argument
+.I bill
+and went dormant waiting for it to complete.
+The mail program then read input from our terminal until we signalled
+an end-of-file via typing a ^D after which the shell noticed
+that mail had completed
+and signaled us that it was ready to read from the terminal again by
+printing another `% ' prompt.
+.PP
+This is the essential pattern of all interaction with \s-2UNIX\s0
+through the shell.
+A complete command is typed at the terminal, the shell executes
+the command and when this execution completes, it prompts for a new command.
+If you run the editor for an hour, the shell will patiently wait for
+you to finish editing and obediently prompt you again whenever you finish
+editing.
+.PP
+An example of a useful command you can execute now is the
+.I tset
+command, which sets the default
+.I erase
+and
+.I kill
+characters on your terminal \- the erase character erases the last
+character you typed and the kill character erases the entire line you
+have entered so far.
+By default, the erase character is the delete key (equivalent to `^?')
+and the kill character is `^U'. Some people prefer to make the erase character
+the backspace key (equivalent to `^H').
+You can make this be true by typing
+.DS
+tset \-e
+.DE
+which tells the program
+.I tset
+to set the erase character to tset's default setting for this character
+(a backspace).
+.NH 2
+Flag arguments
+.PP
+A useful notion in \s-2UNIX\s0 is that of a
+.I flag
+argument.
+While many arguments to commands specify file names or user names,
+some arguments rather specify an optional capability of the command
+which you wish to invoke.
+By convention, such arguments begin with the character `\-' (hyphen).
+Thus the command
+.DS
+ls
+.DE
+will produce a list of the files in the current
+.I "working directory" .
+The option
+.I \-s
+is the size option, and
+.DS
+ls \-s
+.DE
+causes
+.I ls
+to also give, for each file the size of the file in blocks of 512
+characters.
+The manual section for each command in the \s-2UNIX\s0 reference manual
+gives the available options for each command.
+The
+.I ls
+command has a large number of useful and interesting options.
+Most other commands have either no options or only one or two options.
+It is hard to remember options of commands which are not used very
+frequently, so most \s-2UNIX\s0 utilities perform only one or two functions
+rather than having a large number of hard to remember options.
+.NH 2
+Output to files
+.PP
+Commands that normally read input or write output on the terminal
+can also be executed with this input and/or output done to
+a file.
+.PP
+Thus suppose we wish to save the current date in a file called `now'.
+The command
+.DS
+date
+.DE
+will print the current date on our terminal.
+This is because our terminal is the default
+.I "standard output"
+for the date command and the date command prints the date on its
+standard output.
+The shell lets us
+.I redirect
+the
+.I "standard output"
+of a command through a
+notation using the
+.I metacharacter
+`>' and the name of the file where output is to be placed.
+Thus the command
+.DS
+date > now
+.DE
+runs the
+.I date
+command such that its standard output is
+the file `now' rather than the terminal.
+Thus this command places the current date and time into the file `now'.
+It is important to know that the
+.I date
+command was unaware that its output was going to a file rather than
+to the terminal.
+The shell performed this
+.I redirection
+before the command began executing.
+.PP
+One other thing to note here is that the file `now'
+need not have existed before the
+.I date
+command was executed; the shell would have created the file if it did
+not exist.
+And if the file did exist?
+If it had existed previously these previous contents would have been discarded!
+A shell option
+.I noclobber
+exists to prevent this from happening accidentally;
+it is discussed in section 2.2.
+.PP
+The system normally keeps files which you create with `>' and all other files.
+Thus the default is for files to be permanent. If you wish to create a file
+which will be removed automatically, you can begin its name with a `#'
+character, this `scratch' character denotes the fact that the file will
+be a scratch file.*
+.FS
+*Note that if your erase character is a `#', you will have to precede the
+`#' with a `\e'. The fact that the `#' character is the old (pre-\s-2CRT\s0)
+standard erase character means that it seldom appears in a file name, and
+allows this convention to be used for scratch files. If you are using a
+\s-2CRT\s0, your erase character should be a ^H, as we demonstrated
+in section 1.1 how this could be set up.
+.FE
+The system will remove such files after a couple of days,
+or sooner if file space becomes very tight.
+Thus, in running the
+.I date
+command above, we don't really want to save the output forever, so we
+would more likely do
+.DS
+date > #now
+.DE
+.NH 2
+Metacharacters in the shell
+.PP
+The shell has a large number of
+special characters (like `>')
+which indicate special functions.
+We say that these notations have
+.I syntactic
+and
+.I semantic
+meaning to the shell.
+In general, most characters which are neither letters nor digits
+have special meaning to the shell.
+We shall shortly learn a means of
+.I quotation
+which allows us to use
+.I metacharacters
+without the shell treating them in any special way.
+.PP
+Metacharacters normally have effect only when the shell is reading
+our input.
+We need not worry about placing shell metacharacters in a letter
+we are sending via
+.I mail,
+or when we are typing in text or data to some other program.
+Note that the shell is only reading input when it has prompted with
+`% ' (although we can type our input even before it prompts).
+.NH 2
+Input from files; pipelines
+.PP
+We learned above how to
+.I redirect
+the
+.I "standard output"
+of a command
+to a file.
+It is also possible to redirect the
+.I "standard input"
+of a command from a file.
+This is not often necessary since most commands will read from
+a file whose name is given as an argument.
+We can give the command
+.DS
+sort < data
+.DE
+to run the
+.I sort
+command with standard input, where the command normally
+reads its input, from the file
+`data'.
+We would more likely say
+.DS
+sort data
+.DE
+letting the
+.I sort
+command open the file
+`data'
+for input itself since this is less to type.
+.PP
+We should note that if we just typed
+.DS
+sort
+.DE
+then the sort program would sort lines from its
+.I "standard input."
+Since we did not
+.I redirect
+the standard input, it would sort lines as we typed them on the terminal
+until we typed a ^D to indicate an end-of-file.
+.PP
+A most useful capability is the ability to combine the standard output
+of one command with the standard input of another, i.e. to run the
+commands in a sequence known as a
+.I pipeline.
+For instance the command
+.DS
+ls \-s
+.DE
+normally produces a list of the files in our directory with the size
+of each in blocks of 512 characters.
+If we are interested in learning which of our files is largest we
+may wish to have this sorted by size rather than by name, which is
+the default way in which
+.I ls
+sorts.
+We could look at the many options of
+.I ls
+to see if there was an option to do this but would eventually discover
+that there is not.
+Instead we can use a couple of simple options of the
+.I sort
+command, combining it with
+.I ls
+to get what we want.
+.PP
+The
+.I \-n
+option of sort specifies a numeric sort rather than an alphabetic sort.
+Thus
+.DS
+ls \-s | sort \-n
+.DE
+specifies that the output of the
+.I ls
+command run with the option
+.I \-s
+is to be
+.I piped
+to the command
+.I sort
+run with the numeric sort option.
+This would give us a sorted list of our files by size, but with the
+smallest first.
+We could then use the
+.I \-r
+reverse sort option and the
+.I head
+command in combination with the previous command doing
+.DS
+ls \-s | sort \-n \-r | head \-5
+.DE
+Here we have taken a list of our files sorted alphabetically,
+each with the size in blocks.
+We have run this to the standard input of the
+.I sort
+command asking it to sort numerically in reverse order (largest first).
+This output has then been run into the command
+.I head
+which gives us the first few lines.
+In this case we have asked
+.I head
+for the first 5 lines.
+Thus this command gives us the names and sizes of our 5 largest files.
+.PP
+The notation introduced above is called the
+.I pipe
+mechanism.
+Commands separated by `\||\|' characters are connected together by the
+shell and the standard output of each is run into the standard input of the
+next.
+The leftmost command in a pipeline will normally take its standard
+input from the terminal and the rightmost will place its standard
+output on the terminal.
+Other examples of pipelines will be given later when we discuss the
+history mechanism;
+one important use of pipes which is illustrated there is in the
+routing of information to the line printer.
+.NH 2
+Filenames
+.PP
+Many commands to be executed will need the names of files as arguments.
+\s-2UNIX\s0
+.I pathnames
+consist of a number of
+.I components
+separated by `/'.
+Each component except the last names a directory in which the next
+component resides, in effect specifying the
+.I path
+of directories to follow to reach the file.
+Thus the pathname
+.DS
+/etc/motd
+.DE
+specifies a file in the directory
+`etc'
+which is a subdirectory of the
+.I root
+directory `/'.
+Within this directory the file named is `motd' which stands
+for `message of the day'.
+A
+.I pathname
+that begins with a slash is said to be an
+.I absolute
+pathname since it is specified from the absolute top of the entire
+directory hierarchy of the system (the
+.I root ).
+.I Pathnames
+which do not begin with `/' are interpreted as starting in the current
+.I "working directory" ,
+which is, by default, your
+.I home
+directory and can be changed dynamically by the
+.I cd
+change directory command.
+Such pathnames are said to be
+.I relative
+to the working directory since they are found by starting
+in the working directory and descending to lower levels of directories
+for each
+.I component
+of the pathname. If the pathname contains no slashes at all then the
+file is contained in the working directory itself and the pathname is merely
+the name of the file in this directory.
+Absolute pathnames have no relation
+to the working directory.
+.PP
+Most filenames consist of a number of alphanumeric characters and
+`.'s (periods).
+In fact, all printing characters except `/' (slash) may appear in filenames.
+It is inconvenient to have most non-alphabetic characters in filenames
+because many of these have special meaning to the shell.
+The character `.' (period) is not a shell-metacharacter and is often used
+to separate the
+.I extension
+of a file name from the base of the name.
+Thus
+.DS
+prog.c prog.o prog.errs prog.output
+.DE
+are four related files.
+They share a
+.I base
+portion of a name
+(a base portion being that part of the name that is left when a trailing
+`.' and following characters which are not `.' are stripped off).
+The file
+`prog.c'
+might be the source for a C program,
+the file `prog.o' the corresponding object file,
+the file
+`prog.errs' the errors resulting from a compilation of the program
+and the file
+`prog.output' the output of a run of the program.
+.PP
+If we wished to refer to all four of these files in a command, we could
+use the notation
+.DS
+prog.*
+.DE
+This expression is expanded by the shell, before the command to which it is
+an argument is executed, into a list of names which begin with `prog.'.
+The character `*' here matches any sequence (including the empty sequence)
+of characters in a file name.
+The names which match are alphabetically sorted and placed in the
+.I "argument list"
+of the command.
+Thus the command
+.DS
+echo prog.*
+.DE
+will echo the names
+.DS
+prog.c prog.errs prog.o prog.output
+.DE
+Note that the names are in sorted order here, and a different
+order than we listed them above.
+The
+.I echo
+command receives four words as arguments, even though we only typed
+one word as an argument directly.
+The four words were generated by
+.I "filename expansion"
+of the one input word.
+.PP
+Other notations for
+.I "filename expansion"
+are also available.
+The character `?' matches any single character in a filename.
+Thus
+.DS
+echo ? \|?? \|???
+.DE
+will echo a line of filenames; first those with one character names,
+then those with two character names, and finally those with three
+character names.
+The names of each length will be independently sorted.
+.PP
+Another mechanism consists of a sequence of characters between `[' and `]'.
+This metasequence matches any single character from the enclosed set.
+Thus
+.DS
+prog.[co]
+.DE
+will match
+.DS
+prog.c prog.o
+.DE
+in the example above.
+We can also place two characters around a `\-' in this notation to denote
+a range.
+Thus
+.DS
+chap.[1\-5]
+.DE
+might match files
+.DS
+chap.1 chap.2 chap.3 chap.4 chap.5
+.DE
+if they existed.
+This is shorthand for
+.DS
+chap.[12345]
+.DE
+and otherwise equivalent.
+.PP
+An important point to note is that if a list of argument words to
+a command (an
+.I "argument list)"
+contains filename expansion syntax, and if this filename expansion syntax
+fails to match any existing file names, then the shell considers this
+to be an error and prints a diagnostic
+.DS
+No match.
+.DE
+and does not execute the command.
+.PP
+Another very important point is that files with the character `.' at the
+beginning are treated specially.
+Neither `*' or `?' or the `[' `]' mechanism will match it.
+This prevents accidental matching of the filenames `.' and `..'
+in the working directory which have special meaning to the system,
+as well as other files such as
+.I \&.cshrc
+which are not normally
+visible.
+We will discuss the special role of the file
+.I \&.cshrc
+later.
+.PP
+Another filename expansion mechanism gives access to the pathname of
+the
+.I home
+directory of other users.
+This notation consists of the character `~' (tilde) followed by another user's
+login name.
+For instance the word `~bill' would map to the pathname `/usr/bill'
+if the home directory for `bill' was `/usr/bill'.
+Since, on large systems, users may have login directories scattered over
+many different disk volumes with different prefix directory names,
+this notation provides a convenient way of accessing the files
+of other users.
+.PP
+A special case of this notation consists of a `~' alone, e.g. `~/mbox'.
+This notation is expanded by the shell into the file `mbox' in your
+.I home
+directory, i.e. into `/usr/bill/mbox' for me on Ernie Co-vax, the UCB
+Computer Science Department VAX machine, where this document was prepared.
+This can be very useful if you have used
+.I cd
+to change to another directory and have found a file you wish to
+copy using
+.I cp.
+If I give the command
+.DS
+cp thatfile ~
+.DE
+the shell will expand this command to
+.DS
+cp thatfile /usr/bill
+.DE
+since my home directory is /usr/bill.
+.PP
+There also exists a mechanism using the characters `{' and `}' for
+abbreviating a set of words which have common parts but cannot
+be abbreviated by the above mechanisms because they are not files,
+are the names of files which do not yet exist,
+are not thus conveniently described.
+This mechanism will be described much later,
+in section 4.2,
+as it is used less frequently.
+.NH 2
+Quotation
+.PP
+We have already seen a number of metacharacters used by the shell.
+These metacharacters pose a problem in that we cannot use them directly
+as parts of words.
+Thus the command
+.DS
+echo *
+.DE
+will not echo the character `*'.
+It will either echo a sorted list of filenames in the
+current
+.I "working directory,"
+or print the message `No match' if there are
+no files in the working directory.
+.PP
+The recommended mechanism for placing characters which are neither numbers,
+digits, `/', `.' or `\-' in an argument word to a command is to enclose
+it with single quotation characters `\'', i.e.
+.DS
+echo \'*\'
+.DE
+There is one special character `!' which is used by the
+.I history
+mechanism of the shell and which cannot be
+.I escaped
+by placing it within `\'' characters.
+It and the character `\'' itself can be preceded by a single `\e'
+to prevent their special meaning.
+Thus
+.DS
+echo \e\'\e!
+.DE
+prints
+.DS
+\'!
+.DE
+These two mechanisms suffice to place any printing character into a word
+which is an argument to a shell command. They can be combined, as in
+.DS
+echo \e\'\'*\'
+.DE
+which prints
+.DS
+\'*
+.DE
+since the first `\e' escaped the first `\'' and the `*' was enclosed
+between `\'' characters.
+.NH 2
+Terminating commands
+.PP
+When you are executing a command and the shell is
+waiting for it to complete there are several ways
+to force it to stop.
+For instance if you type the command
+.DS
+cat /etc/passwd
+.DE
+the system will print a copy of a list of all users of the system
+on your terminal.
+This is likely to continue for several minutes unless you stop it.
+You can send an
+\s-2INTERRUPT\s0
+.I signal
+to the
+.I cat
+command by typing ^C on your terminal.*
+.FS
+*On some older Unix systems the \s-2DEL\s0 or \s-2RUBOUT\s0 key
+has the same effect. "stty all" will tell you the INTR key value.
+.FE
+Since
+.I cat
+does not take any precautions to avoid or otherwise handle this signal
+the
+\s-2INTERRUPT\s0
+will cause it to terminate.
+The shell notices that
+.I cat
+has terminated and prompts you again with `% '.
+If you hit \s-2INTERRUPT\s0 again, the shell will just
+repeat its prompt since it handles \s-2INTERRUPT\s0 signals
+and chooses to continue to execute commands rather than terminating
+like
+.I cat
+did, which would have the effect of logging you out.
+.PP
+Another way in which many programs terminate is when they get an end-of-file
+from their standard input.
+Thus the
+.I mail
+program in the first example above was terminated when we typed a ^D
+which generates an end-of-file from the standard input.
+The shell also terminates when it gets an end-of-file printing `logout';
+\s-2UNIX\s0 then logs you off the system.
+Since this means that typing too many ^D's can accidentally log us off,
+the shell has a mechanism for preventing this.
+This
+.I ignoreeof
+option will be discussed in section 2.2.
+.PP
+If a command has its standard input redirected from a file, then it will
+normally terminate when it reaches the end of this file.
+Thus if we execute
+.DS
+mail bill < prepared.text
+.DE
+the mail command will terminate without our typing a ^D.
+This is because it read to the end-of-file of our file
+`prepared.text' in which we placed a message for `bill' with an editor program.
+We could also have done
+.DS
+cat prepared.text \||\| mail bill
+.DE
+since the
+.I cat
+command would then have written the text through the pipe to the
+standard input of the mail command.
+When the
+.I cat
+command completed it would have terminated,
+closing down the pipeline
+and the
+.I mail
+command would have received an end-of-file from it and terminated.
+Using a pipe here is more complicated than redirecting input
+so we would more likely use the first form.
+These commands could also have been stopped by sending an \s-2INTERRUPT\s0.
+.PP
+Another possibility for stopping a command is to suspend its execution
+temporarily, with the possibility of continuing execution later. This is
+done by sending a \s-2STOP\s0 signal via typing a ^Z.
+This signal causes all commands running on the terminal
+(usually one but more if a pipeline is executing) to become suspended.
+The shell notices that the command(s) have been suspended, types
+`Stopped' and then prompts for a new command.
+The previously executing command has been suspended, but otherwise
+unaffected by the \s-2STOP\s0 signal. Any other commands can be executed
+while the original command remains suspended. The suspended command can
+be continued using the
+.I fg
+command with no arguments. The shell will then retype the command
+to remind you which command is being continued, and cause the command
+to resume execution. Unless any input files in use by the suspended
+command have been changed in the meantime, the suspension has no effect
+whatsoever on the execution of the command. This feature can be very useful
+during editing, when you need to look at another file before continuing.
+An
+example of command suspension follows.
+.DS
+% mail harold
+Someone just copied a big file into my directory and its name is
+^Z
+Stopped
+% ls
+funnyfile
+prog.c
+prog.o
+% jobs
+.ta 1.75i
+[1] + Stopped mail harold
+% fg
+mail harold
+funnyfile. Do you know who did it?
+EOT
+%
+.so tabs
+.DE
+In this example someone was sending a message to Harold and forgot the
+name of the file he wanted to mention. The mail command was suspended
+by typing ^Z. When the shell noticed that the mail program was
+suspended, it typed `Stopped' and prompted for a new command. Then the
+.I ls
+command was typed to find out the name of the file. The
+.I jobs
+command was run to find out which command was suspended.
+At this time the
+.I fg
+command was typed to continue execution of the mail program. Input
+to the mail program was then continued and ended with a ^D
+which indicated the end of the message at which time the mail
+program typed EOT. The
+.I jobs
+command will show which commands are suspended.
+The ^Z should only be typed at the beginning of a line since
+everything typed on the current line is discarded when a signal is sent
+from the keyboard. This also happens on \s-2INTERRUPT\s0, and \s-2QUIT\s0
+signals. More information on
+suspending jobs and controlling them is given in
+section 2.6.
+.PP
+If you write or run programs which are not fully debugged then it may
+be necessary to stop them somewhat ungracefully.
+This can be done by sending them a \s-2QUIT\s0
+signal, sent by typing a ^\e.
+This will usually provoke the shell to produce a message like:
+.DS
+Quit (Core dumped)
+.DE
+indicating that a file
+`core' has been created containing information about the running program's
+state when it terminated due to the \s-2QUIT\s0 signal.
+You can examine this file yourself, or forward information to the
+maintainer of the program telling him/her where the
+.I "core file"
+is.
+.PP
+If you run background commands (as explained in section 2.6) then these
+commands will ignore \s-2INTERRUPT\s0 and \s-2QUIT\s0 signals at the
+terminal. To stop them you must use the
+.I kill
+command. See section 2.6 for an example.
+.PP
+If you want to examine the output of a command without having it move
+off the screen as the output of the
+.DS
+cat /etc/passwd
+.DE
+command will, you can use the command
+.DS
+more /etc/passwd
+.DE
+The
+.I more
+program pauses after each complete screenful and types `\-\-More\-\-'
+at which point you can hit a space to get another screenful, a return
+to get another line, a `?' to get some help on other commands, or a `q' to end the
+.I more
+program. You can also use more as a filter, i.e.
+.DS
+cat /etc/passwd | more
+.DE
+works just like the more simple more command above.
+.PP
+For stopping output of commands not involving
+.I more
+you can use the
+^S key to stop the typeout. The typeout will resume when you
+hit ^Q or any other key, but ^Q is normally used because
+it only restarts the output and does not become input to the program
+which is running. This works well on low-speed terminals, but at 9600
+baud it is hard to type ^S and ^Q fast enough to paginate
+the output nicely, and a program like
+.I more
+is usually used.
+.PP
+An additional possibility is to use the ^O flush output
+character; when this character is typed, all output from the current
+command is thrown away (quickly) until the next input read occurs
+or until the next shell prompt. This can be used to allow a command
+to complete without having to suffer through the output on a slow
+terminal; ^O is a toggle, so flushing can be turned off by
+typing ^O again while output is being flushed.
+.NH 2
+What now?
+.PP
+We have so far seen a number of mechanisms of the shell and learned a lot
+about the way in which it operates.
+The remaining sections will go yet further into the internals of the
+shell, but you will surely want to try using the
+shell before you go any further.
+To try it you can log in to \s-2UNIX\s0 and type the following
+command to the system:
+.DS
+chsh myname /bin/csh
+.DE
+Here `myname' should be replaced by the name you typed to
+the system prompt of `login:' to get onto the system.
+Thus I would use `chsh bill /bin/csh'.
+.B
+You only have to do this once; it takes effect at next login.
+.R
+You are now ready to try using
+.I csh.
+.PP
+Before you do the `chsh' command, the shell you are using when
+you log into the system is `/bin/sh'.
+In fact, much of the above discussion is applicable to `/bin/sh'.
+The next section will introduce many features particular to
+.I csh
+so you should change your shell to
+.I csh
+before you begin reading it.
+.bp
diff --git a/share/doc/usd/04.csh/csh.2 b/share/doc/usd/04.csh/csh.2
new file mode 100644
index 0000000..5fbf43c
--- /dev/null
+++ b/share/doc/usd/04.csh/csh.2
@@ -0,0 +1,1304 @@
+.\"-
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)csh.2 8.1 (Berkeley) 6/8/93
+.\" $FreeBSD$
+.\"
+.nr H1 1
+.NH
+Details on the shell for terminal users
+.NH 2
+Shell startup and termination
+.PP
+When you login, the shell is started by the system in your
+.I home
+directory and begins by reading commands from a file
+.I \&.cshrc
+in this directory.
+All shells which you may start during your terminal session will
+read from this file.
+We will later see what kinds of commands are usefully placed there.
+For now we need not have this file and the shell does not complain about
+its absence.
+.PP
+A
+.I "login shell" ,
+executed after you login to the system,
+will, after it reads commands from
+.I \&.cshrc,
+read commands from a file
+.I \&.login
+also in your home directory.
+This file contains commands which you wish to do each time you login
+to the \s-2UNIX\s0 system.
+My
+.I \&.login
+file looks something like:
+.DS
+set ignoreeof
+set mail=(/usr/spool/mail/bill)
+echo "${prompt}users" ; users
+alias ts \e
+ \'set noglob ; eval \`tset \-s \-m dialup:c100rv4pna \-m plugboard:?hp2621nl \!*\`\';
+ts; stty intr ^C kill ^U crt
+set time=15 history=10
+msgs \-f
+if (\-e $mail) then
+ echo "${prompt}mail"
+ mail
+endif
+.DE
+.PP
+This file contains several commands to be executed by \s-2UNIX\s0
+each time I login.
+The first is a
+.I set
+command which is interpreted directly by the shell. It sets the shell
+variable
+.I ignoreeof
+which causes the shell to not log me off if I hit ^D. Rather,
+I use the
+.I logout
+command to log off of the system.
+By setting the
+.I mail
+variable, I ask the shell to watch for incoming mail to me. Every 5 minutes
+the shell looks for this file and tells me if more mail has arrived there.
+An alternative to this is to put the command
+.DS
+biff y
+.DE
+in place of this
+.I set;
+this will cause me to be notified immediately when mail arrives, and to
+be shown the first few lines of the new message.
+.PP
+Next I set the shell variable `time' to `15' causing the shell to automatically
+print out statistics lines for commands which execute for at least 15 seconds
+of \s-2CPU\s+2 time. The variable `history' is set to 10 indicating that
+I want the shell to remember the last 10 commands I type in its
+.I "history list" ,
+(described later).
+.PP
+I create an
+.I alias
+``ts'' which executes a
+\fItset\fR\|(1) command setting up the modes of the terminal.
+The parameters to
+.I tset
+indicate the kinds of terminal which I usually use when not on a hardwired
+port. I then execute ``ts'' and also use the
+.I stty
+command to change the interrupt character to ^C and the line kill
+character to ^U.
+.PP
+I then run the `msgs' program, which provides me with any
+system messages which I have not seen before; the `\-f' option here prevents
+it from telling me anything if there are no new messages.
+Finally, if my mailbox file exists, then I run the `mail' program to
+process my mail.
+.PP
+When the `mail' and `msgs' programs finish, the shell will finish
+processing my
+.I \&.login
+file and begin reading commands from the terminal, prompting for each with
+`% '.
+When I log off (by giving the
+.I logout
+command) the shell
+will print `logout' and execute commands from the file `.logout'
+if it exists in my home directory.
+After that the shell will terminate and \s-2UNIX\s0 will log
+me off the system.
+If the system is not going down, I will receive a new login message.
+In any case, after the `logout' message the shell is committed to terminating
+and will take no further input from my terminal.
+.NH 2
+Shell variables
+.PP
+The shell maintains a set of
+.I variables.
+We saw above the variables
+.I history
+and
+.I time
+which had values `10' and `15'.
+In fact, each shell variable has as value an array of
+zero or more
+.I strings.
+Shell variables may be assigned values by the set command. It has
+several forms, the most useful of which was given above and is
+.DS
+set name=value
+.DE
+.PP
+Shell variables may be used to store values which are to
+be used in commands later through a substitution mechanism.
+The shell variables most commonly referenced are, however, those which the
+shell itself refers to.
+By changing the values of these variables one can directly affect the
+behavior of the shell.
+.PP
+One of the most important variables is the variable
+.I path.
+This variable contains a sequence of directory names where the shell
+searches for commands.
+The
+.I set
+command with no arguments
+shows the value of all variables currently defined (we usually say
+.I set)
+in the shell.
+The default value for path will be shown by
+.I set
+to be
+.DS
+% set
+.ta .75i
+argv ()
+cwd /usr/bill
+home /usr/bill
+path (. /usr/ucb /bin /usr/bin)
+prompt %
+shell /bin/csh
+status 0
+term c100rv4pna
+user bill
+%
+.so tabs
+.DE
+This output indicates that the variable path points to the current
+directory `.' and then `/usr/ucb', `/bin' and `/usr/bin'.
+Commands which you may write might be in `.' (usually one of
+your directories).
+Commands developed at Berkeley, live in `/usr/ucb'
+while commands developed at Bell Laboratories live in `/bin' and `/usr/bin'.
+.PP
+A number of locally developed programs on the system live in the directory
+`/usr/local'.
+If we wish that all shells which we invoke to have
+access to these new programs we can place the command
+.DS
+set path=(. /usr/ucb /bin /usr/bin /usr/local)
+.DE
+in our file
+.I \&.cshrc
+in our home directory.
+Try doing this and then logging out and back in and do
+.DS
+set
+.DE
+again to see that the value assigned to
+.I path
+has changed.
+.FS \(dg
+Another directory that might interest you is /usr/new, which contains
+many useful user-contributed programs provided with Berkeley Unix.
+.FE
+.PP
+One thing you should be aware of is that the shell examines each directory
+which you insert into your path and determines which commands are contained
+there. Except for the current directory `.', which the shell treats specially,
+this means that if commands are added to a directory in your search path after
+you have started the shell, they will not necessarily be found by the shell.
+If you wish to use a command which has been added in this way, you should
+give the command
+.DS
+rehash
+.DE
+to the shell, which will cause it to recompute its internal table of command
+locations, so that it will find the newly added command.
+Since the shell has to look in the current directory `.' on each command,
+placing it at the end of the path specification usually works equivalently
+and reduces overhead.
+.PP
+Other useful built in variables are the variable
+.I home
+which shows your home directory,
+.I cwd
+which contains your current working directory,
+the variable
+.I ignoreeof
+which can be set in your
+.I \&.login
+file to tell the shell not to exit when it receives an end-of-file from
+a terminal (as described above).
+The variable `ignoreeof'
+is one of several variables which the shell does not care about the
+value of, only whether they are
+.I set
+or
+.I unset.
+Thus to set this variable you simply do
+.DS
+set ignoreeof
+.DE
+and to unset it do
+.DS
+unset ignoreeof
+.DE
+These give the variable `ignoreeof' no value, but none is desired or required.
+.PP
+Finally, some other built-in shell variables of use are the
+variables
+.I noclobber
+and
+.I mail.
+The metasyntax
+.DS
+> filename
+.DE
+which redirects the standard output of a command
+will overwrite and destroy the previous contents of the named file.
+In this way you may accidentally overwrite a file which is valuable.
+If you would prefer that the shell not overwrite files in this
+way you can
+.DS
+set noclobber
+.DE
+in your
+.I \&.login
+file.
+Then trying to do
+.DS
+date > now
+.DE
+would cause a diagnostic if `now' existed already.
+You could type
+.DS
+date >! now
+.DE
+if you really wanted to overwrite the contents of `now'.
+The `>!' is a special metasyntax indicating that clobbering the
+file is ok.\(dg
+.FS
+\(dgThe space between the `!' and the word `now' is critical here, as `!now'
+would be an invocation of the
+.I history
+mechanism, and have a totally different effect.
+.FE
+.NH 2
+The shell's history list
+.PP
+The shell can maintain a
+.I "history list"
+into which it places the words
+of previous commands.
+It is possible to use a notation to reuse commands or words
+from commands in forming new commands.
+This mechanism can be used to repeat previous commands or to
+correct minor typing mistakes in commands.
+.PP
+The following figure gives a sample session involving typical usage of the
+history mechanism of the shell.
+.KF
+.DS
+% cat bug.c
+main()
+
+{
+ printf("hello);
+}
+% cc !$
+cc bug.c
+"bug.c", line 4: newline in string or char constant
+"bug.c", line 5: syntax error
+% ed !$
+ed bug.c
+29
+4s/);/"&/p
+ printf("hello");
+w
+30
+q
+% !c
+cc bug.c
+% a.out
+hello% !e
+ed bug.c
+30
+4s/lo/lo\e\en/p
+ printf("hello\en");
+w
+32
+q
+% !c \-o bug
+cc bug.c \-o bug
+% size a.out bug
+a.out: 2784+364+1028 = 4176b = 0x1050b
+bug: 2784+364+1028 = 4176b = 0x1050b
+% ls \-l !*
+ls \-l a.out bug
+\(mirwxr\(mixr\(mix 1 bill 3932 Dec 19 09:41 a.out
+\(mirwxr\(mixr\(mix 1 bill 3932 Dec 19 09:42 bug
+% bug
+hello
+% num bug.c | spp
+spp: Command not found.
+% ^spp^ssp
+num bug.c | ssp
+ 1 main()
+ 3 {
+ 4 printf("hello\en");
+ 5 }
+% !! | lpr
+num bug.c | ssp | lpr
+%
+.DE
+.KE
+In this example we have a very simple C program which has a bug (or two)
+in it in the file `bug.c', which we `cat' out on our terminal. We then
+try to run the C compiler on it, referring to the file again as `!$',
+meaning the last argument to the previous command. Here the `!' is the
+history mechanism invocation metacharacter, and the `$' stands for the last
+argument, by analogy to `$' in the editor which stands for the end of the line.
+The shell echoed the command, as it would have been typed without use of
+the history mechanism, and then executed it.
+The compilation yielded error diagnostics so we now run the editor on the
+file we were trying to compile, fix the bug, and run the C compiler again,
+this time referring to this command simply as `!c', which repeats the last
+command which started with the letter `c'. If there were other
+commands starting with `c' done recently we could have said `!cc' or even
+`!cc:p' which would have printed the last command starting with `cc'
+without executing it.
+.PP
+After this recompilation, we ran the resulting `a.out' file, and then
+noting that there still was a bug, ran the editor again. After fixing
+the program we ran the C compiler again, but tacked onto the command
+an extra `\-o bug' telling the compiler to place the resultant binary in
+the file `bug' rather than `a.out'. In general, the history mechanisms
+may be used anywhere in the formation of new commands and other characters
+may be placed before and after the substituted commands.
+.PP
+We then ran the `size' command to see how large the binary program images
+we have created were, and then an `ls \-l' command with the same argument
+list, denoting the argument list `\!*'.
+Finally we ran the program `bug' to see that its output is indeed correct.
+.PP
+To make a numbered listing of the program we ran the `num' command on the file `bug.c'.
+In order to compress out blank lines in the output of `num' we ran the
+output through the filter `ssp', but misspelled it as spp. To correct this
+we used a shell substitute, placing the old text and new text between `^'
+characters. This is similar to the substitute command in the editor.
+Finally, we repeated the same command with `!!', but sent its output to the
+line printer.
+.PP
+There are other mechanisms available for repeating commands. The
+.I history
+command prints out a number of previous commands with numbers by which
+they can be referenced. There is a way to refer to a previous command
+by searching for a string which appeared in it, and there are other,
+less useful, ways to select arguments to include in a new command.
+A complete description of all these mechanisms
+is given in the C shell manual pages in the \s-2UNIX\s0 Programmer's Manual.
+.NH 2
+Aliases
+.PP
+The shell has an
+.I alias
+mechanism which can be used to make transformations on input commands.
+This mechanism can be used to simplify the commands you type,
+to supply default arguments to commands,
+or to perform transformations on commands and their arguments.
+The alias facility is similar to a macro facility.
+Some of the features obtained by aliasing can be obtained also
+using shell command files, but these take place in another instance
+of the shell and cannot directly affect the current shells environment
+or involve commands such as
+.I cd
+which must be done in the current shell.
+.PP
+As an example, suppose that there is a new version of the mail program
+on the system called `newmail'
+you wish to use, rather than the standard mail program which is called
+`mail'.
+If you place the shell command
+.DS
+alias mail newmail
+.DE
+in your
+.I \&.cshrc
+file, the shell will transform an input line of the form
+.DS
+mail bill
+.DE
+into a call on `newmail'.
+More generally, suppose we wish the command `ls' to always show
+sizes of files, that is to always do `\-s'.
+We can do
+.DS
+alias ls ls \-s
+.DE
+or even
+.DS
+alias dir ls \-s
+.DE
+creating a new command syntax `dir'
+which does an `ls \-s'.
+If we say
+.DS
+dir ~bill
+.DE
+then the shell will translate this to
+.DS
+ls \-s /mnt/bill
+.DE
+.PP
+Thus the
+.I alias
+mechanism can be used to provide short names for commands,
+to provide default arguments,
+and to define new short commands in terms of other commands.
+It is also possible to define aliases which contain multiple
+commands or pipelines, showing where the arguments to the original
+command are to be substituted using the facilities of the
+history mechanism.
+Thus the definition
+.DS
+alias cd \'cd \e!* ; ls \'
+.DE
+would do an
+.I ls
+command after each change directory
+.I cd
+command.
+We enclosed the entire alias definition in `\'' characters to prevent
+most substitutions from occurring and the character `;' from being
+recognized as a metacharacter.
+The `!' here is escaped with a `\e' to prevent it from being interpreted
+when the alias command is typed in.
+The `\e!*' here substitutes the entire argument list to the pre-aliasing
+.I cd
+command, without giving an error if there were no arguments.
+The `;' separating commands is used here
+to indicate that one command is to be done and then the next.
+Similarly the definition
+.DS
+alias whois \'grep \e!^ /etc/passwd\'
+.DE
+defines a command which looks up its first argument in the password file.
+.PP
+.B Warning:
+The shell currently reads the
+.I \&.cshrc
+file each time it starts up. If you place a large number of commands
+there, shells will tend to start slowly. A mechanism for saving the shell
+environment after reading the \fI\&.cshrc\fR file and quickly restoring it is
+under development, but for now you should try to limit the number of
+aliases you have to a reasonable number... 10 or 15 is reasonable,
+50 or 60 will cause a noticeable delay in starting up shells, and make
+the system seem sluggish when you execute commands from within the editor
+and other programs.
+.NH 2
+More redirection; >> and >&
+.PP
+There are a few more notations useful to the terminal user
+which have not been introduced yet.
+.PP
+In addition to the standard output, commands also have a
+.I "diagnostic output"
+which is normally directed to the terminal even when the standard output
+is redirected to a file or a pipe.
+It is occasionally desirable to direct the diagnostic output along with
+the standard output.
+For instance if you want to redirect the output of a long running command
+into a file and wish to have a record of any error diagnostic it produces
+you can do
+.DS
+command >& file
+.DE
+The `>&' here tells the shell to route both the diagnostic output and the
+standard output into `file'.
+Similarly you can give the command
+.DS
+command |\|& lpr
+.DE
+to route both standard and diagnostic output through the pipe
+to the line printer daemon
+.I lpr.\(dd
+.FS
+\(dd A command of the form
+.br
+.ti +5
+command >&! file
+.br
+exists, and is used when
+.I noclobber
+is set and
+.I file
+already exists.
+.FE
+.PP
+Finally, it is possible to use the form
+.DS
+command >> file
+.DE
+to place output at the end of an existing file.\(dg
+.FS
+\(dg If
+.I noclobber
+is set, then an error will result if
+.I file
+does not exist, otherwise the shell will create
+.I file
+if it doesn't exist.
+A form
+.br
+.ti +5
+command >>! file
+.br
+makes it not be an error for file to not exist when
+.I noclobber
+is set.
+.FE
+.NH 2
+Jobs; Background, Foreground, or Suspended
+.PP
+When one or more commands
+are typed together as a pipeline or as a sequence of commands separated by
+semicolons, a single
+.I job
+is created by the shell consisting of these commands together as a unit.
+Single commands without pipes or semicolons create the simplest jobs.
+Usually, every line typed to the shell creates a job.
+Some lines that create jobs (one per line) are
+.DS
+sort < data
+ls \-s | sort \-n | head \-5
+mail harold
+.DE
+.PP
+If the metacharacter `&' is typed
+at the end of the commands, then the job is started as a
+.I background
+job. This means that the shell does not wait for it to complete but
+immediately prompts and is ready for another command. The job runs
+.I "in the background"
+at the same time that normal jobs, called
+.I foreground
+jobs, continue to be read and executed by the shell one at a time.
+Thus
+.DS
+du > usage &
+.DE
+would run the
+.I du
+program, which reports on the disk usage of your working directory (as well as
+any directories below it), put the output into the file `usage' and return
+immediately with a prompt for the next command without out waiting for
+.I du
+to finish. The
+.I du
+program would continue executing in the background
+until it finished, even though you can type and execute more commands in the
+mean time.
+When a background
+job terminates, a message is typed by the shell just before the next prompt
+telling you that the job has completed.
+In the following example the
+.I du
+job finishes sometime during the
+execution of the
+.I mail
+command and its completion is reported just before
+the prompt after the
+.I mail
+job is finished.
+.DS
+% du > usage &
+[1] 503
+% mail bill
+How do you know when a background job is finished?
+EOT
+.ta 1.75i
+[1] \- Done du > usage
+%
+.so tabs
+.DE
+If the job did not terminate normally the `Done' message might say
+something else like `Killed'.
+If you want the
+terminations of background jobs to be reported at the time they occur
+(possibly interrupting the output of other foreground jobs), you can set
+the
+.I notify
+variable. In the previous example this would mean that the
+`Done' message might have come right in the middle of the message to
+Bill.
+Background jobs are unaffected by any signals from the keyboard like
+the \s-2STOP\s0, \s-2INTERRUPT\s0, or \s-2QUIT\s0 signals mentioned earlier.
+.PP
+Jobs are recorded in a table inside the shell until they terminate.
+In this table, the shell remembers the command names, arguments and the
+.I "process numbers"
+of all commands in the job as well as the working directory where the job was
+started.
+Each job in the table is either running
+.I "in the foreground"
+with the shell waiting for it to terminate, running
+.I "in the background,"
+or
+.I suspended.
+Only one job can be running in the foreground at one time, but several
+jobs can be suspended or running in the background at once. As each job
+is started, it is assigned a small identifying
+number called the
+.I "job number"
+which can be used later to refer to the job in the commands described below.
+Job numbers remain
+the same until the job terminates and then are re-used.
+.PP
+When a job is started in the background using `&', its number, as well
+as the process numbers of all its (top level) commands, is typed by the shell
+before prompting you for another command.
+For example,
+.DS
+% ls \-s | sort \-n > usage &
+[2] 2034 2035
+%
+.DE
+runs the `ls' program with the `\-s' options, pipes this output into
+the `sort' program with the `\-n' option which puts its output into the
+file `usage'.
+Since the `&' was at the end of the line, these two programs were started
+together as a background job. After starting the job, the shell prints
+the job number in brackets (2 in this case) followed by the process number
+of each program started in the job. Then the shell immediates prompts for
+a new command, leaving the job running simultaneously.
+.PP
+As mentioned in section 1.8, foreground jobs become
+.I suspended
+by typing ^Z
+which sends a \s-2STOP\s0 signal to the currently running
+foreground job. A background job can become suspended by using the
+.I stop
+command described below. When jobs are suspended they merely stop
+any further progress until started again, either in the foreground
+or the background. The shell notices when a job becomes stopped and
+reports this fact, much like it reports the termination of background jobs.
+For foreground jobs this looks like
+.DS
+% du > usage
+^Z
+Stopped
+%
+.DE
+`Stopped' message is typed by the shell when it notices that the
+.I du
+program stopped.
+For background jobs, using the
+.I stop
+command, it is
+.DS
+% sort usage &
+[1] 2345
+% stop %1
+.ta 1.75i
+[1] + Stopped (signal) sort usage
+%
+.so tabs
+.DE
+Suspending foreground jobs can be very useful when you need to temporarily
+change what you are doing (execute other commands) and then return to
+the suspended job. Also, foreground jobs can be suspended and then
+continued as background jobs using the
+.I bg
+command, allowing you to continue other work and
+stop waiting for the foreground job to finish. Thus
+.DS
+% du > usage
+^Z
+Stopped
+% bg
+[1] du > usage &
+%
+.DE
+starts `du' in the foreground, stops it before it finishes, then continues
+it in the background allowing more foreground commands to be executed.
+This is especially helpful
+when a foreground job ends up taking longer than you expected and you
+wish you had started it in the background in the beginning.
+.PP
+All
+.I "job control"
+commands can take an argument that identifies a particular
+job.
+All job name arguments begin with the character `%', since some of the
+job control commands also accept process numbers (printed by the
+.I ps
+command.)
+The default job (when no argument is given) is called the
+.I current
+job and is identified by a `+' in the output of the
+.I jobs
+command, which shows you which jobs you have.
+When only one job is stopped or running in the background (the usual case)
+it is always the current job thus no argument is needed.
+If a job is stopped while running in the foreground it becomes the
+.I current
+job and the existing current job becomes the
+.I previous
+job \- identified by a `\-' in the output of
+.I jobs.
+When the current job terminates, the previous job becomes the current job.
+When given, the argument is either `%\-' (indicating
+the previous job); `%#', where # is the job number;
+`%pref' where pref is some unique prefix of the command name
+and arguments of one of the jobs; or `%?' followed by some string found
+in only one of the jobs.
+.PP
+The
+.I jobs
+command types the table of jobs, giving the job number,
+commands and status (`Stopped' or `Running') of each background or
+suspended job. With the `\-l' option the process numbers are also
+typed.
+.DS
+% du > usage &
+[1] 3398
+% ls \-s | sort \-n > myfile &
+[2] 3405
+% mail bill
+^Z
+Stopped
+% jobs
+.ta 1.75i
+[1] \(mi Running du > usage
+[2] Running ls \-s | sort \-n > myfile
+[3] \(pl Stopped mail bill
+% fg %ls
+ls \-s | sort \-n > myfile
+% more myfile
+.so tabs
+.DE
+.PP
+The
+.I fg
+command runs a suspended or background job in the foreground. It is
+used to restart a previously suspended job or change a background job
+to run in the foreground (allowing signals or input from the terminal).
+In the above example we used
+.I fg
+to change the `ls' job from the
+background to the foreground since we wanted to wait for it to
+finish before looking at its output file.
+The
+.I bg
+command runs a suspended job in the background. It is usually used
+after stopping the currently running foreground job with the
+\s-2STOP\s0 signal. The combination of the \s-2STOP\s0 signal and the
+.I bg
+command changes a foreground job into a background job.
+The
+.I stop
+command suspends a background job.
+.PP
+The
+.I kill
+command terminates a background or suspended job immediately.
+In addition to jobs, it may be given process numbers as arguments,
+as printed by
+.I ps.
+Thus, in the example above, the running
+.I du
+command could have been terminated by the command
+.DS
+% kill %1
+.ta 1.75i
+[1] Terminated du > usage
+%
+.so tabs
+.DE
+.PP
+The
+.I notify
+command (not the variable mentioned earlier) indicates that the termination
+of a specific job should be
+reported at the time it finishes instead of waiting for the next prompt.
+.PP
+If a job running in the background tries to read input from the terminal
+it is automatically stopped. When such a job is then run in the
+foreground, input can be given to the job. If desired, the job can
+be run in the background again until it requests input again.
+This is illustrated in the following sequence where the `s' command in the
+text editor might take a long time.
+.ID
+.nf
+% ed bigfile
+120000
+1,$s/thisword/thatword/
+^Z
+Stopped
+% bg
+[1] ed bigfile &
+%
+ . . . some foreground commands
+.ta 1.75i
+[1] Stopped (tty input) ed bigfile
+% fg
+ed bigfile
+w
+120000
+q
+%
+.so tabs
+.DE
+So after the `s' command was issued, the `ed' job was stopped with ^Z
+and then put in the background using
+.I bg.
+Some time later when the `s' command was finished,
+.I ed
+tried to read another command and was stopped because jobs
+in the background cannot read from the terminal. The
+.I fg
+command returned the `ed' job to the foreground where it could once again
+accept commands from the terminal.
+.PP
+The command
+.DS
+stty tostop
+.DE
+causes all background jobs run on your terminal to stop
+when they are about to
+write output to the terminal. This prevents messages from background
+jobs from interrupting foreground job output and allows you to run
+a job in the background without losing terminal output. It also
+can be used for interactive programs that sometimes have long
+periods without interaction. Thus each time it outputs a prompt for more
+input it will stop before the prompt. It can then be run in the
+foreground using
+.I fg,
+more input can be given and, if necessary stopped and returned to
+the background. This
+.I stty
+command might be a good thing to put in your
+.I \&.login
+file if you do not like output from background jobs interrupting
+your work. It also can reduce the need for redirecting the output
+of background jobs if the output is not very big:
+.DS
+% stty tostop
+% wc hugefile &
+[1] 10387
+% ed text
+\&. . . some time later
+q
+.ta 1.75i
+[1] Stopped (tty output) wc hugefile
+% fg wc
+wc hugefile
+ 13371 30123 302577
+% stty \-tostop
+.so tabs
+.DE
+Thus after some time the `wc' command, which counts the lines, words
+and characters in a file, had one line of output. When it tried to
+write this to the terminal it stopped. By restarting it in the
+foreground we allowed it to write on the terminal exactly when we were
+ready to look at its output.
+Programs which attempt to change the mode of the terminal will also
+block, whether or not
+.I tostop
+is set, when they are not in the foreground, as
+it would be very unpleasant to have a background job change the state
+of the terminal.
+.PP
+Since the
+.I jobs
+command only prints jobs started in the currently executing shell,
+it knows nothing about background jobs started in other login sessions
+or within shell files. The
+.I ps
+can be used in this case to find out about background jobs not started
+in the current shell.
+.NH 2
+Working Directories
+.PP
+As mentioned in section 1.6, the shell is always in a particular
+.I "working directory."
+The `change directory' command
+.I chdir
+(its
+short form
+.I cd
+may also be used)
+changes the working directory of the shell,
+that is, changes the directory you
+are located in.
+.PP
+It is useful to make a directory for each project you wish to work on
+and to place all files related to that project in that directory.
+The `make directory' command,
+.I mkdir,
+creates a new directory.
+The
+.I pwd
+(`print working directory') command
+reports the absolute pathname of the working directory of the shell,
+that is, the directory you are
+located in.
+Thus in the example below:
+.DS
+% pwd
+/usr/bill
+% mkdir newpaper
+% chdir newpaper
+% pwd
+/usr/bill/newpaper
+%
+.DE
+the user has created and moved to the
+directory
+.I newpaper.
+where, for example, he might
+place a group of related files.
+.PP
+No matter where you have moved to in a directory hierarchy,
+you can return to your `home' login directory by doing just
+.DS
+cd
+.DE
+with no arguments.
+The name `..' always means the directory above the current one in
+the hierarchy, thus
+.DS
+cd ..
+.DE
+changes the shell's working directory to the one directly above the
+current one.
+The name `..' can be used in any
+pathname, thus,
+.DS
+cd ../programs
+.DE
+means
+change to the directory `programs' contained in the directory
+above the current one.
+If you have several directories for different
+projects under, say, your home directory,
+this shorthand notation
+permits you to switch easily between them.
+.PP
+The shell always remembers the pathname of its current working directory in
+the variable
+.I cwd.
+The shell can also be requested to remember the previous directory when
+you change to a new working directory. If the `push directory' command
+.I pushd
+is used in place of the
+.I cd
+command, the shell saves the name of the current working directory
+on a
+.I "directory stack"
+before changing to the new one.
+You can see this list at any time by typing the `directories'
+command
+.I dirs.
+.ID
+.nf
+% pushd newpaper/references
+~/newpaper/references ~
+% pushd /usr/lib/tmac
+/usr/lib/tmac ~/newpaper/references ~
+% dirs
+/usr/lib/tmac ~/newpaper/references ~
+% popd
+~/newpaper/references ~
+% popd
+~
+%
+.DE
+The list is printed in a horizontal line, reading left to right,
+with a tilde (~) as
+shorthand for your home directory\(emin this case `/usr/bill'.
+The directory stack is printed whenever there is more than one
+entry on it and it changes.
+It is also printed by a
+.I dirs
+command.
+.I Dirs
+is usually faster and more informative than
+.I pwd
+since it shows the current working directory as well as any
+other directories remembered in the stack.
+.PP
+The
+.I pushd
+command with no argument
+alternates the current directory with the first directory in the
+list.
+The `pop directory'
+.I popd
+command without an argument returns you to the directory you were in prior to
+the current one, discarding the previous current directory from the
+stack (forgetting it).
+Typing
+.I popd
+several times in a series takes you backward through the directories
+you had been in (changed to) by
+.I pushd
+command.
+There are other options to
+.I pushd
+and
+.I popd
+to manipulate the contents of the directory stack and to change
+to directories not at the top of the stack; see the
+.I csh
+manual page for details.
+.PP
+Since the shell remembers the working directory in which each job
+was started, it warns you when you might be confused by restarting
+a job in the foreground which has a different working directory than the
+current working directory of the shell. Thus if you start a background
+job, then change the shell's working directory and then cause the
+background job to run in the foreground, the shell warns you that the
+working directory of the currently running foreground job is different
+from that of the shell.
+.DS
+% dirs \-l
+/mnt/bill
+% cd myproject
+% dirs
+~/myproject
+% ed prog.c
+1143
+^Z
+Stopped
+% cd ..
+% ls
+myproject
+textfile
+% fg
+ed prog.c (wd: ~/myproject)
+.DE
+This way the shell warns you when there
+is an implied change of working directory, even though no cd command was
+issued. In the above example the `ed' job was still in `/mnt/bill/project'
+even though the shell had changed to `/mnt/bill'.
+A similar warning is given when such a foreground job
+terminates or is suspended (using the \s-2STOP\s0 signal) since
+the return to the shell again implies a change of working directory.
+.DS
+% fg
+ed prog.c (wd: ~/myproject)
+ . . . after some editing
+q
+(wd now: ~)
+%
+.DE
+These messages are sometimes confusing if you use programs that change
+their own working directories, since the shell only remembers which
+directory a job is started in, and assumes it stays there.
+The `\-l' option of
+.I jobs
+will type the working directory
+of suspended or background jobs when it is different
+from the current working directory of the shell.
+.NH 2
+Useful built-in commands
+.PP
+We now give a few of the useful built-in commands of the shell describing
+how they are used.
+.PP
+The
+.I alias
+command described above is used to assign new aliases and to show the
+existing aliases.
+With no arguments it prints the current aliases.
+It may also be given only one argument such as
+.DS
+alias ls
+.DE
+to show the current alias for, e.g., `ls'.
+.PP
+The
+.I echo
+command prints its arguments.
+It is often used in
+.I "shell scripts"
+or as an interactive command
+to see what filename expansions will produce.
+.PP
+The
+.I history
+command will show the contents of the history list.
+The numbers given with the history events can be used to reference
+previous events which are difficult to reference using the
+contextual mechanisms introduced above.
+There is also a shell variable called
+.I prompt.
+By placing a `!' character in its value the shell will there substitute
+the number of the current command in the history list.
+You can use this number to refer to this command in a history substitution.
+Thus you could
+.DS
+set prompt=\'\e! % \'
+.DE
+Note that the `!' character had to be
+.I escaped
+here even within `\'' characters.
+.PP
+The
+.I limit
+command is used to restrict use of resources.
+With no arguments it prints the current limitations:
+.DS
+.ta 1i
+cputime unlimited
+filesize unlimited
+datasize 5616 kbytes
+stacksize 512 kbytes
+coredumpsize unlimited
+.so tabs
+.DE
+Limits can be set, e.g.:
+.DS
+limit coredumpsize 128k
+.DE
+Most reasonable units abbreviations will work; see the
+.I csh
+manual page for more details.
+.PP
+The
+.I logout
+command can be used to terminate a login shell which has
+.I ignoreeof
+set.
+.PP
+The
+.I rehash
+command causes the shell to recompute a table of where commands are
+located. This is necessary if you add a command to a directory
+in the current shell's search path and wish the shell to find it,
+since otherwise the hashing algorithm may tell the shell that the
+command wasn't in that directory when the hash table was computed.
+.PP
+The
+.I repeat
+command can be used to repeat a command several times.
+Thus to make 5 copies of the file
+.I one
+in the file
+.I five
+you could do
+.DS
+repeat 5 cat one >> five
+.DE
+.PP
+The
+.I setenv
+command can be used
+to set variables in the environment.
+Thus
+.DS
+setenv TERM adm3a
+.DE
+will set the value of the environment variable \s-2TERM\s0
+to
+`adm3a'.
+A user program
+.I printenv
+exists which will print out the environment.
+It might then show:
+.DS
+% printenv
+HOME=/usr/bill
+SHELL=/bin/csh
+PATH=:/usr/ucb:/bin:/usr/bin:/usr/local
+TERM=adm3a
+USER=bill
+%
+.DE
+.PP
+The
+.I source
+command can be used to force the current shell to read commands from
+a file.
+Thus
+.DS
+source .cshrc
+.DE
+can be used after editing in a change to the
+.I \&.cshrc
+file which you wish to take effect right away.
+.PP
+The
+.I time
+command can be used to cause a command to be timed no matter how much
+\s-2CPU\s0 time it takes.
+Thus
+.DS
+% time cp /etc/rc /usr/bill/rc
+0.0u 0.1s 0:01 8% 2+1k 3+2io 1pf+0w
+% time wc /etc/rc /usr/bill/rc
+ 52 178 1347 /etc/rc
+ 52 178 1347 /usr/bill/rc
+ 104 356 2694 total
+0.1u 0.1s 0:00 13% 3+3k 5+3io 7pf+0w
+%
+.DE
+indicates that the
+.I cp
+command used a negligible amount of user time (u)
+and about 1/10th of a system time (s); the elapsed time was 1 second (0:01),
+there was an average memory usage of 2k bytes of program space and 1k
+bytes of data space over the cpu time involved (2+1k); the program
+did three disk reads and two disk writes (3+2io), and took one page fault
+and was not swapped (1pf+0w).
+The word count command
+.I wc
+on the other hand used 0.1 seconds of user time and 0.1 seconds of system
+time in less than a second of elapsed time.
+The percentage `13%' indicates that over the period when it was active
+the command `wc' used an average of 13 percent of the available \s-2CPU\s0
+cycles of the machine.
+.PP
+The
+.I unalias
+and
+.I unset
+commands can be used
+to remove aliases and variable definitions from the shell, and
+.I unsetenv
+removes variables from the environment.
+.NH 2
+What else?
+.PP
+This concludes the basic discussion of the shell for terminal users.
+There are more features of the shell to be discussed here, and all
+features of the shell are discussed in its manual pages.
+One useful feature which is discussed later is the
+.I foreach
+built-in command which can be used to run the same command
+sequence with a number of different arguments.
+.PP
+If you intend to use \s-2UNIX\s0 a lot you should look through
+the rest of this document and the csh manual pages (section1) to become familiar
+with the other facilities which are available to you.
+.bp
diff --git a/share/doc/usd/04.csh/csh.3 b/share/doc/usd/04.csh/csh.3
new file mode 100644
index 0000000..76ee1eb
--- /dev/null
+++ b/share/doc/usd/04.csh/csh.3
@@ -0,0 +1,649 @@
+.\"-
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)csh.3 8.1 (Berkeley) 6/8/93
+.\" $FreeBSD$
+.\"
+.nr H1 2
+.NH
+Shell control structures and command scripts
+.NH 2
+Introduction
+.PP
+It is possible to place commands in files and to cause shells to be
+invoked to read and execute commands from these files,
+which are called
+.I "shell scripts."
+We here detail those features of the shell useful to the writers of such
+scripts.
+.NH 2
+Make
+.PP
+It is important to first note what shell scripts are
+.I not
+useful for.
+There is a program called
+.I make
+which is very useful for maintaining a group of related files
+or performing sets of operations on related files.
+For instance a large program consisting of one or more files
+can have its dependencies described in a
+.I makefile
+which contains definitions of the commands used to create these
+different files when changes occur.
+Definitions of the means for printing listings, cleaning up the directory
+in which the files reside, and installing the resultant programs
+are easily, and most appropriately placed in this
+.I makefile.
+This format is superior and preferable to maintaining a group of shell
+procedures to maintain these files.
+.PP
+Similarly when working on a document a
+.I makefile
+may be created which defines how different versions of the document
+are to be created and which options of
+.I nroff
+or
+.I troff
+are appropriate.
+.NH 2
+Invocation and the argv variable
+.PP
+A
+.I csh
+command script may be interpreted by saying
+.DS
+% csh script ...
+.DE
+where
+.I script
+is the name of the file containing a group of
+.I csh
+commands and
+`\&...' is replaced by a sequence of arguments.
+The shell places these arguments in the variable
+.I argv
+and then begins to read commands from the script.
+These parameters are then available through the same mechanisms
+which are used to reference any other shell variables.
+.PP
+If you make the file
+`script'
+executable by doing
+.DS
+chmod 755 script
+.DE
+and place a shell comment at the beginning of the shell script
+(i.e. begin the file with a `#' character)
+then a `/bin/csh' will automatically be invoked to execute `script' when
+you type
+.DS
+script
+.DE
+If the file does not begin with a `#' then the standard shell
+`/bin/sh' will be used to execute it.
+This allows you to convert your older shell scripts to use
+.I csh
+at your convenience.
+.NH 2
+Variable substitution
+.PP
+After each input line is broken into words and history substitutions
+are done on it, the input line is parsed into distinct commands.
+Before each command is executed a mechanism know as
+.I "variable substitution"
+is done on these words.
+Keyed by the character `$' this substitution replaces the names
+of variables by their values.
+Thus
+.DS
+echo $argv
+.DE
+when placed in a command script would cause the current value of the
+variable
+.I argv
+to be echoed to the output of the shell script.
+It is an error for
+.I argv
+to be unset at this point.
+.PP
+A number of notations are provided for accessing components and attributes
+of variables.
+The notation
+.DS
+$?name
+.DE
+expands to `1' if name is
+.I set
+or to `0'
+if name is not
+.I set.
+It is the fundamental mechanism used for checking whether particular
+variables have been assigned values.
+All other forms of reference to undefined variables cause errors.
+.PP
+The notation
+.DS
+$#name
+.DE
+expands to the number of elements in the variable
+.I name.
+Thus
+.DS
+% set argv=(a b c)
+% echo $?argv
+1
+% echo $#argv
+3
+% unset argv
+% echo $?argv
+0
+% echo $argv
+Undefined variable: argv.
+%
+.DE
+.PP
+It is also possible to access the components of a variable
+which has several values.
+Thus
+.DS
+$argv[1]
+.DE
+gives the first component of
+.I argv
+or in the example above `a'.
+Similarly
+.DS
+$argv[$#argv]
+.DE
+would give `c',
+and
+.DS
+$argv[1\-2]
+.DE
+would give `a b'. Other notations useful in shell scripts are
+.DS
+$\fIn\fR
+.DE
+where
+.I n
+is an integer as a shorthand for
+.DS
+$argv[\fIn\fR\|]
+.DE
+the
+.I n\|th
+parameter and
+.DS
+$*
+.DE
+which is a shorthand for
+.DS
+$argv
+.DE
+The form
+.DS
+$$
+.DE
+expands to the process number of the current shell.
+Since this process number is unique in the system it can
+be used in generation of unique temporary file names.
+The form
+.DS
+$<
+.DE
+is quite special and is replaced by the next line of input read from
+the shell's standard input (not the script it is reading). This is
+useful for writing shell scripts that are interactive, reading
+commands from the terminal, or even writing a shell script that
+acts as a filter, reading lines from its input file.
+Thus the sequence
+.DS
+echo 'yes or no?\ec'
+set a=($<)
+.DE
+would write out the prompt `yes or no?' without a newline and then
+read the answer into the variable `a'. In this case `$#a' would be
+`0' if either a blank line or end-of-file (^D) was typed.
+.PP
+One minor difference between `$\fIn\fR\|' and `$argv[\fIn\fR\|]'
+should be noted here.
+The form
+`$argv[\fIn\fR\|]'
+will yield an error if
+.I n
+is not in the range
+`1\-$#argv'
+while `$n'
+will never yield an out of range subscript error.
+This is for compatibility with the way older shells handled parameters.
+.PP
+Another important point is that it is never an error to give a subrange
+of the form `n\-'; if there are less than
+.I n
+components of the given variable then no words are substituted.
+A range of the form `m\-n' likewise returns an empty vector without giving
+an error when \fIm\fR exceeds the number of elements of the given variable,
+provided the subscript \fIn\fR is in range.
+.NH 2
+Expressions
+.PP
+In order for interesting shell scripts to be constructed it
+must be possible to evaluate expressions in the shell based on the
+values of variables.
+In fact, all the arithmetic operations of the language C are available
+in the shell
+with the same precedence that they have in C.
+In particular, the operations `==' and `!=' compare strings
+and the operators `&&' and `|\|\||' implement the boolean and/or operations.
+The special operators `=~' and `!~' are similar to `==' and `!=' except
+that the string on the right side can have pattern matching characters
+(like *, ? or []) and the test is whether the string on the left matches
+the pattern on the right.
+.PP
+The shell also allows file enquiries of the form
+.DS
+\-? filename
+.DE
+where `?' is replace by a number of single characters.
+For instance the expression primitive
+.DS
+\-e filename
+.DE
+tell whether the file
+`filename'
+exists.
+Other primitives test for read, write and execute access to the file,
+whether it is a directory, or has non-zero length.
+.PP
+It is possible to test whether a command terminates normally,
+by a primitive of the
+form `{ command }' which returns true, i.e. `1' if the command
+succeeds exiting normally with exit status 0, or `0' if the command
+terminates abnormally or with exit status non-zero.
+If more detailed information about the execution status of a command
+is required, it can be executed and the variable `$status' examined
+in the next command.
+Since `$status' is set by every command, it is very transient.
+It can be saved if it is inconvenient to use it only in the single
+immediately following command.
+.PP
+For a full list of expression components available see the manual
+section for the shell.
+.NH 2
+Sample shell script
+.PP
+A sample shell script which makes use of the expression mechanism
+of the shell and some of its control structure follows:
+.DS
+% cat copyc
+#
+# Copyc copies those C programs in the specified list
+# to the directory ~/backup if they differ from the files
+# already in ~/backup
+#
+set noglob
+foreach i ($argv)
+
+ if ($i !~ *.c) continue # not a .c file so do nothing
+
+ if (! \-r ~/backup/$i:t) then
+ echo $i:t not in backup... not cp\e\'ed
+ continue
+ endif
+
+ cmp \-s $i ~/backup/$i:t # to set $status
+
+ if ($status != 0) then
+ echo new backup of $i
+ cp $i ~/backup/$i:t
+ endif
+end
+.DE
+.PP
+This script makes use of the
+.I foreach
+command, which causes the shell to execute the commands between the
+.I foreach
+and the matching
+.I end
+for each of the values given between `(' and `)' with the named
+variable, in this case `i' set to successive values in the list.
+Within this loop we may use the command
+.I break
+to stop executing the loop
+and
+.I continue
+to prematurely terminate one iteration
+and begin the next.
+After the
+.I foreach
+loop the iteration variable
+(\fIi\fR in this case)
+has the value at the last iteration.
+.PP
+We set the variable
+.I noglob
+here to prevent filename expansion of the members of
+.I argv.
+This is a good idea, in general, if the arguments to a shell script
+are filenames which have already been expanded or if the arguments
+may contain filename expansion metacharacters.
+It is also possible to quote each use of a `$' variable expansion,
+but this is harder and less reliable.
+.PP
+The other control construct used here is a statement of the form
+.DS
+\fBif\fR ( expression ) \fBthen\fR
+ command
+ ...
+\fBendif\fR
+.DE
+The placement of the keywords here is
+.B not
+flexible due to the current implementation of the shell.\(dg
+.FS
+\(dgThe following two formats are not currently acceptable to the shell:
+.sp
+.in +5
+.nf
+\fBif\fR ( expression ) # \fBWon't work!\fR
+\fBthen\fR
+ command
+ ...
+\fBendif\fR
+.fi
+.in -5
+.sp
+and
+.sp
+.in +5
+.nf
+\fBif\fR ( expression ) \fBthen\fR command \fBendif\fR # \fBWon't work\fR
+.in -5
+.fi
+.FE
+.PP
+The shell does have another form of the if statement of the form
+.DS
+\fBif\fR ( expression ) \fBcommand\fR
+.DE
+which can be written
+.DS
+\fBif\fR ( expression ) \e
+ command
+.DE
+Here we have escaped the newline for the sake of appearance.
+The command must not involve `\||\|', `&' or `;'
+and must not be another control command.
+The second form requires the final `\e' to
+.B immediately
+precede the end-of-line.
+.PP
+The more general
+.I if
+statements above also admit a sequence of
+.I else\-if
+pairs followed by a single
+.I else
+and an
+.I endif,
+e.g.:
+.DS
+\fBif\fR ( expression ) \fBthen\fR
+ commands
+\fBelse\fR \fBif\fR (expression ) \fBthen\fR
+ commands
+\&...
+
+\fBelse\fR
+ commands
+\fBendif\fR
+.DE
+.PP
+Another important mechanism used in shell scripts is the `:' modifier.
+We can use the modifier `:r' here to extract a root of a filename or
+`:e' to extract the
+.I extension.
+Thus if the variable
+.I i
+has the value
+`/mnt/foo.bar'
+then
+.sp
+.in +5
+.nf
+% echo $i $i:r $i:e
+/mnt/foo.bar /mnt/foo bar
+%
+.sp
+.in -5
+.fi
+shows how the `:r' modifier strips off the trailing `.bar' and the
+the `:e' modifier leaves only the `bar'.
+Other modifiers will take off the last component of a pathname leaving
+the head `:h' or all but the last component of a pathname leaving the
+tail `:t'.
+These modifiers are fully described in the
+.I csh
+manual pages in the User's Reference Manual.
+It is also possible to use the
+.I "command substitution"
+mechanism described in the next major section to perform modifications
+on strings to then reenter the shell's environment.
+Since each usage of this mechanism involves the creation of a new process,
+it is much more expensive to use than the `:' modification mechanism.\(dd
+.FS
+\(dd It is also important to note that
+the current implementation of the shell limits the number of `:' modifiers
+on a `$' substitution to 1.
+Thus
+.sp
+.nf
+.in +5
+% echo $i $i:h:t
+/a/b/c /a/b:t
+%
+.in -5
+.fi
+.sp
+does not do what one would expect.
+.FE
+Finally, we note that the character `#' lexically introduces a shell
+comment in shell scripts (but not from the terminal).
+All subsequent characters on the input line after a `#' are discarded
+by the shell.
+This character can be quoted using `\'' or `\e' to place it in
+an argument word.
+.NH 2
+Other control structures
+.PP
+The shell also has control structures
+.I while
+and
+.I switch
+similar to those of C.
+These take the forms
+.DS
+\fBwhile\fR ( expression )
+ commands
+\fBend\fR
+.DE
+and
+.DS
+\fBswitch\fR ( word )
+
+\fBcase\fR str1:
+ commands
+ \fBbreaksw\fR
+
+\& ...
+
+\fBcase\fR strn:
+ commands
+ \fBbreaksw\fR
+
+\fBdefault:\fR
+ commands
+ \fBbreaksw\fR
+
+\fBendsw\fR
+.DE
+For details see the manual section for
+.I csh.
+C programmers should note that we use
+.I breaksw
+to exit from a
+.I switch
+while
+.I break
+exits a
+.I while
+or
+.I foreach
+loop.
+A common mistake to make in
+.I csh
+scripts is to use
+.I break
+rather than
+.I breaksw
+in switches.
+.PP
+Finally,
+.I csh
+allows a
+.I goto
+statement, with labels looking like they do in C, i.e.:
+.DS
+loop:
+ commands
+ \fBgoto\fR loop
+.DE
+.NH 2
+Supplying input to commands
+.PP
+Commands run from shell scripts receive by default the standard
+input of the shell which is running the script.
+This is different from previous shells running
+under \s-2UNIX\s0. It allows shell scripts to fully participate
+in pipelines, but mandates extra notation for commands which are to take
+inline data.
+.PP
+Thus we need a metanotation for supplying inline data to commands in
+shell scripts.
+As an example, consider this script which runs the editor to
+delete leading blanks from the lines in each argument file:
+.DS
+% cat deblank
+# deblank \-\- remove leading blanks
+foreach i ($argv)
+ed \- $i << \'EOF\'
+1,$s/^[ ]*//
+w
+q
+\&\'EOF\'
+end
+%
+.DE
+The notation `<< \'EOF\''
+means that the standard input for the
+.I ed
+command is to come from the text in the shell script file
+up to the next line consisting of exactly `\'EOF\''.
+The fact that the `EOF' is enclosed in `\'' characters, i.e. quoted,
+causes the shell to not perform variable substitution on the
+intervening lines.
+In general, if any part of the word following the `<<' which the
+shell uses to terminate the text to be given to the command is quoted
+then these substitutions will not be performed.
+In this case since we used the form `1,$' in our editor script
+we needed to insure that this `$' was not variable substituted.
+We could also have insured this by preceding the `$' here with a `\e',
+i.e.:
+.DS
+1,\e$s/^[ ]*//
+.DE
+but quoting the `EOF' terminator is a more reliable way of achieving the
+same thing.
+.NH 2
+Catching interrupts
+.PP
+If our shell script creates temporary files, we may wish to catch
+interruptions of the shell script so that we can clean up
+these files.
+We can then do
+.DS
+onintr label
+.DE
+where
+.I label
+is a label in our program.
+If an interrupt is received the shell will do a
+`goto label'
+and we can remove the temporary files and then do an
+.I exit
+command (which is built in to the shell)
+to exit from the shell script.
+If we wish to exit with a non-zero status we can do
+.DS
+exit(1)
+.DE
+e.g. to exit with status `1'.
+.NH 2
+What else?
+.PP
+There are other features of the shell useful to writers of shell
+procedures.
+The
+.I verbose
+and
+.I echo
+options and the related
+.I \-v
+and
+.I \-x
+command line options can be used to help trace the actions of the shell.
+The
+.I \-n
+option causes the shell only to read commands and not to execute
+them and may sometimes be of use.
+.PP
+One other thing to note is that
+.I csh
+will not execute shell scripts which do not begin with the
+character `#', that is shell scripts that do not begin with a comment.
+Similarly, the `/bin/sh' on your system may well defer to `csh'
+to interpret shell scripts which begin with `#'.
+This allows shell scripts for both shells to live in harmony.
+.PP
+There is also another quotation mechanism using `"' which allows
+only some of the expansion mechanisms we have so far discussed to occur
+on the quoted string and serves to make this string into a single word
+as `\'' does.
+.bp
diff --git a/share/doc/usd/04.csh/csh.4 b/share/doc/usd/04.csh/csh.4
new file mode 100644
index 0000000..7ef24dc
--- /dev/null
+++ b/share/doc/usd/04.csh/csh.4
@@ -0,0 +1,176 @@
+.\"-
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)csh.4 8.1 (Berkeley) 6/8/93
+.\" $FreeBSD$
+.\"
+.nr H1 3
+.NH
+Other, less commonly used, shell features
+.NH 2
+Loops at the terminal; variables as vectors
+.PP
+It is occasionally useful to use the
+.I foreach
+control structure at the terminal to aid in performing a number
+of similar commands.
+For instance, there were at one point three shells in use on the Cory \s-2UNIX\s0
+system at Cory Hall,
+`/bin/sh',
+`/bin/nsh',
+and
+`/bin/csh'.
+To count the number of persons using each shell one could have issued
+the commands
+.DS
+% grep \-c csh$ /etc/passwd
+27
+% grep \-c nsh$ /etc/passwd
+128
+% grep \-c \-v sh$ /etc/passwd
+430
+%
+.DE
+Since these commands are very similar we can use
+.I foreach
+to do this more easily.
+.DS
+% foreach i (\'sh$\' \'csh$\' \'\-v sh$\')
+? grep \-c $i /etc/passwd
+? end
+27
+128
+430
+%
+.DE
+Note here that the shell prompts for
+input with `? ' when reading the body of the loop.
+.PP
+Very useful with loops are variables which contain lists of filenames
+or other words.
+You can, for example, do
+.DS
+% set a=(\`ls\`)
+% echo $a
+csh.n csh.rm
+% ls
+csh.n
+csh.rm
+% echo $#a
+2
+%
+.DE
+The
+.I set
+command here gave the variable
+.I a
+a list of all the filenames in the current directory as value.
+We can then iterate over these names to perform any chosen function.
+.PP
+The output of a command within `\`' characters is converted by
+the shell to a list of words.
+You can also place the `\`' quoted string within `"' characters
+to take each (non-empty) line as a component of the variable;
+preventing the lines from being split into words at blanks and tabs.
+A modifier `:x' exists which can be used later to expand each component
+of the variable into another variable splitting it into separate words
+at embedded blanks and tabs.
+.NH 2
+Braces { ... } in argument expansion
+.PP
+Another form of filename expansion, alluded
+to before involves the characters `{' and `}'.
+These characters specify that the contained strings, separated by `,'
+are to be consecutively substituted into the containing characters
+and the results expanded left to right.
+Thus
+.DS
+A{str1,str2,...strn}B
+.DE
+expands to
+.DS
+Astr1B Astr2B ... AstrnB
+.DE
+This expansion occurs before the other filename expansions, and may
+be applied recursively (i.e. nested).
+The results of each expanded string are sorted separately, left
+to right order being preserved.
+The resulting filenames are not required to exist if no other expansion
+mechanisms are used.
+This means that this mechanism can be used to generate arguments which are
+not filenames, but which have common parts.
+.PP
+A typical use of this would be
+.DS
+mkdir ~/{hdrs,retrofit,csh}
+.DE
+to make subdirectories `hdrs', `retrofit' and `csh'
+in your home directory.
+This mechanism is most useful when the common prefix is longer
+than in this example, i.e.
+.DS
+chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
+.DE
+.NH 2
+Command substitution
+.PP
+A command enclosed in `\`' characters is replaced, just before
+filenames are expanded, by the output from that command.
+Thus it is possible to do
+.DS
+set pwd=\`pwd\`
+.DE
+to save the current directory in the variable
+.I pwd
+or to do
+.DS
+ex \`grep \-l TRACE *.c\`
+.DE
+to run the editor
+.I ex
+supplying as arguments those files whose names end in `.c'
+which have the string `TRACE' in them.*
+.FS
+*Command expansion also occurs in input redirected with `<<'
+and within `"' quotations.
+Refer to the shell manual section for full details.
+.FE
+.NH 2
+Other details not covered here
+.PP
+In particular circumstances it may be necessary to know the exact
+nature and order of different substitutions performed by the shell.
+The exact meaning of certain combinations of quotations is also
+occasionally important.
+These are detailed fully in its manual section.
+.PP
+The shell has a number of command line option flags mostly of use
+in writing \s-2UNIX\s0 programs,
+and debugging shell scripts.
+See the csh(1) manual section for a list of these options.
+.bp
diff --git a/share/doc/usd/04.csh/csh.a b/share/doc/usd/04.csh/csh.a
new file mode 100644
index 0000000..22c8f76
--- /dev/null
+++ b/share/doc/usd/04.csh/csh.a
@@ -0,0 +1,93 @@
+.\"-
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)csh.a 8.1 (Berkeley) 6/8/93
+.\" $FreeBSD$
+.\"
+.SH
+Appendix \- Special characters
+.LP
+The following table lists the special characters of
+.I csh
+and the \s-2UNIX\s0 system, giving for each the section(s) in which it
+is discussed.
+A number of these characters also have special meaning in expressions.
+See the
+.I csh
+manual section
+for a complete list.
+.ta .75i 1.5i 2.25i
+.LP
+Syntactic metacharacters
+.DS
+; 2.4 separates commands to be executed sequentially
+| 1.5 separates commands in a pipeline
+( ) 2.2,3.6 brackets expressions and variable values
+& 2.5 follows commands to be executed without waiting for completion
+.DE
+.LP
+Filename metacharacters
+.DS
+/ 1.6 separates components of a file's pathname
+\&. 1.6 separates root parts of a file name from extensions
+? 1.6 expansion character matching any single character
+* 1.6 expansion character matching any sequence of characters
+[ ] 1.6 expansion sequence matching any single character from a set
+~ 1.6 used at the beginning of a filename to indicate home directories
+{ } 4.2 used to specify groups of arguments with common parts
+.DE
+.LP
+Quotation metacharacters
+.DS
+\e 1.7 prevents meta-meaning of following single character
+\' 1.7 prevents meta-meaning of a group of characters
+" 4.3 like \', but allows variable and command expansion
+.DE
+.LP
+Input/output metacharacters
+.DS
+< 1.5 indicates redirected input
+> 1.3 indicates redirected output
+.DE
+.LP
+Expansion/substitution metacharacters
+.DS
+$ 3.4 indicates variable substitution
+! 2.3 indicates history substitution
+: 3.6 precedes substitution modifiers
+^ 2.3 used in special forms of history substitution
+\` 4.3 indicates command substitution
+.DE
+.LP
+Other metacharacters
+.DS
+# 1.3,3.6 begins scratch file names; indicates shell comments
+\- 1.2 prefixes option (flag) arguments to commands
+% 2.6 prefixes job name specifications
+.DE
+.bp
diff --git a/share/doc/usd/04.csh/csh.g b/share/doc/usd/04.csh/csh.g
new file mode 100644
index 0000000..ba1b161
--- /dev/null
+++ b/share/doc/usd/04.csh/csh.g
@@ -0,0 +1,1719 @@
+.\"-
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)csh.g 8.1 (Berkeley) 6/8/93
+.\" $FreeBSD$
+.\"
+.SH
+Glossary
+.PP
+This glossary lists the most important terms introduced in the
+introduction to the
+shell and gives references to sections of the shell
+document for further information about them.
+References of the form
+`pr (1)'
+indicate that the command
+.I pr
+is in the \s-2UNIX\s0 User Reference manual in section 1.
+You can look at an online copy of its manual page by doing
+.DS
+man 1 pr
+.DE
+References of the form (2.5)
+indicate that more information can be found in section 2.5 of this
+manual.
+.IP \&\fB.\fR 15n
+Your current directory has the name `.' as well as the name printed
+by the command
+.I pwd;
+see also
+.I dirs.
+The current directory `.' is usually the first
+.I component
+of the search path contained in the variable
+.I path ,
+thus commands which are in `.' are found first (2.2).
+The character `.' is also used in separating
+.I components
+of filenames
+(1.6).
+The character `.' at the beginning of a
+.I component
+of a
+.I pathname
+is treated specially and not matched by the
+.I "filename expansion"
+metacharacters `?', `*', and `[' `]' pairs (1.6).
+.IP \&\fB..\fR
+Each directory has a file `..' in it which is a reference to its
+parent directory.
+After changing into the directory with
+.I chdir ,
+i.e.
+.DS
+chdir paper
+.DE
+you can return to the parent directory by doing
+.DS
+chdir ..
+.DE
+The current directory is printed by
+.I pwd
+(2.7).
+.IP a.out
+Compilers which create executable images create them, by default, in the
+file
+.I a.out.
+for historical reasons (2.3).
+.IP "absolute pathname"
+.br
+A
+.I pathname
+which begins with a `/' is
+.I absolute
+since it specifies the
+.I path
+of directories from the beginning
+of the entire directory system \- called the
+.I root
+directory.
+.I Pathname s
+which are not
+.I absolute
+are called
+.I relative
+(see definition of
+.I "relative pathname" )
+(1.6).
+.IP alias
+An
+.I alias
+specifies a shorter or different name for a \s-2UNIX\s0
+command, or a transformation on a command to be performed in
+the shell.
+The shell has a command
+.I alias
+which establishes
+.I aliases
+and can print their current values.
+The command
+.I unalias
+is used to remove
+.I aliases
+(2.4).
+.IP argument
+Commands in \s-2UNIX\s0 receive a list of
+.I argument
+words.
+Thus the command
+.DS
+echo a b c
+.DE
+consists of the
+.I "command name"
+`echo' and three
+.I argument
+words `a', `b' and `c'.
+The set of
+.I arguments
+after the
+.I "command name"
+is said to be the
+.I "argument list"
+of the command (1.1).
+.IP argv
+The list of arguments to a command written in the shell language
+(a shell script or shell procedure) is stored in a variable called
+.I argv
+within the shell.
+This name is taken from the conventional name in the
+C programming language (3.4).
+.IP background
+Commands started without waiting for them to complete are called
+.I background
+commands (2.6).
+.IP base
+A filename is sometimes thought of as consisting of a
+.I base
+part, before any `.' character, and an
+.I extension
+\- the part after
+the `.'. See
+.I filename
+and
+.I extension
+(1.6) and basename (1).
+.IP bg
+The
+.I bg
+command causes a
+.I suspended
+job to continue execution in the
+.I background
+(2.6).
+.IP bin
+A directory containing binaries of programs and shell scripts to be
+executed is typically called a
+.I bin
+directory.
+The standard system
+.I bin
+directories are `/bin' containing the most
+heavily used commands and `/usr/bin' which contains most other user
+programs.
+Programs developed at UC Berkeley live in `/usr/ucb', while locally
+written programs live in `/usr/local'. Games are kept in the directory
+`/usr/games'.
+You can place binaries in any directory.
+If you wish to execute them often, the name of the directories
+should be a
+.I component
+of the variable
+.I path .
+.IP break
+.I Break
+is a builtin command used to exit from loops within the control
+structure of the shell (3.7).
+.IP breaksw
+The
+.I breaksw
+builtin command is used to exit from a
+.I switch
+control structure, like a
+.I break
+exits from loops (3.7).
+.IP builtin
+A command executed directly by the shell is called a
+.I builtin
+command.
+Most commands in \s-2UNIX\s0 are not built into the shell,
+but rather exist as files in
+.I bin
+directories.
+These commands are accessible because the directories in which
+they reside are named in the
+.I path
+variable.
+.IP case
+A
+.I case
+command is used as a label in a
+.I switch
+statement in the shell's control structure, similar to that of the
+language C.
+Details are given in the shell documentation `csh (1)' (3.7).
+.IP cat
+The
+.I cat
+program catenates a list of specified files on the
+.I "standard output" .
+It is usually used to look at the contents of a single file on the terminal,
+to `cat a file' (1.8, 2.3).
+.IP cd
+The
+.I cd
+command is used to change the
+.I "working directory" .
+With no arguments,
+.I cd
+changes your
+.I "working directory"
+to be your
+.I home
+directory (2.4, 2.7).
+.IP chdir
+The
+.I chdir
+command is a synonym for
+.I cd .
+.I Cd
+is usually used because it is easier to type.
+.IP chsh
+The
+.I chsh
+command is used to change the shell which you use on \s-2UNIX\s0.
+By default, you use a different version of the shell
+which resides in `/bin/sh'.
+You can change your shell to `/bin/csh' by doing
+.DS
+chsh your-login-name /bin/csh
+.DE
+Thus I would do
+.DS
+chsh bill /bin/csh
+.DE
+It is only necessary to do this once.
+The next time you log in to \s-2UNIX\s0 after doing this command,
+you will be using
+.I csh
+rather than the shell in `/bin/sh' (1.9).
+.IP cmp
+.I Cmp
+is a program which compares files.
+It is usually used on binary files, or to see if two files are identical (3.6).
+For comparing text files the program
+.I diff ,
+described in `diff (1)' is used.
+.IP command
+A function performed by the system, either by the shell
+(a builtin
+.I command )
+or by a program residing in a file in
+a directory within the \s-2UNIX\s0 system, is called a
+.I command
+(1.1).
+.IP "command name"
+.br
+When a command is issued, it consists of a
+.I "command name" ,
+which is the first word of the command,
+followed by arguments.
+The convention on \s-2UNIX\s0 is that the first word of a
+command names the function to be performed (1.1).
+.IP "command substitution"
+.br
+The replacement of a command enclosed in `\`' characters
+by the text output by that command
+is called
+.I "command substitution"
+(4.3).
+.IP component
+A part of a
+.I pathname
+between `/' characters is called a
+.I component
+of that
+.I pathname .
+A variable
+which has multiple strings as value is said to have
+several
+.I component s;
+each string is a
+.I component
+of the variable.
+.IP continue
+A builtin command which causes execution of the enclosing
+.I foreach
+or
+.I while
+loop to cycle prematurely.
+Similar to the
+.I continue
+command in the programming language C (3.6).
+.IP control-
+Certain special characters, called
+.I control
+characters, are produced by holding down the \s-2CONTROL\s0 key
+on your terminal and simultaneously pressing another character, much like
+the \s-2SHIFT\s0 key is used to produce upper case characters. Thus
+.I control- c
+is produced by holding down the \s-2CONTROL\s0 key while pressing the
+`c' key. Usually \s-2UNIX\s0 prints a caret (^) followed by the
+corresponding letter when you type a
+.I control
+character (e.g. `^C' for
+.I control- c
+(1.8).
+.IP "core\ dump"
+When a program terminates abnormally, the system places an image
+of its current state in a file named `core'.
+This
+.I "core dump"
+can be examined with the system debugger `adb (1)'
+or `sdb (1)' in order to determine what went wrong with the program (1.8).
+If the shell produces a message of the form
+.DS
+Illegal instruction (core dumped)
+.DE
+(where `Illegal instruction' is only one of several possible
+messages), you should report this to the author of the program
+or a system administrator,
+saving the `core' file.
+.IP cp
+The
+.I cp
+(copy) program is used to copy the contents of one file into another
+file.
+It is one of the most commonly used \s-2UNIX\s0 commands (1.6).
+.IP csh
+The name of the shell
+program that this document describes.
+.IP \&.cshrc
+The file
+.I \&.cshrc
+in your
+.I home
+directory is read by each shell as it begins execution.
+It is usually used to change the setting of the variable
+.I path
+and to set
+.I alias
+parameters which are to take effect globally (2.1).
+.IP cwd
+The
+.I cwd
+variable in the shell holds the
+.I "absolute pathname"
+of the current
+.I "working directory" \&.
+It is changed by the shell whenever your current
+.I "working directory"
+changes and should not be changed otherwise (2.2).
+.IP date
+The
+.I date
+command prints the current date and time (1.3).
+.IP debugging
+.I Debugging
+is the process of correcting mistakes in programs and shell scripts.
+The shell has several options and variables which may be used
+to aid in shell
+.I debugging
+(4.4).
+.IP default:
+The label
+.I default:
+is used within shell
+.I switch
+statements, as it is in the C language
+to label the code to be executed if none of the
+.I case
+labels matches the value switched on (3.7).
+.IP \s-2DELETE\s0
+The
+\s-2DELETE\s0
+or
+\s-2RUBOUT\s0
+key on the terminal normally causes an interrupt to be sent to the current job.
+Many users change the interrupt character to be ^C.
+.IP detached
+A command that continues running in the
+.I background
+after you logout is said to be
+.I detached .
+.IP diagnostic
+An error message produced by a program is often referred to as a
+.I diagnostic .
+Most error messages are not written to the
+.I "standard output" ,
+since that is often directed away from the terminal (1.3, 1.5).
+Error messsages are instead written to the
+.I "diagnostic output"
+which may be directed away from the terminal, but usually is not.
+Thus
+.I diagnostics
+will usually appear on the terminal (2.5).
+.IP directory
+A structure which contains files.
+At any time you are in one particular
+.I directory
+whose names can be printed by the command
+.I pwd .
+The
+.I chdir
+command will change you to another
+.I directory ,
+and make the files
+in that
+.I directory
+visible. The
+.I directory
+in which you are when you first login is your
+.I home
+directory (1.1, 2.7).
+.IP "directory\ stack"
+The shell saves the names of previous
+.I "working directories"
+in the
+.I "directory stack"
+when you change your current
+.I "working directory"
+via the
+.I pushd
+command. The
+.I "directory stack"
+can be printed by using the
+.I dirs
+command, which includes your current
+.I "working directory"
+as the first directory name on the left (2.7).
+.IP dirs
+The
+.I dirs
+command prints the shell's
+.I "directory stack"
+(2.7).
+.IP du
+The
+.I du
+command is a program (described in `du (1)') which
+prints the number of disk blocks is all directories below
+and including your current
+.I "working directory"
+(2.6).
+.IP echo
+The
+.I echo
+command prints its arguments (1.6, 3.6).
+.IP else
+The
+.I else
+command is part of the `if-then-else-endif' control
+command construct (3.6).
+.IP endif
+If an
+.I if
+statement is ended with the word
+.I then ,
+all lines following the
+.I if
+up to a line starting with the word
+.I endif
+or
+.I else
+are executed if the condition between parentheses after the
+.I if
+is true (3.6).
+.IP \s-2EOF\s0
+An
+.I "end\f1-\fPof\f1-\fPfile"
+is generated by the terminal by a control-d,
+and whenever a command reads to the end of a file which
+it has been given as input.
+Commands receiving input from a
+.I pipe
+receive an
+.I "end\f1-\fPof\f1-\fPfile"
+when the command sending them input completes.
+Most commands terminate when they receive an
+.I "end\f1-\fPof\f1-\fPfile" .
+The shell has an option to ignore
+.I "end\f1-\fPof\f1-\fPfile"
+from a terminal
+input which may help you keep from logging out accidentally
+by typing too many control-d's (1.1, 1.8, 3.8).
+.IP escape
+A character `\e' used to prevent the special meaning of a metacharacter
+is said to
+.I escape
+the character from its special meaning.
+Thus
+.DS
+echo \e*
+.DE
+will echo the character `*' while just
+.DS
+echo *
+.DE
+will echo the names of the file in the current directory.
+In this example, \e
+.I escape s
+`*' (1.7).
+There is also a non-printing character called
+.I escape ,
+usually labelled
+\s-2ESC\s0
+or
+\s-2ALTMODE\s0
+on terminal keyboards.
+Some older \s-2UNIX\s0 systems use this character to indicate that
+output is to be
+.I suspended .
+Most systems use control-s to stop the output and control-q to start it.
+.IP /etc/passwd
+This file contains information about the accounts currently on the
+system.
+It consists of a line for each account with fields separated by
+`:' characters (1.8).
+You can look at this file by saying
+.DS
+cat /etc/passwd
+.DE
+The commands
+.I finger
+and
+.I grep
+are often used to search for information in this file.
+See `finger (1)', `passwd(5)', and `grep (1)' for more details.
+.IP exit
+The
+.I exit
+command is used to force termination of a shell script,
+and is built into the shell (3.9).
+.IP "exit\ status"
+A command which discovers a problem may reflect this back to the command
+(such as a shell) which invoked (executed) it.
+It does this by returning a non-zero number as its
+.I "exit status" ,
+a status of zero being considered
+`normal termination'.
+The
+.I exit
+command can be used to force a shell command script to give a non-zero
+.I "exit status"
+(3.6).
+.IP expansion
+The replacement of strings in the shell input which contain metacharacters
+by other strings is referred to as the process of
+.I expansion .
+Thus the replacement of the word `*' by a sorted list of files
+in the current directory is a `filename expansion'.
+Similarly the replacement of the characters `!!' by the text of
+the last command is a `history expansion'.
+.I Expansions
+are also referred to as
+.I substitutions
+(1.6, 3.4, 4.2).
+.IP expressions
+.I Expressions
+are used in the shell
+to control the conditional structures used in the writing of shell
+scripts and in calculating values for these scripts.
+The operators available in shell
+.I expressions
+are those of the language
+C (3.5).
+.IP extension
+Filenames often consist of a
+.I base
+name and an
+.I extension
+separated by the character `.'.
+By convention, groups of related files often share the same
+.I root
+name.
+Thus if `prog.c' were a C program, then the object file for this
+program would be stored in `prog.o'.
+Similarly a paper written with the
+`\-me'
+nroff macro package might be stored in
+`paper.me'
+while a formatted version of this paper might be kept in
+`paper.out' and a list of spelling errors in
+`paper.errs' (1.6).
+.IP fg
+The
+.I "job control"
+command
+.I fg
+is used to run a
+.I background
+or
+.I suspended
+job in the
+.I foreground
+(1.8, 2.6).
+.IP filename
+Each file in \s-2UNIX\s0 has a name consisting of up to 14 characters
+and not including the character `/' which is used in
+.I pathname
+building. Most
+.I filenames
+do not begin with the character `.', and contain
+only letters and digits with perhaps a `.' separating the
+.I base
+portion of the
+.I filename
+from an
+.I extension
+(1.6).
+.IP "filename expansion"
+.br
+.I "Filename expansion"
+uses the metacharacters `*', `?' and `[' and `]'
+to provide a convenient mechanism for naming files.
+Using
+.I "filename expansion"
+it is easy to name all the files in
+the current directory, or all files which have a common
+.I root
+name. Other
+.I "filename expansion"
+mechanisms use the metacharacter `~' and allow
+files in other users' directories to be named easily (1.6, 4.2).
+.IP flag
+Many \s-2UNIX\s0 commands accept arguments which are not the names
+of files or other users but are used to modify the action of the commands.
+These are referred to as
+.I flag
+options, and by convention consist of one or more letters preceded by
+the character `\-' (1.2).
+Thus the
+.I ls
+(list files) command has an option
+`\-s' to list the sizes of files.
+This is specified
+.DS
+ls \-s
+.DE
+.IP foreach
+The
+.I foreach
+command is used in shell scripts and at the terminal to specify
+repetition of a sequence of commands while the value of a certain
+shell variable ranges through a specified list (3.6, 4.1).
+.IP foreground
+When commands are executing in the normal way such that the
+shell is waiting for them to finish before prompting for another
+command they are said to be
+.I "foreground jobs"
+or
+.I "running in the foreground" \&.
+This is as opposed to
+.I background .
+.I Foreground
+jobs can be stopped by signals
+from the terminal caused by typing different
+control characters at the keyboard (1.8, 2.6).
+.IP goto
+The shell has a command
+.I goto
+used in shell scripts to transfer control to a given label (3.7).
+.IP grep
+The
+.I grep
+command searches through a list of argument files for a specified string.
+Thus
+.DS
+grep bill /etc/passwd
+.DE
+will print each line in the file
+.I "/etc/passwd"
+which contains the string `bill'.
+Actually,
+.I grep
+scans for
+.I "regular expressions"
+in the sense of the editors
+`ed (1)' and `ex (1)'.
+.I Grep
+stands for
+`globally find
+.I "regular expression"
+and print' (2.4).
+.IP head
+The
+.I head
+command prints the first few lines of one or more files.
+If you have a bunch of files containing text which you are wondering
+about it is sometimes useful to run
+.I head
+with these files as arguments.
+This will usually show enough of what is in these files to let you decide
+which you are interested in (1.5).
+.br
+.I Head
+is also used to describe the part of a
+.I pathname
+before and including the last `/' character. The
+.I tail
+of a
+.I pathname
+is the part after the last `/'. The `:h' and `:t' modifiers allow the
+.I head
+or
+.I tail
+of a
+.I pathname
+stored in a shell variable to be used (3.6).
+.IP history
+The
+.I history
+mechanism of the shell allows previous commands to be repeated,
+possibly after modification to correct typing mistakes or to change
+the meaning of the command.
+The shell has a
+.I "history list"
+where these commands are kept, and a
+.I history
+variable which controls how large this list is (2.3).
+.IP "home\ directory"
+.br
+Each user has a
+.I "home directory" ,
+which is given in your entry
+in the password file,
+.I /etc/passwd .
+This is the directory which you are placed in when you first login.
+The
+.I cd
+or
+.I chdir
+command with no arguments takes you back to this directory, whose
+name is recorded in the shell variable
+.I home .
+You can also access the
+.I "home directories"
+of other users in forming
+filenames using a
+.I "filename expansion"
+notation and the character `~' (1.6).
+.IP if
+A conditional command within the shell, the
+.I if
+command is used in shell command scripts to make decisions
+about what course of action to take next (3.6).
+.IP ignoreeof
+Normally, your shell will exit, printing
+`logout'
+if you type a control-d at a prompt of `% '.
+This is the way you usually log off the system.
+You can
+.I set
+the
+.I ignoreeof
+variable if you wish in your
+.I \&.login
+file and then use the command
+.I logout
+to logout.
+This is useful if you sometimes accidentally type too many control-d
+characters, logging yourself off
+(2.2).
+.IP input
+Many commands on \s-2UNIX\s0 take information from the terminal or from
+files which they then act on.
+This information is called
+.I input .
+Commands normally read for
+.I input
+from their
+.I "standard input"
+which is, by default, the terminal.
+This
+.I "standard input"
+can be redirected from a file using a shell metanotation
+with the character `<'.
+Many commands will also read from a file specified as argument.
+Commands placed in
+.I pipelines
+will read from the output of the previous
+command in the
+.I pipeline .
+The leftmost command in a
+.I pipeline
+reads from the terminal if
+you neither redirect its
+.I input
+nor give it a filename to use as
+.I "standard input" .
+Special mechanisms exist for supplying input to commands in shell
+scripts (1.5, 3.8).
+.IP interrupt
+An
+.I interrupt
+is a signal to a program that is generated by typing ^C. (On older versions
+of UNIX the \s-2RUBOUT\s0 or \s-2DELETE\s0 key were used for this purpose.)
+It causes most programs to stop execution.
+Certain programs, such as the shell and the editors,
+handle an
+.I interrupt
+in special ways, usually by stopping what they
+are doing and prompting for another command.
+While the shell is executing another command and waiting for it
+to finish, the shell does not listen to
+.I interrupts.
+The shell often wakes up when you hit
+.I interrupt
+because many commands
+die when they receive an
+.I interrupt
+(1.8, 3.9).
+.IP job
+One or more commands
+typed on the same input line separated by `|' or `;' characters
+are run together and are called a
+.I job \&.
+Simple commands run by themselves without any `|' or `;' characters
+are the simplest
+.I jobs.
+.I Jobs
+are classified as
+.I foreground ,
+.I background ,
+or
+.I suspended
+(2.6).
+.IP "job\ control"
+The builtin functions that control the execution of
+jobs are called
+.I "job control"
+commands. These are
+.I "bg, fg, stop, kill"
+(2.6).
+.IP "job\ number"
+When each job
+is started it is assigned a small number called a
+.I "job number"
+which is printed next to the job in the output of the
+.I jobs
+command. This number, preceded by a `%' character, can be used as an argument
+to
+.I "job control"
+commands to indicate
+a specific job (2.6).
+.IP jobs
+The
+.I jobs
+command prints a table showing
+jobs that are either running in the
+.I background
+or are
+.I suspended
+(2.6).
+.IP kill
+A command which sends a
+signal
+to a job causing it to terminate (2.6).
+.IP \&.login
+The file
+.I \&.login
+in your
+.I home
+directory is read by the shell each time you login to \s-2UNIX\s0
+and the commands there are executed.
+There are a number of commands which are usefully placed here,
+especially
+.I set
+commands to the shell itself (2.1).
+.IP "login\ shell"
+The shell that is started on your terminal when you login is called
+your
+.I "login shell" .
+It is different from other shells which you may run (e.g. on
+shell scripts)
+in that it reads the
+.I \&.login
+file before reading commands from the terminal and it reads the
+.I \&.logout
+file after you logout
+(2.1).
+.IP logout
+The
+.I logout
+command causes a login shell to exit.
+Normally, a login shell will exit when you hit control-d
+generating an
+.I end\f1-\fPof\f1-\fPfile,
+but if you have set
+.I ignoreeof
+in you
+.I \&.login
+file then this will not work and you must use
+.I logout
+to log off the \s-2UNIX\s0 system (2.8).
+.IP \&.logout
+When you log off of \s-2UNIX\s0 the shell will execute commands from
+the file
+.I \&.logout
+in your
+.I home
+directory after it prints `logout'.
+.IP lpr
+The command
+.I lpr
+is the line printer daemon.
+The standard input of
+.I lpr
+spooled and printed on the \s-2UNIX\s0 line printer.
+You can also give
+.I lpr
+a list of filenames as arguments to be printed.
+It is most common to use
+.I lpr
+as the last component of a
+.I pipeline
+(2.3).
+.IP ls
+The
+.I ls
+(list files) command is one of the most commonly used \s-2UNIX\s0
+commands.
+With no argument filenames it prints the names of the files in the
+current directory.
+It has a number of useful
+.I flag
+arguments, and can also be given the names of directories
+as arguments, in which case it lists the names of the files in these
+directories (1.2).
+.IP mail
+The
+.I mail
+program is used to send and receive messages from other \s-2UNIX\s0
+users (1.1, 2.1), whether they are logged on or not.
+.IP make
+The
+.I make
+command is used to maintain one or more related files and to
+organize functions to be performed on these files.
+In many ways
+.I make
+is easier to use, and more helpful than
+shell command scripts (3.2).
+.IP makefile
+The file containing commands for
+.I make
+is called
+.I makefile
+or
+.I Makefile
+(3.2).
+.IP manual
+The
+.I manual
+often referred to is the
+`\s-2UNIX\s0 manual'.
+It contains 8 numbered sections with a description of each \s-2UNIX\s0
+program (section 1), system call (section 2), subroutine (section 3),
+device (section 4), special data structure (section 5), game (section 6),
+miscellaneous item (section 7) and system administration program (section 8).
+There are also supplementary documents (tutorials and reference guides)
+for individual programs which require explanation in more detail.
+An online version of the
+.I manual
+is accessible through the
+.I man
+command.
+Its documentation can be obtained online via
+.DS
+man man
+.DE
+If you can't decide what manual page to look in, try the
+.I apropos (1)
+command.
+The supplementary documents are in subdirectories of /usr/doc.
+.IP metacharacter
+.br
+Many characters which are neither letters nor digits have special meaning
+either to the shell or to \s-2UNIX\s0.
+These characters are called
+.I metacharacters .
+If it is necessary to place these characters in arguments to commands
+without them having their special meaning then they must be
+.I quoted .
+An example of a
+.I metacharacter
+is the character `>' which is used
+to indicate placement of output into a file.
+For the purposes of the
+.I history
+mechanism,
+most unquoted
+.I metacharacters
+form separate words (1.4).
+The appendix to this user's manual lists the
+.I metacharacters
+in groups by their function.
+.IP mkdir
+The
+.I mkdir
+command is used to create a new directory.
+.IP modifier
+Substitutions with the
+.I history
+mechanism, keyed by the character `!'
+or of variables using the metacharacter `$', are often subjected
+to modifications, indicated by placing the character `:' after the
+substitution and following this with the
+.I modifier
+itself.
+The
+.I "command substitution"
+mechanism can also be used to perform modification in a similar way,
+but this notation is less clear (3.6).
+.IP more
+The program
+.I more
+writes a file on your terminal allowing you to control how much text
+is displayed at a time.
+.I More
+can move through the file screenful by screenful, line by line,
+search forward for a string, or start again at the beginning of the file.
+It is generally the easiest way of viewing a file (1.8).
+.IP noclobber
+The shell has a variable
+.I noclobber
+which may be set in the file
+.I \&.login
+to prevent accidental destruction of files by the `>' output redirection
+metasyntax of the shell (2.2, 2.5).
+.IP noglob
+The shell variable
+.I noglob
+is set to suppress the
+.I "filename expansion"
+of arguments containing the metacharacters `~', `*', `?', `[' and `]' (3.6).
+.IP notify
+The
+.I notify
+command tells the shell to report on the termination of a specific
+.I "background job"
+at the exact time it occurs as opposed to waiting
+until just before the next prompt to report the termination.
+The
+.I notify
+variable, if set, causes the shell to always report the termination
+of
+.I background
+jobs exactly when they occur (2.6).
+.IP onintr
+The
+.I onintr
+command is built into the shell and is used to control the action
+of a shell command script when an
+.I interrupt
+signal is received (3.9).
+.IP output
+Many commands in \s-2UNIX\s0 result in some lines of text which are
+called their
+.I output.
+This
+.I output
+is usually placed on what is known as the
+.I "standard output"
+which is normally connected to the user's terminal.
+The shell has a syntax using the metacharacter `>' for redirecting
+the
+.I "standard output"
+of a command to a file (1.3).
+Using the
+.I pipe
+mechanism and the metacharacter `|' it is also possible for
+the
+.I "standard output"
+of one command to become the
+.I "standard input"
+of another command (1.5).
+Certain commands such as the line printer daemon
+.I p
+do not place their results on the
+.I "standard output"
+but rather in more
+useful places such as on the line printer (2.3).
+Similarly the
+.I write
+command places its output on another user's terminal rather than its
+.I "standard output"
+(2.3).
+Commands also have a
+.I "diagnostic output"
+where they write their error messages.
+Normally these go to the terminal even if the
+.I "standard output"
+has been sent to a file or another command, but it is possible
+to direct error diagnostics along with
+.I "standard output"
+using a special metanotation (2.5).
+.IP path
+The shell has a variable
+.I path
+which gives the names of the directories in which it searches for
+the commands which it is given.
+It always checks first to see if the command it is given is
+built into the shell.
+If it is, then it need not search for the command as it can do it internally.
+If the command is not builtin, then the shell searches for a file
+with the name given in each of the directories in the
+.I path
+variable, left to right.
+Since the normal definition of the
+.I path
+variable is
+.DS
+path (. /usr/ucb /bin /usr/bin)
+.DE
+the shell normally looks in the current directory, and then in
+the standard system directories `/usr/ucb', `/bin' and `/usr/bin' for the named
+command (2.2).
+If the command cannot be found the shell will print an error diagnostic.
+Scripts of shell commands will be executed using another shell to interpret
+them if they have `execute' permission set.
+This is normally true because a command of the form
+.DS
+chmod 755 script
+.DE
+was executed to turn this execute permission on (3.3).
+If you add new commands to a directory in the
+.I path ,
+you should issue
+the command
+.I rehash
+(2.2).
+.IP pathname
+A list of names, separated by `/' characters, forms a
+.I pathname.
+Each
+.I component,
+between successive `/' characters, names a directory
+in which the next
+.I component
+file resides.
+.I Pathnames
+which begin with the character `/' are interpreted relative
+to the
+.I root
+directory in the file system.
+Other
+.I pathnames
+are interpreted relative to the current directory
+as reported by
+.I pwd.
+The last component of a
+.I pathname
+may name a directory, but
+usually names a file.
+.IP pipeline
+A group of commands which are connected together, the
+.I "standard output"
+of each connected to the
+.I "standard input"
+of the next,
+is called a
+.I pipeline.
+The
+.I pipe
+mechanism used to connect these commands is indicated by
+the shell metacharacter `|' (1.5, 2.3).
+.IP popd
+The
+.I popd
+command changes the shell's
+.I "working directory"
+to the directory you most recently left using the
+.I pushd
+command. It returns to the directory without having to type its name,
+forgetting the name of the current
+.I "working directory"
+before doing so (2.7).
+.IP port
+The part of a computer system to which each terminal is
+connected is called a
+.I port .
+Usually the system has a fixed number of
+.I ports ,
+some of which are connected to telephone lines
+for dial-up access, and some of which are permanently
+wired directly to specific terminals.
+.IP pr
+The
+.I pr
+command is used to prepare listings of the contents of files
+with headers giving the name of the file and the date and
+time at which the file was last modified (2.3).
+.IP printenv
+The
+.I printenv
+command is used
+to print the current setting of variables in the environment
+(2.8).
+.IP process
+An instance of a running program is called a
+.I process
+(2.6).
+\s-2UNIX\s0 assigns each
+.I process
+a unique number when it is
+started \- called the
+.I "process number" .
+.I "Process numbers"
+can be used to stop individual
+.I processes
+using the
+.I kill
+or
+.I stop
+commands when the
+.I processes
+are part of a detached
+.I background
+job.
+.IP program
+Usually synonymous with
+.I command ;
+a binary file or shell command script
+which performs a useful function is often
+called a
+.I program .
+.IP prompt
+Many programs will print a
+.I prompt
+on the terminal when they expect input.
+Thus the editor
+`ex (1)' will print a `:' when it expects input.
+The shell
+.I prompts
+for input with `% ' and occasionally with `? ' when
+reading commands from the terminal (1.1).
+The shell has a variable
+.I prompt
+which may be set to a different value to change the shell's main
+.I prompt .
+This is mostly used when debugging the shell (2.8).
+.IP pushd
+The
+.I pushd
+command, which means `push directory', changes the shell's
+.I "working directory"
+and also remembers the current
+.I "working directory"
+before the change is made, allowing you to return to the same
+directory via the
+.I popd
+command later without retyping its name (2.7).
+.IP ps
+The
+.I ps
+command is used to show the processes you are currently running.
+Each process is shown with its unique process number,
+an indication of the terminal name it is attached to,
+an indication of the state of the process (whether it is running,
+stopped, awaiting some event (sleeping), and whether it is swapped out),
+and the amount of \s-2CPU\s0 time it has used so far.
+The command is identified by printing some of the words used
+when it was invoked (2.6).
+Shells, such as the
+.I csh
+you use to run the
+.I ps
+command, are not normally shown in the output.
+.IP pwd
+The
+.I pwd
+command prints the full
+.I pathname
+of the current
+.I "working directory" \&.
+The
+.I dirs
+builtin command is usually a better and faster choice.
+.IP quit
+The
+.I quit
+signal, generated by a control-\e,
+is used to terminate programs which are behaving unreasonably.
+It normally produces a core image file (1.8).
+.IP quotation
+The process by which metacharacters are prevented their special
+meaning, usually by using the character `\' in pairs, or by
+using the character `\e', is referred to as
+.I quotation
+(1.7).
+.IP redirection
+The routing of input or output from or to a file is known
+as
+.I redirection
+of input or output (1.3).
+.IP rehash
+The
+.I rehash
+command tells the shell to rebuild its internal table of which commands
+are found in which directories in your
+.I path .
+This is necessary when a new program is installed in one of these
+directories (2.8).
+.IP "relative pathname"
+.br
+A
+.I pathname
+which does not begin with a `/' is called a
+.I "relative pathname"
+since it is interpreted
+.I relative
+to the current
+.I "working directory" .
+The first
+.I component
+of such a
+.I pathname
+refers to some file or directory in the
+.I "working directory" ,
+and subsequent
+.I components
+between `/' characters refer to directories below the
+.I "working directory" .
+.I Pathnames
+that are not
+.I relative
+are called
+.I "absolute pathnames"
+(1.6).
+.IP repeat
+The
+.I repeat
+command iterates another command a specified number of times.
+.IP root
+The directory
+that is at the top of the entire directory structure is called the
+.I root
+directory since it is the `root' of the entire tree structure of
+directories. The name used in
+.I pathnames
+to indicate the
+.I root
+is `/'.
+.I Pathnames
+starting with `/' are said to be
+.I absolute
+since they start at the
+.I root
+directory.
+.I Root
+is also used as the part of a
+.I pathname
+that is left after removing
+the
+.I extension .
+See
+.I filename
+for a further explanation (1.6).
+.IP \s-2RUBOUT\s0
+The \s-2RUBOUT\s0 or \s-2DELETE\s0
+key is often used to erase the previously typed character; some users
+prefer the \s-2BACKSPACE\s0 for this purpose. On older versions of \s-2UNIX\s0
+this key served as the \s-2INTR\s0 character.
+.IP "scratch file"
+Files whose names begin with a `#' are referred to as
+.I "scratch files" ,
+since they are automatically removed by the system after a couple of
+days of non-use, or more frequently if disk space becomes tight (1.3).
+.IP script
+Sequences of shell commands placed in a file are called shell command
+.I scripts .
+It is often possible to perform simple tasks using these
+.I scripts
+without writing a program in a language such as C, by
+using the shell to selectively run other programs (3.3, 3.10).
+.IP set
+The builtin
+.I set
+command is used to assign new values to shell variables
+and to show the values of the current variables.
+Many shell variables have special meaning to the shell itself.
+Thus by using the
+.I set
+command the behavior of the shell can be affected (2.1).
+.IP setenv
+Variables in the environment `environ (5)'
+can be changed by using the
+.I setenv
+builtin command (2.8).
+The
+.I printenv
+command can be used to print the value of the variables in the environment.
+.IP shell
+A
+.I shell
+is a command language interpreter.
+It is possible to write and run your own
+.I shell ,
+as
+.I shells
+are no different than any other programs as far as the
+system is concerned.
+This manual deals with the details of one particular
+.I shell ,
+called
+.I csh.
+.IP "shell script"
+See
+.I script
+(3.3, 3.10).
+.IP signal
+A
+.I signal
+in \s-2UNIX\s0 is a short message that is sent to a running program
+which causes something to happen to that process.
+.I Signals
+are sent either by typing special
+.I control
+characters on the keyboard or by using the
+.I kill
+or
+.I stop
+commands (1.8, 2.6).
+.IP sort
+The
+.I sort
+program sorts a sequence of lines in ways that can be controlled
+by argument
+.I flags
+(1.5).
+.IP source
+The
+.I source
+command causes the shell to read commands from a specified file.
+It is most useful for reading files such as
+.I \&.cshrc
+after changing them (2.8).
+.IP "special character"
+.br
+See
+.I metacharacters
+and the
+appendix to this manual.
+.IP standard
+We refer often to the
+.I "standard input"
+and
+.I "standard output"
+of commands.
+See
+.I input
+and
+.I output
+(1.3, 3.8).
+.IP status
+A command normally returns a
+.I status
+when it finishes.
+By convention a
+.I status
+of zero indicates that the command succeeded.
+Commands may return non-zero
+.I status
+to indicate that some abnormal event has occurred.
+The shell variable
+.I status
+is set to the
+.I status
+returned by the last command.
+It is most useful in shell commmand scripts (3.6).
+.IP stop
+The
+.I stop
+command causes a
+.I background
+job to become
+.I suspended
+(2.6).
+.IP string
+A sequential group of characters taken together is called a
+.I string \&.
+.I Strings
+can contain any printable characters (2.2).
+.IP stty
+The
+.I stty
+program changes certain parameters inside \s-2UNIX\s0 which determine
+how your terminal is handled. See `stty (1)' for a complete description (2.6).
+.IP substitution
+The shell implements a number of
+.I substitutions
+where sequences indicated by metacharacters are replaced by other sequences.
+Notable examples of this are history
+.I substitution
+keyed by the
+metacharacter `!' and variable
+.I substitution
+indicated by `$'.
+We also refer to
+.I substitutions
+as
+.I expansions
+(3.4).
+.IP suspended
+A job becomes
+.I suspended
+after a \s-2STOP\s0 signal is sent to it, either by typing a
+.I control -z
+at the terminal (for
+.I foreground
+jobs) or by using the
+.I stop
+command (for
+.I background
+jobs). When
+.I suspended ,
+a job temporarily stops running until it is restarted by either the
+.I fg
+or
+.I bg
+command (2.6).
+.IP switch
+The
+.I switch
+command of the shell allows the shell
+to select one of a number of sequences of commands based on an
+argument string.
+It is similar to the
+.I switch
+statement in the language C (3.7).
+.IP termination
+When a command which is being executed finishes we say it undergoes
+.I termination
+or
+.I terminates.
+Commands normally terminate when they read an
+.I end\f1-\fPof\f1-\fPfile
+from their
+.I "standard input" .
+It is also possible to terminate commands by sending them
+an
+.I interrupt
+or
+.I quit
+signal (1.8).
+The
+.I kill
+program terminates specified jobs (2.6).
+.IP then
+The
+.I then
+command is part of the shell's
+`if-then-else-endif' control construct used in command scripts (3.6).
+.IP time
+The
+.I time
+command can be used to measure the amount of \s-2CPU\s0
+and real time consumed by a specified command as well
+as the amount of disk i/o, memory utilized, and number
+of page faults and swaps taken by the command (2.1, 2.8).
+.IP tset
+The
+.I tset
+program is used to set standard erase and kill characters
+and to tell the system what kind of terminal you are using.
+It is often invoked in a
+.I \&.login
+file (2.1).
+.IP tty
+The word
+.I tty
+is a historical abbreviation for `teletype' which is frequently used
+in \s-2UNIX\s0 to indicate the
+.I port
+to which a given terminal is connected. The
+.I tty
+command will print the name of the
+.I tty
+or
+.I port
+to which your terminal is presently connected.
+.IP unalias
+The
+.I unalias
+command removes aliases (2.8).
+.IP \s-2UNIX\s0
+\s-2UNIX\s0 is an operating system on which
+.I csh
+runs.
+\s-2UNIX\s0 provides facilities which allow
+.I csh
+to invoke other programs such as editors and text formatters which
+you may wish to use.
+.IP unset
+The
+.I unset
+command removes the definitions of shell variables (2.2, 2.8).
+.IP "variable expansion"
+.br
+See
+.I variables
+and
+.I expansion
+(2.2, 3.4).
+.IP variables
+.I Variables
+in
+.I csh
+hold one or more strings as value.
+The most common use of
+.I variables
+is in controlling the behavior
+of the shell.
+See
+.I path ,
+.I noclobber ,
+and
+.I ignoreeof
+for examples.
+.I Variables
+such as
+.I argv
+are also used in writing shell programs (shell command scripts)
+(2.2).
+.IP verbose
+The
+.I verbose
+shell variable can be set to cause commands to be echoed
+after they are history expanded.
+This is often useful in debugging shell scripts.
+The
+.I verbose
+variable is set by the shell's
+.I \-v
+command line option (3.10).
+.IP wc
+The
+.I wc
+program calculates the number of characters, words, and lines in the
+files whose names are given as arguments (2.6).
+.IP while
+The
+.I while
+builtin control construct is used in shell command scripts (3.7).
+.IP word
+A sequence of characters which forms an argument to a command is called
+a
+.I word .
+Many characters which are neither letters, digits, `\-', `.' nor `/'
+form
+.I words
+all by themselves even if they are not surrounded
+by blanks.
+Any sequence of characters may be made into a
+.I word
+by surrounding it
+with `\'' characters
+except for the characters `\'' and `!' which require special treatment
+(1.1).
+This process of placing special characters in
+.I words
+without their special meaning is called
+.I quoting .
+.IP "working directory"
+.br
+At any given time you are in one particular directory, called
+your
+.I "working directory" .
+This directory's name is printed by the
+.I pwd
+command and the files listed by
+.I ls
+are the ones in this directory.
+You can change
+.I "working directories"
+using
+.I chdir .
+.IP write
+The
+.I write
+command is an obsolete way of communicating with other users who are logged in to
+\s-2UNIX\s0 (you have to take turns typing). If you are both using display
+terminals, use \fItalk\fP(1), which is much more pleasant.
diff --git a/share/doc/usd/04.csh/tabs b/share/doc/usd/04.csh/tabs
new file mode 100644
index 0000000..196d437
--- /dev/null
+++ b/share/doc/usd/04.csh/tabs
@@ -0,0 +1,32 @@
+.\"-
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)tabs 8.1 (Berkeley) 6/8/93
+.\" $FreeBSD$
+.\"
+.ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n 65n 70n 75n 80n
diff --git a/share/doc/usd/05.dc/Makefile b/share/doc/usd/05.dc/Makefile
index 2b01e0c..fd1cffc 100644
--- a/share/doc/usd/05.dc/Makefile
+++ b/share/doc/usd/05.dc/Makefile
@@ -4,6 +4,5 @@
VOLUME= usd/05.dc
SRCS= dc
MACROS= -ms
-SRCDIR= ${.CURDIR}/../../../../usr.bin/dc/USD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/usd/05.dc/dc b/share/doc/usd/05.dc/dc
new file mode 100644
index 0000000..4caa0f4
--- /dev/null
+++ b/share/doc/usd/05.dc/dc
@@ -0,0 +1,753 @@
+.\" $FreeBSD$
+.\" $OpenBSD: dc,v 1.2 2003/09/22 19:08:27 otto Exp $
+.\"
+.\" Copyright (C) Caldera International Inc. 2001-2002.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code and documentation must retain the above
+.\" copyright notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed or owned by Caldera
+.\" International, Inc.
+.\" 4. Neither the name of Caldera International, Inc. nor the names of other
+.\" contributors may be used to endorse or promote products derived from
+.\" this software without specific prior written permission.
+.\"
+.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT,
+.\" INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" @(#)dc 8.1 (Berkeley) 6/8/93
+.\"
+.EH 'USD:5-%''DC \- An Interactive Desk Calculator'
+.OH 'DC \- An Interactive Desk Calculator''USD:5-%'
+.\".RP
+.\" ....TM 75-1271-8 39199 39199-11
+.ND
+.TL
+DC \- An Interactive Desk Calculator
+.AU "MH 2C-524" 3878
+Robert Morris
+.AU
+Lorinda Cherry
+.AI
+.\" .MH
+.AB
+DC is an interactive desk calculator program implemented
+on the
+.UX
+time-sharing system to do arbitrary-precision
+integer arithmetic.
+It has provision for manipulating scaled fixed-point numbers and
+for input and output in bases other than decimal.
+.PP
+The size of numbers that can be manipulated is limited
+only by available core storage.
+On typical implementations of
+.UX ,
+the size of numbers that
+can be handled varies from several hundred digits on the smallest
+systems to several thousand on the largest.
+.AE
+.PP
+.SH
+.PP
+.ft I
+Editor's note: the description of the implementation details of DC in this
+paper is only valid for the original version of DC.
+The current version of DC uses a different approach.
+.ft
+.PP
+DC is an arbitrary precision arithmetic package implemented
+on the
+.UX
+time-sharing system
+in the form of an interactive desk calculator.
+It works like a stacking calculator using reverse Polish notation.
+Ordinarily DC operates on decimal integers, but one may
+specify an input base, output base, and a number of fractional
+digits to be maintained.
+.PP
+A language called BC [1] has been developed which accepts
+programs written in the familiar style of higher-level
+programming languages and compiles output which is
+interpreted by DC.
+Some of the commands described below were designed
+for the compiler interface and are not easy for a human user
+to manipulate.
+.PP
+Numbers that are typed into DC are put on a push-down
+stack.
+DC commands work by taking the top number or two
+off the stack, performing the desired operation, and pushing the result
+on the stack.
+If an argument is given,
+input is taken from that file until its end,
+then from the standard input.
+.SH
+SYNOPTIC DESCRIPTION
+.PP
+Here we describe the DC commands that are intended
+for use by people. The additional commands that are
+intended to be invoked by compiled output are
+described in the detailed description.
+.PP
+Any number of commands are permitted on a line.
+Blanks and new-line characters are ignored except within numbers
+and in places where a register name is expected.
+.PP
+The following constructions are recognized:
+.SH
+number
+.IP
+The value of the number is pushed onto the main stack.
+A number is an unbroken string of the digits 0-9
+and the capital letters A\-F which are treated as digits
+with values 10\-15 respectively.
+The number may be preceded by an underscore _ to input a
+negative number.
+Numbers may contain decimal points.
+.SH
++ \- * % ^
+.IP
+The
+top two values on the stack are added
+(\fB+\fP),
+subtracted
+(\fB\-\fP),
+multiplied (\fB*\fP),
+divided (\fB/\fP),
+remaindered (\fB%\fP),
+or exponentiated (^).
+The two entries are popped off the stack;
+the result is pushed on the stack in their place.
+The result of a division is an integer truncated toward zero.
+See the detailed description below for the treatment of
+numbers with decimal points.
+An exponent must not have any digits after the decimal point.
+.SH
+s\fIx\fP
+.IP
+The
+top of the main stack is popped and stored into
+a register named \fIx\fP, where \fIx\fP may be any character.
+If
+the
+.ft B
+s
+.ft
+is capitalized,
+.ft I
+x
+.ft
+is treated as a stack and the value is pushed onto it.
+Any character, even blank or new-line, is a valid register name.
+.SH
+l\fIx\fP
+.IP
+The
+value in register
+.ft I
+x
+.ft
+is pushed onto the stack.
+The register
+.ft I
+x
+.ft
+is not altered.
+If the
+.ft B
+l
+.ft
+is capitalized,
+register
+.ft I
+x
+.ft
+is treated as a stack and its top value is popped onto the main stack.
+.LP
+All registers start with empty value which is treated as a zero
+by the command \fBl\fP and is treated as an error by the command \fBL\fP.
+.SH
+d
+.IP
+The
+top value on the stack is duplicated.
+.SH
+p
+.IP
+The top value on the stack is printed.
+The top value remains unchanged.
+.SH
+f
+.IP
+All values on the stack and in registers are printed.
+.SH
+x
+.IP
+treats the top element of the stack as a character string,
+removes it from the stack, and
+executes it as a string of DC commands.
+.SH
+[ ... ]
+.IP
+puts the bracketed character string onto the top of the stack.
+.SH
+q
+.IP
+exits the program.
+If executing a string, the recursion level is
+popped by two.
+If
+.ft B
+q
+.ft
+is capitalized,
+the top value on the stack is popped and the string execution level is popped
+by that value.
+.SH
+<\fIx\fP >\fIx\fP =\fIx\fP !<\fIx\fP !>\fIx\fP !=\fIx\fP
+.IP
+The
+top two elements of the stack are popped and compared.
+Register
+.ft I
+x
+.ft
+is executed if they obey the stated
+relation.
+Exclamation point is negation.
+.SH
+v
+.IP
+replaces the top element on the stack by its square root.
+The square root of an integer is truncated to an integer.
+For the treatment of numbers with decimal points, see
+the detailed description below.
+.SH
+!
+.IP
+interprets the rest of the line as a
+.UX
+command.
+Control returns to DC when the
+.UX
+command terminates.
+.SH
+c
+.IP
+All values on the stack are popped; the stack becomes empty.
+.SH
+i
+.IP
+The top value on the stack is popped and used as the
+number radix for further input.
+If \fBi\fP is capitalized, the value of
+the input base is pushed onto the stack.
+No mechanism has been provided for the input of arbitrary
+numbers in bases less than 1 or greater than 16.
+.SH
+o
+.IP
+The top value on the stack is popped and used as the
+number radix for further output.
+If \fBo\fP is capitalized, the value of the output
+base is pushed onto the stack.
+.SH
+k
+.IP
+The top of the stack is popped, and that value is used as
+a scale factor
+that influences the number of decimal places
+that are maintained during multiplication, division, and exponentiation.
+The scale factor must be greater than or equal to zero and
+less than 100.
+If \fBk\fP is capitalized, the value of the scale factor
+is pushed onto the stack.
+.SH
+z
+.IP
+The value of the stack level is pushed onto the stack.
+.SH
+?
+.IP
+A line of input is taken from the input source (usually the console)
+and executed.
+.SH
+DETAILED DESCRIPTION
+.SH
+Internal Representation of Numbers
+.PP
+Numbers are stored internally using a dynamic storage allocator.
+Numbers are kept in the form of a string
+of digits to the base 100 stored one digit per byte
+(centennial digits).
+The string is stored with the low-order digit at the
+beginning of the string.
+For example, the representation of 157
+is 57,1.
+After any arithmetic operation on a number, care is taken
+that all digits are in the range 0\-99 and that
+the number has no leading zeros.
+The number zero is represented by the empty string.
+.PP
+Negative numbers are represented in the 100's complement
+notation, which is analogous to two's complement notation for binary
+numbers.
+The high order digit of a negative number is always \-1
+and all other digits are in the range 0\-99.
+The digit preceding the high order \-1 digit is never a 99.
+The representation of \-157 is 43,98,\-1.
+We shall call this the canonical form of a number.
+The advantage of this kind of representation of negative
+numbers is ease of addition. When addition is performed digit
+by digit, the result is formally correct. The result need only
+be modified, if necessary, to put it into canonical form.
+.PP
+Because the largest valid digit is 99 and the byte can
+hold numbers twice that large, addition can be carried out
+and the handling of carries done later when
+that is convenient, as it sometimes is.
+.PP
+An additional byte is stored with each number beyond
+the high order digit to indicate the number of
+assumed decimal digits after the decimal point. The representation
+of .001 is 1,\fI3\fP
+where the scale has been italicized to emphasize the fact that it
+is not the high order digit.
+The value of this extra byte is called the
+.ft B
+scale factor
+.ft
+of the number.
+.SH
+The Allocator
+.PP
+DC uses a dynamic string storage allocator
+for all of its internal storage.
+All reading and writing of numbers internally is done through
+the allocator.
+Associated with each string in the allocator is a four-word header containing pointers
+to the beginning of the string, the end of the string,
+the next place to write, and the next place to read.
+Communication between the allocator and DC
+is done via pointers to these headers.
+.PP
+The allocator initially has one large string on a list
+of free strings. All headers except the one pointing
+to this string are on a list of free headers.
+Requests for strings are made by size.
+The size of the string actually supplied is the next higher
+power of 2.
+When a request for a string is made, the allocator
+first checks the free list to see if there is
+a string of the desired size.
+If none is found, the allocator finds the next larger free string and splits it repeatedly until
+it has a string of the right size.
+Left-over strings are put on the free list.
+If there are no larger strings,
+the allocator tries to coalesce smaller free strings into
+larger ones.
+Since all strings are the result
+of splitting large strings,
+each string has a neighbor that is next to it in core
+and, if free, can be combined with it to make a string twice as long.
+This is an implementation of the `buddy system' of allocation
+described in [2].
+.PP
+Failing to find a string of the proper length after coalescing,
+the allocator asks the system for more space.
+The amount of space on the system is the only limitation
+on the size and number of strings in DC.
+If at any time in the process of trying to allocate a string, the allocator runs out of
+headers, it also asks the system for more space.
+.PP
+There are routines in the allocator for reading, writing, copying, rewinding,
+forward-spacing, and backspacing strings.
+All string manipulation is done using these routines.
+.PP
+The reading and writing routines
+increment the read pointer or write pointer so that
+the characters of a string are read or written in
+succession by a series of read or write calls.
+The write pointer is interpreted as the end of the
+information-containing portion of a string and a call
+to read beyond that point returns an end-of-string indication.
+An attempt to write beyond the end of a string
+causes the allocator to
+allocate a larger space and then copy
+the old string into the larger block.
+.SH
+Internal Arithmetic
+.PP
+All arithmetic operations are done on integers.
+The operands (or operand) needed for the operation are popped
+from the main stack and their scale factors stripped off.
+Zeros are added or digits removed as necessary to get
+a properly scaled result from the internal arithmetic routine.
+For example, if the scale of the operands is different and decimal
+alignment is required, as it is for
+addition, zeros are appended to the operand with the smaller
+scale.
+After performing the required arithmetic operation,
+the proper scale factor is appended to the end of the number before
+it is pushed on the stack.
+.PP
+A register called \fBscale\fP plays a part
+in the results of most arithmetic operations.
+\fBscale\fP is the bound on the number of decimal places retained in
+arithmetic computations.
+\fBscale\fP may be set to the number on the top of the stack
+truncated to an integer with the \fBk\fP command.
+\fBK\fP may be used to push the value of \fBscale\fP on the stack.
+\fBscale\fP must be greater than or equal to 0 and less than 100.
+The descriptions of the individual arithmetic operations will
+include the exact effect of \fBscale\fP on the computations.
+.SH
+Addition and Subtraction
+.PP
+The scales of the two numbers are compared and trailing
+zeros are supplied to the number with the lower scale to give both
+numbers the same scale. The number with the smaller scale is
+multiplied by 10 if the difference of the scales is odd.
+The scale of the result is then set to the larger of the scales
+of the two operands.
+.PP
+Subtraction is performed by negating the number
+to be subtracted and proceeding as in addition.
+.PP
+Finally, the addition is performed digit by digit from the
+low order end of the number. The carries are propagated
+in the usual way.
+The resulting number is brought into canonical form, which may
+require stripping of leading zeros, or for negative numbers
+replacing the high-order configuration 99,\-1 by the digit \-1.
+In any case, digits which are not in the range 0\-99 must
+be brought into that range, propagating any carries or borrows
+that result.
+.SH
+Multiplication
+.PP
+The scales are removed from the two operands and saved.
+The operands are both made positive.
+Then multiplication is performed in
+a digit by digit manner that exactly mimics the hand method
+of multiplying.
+The first number is multiplied by each digit of the second
+number, beginning with its low order digit. The intermediate
+products are accumulated into a partial sum which becomes the
+final product.
+The product is put into the canonical form and its sign is
+computed from the signs of the original operands.
+.PP
+The scale of the result is set equal to the sum
+of the scales of the two operands.
+If that scale is larger than the internal register
+.ft B
+scale
+.ft
+and also larger than both of the scales of the two operands,
+then the scale of the result is set equal to the largest
+of these three last quantities.
+.SH
+Division
+.PP
+The scales are removed from the two operands.
+Zeros are appended or digits removed from the dividend to make
+the scale of the result of the integer division equal to
+the internal quantity
+\fBscale\fP.
+The signs are removed and saved.
+.PP
+Division is performed much as it would be done by hand.
+The difference of the lengths of the two numbers
+is computed.
+If the divisor is longer than the dividend,
+zero is returned.
+Otherwise the top digit of the divisor is divided into the top
+two digits of the dividend.
+The result is used as the first (high-order) digit of the
+quotient.
+It may turn out be one unit too low, but if it is, the next
+trial quotient will be larger than 99 and this will be
+adjusted at the end of the process.
+The trial digit is multiplied by the divisor and the result subtracted
+from the dividend and the process is repeated to get
+additional quotient digits until the remaining
+dividend is smaller than the divisor.
+At the end, the digits of the quotient are put into
+the canonical form, with propagation of carry as needed.
+The sign is set from the sign of the operands.
+.SH
+Remainder
+.PP
+The division routine is called and division is performed
+exactly as described. The quantity returned is the remains of the
+dividend at the end of the divide process.
+Since division truncates toward zero, remainders have the same
+sign as the dividend.
+The scale of the remainder is set to
+the maximum of the scale of the dividend and
+the scale of the quotient plus the scale of the divisor.
+.SH
+Square Root
+.PP
+The scale is stripped from the operand.
+Zeros are added if necessary to make the
+integer result have a scale that is the larger of
+the internal quantity
+\fBscale\fP
+and the scale of the operand.
+.PP
+The method used to compute sqrt(y) is Newton's method
+with successive approximations by the rule
+.EQ
+x sub {n+1} ~=~ half ( x sub n + y over x sub n )
+.EN
+The initial guess is found by taking the integer square root
+of the top two digits.
+.SH
+Exponentiation
+.PP
+Only exponents with zero scale factor are handled. If the exponent is
+zero, then the result is 1. If the exponent is negative, then
+it is made positive and the base is divided into one. The scale
+of the base is removed.
+.PP
+The integer exponent is viewed as a binary number.
+The base is repeatedly squared and the result is
+obtained as a product of those powers of the base that
+correspond to the positions of the one-bits in the binary
+representation of the exponent.
+Enough digits of the result
+are removed to make the scale of the result the same as if the
+indicated multiplication had been performed.
+.SH
+Input Conversion and Base
+.PP
+Numbers are converted to the internal representation as they are read
+in.
+The scale stored with a number is simply the number of fractional digits input.
+Negative numbers are indicated by preceding the number with a \fB\_\fP (an
+underscore).
+The hexadecimal digits A\-F correspond to the numbers 10\-15 regardless of input base.
+The \fBi\fP command can be used to change the base of the input numbers.
+This command pops the stack, truncates the resulting number to an integer,
+and uses it as the input base for all further input.
+The input base is initialized to 10 but may, for example be changed to
+8 or 16 to do octal or hexadecimal to decimal conversions.
+The command \fBI\fP will push the value of the input base on the stack.
+.SH
+Output Commands
+.PP
+The command \fBp\fP causes the top of the stack to be printed.
+It does not remove the top of the stack.
+All of the stack and internal registers can be output
+by typing the command \fBf\fP.
+The \fBo\fP command can be used to change the output base.
+This command uses the top of the stack, truncated to an integer as
+the base for all further output.
+The output base in initialized to 10.
+It will work correctly for any base.
+The command \fBO\fP pushes the value of the output base on the stack.
+.SH
+Output Format and Base
+.PP
+The input and output bases only affect
+the interpretation of numbers on input and output; they have no
+effect on arithmetic computations.
+Large numbers are output with 70 characters per line;
+a \\ indicates a continued line.
+All choices of input and output bases work correctly, although not all are
+useful.
+A particularly useful output base is 100000, which has the effect of
+grouping digits in fives.
+Bases of 8 and 16 can be used for decimal-octal or decimal-hexadecimal
+conversions.
+.SH
+Internal Registers
+.PP
+Numbers or strings may be stored in internal registers or loaded on the stack
+from registers with the commands \fBs\fP and \fBl\fP.
+The command \fBs\fIx\fR pops the top of the stack and
+stores the result in register \fBx\fP.
+\fIx\fP can be any character.
+\fBl\fIx\fR puts the contents of register \fBx\fP on the top of the stack.
+The \fBl\fP command has no effect on the contents of register \fIx\fP.
+The \fBs\fP command, however, is destructive.
+.SH
+Stack Commands
+.PP
+The command \fBc\fP clears the stack.
+The command \fBd\fP pushes a duplicate of the number on the top of the stack
+on the stack.
+The command \fBz\fP pushes the stack size on the stack.
+The command \fBX\fP replaces the number on the top of the stack
+with its scale factor.
+The command \fBZ\fP replaces the top of the stack
+with its length.
+.SH
+Subroutine Definitions and Calls
+.PP
+Enclosing a string in \fB[ ]\fP pushes the ascii string on the stack.
+The \fBq\fP command quits or in executing a string, pops the recursion levels by two.
+.SH
+Internal Registers \- Programming DC
+.PP
+The load and store
+commands together with \fB[ ]\fP to store strings, \fBx\fP to execute
+and the testing commands `<', `>', `=', `!<', `!>', `!=' can be used to program
+DC.
+The \fBx\fP command assumes the top of the stack is an string of DC commands
+and executes it.
+The testing commands compare the top two elements on the stack and if the relation holds, execute the register
+that follows the relation.
+For example, to print the numbers 0-9,
+.DS
+[lip1+ si li10>a]sa
+0si lax
+.DE
+.SH
+Push-Down Registers and Arrays
+.PP
+These commands were designed for used by a compiler, not by
+people.
+They involve push-down registers and arrays.
+In addition to the stack that commands work on, DC can be thought
+of as having individual stacks for each register.
+These registers are operated on by the commands \fBS\fP and \fBL\fP.
+\fBS\fIx\fR pushes the top value of the main stack onto the stack for
+the register \fIx\fP.
+\fBL\fIx\fR pops the stack for register \fIx\fP and puts the result on the main
+stack.
+The commands \fBs\fP and \fBl\fP also work on registers but not as push-down
+stacks.
+\fBl\fP doesn't effect the top of the
+register stack, and \fBs\fP destroys what was there before.
+.PP
+The commands to work on arrays are \fB:\fP and \fB;\fP.
+\fB:\fIx\fR pops the stack and uses this value as an index into
+the array \fIx\fP.
+The next element on the stack is stored at this index in \fIx\fP.
+An index must be greater than or equal to 0 and
+less than 2048.
+\fB;\fIx\fR is the command to load the main stack from the array \fIx\fP.
+The value on the top of the stack is the index
+into the array \fIx\fP of the value to be loaded.
+.SH
+Miscellaneous Commands
+.PP
+The command \fB!\fP interprets the rest of the line as a
+.UX
+command and passes it to
+.UX
+to execute.
+One other compiler command is \fBQ\fP.
+This command uses the top of the stack as the number of levels of recursion to skip.
+.SH
+DESIGN CHOICES
+.PP
+The real reason for the use of a dynamic storage allocator was
+that a general purpose program could be (and in fact has been)
+used for a variety of other tasks.
+The allocator has some value for input and for compiling (i.e.
+the bracket [...] commands) where it cannot be known in advance
+how long a string will be.
+The result was that at a modest
+cost in execution time, all considerations of string allocation
+and sizes of strings were removed from the remainder of the program
+and debugging was made easier. The allocation method
+used wastes approximately 25% of available space.
+.PP
+The choice of 100 as a base for internal arithmetic
+seemingly has no compelling advantage. Yet the base cannot
+exceed 127 because of hardware limitations and at the cost
+of 5% in space, debugging was made a great deal easier and
+decimal output was made much faster.
+.PP
+The reason for a stack-type arithmetic design was
+to permit all DC commands from addition to subroutine execution
+to be implemented in essentially the same way. The result
+was a considerable degree of logical separation of the final
+program into modules with very little communication between
+modules.
+.PP
+The rationale for the lack of interaction between the scale and the bases
+was to provide an understandable means of proceeding after
+a change of base or scale when numbers had already been entered.
+An earlier implementation which had global notions of
+scale and base did not work out well.
+If the value of
+.ft B
+scale
+.ft
+were to be interpreted in the current
+input or output base,
+then a change of base or scale in the midst of a
+computation would cause great confusion in the interpretation
+of the results.
+The current scheme has the advantage that the value of
+the input and output bases
+are only used for input and output, respectively, and they
+are ignored in all other operations.
+The value of
+scale
+is not used for any essential purpose by any part of the program
+and it is used only to prevent the number of
+decimal places resulting from the arithmetic operations from
+growing beyond all bounds.
+.PP
+The design rationale for the choices for the scales of
+the results of arithmetic were that in no case should
+any significant digits be thrown away if, on appearances, the
+user actually wanted them. Thus, if the user wants
+to add the numbers 1.5 and 3.517, it seemed reasonable to give
+him the result 5.017 without requiring him to unnecessarily
+specify his rather obvious requirements for precision.
+.PP
+On the other hand, multiplication and exponentiation produce
+results with many more digits than their operands and it
+seemed reasonable to give as a minimum the number of decimal
+places in the operands but not to give more than that
+number of digits
+unless the user asked for them by specifying a value for \fBscale\fP.
+Square root can be handled in just the same way as multiplication.
+The operation of division gives arbitrarily many decimal places
+and there is simply no way to guess how many places the user
+wants.
+In this case only, the user must
+specify a \fBscale\fP to get any decimal places at all.
+.PP
+The scale of remainder was chosen to make it possible
+to recreate the dividend from the quotient and remainder.
+This is easy to implement; no digits are thrown away.
+.SH
+References
+.IP [1]
+L. L. Cherry, R. Morris,
+.ft I
+BC \- An Arbitrary Precision Desk-Calculator Language.
+.ft
+.IP [2]
+K. C. Knowlton,
+.ft I
+A Fast Storage Allocator,
+.ft
+Comm. ACM \fB8\fP, pp. 623-625 (Oct. 1965).
diff --git a/share/doc/usd/06.bc/Makefile b/share/doc/usd/06.bc/Makefile
index 12dfedd..b4f340c 100644
--- a/share/doc/usd/06.bc/Makefile
+++ b/share/doc/usd/06.bc/Makefile
@@ -4,6 +4,5 @@
VOLUME= usd/06.bc
SRCS= bc
MACROS= -ms
-SRCDIR= ${.CURDIR}/../../../../usr.bin/bc/USD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/usd/06.bc/bc b/share/doc/usd/06.bc/bc
new file mode 100644
index 0000000..c4e68c6
--- /dev/null
+++ b/share/doc/usd/06.bc/bc
@@ -0,0 +1,1241 @@
+.\" $FreeBSD$
+.\" $OpenBSD: bc,v 1.9 2004/07/09 10:23:05 jmc Exp $
+.\"
+.\" Copyright (C) Caldera International Inc. 2001-2002.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code and documentation must retain the above
+.\" copyright notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed or owned by Caldera
+.\" International, Inc.
+.\" 4. Neither the name of Caldera International, Inc. nor the names of other
+.\" contributors may be used to endorse or promote products derived from
+.\" this software without specific prior written permission.
+.\"
+.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT,
+.\" INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" @(#)bc 6.2 (Berkeley) 4/17/91
+.\"
+.if n \{\
+.po 5n
+.ll 70n
+.\}
+.EH 'USD:6-%''BC \- An Arbitrary Precision Desk-Calculator Language'
+.OH 'BC \- An Arbitrary Precision Desk-Calculator Language''USD:6-%'
+.\".RP
+.TL
+BC \- An Arbitrary Precision Desk-Calculator Language
+.AU
+Lorinda Cherry
+.AU
+Robert Morris
+.AI
+.\" .MH
+.AB
+BC is a language and a compiler for doing arbitrary precision arithmetic
+on the PDP-11 under the
+.UX
+time-sharing
+system. The output of the compiler is interpreted and executed by
+a collection of routines which can input, output, and do
+arithmetic on indefinitely large integers and on scaled fixed-point
+numbers.
+.PP
+These routines are themselves based on a dynamic storage allocator.
+Overflow does not occur until all available core storage
+is exhausted.
+.PP
+The language has a complete control structure as well as immediate-mode
+operation. Functions can be defined and saved for later execution.
+.PP
+Two five hundred-digit numbers can be multiplied to give a
+thousand digit result in about ten seconds.
+.PP
+A small collection of library functions is also available,
+including sin, cos, arctan, log, exponential, and Bessel functions of
+integer order.
+.PP
+Some of the uses of this compiler are
+.IP \-
+to do computation with large integers,
+.IP \-
+to do computation accurate to many decimal places,
+.IP \-
+conversion of numbers from one base to another base.
+.AE
+.PP
+.SH
+Introduction
+.PP
+BC is a language and a compiler for doing arbitrary precision
+arithmetic on the
+.UX
+time-sharing system [1].
+The compiler was written to make conveniently available a
+collection of routines (called DC [5]) which are capable of doing
+arithmetic on integers of arbitrary size. The compiler
+is by no means intended to provide a complete programming
+language.
+It is a minimal language facility.
+.PP
+There is a scaling provision that permits the
+use of decimal point notation.
+Provision is made for input and output in bases other than
+decimal. Numbers can be converted from decimal to octal by
+simply setting the output base to equal 8.
+.PP
+The actual limit on the number of digits that can
+be handled depends on the amount of storage available on the machine.
+Manipulation of numbers with many hundreds of digits
+is possible even on the smallest versions of
+.UX .
+.PP
+The syntax of BC has been deliberately selected to agree
+substantially with the C language [2]. Those who
+are familiar with C will find few surprises in this language.
+.SH
+Simple Computations with Integers
+.PP
+The simplest kind of statement is an arithmetic expression
+on a line by itself.
+For instance, if you type in the line:
+.DS
+.ft B
+142857 + 285714
+.ft P
+.DE
+the program responds immediately with the line
+.DS
+.ft B
+428571
+.ft P
+.DE
+The operators \-, *, /, %, and ^ can also be used; they
+indicate subtraction, multiplication, division, remaindering, and
+exponentiation, respectively. Division of integers produces an
+integer result truncated toward zero.
+Division by zero produces an error
+comment.
+.PP
+Any term in an expression may be prefixed by a minus sign to
+indicate that it is to be negated (the `unary' minus sign).
+The expression
+.DS
+.ft B
+7+\-3
+.ft P
+.DE
+is interpreted to mean that \-3 is to be added to 7.
+.PP
+More complex expressions with several operators and with
+parentheses are interpreted just as in
+Fortran, with ^ having the greatest binding
+power, then * and % and /, and finally + and \-.
+Contents of parentheses are evaluated before material
+outside the parentheses.
+Exponentiations are
+performed from right to left and the other operators
+from left to right.
+The two expressions
+.DS
+.ft B
+a^b^c and a^(b^c)
+.ft P
+.DE
+are equivalent, as are the two expressions
+.DS
+.ft B
+a*b*c and (a*b)*c
+.ft P
+.DE
+BC shares with Fortran and C the undesirable convention that
+.DS
+\fBa/b*c\fP is equivalent to \fB(a/b)*c\fP
+.ft P
+.DE
+.PP
+Internal storage registers to hold numbers have single lower-case
+letter names. The value of an expression can be assigned to
+a register in the usual way. The statement
+.DS
+.ft B
+x = x + 3
+.ft P
+.DE
+has the effect of increasing by three the value of the contents of the
+register named x.
+When, as in this case, the outermost operator is an =, the
+assignment is performed but the result is not printed.
+Only 26 of these named storage registers are available.
+.PP
+There is a built-in square root function whose
+result is truncated to an integer (but see scaling below).
+The lines
+.DS
+.ft B
+x = sqrt(191)
+x
+.ft P
+.DE
+produce the printed result
+.DS
+.ft B
+13
+.ft P
+.DE
+.SH
+Bases
+.PP
+There are special internal quantities, called `ibase' and `obase'.
+The contents of `ibase', initially set to 10,
+determines the base used for interpreting numbers read in.
+For example, the lines
+.DS
+.ft B
+ibase = 8
+11
+.ft P
+.DE
+will produce the output line
+.DS
+.ft B
+9
+.ft P
+.DE
+and you are all set up to do octal to decimal conversions.
+Beware, however of trying to change the input base back
+to decimal by typing
+.DS
+.ft B
+ibase = 10
+.ft P
+.DE
+Because the number 10 is interpreted as octal, this statement will
+have no effect.
+For those who deal in hexadecimal notation,
+the characters A\-F are permitted in numbers
+(no matter what base is in effect)
+and are
+interpreted as digits having values 10\-15 respectively.
+The statement
+.DS
+.ft B
+ibase = A
+.ft P
+.DE
+will change you back to decimal input base no matter what the
+current input base is.
+Negative and large positive input bases are
+permitted but useless.
+No mechanism has been provided for the input of arbitrary
+numbers in bases less than 1 and greater than 16.
+.PP
+The contents of `obase', initially set to 10, are used as the base for output
+numbers. The lines
+.DS
+.ft B
+obase = 16
+1000
+.ft P
+.DE
+will produce the output line
+.DS
+.ft B
+3E8
+.ft P
+.DE
+which is to be interpreted as a 3-digit hexadecimal number.
+Very large output bases are permitted, and they are sometimes useful.
+For example, large numbers can be output in groups of five digits
+by setting `obase' to 100000.
+Strange (i.e. 1, 0, or negative) output bases are
+handled appropriately.
+.PP
+Very large numbers are split across lines with 70 characters per line.
+Lines which are continued end with \\.
+Decimal output conversion is practically instantaneous, but output
+of very large numbers (i.e., more than 100 digits) with other bases
+is rather slow.
+Non-decimal output conversion of
+a one hundred digit number takes about
+three seconds.
+.PP
+It is best to remember that `ibase' and `obase' have no effect
+whatever on the course of internal computation or
+on the evaluation of expressions, but only affect input and
+output conversion, respectively.
+.SH
+Scaling
+.PP
+A third special internal quantity called `scale' is
+used to determine the scale of calculated
+quantities.
+Numbers may have
+up to a specific number of decimal digits after the decimal point.
+This fractional part is retained in further computations.
+We refer to the number of digits after the decimal point of
+a number as its scale.
+The current implementation allows scales to be as large as can be
+represented by a 32-bit unsigned number minus one.
+This is a non-portable extension.
+The original implementation allowed for a maximum scale of 99.
+.PP
+When two scaled numbers are combined by
+means of one of the arithmetic operations, the result
+has a scale determined by the following rules. For
+addition and subtraction, the scale of the result is the larger
+of the scales of the two operands. In this case,
+there is never any truncation of the result.
+For multiplications, the scale of the result is never
+less than the maximum of the two scales of the operands,
+never more than the sum of the scales of the operands
+and, subject to those two restrictions,
+the scale of the result is set equal to the contents of the internal
+quantity `scale'.
+The scale of a quotient is the contents of the internal
+quantity `scale'. The scale of a remainder is
+the sum of the scales of the quotient and the divisor.
+The result of an exponentiation is scaled as if
+the implied multiplications were performed.
+An exponent must be an integer.
+The scale of a square root is set to the maximum of the scale
+of the argument and the contents of `scale'.
+.PP
+All of the internal operations are actually carried out in terms
+of integers, with digits being discarded when necessary.
+In every case where digits are discarded, truncation and
+not rounding is performed.
+.PP
+The contents of
+`scale' must be no greater than
+4294967294 and no less than 0. It is initially set to 0.
+.PP
+The internal quantities `scale', `ibase', and `obase' can be
+used in expressions just like other variables.
+The line
+.DS
+.ft B
+scale = scale + 1
+.ft P
+.DE
+increases the value of `scale' by one, and the line
+.DS
+.ft B
+scale
+.ft P
+.DE
+causes the current value of `scale' to be printed.
+.PP
+The value of `scale' retains its meaning as a
+number of decimal digits to be retained in internal
+computation even when `ibase' or `obase' are not equal to 10.
+The internal computations (which are still conducted in decimal,
+regardless of the bases) are performed to the specified number
+of decimal digits, never hexadecimal or octal or any
+other kind of digits.
+.SH
+Functions
+.PP
+The name of a function is a single lower-case letter.
+Function names are permitted to collide with simple
+variable names.
+Twenty-six different defined functions are permitted
+in addition to the twenty-six variable names.
+The line
+.DS
+.ft B
+ define a(x){
+.ft P
+.DE
+begins the definition of a function with one argument.
+This line must be followed by one or more statements,
+which make up the body of the function, ending
+with a right brace }.
+Return of control from a function occurs when a return
+statement is executed or when the end of the function is reached.
+The return statement can take either
+of the two forms
+.DS
+.ft B
+return
+return(x)
+.ft P
+.DE
+In the first case, the value of the function is 0, and in
+the second, the value of the expression in parentheses.
+.PP
+Variables used in the function can be declared as automatic
+by a statement of the form
+.DS
+.ft B
+auto x,y,z
+.ft P
+.DE
+There can be only one `auto' statement in a function and it must
+be the first statement in the definition.
+These automatic variables are allocated space and initialized
+to zero on entry to the function and thrown away on return. The
+values of any variables with the same names outside the function
+are not disturbed.
+Functions may be called recursively and the automatic variables
+at each level of call are protected.
+The parameters named in a function definition are treated in
+the same way as the automatic variables of that function
+with the single exception that they are given a value
+on entry to the function.
+An example of a function definition is
+.DS
+.ft B
+ define a(x,y){
+ auto z
+ z = x*y
+ return(z)
+ }
+.ft P
+.DE
+The value of this function, when called, will be the
+product of its
+two arguments.
+.PP
+A function is called by the appearance of its name
+followed by a string of arguments enclosed in
+parentheses and separated by commas.
+The result
+is unpredictable if the wrong number of arguments is used.
+.PP
+Functions with no arguments are defined and called using
+parentheses with nothing between them: b().
+.PP
+If the function
+.ft I
+a
+.ft
+above has been defined, then the line
+.DS
+.ft B
+a(7,3.14)
+.ft P
+.DE
+would cause the result 21.98 to be printed and the line
+.DS
+.ft B
+x = a(a(3,4),5)
+.ft P
+.DE
+would cause the value of x to become 60.
+.SH
+Subscripted Variables
+.PP
+A single lower-case letter variable name
+followed by an expression in brackets is called a subscripted
+variable (an array element).
+The variable name is called the array name and the expression
+in brackets is called the subscript.
+Only one-dimensional arrays are
+permitted. The names of arrays are permitted to
+collide with the names of simple variables and function names.
+Any fractional
+part of a subscript is discarded before use.
+Subscripts must be greater than or equal to zero and
+less than or equal to 2047.
+.PP
+Subscripted variables may be freely used in expressions, in
+function calls, and in return statements.
+.PP
+An array name may be used as an argument to a function,
+or may be declared as automatic in
+a function definition by the use of empty brackets:
+.DS
+.ft B
+f(a[\|])
+define f(a[\|])
+auto a[\|]
+.ft P
+.DE
+When an array name is so used, the whole contents of the array
+are copied for the use of the function, and thrown away on exit
+from the function.
+Array names which refer to whole arrays cannot be used
+in any other contexts.
+.SH
+Control Statements
+.PP
+The `if', the `while', and the `for' statements
+may be used to alter the flow within programs or to cause iteration.
+The range of each of them is a statement or
+a compound statement consisting of a collection of
+statements enclosed in braces.
+They are written in the following way
+.DS
+.ft B
+if(relation) statement
+if(relation) statement else statement
+while(relation) statement
+for(expression1; relation; expression2) statement
+.ft P
+.DE
+or
+.DS
+.ft B
+if(relation) {statements}
+if(relation) {statements} else {statements}
+while(relation) {statements}
+for(expression1; relation; expression2) {statements}
+.ft P
+.DE
+.PP
+A relation in one of the control statements is an expression of the form
+.DS
+.ft B
+x>y
+.ft P
+.DE
+where two expressions are related by one of the six relational
+operators `<', `>', `<=', `>=', `==', or `!='.
+The relation `=='
+stands for `equal to' and `!=' stands for `not equal to'.
+The meaning of the remaining relational operators is
+clear.
+.PP
+BEWARE of using `=' instead of `==' in a relational. Unfortunately,
+both of them are legal, so you will not get a diagnostic
+message, but `=' really will not do a comparison.
+.PP
+The `if' statement causes execution of its range
+if and only if the relation is true.
+Then control passes to the next statement in sequence.
+If an `else' branch is present, the statements in this branch are
+executed if the relation is false.
+The `else' keyword is a non-portable extension.
+.PP
+The `while' statement causes execution of its range
+repeatedly as long as the relation
+is true. The relation is tested before each execution
+of its range and if the relation
+is false, control passes to the next statement beyond the range
+of the while.
+.PP
+The `for' statement begins
+by executing `expression1'. Then the relation is tested
+and, if true, the statements in the range of the `for' are executed.
+Then `expression2' is executed. The relation is tested, and so on.
+The typical use of the `for' statement is for a controlled iteration,
+as in the statement
+.DS
+.ft B
+for(i=1; i<=10; i=i+1) i
+.ft P
+.DE
+which will print the integers from 1 to 10.
+Here are some examples of the use of the control statements.
+.DS
+.ft B
+define f(n){
+auto i, x
+x=1
+for(i=1; i<=n; i=i+1) x=x*i
+return(x)
+}
+.ft P
+.DE
+The line
+.DS
+.ft B
+ f(a)
+.ft P
+.DE
+will print
+.ft I
+a
+.ft
+factorial if
+.ft I
+a
+.ft
+is a positive integer.
+Here is the definition of a function which will
+compute values of the binomial coefficient
+(m and n are assumed to be positive integers).
+.DS
+.ft B
+define b(n,m){
+auto x, j
+x=1
+for(j=1; j<=m; j=j+1) x=x*(n\-j+1)/j
+return(x)
+}
+.ft P
+.DE
+The following function computes values of the exponential function
+by summing the appropriate series
+without regard for possible truncation errors:
+.DS
+.ft B
+scale = 20
+define e(x){
+ auto a, b, c, d, n
+ a = 1
+ b = 1
+ c = 1
+ d = 0
+ n = 1
+ while(1==1){
+ a = a*x
+ b = b*n
+ c = c + a/b
+ n = n + 1
+ if(c==d) return(c)
+ d = c
+ }
+}
+.ft P
+.DE
+.SH
+Some Details
+.PP
+There are some language features that every user should know
+about even if he will not use them.
+.PP
+Normally statements are typed one to a line. It is also permissible
+to type several statements on a line separated by semicolons.
+.PP
+If an assignment statement is parenthesized, it then has
+a value and it can be used anywhere that an expression can.
+For example, the line
+.DS
+.ft B
+(x=y+17)
+.ft P
+.DE
+not only makes the indicated assignment, but also prints the
+resulting value.
+.PP
+Here is an example of a use of the value of an
+assignment statement even when it is not parenthesized.
+.DS
+.ft B
+x = a[i=i+1]
+.ft P
+.DE
+causes a value to be assigned to x and also increments i
+before it is used as a subscript.
+.PP
+The following constructs work in BC in exactly the same manner
+as they do in the C language. Consult the appendix or the
+C manuals [2] for their exact workings.
+.DS
+.ft B
+.ta 2i
+x=y=z is the same as x=(y=z)
+x += y x = x+y
+x \-= y x = x\-y
+x *= y x = x*y
+x /= y x = x/y
+x %= y x = x%y
+x ^= y x = x^y
+x++ (x=x+1)\-1
+x\-\- (x=x\-1)+1
+++x x = x+1
+\-\-x x = x\-1
+.ft P
+.DE
+Even if you don't intend to use the constructs,
+if you type one inadvertently, something correct but unexpected
+may happen.
+.SH
+Three Important Things
+.PP
+1. To exit a BC program, type `quit'.
+.PP
+2. There is a comment convention identical to that of C and
+of PL/I. Comments begin with `/*' and end with `*/'.
+As a non-portable extension, comments may also start with a `#' and end with
+a newline.
+The newline is not part of the comment.
+.PP
+3. There is a library of math functions which may be obtained by
+typing at command level
+.DS
+.ft B
+bc \-l
+.ft P
+.DE
+This command will load a set of library functions
+which, at the time of writing, consists of sine (named `s'),
+cosine (`c'), arctangent (`a'), natural logarithm (`l'),
+exponential (`e') and Bessel functions of integer order (`j(n,x)'). Doubtless more functions will be added
+in time.
+The library sets the scale to 20. You can reset it to something
+else if you like.
+The design of these mathematical library routines
+is discussed elsewhere [3].
+.PP
+If you type
+.DS
+.ft B
+bc file ...
+.ft P
+.DE
+BC will read and execute the named file or files before accepting
+commands from the keyboard. In this way, you may load your
+favorite programs and function definitions.
+.SH
+Acknowledgement
+.PP
+The compiler is written in YACC [4]; its original
+version was written by S. C. Johnson.
+.SH
+References
+.IP [1]
+K. Thompson and D. M. Ritchie,
+.ft I
+UNIX Programmer's Manual,
+.ft
+Bell Laboratories,
+1978.
+.IP [2]
+B. W. Kernighan and
+D. M. Ritchie,
+.ft I
+The C Programming Language,
+.ft
+Prentice-Hall, 1978.
+.IP [3]
+R. Morris,
+.ft I
+A Library of Reference Standard Mathematical Subroutines,
+.ft
+Bell Laboratories internal memorandum, 1975.
+.IP [4]
+S. C. Johnson,
+.ft I
+YACC \(em Yet Another Compiler-Compiler.
+.ft
+Bell Laboratories Computing Science Technical Report #32, 1978.
+.IP [5]
+R. Morris and L. L. Cherry,
+.ft I
+DC \- An Interactive Desk Calculator.
+.ft
+.LP
+.bp
+.ft B
+.DS C
+Appendix
+.DE
+.ft
+.NH
+Notation
+.PP
+In the following pages syntactic categories are in \fIitalics\fP;
+literals are in \fBbold\fP; material in brackets [\|] is optional.
+.NH
+Tokens
+.PP
+Tokens consist of keywords, identifiers, constants, operators,
+and separators.
+Token separators may be blanks, tabs or comments.
+Newline characters or semicolons separate statements.
+.NH 2
+Comments
+.PP
+Comments are introduced by the characters /* and terminated by
+*/.
+As a non-portable extension, comments may also start with a # and
+end with a newline.
+The newline is not part of the comment.
+.NH 2
+Identifiers
+.PP
+There are three kinds of identifiers \- ordinary identifiers, array identifiers
+and function identifiers.
+All three types consist of single lower-case letters.
+Array identifiers are followed by square brackets, possibly
+enclosing an expression describing a subscript.
+Arrays are singly dimensioned and may contain up to 2048
+elements.
+Indexing begins at zero so an array may be indexed from 0 to 2047.
+Subscripts are truncated to integers.
+Function identifiers are followed by parentheses, possibly enclosing arguments.
+The three types of identifiers do not conflict;
+a program can have a variable named \fBx\fP,
+an array named \fBx\fP and a function named \fBx\fP, all of which are separate and
+distinct.
+.NH 2
+Keywords
+.PP
+The following are reserved keywords:
+.ft B
+.ta .5i 1.0i
+.nf
+ ibase if
+ obase break
+ scale define
+ sqrt auto
+ length return
+ while quit
+ for continue
+ else last
+ print
+.fi
+.ft
+.NH 2
+Constants
+.PP
+Constants consist of arbitrarily long numbers
+with an optional decimal point.
+The hexadecimal digits \fBA\fP\-\fBF\fP are also recognized as digits with
+values 10\-15, respectively.
+.NH 1
+Expressions
+.PP
+The value of an expression is printed unless the main
+operator is an assignment.
+The value printed is assigned to the special variable \fBlast\fP.
+A single dot may be used as a synonym for \fBlast\fP.
+This is a non-portable extension.
+Precedence is the same as the order
+of presentation here, with highest appearing first.
+Left or right associativity, where applicable, is
+discussed with each operator.
+.bp
+.NH 2
+Primitive expressions
+.NH 3
+Named expressions
+.PP
+Named expressions are
+places where values are stored.
+Simply stated,
+named expressions are legal on the left
+side of an assignment.
+The value of a named expression is the value stored in the place named.
+.NH 4
+\fIidentifiers\fR
+.PP
+Simple identifiers are named expressions.
+They have an initial value of zero.
+.NH 4
+\fIarray-name\fP\|[\|\fIexpression\fP\|]
+.PP
+Array elements are named expressions.
+They have an initial value of zero.
+.NH 4
+\fBscale\fR, \fBibase\fR and \fBobase\fR
+.PP
+The internal registers
+\fBscale\fP, \fBibase\fP and \fBobase\fP are all named expressions.
+\fBscale\fP is the number of digits after the decimal point to be
+retained in arithmetic operations.
+\fBscale\fR has an initial value of zero.
+\fBibase\fP and \fBobase\fP are the input and output number
+radix respectively.
+Both \fBibase\fR and \fBobase\fR have initial values of 10.
+.NH 3
+Function calls
+.NH 4
+\fIfunction-name\fB\|(\fR[\fIexpression\fR\|[\fB,\|\fIexpression\|\fR.\|.\|.\|]\|]\fB)
+.PP
+A function call consists of a function name followed by parentheses
+containing a comma-separated list of
+expressions, which are the function arguments.
+A whole array passed as an argument is specified by the
+array name followed by empty square brackets.
+All function arguments are passed by
+value.
+As a result, changes made to the formal parameters have
+no effect on the actual arguments.
+If the function terminates by executing a return
+statement, the value of the function is
+the value of the expression in the parentheses of the return
+statement or is zero if no expression is provided
+or if there is no return statement.
+.NH 4
+sqrt\|(\|\fIexpression\fP\|)
+.PP
+The result is the square root of the expression.
+The result is truncated in the least significant decimal place.
+The scale of the result is
+the scale of the expression or the
+value of
+.ft B
+scale,
+.ft
+whichever is larger.
+.NH 4
+length\|(\|\fIexpression\fP\|)
+.PP
+The result is the total number of significant decimal digits in the expression.
+The scale of the result is zero.
+.NH 4
+scale\|(\|\fIexpression\fP\|)
+.PP
+The result is the scale of the expression.
+The scale of the result is zero.
+.NH 3
+Constants
+.PP
+Constants are primitive expressions.
+.NH 3
+Parentheses
+.PP
+An expression surrounded by parentheses is
+a primitive expression.
+The parentheses are used to alter the
+normal precedence.
+.NH 2
+Unary operators
+.PP
+The unary operators
+bind right to left.
+.NH 3
+\-\|\fIexpression\fP
+.PP
+The result is the negative of the expression.
+.NH 3
+++\|\fInamed-expression\fP
+.PP
+The named expression is
+incremented by one.
+The result is the value of the named expression after
+incrementing.
+.NH 3
+\-\-\|\fInamed-expression\fP
+.PP
+The named expression is
+decremented by one.
+The result is the value of the named expression after
+decrementing.
+.NH 3
+\fInamed-expression\fP\|++
+.PP
+The named expression is
+incremented by one.
+The result is the value of the named expression before
+incrementing.
+.NH 3
+\fInamed-expression\fP\|\-\-
+.PP
+The named expression is
+decremented by one.
+The result is the value of the named expression before
+decrementing.
+.NH 2
+Exponentiation operator
+.PP
+The exponentiation operator binds right to left.
+.NH 3
+\fIexpression\fP ^ \fIexpression\fP
+.PP
+The result is the first
+expression raised to the power of the
+second expression.
+The second expression must be an integer.
+If \fIa\fP
+is the scale of the left expression
+and \fIb\fP is the absolute value
+of the right expression,
+then the scale of the result is:
+.PP
+min\|(\|\fIa\(mub\fP,\|max\|(\|\fBscale\fP,\|\fIa\fP\|)\|)
+.NH 2
+Multiplicative operators
+.PP
+The operators *, /, % bind left to right.
+.NH 3
+\fIexpression\fP * \fIexpression\fP
+.PP
+The result is the product
+of the two expressions.
+If \fIa\fP and \fIb\fP are the
+scales of the two expressions,
+then the scale of the result is:
+.PP
+min\|(\|\fIa+b\fP,\|max\|(\|\fBscale\fP,\|\fIa\fP,\|\fIb\fP\|)\|)
+.NH 3
+\fIexpression\fP / \fIexpression\fP
+.PP
+The result is the quotient of the two expressions.
+The scale of the result is the value of \fBscale\fR.
+.NH 3
+\fIexpression\fP % \fIexpression\fP
+.PP
+The % operator produces the remainder of the division
+of the two expressions.
+More precisely,
+\fIa\fP%\fIb\fP is \fIa\fP\-\fIa\fP/\fIb\fP*\fIb\fP.
+.PP
+The scale of the result is the sum of the scale of
+the divisor and the value of
+.ft B
+scale
+.ft
+.NH 2
+Additive operators
+.PP
+The additive operators bind left to right.
+.NH 3
+\fIexpression\fP + \fIexpression\fP
+.PP
+The result is the sum of the two expressions.
+The scale of the result is
+the maximum of the scales of the expressions.
+.NH 3
+\fIexpression\fP \- \fIexpression\fP
+.PP
+The result is the difference of the two expressions.
+The scale of the result is the
+maximum of the scales of the expressions.
+.NH 2
+assignment operators
+.PP
+The assignment operators bind right to left.
+.NH 3
+\fInamed-expression\fP = \fIexpression\fP
+.PP
+This expression results in assigning the value of the expression
+on the right
+to the named expression on the left.
+.NH 3
+\fInamed-expression\fP += \fIexpression\fP
+.NH 3
+\fInamed-expression\fP \-= \fIexpression\fP
+.NH 3
+\fInamed-expression\fP *= \fIexpression\fP
+.NH 3
+\fInamed-expression\fP /= \fIexpression\fP
+.NH 3
+\fInamed-expression\fP %= \fIexpression\fP
+.NH 3
+\fInamed-expression\fP ^= \fIexpression\fP
+.PP
+The result of the above expressions is equivalent
+to ``named expression = named expression OP expression'',
+where OP is the operator after the = sign.
+.NH 1
+Relations
+.PP
+Unlike all other operators, the relational operators
+are only valid as the object of an \fBif\fP, \fBwhile\fP,
+or inside a \fBfor\fP statement.
+.NH 2
+\fIexpression\fP < \fIexpression\fP
+.NH 2
+\fIexpression\fP > \fIexpression\fP
+.NH 2
+\fIexpression\fP <= \fIexpression\fP
+.NH 2
+\fIexpression\fP >= \fIexpression\fP
+.NH 2
+\fIexpression\fP == \fIexpression\fP
+.NH 2
+\fIexpression\fP != \fIexpression\fP
+.NH 1
+Storage classes
+.PP
+There are only two storage classes in BC, global and automatic
+(local).
+Only identifiers that are to be local to a function need be
+declared with the \fBauto\fP command.
+The arguments to a function
+are local to the function.
+All other identifiers are assumed to be global
+and available to all functions.
+All identifiers, global and local, have initial values
+of zero.
+Identifiers declared as \fBauto\fP are allocated on entry to the function
+and released on returning from the function.
+They therefore do not retain values between function calls.
+\fBauto\fP arrays are specified by the array name followed by empty square brackets.
+.PP
+Automatic variables in BC do not work in exactly the same way
+as in either C or PL/I. On entry to a function, the old values of
+the names that appear as parameters and as automatic
+variables are pushed onto a stack.
+Until return is made from the function, reference to these
+names refers only to the new values.
+.NH 1
+Statements
+.PP
+Statements must be separated by semicolon or newline.
+Except where altered by control statements, execution
+is sequential.
+.NH 2
+Expression statements
+.PP
+When a statement is an expression, unless
+the main operator is an assignment, the value
+of the expression is printed, followed by a newline character.
+.NH 2
+Compound statements
+.PP
+Statements may be grouped together and used when one statement is expected
+by surrounding them with { }.
+.NH 2
+Quoted string statements
+.PP
+"any string"
+.sp .5
+This statement prints the string inside the quotes.
+.NH 2
+If statements
+.sp .5
+\fBif\|(\|\fIrelation\fB\|)\|\fIstatement\fR
+.PP
+The substatement is executed if the relation is true.
+.NH 2
+If-else statements
+.sp .5
+\fBif\|(\|\fIrelation\fB\|)\|\fIstatement\fB\|else\|\fIstatement\fR
+.PP
+The first substatement is executed if the relation is true, the second
+substatement if the relation is false.
+The \fBif-else\fR statement is a non-portable extension.
+.NH 2
+While statements
+.sp .5
+\fBwhile\|(\|\fIrelation\fB\|)\|\fIstatement\fR
+.PP
+The statement is executed while the relation
+is true.
+The test occurs before each execution of the statement.
+.NH 2
+For statements
+.sp .5
+\fBfor\|(\|\fIexpression\fB; \fIrelation\fB; \fIexpression\fB\|)\|\fIstatement\fR
+.PP
+The \fBfor\fR statement is the same as
+.nf
+.ft I
+ first-expression
+ \fBwhile\|(\fPrelation\|\fB) {\fP
+ statement
+ last-expression
+ }
+.ft R
+.fi
+.PP
+All three expressions may be left out.
+This is a non-portable extension.
+.NH 2
+Break statements
+.sp .5
+\fBbreak\fP
+.PP
+\fBbreak\fP causes termination of a \fBfor\fP or \fBwhile\fP statement.
+.NH 2
+Continue statements
+.sp .5
+\fBcontinue\fP
+.PP
+\fBcontinue\fP causes the next iteration of a \fBfor\fP or \fBwhile\fP
+statement to start, skipping the remainder of the loop.
+For a \fBwhile\fP statement, execution continues with the evaluation
+of the condition.
+For a \fBfor\fP statement, execution continues with evaluation of
+the last-expression.
+The \fBcontinue\fP statement is a non-portable extension.
+.NH 2
+Auto statements
+.sp .5
+\fBauto \fIidentifier\fR\|[\|\fB,\fIidentifier\fR\|]
+.PP
+The \fBauto\fR statement causes the values of the identifiers to be pushed down.
+The identifiers can be ordinary identifiers or array identifiers.
+Array identifiers are specified by following the array name by empty square
+brackets.
+The auto statement must be the first statement
+in a function definition.
+.NH 2
+Define statements
+.sp .5
+.nf
+\fBdefine(\|\fR[\fIparameter\|\fR[\fB\|,\|\fIparameter\|.\|.\|.\|\fR]\|]\|\fB)\|{\fI
+ statements\|\fB}\fR
+.fi
+.PP
+The \fBdefine\fR statement defines a function.
+The parameters may
+be ordinary identifiers or array names.
+Array names must be followed by empty square brackets.
+As a non-portable extension, the opening brace may also appear on the
+next line.
+.NH 2
+Return statements
+.sp .5
+\fBreturn\fP
+.sp .5
+\fBreturn(\fI\|expression\|\fB)\fR
+.PP
+The \fBreturn\fR statement causes termination of a function,
+popping of its auto variables, and
+specifies the result of the function.
+The first form is equivalent to \fBreturn(0)\fR.
+The result of the function is the result of the expression
+in parentheses.
+Leaving out the expression between parentheses is equivalent to
+\fBreturn(0)\fR.
+As a non-portable extension, the parentheses may be left out.
+.NH 2
+Print
+.PP
+The \fBprint\fR statement takes a list of comma-separated expressions.
+Each expression in the list is evaluated and the computed
+value is printed and assigned to the variable `last'.
+No trailing newline is printed.
+The expression may also be a string enclosed in double quotes.
+Within these strings the following escape sequences may be used:
+\ea
+for bell (alert),
+`\eb'
+for backspace,
+`\ef'
+for formfeed,
+`\en'
+for newline,
+`\er'
+for carriage return,
+`\et'
+`for tab,
+`\eq'
+for double quote and
+`\e\e'
+for backslash.
+Any other character following a backslash will be ignored.
+Strings will not be assigned to `last'.
+The \fBprint\fR statement is a non-portable extension.
+.NH 2
+Quit
+.PP
+The \fBquit\fR statement stops execution of a BC program and returns
+control to UNIX when it is first encountered.
+Because it is not treated as an executable statement,
+it cannot be used
+in a function definition or in an
+.ft B
+if, for,
+.ft
+or
+.ft B
+while
+.ft
+statement.
diff --git a/share/doc/usd/07.mail/Makefile b/share/doc/usd/07.mail/Makefile
index d5a6d3c..790aa96 100644
--- a/share/doc/usd/07.mail/Makefile
+++ b/share/doc/usd/07.mail/Makefile
@@ -6,6 +6,5 @@ SRCS= mail0.nr mail1.nr mail2.nr mail3.nr mail4.nr mail5.nr mail6.nr \
mail7.nr mail8.nr mail9.nr maila.nr
MACROS= -me
USE_TBL=
-SRCDIR= ${.CURDIR}/../../../../usr.bin/mail/USD.doc
.include <bsd.doc.mk>
diff --git a/share/doc/usd/07.mail/mail0.nr b/share/doc/usd/07.mail/mail0.nr
new file mode 100644
index 0000000..e569a5f
--- /dev/null
+++ b/share/doc/usd/07.mail/mail0.nr
@@ -0,0 +1,72 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mail0.nr 8.1 (Berkeley) 6/8/93
+.\"
+.\" $FreeBSD$
+.\"
+.eh 'USD:7-%''Mail Reference Manual'
+.oh 'Mail Reference Manual''USD:7-%'
+.if n \
+.nr fs .5v
+.\".he 'Mail Reference Manual'\n(mo/\n(dy/\n(yr'%'
+.tp
+.sp 1.0i
+.sz 12
+.rb
+.(l C
+MAIL REFERENCE MANUAL
+.)l
+.sz 10
+.sp 2
+.i
+.(l C
+Kurt Shoens
+.)l
+.r
+.(l C
+Revised by
+.)l
+.(l C
+.i
+Craig Leres\ \c
+.r
+and\ \c
+.i
+Mark Andrews
+.)l
+.r
+.(l C
+Version 5.5
+
+
+.)l
+.pn 2
diff --git a/share/doc/usd/07.mail/mail1.nr b/share/doc/usd/07.mail/mail1.nr
new file mode 100644
index 0000000..50e7883
--- /dev/null
+++ b/share/doc/usd/07.mail/mail1.nr
@@ -0,0 +1,92 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mail1.nr 8.1 (Berkeley) 6/8/93
+.\"
+.sh 1 Introduction
+.pp
+.i Mail
+provides a simple and friendly environment for sending and receiving mail.
+It divides incoming mail into
+its constituent messages and allows the user to deal with them
+in any order. In addition, it provides a set of
+.i ed -\c
+like commands for manipulating messages and sending mail.
+.i Mail
+offers the user simple editing capabilities to ease the composition
+of outgoing messages, as well as providing the ability to define and send
+to names which address groups of users. Finally,
+.i Mail
+is able to send and receive messages across such networks as the
+ARPANET, UUCP, and Berkeley network.
+.pp
+This document describes how to use the
+.i Mail
+program to send and receive messages. The reader is not assumed to
+be familiar with other message handling systems, but should be
+familiar with the \s-2UNIX\s0\**
+.(f
+\** \s-1UNIX\s0 is a trademark of Bell Laboratories.
+.)f
+shell, the text editor, and some of the common \s-2UNIX\s0 commands.
+.q "The \s-2UNIX\s0 Programmer's Manual,"
+.q "An Introduction to Csh,"
+and
+.q "Text Editing with Ex and Vi"
+can be consulted for more information on these topics.
+.pp
+Here is how messages are handled:
+the mail system accepts incoming
+.i messages
+for you from other people
+and collects them in a file, called your
+.i "system mailbox" .
+When you login, the system notifies you if there are any messages
+waiting in your system mailbox. If you are a
+.i csh
+user, you will be notified when new mail arrives if you inform
+the shell of the location of your mailbox. On version 7 systems,
+your system mailbox is located in the directory /var/mail
+in a file with your login name. If your login name is
+.q sam,
+then you can make
+.i csh
+notify you of new mail by including the following line in your .cshrc
+file:
+.(l
+set mail=/var/mail/sam
+.)l
+When you read your mail using
+.i Mail ,
+it reads your system mailbox and separates that file into the
+individual messages that have been sent to you. You can then
+read, reply to, delete, or save these messages.
+Each message is marked with its author and the date they sent it.
diff --git a/share/doc/usd/07.mail/mail2.nr b/share/doc/usd/07.mail/mail2.nr
new file mode 100644
index 0000000..0419859
--- /dev/null
+++ b/share/doc/usd/07.mail/mail2.nr
@@ -0,0 +1,617 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mail2.nr 8.1 (Berkeley) 6/8/93
+.\"
+.bp
+.sh 1 "Common usage"
+.pp
+The
+.i Mail
+command has two distinct usages, according to whether one
+wants to send or receive mail. Sending mail is simple: to send a
+message to a user whose login name is, say,
+\*(lqroot,\*(rq
+use the shell
+command:
+.(l
+% Mail root
+.)l
+then type your message. When you reach the end of the message, type
+an EOT (control\-d) at the beginning of a line, which will cause
+.i Mail
+to echo \*(lqEOT\*(rq and return you to the Shell. When the user you sent mail
+to next logs in, he will receive the message:
+.(l
+You have mail.
+.)l
+to alert him to the existence of your message.
+.pp
+If, while you are composing the message
+you decide that you do not wish to send it after all, you can
+abort the letter with a \s-2RUBOUT\s0. Typing a single \s-2RUBOUT\s0
+causes
+.i Mail
+to print
+.(l
+(Interrupt -- one more to kill letter)
+.)l
+Typing a second
+\s-2RUBOUT\s0 causes
+.i Mail
+to save your partial letter on the file
+.q dead.letter
+in your home directory and abort the letter.
+Once you have
+sent mail to someone, there is no way to undo the act, so be
+careful.
+.pp
+The message your recipient reads will consist of the message you
+typed, preceded by a line telling who sent the message (your login name)
+and the date and time it
+was sent.
+.pp
+If you want to send the same message to several other people, you can list
+their login names on the command line.
+Thus,
+.(l
+% Mail sam bob john
+Tuition fees are due next Friday. Don't forget!!
+<Control\-d>
+EOT
+%
+.)l
+will send the reminder to sam, bob, and john.
+.pp
+If, when you log in, you see the message,
+.(l
+You have mail.
+.)l
+you can read the mail by typing simply:
+.(l
+% Mail
+.)l
+.i Mail
+will respond by typing its version number and date and then listing
+the messages you have waiting. Then it will type a prompt and await
+your command. The messages are assigned numbers starting with 1 \*- you
+refer to the messages with these numbers.
+.i Mail
+keeps track of which messages are
+.i new
+(have been sent since you last read your mail) and
+.i read
+(have been read by you). New messages have an
+.b N
+next to them in the header listing and old, but unread messages have
+a
+.b U
+next to them.
+.i Mail
+keeps track of new/old and read/unread messages by putting a
+header field called
+.q Status
+into your messages.
+.pp
+To look at a specific message, use the
+.b type
+command, which may be abbreviated to simply
+.b t .
+For example, if you had the following messages:
+.(l
+N 1 root Wed Sep 21 09:21 "Tuition fees"
+N 2 sam Tue Sep 20 22:55
+.)l
+you could examine the first message by giving the command:
+.(l
+type 1
+.)l
+which might cause
+.i Mail
+to respond with, for example:
+.(l
+Message 1:
+From root Wed Sep 21 09:21:45 1978
+Subject: Tuition fees
+Status: R
+
+Tuition fees are due next Wednesday. Don't forget!!
+
+.)l
+Many
+.i Mail
+commands that operate on messages take a message number as an
+argument like the
+.b type
+command. For these commands, there is a notion of a current
+message. When you enter the
+.i Mail
+program, the current message is initially the first one. Thus,
+you can often omit the message number and use, for example,
+.(l
+t
+.)l
+to type the current message. As a further shorthand, you can type a message
+by simply giving its message number. Hence,
+.(l
+1
+.)l
+would type the first message.
+.pp
+Frequently, it is useful to read the messages in your mailbox in order,
+one after another. You can read the next message in
+.i Mail
+by simply typing a newline. As a special case, you can type a newline
+as your first command to
+.i Mail
+to type the first message.
+.pp
+If, after typing a message, you wish to immediately send a reply,
+you can do so with the
+.b reply
+command.
+.b Reply ,
+like
+.b type ,
+takes a message number as an argument.
+.i Mail
+then begins a message addressed to the user who sent you the message.
+You may then type in your letter in reply, followed by a <control-d>
+at the beginning of a line, as before.
+.i Mail
+will type EOT, then type the ampersand prompt to indicate its readiness
+to accept another command. In our example, if, after typing the
+first message, you wished to reply to it, you might give the command:
+.(l
+reply
+.)l
+.i Mail
+responds by typing:
+.(l
+To: root
+Subject: Re: Tuition fees
+.)l
+and waiting for you to enter your letter.
+You are now in the message collection mode described at the beginning
+of this section and
+.i Mail
+will gather up your message up to a control\-d.
+Note that it copies the subject
+header from the original message. This is useful in that correspondence
+about a particular matter will tend to retain the same subject heading,
+making it easy to recognize. If there are other header fields in
+the message, the information found will also be used.
+For example, if the letter had a
+.q "To:"
+header listing several recipients,
+.i Mail
+would arrange to send your replay to the same people as well.
+Similarly, if the original message contained a
+.q "Cc:"
+(carbon copies to) field,
+.i Mail
+would send your reply to
+.i those
+users, too.
+.i Mail
+is careful, though, not too send the message to
+.i you ,
+even if you appear in the
+.q "To:"
+or
+.q "Cc:"
+field, unless you ask to be included explicitly. See section 4 for more
+details.
+.pp
+After typing in your letter, the dialog with
+.i Mail
+might look like the following:
+.(l
+reply
+To: root
+Subject: Tuition fees
+
+Thanks for the reminder
+EOT
+&
+.)l
+.pp
+The
+.b reply
+command is especially useful for sustaining extended conversations
+over the message system, with other
+.q listening
+users receiving copies of the conversation. The
+.b reply
+command can be abbreviated to
+.b r .
+.pp
+Sometimes you will receive a message that has been sent to
+several people and wish to reply
+.i only
+to the person who sent it.
+.b Reply
+with a capital
+.b R
+replies to a message, but sends a copy to the sender only.
+.pp
+If you wish, while reading your mail, to send a message to someone,
+but not as a reply to one of your messages, you can send the message
+directly with the
+.b mail
+command, which takes as arguments the names of the recipients you wish
+to send to. For example, to send a message to
+.q frank,
+you would do:
+.(l
+mail frank
+This is to confirm our meeting next Friday at 4.
+EOT
+&
+.)l
+The
+.b mail
+command can be abbreviated to
+.b m .
+.pp
+Normally, each message you receive is saved in the file
+.i mbox
+in your login directory at the time you leave
+.i Mail .
+Often,
+however, you will not want to save a particular message you
+have received because it is only of passing interest. To avoid
+saving a message in
+.i mbox
+you can delete it using the
+.b delete
+command. In our example,
+.(l
+delete 1
+.)l
+will prevent
+.i Mail
+from saving message 1 (from root) in
+.i mbox .
+In addition to not saving deleted messages,
+.i Mail
+will not let
+you type them, either. The effect is to make the message disappear
+altogether, along with its number. The
+.b delete
+command can be abbreviated to simply
+.b d .
+.pp
+Many features of
+.i Mail
+can be tailored to your liking with the
+.b set
+command. The
+.b set
+command has two forms, depending on whether you are setting
+a
+.i binary
+option or a
+.i valued
+option.
+Binary options are either on or off. For example, the
+.q ask
+option informs
+.i Mail
+that each time you send a message, you want it to prompt you for
+a subject header, to be included in the message.
+To set the
+.q ask
+option, you would type
+.(l
+set ask
+.)l
+.pp
+Another useful
+.i Mail
+option is
+.q hold.
+Unless told otherwise,
+.i Mail
+moves the messages from your system mailbox to the file
+.i mbox
+in your home directory when you leave
+.i Mail .
+If you want
+.i Mail
+to keep your letters in the system mailbox instead, you can set the
+.q hold
+option.
+.pp
+Valued options are values which
+.i Mail
+uses to adapt to your tastes. For example, the
+.q SHELL
+option tells
+.i Mail
+which shell you like to use, and is specified by
+.(l
+set SHELL=/bin/csh
+.)l
+for example. Note that no spaces are allowed in
+.q "SHELL=/bin/csh."
+A complete list of the
+.i Mail
+options appears in section 5.
+.pp
+Another important valued option is
+.q crt.
+If you use a fast video terminal, you will find that when you
+print long messages, they fly by too quickly for you to read them.
+With the
+.q crt
+option, you can make
+.i Mail
+print any message larger than a given number of lines by sending
+it through a paging program. This program is specified by the
+valued option \fBPAGER\fP.
+If \fBPAGER\fP is not set, a default paginator is used.
+For example, most CRT users with 24-line screens should do:
+.(l
+set crt=24
+.)l
+to paginate messages that will not fit on their screens.
+In the default state, \fImore\fP (default paginator) prints a screenful of
+information, then types --More--. Type a space to see the next screenful.
+.pp
+Another adaptation to user needs that
+.i Mail
+provides is that of
+.i aliases .
+An alias is simply a name which stands for one or more
+real user names.
+.i Mail
+sent to an alias is really sent to the list of real users
+associated with it. For example, an alias can be defined for the
+members of a project, so that you can send mail to the whole project
+by sending mail to just a single name. The
+.b alias
+command in
+.i Mail
+defines an alias. Suppose that the users in a project are
+named Sam, Sally, Steve, and Susan. To define an alias called
+.q project
+for them, you would use the
+.i Mail
+command:
+.(l
+alias project sam sally steve susan
+.)l
+The
+.b alias
+command can also be used to provide a convenient name for someone
+whose user name is inconvenient. For example, if a user named
+.q "Bob Anderson"
+had the login name
+.q anderson,"
+you might want to use:
+.(l
+alias bob anderson
+.)l
+so that you could send mail to the shorter name,
+.q bob.
+.pp
+While the
+.b alias
+and
+.b set
+commands allow you to customize
+.i Mail ,
+they have the drawback that they must be retyped each time you enter
+.i Mail .
+To make them more convenient to use,
+.i Mail
+always looks for two files when it is invoked. It first reads
+a system wide file
+.q /etc/mail.rc,
+then a user specific file,
+.q .mailrc,
+which is found in the user's home directory.
+The system wide file
+is maintained by the system administrator and
+contains
+.b set
+commands that are applicable to all users of the system.
+The
+.q .mailrc
+file is usually used by each user to set options the way he likes
+and define individual aliases.
+For example, my .mailrc file looks like this:
+.(l
+set ask nosave SHELL=/bin/csh
+.)l
+As you can see, it is possible to set many options in the
+same
+.b set
+command. The
+.q nosave
+option is described in section 5.
+.pp
+Mail aliasing is implemented
+at the system-wide level
+by the mail delivery
+system
+.i sendmail .
+These aliases are stored in the file /usr/lib/aliases and are
+accessible to all users of the system.
+The lines in /usr/lib/aliases are of
+the form:
+.(l
+alias: name\*<1\*>, name\*<2\*>, name\*<3\*>
+.)l
+where
+.i alias
+is the mailing list name and the
+.i name\*<i\*>
+are the members of the list. Long lists can be continued onto the next
+line by starting the next line with a space or tab. Remember that you
+must execute the shell command
+.i newaliases
+after editing /usr/lib/aliases since the delivery system
+uses an indexed file created by
+.i newaliases .
+.pp
+We have seen that
+.i Mail
+can be invoked with command line arguments which are people
+to send the message to, or with no arguments to read mail.
+Specifying the
+.rb \-f
+flag on the command line causes
+.i Mail
+to read messages from a file other than your system mailbox.
+For example, if you have a collection of messages in
+the file
+.q letters
+you can use
+.i Mail
+to read them with:
+.(l
+% Mail \-f letters
+.)l
+You can use all
+the
+.i Mail
+commands described in this document to examine, modify, or delete
+messages from your
+.q letters
+file, which will be rewritten when you leave
+.i Mail
+with the
+.b quit
+command described below.
+.pp
+Since mail that you read is saved in the file
+.i mbox
+in your home directory by default, you can read
+.i mbox
+in your home directory by using simply
+.(l
+% Mail \-f
+.)l
+.pp
+Normally, messages that you examine using the
+.b type
+command are saved in the file
+.q mbox
+in your home directory if you leave
+.i Mail
+with the
+.b quit
+command described below.
+If you wish to retain a message in your system mailbox
+you can use the
+.b preserve
+command to tell
+.i Mail
+to leave it there.
+The
+.b preserve
+command accepts a list of message numbers, just like
+.b type
+and may be abbreviated to
+.b pre .
+.pp
+Messages in your system mailbox that you do not examine are
+normally retained in your system mailbox automatically.
+If you wish to have such a message saved in
+.i mbox
+without reading it, you may use the
+.b mbox
+command to have them so saved. For example,
+.(l
+mbox 2
+.)l
+in our example would cause the second message (from sam)
+to be saved in
+.i mbox
+when the
+.b quit
+command is executed.
+.b Mbox
+is also the way to direct messages to your
+.i mbox
+file if you have set the
+.q hold
+option described above.
+.b Mbox
+can be abbreviated to
+.b mb .
+.pp
+When you have perused all the messages of interest, you can leave
+.i Mail
+with the
+.b quit
+command, which saves the messages you have typed but not
+deleted in the file
+.i mbox
+in your login directory. Deleted messages are discarded irretrievably,
+and messages left untouched are preserved in your system mailbox so
+that you will see them the next time you type:
+.(l
+% Mail
+.)l
+The
+.b quit
+command can be abbreviated to simply
+.b q .
+.pp
+If you wish for some reason to leave
+.i Mail
+quickly without altering either your system mailbox or
+.i mbox ,
+you can type the
+.b x
+command (short for
+.b exit ),
+which will immediately return you to the Shell without changing anything.
+.pp
+If, instead, you want to execute a Shell command without leaving
+.i Mail ,
+you
+can type the command preceded by an exclamation point, just as in the
+text editor. Thus, for instance:
+.(l
+!date
+.)l
+will print the current date without leaving
+.i Mail .
+.pp
+Finally, the
+.b help
+command is available to print out a brief summary of the
+.i Mail
+commands, using only the single character command abbreviations.
diff --git a/share/doc/usd/07.mail/mail3.nr b/share/doc/usd/07.mail/mail3.nr
new file mode 100644
index 0000000..8b133ef
--- /dev/null
+++ b/share/doc/usd/07.mail/mail3.nr
@@ -0,0 +1,133 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mail3.nr 8.1 (Berkeley) 6/8/93
+.\"
+.sh 1 "Maintaining folders"
+.pp
+.i Mail
+includes a simple facility for maintaining groups of messages together
+in folders. This section describes this facility.
+.pp
+To use the folder facility, you must tell
+.i Mail
+where you wish to keep your folders. Each folder of messages will
+be a single file. For convenience, all of your folders are kept in
+a single directory of your choosing. To tell
+.i Mail
+where your folder directory is, put a line of the form
+.(l
+set folder=letters
+.)l
+in your
+.i .mailrc
+file. If, as in the example above, your folder directory does not
+begin with a `/,'
+.i Mail
+will assume that your folder directory is to be found starting from
+your home directory. Thus, if your home directory is
+.b /home/person
+the above example told
+.i Mail
+to find your folder directory in
+.b /home/person/letters .
+.pp
+Anywhere a file name is expected, you can use a folder name, preceded
+with `+.' For example, to put a message into a folder with the
+.b save
+command, you can use:
+.(l
+save +classwork
+.)l
+to save the current message in the
+.i classwork
+folder. If the
+.i classwork
+folder does not yet exist, it will be created. Note that messages
+which are saved with the
+.b save
+command are automatically removed from your system mailbox.
+.pp
+In order to make a copy of a message in a folder without causing
+that message to be removed from your system mailbox, use the
+.b copy
+command, which is identical in all other respects to the
+.b save
+command. For example,
+.(l
+copy +classwork
+.)l
+copies the current message into the
+.i classwork
+folder and leaves a copy in your system mailbox.
+.pp
+The
+.b folder
+command
+can be used to direct
+.i Mail
+to the contents of a different folder.
+For example,
+.(l
+folder +classwork
+.)l
+directs
+.i Mail
+to read the contents of the
+.i classwork
+folder. All of the commands that you can use on your system
+mailbox are also applicable to folders, including
+.b type ,
+.b delete ,
+and
+.b reply .
+To inquire which folder you are currently editing, use simply:
+.(l
+folder
+.)l
+.pp
+To list your current set of folders, use the
+.b folders
+command.
+.pp
+To start
+.i Mail
+reading one of your folders, you can use the
+.b \-f
+option described in section 2. For example:
+.(l
+% Mail \-f +classwork
+.)l
+will cause
+.i Mail
+to read your
+.i classwork
+folder without looking at your system mailbox.
diff --git a/share/doc/usd/07.mail/mail4.nr b/share/doc/usd/07.mail/mail4.nr
new file mode 100644
index 0000000..1a1e046
--- /dev/null
+++ b/share/doc/usd/07.mail/mail4.nr
@@ -0,0 +1,437 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mail4.nr 8.1 (Berkeley) 6/8/93
+.\"
+.bp
+.sh 1 "More about sending mail"
+.sh 2 "Tilde escapes"
+.pp
+While typing in a message to be sent to others, it is often
+useful to be able to invoke the text editor on the partial message,
+print the message, execute a shell command, or do some other
+auxiliary function.
+.i Mail
+provides these capabilities through
+.i "tilde escapes" ,
+which consist of a tilde (~) at the beginning of a line, followed by
+a single character which indicates the function to be performed. For
+example, to print the text of the message so far, use:
+.(l
+~p
+.)l
+which will print a line of dashes, the recipients of your message, and
+the text of the message so far.
+Since
+.i Mail
+requires two consecutive \s-2RUBOUT\s0's to abort a letter, you
+can use a single \s-2RUBOUT\s0 to abort the output of ~p or any other
+~ escape without killing your letter.
+.pp
+If you are dissatisfied with the message as
+it stands, you can invoke the text editor on it using the escape
+.(l
+~e
+.)l
+which causes the message to be copied into a temporary file and an
+instance of the editor to be spawned. After modifying the message to
+your satisfaction, write it out and quit the editor.
+.i Mail
+will respond
+by typing
+.(l
+(continue)
+.)l
+after which you may continue typing text which will be appended to your
+message, or type <control-d> to end the message.
+A standard text editor is provided by
+.i Mail .
+You can override this default by setting the valued option
+.q EDITOR
+to something else. For example, you might prefer:
+.(l
+set EDITOR=/usr/bin/ex
+.)l
+.pp
+Many systems offer a screen editor as an alternative to the standard
+text editor, such as the
+.i vi
+editor from UC Berkeley.
+To use the screen, or
+.i visual
+editor, on your current message, you can use the escape,
+.(l
+~v
+.)l
+~v works like ~e, except that the screen editor is invoked instead.
+A default screen editor is defined by
+.i Mail .
+If it does not suit you, you can set the valued option
+.q VISUAL
+to the path name of a different editor.
+.pp
+It is often useful to be able to include the contents of some
+file in your message; the escape
+.(l
+~r filename
+.)l
+is provided for this purpose, and causes the named file to be appended
+to your current message.
+.i Mail
+complains if the file doesn't exist
+or can't be read. If the read is successful, the number of lines and
+characters appended to your message is printed, after which you may continue
+appending text. The filename may contain shell metacharacters like * and ?
+which are expanded according to the conventions of your shell.
+.pp
+As a special case of ~r, the escape
+.(l
+~d
+.)l
+reads in the file
+.q dead.letter
+in your home directory. This is often useful since
+.i Mail
+copies the text
+of your message there when you abort a message with \s-2RUBOUT\s0.
+.pp
+To save the current text of your message on a file you may use the
+.(l
+~w filename
+.)l
+escape.
+.i Mail
+will print out the number of lines and characters written
+to the file, after which you may continue appending text to your message.
+Shell metacharacters may be used in the filename, as in ~r and are expanded
+with the conventions of your shell.
+.pp
+If you are sending mail from within
+.i Mail's
+command mode
+you can read a message sent to you into the message
+you are constructing with the escape:
+.(l
+~m 4
+.)l
+which will read message 4 into the current message, shifted right by
+one tab stop. You can name any non-deleted message, or list of messages.
+Messages can also be forwarded without shifting by a tab stop with ~f.
+This is the usual way to forward a message.
+.pp
+If, in the process of composing a message, you decide to add additional
+people to the list of message recipients, you can do so with the escape
+.(l
+~t name1 name2 ...
+.)l
+You may name as few or many additional recipients as you wish. Note
+that the users originally on the recipient list will still receive
+the message; you cannot remove someone from the recipient
+list with ~t.
+.pp
+If you wish, you can associate a subject with your message by using the
+escape
+.(l
+~s Arbitrary string of text
+.)l
+which replaces any previous subject with
+.q "Arbitrary string of text."
+The subject, if given, is sent near the
+top of the message prefixed with
+.q "Subject:"
+You can see what the message will look like by using ~p.
+.pp
+For political reasons, one occasionally prefers to list certain
+people as recipients of carbon copies of a message rather than
+direct recipients. The escape
+.(l
+~c name1 name2 ...
+.)l
+adds the named people to the
+.q "Cc:"
+list, similar to ~t.
+Again, you can execute ~p to see what the message will look like.
+.pp
+The escape
+.(l
+~b name1 name2 ...
+.)l
+adds the named people to the
+.q "Cc:"
+list, but does not make the names visible in the
+.q "Cc:"
+line ("blind" carbon copy).
+.pp
+The recipients of the message together constitute the
+.q "To:"
+field, the subject the
+.q "Subject:"
+field, and the carbon copies the
+.q "Cc:"
+field. If you wish to edit these in ways impossible with the ~t, ~s, ~c
+and ~b escapes, you can use the escape
+.(l
+~h
+.)l
+which prints
+.q "To:"
+followed by the current list of recipients and leaves the cursor
+(or printhead) at the end of the line. If you type in ordinary
+characters, they are appended to the end of the current list of
+recipients. You can also use your erase character to erase back into
+the list of recipients, or your kill character to erase them altogether.
+Thus, for example, if your erase and kill characters are the standard
+(on printing terminals) # and @ symbols,
+.(l
+~h
+To: root kurt####bill
+.)l
+would change the initial recipients
+.q "root kurt"
+to
+.q "root bill."
+When you type a newline,
+.i Mail
+advances to the
+.q "Subject:"
+field, where the same rules apply. Another newline brings you to
+the
+.q "Cc:"
+field, which may be edited in the same fashion. Another newline
+brings you to the
+.q "Bcc:"
+("blind" carbon copy) field, which follows the same rules as the "Cc:"
+field. Another newline
+leaves you appending text to the end of your message. You can use
+~p to print the current text of the header fields and the body
+of the message.
+.pp
+To effect a temporary escape to the shell, the escape
+.(l
+~!command
+.)l
+is used, which executes
+.i command
+and returns you to mailing mode without altering the text of
+your message. If you wish, instead, to filter the body of your
+message through a shell command, then you can use
+.(l
+~|command
+.)l
+which pipes your message through the command and uses the output
+as the new text of your message. If the command produces no output,
+.i Mail
+assumes that something is amiss and retains the old version
+of your message. A frequently-used filter is the command
+.i fmt ,
+designed to format outgoing mail.
+.pp
+To effect a temporary escape to
+.i Mail
+command mode instead, you can use the
+.(l
+~:\fIMail command\fP
+.)l
+escape. This is especially useful for retyping the message you are
+replying to, using, for example:
+.(l
+~:t
+.)l
+It is also useful for setting options and modifying aliases.
+.pp
+If you wish abort the current message, you can use the escape
+.(l
+~q
+.)l
+This will terminate the current message and return you to the
+shell (or \fIMail\fP if you were using the \fBmail\fP command).
+If the \fBsave\fP option is set, the message will be copied
+to the file
+.q dead.letter
+in your home directory.
+.pp
+If you wish (for some reason) to send a message that contains
+a line beginning with a tilde, you must double it. Thus, for example,
+.(l
+~~This line begins with a tilde.
+.)l
+sends the line
+.(l
+~This line begins with a tilde.
+.)l
+.pp
+Finally, the escape
+.(l
+~?
+.)l
+prints out a brief summary of the available tilde escapes.
+.pp
+On some terminals (particularly ones with no lower case)
+tilde's are difficult to type.
+.i Mail
+allows you to change the escape character with the
+.q escape
+option. For example, I set
+.(l
+set escape=]
+.)l
+and use a right bracket instead of a tilde. If I ever need to
+send a line beginning with right bracket, I double it, just as for ~.
+Changing the escape character removes the special meaning of ~.
+.sh 2 "Network access"
+.pp
+This section describes how to send mail to people on other machines.
+Recall that sending to a plain login name sends mail to that person
+on your machine. If your machine is directly (or sometimes, even,
+indirectly) connected to the Arpanet, you can send messages to people
+on the Arpanet using a name of the form
+.(l
+name@host.domain
+.)l
+where
+.i name
+is the login name of the person you're trying to reach,
+.i host
+is the name of the machine on the Arpanet,
+and
+.i domain
+is the higher-level scope within which the hostname is known, e.g. EDU (for educational
+institutions), COM (for commercial entities), GOV (for governmental agencies),
+ARPA for many other things, BITNET or CSNET for those networks.
+.pp
+If your recipient logs in on a machine connected to yours by
+UUCP (the Bell Laboratories supplied network that communicates
+over telephone lines), sending mail can be a bit more complicated.
+You must know the list of machines through which your message must
+travel to arrive at his site. So, if his machine is directly connected
+to yours, you can send mail to him using the syntax:
+.(l
+host!name
+.)l
+where, again,
+.i host
+is the name of the machine and
+.i name
+is the login name.
+If your message must go through an intermediary machine first, you
+must use the syntax:
+.(l
+intermediary!host!name
+.)l
+and so on. It is actually a feature of UUCP that the map of all
+the systems in the network is not known anywhere (except where people
+decide to write it down for convenience). Talk to your system administrator
+about good ways to get places; the
+.i uuname
+command will tell you systems whose names are recognized, but not which
+ones are frequently called or well-connected.
+.pp
+When you use the
+.b reply
+command to respond to a letter, there is a problem of figuring out the
+names of the users in the
+.q "To:"
+and
+.q "Cc:"
+lists
+.i "relative to the current machine" .
+If the original letter was sent to you by someone on the local machine,
+then this problem does not exist, but if the message came from a remote
+machine, the problem must be dealt with.
+.i Mail
+uses a heuristic to build the correct name for each user relative
+to the local machine. So, when you
+.b reply
+to remote mail, the names in the
+.q "To:"
+and
+.q "Cc:"
+lists may change somewhat.
+.sh 2 "Special recipients"
+.pp
+As described previously, you can send mail to either user names or
+.b alias
+names. It is also possible to send messages directly to files or to
+programs, using special conventions. If a recipient name has a
+`/' in it or begins with a `+', it is assumed to be the
+path name of a file into which
+to send the message. If the file already exists, the message is
+appended to the end of the file. If you want to name a file in
+your current directory (ie, one for which a `/' would not usually
+be needed) you can precede the name with `./'
+So, to send mail to the file
+.q memo
+in the current directory, you can give the command:
+.(l
+% Mail ./memo
+.)l
+If the name begins with a `+,' it is expanded into the full path name
+of the folder name in your folder directory.
+This ability to send mail to files can be used for a variety of
+purposes, such as maintaining a journal and keeping a record of
+mail sent to a certain group of users. The second example can be
+done automatically by including the full pathname of the record
+file in the
+.b alias
+command for the group. Using our previous
+.b alias
+example, you might give the command:
+.(l
+alias project sam sally steve susan /usr/project/mail_record
+.)l
+Then, all mail sent to "project" would be saved on the file
+.q /usr/project/mail_record
+as well as being sent to the members of the project. This file
+can be examined using
+.i "Mail \-f" .
+.pp
+It is sometimes useful to send mail directly to a program, for
+example one might write a project billboard program and want to access
+it using
+.i Mail .
+To send messages to the billboard program, one can send mail
+to the special name `|billboard' for example.
+.i Mail
+treats recipient names that begin with a `|' as a program to send
+the mail to. An
+.b alias
+can be set up to reference a `|' prefaced name if desired.
+.i Caveats :
+the shell treats `|' specially, so it must be quoted on the command
+line. Also, the `| program' must be presented as a single argument to
+mail. The safest course is to surround the entire name with double
+quotes. This also applies to usage in the
+.b alias
+command. For example, if we wanted to alias `rmsgs' to `rmsgs \-s'
+we would need to say:
+.(l
+alias rmsgs "| rmsgs -s"
+.)l
diff --git a/share/doc/usd/07.mail/mail5.nr b/share/doc/usd/07.mail/mail5.nr
new file mode 100644
index 0000000..10e707c
--- /dev/null
+++ b/share/doc/usd/07.mail/mail5.nr
@@ -0,0 +1,1042 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mail5.nr 8.1 (Berkeley) 6/8/93
+.\" $FreeBSD$
+.\"
+.bp
+.sh 1 "Additional features"
+.pp
+This section describes some additional commands useful for
+reading your mail, setting options, and handling lists of messages.
+.sh 2 "Message lists"
+.pp
+Several
+.i Mail
+commands accept a list of messages as an argument.
+Along with
+.b type
+and
+.b delete ,
+described in section 2,
+there is the
+.b from
+command, which prints the message headers associated with the
+message list passed to it.
+The
+.b from
+command is particularly useful in conjunction with some of the
+message list features described below.
+.pp
+A
+.i "message list"
+consists of a list of message numbers, ranges, and names,
+separated by spaces or tabs. Message numbers may be either
+decimal numbers, which directly specify messages, or one of the
+special characters
+.q \(ua
+.q "."
+or
+.q "$"
+to specify the first relevant, current, or last
+relevant message, respectively.
+.i Relevant
+here means, for most commands
+.q "not deleted"
+and
+.q "deleted"
+for the
+.b undelete
+command.
+.pp
+A range of messages consists of two message numbers (of the form
+described in the previous paragraph) separated by a dash.
+Thus, to print the first four messages, use
+.(l
+type 1\-4
+.)l
+and to print all the messages from the current message to the last
+message, use
+.(l
+type .\-$
+.)l
+.pp
+A
+.i name
+is a user name. The user names given in the message list are
+collected together and each message selected by other means
+is checked to make sure it was sent by one of the named users.
+If the message consists entirely of user names, then every
+message sent by one of those users that is
+.i relevant
+(in the sense described earlier)
+is selected. Thus, to print every message sent to you by
+.q root,
+do
+.(l
+type root
+.)l
+.pp
+As a shorthand notation, you can specify simply
+.q *
+to get every
+.i relevant
+(same sense)
+message. Thus,
+.(l
+type *
+.)l
+prints all undeleted messages,
+.(l
+delete *
+.)l
+deletes all undeleted messages, and
+.(l
+undelete *
+.)l
+undeletes all deleted messages.
+.pp
+You can search for the presence of a word in subject lines with
+.b / .
+For example, to print the headers of all messages that contain the
+word
+.q PASCAL,
+do:
+.(l
+from /pascal
+.)l
+Note that subject searching ignores upper/lower case differences.
+.sh 2 "List of commands"
+.pp
+This section describes all the
+.i Mail
+commands available when
+receiving mail.
+.ip "\fB\-\fP\ \ "
+The
+.rb \-
+command goes to the previous message and prints it. The
+.rb \-
+command may be given a decimal number
+.i n
+as an argument, in which case the
+.i n th
+previous message is gone to and printed.
+.ip "\fB?\fP\ \ "
+Prints a brief summary of commands.
+.ip "\fB!\fP\ \ "
+Used to preface a command to be executed by the shell.
+.ip "\fBPrint\fP\ \ "
+Like
+.b print ,
+but also print out ignored header fields. See also
+\fBprint\fP, \fBignore\fP and \fBretain\fP.
+\fBPrint\fP can be abbreviated to \fBP\fP.
+.ip "\fBReply\fP or \fBRespond\fP\ \ "
+Note the capital \fBR\fP in the name.
+Frame a reply to a one or more messages.
+The reply (or replies if you are using this on multiple messages)
+will be sent ONLY to the person who sent you the message
+(respectively, the set of people who sent the messages you are
+replying to).
+You can
+add people using the \fB~t\fP, \fB~c\fP and \fB~b\fP
+tilde escapes. The subject in your reply is formed by prefacing the
+subject in the original message with
+.q "Re:"
+unless it already began thus.
+If the original message included a
+.q "reply-to"
+header field, the reply will go
+.i only
+to the recipient named by
+.q "reply-to."
+You type in your message using the same conventions available to you
+through the
+.b mail
+command.
+The
+.b Reply
+command is especially useful for replying to messages that were sent
+to enormous distribution groups when you really just want to
+send a message to the originator. Use it often.
+\fBReply\fP (and \fBRespond\fP) can be abbreviated to \fBR\fP.
+.ip "\fBType\fP\ \ "
+Identical to the
+.b Print
+command.
+\fBType\fP can be abbreviated to \fBT\fP.
+.ip "\fBalias\fP\ \ "
+Define a name to stand for a set of other names.
+This is used when you want to send messages to a certain
+group of people and want to avoid retyping their names.
+For example
+.(l
+alias project john sue willie kathryn
+.)l
+creates an alias
+.i project
+which expands to the four people John, Sue, Willie, and Kathryn.
+If no arguments are given, all currently-defined aliases are printed.
+If one argument is given, that alias is printed (if it exists).
+\fBAlias\fP can be abbreviated to \fBa\fP.
+.ip "\fBalternates\fP\ \ "
+If you have accounts on several machines, you may find it convenient
+to use the /usr/lib/aliases on all the machines except one to direct
+your mail to a single account.
+The
+.b alternates
+command is used to inform
+.i Mail
+that each of these other addresses is really
+.i you .
+.i Alternates
+takes a list of user names and remembers that they are all actually you.
+When you
+.b reply
+to messages that were sent to one of these alternate names,
+.i Mail
+will not bother to send a copy of the message to this other address (which
+would simply be directed back to you by the alias mechanism).
+If
+.i alternates
+is given no argument, it lists the current set of alternate names.
+.b Alternates
+is usually used in the .mailrc file.
+\fBAlternates\fP can be abbreviated to \fBalt\fP.
+.ip "\fBchdir\fP\ \ "
+The
+.b chdir
+command allows you to change your current directory.
+.b Chdir
+takes a single argument, which is taken to be the pathname of
+the directory to change to. If no argument is given,
+.b chdir
+changes to your home directory.
+\fBChdir\fP can be abbreviated to \fBc\fP.
+.ip "\fBcopy\fP\ \ "
+The
+.b copy
+command does the same thing that
+.b save
+does, except that it does not mark the messages it is used on
+for deletion when you quit.
+\fBCopy\fP can be abbreviated to \fBco\fP.
+.ip "\fBdelete\fP\ \ "
+Deletes a list of messages. Deleted messages can be reclaimed
+with the
+.b undelete
+command.
+\fBDelete\fP can be abbreviated to \fBd\fP.
+.ip "\fBdp\fP or \fBdt\fP\ \ "
+These
+commands delete the current message and print the next message.
+They are useful for quickly reading and disposing of mail.
+If there is no next message, \fImail\fP says ``at EOF.''
+.ip "\fBedit\fP\ \ "
+To edit individual messages using the text editor, the
+.b edit
+command is provided. The
+.b edit
+command takes a list of messages as described under the
+.b type
+command and processes each by writing it into the file
+Message\c
+.i x
+where
+.i x
+is the message number being edited and executing the text editor on it.
+When you have edited the message to your satisfaction, write the message
+out and quit, upon which
+.i Mail
+will read the message back and remove the file.
+.b Edit
+can be abbreviated to
+.b e .
+.ip "\fBelse\fP\ \ "
+Marks the end of the then-part of an
+.b if
+statement and the beginning of the
+part to take effect if the condition of the
+.b if
+statement is false.
+.ip "\fBendif\fP\ \ "
+Marks the end of an
+.b if
+statement.
+.ip "\fBexit\fP or \fBxit\fP\ \ "
+Leave
+.i Mail
+without updating the system mailbox or the file your were reading.
+Thus, if you accidentally delete several messages, you can use
+.b exit
+to avoid scrambling your mailbox.
+\fBExit\fP can be abbreviated to \fBex\fP or \fBx\fP.
+.ip "\fBfile\fP\ \ "
+The same as
+.b folder .
+\fBFile\fP can be abbreviated to \fBfi\fP.
+.ip "\fBfolders\fP\ \ "
+List the names of the folders in your folder directory.
+.ip "\fBfolder\fP\ \ "
+The
+.b folder
+command switches to a new mail file or folder. With no arguments, it
+tells you which file you are currently reading. If you give
+it an argument, it will write out changes (such as deletions)
+you have made in the current file and read the new file.
+Some special conventions are recognized for the name:
+.(b
+.TS
+center;
+c c
+l a.
+Name Meaning
+_
+# Previous file read
+% Your system mailbox
+%name \fIName\fP's system mailbox
+& Your ~/mbox file
++folder A file in your folder directory
+.TE
+.)b
+\fBFolder\fP can be abbreviated to \fBfo\fP.
+.ip "\fBfrom\fP\ \ "
+The
+.b from
+command takes a list of messages and prints out the header lines for each one;
+hence
+.(l
+from joe
+.)l
+is the easy way to display all the message headers from \*(lqjoe.\*(rq
+\fBFrom\fP can be abbreviated to \fBf\fP.
+.ip "\fBheaders\fP\ \ "
+When you start up
+.i Mail
+to read your mail, it lists the message headers that you have.
+These headers tell you who each message is from, when they were
+received, how many lines and characters each message is, and the
+.q "Subject:"
+header field of each message, if present. In addition,
+.i Mail
+tags the message header of each message that has been the object
+of the
+.b preserve
+command with a
+.q P.
+Messages that have been
+.b saved
+or
+.b written
+are flagged with a
+.q *.
+Finally,
+.b deleted
+messages are not printed at all. If you wish to reprint the current
+list of message headers, you can do so with the
+.b headers
+command. The
+.b headers
+command (and thus the initial header listing)
+only lists the first so many message headers.
+The number of headers listed depends on the speed of your
+terminal.
+This can be overridden by specifying the number of headers you
+want with the
+.i window
+option.
+.i Mail
+maintains a notion of the current
+.q window
+into your messages for the purposes of printing headers.
+Use the
+.b z
+command to move forward and back a window.
+You can move
+.i Mail's
+notion of the current window directly to a particular message by
+using, for example,
+.(l
+headers 40
+.)l
+to move
+.i Mail's
+attention to the messages around message 40.
+If a ``+'' argument is given, then the next screenful of message headers is
+printed, and if a ``\-'' argument is given, the previous screenful of message
+headers is printed.
+\fBHeaders\fP can be abbreviated to \fBh\fP.
+.ip "\fBhelp\fP\ \ "
+Print a brief and usually out of date help message about the commands
+in
+.i Mail .
+The
+.i man
+page for
+.i mail
+is usually more up-to-date than either the help message or this manual.
+It is also a synonym for \fB?\fP.
+.ip "\fBhold\fP\ \ "
+Arrange to hold a list of messages in the system mailbox, instead
+of moving them to the file
+.i mbox
+in your home directory. If you set the binary option
+.i hold ,
+this will happen by default.
+It does not override the \fBdelete\fP command.
+\fBHold\fP can be abbreviated to \fBho\fP.
+.ip "\fBif\fP\ \ "
+Commands in your
+.q .mailrc
+file can be executed conditionally depending on whether you are
+sending or receiving mail with the
+.b if
+command. For example, you can do:
+.(l
+if receive
+ \fIcommands\fP...
+endif
+.)l
+An
+.b else
+form is also available:
+.(l
+if send
+ \fIcommands\fP...
+else
+ \fIcommands\fP...
+endif
+.)l
+Note that the only allowed conditions are
+.b receive
+and
+.b send .
+.ip "\fBignore\fP \ \ "
+.b N.B.:
+.i Ignore
+has been superseded by
+.i retain.
+.br
+Add the list of header fields named to the
+.i "ignore list" .
+Header fields in the ignore list are not printed on your
+terminal when you print a message. This allows you to suppress
+printing of certain machine-generated header fields, such as
+.i Via
+which are not usually of interest. The
+.b Type
+and
+.b Print
+commands can be used to print a message in its entirety, including
+ignored fields.
+If
+.b ignore
+is executed with no arguments, it lists the current set of ignored fields.
+.ip "\fBlist\fP\ \ "
+List the valid
+.i Mail
+commands.
+\fBList\fP can be abbreviated to \fBl\fP.
+.\".ip \fBlocal\fP
+.\"Define a list of local names for this host. This command is useful
+.\"when the host is known by more than one name. Names in the list
+.\"may be qualified be the domain of the host. The first name on the local
+.\"list is the
+.\".i distinguished
+.\"name of the host.
+.\"The names on the local list are used by
+.\".i Mail
+.\"to decide which addresses are local to the host.
+.\"For example:
+.\".(l
+.\"local ucbarpa.BERKELEY.ARPA arpa.BERKELEY.ARPA \\
+.\" arpavax.BERKELEY.ARPA r.BERKELEY.ARPA \\
+.\" ucb-arpa.ARPA
+.\".)l
+.\"From this list we see that
+.\".i "fred@ucbarpa.BERKELEY.ARPA",
+.\".i "harold@arpa.BERKELEY",
+.\"and
+.\".i "larry@r"
+.\"are all addresses of users on the local host.
+.\"The
+.\".b local
+.\"command is usually not used be general users since it is designed for
+.\"local configuration; it is usually found in the file /etc/mail.rc.
+.ip "\fBmail\fP\ \ "
+Send mail to one or more people. If you have the
+.i ask
+option set,
+.i Mail
+will prompt you for a subject to your message. Then you
+can type in your message, using tilde escapes as described in
+section 4 to edit, print, or modify your message. To signal your
+satisfaction with the message and send it, type control-d at the
+beginning of a line, or a . alone on a line if you set the option
+.i dot .
+To abort the message, type two interrupt characters (\s-2RUBOUT\s0
+by default) in a row or use the
+.b ~q
+escape.
+The \fBmail\fP command can be abbreviated to \fBm\fP.
+.ip "\fBmbox\fP\ \ "
+Indicate that a list of messages be sent to
+.i mbox
+in your home directory when you quit. This is the default
+action for messages if you do
+.i not
+have the
+.i hold
+option set.
+.ip "\fBnext\fP or \fB+\fP\ \ "
+The
+.b next
+command goes to the next message and types it. If given a message list,
+.b next
+goes to the first such message and types it. Thus,
+.(l
+next root
+.)l
+goes to the next message sent by
+.q root
+and types it. The
+.b next
+command can be abbreviated to simply a newline, which means that one
+can go to and type a message by simply giving its message number or
+one of the magic characters
+.q "^"
+.q "."
+or
+.q "$".
+Thus,
+.(l
+\&.
+.)l
+prints the current message and
+.(l
+4
+.)l
+prints message 4, as described previously.
+\fBNext\fP can be abbreviated to \fBn\fP.
+.ip "\fBpreserve\fP\ \ "
+Same as
+.b hold .
+Cause a list of messages to be held in your system mailbox when you quit.
+\fBPreserve\fP can be abbreviated to \fBpre\fP.
+.ip "\fBprint\fP\ \ "
+Print the specified messages. If the
+.b crt
+variable is set, messages longer than the number of lines it indicates
+are paged through the command specified by the \fBPAGER\fP variable.
+The \fBprint\fP command can be abbreviated to \fBp\fP.
+.ip "\fBquit\fP\ \ "
+Terminates the session, saving all undeleted, unsaved and unwritten messages
+in the user's \fImbox\fP file in their login directory
+(messages marked as having been read), preserving all
+messages marked with \fBhold\fP or \fBpreserve\fP or never referenced
+in their system mailbox.
+Any messages that were deleted, saved, written or saved to \fImbox\fP are
+removed from their system mailbox.
+If new mail has arrived during the session, the message
+``You have new mail'' is given. If given while editing a mailbox file
+with the \fB\-f\fP flag, then the edit file is rewritten.
+A return to the Shell is effected, unless the rewrite of edit file fails,
+in which case the user can escape with the \fBexit\fP command.
+\fBQuit\fP can be abbreviated to \fBq\fP.
+.ip "\fBreply\fP or \fBrespond\fP\ \ "
+Frame a reply to a single message.
+The reply will be sent to the
+person who sent you the message (to which you are replying), plus all
+the people who received the original message, except you. You can
+add people using the \fB~t\fP, \fB~c\fP and \fB~b\fP
+tilde escapes. The subject in your reply is formed by prefacing the
+subject in the original message with
+.q "Re:"
+unless it already began thus.
+If the original message included a
+.q "reply-to"
+header field, the reply will go
+.i only
+to the recipient named by
+.q "reply-to."
+You type in your message using the same conventions available to you
+through the
+.b mail
+command.
+The \fBreply\fP (and \fBrespond\fP) command can be abbreviated to \fBr\fP.
+.ip "\fBretain\fP\ \ "
+Add the list of header fields named to the \fIretained list\fP.
+Only the header fields in the retain list
+are shown on your terminal when you print a message.
+All other header fields are suppressed.
+The
+.b Type
+and
+.b Print
+commands can be used to print a message in its entirety.
+If
+.b retain
+is executed with no arguments, it lists the current set of
+retained fields.
+.ip "\fBsave\fP\ \ "
+It is often useful to be able to save messages on related topics
+in a file. The
+.b save
+command gives you the ability to do this. The
+.b save
+command takes as an argument a list of message numbers, followed by
+the name of the file in which to save the messages. The messages
+are appended to the named file, thus allowing one to keep several
+messages in the file, stored in the order they were put there.
+The filename in quotes, followed by the line
+count and character count is echoed on the user's terminal.
+An example of the
+.b save
+command relative to our running example is:
+.(l
+s 1 2 tuitionmail
+.)l
+.b Saved
+messages are not automatically saved in
+.i mbox
+at quit time, nor are they selected by the
+.b next
+command described above, unless explicitly specified.
+\fBSave\fP can be abbreviated to \fBs\fP.
+.ip "\fBset\fP\ \ "
+Set an option or give an option a value. Used to customize
+.i Mail .
+Section 5.3 contains a list of the options. Options can be
+.i binary ,
+in which case they are
+.i on
+or
+.i off ,
+or
+.i valued .
+To set a binary option
+.i option
+.i on ,
+do
+.(l
+set option
+.)l
+To give the valued option
+.i option
+the value
+.i value ,
+do
+.(l
+set option=value
+.)l
+There must be no space before or after the ``='' sign.
+If no arguments are given, all variable values are printed.
+Several options can be specified in a single
+.b set
+command.
+\fBSet\fP can be abbreviated to \fBse\fP.
+.ip "\fBshell\fP\ \ "
+The
+.b shell
+command allows you to
+escape to the shell.
+.b Shell
+invokes an interactive shell and allows you to type commands to it.
+When you leave the shell, you will return to
+.i Mail .
+The shell used is a default assumed by
+.i Mail ;
+you can override this default by setting the valued option
+.q SHELL,
+eg:
+.(l
+set SHELL=/bin/csh
+.)l
+\fBShell\fP can be abbreviated to \fBsh\fP.
+.ip "\fBsize\fP\ \ "
+Takes a message list and prints out the size in characters of each
+message.
+.ip "\fBsource\fP\ \ "
+The
+.b source
+command reads
+.i mail
+commands from a file. It is useful when you are trying to fix your
+.q .mailrc
+file and you need to re-read it.
+\fBSource\fP can be abbreviated to \fBso\fP.
+.ip "\fBtop\fP\ \ "
+The
+.b top
+command takes a message list and prints the first five lines
+of each addressed message.
+If you wish, you can change the number of lines that
+.b top
+prints out by setting the valued option
+.q "toplines."
+On a CRT terminal,
+.(l
+set toplines=10
+.)l
+might be preferred.
+\fBTop\fP can be abbreviated to \fBto\fP.
+.ip "\fBtype\fP\ \ "
+Same as \fBprint\fP.
+Takes a message list and types out each message on the terminal.
+The \fBtype\fP command can be abbreviated to \fBt\fP.
+.ip "\fBundelete\fP \ \"
+Takes a message list and marks each message as \fInot\fP
+being deleted.
+\fBUndelete\fP can be abbreviated to \fBu\fP.
+.ip "\fBunread\fP\ \ "
+Takes a message list and marks each message as
+.i not
+having been read.
+\fBUnread\fP can be abbreviated to \fBU\fP.
+.ip "\fBunset\fP\ \ "
+Takes a list of option names and discards their remembered values;
+the inverse of \fBset\fP .
+.ip "\fBvisual\fP\ \ "
+It is often useful to be able to invoke one of two editors,
+based on the type of terminal one is using. To invoke
+a display oriented editor, you can use the
+.b visual
+command. The operation of the
+.b visual
+command is otherwise identical to that of the
+.b edit
+command.
+.ne 2v+\n(psu
+.sp \n(psu
+Both the
+.b edit
+and
+.b visual
+commands assume some default text editors. These default editors
+can be overridden by the valued options
+.q EDITOR
+and
+.q VISUAL
+for the standard and screen editors. You might want to do:
+.(l
+set EDITOR=/usr/bin/ex VISUAL=/usr/bin/vi
+.)l
+\fBVisual\fP can be abbreviated to \fBv\fP.
+.ip "\fBwrite\fP\ \ "
+The
+.b save
+command always writes the entire message, including the headers,
+into the file. If you want to write just the message itself, you
+can use the
+.b write
+command. The
+.b write
+command has the same syntax as the
+.b save
+command, and can be abbreviated to simply
+.b w .
+Thus, we could write the second message by doing:
+.(l
+w 2 file.c
+.)l
+As suggested by this example, the
+.b write
+command is useful for such tasks as sending and receiving
+source program text over the message system.
+The filename in quotes, followed by the line
+count and character count is echoed on the user's terminal.
+.ip "\fBz\fP\ \ "
+.i Mail
+presents message headers in windowfuls as described under
+the
+.b headers
+command.
+You can move
+.i Mail's
+attention forward to the next window by giving the
+.(l
+z+
+.)l
+command. Analogously, you can move to the previous window with:
+.(l
+z\-
+.)l
+.sh 2 "Custom options"
+.pp
+Throughout this manual, we have seen examples of binary and valued options.
+This section describes each of the options in alphabetical order, including
+some that you have not seen yet.
+To avoid confusion, please note that the options are either
+all lower case letters or all upper case letters. When I start a sentence
+such as:
+.q "Ask"
+causes
+.i Mail
+to prompt you for a subject header,
+I am only capitalizing
+.q ask
+as a courtesy to English.
+.ip "\fBEDITOR\fP\ \ "
+The valued option
+.q EDITOR
+defines the pathname of the text editor to be used in the
+.b edit
+command and ~e. If not defined, a standard editor is used.
+.ip "\fBPAGER\fP\ \ "
+Pathname of the program to use for paginating output when
+it exceeds \fIcrt\fP lines.
+A default paginator is used if this option is not defined.
+.ip "\fBSHELL\fP\ \ "
+The valued option
+.q SHELL
+gives the path name of your shell. This shell is used for the
+.b !
+command and ~! escape. In addition, this shell expands
+file names with shell metacharacters like * and ? in them.
+.ip "\fBVISUAL\fP\ \ "
+The valued option
+.q VISUAL
+defines the pathname of the screen editor to be used in the
+.b visual
+command
+and ~v escape. A standard screen editor is used if you do not define one.
+.ip "\fBappend\fP\ \ "
+The
+.q append
+option is binary and
+causes messages saved in
+.i mbox
+to be appended to the end rather than prepended.
+Normally, \fIMail\fP will put messages in \fImbox\fP
+in the same order that the system puts messages in your system mailbox.
+By setting
+.q append,
+you are requesting that
+.i mbox
+be appended to regardless. It is in any event quicker to append.
+.ip "\fBask\fP\ \ "
+.q "Ask"
+is a binary option which
+causes
+.i Mail
+to prompt you for the subject of each message you send.
+If you respond with simply a newline, no subject field will be sent.
+.ip "\fBaskcc\fP\ \ "
+.q Askcc
+is a binary option which
+causes you to be prompted for additional carbon copy recipients at the
+end of each message. Responding with a newline shows your
+satisfaction with the current list.
+.ip "\fBautoprint\fP\ \ "
+.q Autoprint
+is a binary option which
+causes the
+.b delete
+command to behave like
+.b dp
+\*- thus, after deleting a message, the next one will be typed
+automatically. This is useful when quickly scanning and deleting
+messages in your mailbox.
+.ip "\fBcrt\fP \ \ "
+The valued option
+.q crt
+is used as a threshold to determine how long a message must
+be before
+.b PAGER
+is used to read it.
+.ip "\fBdebug\fP \ \ "
+The binary option
+.q debug
+causes debugging information to be displayed. Use of this
+option is the same as using the \fB\-d\fP command line flag.
+.ip "\fBdot\fP\ \ "
+.q Dot
+is a binary option which, if set, causes
+.i Mail
+to interpret a period alone on a line as the terminator
+of the message you are sending.
+.ip "\fBescape\fP\ \ "
+To allow you to change the escape character used when sending
+mail, you can set the valued option
+.q escape.
+Only the first character of the
+.q escape
+option is used, and it must be doubled if it is to appear as
+the first character of a line of your message. If you change your escape
+character, then ~ loses all its special meaning, and need no longer be doubled
+at the beginning of a line.
+.ip "\fBfolder\fP\ \ "
+The name of the directory to use for storing folders of messages.
+If this name begins with a `/'
+.i Mail
+considers it to be an absolute pathname; otherwise, the folder directory
+is found relative to your home directory.
+.ip "\fBhold\fP\ \ "
+The binary option
+.q hold
+causes messages that have been read but not manually dealt with
+to be held in the system mailbox. This prevents such messages from
+being automatically swept into your \fImbox\fP file.
+.ip "\fBignore\fP\ \ "
+The binary option
+.q ignore
+causes \s-2RUBOUT\s0 characters from your terminal to be ignored and echoed
+as @'s while you are sending mail. \s-2RUBOUT\s0 characters retain their
+original meaning in
+.i Mail
+command mode.
+Setting the
+.q ignore
+option is equivalent to supplying the
+.b \-i
+flag on the command line as described in section 6.
+.ip "\fBignoreeof\fP\ \ "
+An option related to
+.q dot
+is
+.q ignoreeof
+which makes
+.i Mail
+refuse to accept a control\-d as the end of a message.
+.q Ignoreeof
+also applies to
+.i Mail
+command mode.
+.ip "\fBkeep\fP\ \ "
+The
+.q keep
+option causes
+.i Mail
+to truncate your system mailbox instead of deleting it when it
+is empty. This is useful if you elect to protect your mailbox, which
+you would do with the shell command:
+.(l
+chmod 600 /var/mail/yourname
+.)l
+where
+.i yourname
+is your login name. If you do not do this, anyone can probably read
+your mail, although people usually don't.
+.ip "\fBkeepsave\fP\ \ "
+When you
+.b save
+a message,
+.i Mail
+usually discards it when you
+.b quit .
+To retain all saved messages, set the
+.q keepsave
+option.
+.ip "\fBmetoo\fP\ \ "
+When sending mail to an alias,
+.i Mail
+makes sure that if you are included in the alias, that mail will not
+be sent to you. This is useful if a single alias is being used by
+all members of the group. If however, you wish to receive a copy of
+all the messages you send to the alias, you can set the binary option
+.q metoo.
+.ip "\fBnoheader\fP\ \ "
+The binary option
+.q noheader
+suppresses the printing of the version and headers when
+.i Mail
+is first invoked. Setting this option is the same as using
+.b \-N
+on the command line.
+.ip "\fBnosave\fP\ \ "
+Normally,
+when you abort a message with two \s-2RUBOUTs\s0,
+.i Mail
+copies the partial letter to the file
+.q dead.letter
+in your home directory. Setting the binary option
+.q nosave
+prevents this.
+.ip "\fBReplyall\fP\ \ "
+Reverses the sense of
+.i reply
+and
+.i Reply
+commands.
+.ip "\fBquiet\fP\ \ "
+The binary option
+.q quiet
+suppresses the printing of the version when
+.i Mail
+is first invoked,
+as well as printing the for example
+.q "Message 4:"
+from the
+.b type
+command.
+.ip "\fBrecord\fP\ \ "
+If you love to keep records, then the
+valued option
+.q record
+can be set to the name of a file to save your outgoing mail.
+Each new message you send is appended to the end of the file.
+.ip "\fBscreen\fP\ \ "
+When
+.i Mail
+initially prints the message headers, it determines the number to
+print by looking at the speed of your terminal. The faster your
+terminal, the more it prints.
+The valued option
+.q screen
+overrides this calculation and
+specifies how many message headers you want printed.
+This number is also used for scrolling with the
+.b z
+command.
+.ip "\fBsendmail\fP\ \ "
+To use an alternate mail delivery system, set the
+.q sendmail
+option to the full pathname of the program to use. Note: this is not
+for everyone! Most people should use the default delivery system.
+.ip "\fBtoplines\fP\ \ "
+The valued option
+.q toplines
+defines the number of lines that the
+.q top
+command will print out instead of the default five lines.
+.ip "\fBverbose\fP\ \ "
+The binary option "verbose" causes
+.i Mail
+to invoke sendmail with the
+.b \-v
+flag, which causes it to go into verbose mode and announce expansion
+of aliases, etc. Setting the "verbose" option is equivalent to
+invoking
+.i Mail
+with the
+.b \-v
+flag as described in section 6.
diff --git a/share/doc/usd/07.mail/mail6.nr b/share/doc/usd/07.mail/mail6.nr
new file mode 100644
index 0000000..0465a94
--- /dev/null
+++ b/share/doc/usd/07.mail/mail6.nr
@@ -0,0 +1,125 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mail6.nr 8.1 (Berkeley) 6/8/93
+.\"
+.bp
+.sh 1 "Command line options"
+.pp
+This section describes command line options for
+.i Mail
+and what they are used for.
+.ip \-N
+Suppress the initial printing of headers.
+.ip \-d
+Turn on debugging information. Not of general interest.
+.ip "\-f file\ \ "
+Show the messages in
+.i file
+instead of your system mailbox. If
+.i file
+is omitted,
+.i Mail
+reads
+.i mbox
+in your home directory.
+.ip \-i
+Ignore tty interrupt signals. Useful on noisy phone lines, which
+generate spurious RUBOUT or DELETE characters. It's usually
+more effective to change your interrupt character to control\-c,
+for which see the
+.i stty
+shell command.
+.ip \-n
+Inhibit reading of /etc/mail.rc. Not generally useful, since
+/etc/mail.rc is usually empty.
+.ip "\-s string"
+Used for sending mail.
+.i String
+is used as the subject of the message being composed. If
+.i string
+contains blanks, you must surround it with quote marks.
+.ip "\-u name"
+Read
+.i names's
+mail instead of your own. Unwitting others often neglect to protect
+their mailboxes, but discretion is advised. Essentially,
+.b "\-u user"
+is a shorthand way of doing
+.b "\-f /var/mail/user".
+.ip "\-v"
+Use the
+.b \-v
+flag when invoking sendmail. This feature may also be enabled
+by setting the the option "verbose".
+.pp
+The following command line flags are also recognized, but are
+intended for use by programs invoking
+.i Mail
+and not for people.
+.ip "\-T file"
+Arrange to print on
+.i file
+the contents of the
+.i article-id
+fields of all messages that were either read or deleted.
+.b \-T
+is for the
+.i readnews
+program and should NOT be used for reading your mail.
+.ip "\-h number"
+Pass on hop count information.
+.i Mail
+will take the number, increment it, and pass it with
+.b \-h
+to the mail delivery system.
+.b \-h
+only has effect when sending mail and is used for network mail
+forwarding.
+.ip "\-r name"
+Used for network mail forwarding: interpret
+.i name
+as the sender of the message. The
+.i name
+and
+.b \-r
+are simply sent along to the mail delivery system. Also,
+.i Mail
+will wait for the message to be sent and return the exit status.
+Also restricts formatting of message.
+.pp
+Note that
+.b \-h
+and
+.b \-r ,
+which are for network mail forwarding, are not used in practice
+since mail forwarding is now handled separately. They may
+disappear soon.
diff --git a/share/doc/usd/07.mail/mail7.nr b/share/doc/usd/07.mail/mail7.nr
new file mode 100644
index 0000000..0b2590b
--- /dev/null
+++ b/share/doc/usd/07.mail/mail7.nr
@@ -0,0 +1,107 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mail7.nr 8.1 (Berkeley) 6/8/93
+.\"
+.sh 1 "Format of messages"
+.pp
+This section describes the format of messages.
+Messages begin with a
+.i from
+line, which consists of the word
+.q From
+followed by a user name, followed by anything, followed by
+a date in the format returned by the
+.i ctime
+library routine described in section 3 of the Unix Programmer's
+Manual. A possible
+.i ctime
+format date is:
+.(l
+Tue Dec 1 10:58:23 1981
+.)l
+The
+.i ctime
+date may be optionally followed by a single space and a
+time zone indication, which
+should be three capital letters, such as PDT.
+.pp
+Following the
+.i from
+line are zero or more
+.i "header field"
+lines.
+Each header field line is of the form:
+.(l
+name: information
+.)l
+.i Name
+can be anything, but only certain header fields are recognized as
+having any meaning. The recognized header fields are:
+.i article-id ,
+.i bcc ,
+.i cc ,
+.i from ,
+.i reply-to ,
+.i sender ,
+.i subject ,
+and
+.i to .
+Other header fields are also significant to other systems; see,
+for example, the current Arpanet message standard for much more
+information on this topic.
+A header field can be continued onto following lines by making the
+first character on the following line a space or tab character.
+.pp
+If any headers are present, they must be followed by a blank line.
+The part that follows is called the
+.i body
+of the message, and must be ASCII text, not containing null characters.
+Each line in the message body must be no longer than 512 characters and
+terminated with an ASCII newline character.
+If binary data must be passed through the mail system, it is suggested
+that this data be encoded in a system which encodes six bits into
+a printable character (i.e.: uuencode).
+For example, one could use the upper and lower case letters, the digits,
+and the characters comma and period to make up the 64 characters.
+Then, one can send a 16-bit binary number
+as three characters. These characters should be packed into lines,
+preferably lines about 70 characters long as long lines are transmitted
+more efficiently.
+.pp
+The message delivery system always adds a blank line to the end of
+each message. This blank line must not be deleted.
+.pp
+The UUCP message delivery system sometimes adds a blank line to
+the end of a message each time it is forwarded through a machine.
+.pp
+It should be noted that some network transport protocols enforce
+limits to the lengths of messages.
diff --git a/share/doc/usd/07.mail/mail8.nr b/share/doc/usd/07.mail/mail8.nr
new file mode 100644
index 0000000..b09afbd
--- /dev/null
+++ b/share/doc/usd/07.mail/mail8.nr
@@ -0,0 +1,75 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mail8.nr 8.1 (Berkeley) 6/8/93
+.\"
+.bp
+.sh 1 "Glossary"
+.pp
+This section contains the definitions of a few phrases
+peculiar to
+.i Mail .
+.ip "\fIalias\fP"
+An alternative name for a person or list of people.
+.ip "\fIflag\fP"
+An option, given on the command line of
+.i Mail ,
+prefaced with a \-. For example,
+.b \-f
+is a flag.
+.ip "\fIheader field\fP"
+At the beginning of a message, a line which contains information
+that is part of the structure of the message. Popular header fields
+include
+.i to ,
+.i cc ,
+and
+.i subject .
+.ip "\fImail\ \ \fP"
+A collection of messages. Often used in the phrase,
+.q "Have you read your mail?"
+.ip "\fImailbox\fP"
+The place where your mail is stored, typically in the directory
+/var/mail.
+.ip "\fImessage\fP"
+A single letter from someone, initially stored in your
+.i mailbox .
+.ip "\fImessage list\fP"
+A string used in
+.i Mail
+command mode to describe a sequence of messages.
+.ip "\fIoption\fP"
+A piece of special purpose information used to tailor
+.i Mail
+to your taste.
+Options are specified with the
+.b set
+command.
diff --git a/share/doc/usd/07.mail/mail9.nr b/share/doc/usd/07.mail/mail9.nr
new file mode 100644
index 0000000..271548e
--- /dev/null
+++ b/share/doc/usd/07.mail/mail9.nr
@@ -0,0 +1,203 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mail9.nr 8.1 (Berkeley) 6/8/93
+.\"
+.bp
+.sh 1 "Summary of commands, options, and escapes"
+.pp
+This section gives a quick summary of the
+.i Mail
+commands, binary and valued options, and tilde escapes.
+.pp
+The following table describes the commands:
+.TS
+center ;
+c ci
+lb l.
+Command Description
+_
++ Same as \fBnext\fP
+- Back up to previous message
+? Print brief summary of \fIMail\fP commands
+! Single command escape to shell
+Print Type message with ignored fields
+Reply Reply to author of message only
+Respond Same as \fBReply\fP
+Type Type message with ignored fields
+alias Define an alias as a set of user names
+alternates List other names you are known by
+chdir Change working directory, home by default
+copy Copy a message to a file or folder
+delete Delete a list of messages
+dp Same as \fBdt\fP
+dt Delete current message, type next message
+edit Edit a list of messages
+else Start of else part of conditional; see \fBif\fP
+endif End of conditional statement; see \fBif\fP
+exit Leave mail without changing anything
+file Interrogate/change current mail file
+folder Same as \fBfile\fP
+folders List the folders in your folder directory
+from List headers of a list of messages
+headers List current window of messages
+help Same as \fB?\fP
+hold Same as \fBpreserve\fP
+if Conditional execution of \fIMail\fP commands
+ignore Set/examine list of ignored header fields
+list List valid \fIMail\fP commands
+local List other names for the local host
+mail Send mail to specified names
+mbox Arrange to save a list of messages in \fImbox\fP
+next Go to next message and type it
+preserve Arrange to leave list of messages in system mailbox
+print Print messages
+quit Leave \fIMail\fP; update system mailbox, \fImbox\fP as appropriate
+reply Compose a reply to a message
+respond Same as \fBreply\fP
+retain Supersedes \fBignore\fP
+save Append messages, headers included, on a file
+set Set binary or valued options
+shell Invoke an interactive shell
+size Prints out size of message list
+source Read \fImail\fP commands from a file
+top Print first so many (5 by default) lines of list of messages
+type Same as \fBprint\fP
+undelete Undelete list of messages
+unread Marks list of messages as not been read
+unset Undo the operation of a \fBset\fP
+visual Invoke visual editor on a list of messages
+write Append messages to a file, don't include headers
+xit Same as \fBexit\fP
+z Scroll to next/previous screenful of headers
+.TE
+.bp
+.(b
+.pp
+The following table describes the options. Each option is
+shown as being either a binary or valued option.
+.TS
+center;
+c ci ci
+l ci l.
+Option Type Description
+_
+EDITOR valued Pathname of editor for ~e and \fBedit\fP
+PAGER valued Pathname of paginator for \fBPrint\fP, \fBprint\fP, \fBType\fP and \fBtype\fP
+SHELL valued Pathname of shell for \fBshell\fP, ~! and \fB!\fP
+VISUAL valued Pathname of screen editor for ~v, \fBvisual\fP
+append binary Always append messages to end of \fImbox\fP
+ask binary Prompt user for Subject: field when sending
+askcc binary Prompt user for additional Cc's at end of message
+autoprint binary Print next message after \fBdelete\fP
+crt valued Minimum number of lines before using \fBPAGER\fP
+debug binary Print out debugging information
+dot binary Accept . alone on line to terminate message input
+escape valued Escape character to be used instead of\ \ ~
+folder valued Directory to store folders in
+hold binary Hold messages in system mailbox by default
+ignore binary Ignore \s-2RUBOUT\s0 while sending mail
+ignoreeof binary Don't terminate letters/command input with \fB\(uaD\fP
+keep binary Don't unlink system mailbox when empty
+keepsave binary Don't delete \fBsave\fPd messages by default
+metoo binary Include sending user in aliases
+noheader binary Suppress initial printing of version and headers
+nosave binary Don't save partial letter in \fIdead.letter\fP
+quiet binary Suppress printing of \fIMail\fP version and message numbers
+record valued File to save all outgoing mail in
+screen valued Size of window of message headers for \fBz\fP, etc.
+sendmail valued Choose alternate mail delivery system
+toplines valued Number of lines to print in \fBtop\fP
+verbose binary Invoke sendmail with the \fB\-v\fP flag
+.TE
+.)b
+.(b
+.pp
+The following table summarizes the tilde escapes available
+while sending mail.
+.TS
+center;
+c ci ci
+l li l.
+Escape Arguments Description
+_
+~! command Execute shell command
+~b name ... Add names to "blind" Cc: list
+~c name ... Add names to Cc: field
+~d Read \fIdead.letter\fP into message
+~e Invoke text editor on partial message
+~f messages Read named messages
+~h Edit the header fields
+~m messages Read named messages, right shift by tab
+~p Print message entered so far
+~q Abort entry of letter; like \s-2RUBOUT\s0
+~r filename Read file into message
+~s string Set Subject: field to \fIstring\fP
+~t name ... Add names to To: field
+~v Invoke screen editor on message
+~w filename Write message on file
+~| command Pipe message through \fIcommand\fP
+~: Mail command Execute a \fIMail\fP command
+~~ string Quote a ~ in front of \fIstring\fP
+.TE
+.)b
+.(b
+.pp
+The following table shows the command line flags that
+.i Mail
+accepts:
+.TS
+center;
+c c
+l a.
+Flag Description
+_
+\-N Suppress the initial printing of headers
+\-T \fIfile\fP Article-id's of read/deleted messages to \fIfile\fP
+\-d Turn on debugging
+\-f \fIfile\fP Show messages in \fIfile\fP or \fI~/mbox\fP
+\-h \fInumber\fP Pass on hop count for mail forwarding
+\-i Ignore tty interrupt signals
+\-n Inhibit reading of /etc/mail.rc
+\-r \fIname\fP Pass on \fIname\fP for mail forwarding
+\-s \fIstring\fP Use \fIstring\fP as subject in outgoing mail
+\-u \fIname\fP Read \fIname's\fP mail instead of your own
+\-v Invoke sendmail with the \fB\-v\fP flag
+.TE
+.)b
+.lp
+Notes:
+.b \-T ,
+.b \-d ,
+.b \-h ,
+and
+.b \-r
+are not for human use.
diff --git a/share/doc/usd/07.mail/maila.nr b/share/doc/usd/07.mail/maila.nr
new file mode 100644
index 0000000..84b01fe
--- /dev/null
+++ b/share/doc/usd/07.mail/maila.nr
@@ -0,0 +1,33 @@
+.\" Copyright (c) 1980, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)maila.nr 8.1 (Berkeley) 6/8/93
+.\"
OpenPOWER on IntegriCloud