Research V7 development
authorS. R. Bourne <srb@research.uucp>
Wed, 10 Jan 1979 20:22:21 +0000 (15:22 -0500)
committerS. R. Bourne <srb@research.uucp>
Wed, 10 Jan 1979 20:22:21 +0000 (15:22 -0500)
Work on file usr/doc/shell/t.mac
Work on file usr/doc/shell/t1
Work on file usr/doc/shell/t2
Work on file usr/doc/shell/t3
Work on file usr/doc/shell/t4

Synthesized-from: v7

usr/doc/shell/t.mac [new file with mode: 0644]
usr/doc/shell/t1 [new file with mode: 0644]
usr/doc/shell/t2 [new file with mode: 0644]
usr/doc/shell/t3 [new file with mode: 0644]
usr/doc/shell/t4 [new file with mode: 0644]

diff --git a/usr/doc/shell/t.mac b/usr/doc/shell/t.mac
new file mode 100644 (file)
index 0000000..93fe4c4
--- /dev/null
@@ -0,0 +1,29 @@
+.ds ZZ \fB.\|.\|.\fP
+.ds ST \v'.3m'\s+2*\s0\v'-.3m'
+.ds DO \h'\w'do 'u'
+.ds Ca \h'\w'case 'u'
+.ds WH \h'\w'while 'u'
+.ds VT \|\fB\(or\fP\|
+.ds TH \h'\w'then 'u'
+.ds DC \*(DO\*(CA
+.ds AP >\h'-.2m'>
+.ds HE <\h'-.2m'<
+..     \" macros for algol 68c reference manual
+.ds DA 1977 November 1
+.ds md \v'.25m'
+.ds mu \v'-.25m'
+.ds U \*(mu\s-3
+.ds V \s0\*(md
+.ds L \*(md\s-3
+.ds M \s0\*(mu
+.ds S \s-1
+.ds T \s0
+..     \" small 1
+.ds O \*S1\*T
+.ds h \|
+.ds s \|\|
+..     \" ellipsis
+.ds e .\|.\|.
+..     \" subscripts
+.ds 1 \*(md\s-41\s0\*(mu
+.ds 2 \*(md\s-42\s0\*(mu
diff --git a/usr/doc/shell/t1 b/usr/doc/shell/t1
new file mode 100644 (file)
index 0000000..4f735c8
--- /dev/null
@@ -0,0 +1,438 @@
+.RP
+.TL 
+An Introduction to the UNIX Shell
+.AU
+S. R. Bourne
+.AI
+.MH
+.AB
+.LP
+The
+.ul
+shell
+is a command programming language that provides an interface
+to the
+.UX
+operating system.
+Its features include
+control-flow primitives, parameter passing, variables and
+string substitution.
+Constructs such as
+.ul
+while, if then else, case
+and
+.ul
+for
+are available.
+Two-way communication is possible between the
+.ul
+shell
+and commands.
+String-valued parameters, typically file names or flags, may be
+passed to a command.
+A return code is set by commands that may be used to determine control-flow,
+and the standard output from a command may be used
+as shell input.
+.LP
+The
+.ul
+shell
+can modify the environment
+in which commands run.
+Input and output can be redirected
+to files, and processes that communicate through `pipes'
+can be invoked.
+Commands are found by
+searching directories
+in the file system in a
+sequence that can be defined by the user.
+Commands can be read either from the terminal or from a file,
+which allows command procedures to be
+stored for later use.
+.AE
+.ds ST \v'.3m'\s+2*\s0\v'-.3m'
+.SH
+1.0\ Introduction
+.LP
+The shell is both a command language
+and a programming language
+that provides an interface to the UNIX
+operating system.
+This memorandum describes, with
+examples, the UNIX shell.
+The first section covers most of the
+everyday requirements
+of terminal users.
+Some familiarity with UNIX
+is an advantage when reading this section;
+see, for example,
+"UNIX for beginners".
+.[
+unix beginn kernigh 1978
+.]
+Section 2 describes those features
+of the shell primarily intended
+for use within shell procedures.
+These include the control-flow
+primitives and string-valued variables
+provided by the shell.
+A knowledge of a programming language
+would be a help when reading this section.
+The last section describes the more
+advanced features of the shell.
+References of the form "see \fIpipe\fP (2)"
+are to a section of the UNIX manual.
+.[
+seventh 1978 ritchie thompson
+.]
+.SH
+1.1\ Simple\ commands
+.LP
+Simple commands consist of one or more words
+separated by blanks.
+The first word is the name of the command
+to be executed; any remaining words
+are passed as arguments to the command.
+For example,
+.DS
+       who
+.DE
+is a command that prints the names
+of users logged in.
+The command
+.DS
+       ls \(mil
+.DE
+prints a list of files in the current
+directory.
+The argument \fI\(mil\fP tells \fIls\fP
+to print status information, size and
+the creation date for each file.
+.SH
+1.2\ Background\ commands
+.LP
+To execute a command the shell normally
+creates a new \fIprocess\fP
+and waits for it to finish.
+A command may be run without waiting
+for it to finish.
+For example,
+.DS
+       cc pgm.c &
+.DE
+calls the C compiler to compile
+the file \fIpgm.c\|.\fP
+The trailing \fB&\fP is an operator that instructs the shell
+not to wait for the command to finish.
+To help keep track of such a process
+the shell reports its process
+number following its creation.
+A list of currently active processes may be obtained
+using the \fIps\fP command.
+.SH
+1.3\ Input\ output\ redirection
+.LP
+Most commands produce output on the standard output
+that is initially connected to the terminal.
+This output may be sent to a file
+by writing, for example,
+.DS
+       ls \(mil >file
+.DE
+The notation \fI>file\fP
+is interpreted by the shell and is not passed
+as an argument to \fIls.\fP
+If \fIfile\fP does not exist then the
+shell creates it;
+otherwise the original contents of
+\fIfile\fP are replaced with the output
+from \fIls.\fP
+Output may be appended to a file
+using the notation
+.DS
+       ls \(mil \*(APfile
+.DE
+In this case \fIfile\fP is also created if it does not already
+exist.
+.LP
+The standard input of a command may be taken
+from a file instead of the terminal by
+writing, for example,
+.DS
+       wc <file
+.DE
+The command \fIwc\fP reads its standard input
+(in this case redirected from \fIfile\fP)
+and prints the number of characters, words and
+lines found.
+If only the number of lines is required
+then
+.DS
+       wc \(mil <file
+.DE
+could be used.
+.SH
+1.4\ Pipelines\ and\ filters
+.LP
+The standard output of one command may be
+connected to the standard input of another
+by writing
+the `pipe' operator,
+indicated by \*(VT,
+as in,
+.DS
+       ls \(mil \*(VT wc
+.DE
+Two commands connected in this way constitute
+a \fIpipeline\fP and
+the overall effect is the same as
+.DS
+       ls \(mil >file; wc <file
+.DE
+except that no \fIfile\fP is used.
+Instead the two processes are connected
+by a pipe (see \fIpipe\fP (2)) and are
+run in parallel.
+Pipes are unidirectional and
+synchronization is achieved by
+halting \fIwc\fP when there is
+nothing to read and halting \fIls\fP
+when the pipe is full.
+.LP
+A \fIfilter\fP is a command
+that reads its standard input,
+transforms it in some way,
+and prints the result as output.
+One such filter, \fIgrep,\fP
+selects from its input those lines
+that contain some specified string.
+For example,
+.DS
+       ls \*(VT grep old
+.DE
+prints those lines, if any, of the output
+from \fIls\fP that contain
+the string \fIold.\fP
+Another useful filter is \fIsort\fP.
+For example,
+.DS
+       who \*(VT sort
+.DE
+will print an alphabetically sorted list
+of logged in users.
+.LP
+A pipeline may consist of more than two commands,
+for example,
+.DS
+       ls \*(VT grep old \*(VT wc \(mil
+.DE
+prints the number of file names
+in the current directory containing
+the string \fIold.\fP
+.SH
+1.5\ File\ name\ generation
+.LP
+Many commands accept arguments
+which are file names.
+For example,
+.DS
+       ls \(mil main.c
+.DE
+prints information relating to the file \fImain.c\fP\|.
+.LP
+The shell provides a mechanism
+for generating a list of file names
+that match a pattern.
+For example,
+.DS
+       ls \(mil \*(ST.c
+.DE
+generates, as arguments to \fIls,\fP
+all file names in the current directory that end in \fI.c\|.\fP
+The character \*(ST is a pattern that will match any string
+including the null string.
+In general \fIpatterns\fP are specified
+as follows.
+.RS
+.IP \fB\*(ST\fR 8
+Matches any string of characters
+including the null string.
+.IP \fB?\fR 8
+Matches any single character.
+.IP \fB[\*(ZZ]\fR 8
+Matches any one of the characters
+enclosed.
+A pair of characters separated by a minus will
+match any character lexically between
+the pair.
+.RE
+.LP
+For example,
+.DS
+       [a\(miz]\*(ST
+.DE
+matches all names in the current directory
+beginning with
+one of the letters \fIa\fP through \fIz.\fP
+.DS
+       /usr/fred/test/?
+.DE
+matches all names in the directory
+\fB/usr/fred/test\fP that consist of a single character.
+If no file name is found that matches
+the pattern then the pattern is passed,
+unchanged, as an argument.
+.LP
+This mechanism is useful both to save typing
+and to select names according to some pattern.
+It may also be used to find files.
+For example,
+.DS
+       echo /usr/fred/\*(ST/core
+.DE
+finds and prints the names of all \fIcore\fP files in sub-directories
+of \fB/usr/fred\|.\fP
+(\fIecho\fP is a standard UNIX command that prints
+its arguments, separated by blanks.)
+This last feature can be expensive,
+requiring a scan of all
+sub-directories of \fB/usr/fred\|.\fP
+.LP
+There is one exception to the general
+rules given for patterns.
+The character `\fB.\fP'
+at the start of a file name must be explicitly
+matched.
+.DS
+       echo \*(ST
+.DE
+will therefore echo all file names in the current
+directory not beginning
+with `\fB.\fP'\|.
+.DS
+       echo \fB.\fP\*(ST
+.DE
+will echo all those file names that begin with `\fB.\fP'\|.
+This avoids inadvertent matching
+of the names `\fB.\fP' and `\fB..\fP'
+which mean `the current directory'
+and `the parent directory'
+respectively.
+(Notice that \fIls\fP suppresses
+information for the files `\fB.\fP' and `\fB..\fP'\|.)
+.SH
+1.6\ Quoting
+.LP
+Characters that have a special meaning
+to the shell, such as \fB< > \*(ST ? \*(VT &\|,\fR
+are called metacharacters.
+A complete list of metacharacters is given
+in appendix B.
+Any character preceded by a \fB\\\fR is \fIquoted\fP
+and loses its special meaning, if any.
+The \fB\\\fP is elided so that
+.DS
+       echo \\\\?
+.DE
+will echo a single \fB?\|,\fP
+and
+.DS
+       echo \\\\\\\\
+.DE
+will echo a single \fB\\\|.\fR
+To allow long strings to be continued over
+more than one line
+the sequence \fB\\newline\fP
+is ignored.
+.LP
+\fB\\\fP is convenient for quoting
+single characters.
+When more than one character needs
+quoting the above mechanism is clumsy and
+error prone.
+A string of characters may be quoted
+by enclosing the string between single quotes.
+For example,
+.DS
+       echo xx\'\*(ST\*(ST\*(ST\*(ST\'xx
+.DE
+will echo
+.DS
+       xx\*(ST\*(ST\*(ST\*(STxx
+.DE
+The quoted string may not contain
+a single quote
+but may contain newlines, which are preserved.
+This quoting mechanism is the most
+simple and is recommended
+for casual use.
+.LP
+A third quoting mechanism using double quotes
+is also available
+that prevents interpretation of some but not all
+metacharacters.
+Discussion of the
+details is deferred
+to section 3.4\|.
+.SH
+1.7\ Prompting
+.LP
+When the shell is used from a terminal it will
+issue a prompt before reading a command.
+By default this prompt is `\fB$\ \fR'\|.
+It may be changed by saying,
+for example,
+.DS
+       \s-1PS1\s0=yesdear
+.DE
+that sets the prompt to be the string \fIyesdear\|.\fP
+If a newline is typed and further input is needed
+then the shell will issue the prompt `\fB>\ \fR'\|.
+Sometimes this can be caused by mistyping
+a quote mark.
+If it is unexpected then an interrupt (\s-1DEL\s0)
+will return the shell to read another command.
+This prompt may be changed by saying, for example,
+.DS
+       \s-1PS2\s0=more
+.DE
+.SH
+1.8\ The\ shell\ and\ login
+.LP
+Following \fIlogin\fP (1)
+the shell is called to read and execute
+commands typed at the terminal.
+If the user's login directory
+contains the file \fB.profile\fP
+then it is assumed to contain commands
+and is read by the shell before reading
+any commands from the terminal.
+.SH
+1.9\ Summary
+.sp
+.RS
+.IP \(bu
+\fBls\fP
+.br
+Print the names of files in the current directory.
+.IP \(bu
+\fBls >file\fP
+.br
+Put the output from \fIls\fP into \fIfile.\fP
+.IP \(bu
+\fBls \*(VT wc \(mil\fR
+.br
+Print the number of files in the current directory.
+.IP \(bu
+\fBls \*(VT grep old\fR
+.br
+Print those file names containing the string \fIold.\fP
+.IP \(bu
+\fBls \*(VT grep old \*(VT wc \(mil\fR
+.br
+Print the number of files whose name contains the string \fIold.\fP
+.IP \(bu
+\fBcc pgm.c &\fR
+.br
+Run \fIcc\fP in the background.
+.RE
diff --git a/usr/doc/shell/t2 b/usr/doc/shell/t2
new file mode 100644 (file)
index 0000000..c7e581f
--- /dev/null
@@ -0,0 +1,829 @@
+.bp
+.SH
+2.0\ Shell\ procedures
+.LP
+The shell may be used to read and execute commands
+contained in a file.
+For example,
+.DS
+       sh file [ args \*(ZZ ]
+.DE
+calls the shell to read commands from \fIfile.\fP
+Such a file is called a \fIcommand procedure\fP
+or \fIshell procedure.\fP
+Arguments may be supplied with the call
+and are referred to in \fIfile\fP
+using the positional parameters
+\fB$1, $2, \*(ZZ\|.\fR
+For example, if the file \fIwg\fP contains
+.DS
+       who \*(VT grep $1
+.DE
+then
+.DS
+       sh wg fred
+.DE
+is equivalent to
+.DS
+       who \*(VT grep fred
+.DE
+.LP
+UNIX files have three independent attributes,
+\fIread,\fP \fIwrite\fP and \fIexecute.\fP
+The UNIX command \fIchmod\fP (1) may be used
+to make a file executable.
+For example,
+.DS
+       chmod +x wg
+.DE
+will ensure that the file \fIwg\fP has execute status.
+Following this, the command
+.DS
+       wg fred
+.DE
+is equivalent to
+.DS
+       sh wg fred
+.DE
+This allows shell procedures and programs
+to be used interchangeably.
+In either case a new process is created to
+run the command.
+.LP
+As well as providing names for the positional
+parameters,
+the number of positional parameters in the call
+is available as \fB$#\|.\fP
+The name of the file being executed
+is available as \fB$0\|.\fP
+.LP
+A special shell parameter \fB$\*(ST\fP
+is used to substitute for all positional parameters
+except \fB$0\|.\fP
+A typical use of this is to provide
+some default arguments,
+as in,
+.DS
+       nroff \(miT450 \(mims $\*(ST
+.DE
+which simply prepends some arguments
+to those already given.
+.SH
+2.1\ Control\ flow\ -\ for
+.LP
+A frequent use of shell procedures is to loop
+through the arguments (\fB$1, $2, \*(ZZ\fR)
+executing commands once for each argument.
+An example of such a procedure is
+\fItel\fP that searches the file
+\fB/usr/lib/telnos\fR
+that contains lines of the form
+.DS
+       \*(ZZ
+       fred mh0123
+       bert mh0789
+       \*(ZZ
+.DE
+The text of \fItel\fP is
+.DS
+       for i
+       do grep $i /usr/lib/telnos; done
+.DE
+The command
+.DS
+       tel fred
+.DE
+prints those lines in \fB/usr/lib/telnos\fR
+that contain the string \fIfred\|.\fP
+.DS
+       tel fred bert
+.DE
+prints those lines containing \fIfred\fP
+followed by those for \fIbert.\fP
+.LP
+The \fBfor\fP loop notation is recognized by the shell
+and has the general form
+.DS
+       \fBfor\fR \fIname\fR \fBin\fR \fIw1 w2 \*(ZZ\fR
+       \fBdo\fR \fIcommand-list\fR
+       \fBdone\fR
+.DE
+A \fIcommand-list\fP is a sequence of one or more
+simple commands separated or terminated by a newline or semicolon.
+Furthermore, reserved words
+like \fBdo\fP and \fBdone\fP are only
+recognized following a newline or
+semicolon.
+\fIname\fP is a shell variable that is set
+to the words \fIw1 w2 \*(ZZ\fR in turn each time the \fIcommand-list\fP
+following \fBdo\fP
+is executed.
+If \fBin\fR \fIw1 w2 \*(ZZ\fR
+is omitted then the loop
+is executed once for each positional parameter;
+that is, \fBin\fR \fI$\*(ST\fR is assumed.
+.LP
+Another example of the use of the \fBfor\fP
+loop is the \fIcreate\fP command
+whose text is
+.DS
+       for i do >$i; done
+.DE
+The command
+.DS
+       create alpha beta
+.DE
+ensures that two empty files
+\fIalpha\fP and \fIbeta\fP exist
+and are empty.
+The notation \fI>file\fP may be used on its
+own to create or clear the contents of a file.
+Notice also that a semicolon (or newline) is required before \fBdone.\fP
+.SH
+2.2\ Control\ flow\ -\ case
+.LP
+A multiple way branch is provided for by the
+\fBcase\fP notation.
+For example,
+.DS
+       case $# in
+       \*(Ca1) cat \*(AP$1 ;;
+       \*(Ca2) cat \*(AP$2 <$1 ;;
+       \*(Ca\*(ST)     echo \\'usage: append [ from ] to\\' ;;
+       esac
+.DE
+is an \fIappend\fP command.
+When called
+with one argument as
+.DS
+       append file
+.DE
+\fB$#\fP is the string \fI1\fP and
+the standard input is copied onto the
+end of \fIfile\fP
+using the \fIcat\fP command.
+.DS
+       append file1 file2
+.DE
+appends the contents of \fIfile1\fP
+onto \fIfile2.\fP
+If the number of arguments supplied to
+\fIappend\fP is other than 1 or 2
+then a message is printed indicating
+proper usage.
+.LP
+The general form of the \fBcase\fP command
+is
+.DS
+       \fBcase \fIword \fBin
+       \*(Ca\fIpattern\|\fB)\ \fIcommand-list\fB\|;;
+       \*(Ca\*(ZZ
+       \fBesac\fR
+.DE
+The shell attempts to match
+\fIword\fR with each \fIpattern,\fR
+in the order in which the patterns
+appear.
+If a match is found the
+associated \fIcommand-list\fP is
+executed and execution
+of the \fBcase\fP is complete.
+Since \*(ST is the pattern that matches any
+string it can be used for the default case.
+.LP
+A word of caution:
+no check is made to ensure that only
+one pattern matches
+the case argument.
+The first match found defines the set of commands
+to be executed.
+In the example below the commands following
+the second \*(ST will never be executed.
+.DS
+       case $# in
+       \*(Ca\*(ST) \*(ZZ ;;
+       \*(Ca\*(ST) \*(ZZ ;;
+       esac
+.DE
+.LP
+Another example of the use of the \fBcase\fP
+construction is to distinguish
+between different forms
+of an argument.
+The following example is a fragment of a \fIcc\fP command.
+.DS
+       for i
+       do case $i in
+       \*(DC\(mi[ocs]) \*(ZZ ;;
+       \*(DC\(mi\*(ST) echo \\'unknown flag $i\\' ;;
+       \*(DC\*(ST.c)   /lib/c0 $i \*(ZZ ;;
+       \*(DC\*(ST)     echo \\'unexpected argument $i\\' ;;
+       \*(DOesac
+       done
+.DE
+.LP
+To allow the same commands to be associated
+with more than one pattern
+the \fBcase\fP command provides
+for alternative patterns
+separated by a \*(VT\|.
+For example,
+.DS
+       case $i in
+       \*(Ca\(mix\*(VT\(miy)   \*(ZZ
+       esac
+.DE
+is equivalent to
+.DS
+       case $i in
+       \*(Ca\(mi[xy])  \*(ZZ
+       esac
+.DE
+.LP
+The usual quoting conventions apply
+so that
+.DS
+       case $i in
+       \*(Ca\\\\?)     \*(ZZ
+.DE
+will match the character \fB?\|.\fP
+.SH
+2.3\ Here\ documents
+.LP
+The shell procedure \fItel\fP
+in section 2.1 uses the file \fB/usr/lib/telnos\fR
+to supply the data
+for \fIgrep.\fP
+An alternative is to include this
+data
+within the shell procedure as a \fIhere\fP document, as in,
+.DS
+       for i
+       do grep $i \*(HE!
+       \*(DO\*(ZZ
+       \*(DOfred mh0123
+       \*(DObert mh0789
+       \*(DO\*(ZZ
+       !
+       done
+.DE
+In this example
+the shell takes the lines between \fB\*(HE!\fR and \fB!\fR
+as the standard input for \fIgrep.\fP
+The string \fB!\fR is arbitrary, the document
+being terminated by a line that consists
+of the string following \*(HE\|.
+.LP
+Parameters are substituted in the document
+before it is made available to \fIgrep\fP
+as illustrated by the following procedure
+called \fIedg\|.\fP
+.DS
+       ed $3 \*(HE%
+       g/$1/s//$2/g
+       w
+       %
+.DE
+The call
+.DS
+       edg string1 string2 file
+.DE
+is then equivalent to the command
+.DS
+       ed file \*(HE%
+       g/string1/s//string2/g
+       w
+       %
+.DE
+and changes all occurrences of \fIstring1\fP
+in \fIfile\fP to \fIstring2\|.\fP
+Substitution can be prevented using \\
+to quote the special character \fB$\fP
+as in
+.DS
+       ed $3 \*(HE+
+       1,\\\\$s/$1/$2/g
+       w
+       +
+.DE
+(This version of \fIedg\fP is equivalent to
+the first except that \fIed\fP will print
+a \fB?\fR if there are no occurrences of
+the string \fB$1\|.\fP)
+Substitution within a \fIhere\fP document
+may be prevented entirely by quoting
+the terminating string,
+for example,
+.DS
+       grep $i \*(HE\\\\#
+       \*(ZZ
+       #
+.DE
+The document is presented
+without modification to \fIgrep.\fP
+If parameter substitution is not required
+in a \fIhere\fP document this latter form
+is more efficient.
+.SH
+2.4\ Shell\ variables
+.LP
+The shell
+provides string-valued variables.
+Variable names begin with a letter
+and consist of letters, digits and
+underscores.
+Variables may be given values by writing, for example,
+.DS
+       user=fred\ box=m000\ acct=mh0000
+.DE
+which assigns values to the variables
+\fBuser, box\fP and \fBacct.\fP
+A variable may be set to the null string
+by saying, for example,
+.DS
+       null=
+.DE
+The value of a variable is substituted
+by preceding its name with \fB$\|;\fP
+for example,
+.DS
+       echo $user
+.DE
+will echo \fIfred.\fP
+.LP
+Variables may be used interactively
+to provide abbreviations for frequently
+used strings.
+For example,
+.DS
+       b=/usr/fred/bin
+       mv pgm $b
+.DE
+will move the file \fIpgm\fP
+from the current directory to the directory \fB/usr/fred/bin\|.\fR
+A more general notation is available for parameter
+(or variable)
+substitution, as in,
+.DS
+       echo ${user}
+.DE
+which is equivalent to
+.DS
+       echo $user
+.DE
+and is used when the parameter name is
+followed by a letter or digit.
+For example,
+.DS
+       tmp=/tmp/ps
+       ps a >${tmp}a
+.DE
+will direct the output of \fIps\fR
+to the file \fB/tmp/psa,\fR
+whereas,
+.DS
+       ps a >$tmpa
+.DE
+would cause the value of the variable \fBtmpa\fP
+to be substituted.
+.LP
+Except for \fB$?\fP the following
+are set initially by the shell.
+\fB$?\fP is set after executing each command.
+.RS
+.IP \fB$?\fP 8
+The exit status (return code)
+of the last command executed
+as a decimal string.
+Most commands return a zero exit status
+if they complete successfully,
+otherwise a non-zero exit status is returned.
+Testing the value of return codes is dealt with
+later under \fBif\fP and \fBwhile\fP commands.
+.IP \fB$#\fP 8
+The number of positional parameters
+(in decimal).
+Used, for example, in the \fIappend\fP command
+to check the number of parameters.
+.IP \fB$$\fP 8
+The process number of this shell (in decimal).
+Since process numbers are unique among
+all existing processes, this string is
+frequently used to generate
+unique
+temporary file names.
+For example,
+.DS
+       ps a >/tmp/ps$$
+       \*(ZZ
+       rm /tmp/ps$$
+.DE
+.IP \fB$\|!\fP 8
+The process number of the last process
+run in the background (in decimal).
+.IP \fB$\(mi\fP 8
+The current shell flags, such as
+\fB\(mix\fR and \fB\(miv\|.\fR
+.RE
+.LP
+Some variables have a special meaning to the
+shell and should be avoided for general
+use.
+.RS
+.IP \fB$\s-1MAIL\s0\fP 8
+When used interactively
+the shell looks at the file
+specified by this variable
+before it issues a prompt.
+If the specified file has been modified
+since it
+was last looked at the shell
+prints the message
+\fIyou have mail\fP before prompting
+for the next command.
+This variable is typically set
+in the file \fB.profile,\fP
+in the user's login directory.
+For example,
+.DS
+       \s-1MAIL\s0=/usr/mail/fred
+.DE
+.IP \fB$\s-1HOME\s0\fP 8
+The default argument
+for the \fIcd\fP command.
+The current directory is used to resolve
+file name references that do not begin with
+a \fB/\|,\fR
+and is changed using the \fIcd\fP command.
+For example,
+.DS
+       cd /usr/fred/bin
+.DE
+makes the current directory \fB/usr/fred/bin\|.\fR
+.DS
+       cat wn
+.DE
+will print on the terminal the file \fIwn\fP
+in this directory.
+The command
+\fIcd\fP with no argument
+is equivalent to
+.DS
+       cd $\s-1HOME\s0
+.DE
+This variable is also typically set in the
+the user's login profile.
+.IP \fB$\s-1PATH\s0\fP 8
+A list of directories that contain commands (the \fIsearch path\fR\|).
+Each time a command is executed by the shell
+a list of directories is searched
+for an executable file.
+.ne 5
+If \fB$\s-1PATH\s0\fP is not set
+then the current directory,
+\fB/bin\fP, and \fB/usr/bin\fP are searched by default.
+.ne 5
+Otherwise \fB$\s-1PATH\s0\fP consists of directory
+names separated by \fB:\|.\fP
+For example,
+.DS
+       \s-1PATH\s0=\fB:\fP/usr/fred/bin\fB:\fP/bin\fB:\fP/usr/bin
+.DE
+specifies that the current directory
+(the null string before the first \fB:\fP\|),
+\fB/usr/fred/bin, /bin \fRand\fP /usr/bin\fR
+are to be searched in that order.
+In this way individual users
+can have their own `private' commands
+that are accessible independently
+of the current directory.
+If the command name contains a \fB/\fR then this directory search
+is not used; a single attempt
+is made to execute the command.
+.IP \fB$\s-1PS1\s0\fP 8
+The primary shell prompt string, by default, `\fB$\ \fR'.
+.IP \fB$\s-1PS2\s0\fP 8
+The shell prompt when further input is needed,
+by default, `\fB>\ \fR'.
+.IP \fB$\s-1IFS\s0\fP 8
+The set of characters used by \fIblank
+interpretation\fR (see section 3.4).
+.RE
+.SH
+2.5\ The\ test\ command
+.LP
+The \fItest\fP command, although not part of the shell,
+is intended for use by shell programs.
+For example,
+.DS
+       test \(mif file
+.DE
+returns zero exit status if \fIfile\fP
+exists and non-zero exit status otherwise.
+In general \fItest\fP evaluates a predicate
+and returns the result as its exit status.
+Some of the more frequently used \fItest\fP
+arguments are given here, see \fItest\fP (1)
+for a complete specification.
+.DS
+       test s          true if the argument \fIs\fP is not the null string
+       test \(mif file true if \fIfile\fP exists
+       test \(mir file true if \fIfile\fP is readable
+       test \(miw file true if \fIfile\fP is writable
+       test \(mid file true if \fIfile\fP is a directory
+.DE
+.SH
+2.6\ Control\ flow\ -\ while
+.LP
+The actions of
+the \fBfor\fP loop and the \fBcase\fP
+branch are determined by data available to the shell.
+A \fBwhile\fP or \fBuntil\fP loop
+and an \fBif then else\fP branch
+are also provided whose
+actions are determined by the exit status
+returned by commands.
+A \fBwhile\fP loop has the general form
+.DS
+       \fBwhile\fP \fIcommand-list\*1\fP
+       \fBdo\fP \fIcommand-list\*2\fP
+       \fBdone\fP
+.DE
+.LP
+The value tested by the \fBwhile\fP command
+is the exit status of the last simple command
+following \fBwhile.\fP
+Each time round the loop
+\fIcommand-list\*1\fP is executed;
+if a zero exit status is returned then
+\fIcommand-list\*2\fP
+is executed;
+otherwise, the loop terminates.
+For example,
+.DS
+       while test $1
+       do \*(ZZ
+       \*(DOshift
+       done
+.DE
+is equivalent to
+.DS
+       for i
+       do \*(ZZ
+       done
+.DE
+\fIshift\fP is a shell command that
+renames the positional parameters
+\fB$2, $3, \*(ZZ\fR as \fB$1, $2, \*(ZZ\fR
+and loses \fB$1\|.\fP
+.LP
+Another kind of use for the \fBwhile/until\fP
+loop is to wait until some
+external event occurs and then run
+some commands.
+In an \fBuntil\fP loop
+the termination condition is reversed.
+For example,
+.DS
+       until test \(mif file
+       do sleep 300; done
+       \fIcommands\fP
+.DE
+will loop until \fIfile\fP exists.
+Each time round the loop it waits for
+5 minutes before trying again.
+(Presumably another process
+will eventually create the file.)
+.SH
+2.7\ Control\ flow\ -\ if
+.LP
+Also available is a
+general conditional branch
+of the form,
+.DS
+       \fBif\fP \fIcommand-list
+       \fBthen \fIcommand-list
+       \fBelse \fIcommand-list
+       \fBfi\fR
+.DE
+that tests the value returned by the last simple command
+following \fBif.\fP
+.LP
+The \fBif\fP command may be used
+in conjunction with the \fItest\fP command
+to test for the existence of a file as in
+.DS
+       if test \(mif file
+       then    \fIprocess file\fP
+       else    \fIdo something else\fP
+       fi
+.DE
+.LP
+An example of the use of \fBif, case\fP
+and \fBfor\fP constructions is given in
+section 2.10\|.
+.LP
+A multiple test \fBif\fP command
+of the form
+.DS
+       if \*(ZZ
+       then    \*(ZZ
+       else    if \*(ZZ
+               then    \*(ZZ
+               else    if \*(ZZ
+                       \*(ZZ
+                       fi
+               fi
+       fi
+.DE
+may be written using an extension of the \fBif\fP
+notation as,
+.DS
+       if \*(ZZ
+       then    \*(ZZ
+       elif    \*(ZZ
+       then    \*(ZZ
+       elif    \*(ZZ
+       \*(ZZ
+       fi
+.DE
+.LP
+The following example is the \fItouch\fP command
+which changes the `last modified' time for a list
+of files.
+The command may be used in conjunction
+with \fImake\fP (1) to force recompilation of a list
+of files.
+.DS
+       flag=
+       for i
+       do case $i in
+       \*(DC\(mic)     flag=N ;;
+       \*(DC\*(ST)     if test \(mif $i
+       \*(DC   then    ln $i junk$$; rm junk$$
+       \*(DC   elif test $flag
+       \*(DC   then    echo file \\\\\'$i\\\\\' does not exist
+       \*(DC   else    >$i
+       \*(DC   fi
+       \*(DO esac
+       done
+.DE
+The \fB\(mic\fP flag is used in this command to
+force subsequent files to be created if they do not already exist.
+Otherwise, if the file does not exist, an error message is printed.
+The shell variable \fIflag\fP
+is set to some non-null string if the \fB\(mic\fP
+argument is encountered.
+The commands
+.DS
+       ln \*(ZZ; rm \*(ZZ
+.DE
+make a link to the file and then remove it
+thus causing the last modified date to be updated.
+.LP
+The sequence
+.DS
+       if command1
+       then    command2
+       fi
+.DE
+may be written
+.DS
+       command1 && command2
+.DE
+Conversely,
+.DS
+       command1 \*(VT\*(VT command2
+.DE
+executes \fIcommand2\fP only if \fIcommand1\fP
+fails.
+In each case the value returned
+is that of the last simple command executed.
+.SH
+2.8\ Command\ grouping
+.LP
+Commands may be grouped in two ways,
+.DS
+       \fB{\fI command-list\fB ; }\fR
+.DE
+and
+.DS
+       \fB(\fI command-list\fB )\fR
+.DE
+.LP
+In the first \fIcommand-list\fP is simply executed.
+The second form executes \fIcommand-list\fP
+as a separate process.
+For example,
+.DS
+       (cd x; rm junk )
+.DE
+executes \fIrm junk\fP in the directory
+\fBx\fP without changing the current
+directory of the invoking shell.
+.LP
+The commands
+.DS
+       cd x; rm junk
+.DE
+have the same effect but leave the invoking
+shell in the directory \fBx.\fP
+.SH
+2.9\ Debugging\ shell\ procedures
+.LP
+The shell provides two tracing mechanisms
+to help when debugging shell procedures.
+The first is invoked within the procedure
+as
+.DS
+       set \(miv
+.DE
+(\fBv\fP for verbose) and causes lines of the
+procedure to be printed as they are read.
+It is useful to help isolate syntax errors.
+It may be invoked without modifying the procedure
+by saying
+.DS
+       sh \(miv proc \*(ZZ
+.DE
+where \fIproc\fP is the name of the shell procedure.
+This flag may be used in conjunction
+with the \fB\(min\fP flag which prevents
+execution of subsequent commands.
+(Note that saying \fIset \(min\fP at a terminal
+will render the terminal useless
+until an end-of-file is typed.)
+.LP
+The command
+.DS
+       set \(mix
+.DE
+will produce an execution
+trace.
+Following parameter substitution
+each command is printed as it is executed.
+(Try these at the terminal to see
+what effect they have.)
+Both flags may be turned off by saying
+.DS
+       set \(mi
+.DE
+and the current setting of the shell flags is available as \fB$\(mi\|.\fR
+.SH
+2.10\ The\ man\ command
+.LP
+The following is the \fIman\fP command
+which is used to print sections of the UNIX manual.
+It is called, for example, as
+.DS
+               man sh
+               man \(mit ed
+               man 2 fork
+.DE
+In the first the manual section for \fIsh\fP
+is printed.
+Since no section is specified, section 1 is used.
+The second example will typeset (\fB\(mit\fP option)
+the manual section for \fIed.\fP
+The last prints the \fIfork\fP manual page
+from section 2.
+.sp 2
+.DS
+       cd /usr/man
+
+       : \'colon is the comment command\'
+       : \'default is nroff ($N), section 1 ($s)\'
+       N=n\ s=1
+
+       for i
+       do case $i in
+.sp .5
+       \*(DC[1\(mi9]\*(ST)     s=$i ;;
+.sp .5
+       \*(DC\(mit)     N=t ;;
+.sp .5
+       \*(DC\(min)     N=n ;;
+.sp .5
+       \*(DC\(mi\*(ST) echo unknown flag \\\\\'$i\\\\\' ;;
+.sp .5
+       \*(DC\*(ST)     if test \(mif man$s/$i.$s
+       \*(DC   then    ${N}roff man0/${N}aa man$s/$i.$s
+       \*(DC   else    : \'look through all manual sections\'
+       \*(DC           found=no
+       \*(DC           for j in 1 2 3 4 5 6 7 8 9
+       \*(DC           do if test \(mif man$j/$i.$j
+       \*(DC           \*(DOthen man $j $i
+       \*(DC           \*(DO\*(THfound=yes
+       \*(DC           \*(DOfi
+       \*(DC           done
+       \*(DC           case $found in
+       \*(DC           \*(Cano) echo \\'$i: manual page not found\\'
+       \*(DC           esac
+       \*(DC   fi
+       \*(DOesac
+       done
+.DE
+.ce
+.ft B
+Figure 1. A version of the man command
+.ft R
diff --git a/usr/doc/shell/t3 b/usr/doc/shell/t3
new file mode 100644 (file)
index 0000000..6e7b0ee
--- /dev/null
@@ -0,0 +1,817 @@
+.bp
+.SH
+3.0\ Keyword\ parameters
+.LP
+Shell variables may be given values
+by assignment
+or when a shell procedure is invoked.
+An argument to a shell procedure of the form
+\fIname=value\fP
+that precedes the command name
+causes \fIvalue\fP
+to be assigned to \fIname\fP
+before execution of the procedure begins.
+The value of \fIname\fP in the invoking
+shell is not affected.
+For example,
+.DS
+       user=fred\ command
+.DE
+will execute \fIcommand\fP with
+\fBuser\fP set to \fIfred\fP.
+The \fB\(mik\fR flag causes arguments of the form
+\fIname=value\fP to be interpreted in this way
+anywhere in the argument list.
+Such \fInames\fP are sometimes
+called keyword parameters.
+If any arguments remain they
+are available as positional
+parameters \fB$1, $2, \*(ZZ\|.\fP
+.LP
+The \fIset\fP command
+may also be used to set positional parameters
+from within a procedure.
+For example,
+.DS
+       set\ \(mi\ \*(ST
+.DE
+will set \fB$1\fP to the first file name
+in the current directory, \fB$2\fP to the next,
+and so on.
+Note that the first argument, \(mi, ensures correct treatment
+when the first file name begins with a \(mi\|.
+.LP
+.SH
+3.1\ Parameter\ transmission
+.LP
+When a shell procedure is invoked both positional
+and keyword parameters may be supplied with the call.
+Keyword parameters are also made available implicitly
+to a shell procedure
+by specifying in advance that such parameters
+are to be exported.
+For example,
+.DS
+       export\ user\ box
+.DE
+marks the variables \fBuser\fP and \fBbox\fP
+for export.
+When a shell procedure is invoked
+copies are made of all exportable variables
+for use within the invoked procedure.
+Modification of such variables
+within the procedure does not
+affect the values in the invoking shell.
+It is generally true of
+a shell procedure
+that it
+may not modify the state
+of its caller without explicit
+request on the part of the caller.
+(Shared file descriptors are an
+exception to this rule.)
+.LP
+Names whose value is intended to remain
+constant may be declared \fIreadonly\|.\fP
+The form of this command is the same as that of the \fIexport\fP
+command,
+.DS
+       readonly name \*(ZZ
+.DE
+Subsequent attempts to set readonly variables
+are illegal.
+.SH
+3.2\ Parameter\ substitution
+.LP
+If a shell parameter is not set
+then the null string is substituted for it.
+For example, if the variable \fBd\fP
+is not set
+.DS
+       echo $d
+.DE
+or
+.DS
+       echo ${d}
+.DE
+will echo nothing.
+A default string may be given
+as in
+.DS
+       echo ${d\(mi\fB.\fR}
+.DE
+which will echo
+the value of the variable \fBd\fP
+if it is set and `\fB.\fP' otherwise.
+The default string is evaluated using the usual
+quoting conventions so that
+.DS
+       echo ${d\(mi\'\*(ST\'}
+.DE
+will echo \fB\*(ST\fP if the variable \fBd\fP
+is not set.
+Similarly
+.DS
+       echo ${d\(mi$1}
+.DE
+will echo the value of \fBd\fP if it is set
+and the value (if any) of \fB$1\fP otherwise.
+A variable may be assigned a default value
+using
+the notation
+.DS
+       echo ${d=\fB.\fR}
+.DE
+which substitutes the same string as
+.DS
+       echo ${d\(mi\fB.\fR}
+.DE
+and if \fBd\fP were not previously set
+then it will be set to the string `\fB.\fP'\|.
+(The notation ${\*(ZZ=\*(ZZ}
+is not available for positional parameters.)
+.LP
+If there is no sensible default then
+the notation
+.DS
+       echo ${d?message}
+.DE
+will echo the value of the variable \fBd\fP if it has
+one, otherwise \fImessage\fP is printed by the shell and
+execution of the shell procedure is abandoned.
+If \fImessage\fP is absent then a standard message
+is printed.
+A shell procedure that requires some parameters
+to be set might start as follows.
+.DS
+       :\ ${user?}\ ${acct?}\ ${bin?}
+       \*(ZZ
+.DE
+Colon (\fB:\fP) is a command
+that is
+built in to the shell and does nothing
+once its arguments have been evaluated.
+If any of the variables \fBuser, acct\fP
+or \fBbin\fP are not set then the shell
+will abandon execution of the procedure.
+.SH
+3.3\ Command\ substitution
+.LP
+The standard output from a command can be
+substituted in a similar way to parameters.
+The command \fIpwd\fP prints on its standard
+output the name of the current directory.
+For example, if the current directory is
+\fB/usr/fred/bin\fR
+then the command
+.DS
+       d=\`pwd\`
+.DE
+is equivalent to
+.DS
+       d=/usr/fred/bin
+.DE
+.LP
+The entire string between grave accents (\`\*(ZZ\`)
+is taken as the command
+to be executed
+and is replaced with the output from
+the command.
+The command is written using the usual
+quoting conventions
+except that a \fB\`\fR must be escaped using
+a \fB\\\|.\fR
+For example,
+.DS
+       ls \`echo "$1"\`
+.DE
+is equivalent to
+.DS
+       ls $1
+.DE
+Command substitution occurs in all contexts
+where parameter substitution occurs (including \fIhere\fP documents) and the
+treatment of the resulting text is the same
+in both cases.
+This mechanism allows string
+processing commands to be used within
+shell procedures.
+An example of such a command is \fIbasename\fP
+which removes a specified suffix from a string.
+For example,
+.DS
+       basename main\fB.\fPc \fB.\fPc
+.DE
+will print the string \fImain\|.\fP
+Its use is illustrated by the following
+fragment from a \fIcc\fP command.
+.DS
+       case $A in
+       \*(Ca\*(ZZ
+       \*(Ca\*(ST\fB.\fPc)     B=\`basename $A \fB.\fPc\`
+       \*(Ca\*(ZZ
+       esac
+.DE
+that sets \fBB\fP to the part of \fB$A\fP
+with the suffix \fB.c\fP stripped.
+.LP
+Here are some composite examples.
+.RS
+.IP \(bu
+.ft B
+for i in \`ls \(mit\`; do \*(ZZ
+.ft R
+.br
+The variable \fBi\fP is set
+to the names of files in time order,
+most recent first.
+.IP \(bu
+.ft B
+set \`date\`; echo $6 $2 $3, $4
+.ft R
+.br
+will print, e.g.,
+.ft I
+1977 Nov 1, 23:59:59
+.ft R
+.RE
+.SH
+3.4\ Evaluation\ and\ quoting
+.LP
+The shell is a macro processor that
+provides parameter substitution, command substitution and file
+name generation for the arguments to commands.
+This section discusses the order in which
+these evaluations occur and the
+effects of the various quoting mechanisms.
+.LP
+Commands are parsed initially according to the grammar
+given in appendix A.
+Before a command is executed
+the following
+substitutions occur.
+.RS
+.IP \(bu
+parameter substitution, e.g. \fB$user\fP
+.IP \(bu
+command substitution, e.g. \fB\`pwd\`\fP
+.RS
+.LP
+Only one evaluation occurs so that if, for example, the value of the variable
+\fBX\fP
+is the string \fI$y\fP
+then
+.DS
+       echo $X
+.DE
+will echo \fI$y\|.\fP
+.RE
+.IP \(bu
+blank interpretation
+.RS
+.LP
+Following the above substitutions
+the resulting characters
+are broken into non-blank words (\fIblank interpretation\fP).
+For this purpose `blanks' are the characters of the string
+\fB$\s-1IFS\s0\fP.
+By default, this string consists of blank, tab and newline.
+The null string
+is not regarded as a word unless it is quoted.
+For example,
+.DS
+       echo \'\'
+.DE
+will pass on the null string as the first argument to \fIecho\fP,
+whereas
+.DS
+       echo $null
+.DE
+will call \fIecho\fR with no arguments
+if the variable \fBnull\fP is not set
+or set to the null string.
+.RE
+.IP \(bu
+file name generation
+.RS
+.LP
+Each word
+is then scanned for the file pattern characters
+\fB\*(ST, ?\fR and \fB[\*(ZZ]\fR
+and an alphabetical list of file names
+is generated to replace the word.
+Each such file name is a separate argument.
+.RE
+.RE
+.LP
+The evaluations just described also occur
+in the list of words associated with a \fBfor\fP
+loop.
+Only substitution occurs
+in the \fIword\fP used
+for a \fBcase\fP branch.
+.LP
+As well as the quoting mechanisms described
+earlier using \fB\\\fR and \fB\'\*(ZZ\'\fR
+a third quoting mechanism is provided using double quotes.
+Within double quotes parameter and command substitution
+occurs but file name generation and the interpretation
+of blanks does not.
+The following characters
+have a special meaning within double quotes
+and may be quoted using \fB\\\|.\fP
+.DS
+       \fB$    \fPparameter substitution
+       \fB\`\fP        command substitution
+       \fB"\fP ends the quoted string
+       \fB\e\fP        quotes the special characters \fB$ \` " \e\fP
+.DE
+For example,
+.DS
+       echo "$x"
+.DE
+will pass the value of the variable \fBx\fP as a
+single argument to \fIecho.\fP
+Similarly,
+.DS
+       echo "$\*(ST"
+.DE
+will pass the positional parameters as a single
+argument and is equivalent to
+.DS
+       echo "$1 $2 \*(ZZ"
+.DE
+The notation \fB$@\fP
+is the same as \fB$\*(ST\fR
+except when it is quoted.
+.DS
+       echo "$@"
+.DE
+will pass the positional parameters, unevaluated, to \fIecho\fR
+and is equivalent to
+.DS
+       echo "$1" "$2" \*(ZZ
+.DE
+.LP
+The following table gives, for each quoting mechanism,
+the shell metacharacters that are evaluated.
+.DS
+.ce
+.ft I
+metacharacter
+.ft
+.in 1.5i
+       \e      $       *       \`      "       \'
+\'     n       n       n       n       n       t
+\`     y       n       n       t       n       n
+"      y       y       n       y       t       n
+
+       t       terminator
+       y       interpreted
+       n       not interpreted
+
+.in
+.ft B
+.ce
+Figure 2. Quoting mechanisms
+.ft
+.DE
+.LP
+In cases where more than one evaluation of a string
+is required the built-in command \fIeval\fP
+may be used.
+For example,
+if the variable \fBX\fP has the value
+\fI$y\fP, and if \fBy\fP has the value \fIpqr\fP
+then
+.DS
+       eval echo $X
+.DE
+will echo the string \fIpqr\|.\fP
+.LP
+In general the \fIeval\fP command
+evaluates its arguments (as do all commands)
+and treats the result as input to the shell.
+The input is read and the resulting command(s)
+executed.
+For example,
+.DS
+       wg=\\'eval who\*(VTgrep\\'
+       $wg fred
+.DE
+is equivalent to
+.DS
+       who\*(VTgrep fred
+.DE
+In this example,
+\fIeval\fP is required
+since there is no interpretation
+of metacharacters, such as \fB\*(VT\|,\fP following
+substitution.
+.SH
+3.5\ Error\ handling
+.LP
+The treatment of errors detected by
+the shell depends on the type of error
+and on whether the shell is being
+used interactively.
+An interactive shell is one whose
+input and output are connected
+to a terminal (as determined by
+\fIgtty\fP (2)).
+A shell invoked with the \fB\(mii\fP
+flag is also interactive.
+.LP
+Execution of a command (see also 3.7) may fail
+for any of the following reasons.
+.IP \(bu
+Input output redirection may fail.
+For example, if a file does not exist
+or cannot be created.
+.IP \(bu
+The command itself does not exist
+or cannot be executed.
+.IP \(bu
+The command terminates abnormally,
+for example, with a "bus error"
+or "memory fault".
+See Figure 2 below for a complete list
+of UNIX signals.
+.IP \(bu
+The command terminates normally
+but returns a non-zero exit status.
+.LP
+In all of these cases the shell
+will go on to execute the next command.
+Except for the last case an error
+message will be printed by the shell.
+All remaining errors cause the shell
+to exit from a command procedure.
+An interactive shell will return
+to read another command from the terminal.
+Such errors include the following.
+.IP \(bu
+Syntax errors.
+e.g., if \*(ZZ then \*(ZZ done
+.IP \(bu
+A signal such as interrupt.
+The shell waits for the current
+command, if any, to finish execution and
+then either exits or returns to the terminal.
+.IP \(bu
+Failure of any of the built-in commands
+such as \fIcd.\fP
+.LP
+The shell flag \fB\(mie\fP
+causes the shell to terminate
+if any error is detected.
+.DS
+1      hangup
+2      interrupt
+3*     quit
+4*     illegal instruction
+5*     trace trap
+6*     IOT instruction
+7*     EMT instruction
+8*     floating point exception
+9      kill (cannot be caught or ignored)
+10*    bus error
+11*    segmentation violation
+12*    bad argument to system call
+13     write on a pipe with no one to read it
+14     alarm clock
+15     software termination (from \fIkill\fP (1))
+
+.DE
+.ft B
+.ce
+Figure 3. UNIX signals
+.ft
+
+Those signals marked with an asterisk
+produce a core dump
+if not caught.
+However,
+the shell itself ignores quit which is the only
+external signal that can cause a dump.
+The signals in this list of potential interest
+to shell programs are 1, 2, 3, 14 and 15.
+.SH
+3.6\ Fault\ handling
+.LP
+Shell procedures normally terminate
+when an interrupt is received from the
+terminal.
+The \fItrap\fP command is used
+if some cleaning up is required, such
+as removing temporary files.
+For example,
+.DS
+       trap\ \'rm\ /tmp/ps$$; exit\'\ 2
+.DE
+sets a trap for signal 2 (terminal
+interrupt), and if this signal is received
+will execute the commands
+.DS
+       rm /tmp/ps$$; exit
+.DE
+\fIexit\fP is
+another built-in command
+that terminates execution of a shell procedure.
+The \fIexit\fP is required; otherwise,
+after the trap has been taken,
+the shell will resume executing
+the procedure
+at the place where it was interrupted.
+.LP
+UNIX signals can be handled in one of three ways.
+They can be ignored, in which case
+the signal is never sent to the process.
+They can be caught, in which case the process
+must decide what action to take when the
+signal is received.
+Lastly, they can be left to cause
+termination of the process without
+it having to take any further action.
+If a signal is being ignored
+on entry to the shell procedure, for example,
+by invoking it in the background (see 3.7) then \fItrap\fP
+commands (and the signal) are ignored.
+.LP
+The use of \fItrap\fP is illustrated
+by this modified version of the \fItouch\fP
+command (Figure 4).
+The cleanup action is to remove the file \fBjunk$$\fR\|.
+.DS
+       flag=
+       trap\ \'rm\ \(mif\ junk$$;\ exit\'\ 1 2 3 15
+       for i
+       do\ case\ $i\ in
+       \*(DC\(mic)     flag=N ;;
+       \*(DC\*(ST)     if\ test\ \(mif\ $i
+       \*(DC   then    ln\ $i\ junk$$;\ rm\ junk$$
+       \*(DC   elif\ test\ $flag
+       \*(DC   then    echo\ file\ \\\\\'$i\\\\\'\ does\ not\ exist
+       \*(DC   else    >$i
+       \*(DC   fi
+       \*(DOesac
+       done
+.DE
+.sp
+.ft B
+.ce
+Figure 4. The touch command
+.ft
+.sp
+The \fItrap\fP command
+appears before the creation
+of the temporary file;
+otherwise it would be
+possible for the process
+to die without removing
+the file.
+.LP
+Since there is no signal 0 in UNIX
+it is used by the shell to indicate the
+commands to be executed on exit from the
+shell procedure.
+.LP
+A procedure may, itself, elect to
+ignore signals by specifying the null
+string as the argument to trap.
+The following fragment is taken from the
+\fInohup\fP command.
+.DS
+       trap \'\' 1 2 3 15
+.DE
+which causes \fIhangup, interrupt, quit \fRand\fI kill\fR
+to be ignored both by the
+procedure and by invoked commands.
+.LP
+Traps may be reset by saying
+.DS
+       trap 2 3
+.DE
+which resets the traps for signals 2 and 3 to their default values.
+A list of the current values of traps may be obtained
+by writing
+.DS
+       trap
+.DE
+.LP
+The procedure \fIscan\fP (Figure 5) is an example
+of the use of \fItrap\fP where there is no exit
+in the trap command.
+\fIscan\fP takes each directory
+in the current directory, prompts
+with its name, and then executes
+commands typed at the terminal
+until an end of file or an interrupt is received.
+Interrupts are ignored while executing
+the requested commands but cause
+termination when \fIscan\fP is
+waiting for input.
+.DS
+       d=\`pwd\`
+       for\ i\ in\ \*(ST
+       do\ if\ test\ \(mid\ $d/$i
+       \*(DOthen\ cd\ $d/$i
+       \*(DO\*(THwhile\ echo\ "$i:"
+       \*(DO\*(TH\*(WHtrap\ exit\ 2
+       \*(DO\*(TH\*(WHread\ x
+       \*(DO\*(THdo\ trap\ :\ 2;\ eval\ $x;\ done
+       \*(DOfi
+       done
+.DE
+.sp
+.ft B
+.ce
+Figure 5. The scan command
+.ft
+.sp
+\fIread x\fR is a built-in command that reads one line from the
+standard input
+and places the result in the variable \fBx\|.\fP
+It returns a non-zero exit status if either
+an end-of-file is read or an interrupt
+is received.
+.SH
+3.7\ Command\ execution
+.LP
+To run a command (other than a built-in) the shell first creates
+a new process using the system call \fIfork.\fP
+The execution environment for the command
+includes input, output and the states of signals, and
+is established in the child process
+before the command is executed.
+The built-in command \fIexec\fP
+is used in the rare cases when no fork
+is required
+and simply replaces the shell with a new command.
+For example, a simple version of the \fInohup\fP
+command looks like
+.DS
+       trap \\'\\' 1 2 3 15
+       exec $\*(ST
+.DE
+The \fItrap\fP turns off the signals specified
+so that they are ignored by subsequently created commands
+and \fIexec\fP replaces the shell by the command
+specified.
+.LP
+Most forms of input output redirection have already been
+described.
+In the following \fIword\fP is only subject
+to parameter and command substitution.
+No file name generation or blank interpretation
+takes place so that, for example,
+.DS
+               echo \*(ZZ >\*(ST.c
+.DE
+will write its output into a file whose name is \fB\*(ST.c\|.\fP
+Input output specifications are evaluated left to right
+as they appear in the command.
+.IP >\ \fIword\fP 12
+The standard output (file descriptor 1)
+is sent to the file \fIword\fP which is
+created if it does not already exist.
+.IP \*(AP\ \fIword\fP 12
+The standard output is sent to file \fIword.\fP
+If the file exists then output is appended
+(by seeking to the end);
+otherwise the file is created.
+.IP <\ \fIword\fP 12
+The standard input (file descriptor 0)
+is taken from the file \fIword.\fP
+.IP \*(HE\ \fIword\fP 12
+The standard input is taken from the lines
+of shell input that follow up to but not
+including a line consisting only of \fIword.\fP
+If \fIword\fP is quoted then no interpretation
+of the document occurs.
+If \fIword\fP is not quoted
+then parameter and command substitution
+occur and \fB\\\fP is used to quote
+the characters \fB\\\fP \fB$\fP \fB\`\fP and the first character
+of \fIword.\fP
+In the latter case \fB\\newline\fP is ignored (c.f. quoted strings).
+.IP >&\ \fIdigit\fP 12
+The file descriptor \fIdigit\fP is duplicated using the system
+call \fIdup\fP (2)
+and the result is used as the standard output.
+.IP <&\ \fIdigit\fP 12
+The standard input is duplicated from file descriptor \fIdigit.\fP
+.IP <&\(mi 12
+The standard input is closed.
+.IP >&\(mi 12
+The standard output is closed.
+.LP
+Any of the above may be preceded by a digit in which
+case the file descriptor created is that specified by the digit
+instead of the default 0 or 1.
+For example,
+.DS
+       \*(ZZ 2>file
+.DE
+runs a command with message output (file descriptor 2)
+directed to \fIfile.\fP
+.DS
+       \*(ZZ 2>&1
+.DE
+runs a command with its standard output and message output
+merged.
+(Strictly speaking file descriptor 2 is created
+by duplicating file descriptor 1 but the effect is usually to
+merge the two streams.)
+.LP
+The environment for a command run in the background such as
+.DS
+       list \*(ST.c \*(VT lpr &
+.DE
+is modified in two ways.
+Firstly, the default standard input
+for such a command is the empty file \fB/dev/null\|.\fR
+This prevents two processes (the shell and the command),
+which are running in parallel, from trying to
+read the same input.
+Chaos would ensue
+if this were not the case.
+For example,
+.DS
+       ed file &
+.DE
+would allow both the editor and the shell
+to read from the same input at the same time.
+.LP
+The other modification to the environment of a background
+command is to turn off the QUIT and INTERRUPT signals
+so that they are ignored by the command.
+This allows these signals to be used
+at the terminal without causing background
+commands to terminate.
+For this reason the UNIX convention
+for a signal is that if it is set to 1
+(ignored) then it is never changed
+even for a short time.
+Note that the shell command \fItrap\fP
+has no effect for an ignored signal.
+.SH
+3.8\ Invoking\ the\ shell
+.LP
+The following flags are interpreted by the shell
+when it is invoked.
+If the first character of argument zero is a minus,
+then commands are read from the file \fB.profile\|.\fP
+.IP \fB\(mic\fP\ \fIstring\fP
+.br
+If the \fB\(mic\fP flag is present then
+commands are read from \fIstring\|.\fP
+.IP \fB\(mis\fP
+If the \fB\(mis\fP flag is present or if no
+arguments remain
+then commands are read from the standard input.
+Shell output is written to
+file descriptor 2.
+.IP \fB\(mii\fP
+If the \fB\(mii\fP flag is present or
+if the shell input and output are attached to a terminal (as told by \fIgtty\fP)
+then this shell is \fIinteractive.\fP
+In this case TERMINATE is ignored (so that \fBkill 0\fP
+does not kill an interactive shell) and INTERRUPT is caught and ignored
+(so that \fBwait\fP is interruptable).
+In all cases QUIT is ignored by the shell.
+.SH
+Acknowledgements
+.LP
+The design of the shell is
+based in part on the original UNIX shell
+.[
+unix command language thompson
+.]
+and the PWB/UNIX shell,
+.[
+pwb shell mashey unix
+.]
+some
+features having been taken from both.
+Similarities also exist with the
+command interpreters
+of the Cambridge Multiple Access System
+.[
+cambridge multiple access system hartley
+.]
+and of CTSS.
+.[
+ctss
+.]
+.LP
+I would like to thank Dennis Ritchie
+and John Mashey for many
+discussions during the design of the shell.
+I am also grateful to the members of the Computing Science Research Center
+and to Joe Maranzano for their
+comments on drafts of this document.
+.SH
+.[
+$LIST$
+.]
diff --git a/usr/doc/shell/t4 b/usr/doc/shell/t4
new file mode 100644 (file)
index 0000000..380c867
--- /dev/null
@@ -0,0 +1,134 @@
+.bp
+.SH
+Appendix\ A\ -\ Grammar
+.LP
+.DS
+\fIitem:               word
+               input-output
+               name = value
+.sp 0.8
+simple-command: item
+               simple-command item
+.sp 0.8
+command:       simple-command
+               \fB( \fIcommand-list \fB)
+               \fB{ \fIcommand-list \fB}
+               \fBfor \fIname \fBdo \fIcommand-list \fBdone
+               \fBfor \fIname \fBin \fIword \*(ZZ \fBdo \fIcommand-list \fBdone
+               \fBwhile \fIcommand-list \fBdo \fIcommand-list \fBdone
+               \fBuntil \fIcommand-list \fBdo \fIcommand-list \fBdone
+               \fBcase \fIword \fBin \fIcase-part \*(ZZ \fBesac
+               \fBif \fIcommand-list \fBthen \fIcommand-list \fIelse-part \fBfi
+.sp 0.8
+\fIpipeline:           command
+               pipeline \fB\*(VT\fI command
+.sp 0.8
+andor:         pipeline
+               andor \fB&&\fI pipeline
+               andor \fB\*(VT\*(VT\fI pipeline
+.sp 0.8
+command-list:  andor
+               command-list \fB;\fI
+               command-list \fB&\fI
+               command-list \fB;\fI andor
+               command-list \fB&\fI andor
+.sp 0.8
+input-output:  \fB> \fIfile
+               \fB< \fIfile
+               \fB\*(AP \fIword
+               \fB\*(HE \fIword
+.sp 0.8
+file:          word
+               \fB&\fI digit
+               \fB&\fI \(mi
+.sp 0.8
+case-part:     pattern\fB ) \fIcommand-list\fB ;;
+.sp 0.8
+\fIpattern:            word
+               pattern \fB\*(VT\fI word
+.sp 0.8
+\fIelse-part:  \fBelif \fIcommand-list\fB then\fI command-list else-part\fP
+               \fBelse \fIcommand-list\fI
+               empty
+.sp 0.8
+empty:
+.sp 0.8
+word:          \fRa sequence of non-blank characters\fI
+.sp 0.8
+name:          \fRa sequence of letters, digits or underscores starting with a letter\fI
+.sp 0.8
+digit:         \fB0 1 2 3 4 5 6 7 8 9\fP
+.DE
+.LP
+.bp
+.SH
+Appendix\ B\ -\ Meta-characters\ and\ Reserved\ Words
+.LP
+a) syntactic
+.RS
+.IP \fB\*(VT\fR 6
+pipe symbol
+.IP \fB&&\fR 6
+`andf' symbol
+.IP \fB\*(VT\*(VT\fR 6
+`orf' symbol
+.IP \fB;\fP 6
+command separator
+.IP \fB;;\fP 6
+case delimiter
+.IP \fB&\fP 6
+background commands
+.IP \fB(\ )\fP 6
+command grouping
+.IP \fB<\fP 6
+input redirection
+.IP \fB\*(HE\fP 6
+input from a here document
+.IP \fB>\fP 6
+output creation
+.IP \fB\*(AP\fP 6
+output append
+.sp 2
+.RE
+.LP
+b) patterns
+.RS
+.IP \fB\*(ST\fP 6
+match any character(s) including none
+.IP \fB?\fP 6
+match any single character
+.IP \fB[...]\fP 6
+match any of the enclosed characters
+.sp 2
+.RE
+.LP
+c) substitution
+.RS
+.IP \fB${...}\fP 6
+substitute shell variable
+.IP \fB\`...\`\fP 6
+substitute command output
+.sp 2
+.RE
+.LP
+d) quoting
+.RS
+.IP \fB\e\fP 6
+quote the next character
+.IP \fB\'...\'\fP 6
+quote the enclosed characters except for \'
+.IP \fB"\&..."\fR 6
+quote the enclosed characters except
+for \fB$ \` \e "\fP
+.sp 2
+.RE
+.LP
+e) reserved words
+.DS
+.ft B
+if then else elif fi
+case in esac
+for while until do done
+{  }
+.ft
+.DE