+.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$
+.]