2523 lines
62 KiB
Plaintext
2523 lines
62 KiB
Plaintext
.ds DT November 16, 1988 \" use troff -mm
|
|
.nr N 2
|
|
.SA 1 \" right justified
|
|
.TL "311531-0101" "49059-6" \" charging case filing case
|
|
Introduction to \f3ksh\fP ( Issue 4)
|
|
.AU "David G. Korn" DGK MH 59113 7975 3C-526B "(ulysses!dgk)"
|
|
.TM 59113-881116-?? \" technical memo + TM numbers
|
|
.AS 1 \" abstract start for TM
|
|
\f3ksh\fP is a program that serves as a command language
|
|
(shell) for the UNIX*\
|
|
.FS *
|
|
UNIX is a registered trademark of AT&T
|
|
.FE
|
|
operating system.
|
|
It is essentially compatible with the System V version of the Bourne shell\*(Rf ,
|
|
.RS
|
|
S. R. Bourne,
|
|
.I "An Introduction to the UNIX
|
|
Shell,"
|
|
BSTJ - Vol. 57, No. 6 part 2, pages 1947-1972.
|
|
.RF
|
|
has many additional features,
|
|
such as those found in
|
|
the C Shell\*(Rf,
|
|
.RS
|
|
W. Joy,
|
|
.I "An Introduction to the C Shell,"
|
|
University of California, Berkeley, 1980.
|
|
.RF
|
|
and executes faster than either of these shells.
|
|
This memo introduces many of the additional features
|
|
and explains some of the reasons for the better
|
|
performance.
|
|
This memo
|
|
assumes that the reader is already familiar with the Bourne shell.
|
|
This memo has been substantially revised
|
|
since its last release
|
|
because \f3ksh\fP has changed significantly.
|
|
The Appendix contains
|
|
a sample script written in \f3ksh\fP.
|
|
The manual page for the current version is also included.
|
|
.AE \" abstract end
|
|
.OK Shell "Command interpreter" Language UNIX \" keyword
|
|
.MT 1 \" memo type
|
|
.H 1 "Introduction"
|
|
.P
|
|
The term "shell" is used to describe a program that provides
|
|
a command language
|
|
interface.
|
|
Because the UNIX*\
|
|
.FS *
|
|
UNIX is a registered trademark of AT&T
|
|
.FE
|
|
system shell is a user level program, and not part of
|
|
the operating system itself,
|
|
anyone can write a new shell or modify an existing one.
|
|
This has caused an evolutionary progress
|
|
in the design and implementation of shells,
|
|
with the better ones surviving.
|
|
The most widely available UNIX system shells are the Bourne shell\*(Rf,
|
|
.RS
|
|
S. R. Bourne,
|
|
.IR "An Introduction to the UNIX Shell" ,
|
|
Bell System Technical Journal,
|
|
Vol. 57, No. 6, Part 2, pp. 1947-1972, July 1978.
|
|
.RF
|
|
written by Steve Bourne
|
|
at AT&T Bell Laboratories,
|
|
the C shell\*(Rf,
|
|
.RS
|
|
W. Joy,
|
|
.IR "An Introduction to the C Shell" ,
|
|
Unix Programmer's Manual, Berkeley Software Distribution,
|
|
University of California, Berkeley, 1980.
|
|
.RF
|
|
written by Bill Joy at the University of California, Berkeley,
|
|
and the KornShell language \*(Rf,
|
|
.RS
|
|
Morris Bolsky and David Korn,
|
|
.IR "The KornShell Command and Programming Language" ,
|
|
Prentice Hall, 1989.
|
|
.RF
|
|
written by David Korn
|
|
at AT&T Bell Laboratories.
|
|
The Bourne shell is available on almost all versions of the UNIX
|
|
system.
|
|
The C Shell is available with all Berkeley Software Distribution,
|
|
BSD, UNIX systems.
|
|
.B ksh
|
|
is available in binary form on several systems.
|
|
The source for the KornShell language is available from the AT&T Toolchest,
|
|
an electronic software distribution system.
|
|
It runs on all known versions of the UNIX system and
|
|
on many UNIX system look-alikes.
|
|
.P
|
|
There have been several recent articles comparing the UNIX system shells.
|
|
Jason Levitt\*(Rf
|
|
.RS
|
|
Jason Levitt,
|
|
.IR "The Korn Shell: An Emerging Standard" ,
|
|
UNIX/World, pp. 74-81, September 1986.
|
|
.RF
|
|
highlights some of the new features
|
|
introduced by the KornShell language.
|
|
Rich Bilancia\*(Rf
|
|
.RS
|
|
Rich Bilancia,
|
|
.IR "Proficiency and Power are Yours With the Korn Shell" ,
|
|
UNIX/World, pp. 103-107, September 1987.
|
|
.RF
|
|
explains some of the advantages of using the KornShell language.
|
|
John Sebes\*(Rf
|
|
.RS
|
|
John Sebes,
|
|
.I "Comparing UNIX Shells,"
|
|
UNIX Papers,
|
|
Edited by the Waite Group, Howard W. Sams & Co., 1987.
|
|
.RF
|
|
provides a more detailed comparison of the three shells,
|
|
both as a command language and as a programming language.
|
|
He states, "[The new KornShell language] turns out to be the best for
|
|
most applications. [It] has a host of new features that are
|
|
significant improvements over both the C shell and Bourne shell."
|
|
.P
|
|
The KornShell language is a superset of the
|
|
Bourne shell. The KornShell language has many of the popular C shell features,
|
|
plus additional features of its own.
|
|
Its initial popularity stems primarily from its improvements as
|
|
a command language.
|
|
The primary interactive benefit of the KornShell command language
|
|
is a visual command line editor that allows you to
|
|
make corrections to your current command line
|
|
or to earlier command lines,
|
|
without having to retype them.
|
|
However,
|
|
in the long run,
|
|
the power of the KornShell language as a high-level programming language,
|
|
as described by Dolotta and Mashey\*(Rf,
|
|
.RS
|
|
T. A. Dolotta and J. R. Mashey,
|
|
.I "Using the shell as a Primary Programming Tool,"
|
|
Proc. 2nd. Int. Conf. on Software Engineering, 1976,
|
|
pages 169-176.
|
|
.RF
|
|
may prove to be of greater significance.
|
|
An application that was originally written in the C programming language
|
|
was rewritten in the KornShell language.
|
|
More than 20,000 lines of C code were replaced with KornShell scripts
|
|
totaling fewer than 700 lines.
|
|
In most instances there was no perceptible difference in performance
|
|
between the two versions of the code.
|
|
.P
|
|
This memo is an introduction to
|
|
.BR ksh ,
|
|
the program that implements the KornShell language.
|
|
The memo describes the features of the 11/16/88 release of
|
|
.BR ksh .
|
|
To find the version of
|
|
.B ksh
|
|
you are running, issue the
|
|
.B what
|
|
command on the program, or issue the control-V directive from the emacs
|
|
edit mode.
|
|
This memo is not a tutorial, only an introduction.
|
|
See reference [4] for a more complete treatment of the KornShell language.
|
|
.P
|
|
A concerted effort has been made to achieve System V Bourne shell
|
|
compatibility so that scripts written for the Bourne shell
|
|
can run without modification with \f3ksh\fP.
|
|
The description of features in this memo assumes
|
|
that the reader is already familiar with the Bourne shell.
|
|
.P
|
|
.H 1 "Shell Variables"
|
|
.P
|
|
The ability to define and use variables to store and retrieve values
|
|
is an important feature in most programming languages.
|
|
\f3ksh\fP has variables with
|
|
.I identifier
|
|
names that follow the
|
|
same rules as the Bourne shell.
|
|
Since all variables have string representations,
|
|
there is no need to specify the
|
|
.I type
|
|
of each variable in the shell.
|
|
In \f3ksh\fP,
|
|
each variable can have one or more
|
|
.I attributes
|
|
that control the internal representation of the variable,
|
|
the way the variable is printed, and its access or
|
|
scope.
|
|
Two of the attributes,
|
|
.I readonly
|
|
and
|
|
.IR export ,
|
|
are available in the Bourne shell.
|
|
The
|
|
.B typeset
|
|
built-in command of \f3ksh\fP
|
|
assigns attributes to variables.
|
|
The complete list of attributes,
|
|
some of which are discussed here,
|
|
appears in the manual page.
|
|
The
|
|
.B unset
|
|
built-in of the \f3ksh\fP removes
|
|
values and attributes of parameters.
|
|
When a variable is exported, its attributes are also exported.
|
|
.P
|
|
Whenever a value is assigned to a variable,
|
|
the value is transformed according to the attributes of the variable.
|
|
Changing the attribute of a variable can change its value.
|
|
There are three attributes for field justification,
|
|
as might be needed for formatting a report.
|
|
For each of these attributes, a width can be defined explicitly or else
|
|
it is defined the first time an assignment is made to the variable.
|
|
Each assignment causes justification of the field, truncating
|
|
if necessary.
|
|
Assignment to fixed sized variables
|
|
provides a simple way to generate a substring consisting of
|
|
a fixed number of characters from
|
|
the beginning or end of a string.
|
|
.P
|
|
The attributes
|
|
.B \-u
|
|
and
|
|
.BR \-l ,
|
|
are used for upper case and lower case
|
|
formatting respectively.
|
|
Since it makes no sense to have both attributes on simultaneously,
|
|
turning on either of these attributes turns the other off.
|
|
The following script provides an example of the use of shell variables
|
|
with attributes.
|
|
This script reads a file of lines each consisting of five fields separated by
|
|
.B :
|
|
and prints fields 4 and 2 in upper case in columns 1-15, left justified,
|
|
and columns 20-25 right-justified respectively.
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
.ta 3.4i
|
|
.B
|
|
typeset \-L15u f4 # 15 character left justified
|
|
typeset \-R6u f2 # 6 character right justified
|
|
IFS=:
|
|
set \-f # skip file name generation
|
|
while read \-r f1 f2 f3 f4 f5 # read line, split into fields
|
|
do print \-r "$f4 $f2" # print fields 4 and 2
|
|
done
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
.P
|
|
The integer attribute,
|
|
.BR \-i ,
|
|
causes the variable to be internally represented as an integer.
|
|
The
|
|
.B i
|
|
can be followed by a number representing the numeric base for printing,
|
|
otherwise the first assignment to an
|
|
.I integer
|
|
variable defines the output
|
|
.I base
|
|
(see below).
|
|
This base will be used
|
|
whenever the variable is expanded via
|
|
.B $ .
|
|
Assignment to
|
|
.I integer
|
|
typed variables result in arithmetic evaluation,
|
|
as described below,
|
|
of the right hand side.
|
|
.P
|
|
\f3ksh\fP allows one-dimensional
|
|
.I arrays
|
|
in addition to simple variables.
|
|
Any variable can become an array
|
|
by referring to it with
|
|
a
|
|
.IR subscript .
|
|
All elements of an array need not exist.
|
|
Subscripts for arrays
|
|
must evaluate to an
|
|
integer between 0 and some maximum value, otherwise
|
|
an error results.
|
|
The maximum value may vary from one machine to another but
|
|
is at least 511.
|
|
Evaluation of subscripts is described in
|
|
the next section.
|
|
Attributes apply to the whole array.
|
|
.P
|
|
Assignments to array variables can be made to individual elements
|
|
via parameter
|
|
assignment commands or the
|
|
.B typeset
|
|
built-in.
|
|
Additionally, values can be assigned sequentially using the
|
|
.B \-A
|
|
.I name
|
|
option of the
|
|
.B set
|
|
command.
|
|
Referencing of subscripted variables requires the character
|
|
.BR $ ,
|
|
but also requires braces around the array element name.
|
|
The braces are needed to avoid conflicts with the
|
|
file name generation mechanism.
|
|
The form of any array element reference is:
|
|
.ce
|
|
.BI ${ name [ subscript ]} .
|
|
A subscript value of
|
|
.B *
|
|
or
|
|
.B @
|
|
can be used to generate all elements of an array,
|
|
as they are used for expansion of positional parameters.
|
|
.P
|
|
A few additional operations are available on shell variables.
|
|
\f3${#\fP\f2name\fP\f3}\fP
|
|
will be the length in bytes of
|
|
\f3$\fP\f2name\fP.
|
|
For an array variable
|
|
\f3${#\fP\f2name\fP\f3[*]}\fP
|
|
gives the number of elements in the array.
|
|
.P
|
|
There are four parameter substitution modifiers that
|
|
have been added to strip off leading and trailing substrings
|
|
during parameter substitution.
|
|
The modifier
|
|
.BR # ( ## )
|
|
strips off the smallest (largest) matching pattern from the left
|
|
and the modifier
|
|
.BR % ( %% )
|
|
strips off the smallest (largest) matching pattern from the right.
|
|
For example, if the shell variable
|
|
.B i
|
|
has value
|
|
.BR file.c ,
|
|
then the expression
|
|
.B ${i%.c}.o
|
|
has value
|
|
.BR file.o .
|
|
.H 1 "Pattern Matching"
|
|
The characters
|
|
.BR ? ,
|
|
.BR * ,
|
|
and
|
|
.B [
|
|
are processed specially
|
|
by the shell when not quoted.
|
|
These characters are used to form patterns that
|
|
match strings.
|
|
Patterns are used by the shell to match filenames,
|
|
to specify substrings,
|
|
and for
|
|
.B case
|
|
commands.
|
|
The character
|
|
.B ?
|
|
matches any one character.
|
|
The character
|
|
.B *
|
|
matches zero or more characters.
|
|
The character sequence
|
|
.BR [ ... ]
|
|
defines a character class
|
|
that matches any character contained within
|
|
.BR [] .
|
|
A range of characters can be specified by putting a
|
|
.B \-
|
|
between the first and last character of the range.
|
|
An exclamation mark,
|
|
.BR ! ,
|
|
immediately after the
|
|
.BR [ ,
|
|
means match all characters except the characters specified.
|
|
For example, the pattern
|
|
.B a?c*.[!a\-z]
|
|
matches any string beginning with an
|
|
.BR a ,
|
|
whose third character is a
|
|
.BR c ,
|
|
and that ends in
|
|
.B .
|
|
(dot) followed by any character except the lowercase letters,
|
|
.BR a\-z .
|
|
.P
|
|
.B ksh
|
|
treats
|
|
strings of the form
|
|
.BI ( pattern-list )
|
|
, where
|
|
.I pattern-list
|
|
is a list of one or more patterns separated by a
|
|
.BR \(bv ,
|
|
specially when preceded by
|
|
.BR * ,
|
|
.BR ? ,
|
|
.BR + ,
|
|
.BR @ ,
|
|
or
|
|
.BR ! .
|
|
A
|
|
.B ?
|
|
preceding
|
|
.BI ( pattern-list )
|
|
means that the pattern list enclosed in
|
|
.B ()
|
|
is optional.
|
|
An
|
|
.BI @( pattern-list )
|
|
matches any pattern in the list of patterns enclosed in
|
|
.BR () .
|
|
A
|
|
.BI *( pattern-list )
|
|
matches any string that contains zero or more of each of the enclosed
|
|
patterns,
|
|
whereas
|
|
.BI +( pattern-list )
|
|
requires a match of one or more of any of the given patterns.
|
|
For instance, the pattern
|
|
.B +([0\-9])?(.)
|
|
matches one or more digits optionally followed by a
|
|
.BR . (dot).
|
|
A
|
|
.BI !( pattern-list )
|
|
matches anything except any of the given patterns.
|
|
For example,
|
|
.B "echo !(*.o)"
|
|
will display any file name that does not end in
|
|
.BR .o .
|
|
.H 1 "Arithmetic Evaluation"
|
|
.P
|
|
The built-in command,
|
|
.B let ,
|
|
provides the ability to do integer arithmetic.
|
|
All arithmetic evaluations are performed using
|
|
.I long
|
|
arithmetic.
|
|
Arithmetic constants are written as
|
|
.br
|
|
.ce
|
|
.IB base # number
|
|
where
|
|
.I base
|
|
is a decimal integer between
|
|
two and thirty-six and
|
|
.I number
|
|
is any non-negative number.
|
|
Anything after a decimal point is truncated.
|
|
Base ten is used
|
|
if no base is specified.
|
|
.P
|
|
Arithmetic expressions are made from constants,
|
|
variables, and one or more of the operators
|
|
listed in the manual page.
|
|
Operators are evaluated in order of precedence and follow
|
|
the same precedence rules as the C language.
|
|
Parentheses may be used for grouping.
|
|
A variable does not have to have the integer attribute
|
|
to be used within an arithmetic expression.
|
|
The name of the variable is replaced
|
|
by its value within an arithmetic
|
|
expression.
|
|
The statement
|
|
.ce
|
|
.B
|
|
let x=x+1
|
|
.R
|
|
can be used to
|
|
increment a variable
|
|
.BR x .
|
|
Note that there is no space before or after the operators
|
|
.B +
|
|
and
|
|
.BR = .
|
|
This is because each argument to
|
|
.B let
|
|
is an expression to evaluate.
|
|
The last expression determines
|
|
the value returned by
|
|
.BR let .
|
|
Let returns true
|
|
if the last expression evaluates to a non-zero value.
|
|
Otherwise,
|
|
.B let
|
|
returns false.
|
|
.P
|
|
Many of the arithmetic operators have special meaning
|
|
to the shell and must be quoted.
|
|
Since this can be burdensome, an alternate form of arithmetic
|
|
evaluation syntax has been provided.
|
|
For any command that begins with
|
|
.B ((
|
|
and ends in
|
|
.BR )) ,
|
|
all the characters until the
|
|
.B ))
|
|
are treated as a quoted arithmetic expression.
|
|
The double open and close parentheses
|
|
avoids incompatibility with the Bourne shell's use of
|
|
parentheses for grouping a set of commands
|
|
to be run in a sub-shell.
|
|
Expressions inside double parentheses can contain blanks
|
|
and special characters without quoting.
|
|
More precisely,
|
|
.ce
|
|
.B
|
|
(( ... ))
|
|
.R
|
|
is equivalent to
|
|
.ce
|
|
.B
|
|
let " ... "
|
|
.R
|
|
.P
|
|
In addition,
|
|
.B
|
|
$(( ... ))
|
|
.R
|
|
expands to the value of the enclosed arithmetic expression.
|
|
This expansion can occur wherever parameter expansion is performed.
|
|
.P
|
|
The following script prints the first
|
|
.I n
|
|
lines of its standard input onto its standard output,
|
|
where
|
|
.I n
|
|
can be supplied as an optional argument whose default value is 20.
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
.ta 4i
|
|
typeset \-i n=${1-20} # set n
|
|
while (( (n\-=1)>=0 )) && read \-r line # at most n lines
|
|
do print \-r \- "$line"
|
|
done
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
.H 1 "Conditional Expressions"
|
|
The Bourne shell uses the
|
|
.B test
|
|
command, or the equivalent
|
|
.B [
|
|
command, to test the attributes for
|
|
files and to compare strings or numbers.
|
|
The problem with
|
|
.B test
|
|
is that the shell has expanded the words of the
|
|
.B test
|
|
command and
|
|
split them into arguments before
|
|
.B test
|
|
begins execution.
|
|
.B test
|
|
cannot distinguish between operators and operands.
|
|
In most cases
|
|
.B
|
|
test "$1"
|
|
.R
|
|
will test whether argument 1 is non-null.
|
|
However,
|
|
if argument 1 is
|
|
.BR \-f ,
|
|
then
|
|
.B test
|
|
will treat
|
|
.B \-f
|
|
as an operator and
|
|
yield a syntax error.
|
|
One of the most frequent errors with
|
|
.B test
|
|
occurs when its operands are not within double quotes.
|
|
In this case, the argument may expand to more than a single
|
|
argument or to no argument at all. In either case this
|
|
will likely cause a syntax error.
|
|
What makes this most insidious is that these errors are frequently
|
|
data dependent. A script that appears to run correctly may abort
|
|
if given unexpected data.
|
|
.P
|
|
To get around these problems,
|
|
.B ksh
|
|
has a compound command for condition expression testing
|
|
as part of the language.
|
|
The reserved words
|
|
.B [[
|
|
and
|
|
.B ]]
|
|
delimit the range of the command.
|
|
The words between
|
|
.B [[
|
|
and
|
|
.B ]]
|
|
are not processed for word splitting or for filename generation.
|
|
In addition, since
|
|
.B ksh
|
|
determines the operators before parameter expansion,
|
|
expansions that yield no argument cause no problem.
|
|
The operators within
|
|
.BR [[ ... ]]
|
|
are almost the same as those for the
|
|
.B test
|
|
command.
|
|
All unary operators are of the form
|
|
.BI \- letter
|
|
and are followed by a single operand.
|
|
Instead of
|
|
.B \-a
|
|
and
|
|
.BR \-o ,
|
|
.BR [[ ... ]]
|
|
uses
|
|
.B &&
|
|
and
|
|
.B \(bv\(bv
|
|
to indicate "and" and "or".
|
|
Parenthesis are used without quoting for grouping.
|
|
.P
|
|
The right hand side of the string comparison operators
|
|
.B =
|
|
and
|
|
.B !=
|
|
take a pattern and tests whether the left hand operand
|
|
matches this pattern. Quoting the pattern results
|
|
is a string comparison rather then the pattern match.
|
|
The operators
|
|
.B <
|
|
and
|
|
.B >
|
|
within
|
|
.BR [[ ... ]]
|
|
designate lexicographical comparison.
|
|
.P
|
|
In addition there are several other new comparison primitives.
|
|
The binary operators
|
|
.B \-ot
|
|
and
|
|
.B \-nt
|
|
compare the modification times
|
|
of two files to see which is file is
|
|
.I "older than"
|
|
or
|
|
.I "newer than"
|
|
the other.
|
|
The binary operator
|
|
.B \-ef
|
|
tests whether two files
|
|
have the same device and i-node number,
|
|
i.\ e., a link to the same file.
|
|
.P
|
|
The unary operator
|
|
.B \-L
|
|
returns true if its operand is a symbolic link.
|
|
The unary operator
|
|
.B \-O
|
|
(
|
|
.B \-G
|
|
)
|
|
returns true if the owner (or group) of the file operand matches
|
|
that of the caller.
|
|
The unary operator
|
|
.B \-o
|
|
returns true when its operand is the name of an option that is
|
|
currently on.
|
|
.P
|
|
The following script illustrates some of the uses of
|
|
.BR [[ ... ]] .
|
|
The man page contains the complete list of operators.
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
.ta 4i
|
|
for i in "${@}"
|
|
do # execute foo for numeric directory
|
|
if [[ \-d $i && $i = +([0\-9]) ]]
|
|
then foo
|
|
# otherwise if writable or executable file and not mine
|
|
elif [[ (\-w $i\(bv\(bv\-x $i) && ! \-O $i]]
|
|
then bar
|
|
fi
|
|
done
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
.H 1 "Functions and Command Aliasing"
|
|
.P
|
|
Two new mechanisms have been provided for creating
|
|
pseudo-commands, i.e.,
|
|
things that look like commands,
|
|
but do not always create a process.
|
|
The first technique is called command name
|
|
.IR aliasing .
|
|
.P
|
|
As a command is being read,
|
|
the command name is checked against a list of
|
|
.I alias
|
|
names.
|
|
If it is found,
|
|
the name is replaced by the text associated with the
|
|
.I alias
|
|
and then rescanned.
|
|
When rescanning the text for an alias, alias substitutions
|
|
are performed except for an alias that is currently being processed.
|
|
This prevents infinite loops in alias substitutions.
|
|
Ordinarily, only the command name word is processed for alias substitution.
|
|
However, if the value of an alias ends in a space,
|
|
then the word following the alias is also checked for alias substitution.
|
|
This makes it possible for aliases to work with commands such as
|
|
.BR nohup .
|
|
.P
|
|
Aliases are defined with the
|
|
.B alias
|
|
built-in.
|
|
The form of an
|
|
.B alias
|
|
command definition is:
|
|
.ce
|
|
.BI "alias " name = value
|
|
The first character of an
|
|
.I alias
|
|
name can be any non-special printable character, while all remaining characters
|
|
must be alpha-numeric.
|
|
The replacement text,
|
|
.I value,
|
|
can contain any valid shell script,
|
|
including meta-characters such as pipe symbols and i/o-redirection.
|
|
Unlike
|
|
.BR csh ,
|
|
aliases in
|
|
.B ksh
|
|
cannot take arguments.
|
|
Aliases can be used to redefine built-in commands so that
|
|
the alias
|
|
.ce
|
|
.B "alias test=./test"
|
|
can be used to look for
|
|
.B test
|
|
in your current working directory rather than
|
|
using the built-in
|
|
.B test
|
|
command.
|
|
Reserved words such as
|
|
.B for
|
|
and
|
|
.B while
|
|
cannot be changed by aliasing.
|
|
The command
|
|
.BR alias ,
|
|
without arguments, generates
|
|
a list of aliases and corresponding texts.
|
|
The
|
|
.B unalias
|
|
command removes the name and text of an alias.
|
|
.P
|
|
Aliases are used to save typing and to improve readability of scripts.
|
|
For example, the alias
|
|
.B
|
|
alias integer=\(fmtypeset \-i\(fm
|
|
.R
|
|
allows the integer variables
|
|
.B i
|
|
and
|
|
.B j
|
|
to be declared and initialized with the command
|
|
.BR "integer i=0 j=1" .
|
|
.P
|
|
The location of an alias command can be important
|
|
since aliases are only processed when a command is read.
|
|
A
|
|
.B .
|
|
procedure is read all at once (unlike
|
|
.I profiles
|
|
which are read a command at
|
|
a time) so that any aliases defined there will not effect any commands
|
|
within this script.
|
|
.P
|
|
Aliases can be used to bind program names to the
|
|
full path-name of the program. This eliminates the path search
|
|
but requires knowledge of where that program will be stored.
|
|
.I Tracked
|
|
aliases
|
|
make this use for aliasing automatic.
|
|
A tracked alias is not given a value. Its value is
|
|
defined at the first
|
|
reference by a path-search as the full path-name equivalent of the name, and
|
|
remains defined until the
|
|
.B PATH
|
|
variable is set.
|
|
Programs found in directories that do not begin with
|
|
.B /
|
|
that occur earlier in the path-search than the value of the
|
|
tracked alias, take precedence over tracked aliases.
|
|
.P
|
|
Tracked aliases provide an alternative to the
|
|
.B csh
|
|
command hashing facility. Tracked aliases do not require time for
|
|
initialization and allow for new commands to be introduced
|
|
without the need for re-hashing.
|
|
The
|
|
.B \-h
|
|
option to the shell allows all command names
|
|
to become tracked aliases.
|
|
This option is automatically turned on for non-interactive shells.
|
|
.P
|
|
.I Functions
|
|
are more general than aliases but also more costly.
|
|
Function definitions are of the form
|
|
.sp
|
|
.in +.5i
|
|
.BI "function " name
|
|
.br
|
|
.B {
|
|
.br
|
|
any shell script
|
|
.br
|
|
.B }
|
|
.sp
|
|
.in
|
|
The function is invoked by writing
|
|
.I name
|
|
and optionally following it with arguments.
|
|
Positional parameters are saved before each
|
|
function call and restored when completed.
|
|
Functions are executed in the current shell environment
|
|
and can share named variables with the calling program.
|
|
Options, other than execution trace
|
|
.BR \-x ,
|
|
set by the calling program are
|
|
passed down to a function.
|
|
The option flags are
|
|
not shared with
|
|
the function so that any options set within a function are
|
|
restored when the function exits.
|
|
Traps ignored by the caller are ignored within the function
|
|
and cannot be enabled.
|
|
Traps caught by the calling program are reset to their
|
|
default action with the function.
|
|
In most instances, the default action is
|
|
to cause the function to terminate.
|
|
A trap on
|
|
.B EXIT
|
|
defined within a function executes after the function
|
|
completes but
|
|
before the caller resumes.
|
|
Therefore,
|
|
any variable assignments and
|
|
any options set as part of a trap action will be effective
|
|
after the caller resumes.
|
|
The
|
|
.B return
|
|
built-in can be used to cause the function to return to
|
|
the statement following
|
|
the point of invocation.
|
|
.P
|
|
By default, variables are inherited by the function and shared
|
|
by the calling program.
|
|
However,
|
|
environment substitutions preceding the function call
|
|
apply only to the scope of the function call.
|
|
Also, variables defined with the
|
|
.B typeset
|
|
built-in command are local to the function that they are declared in.
|
|
Thus, for the function defined
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
function name
|
|
{
|
|
typeset \-i x=10
|
|
let z=x+y
|
|
print $z
|
|
}
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
invoked as
|
|
.BR "y=13 name" ,
|
|
.B x
|
|
and
|
|
.B y
|
|
are local variables with respect to the function
|
|
.B name
|
|
while
|
|
.B z
|
|
is global.
|
|
.P
|
|
Alias and function names are never directly carried across separate
|
|
invocations of \f3ksh\fP, but can be passed down scripts invoked by name
|
|
by using the
|
|
.B \-x
|
|
flag described below.
|
|
Ordinarily, shell scripts invoked by name are executed
|
|
in the process which is a copy of the caller
|
|
rather than causing a separate invocation of
|
|
.BR ksh ,
|
|
while scripts invoked as
|
|
.B ksh
|
|
.I script
|
|
and shell escapes from other programs
|
|
are carried out by a separate shell invocation.
|
|
The
|
|
.B \-x
|
|
flag is used with
|
|
.B alias
|
|
to carry aliases to shell scripts invoked by name, while the
|
|
.B \-fx
|
|
flags of
|
|
.B typeset
|
|
are used to do the same for functions.
|
|
.P
|
|
To cause alias and function definitions to be in effect for
|
|
separate invocations of
|
|
.BR ksh ,
|
|
it is necessary to
|
|
create a startup file and put the aliases and functions definitions
|
|
in this file.
|
|
By setting and exporting the environment variable,
|
|
.BR ENV ,
|
|
to the name of this file,
|
|
the aliases and functions will be defined each time \f3ksh\fP
|
|
is invoked.
|
|
The value of the
|
|
.B ENV
|
|
variable undergoes parameter substitution prior to its use.
|
|
.P
|
|
Aliases and functions
|
|
without the
|
|
.B \-x
|
|
flag apply only to interactive shells.
|
|
The
|
|
.B \-x
|
|
flag is required for the definition to apply for
|
|
scripts, as well as interactive use.
|
|
Setting this flag to redefine the semantics of a command
|
|
can have undesired side effects.
|
|
For example,
|
|
.B "alias \-x ls='ls \-l'"
|
|
will cause shell procedures which use the
|
|
.B ls
|
|
command within a pipeline to break.
|
|
.P
|
|
Several of the UNIX system commands can be aliased to \f3ksh\fP built-ins.
|
|
Some of these are automatically set each time the shell is invoked.
|
|
In addition,
|
|
about twenty frequently used UNIX system commands are set as tracked aliases.
|
|
.P
|
|
A name is checked to see if it is a built-in command before checking to see
|
|
if it is a function. To write a function to replace a built-in command
|
|
you must define a function with a different name and alias the
|
|
built-in name to this function.
|
|
For example to write a
|
|
.B cd
|
|
function which changes the directory and prints out the directory name,
|
|
you can write,
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
alias cd=_cd
|
|
function _cd
|
|
{
|
|
if 'cd' "$@"
|
|
then echo $PWD
|
|
fi
|
|
}
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
The single quotes around
|
|
.B cd
|
|
within the function prevents alias substitution.
|
|
The
|
|
.B PWD
|
|
variable is described below.
|
|
.P
|
|
The combination of aliases and functions can be used
|
|
to do things that can't be done with either of these
|
|
separately. For example, the function and aliases
|
|
defined as
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
function _from # i=start to finish [ by incr]
|
|
{
|
|
typeset var=${1%%=*}
|
|
integer incr=${5\-1} $1
|
|
while (( $var <= $3 ))
|
|
do _repeat
|
|
let $var=$var+incr
|
|
done
|
|
}
|
|
alias repeat='function _repeat {' from='}; _from'
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
allow you to write loops such as
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
repeat
|
|
any script command
|
|
from i=1 to 13 by 3
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
with the expected behavior.
|
|
.P
|
|
Function definitions in the
|
|
.B ENV
|
|
file cause the shell to take longer to begin executing.
|
|
To save time, it is possible to put the function definitions
|
|
into a directory in a file whoses name is the name of the
|
|
function.
|
|
The
|
|
.B FPATH
|
|
variable is a colon separated list that
|
|
.B ksh
|
|
uses to search for function definitions.
|
|
When
|
|
.B ksh
|
|
encounters an autoload function,
|
|
it runs the
|
|
.B .
|
|
command on the script containing the function,
|
|
and then executes the function.
|
|
.H 1 "Input and Output"
|
|
.P
|
|
An extended I/O capability has been added
|
|
to enhance the
|
|
use of the shell as a programming language.
|
|
The Bourne shell has a built-in
|
|
.B read
|
|
for reading lines from file descriptor 0,
|
|
but does not have any internal output mechanism.
|
|
Recent versions of the System V shell
|
|
have
|
|
.B echo(1)
|
|
as a built-in command.
|
|
Unfortunately, there are several incompatible versions of
|
|
.B echo
|
|
that are used widely.
|
|
Even worse,
|
|
.B read
|
|
and
|
|
.B echo
|
|
aren't able to perform some often required tasks.
|
|
For example, there is no way to read in a line
|
|
from a terminal and to
|
|
.I echo
|
|
the line exactly as is.
|
|
In the Bourne shell,
|
|
the
|
|
.B read
|
|
built-in cannot be used to read lines that end in
|
|
.BR `\e' ,
|
|
and the
|
|
.B echo
|
|
command will treat certain sequences as control sequences.
|
|
In addition,
|
|
there is no way to have more than one file open
|
|
at any time for reading.
|
|
.P
|
|
\f3ksh\fP has options on the
|
|
.B read
|
|
command to specify the file
|
|
descriptor for the input.
|
|
The
|
|
.B exec
|
|
built-in can be used to open, close, and duplicate file streams.
|
|
The
|
|
.B \-r
|
|
option allows a
|
|
.B `\e'
|
|
at the end of an input line to be treated as a regular
|
|
character rather than the line continuation character.
|
|
The first argument of the
|
|
.B read
|
|
command can be followed by a
|
|
.B ?
|
|
and a prompt to produce a prompt at the
|
|
terminal before the read.
|
|
If the input is not from a terminal device then
|
|
the prompt is not issued.
|
|
.P
|
|
The \f3ksh\fP built-in,
|
|
.BR print ,
|
|
is used to output characters to the terminal or to a file.
|
|
Again, it is possible to specify the file descriptor number
|
|
as an option to the command.
|
|
Ordinarily, the arguments to this command are processed
|
|
the same as for
|
|
.BR echo(1) .
|
|
However, the
|
|
.B \-r
|
|
flag can be used to output the arguments without any special meaning.
|
|
The
|
|
.B \-n
|
|
flag can be used here to suppress the trailing new-line
|
|
that is ordinarily appended.
|
|
.P
|
|
To improve performance of existing shell programs,
|
|
the
|
|
.B echo
|
|
command is built into \f3ksh\fP.
|
|
For the System V version of \f3ksh\fP, the built-in
|
|
.B echo
|
|
is equivalent to
|
|
.ce
|
|
\f3print \-\fR,
|
|
where the
|
|
.B \-
|
|
signifies that there are no more options permitted.
|
|
On the Berkeley UNIX version the value of the
|
|
.B PATH
|
|
variable determines the behavior of the built-in
|
|
.B echo
|
|
command.
|
|
If
|
|
.B echo
|
|
would resolve to
|
|
.B /bin/echo
|
|
with a path search, then
|
|
.B echo
|
|
is equivalent to
|
|
.ce
|
|
\f3print \-R\fR.
|
|
The
|
|
.B \-R
|
|
option allows only the
|
|
.B \-n
|
|
flag to be recognized as the next argument.
|
|
Otherwise,
|
|
.B echo
|
|
behaves like the System V
|
|
.B echo
|
|
command.
|
|
.P
|
|
The shell is frequently used as a programming language for
|
|
interactive dialogues.
|
|
The
|
|
.B select
|
|
statement has been added to the language
|
|
to make it easier to
|
|
present menu selection alternatives to the
|
|
user and evaluate the reply.
|
|
The list of alternatives is numbered and put in columns.
|
|
A user settable prompt,
|
|
.BR PS3 ,
|
|
is issued and if the answer is
|
|
a number corresponding to one of the alternatives,
|
|
the select loop variable is set to this value.
|
|
In any case, the
|
|
.B REPLY
|
|
variable is used to store the user entered reply.
|
|
The shell variables
|
|
.B LINES
|
|
and
|
|
.B COLUMNS
|
|
are used to control the layout of select lists.
|
|
.H 1 "Command Re-entry"
|
|
.P
|
|
An interactive shell saves the
|
|
commands you type at a terminal in a file.
|
|
If the variable
|
|
.B HISTFILE
|
|
is set to the name of a file to which the user
|
|
has write access,
|
|
then the commands are stored in this
|
|
.I history
|
|
file.
|
|
Otherwise the file
|
|
.B $HOME/.sh_history
|
|
is checked for write access and if this fails
|
|
an unnamed file is used to hold the history lines.
|
|
Commands are always appended to this file so that the file
|
|
can be shared by instances of
|
|
.B ksh
|
|
running at the same time.
|
|
The file may be truncated when
|
|
.B ksh
|
|
determines that no other shell is using the history file.
|
|
The number of commands accessible to the user is determined by the value of the
|
|
.B HISTSIZE
|
|
variable at the time the shell is invoked.
|
|
The default value is 128.
|
|
A command may consist of one or more lines since a compound
|
|
command is considered one command.
|
|
If the character
|
|
.B !
|
|
is placed within the
|
|
.I "primary prompt"
|
|
string,
|
|
.BR PS1 ,
|
|
then it is replaced by the command number each time the prompt is given.
|
|
Whenever the history file is named,
|
|
all shells which use this file share access to the same history.
|
|
.P
|
|
A built-in command
|
|
.B fc
|
|
(fix command) is used to list and/or edit
|
|
any of these saved commands.
|
|
The command can always be specified with
|
|
a range of one or more commands.
|
|
The range can be specified by giving the command
|
|
number, relative or absolute, or by giving
|
|
the first character or characters of the command.
|
|
The option
|
|
.B \-l
|
|
is used to specify listing of previous commands.
|
|
When given without specifying the range,
|
|
the last 16
|
|
commands are listed, each
|
|
preceded by the command number.
|
|
.P
|
|
If the listing option is not selected,
|
|
then the range of commands specified,
|
|
or the last command if no range is given,
|
|
is passed to an editor program before
|
|
being re-executed by \f3ksh\fP.
|
|
The editor to be used may be specified
|
|
with the option
|
|
.B \-e
|
|
and following it with the editor name.
|
|
If this option is not specified, the
|
|
value of the shell variable
|
|
.B FCEDIT
|
|
is used as the name of the editor,
|
|
providing that this variable has non-null value.
|
|
If this variable is not set, or is null,
|
|
and the
|
|
.B \-e
|
|
option has not been selected,
|
|
then
|
|
.B /bin/ed
|
|
is used.
|
|
When editing has been complete,
|
|
the edited text automatically becomes
|
|
the input for \f3ksh\fP.
|
|
As this text is read by \f3ksh\fP, it is echoed onto the terminal.
|
|
.P
|
|
An editor name of
|
|
.B \-
|
|
is used to bypass the editing and just re-execute the command.
|
|
In this case only a single command can be specified as the range
|
|
and an optional argument of the form
|
|
\f2old\fP\f3=\fP\f2new\fP
|
|
may be added which requests a simple string substitution
|
|
prior to evaluation.
|
|
A convenient alias,
|
|
.ce
|
|
.B
|
|
alias r=\(fmfc \-e \-\(fm
|
|
.R
|
|
has been pre-defined so that
|
|
the single key-stroke
|
|
.B r
|
|
can be used to re-execute the previous command
|
|
and the key-stroke sequence,
|
|
.B
|
|
r abc=def c
|
|
.R
|
|
can be used to re-execute the last command that starts with
|
|
the letter
|
|
.B c
|
|
with the first occurrence of the string
|
|
.B abc
|
|
replaced with the string
|
|
.BR def .
|
|
Typing
|
|
.B
|
|
r c > file
|
|
.R
|
|
re-executes the most recent command starting with the letter
|
|
.BR c ,
|
|
with standard output redirected to
|
|
.IR file .
|
|
.H 1 "In-line editing"
|
|
.P
|
|
Lines typed from a terminal frequently need changes made
|
|
before entering them.
|
|
With the Bourne shell the only method to fix up commands
|
|
is by backspacing or killing the whole line.
|
|
\f3ksh\fP offers options that allow the user to edit parts of the
|
|
current command line before submitting the command.
|
|
The in-line edit options make the command line into a single
|
|
line screen edit window.
|
|
When the command is longer than the width of the terminal,
|
|
only a portion of the command is visible.
|
|
Moving within the line automatically makes that portion visible.
|
|
Editing can be performed on this window until the
|
|
.I return
|
|
key is pressed.
|
|
The editing modes have commands that access the history file
|
|
in which previous commands are saved.
|
|
A user can copy any of the most recent
|
|
.B HISTSIZE
|
|
commands from this file into the input edit window.
|
|
You can locate commands by searching or by position.
|
|
.P
|
|
The in-line editing options do not use the
|
|
.I termcap
|
|
or
|
|
.I terminfo
|
|
databases.
|
|
They work on most standard terminals.
|
|
They only require that the backspace character moves the cursor left
|
|
and the space character overwrites the current character on the screen
|
|
and moves the cursor to the right.
|
|
.P
|
|
There is a choice of editor options.
|
|
The
|
|
.IR emacs ,
|
|
.IR gmacs ,
|
|
or
|
|
.I vi
|
|
option is selected by turning on the
|
|
corresponding
|
|
option of the
|
|
.B set
|
|
command.
|
|
If the value of the
|
|
.B EDITOR
|
|
or
|
|
.B VISUAL
|
|
variables ends with any of these suffixes
|
|
the corresponding option is turned on.
|
|
A large subset of each of these editors'
|
|
features are available within the shell. Additional
|
|
functions, such as file name completion, have also been added.
|
|
.P
|
|
The code for the
|
|
.I emacs
|
|
and
|
|
.I gmacs
|
|
editing option was supplied by Mike Veach.
|
|
In the
|
|
.I emacs
|
|
or
|
|
.I gmacs
|
|
mode the user positions the cursor to the point
|
|
needing correction and inserts, deletes, or replaces
|
|
characters as needed.
|
|
The only difference between these two modes is the
|
|
meaning of the command
|
|
.BR ^T .
|
|
Control keys and escape sequences are used for cursor
|
|
positioning and control functions.
|
|
The available editing functions are listed in the manual page.
|
|
.P
|
|
The code for the
|
|
.I vi
|
|
editing option was supplied by Pat Sullivan.
|
|
The
|
|
.I vi
|
|
editing mode
|
|
starts in insert mode and enters control mode when the
|
|
user types
|
|
.B ESC ( 033 ).
|
|
The
|
|
.I return
|
|
key, which submits the current command for processing,
|
|
can be entered from either mode.
|
|
The cursor can be anywhere on the line.
|
|
A subset of commonly used
|
|
.I vi
|
|
commands are available.
|
|
The
|
|
.B k
|
|
and
|
|
.B j
|
|
command that normally move up and down by one
|
|
.IR line ,
|
|
move up and down one
|
|
.I command
|
|
in the history file,
|
|
copying the command into the input edit window.
|
|
For reasons of efficiency,
|
|
the terminal is kept in canonical mode until an
|
|
.B ESC
|
|
is typed.
|
|
On some terminals,
|
|
and on earlier versions of the UNIX operating system,
|
|
this doesn't work correctly.
|
|
The
|
|
.B viraw
|
|
option
|
|
of the
|
|
.B set
|
|
command, which always uses
|
|
.B raw
|
|
or
|
|
.B cbreak
|
|
mode,
|
|
must be used in this case.
|
|
.P
|
|
Most of the code for the editing options does not rely on the
|
|
\f3ksh\fP code and can be used in a stand-alone mode with most any command
|
|
to add in-line edit capability.
|
|
However,
|
|
all versions of the in-line editors have some features that
|
|
use some shell specific code. For example,
|
|
.B ESC-=
|
|
in all edit modes prints the names of files that match the current
|
|
word and
|
|
.B ESC-*
|
|
adds the expanded list of matching files to the command line.
|
|
A trailing
|
|
.B *
|
|
is added to the word if it doesn't contain any file pattern matching
|
|
characters before the expansion.
|
|
In
|
|
.B emacs
|
|
and
|
|
.B gmacs
|
|
mode,
|
|
.B ESC-ESC
|
|
indicates filename completion.
|
|
The current word is compared with all the filenames that
|
|
start with this prefix, and as many characters as possible are
|
|
appended to the word while continuing to be unique.
|
|
If a single filename contains the word prefix,
|
|
then word is replaced by the filename, and a
|
|
.B '/'
|
|
is appended if
|
|
filename is a directory, otherwise a space is added.
|
|
In
|
|
.B vi
|
|
mode,
|
|
.B \e
|
|
from control mode gives the same behavior.
|
|
.H 1 "Job Control"
|
|
.P
|
|
The job control mechanism
|
|
is almost identical to the version found in
|
|
.B csh
|
|
of the Berkeley UNIX operating system,
|
|
version 4.1.
|
|
The job control feature allows the user to stop and
|
|
restart programs, and to move programs to and from the
|
|
foreground and the background.
|
|
It will only work on systems that provide support for
|
|
these features.
|
|
However,
|
|
even systems without job control have a
|
|
.B monitor
|
|
option which when enabled will report the progress
|
|
of background jobs and enable the user to
|
|
.B kill
|
|
jobs by job number or job name.
|
|
.P
|
|
An interactive shell associates a
|
|
.I job
|
|
with each pipeline typed in from the terminal
|
|
and assigns them a small integer number
|
|
called the job number.
|
|
If the job is run asynchronously,
|
|
the job number is printed at the terminal.
|
|
At any given time, only one job owns the terminal,
|
|
i.e., keyboard signals are only sent to the processes in one job.
|
|
When \f3ksh\fP creates a foreground job,
|
|
it gives it ownership of the terminal.
|
|
If you are running a job and wish to stop
|
|
it you hit the key
|
|
.B ^Z
|
|
(control-Z)
|
|
which sends a
|
|
.B STOP
|
|
signal to all processes in the current job.
|
|
The shell receives notification that the processes
|
|
have stopped and takes back control of the terminal.
|
|
.P
|
|
There are commands to continue programs in the foreground
|
|
and background.
|
|
There are several ways to refer to jobs.
|
|
The character
|
|
.B %
|
|
introduces a job name.
|
|
You can refer to jobs by name or number as described in the manual page.
|
|
The built-in command
|
|
.B bg
|
|
allows you to continue a job in the background,
|
|
while the built-in command
|
|
.B fg
|
|
allows you to continue a job in the foreground even
|
|
though you may have started it in the background.
|
|
.P
|
|
A job being run in the background will stop if it tries
|
|
to read from the terminal.
|
|
It is also possible to stop background jobs that try to write on
|
|
the terminal by setting the terminal options
|
|
appropriately.
|
|
.P
|
|
There is a built-in command
|
|
.B jobs
|
|
that lists the status of all running and stopped jobs.
|
|
In addition,
|
|
you are notified of the change of state of any background
|
|
jobs just before each prompt.
|
|
If you want to be notified about background job completions
|
|
at other times, then set the
|
|
.B CHLD
|
|
trap to
|
|
.BR "jobs \-n" .
|
|
When you try to leave the shell while jobs are stopped or running,
|
|
you will receive a message from \f3ksh\fP.
|
|
If you ignore this message and try to leave again,
|
|
all stopped processes will be terminated.
|
|
.P
|
|
A built-in version of
|
|
.B kill
|
|
makes it possible to use
|
|
.I job
|
|
numbers as targets for signals.
|
|
Signals can be selected by number or name.
|
|
The name of the signal is the name found in the
|
|
.I include
|
|
file
|
|
.B /usr/include/sys/signal.h
|
|
with the prefix
|
|
.B SIG
|
|
removed.
|
|
The
|
|
.B \-l
|
|
flag of
|
|
.B kill
|
|
generates a list of valid signal numbers and names.
|
|
.H 1 Security
|
|
There are several documented problems associated with the security of
|
|
shell procedures\*(Rf.
|
|
.RS
|
|
F. T. Grampp and R. H. Morris,
|
|
.I "UNIX Operating System Security,"
|
|
AT&T Bell Labs Tech. Journal, Vol. 63, No. 8, Part 2, pp.1649-1671, 1984.
|
|
.RF
|
|
These security holes occur primarily because a user can manipulate the
|
|
.I environment
|
|
to subvert the intent of a
|
|
.I setuid
|
|
shell procedure.
|
|
Frequently, shell procedures are initiated from
|
|
binary programs, without the author's
|
|
awareness, by library routines which invoke shells to carry out
|
|
their tasks.
|
|
When the binary program is run
|
|
.I setuid
|
|
then the shell procedure runs with the permissions afforded to the
|
|
owner of the binary file.
|
|
.P
|
|
In the Bourne shell,
|
|
the
|
|
.B IFS
|
|
parameter is used to split each word into separate command arguments.
|
|
If a user knows that some
|
|
.I setuid
|
|
program will run
|
|
.B "sh \-c /bin/pwd"
|
|
(or any other command in
|
|
.BR /bin )
|
|
then the user sets and exports
|
|
.BR IFS=/ .
|
|
Instead of running
|
|
.B /bin/pwd
|
|
the shell will run
|
|
.B bin
|
|
with
|
|
.B pwd
|
|
as an argument.
|
|
The user puts his or her own
|
|
.B bin
|
|
program into the current directory.
|
|
This program can
|
|
create a copy of the shell,
|
|
make this shell
|
|
.IR setuid ,
|
|
and then run the
|
|
.B /bin/pwd
|
|
program so that the original program continues to run successfully.
|
|
This kind of penetration is not possible with
|
|
.B ksh
|
|
since the
|
|
.B IFS
|
|
parameter only splits arguments that result from command or parameter
|
|
substitution.
|
|
.P
|
|
Some
|
|
.I setuid
|
|
programs run programs using
|
|
.I system()
|
|
without giving the full path name.
|
|
If the
|
|
user sets the
|
|
.B PATH
|
|
variable so that the desired command will be found
|
|
in his or her local bin, then the same technique described above can
|
|
be employed to compromise the security of the system.
|
|
To close up this and other security holes,
|
|
.B ksh
|
|
resets the effective user id to the real user id and the effective
|
|
group id to the real group id unless the
|
|
.I privileged
|
|
option
|
|
.RB ( \-p\^ )
|
|
is specified at invocation.
|
|
In
|
|
this mode, the
|
|
.I privileged
|
|
mode, the
|
|
.B .profile
|
|
and
|
|
.B ENV
|
|
files are not processed.
|
|
Instead, the file
|
|
.B /etc/suid_profile
|
|
is read and executed.
|
|
This gives an administrator control over the
|
|
environment to set the
|
|
.B PATH
|
|
variable or to log setuid shell invocations.
|
|
Clearly security of the system is compromised if
|
|
.B /etc
|
|
or this file is publicly writable.
|
|
.P
|
|
In the Berkeley UNIX version the operating system looks for the characters
|
|
.B #!
|
|
as the first two characters of an executable file.
|
|
If these characters are found, then the next word on this line is taken
|
|
as the interpreter to
|
|
.I exec
|
|
for this command and the interpreter is
|
|
.IR exec ed
|
|
with the name of the script as argument zero and argument one.
|
|
If the
|
|
.I setuid
|
|
or
|
|
.I setgid
|
|
bits are on for this file, then the interpreter
|
|
is run with the effective uid and/or gid set accordingly.
|
|
This scheme has two major drawbacks.
|
|
First of all, using the
|
|
.B #!
|
|
notation forces an
|
|
.B exec
|
|
of the interpreter even when the call is invoked from the interpreter
|
|
which it must exec. This is inefficient since
|
|
the interpreter can handle a failed exec much faster than starting up
|
|
again.
|
|
More importantly,
|
|
.I setuid
|
|
and
|
|
.I setgid
|
|
procedures provide an easy target for intrusion.
|
|
By linking a
|
|
.I setuid
|
|
or
|
|
.I setgid
|
|
procedure to a name beginning with a
|
|
.B \-
|
|
the interpreter is fooled into thinking that it is being invoked with
|
|
a command line option rather than the name of a file.
|
|
When the interpreter is the shell, the user gets a privileged
|
|
interactive shell.
|
|
There is code in
|
|
.B ksh
|
|
to guard against this simple form of intrusion.
|
|
.P
|
|
A more reliable way to handle
|
|
.I setuid
|
|
and
|
|
.I setgid
|
|
procedures is provided with
|
|
.BR ksh .
|
|
The technique does not require any changes to the operating system
|
|
and provides better security.
|
|
Another advantage to this method is that it also allows scripts which
|
|
have execute permission but no read permission to run. Taking away read
|
|
permission makes scripts more secure.
|
|
.P
|
|
The method relies on a setuid
|
|
.B root
|
|
program to authenticate the
|
|
request and exec the shell with the correct mode bits to carry out
|
|
the task. This shell is invoked with the requested file already open
|
|
for reading. A script which cannot be opened for reading or which
|
|
has its suid and/or setgid bits turned on causes this setuid
|
|
.B root
|
|
program to get execed.
|
|
For security reasons, this program is given the full
|
|
pathname
|
|
.BR /etc/suid_exec .
|
|
A description of the implementation of the
|
|
.B suid_exec
|
|
program can be found in
|
|
a separate paper\*(Rf.
|
|
.RS
|
|
D. G Korn
|
|
.I "Parlez-vous Kanji?"
|
|
TM-59554-860602-03, 1986.
|
|
.RF
|
|
.H 1 "Miscellaneous"
|
|
.P
|
|
\f3ksh\fP has several additional features to enhance functionality and performance.
|
|
This section lists most of these features.
|
|
.H 2 "Tilde substitution"
|
|
The character
|
|
.B \(ap
|
|
at the beginning of a word has special meaning to \f3ksh\fP.
|
|
If the characters after the
|
|
.B \(ap
|
|
up to a
|
|
.B /
|
|
match a user login name in the
|
|
.B /etc/passwd
|
|
file, then the
|
|
.B \(ap
|
|
and the name are replaced by
|
|
that user's login directory.
|
|
If no match is found, the original word
|
|
is unchanged.
|
|
A
|
|
.B \(ap
|
|
by itself, or in front of a
|
|
.BR / ,
|
|
is replaced by the value of the
|
|
.B HOME
|
|
parameter.
|
|
A
|
|
.B \(ap
|
|
followed by a
|
|
.B +
|
|
or
|
|
.B \-
|
|
is replaced by the value of
|
|
.B $PWD
|
|
and
|
|
.B $OLDPWD
|
|
respectively.
|
|
.H 2 "Built-in I/O Redirection"
|
|
.P
|
|
All built-in commands can be redirected.
|
|
Compound commands which are redirected are not carried out in
|
|
a separate process.
|
|
.H 2 "Command Substitution"
|
|
.P
|
|
Command substitution ( \fB\(ga\(ga\fR)
|
|
in the Bourne shell suffers from some
|
|
complicated quoting rules.
|
|
It is hard to write a
|
|
.B sed
|
|
pattern which contains back slashes within command substitution.
|
|
Putting the pattern in single quotes doesn't help much.
|
|
\f3ksh\fP leaves the Bourne shell command substitution alone and adds
|
|
a newer and easier to use command substitution syntax.
|
|
All the characters between a
|
|
.B $(
|
|
and a matching
|
|
.B )
|
|
are evaluated as a command and the output is substituted just as
|
|
with \fB\(ga\(ga\fR.
|
|
The
|
|
.B $
|
|
means
|
|
.I "value of"
|
|
and the
|
|
.B ()
|
|
denotes a command.
|
|
The command itself can contain quoted strings even if the substitution
|
|
occurs within double quotes. Nesting is legal. You can use
|
|
unbalanced parenthesis within the command providing that they are
|
|
quoted.
|
|
.P
|
|
The special command substitution of the form
|
|
\fB$(cat file)\fR
|
|
can be replaced by
|
|
\fB$(< file)\fR,
|
|
which is faster because no separate process is created.
|
|
.H 2 "Added options"
|
|
.P
|
|
Several options have been added to the shell and
|
|
all options have names
|
|
that can be used in place of flags for setting and resetting options.
|
|
The command
|
|
.B "set \-o"
|
|
will list the current option settings.
|
|
.P
|
|
If the
|
|
.B bgnice
|
|
option is set,
|
|
background jobs are run at a lower priority.
|
|
.P
|
|
The option
|
|
.B markdirs
|
|
causes a trailing
|
|
.B /
|
|
to be appended on every directory name resulting from a pattern match.
|
|
.P
|
|
The job
|
|
.B monitor
|
|
option will cause a report to be printed
|
|
before issuing the next prompt
|
|
when each background job completes.
|
|
It is automatically enabled for systems that have
|
|
job control.
|
|
.P
|
|
The
|
|
.B noclobber
|
|
option causes
|
|
.B ksh
|
|
to print an error message when you use
|
|
.B >
|
|
to redirect to a file that already exists.
|
|
If you want to redirect to an existing file, then
|
|
you have to use
|
|
.B >|
|
|
to override.
|
|
.P
|
|
The option,
|
|
.B \-f
|
|
or
|
|
.BR noglob ,
|
|
is used to disable file name generation.
|
|
.P
|
|
The option
|
|
.B ignoreeof
|
|
can be used to prevent
|
|
.B ^D
|
|
from exiting the shell and possibly logging you out.
|
|
You must type
|
|
.B exit
|
|
to log out.
|
|
.P
|
|
The
|
|
.B nolog
|
|
option prevents
|
|
function definitions from
|
|
being stored in the history file.
|
|
This speeds up reading functions and does not allow the function
|
|
to be displayed.
|
|
.P
|
|
The
|
|
.B privileged
|
|
or
|
|
.B \-p
|
|
options provides additional security by disabling the
|
|
.B .profile
|
|
and
|
|
.B ENV
|
|
from being processed.
|
|
Whenever a shell begins execution
|
|
the effective uid (gid) is set to
|
|
the real uid (gid) unless
|
|
this option is enabled.
|
|
Instead of the
|
|
.B ENV
|
|
file, the file
|
|
.B /etc/suid_profile
|
|
is read so that administrators can have control over setuid scripts.
|
|
Turning
|
|
.B privileged
|
|
off causes the effective uid (gid) to be set to the real uid (gid).
|
|
.H 2 "Built-in pwd"
|
|
The
|
|
.B pwd
|
|
command is built-into ksh and therefore much faster.
|
|
.B ksh
|
|
maintains a logical view of the file system hierarchy.
|
|
On systems with symbolic links,
|
|
.B "pwd \-P"
|
|
generates the physical pathname of the present working
|
|
directory by resolving all the symbolic links.
|
|
.P
|
|
The
|
|
.B \-h
|
|
or
|
|
.B trackall
|
|
option will cause any command whose name is a valid alias
|
|
name to become a
|
|
.I tracked
|
|
alias.
|
|
This option is automatically turned on for non-interactive shells.
|
|
.H 2 "Logical naming"
|
|
By default,
|
|
the
|
|
.B cd
|
|
command will take you where you expect to go even if you cross
|
|
symbolic links. Thus,
|
|
.B "cd .."
|
|
will move you up one level closer to the root even if your
|
|
current directory is a symbolic link.
|
|
On systems with symbolic links,
|
|
.B "cd \-P"
|
|
causes
|
|
.B ..
|
|
to be treated physically.
|
|
.H 2 "Previous Directory"
|
|
.P
|
|
\f3ksh\fP remembers your last directory
|
|
in the variable
|
|
.BR OLDPWD .
|
|
The
|
|
.B cd
|
|
built-in can be given with argument
|
|
.B \-
|
|
to return to the previous directory
|
|
and prints the name of the directory.
|
|
Note that
|
|
.B "cd \-"
|
|
done twice returns you to the starting directory,
|
|
not the second previous directory.
|
|
A directory
|
|
.I stack
|
|
manager has been written as shell
|
|
.I functions
|
|
to
|
|
.I push
|
|
and
|
|
.I pop
|
|
directories from the stack.
|
|
.H 2 "Additional Variables and Parameters"
|
|
.P
|
|
Several new parameters have special meaning to \f3ksh\fP.
|
|
.P
|
|
The variable
|
|
.B FCEDIT
|
|
is used by the
|
|
.B fc
|
|
built-in described above.
|
|
.P
|
|
The variable
|
|
.B FPATH
|
|
is a colon (
|
|
.B :
|
|
) separated list of directories
|
|
used to search for function definitions.
|
|
.P
|
|
The variables
|
|
.B VISUAL
|
|
and
|
|
.B EDITOR
|
|
are used for determining the edit modes as described above.
|
|
.P
|
|
The variable
|
|
.B ENV
|
|
undergoes parameter expansion to
|
|
define the startup file for each
|
|
\f3ksh\fP invocations.
|
|
.P
|
|
The variable
|
|
.B ERRNO
|
|
holds the value of the C variable
|
|
.I errno
|
|
and is system dependent. It is useful
|
|
for debugging.
|
|
.P
|
|
The variables
|
|
.B HISTSIZE
|
|
and
|
|
.B HISTFILE
|
|
control the size and location of the file containing
|
|
commands entered at a terminal.
|
|
.P
|
|
The variable
|
|
.B LINENO
|
|
is set to the current line number relative to the
|
|
beginning of the current script or function.
|
|
It is most useful as part of the
|
|
.B PS4
|
|
prompt.
|
|
.P
|
|
The variable
|
|
.B MAILPATH
|
|
is a colon (
|
|
.B :
|
|
) separated list of file names to be checked for changes
|
|
periodically. The user is notified
|
|
before the next prompt.
|
|
Each of the names in this list can be followed by a
|
|
.B ?
|
|
and a prompt to be given when a change has been detected in the file.
|
|
The prompt will be evaluated for parameter substitution.
|
|
The parameter
|
|
.B $_
|
|
within a mail message will evaluate to the name of the file that
|
|
has changed.
|
|
The parameter
|
|
.B MAILCHECK
|
|
is used to specify the minimal interval in seconds before
|
|
new mail is checked for.
|
|
.P
|
|
The variable
|
|
.B OLDPWD
|
|
is used to hold the previous working directory of the shell.
|
|
.P
|
|
The variable
|
|
.B PS3
|
|
is displayed when waiting for a reply from a
|
|
.B select
|
|
line.
|
|
.P
|
|
The
|
|
.B PS4
|
|
variable
|
|
is evaluated for parameter substitution and
|
|
is displayed before each command during an execution trace.
|
|
.P
|
|
The variable
|
|
.B PWD
|
|
is used to hold the current working directory of the shell.
|
|
.P
|
|
The variable
|
|
.B RANDOM
|
|
produces a random number in the range 0 to 32767 each time it is referenced.
|
|
Assignment to this variable sets the seed for the
|
|
random number generator.
|
|
.P
|
|
The variable
|
|
.B SECONDS
|
|
is incremented every second.
|
|
In a roundabout way, this variable
|
|
can be used to generate a time stamp into the
|
|
.B PS1
|
|
prompt.
|
|
The following code explains how you can do this on
|
|
System V. On BSD, you need another command to initialize
|
|
the
|
|
.B SECONDS
|
|
variable.
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
# If you . this script then you can use $TIME as part of your PS1 string to get
|
|
# the time of day in your prompt
|
|
typeset \-RZ2 _x1 _x2 _x3
|
|
let SECONDS=$(date '+3600*%H+60*%M+%S')
|
|
_s='(_x1=(SECONDS/3600)%24)==(_x2=(SECONDS/60)%60)==(_x3=SECONDS%60)'
|
|
TIME='"${_d[_s]}$_x1:$_x2:$_x3"'
|
|
# PS1=${TIME}whatever
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
.P
|
|
The parameter
|
|
.B PPID
|
|
is used to generate the process id of the process which invoked this shell.
|
|
.P
|
|
The value of the parameter
|
|
.B _
|
|
is the last argument of the previous foreground command.
|
|
Before execing each command this parameter is set to the file
|
|
name of the command and placed in the environment.
|
|
.P
|
|
The parameter
|
|
.B TMOUT
|
|
can be set to be the number of seconds that the shell will wait for
|
|
input before terminating. A 60 second warning message is printed
|
|
before terminating.
|
|
.P
|
|
The
|
|
.B COLUMNS
|
|
variable can be used to adjust the width of the edit window for
|
|
the in-line edit modes. It is also used by the
|
|
.B select
|
|
command to present menu choices.
|
|
.P
|
|
The
|
|
.B LINES
|
|
variable controls how many rows a select list will take up on the screen.
|
|
Select lists will try to occupy no more than two-thirds of
|
|
.B LINES
|
|
lines on the screen.
|
|
.H 2 "Modified variables"
|
|
.P
|
|
The input field separator parameter,
|
|
.BR IFS ,
|
|
is only used to split words that have undergone parameter or command
|
|
substitution.
|
|
The first character of
|
|
.B IFS
|
|
value is used to separate each item with
|
|
.B $*
|
|
and
|
|
.BI ${ name [*]} .
|
|
In addition, adjacent non-blank delimiters separate
|
|
null fields in \f3ksh\fP.
|
|
.P
|
|
The
|
|
.B PS1
|
|
parameter is evaluated for parameter substitution and a
|
|
.B !
|
|
is replaced by the current command number.
|
|
.H 2 "Timing Commands"
|
|
.P
|
|
A keyword
|
|
.B time
|
|
has been added to replace
|
|
the
|
|
.B time
|
|
command.
|
|
Any function, command or pipeline can be preceded by this keyword
|
|
to obtain information about the elapsed, user, and system times.
|
|
Since I/O redirections bind to the command, not to
|
|
.BR time ,
|
|
parenthesis should be used to redirect the timing information which
|
|
is normally printed on file descriptor 2.
|
|
.H 2 "Co-process"
|
|
\f3ksh\fP can spawn a
|
|
.I co-process
|
|
by adding a
|
|
.B "|&"
|
|
after a command.
|
|
This process will be run with its standard input and its
|
|
standard output connected to the shell. The built-in command
|
|
.B print
|
|
with the
|
|
.B \-p
|
|
option will write into the standard input of this
|
|
process and
|
|
the built-in command
|
|
.B read
|
|
with the
|
|
.B \-p
|
|
option will read from the output of this process.
|
|
.H 2 "Process Substitution"
|
|
.P
|
|
This feature is only available
|
|
on versions of the UNIX operating system which support the
|
|
.B /dev/fd
|
|
directory for naming open files.
|
|
Each command argument of the form
|
|
\f3<(\fP\f2list\^\fP\f3)\fP
|
|
or
|
|
\f3>(\fP\f2list\^\fP\f3)\fP
|
|
will run process
|
|
.I list
|
|
asynchronously connected to some file in the
|
|
.B /dev/fd
|
|
directory.
|
|
The name of this file will become the argument to the command.
|
|
If the form with
|
|
.B >
|
|
is selected then writing on this file will provide input for
|
|
.IR list .
|
|
If
|
|
.B <
|
|
is used,
|
|
then the file passed as an argument will contain the output of the
|
|
.I list
|
|
process.
|
|
For example,
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
paste <(cut \-f1 \f2file1\fP) <(cut \-f3 \f2file2\fP) | tee >(\f2process1\fP) >(\fP\f2process2\fP)
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
.I cuts
|
|
fields 1 and 3 from
|
|
the files
|
|
.I file1
|
|
and
|
|
.I file2
|
|
respectively,
|
|
.I pastes
|
|
the results together, and
|
|
sends it
|
|
to the processes
|
|
.I process1
|
|
and
|
|
.IR process2 ,
|
|
as well as putting it onto the standard output.
|
|
Note that the file which is passed as an argument to the command is
|
|
a UNIX system
|
|
.IR pipe (2)
|
|
so that the programs that expect to
|
|
.IR lseek (2)
|
|
on the file will not work.
|
|
.H 2 "Whence"
|
|
.P
|
|
The addition of
|
|
.IR aliases ,
|
|
.IR functions ,
|
|
and more built-ins
|
|
has made it substantially more difficult to know what
|
|
a given command word really means.
|
|
A built-in command,
|
|
.B whence
|
|
when used with the
|
|
.B \-v
|
|
option has been provided to answer this question.
|
|
A line is printed for each argument to
|
|
.B whence
|
|
telling what would happen if this argument were used as a command name.
|
|
It reports on keywords, aliases, built-ins, and
|
|
functions.
|
|
If the command is none of the above,
|
|
it follows the path search rules and prints the full path-name,
|
|
if any, otherwise it prints an error message.
|
|
.H 2 "Added Traps"
|
|
All traps can be given by name in \f3ksh\fP. The names of traps
|
|
corresponding to signals are the same as the signal name with
|
|
the
|
|
.B SIG
|
|
prefix removed.
|
|
The trap
|
|
.B 0
|
|
is named
|
|
.B EXIT
|
|
and a new trap named
|
|
.B ERR
|
|
has been added.
|
|
This trap is invoked whenever the shell would exit if the
|
|
.B \-e
|
|
flag were set.
|
|
This trap is used by
|
|
Fourth Generation Make\*(Rf
|
|
.RS
|
|
G. S. Fowler,
|
|
"The Fourth Generation Make,"
|
|
Proceedings of the Portland USENIX meeting, pp. 159-174, 1985.
|
|
.RF
|
|
which runs \f3ksh\fP
|
|
as a co-process.
|
|
.P
|
|
A trap named
|
|
.B DEBUG
|
|
gets executed after each command.
|
|
This trap can be used for debugging purposes.
|
|
.H 2 "Coded in Standard C"
|
|
.P
|
|
Early versions of Bourne shell were coded in an ALGOL-68 like dialect of C.
|
|
\f3ksh\fP is coded in standard C.
|
|
It tries to adapt itself to the environment when it is compiled
|
|
taking advantage of the features of the host environment when possible.
|
|
For the most part, the code conforms to the proposed ANSI C language
|
|
and where possible, to the IEEE Posix 1003.1 standard.
|
|
\f3ksh\fP does not catch the segmentation violation signal, SIGSEGV,
|
|
so that it can run on machines that can't recover from these traps.
|
|
.H 2 Internationalization
|
|
\f3ksh\fP treats eight bit characters transparently without stripping off the
|
|
leading bit.
|
|
There is also a compile time switch to enable handling multi-byte
|
|
and multi-width characters sets.
|
|
.H 2 "No special meaning for ^"
|
|
The Bourne shell uses
|
|
.B ^
|
|
as an archaic synonym for
|
|
.B | .
|
|
The
|
|
.B ^
|
|
is not a special character to \f3ksh\fP.
|
|
.H 2 "Added conveniences"
|
|
You can refer to multi-digit positional parameters in \f3ksh\fP by putting
|
|
the number in braces. Thus,
|
|
.B ${12}
|
|
is legal in \f3ksh\fP but illegal in the Bourne shell.
|
|
.P
|
|
\f3ksh\fP will perform file name expansion of file name arguments if the
|
|
expansion is unique. Thus,
|
|
.B "cat < file*"
|
|
will expand the file name if the expansion is unique.
|
|
.P
|
|
If you invoke the shell as
|
|
.B "ksh script"
|
|
then \f3ksh\fP will do a path search on script.
|
|
.P
|
|
Unbalanced quotes will cause the shell to print an
|
|
error message giving the type of quote and the line number
|
|
on which the opening quote occurs.
|
|
.P
|
|
Run time error messages detected by the shell will print the
|
|
line number within a function or script where the error was
|
|
detected.
|
|
.H 1 "Example"
|
|
.P
|
|
An example of a \f3ksh\fP script is included
|
|
in the Appendix.
|
|
This one page program is a variant of the UNIX system
|
|
.I grep(1)
|
|
program.
|
|
Pattern matching for this version of
|
|
.I grep
|
|
means shell patterns consisting of
|
|
.BR ? ,
|
|
.BR * ,
|
|
and
|
|
.BR [] .
|
|
.P
|
|
The first half examines option flags.
|
|
Note that all options except
|
|
.B \-b
|
|
have been implemented.
|
|
The second half goes through each line of each file
|
|
to look for a pattern match.
|
|
.P
|
|
This program is not intended to serve as a
|
|
replacement for
|
|
.BR grep ;
|
|
just as an illustration of the programming power of \f3ksh\fP.
|
|
Note that no auxiliary processes are spawned by this script.
|
|
It was written and debugged in under two hours.
|
|
While performance is acceptable for small programs,
|
|
this program runs at only one tenth
|
|
the speed of
|
|
.B grep
|
|
for large files.
|
|
.H 1 "Performance"
|
|
.P
|
|
\f3ksh\fP executes many scripts faster than the System V Bourne shell.
|
|
One major reason is that many of the functions provided by
|
|
.I echo (1)
|
|
and
|
|
.IR expr (1)
|
|
are built-in.
|
|
The time to execute a built-in function is one or two
|
|
orders of magnitude faster than performing a fork and
|
|
execute of the shell.
|
|
Command substitution of built-ins is performed without
|
|
creating another process, and often without even
|
|
creating a temporary file.
|
|
.P
|
|
Another reason for improved performance is that all I/O is buffered.
|
|
Output buffers are flushed only when required.
|
|
Several of the internal algorithms have been changed
|
|
so that the number of subroutine calls has been
|
|
substantially reduced.
|
|
\f3ksh\fP uses hash tables for variables.
|
|
Scripts that rely heavily on referencing variables execute faster.
|
|
More processing is performed while reading the script
|
|
so that execution time is saved while running loops.
|
|
.P
|
|
Scripts that do little internal processing and create many processes
|
|
may run a little slower on System V because the time to
|
|
.I fork
|
|
\f3ksh\fP is slightly slower than for the Bourne shell.
|
|
On the Berkeley Unix version, \f3ksh\fP can be compiled with a
|
|
.B VFORK
|
|
option which uses
|
|
.I vfork
|
|
whenever possible.
|
|
In this case, binary programs startup somewhat faster but shell
|
|
script files start a little slower since a separate invocation
|
|
of the \f3ksh\fP in required.
|
|
.P
|
|
The
|
|
.B ENV
|
|
file can have an undesirable effect on performance.
|
|
Even if this file is small, the shell must perform an open of this
|
|
file. If large functions are placed in
|
|
the
|
|
.B ENV
|
|
file they must be read in and compiled even if they are never referenced.
|
|
If you need the startup file for interactive shells only, then set your
|
|
.B ENV
|
|
variable to a
|
|
value which evaluates to a file name for interactive shells and to
|
|
the null string otherwise. If you export the startup file name
|
|
in the variable
|
|
.BR START ,
|
|
then setting
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
ENV='${START[(_$\-=0)+(_=1)\-_${\-%%*i*}]}'
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
will only invoke the startup file for interactive shells
|
|
since the subscript evaluates to 0
|
|
only if the shell is interactive.
|
|
.P
|
|
If you need a startup
|
|
.B ENV
|
|
file for all shells
|
|
then use a
|
|
.B case
|
|
command on the
|
|
.B $\-
|
|
parameter to distinguish which actions only apply to interactive shells.
|
|
The
|
|
.B ENV
|
|
file should look like
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
# options aliases and functions for all shell invocations
|
|
case $\- in
|
|
*i*)
|
|
# options aliases and functions for interactive only
|
|
;;
|
|
esac
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
.P
|
|
If there are functions which are only occasionally referenced, put them
|
|
into a separate file
|
|
.B $HOME/functions
|
|
or any name you prefer
|
|
and put aliases in the
|
|
.B ENV
|
|
file for each function name of the form
|
|
.B
|
|
.sp
|
|
.nf
|
|
.in .5i
|
|
alias \f2function_name\fP='. $HOME/functions;\f2function_name\fP'
|
|
.fi
|
|
.ta
|
|
.in
|
|
.sp
|
|
.R
|
|
In the beginning of the
|
|
.B $HOME/functions
|
|
file you must unalias each of the function names defined in the
|
|
file.
|
|
The first reference to any
|
|
.I function_name
|
|
in the function file
|
|
causes the function file to get read in and the functions compiled.
|
|
The use of "autoload" (typeset \-fu) functions can also be used to
|
|
improve the performance of the shell by avoiding the definition of
|
|
functions until they are needed.
|
|
.H 1 "Conclusion"
|
|
.P
|
|
\f3ksh\fP has several thousand regular users.
|
|
\f3ksh\fP is a suitable replacement for the Bourne shell.
|
|
It offers new features,
|
|
better performance,
|
|
and is essentially upward compatible with the Bourne shell.
|
|
Many of the known bugs of the Bourne shell
|
|
have been eliminated.
|
|
.SG dgk \" signature typist initials
|
|
.CS 14 24 38 0 0 16 \" cover sheet for TM
|
|
.bp
|
|
.ce
|
|
APPENDIX
|
|
.nf
|
|
#
|
|
# SHELL VERSION OF GREP
|
|
#
|
|
vflag= xflag= cflag= lflag= nflag=
|
|
set \-f
|
|
while ((1)) # look for grep options
|
|
do case "$1" in
|
|
\-v*) vflag=1;;
|
|
\-x*) xflag=1;;
|
|
\-c*) cflag=1;;
|
|
\-l*) lflag=1;;
|
|
\-n*) nflag=1;;
|
|
\-b*) print \(fmb option not supported\(fm;;
|
|
\-e*) shift;expr="$1";;
|
|
\-f*) shift;expr=$( < $1 );;
|
|
\-*) print $0: \(fmunknown flag\(fm;exit 2;;
|
|
*) if test "$expr" = \(fm\|\(fm
|
|
then expr="$1";shift
|
|
fi
|
|
test "$xflag" |\|| expr="*${expr}*"
|
|
break;;
|
|
esac
|
|
shift # next argument
|
|
done
|
|
noprint=$vflag$cflag$lflag # don't print if these flags set
|
|
integer n=0 c=0 tc=0 nargs=$# # initialize counters
|
|
for i in "$@" # go through the files
|
|
do if ((nargs<=1))
|
|
then fname=\(fm\|\(fm
|
|
else fname="$i":
|
|
fi
|
|
test "$i" && exec 0< $i # open file if necessary
|
|
while read \-r line # read in a line
|
|
do let n=n+1
|
|
case "$line" in
|
|
$expr) # line matches pattern
|
|
if test "$noprint" = ""
|
|
then print \-r \- "$fname${nflag:+$n:}$line"
|
|
fi
|
|
let c=c+1 ;;
|
|
*) # not a match
|
|
if test "$vflag"
|
|
then print \-r \- "$fname${nflag:+$n:}$line"
|
|
fi;;
|
|
esac
|
|
done
|
|
if test "$lflag" && ((c))
|
|
then print \- $i
|
|
fi
|
|
let tc=tc+c n=0 c=0
|
|
done
|
|
test "$cflag" && print $tc # print count if cflag is set
|
|
let tc # set the exit value
|
|
.fi
|