home *** CD-ROM | disk | FTP | other *** search
- Subject: v19i001: A reimplementation of the System V shell, Part01/08
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: ka@june.cs.washington.edu (Kenneth Almquist)
- Posting-number: Volume 19, Issue 1
- Archive-name: ash/part01
-
- Ash is a reimplementation of the System V shell. Currently it has most
- features of that shell, plus some additions. It runs on 4.2 and 4.3BSD,
- SystemV releases 1, 2, 3, SystemIII, and perhaps Version 7. Documentation
- includes a list of differences, a manpage, and internals documentation.
- It has several built-ins and shell functions.
-
- Ash is copyrighted but there are few restrictions on what you can do
- with it. Read the file LICENSE, which gives the details and explains
- about the lack of a warrantee.
-
- ------------------------
- # This is part 1 of ash. To unpack, feed it into the shell (not csh).
- # The ash distribution consists of eight pieces. Be sure you get them all.
- # After you unpack everything, read the file README.
-
- echo extracting README
- cat > README <<\EOF
- What is ash?
-
- Ash is a reimplementation of the System V shell. Currently it has
- most features of that shell, plus some additions. The file ash.1
- contains the manual entry for ash. The file DIFFERENCES lists known
- differences between ash and the standard shell. The file TOUR provides
- some documentation of the internals. Manual pages for some builtin
- commands are in the bltin subdirectory.
-
- Ash is copyrighted but there are few restrictions on what you can do
- with it. Read the file LICENSE, which gives the details and explains
- about the lack of a warrantee.
-
-
- Compiling
-
- 1) Create shell.h. Three versions are provided with distribution:
- shell.h.bsd for 4.2/4.3 BSD
- shell.h.s5r3 for System V release 3
- shell.h.s5r2 for System III and System V release 1 and 2
- For a Version 7 system, try using shell.h.s5r2 with SYSV undefined.
-
- 2) Type "make". You may want to add DEBUG=-O to the make commands to
- turn on optimization. Also, use gcc rather than cc if you have it
- (but remember that ANSI compilers like gcc won't work with the BSD
- header files as distributed by Berkeley; if you use the unmodified
- header files with gcc, job control won't work.) If you don't have
- an ANSI C compiler, you will get a lot of messages about illegal
- pointer combinations; ignore them. You can also ignore messages
- from the loader telling you to run ranlib.
-
- 3) Install the commands where ever you feel like. Besides ash, there
- are several commands in the bltin directory: catf, expr, echo, line,
- nlecho test, [, and umask. These are stand alone versions of builtin
- commands. Finally, the directory funcs contains shell functions.
- Install these in a suitable directory and include them in your
- path (e. g. PATH=$PATH:$HOME/ash/funcs%func).
-
- If you are adventurous, you can compile with MALLOC=mymalloc.o, which
- will get you a version of malloc that uses a first fit allocation scheme.
- It may make more efficient use of memory than the standard version of
- malloc on your system. The code was written for a VAX and is somewhat
- machine dependent.
- EOF
- if test `wc -c < README` -ne 2114
- then echo 'README is the wrong size'
- fi
- if test ! -d bltin
- then mkdir bltin
- fi
- if test ! -d funcs
- then mkdir funcs
- fi
- echo extracting LICENSE
- cat > LICENSE <<\EOF
- ASH GENERAL PUBLIC LICENSE
-
- 1. You may copy and distribute ash code or code derived from it in
- source or object form, provided that you conspicuously and appropriately
- publish on each copy a valid copyright notice "Copyright 1989 by Kenneth
- Almquist." (or with whatever year is appropriate); keep intact the
- notices on all files that refer to this License Agreement and to the
- absence of any warranty; and give any other recipients of the ash program
- a copy of this License Agreement along with the program.
-
- 2. You may not copy, sublicense, distribute or transfer ash except as
- expressly provided under this License Agreement. Any attempt otherwise
- to copy, sublicense, distribute or transfer ash is void and your rights
- to use ash under this License agreement shall be automatically terminated.
- However, parties who have received computer software programs from you
- with this License Agreement will not have their licenses terminated so
- long as such parties remain in full compliance.
-
-
- NO WARRANTY
-
- Because ash is licensed free of charge, I provide absolutely no
- warranty, to the extent permitted by applicable state law. Except
- when otherwise stated in writing, Kenneth Almquist and/or other
- parties provide ash "as is" without warranty of any kind, either
- expressed or implied, including, but not limited to, the implied
- warranties of merchantability and fitness for a particular purpose.
- The entire risk as to the quality and performance of the program is
- with you. Should the ash program prove defective, you assume the cost
- of all necessary servicing, repair or correction.
-
- In no event unless required by applicable law will Kenneth Almquist
- and/or any other party who may modify and redistribute ash as permitted
- above, be liable to you for damages, including any lost profits, lost
- monies, or other special, incidental or consequential damages arising
- out of the use or inability to use (including but not limited to loss
- of data or data being rendered inaccurate or losses sustained by third
- parties or a failure of the program to operate with programs provided
- by other parties) the program, even if you have been advised of the
- possibility of such damages, or for any claim by any other party.
- EOF
- if test `wc -c < LICENSE` -ne 2230
- then echo 'LICENSE is the wrong size'
- fi
- rm -f bltin/LICENSE
- ln LICENSE bltin/LICENSE
- rm -f funcs/LICENSE
- ln LICENSE funcs/LICENSE
- echo extracting DIFFERENCES
- cat > DIFFERENCES <<\EOF
- If you are used to the Berkeley shell, there are a bunch of Sys-
- tem V features which will be new. I give a partial list here:
-
- 1. Shell functions are included. The syntax is:
-
- name () command
-
- Typically the command will be a list of commands enclosed
- between "{" and "}". The directory "funcs" contains a few
- sample functions.
-
- 2. The -f option suppresses file name generation.
-
- 3. The syntax "[!...]" specifies a negated character class which
- will match any character not in "...".
-
- 4. The first time you execute a command, the shell remembers
- where it found it. If a command is not found, nothing is
- recorded. If the location of a command changes, you can say
- "hash command_name" to cause the command to be searched for
- again, or you can say "hash -r" to cause it to forget the lo-
- cation of all commands.
-
- Differences between ash and the System V shell:
-
- 5. Shell functions can have local variables. These are declared
- by writing
- local var1 var2 ...
- at the top of the function. As a special case, the name "-"
- makes the shell options local to the function so that the
- original values of the options will be restored when the
- function returns. Function arguments and the internal vari-
- ables used by getopts are implicitly made local to a func-
- tion. This means that you can call a shell function, and
- when the shell function returns the values of the positional
- parameters ($1, $2, etc.) will be unchanged.
-
- 6. A directory of shell functions can be included in the search
- path. This is done by following the directory name by
- "%func". For example
-
- PATH=:/bin:/usr/bin:/usr/local/ashfuncs%func
-
- will cause the directory /usr/local/ashfuncs to be searched
- for shell functions. Each file in that directory should de-
- fine a shell function with the same name as the file. Some-
- times it's convenient to combine several related functions
- into a single file. In this case there must be one link to
- the file for each function (see ln(1)). Note that once a
- shell function has been read in, it will stay defined even if
- PATH is changed or you do a "hash -r" command.
-
- 7. Function definitions override builtin commands. In addition,
- if the string "%builtin" appears in PATH then the list of
- builtin commands will be search at that point in the path.
- If the string "%builtin" does not appear in PATH, then the
- list of builtin commands will be searched before PATH.
-
- 8. It is legal to have both a function and a variable with the
- same name. If you do this, then unset builtin will unset
- both the variable and the name.
-
- 9. Ash allows you to negate a pattern by prefixing it with two
- exclamation points. For example,
- ls src/!!*.o
- lists all files in the src directory whose names do not end
- in ".o". Two exclamation points are required rather than one
- to decrease the chances of users not familiar with this
- feature invoking it by accident.
-
- 10. Ash can simulate a /u directory containing the home direc-
- tories of all the users on the system. It is of course
- better to have this handled by the file system if your system
- supports symbolic links.
-
- 11. The readonly and export commands allow you to assign a value
- to a variable at the same time you export it or make it read
- only. For example:
-
- export TERM=2621
-
- sets the value of TERM to "2621" and then exports it.
-
- 12. The method that sh uses to handle variables passed to it in
- the environment appears to me to be unnecessarily confusing.
- When ash starts up, it reads the environment, and for each
- entry of the form "name=value", sets the variable "name" to
- "value" and exports "name".
-
- 13. The System V shell does strange things with backslashes in-
- side back quotes. In ash, commands inside back quotes are
- parsed just like other commands. Ash accepts "$(cmd)" as a
- synomynm for "`cmd`".
-
- 14. The login and newgrp builtins have been replaced with shell
- functions. The times and ulimit commands are not implement-
- ed.
-
- 15. The echo builtin has a "-n" option for compatibility with the
- BSD echo.
-
- 16. Test and expr have been merged into a single command and have
- been built in. Both commands accept the same syntax, which
- is a merger of the operators provided by the two commands in-
- dividually, except that the relational operators of expr have
- been omitted. I believe that the new command is slightly
- more picky that the old test command about using strings that
- are the same as operators; you should write
-
- test "'$line'" = "'X'"
-
- rather than
-
- test "$line" = ""
-
- The single quotes are used to indicate that the argument is a
- string rather than an operator. In the example I include
- single quotes around both arguments to the "=" operator rath-
- er than just the first one in order to make the test work
- correctly on versions of test that don't treat single quotes
- specially.
-
- Don't underestimate the power of regular expressions. For
- example, expr can compute substrings:
-
- y="`expr "$x" : ".\{4\}\(.\{0,3\}\)"`"
-
- sets y to the three character string of x beginning after the
- fourth character. If x is too short, it returns the all the
- characters available. (The System V syntax \{0,3\} matches 0
- to 3 occurances of the preceding character; \{4\} is a
- synonym for \{4,4\}.)
-
- 17. The following flags are not implemented: a, h, k, t, u, v.
- These don't seem very useful to me (with the possible excep-
- tion of -v), so I'm not likely to add them unless people ask.
-
- 18. An interface to the Berkeley job control facilities is pro-
- vided on systems where the kernel supports Berkeley job con-
- trol, although not all the features of csh are included. The
- -j flag turns on job control. (It is set on by default for
- interactive shells.) There are fg and bg commands function
- more or less like the csh equivalents.
-
- The jobs command lists all the processes that you have start-
- ed. It is available even on systems without job control.
-
- 19. The character ^ is not a synonym for |.
-
- 20. In an interactive shell, the variable "$_" is set to the
- value of the argument to the last command executed (exclusive
- of commands inside executed inside shell functions). This is
- intended to be used in sequences like:
- mkdir long_directory_name
- cd $_
- There is also a new builtin named "lc" (for last command)
- which re-executed the last command (with no arguments) or de-
- fines a function that will execute the command (if a function
- name is given as an argument). This is intended to make it
- easier to re-execute a command.
-
- I conclude by listing a few features that I have omitted inten-
- tionally.
-
- 1. Aliases. Use functions instead.
-
- 2. Features that duplicate existing functionality.
-
- 3. History. It seems to me that the csh history mechanism is
- mostly a response to the deficiencies of UNIX terminal I/O.
- Those of you running 4.2 BSD should try out atty (which I am
- posting to the net at the same time as ash) and see if you
- still want history.
-
- 4. Restricted shell. Restricted shells tend to be insecure.
- EOF
- if test `wc -c < DIFFERENCES` -ne 7363
- then echo 'DIFFERENCES is the wrong size'
- fi
- echo extracting ash.1
- cat > ash.1 <<\EOF
- .TH ASH 1
- .\" Copyright (C) 1989 by Kenneth Almquist.
- .de h \" subheading
- .sp
- .ti -0.3i
- .B "\\$1"
- .PP
- ..
- .de d \" begin display
- .sp
- .in +4
- .nf
- ..
- .de e \" end display
- .in -4
- .fi
- .sp
- ..
- .de c \" command, etc.
- .br
- .HP 5
- \fB\\$1\fR
- .br
- ..
- .de b \" begin builtin command
- .HP 5
- .B \\$1
- ..
- .SH NAME
- ash \- a shell
- .SH SYNOPSIS
- .B ash
- [
- .B -efIijnsxz
- ] [
- .B +efIijnsxz
- ] [
- .B -c
- .I command
- ] [
- .I arg
- ] ...
- .SH COPYRIGHT
- .if n Copyright (C) 1989 by Kenneth Almquist.
- .if t Copyright \(co 1989 by Kenneth Almquist.
- .SH DESCRIPTION
- .I Ash
- is a version of
- .I sh
- with features similar to those of the System V shell.
- This manual page lists all the features of
- .I ash
- but concentrates on the ones not in other shells.
- .h "Invocation"
- If the
- .B -c
- options is given, then the shell executes the specified shell command.
- The
- .B -s
- flag cause the shell to read commands from the standard input (after
- executing any command specified with the
- .B -c
- option.
- If neither the
- .B -s
- or
- .B -c
- options are set, then the first
- .I arg
- is taken as the name of a file to read commands from.
- If this is impossible because there are no arguments following
- the options, then
- .I ash
- will set the
- .B -s
- flag and will read commands from the standard input.
- .PP
- The shell sets the initial value of the positional parameters from the
- .IR arg s
- remaining after any
- .I arg
- used as the name of a file of commands is deleted.
- .PP
- The flags (other than
- .BR -c )
- are set by preceding them with ``-'' and cleared by preceding them
- with ``+''; see the
- .I set
- builtin command for a list of flags.
- If no value is specified for the
- .B -i
- flag, the
- .B -s
- flag is set, and the standard input and output of the shell
- are connected to terminals, then the
- .B -i
- flag will be set.
- If no value is specified for the
- .B -j
- flag, then the
- .B -j
- flag will be set if the
- .B -i
- flag is set.
- .PP
- When the shell is invoked with the
- .B -c
- option, it is good practice to include the
- .I -i
- flag if the command was entered interactively by a user.
- For compatibility with the System V shell, the
- .I -i
- option should come after the
- .B -c
- option.
- .PP
- If the first character of argument zero to the shell is ``-'',
- the shell is assumed to be a login shell, and the files
- .B /etc/profile
- and
- .B .profile
- are read if they exist.
- If the environment variable SHINIT is set on entry to the shell,
- the commands in SHINIT are normally parsed and executed. SHINIT is
- not examined if the shell is a login shell, or if it the shell is running a
- shell procedure. (A shell is considered to be running a shell
- procedure if neither the
- .B -s
- nor the
- .B -c
- options are set.)
- .h "Control Structures"
- A
- .I list
- is a sequence of zero or more commands separated by newlines,
- semicolons, or ampersands, and optionally terminated by one of these
- three characters. (This differs from the System V shell, which
- requires a list to contain at least one command in most cases.) The
- commands in a list are executed in the order they are written.
- If command is followed by an ampersand, the shell starts the command
- and immediately proceed onto the next command; otherwise it waits
- for the command to terminate before proceeding to the next one.
- .PP
- ``&&'' and ``||'' are binary operators.
- ``&&'' executes the first command, and then executes the second command
- iff the exit status of the first command is zero. ``||'' is similar,
- but executes the second command iff the exit status of the first command
- is nonzero. ``&&'' and ``||'' both have the same priority.
- .PP
- The ``|'' operator is a binary operator which feeds the standard output
- of the first command into the standard input of the second command.
- The exit status of the ``|'' operator is the exit status of the second
- command. ``|'' has a higher priority than ``||'' or ``&&''.
- .PP
- An
- .I if
- command looks like
- .d
- \fBif\fR list
- \fBthen\fR list
- .ti -\w'[ 'u
- [ \fBelif\fR list
- \fBthen\fR list ] ...
- .ti -\w'[ 'u
- [ \fBelse\fR list ]
- \fBfi\fR
- .e
- .PP
- A
- .I while
- command looks like
- .d
- \fBwhile\fR list
- \fBdo\fR list
- \fBdone\fR
- .e
- The two lists are executed repeatedly while the exit status of the first
- list is zero. The
- .I until
- command is similar, but has the word
- .B until
- in place of
- .B while
- repeats until the exit status of the first list
- is zero.
- .PP
- The
- .I for
- command looks like
- .d
- \fBfor\fR variable \fBin\fR word...
- \fBdo\fR list
- \fBdone\fR
- .e
- The words are expanded, and then the list is executed repeatedly with
- the variable set to each word in turn.
- .B do
- and
- .B done
- may be replaced with
- ``{'' and ``}''.
- .PP
- The
- .I break
- and
- .I continue
- commands look like
- .d
- \fBbreak\fR [ num ]
- \fBcontinue\fR [ num ]
- .e
- .I Break
- terminates the
- .I num
- innermost
- .I for
- or
- .I while
- loops.
- .I Continue
- continues with the next iteration of the
- .IRnum'th
- innermost loop.
- These are implemented as builtin commands.
- .PP
- The
- .I case
- command looks like
- .d
- \fBcase\fR word \fBin\fR
- pattern\fB)\fR list \fB;;\fR
- \&...
- \fBesac\fR
- .e
- The pattern can actually be one or more patterns (see
- .I Patterns
- below), separated by ``|'' characters.
- .PP
- Commands may be grouped by writing either
- .d
- \fB(\fRlist\fB)\fR
- .e
- or
- .d
- \fB{\fR list; \fB}\fR
- .e
- The first of these executes the commands in a subshell.
- .PP
- A function definition looks like
- .d
- name \fB( )\fR command
- .e
- A function definition is an executable statement; when executed it installs
- a function named
- .B name
- and returns an exit status of zero.
- The command is normally a list enclosed between ``{'' and ``}''.
- .PP
- Variables may be declared to be local to a function by using a
- .I local
- command. This should appear as the first staement of a function,
- and looks like
- .d
- \fBlocal\fR [ variable | \fB-\fR ] ...
- .e
- .I Local
- is implemented as a builtin command.
- .PP
- When a variable is made local, it inherits the initial value and
- exported and readonly flags from the variable with the same name in the
- surrounding scope, if there is one. Otherwise, the variable is
- initially unset.
- .I Ash
- uses dynamic scoping, so that if you make the variable
- .B x
- local to function
- .IR f ,
- which then calls function
- .IR g ,
- references to the variable
- .B x
- made inside
- .I g
- will refer to the variable
- .B x
- declared inside
- .IR f ,
- not to the global variable named
- .BR x .
- .PP
- The only special parameter than can be made local is ``\fB-\fR''.
- Making ``\fB-\fR'' local any shell options that are changed via the
- .I set
- command inside the function to be restored to their original values
- when the function returns.
- .PP
- The
- .I return
- command looks like
- .d
- \fBreturn\fR [ exitstatus ]
- .e
- It terminates the currently executing function.
- .I Return
- is implemented as a builtin command.
- .h "Simple Commands"
- A simple command is a sequence of words. The execution of a simple
- command proceeds as follows. First, the leading words of the form
- ``name=value'' are stripped off and assigned to the environment of
- the command. Second, the words are expanded. Third, the first
- remaining word is taken as the command name that command is located.
- Fourth, any redirections are performed. Fifth, the command is
- executed. We look at these operations in reverse order.
- .PP
- The execution of the command varies with the type of command.
- There are three types of commands: shell functions, builtin commands,
- and normal programs.
- .PP
- When a shell function is executed, all of the shell positional parameters
- (except $0, which remains unchanged) are set to the parameters to the shell
- function. The variables which are explicitly placed in the environment
- of the command (by placing assignments to them before the function name)
- are made local to the function and are set to values given.
- Then the command given in the function definition is executed.
- The positional parameters are restored to their original values when
- the command completes.
- .PP
- Shell builtins are executed internally to the shell, without spawning
- a new process.
- .PP
- When a normal program is executed, the shell runs the program, passing
- the parameters and the environment to the program. If the program is
- a shell procedure, the shell will interpret the program in a subshell.
- The shell will reinitialize itself in this case, so that the effect
- will be as if a new shell had been invoked to handle the shell procedure,
- except that the location of commands located in the parent shell will
- be remembered by the child. If the program is a file beginning with
- ``#!'', the remainder of the first line specifies an interpreter for
- the program. The shell (or the operating system, under Berkeley UNIX)
- will run the interpreter in this case. The arguments to the interpreter
- will consist of any arguments given on the first line of the program,
- followed by the name of the program, followed by the arguments passed
- to the program.
- .h "Redirection"
- Input/output redirections can be intermixed with the words in a simple
- command and can be placed following any of the other commands. When
- redirection occurs, the shell saves the old values of the file descriptors
- and restores them when the command completes. The ``<'', ``>'', and ``>>''
- redirections open a file for input, output, and appending, respectively.
- The ``<&digit'' and ``>&digit'' makes the input or output a duplicate
- of the file descriptor numbered by the digit. If a minus sign is used
- in place of a digit, the standard input or standard output are closed.
- .PP
- The ``<<\ word'' redirection
- takes input from a
- .I here
- document.
- As the shell encounters ``<<'' redirections, it collects them. The
- next time it encounters an unescaped newline, it reads the documents
- in turn. The word following the ``<<'' specifies the contents of the
- line that terminates the document. If none of the quoting methods
- ('', "", or \e) are used to enter the word, then the document is treated
- like a word inside double quotes: ``$'' and backquote are expanded
- and backslash can be used to escape these and to continue long lines.
- The word cannot contain any variable or command substitutions, and
- its length (after quoting) must be in the range of 1 to 79 characters.
- If ``<<-'' is used in place of ``<<'', then leading tabs are deleted
- from the lines of the document. (This is to allow you do indent shell
- procedures containing here documents in a natural fashion.)
- .PP
- Any of the preceding redirection operators may be preceded by a single
- digit specifying the file descriptor to be redirected. There cannot
- be any white space between the digit and the redirection operator.
- .h "Path Search"
- When locating a command, the shell first looks to see if it has a
- shell function by that name. Then, if PATH does not contain an
- entry for "%builtin", it looks for a builtin command by that name.
- Finally, it searches each entry in PATH in turn for the command.
- .PP
- The value of the PATH variable should be a series of entries separated
- by colons.
- Each entry consists of a directory name, or a directory name followed
- by a flag beginning with a percent sign.
- The current directory should be indicated by an empty directory name.
- .PP
- If no percent sign is present, then the entry causes the shell to
- search for the command in the specified directory. If the flag is
- ``%builtin'' then the list of shell builtin commands is searched.
- If the flag is ``%func'' then the directory is searched for a file which
- is read as input to the shell. This file should define a function
- whose name is the name of the command being searched for.
- .PP
- Command names containing a slash are simply executed without performing
- any of the above searches.
- .h "The Environment"
- The environment of a command is a set of name/value pairs. When the
- shell is invoked, it reads these names and values, sets the shell
- variables with these names to the corresponding values, and marks
- the variables as exported. The
- .I export
- command can be used to mark additional variables as exported.
- .PP
- The environment of a command is constructed by constructing name/value
- pairs from all the exported shell variables, and then modifying this
- set by the assignments which precede the command, if any.
- .h "Expansion"
- The process of evaluating words when a shell procedure is executed is
- called
- .IR expansion .
- Expansion consists of four steps: variable substitution, command
- substitution, word splitting, and file name generation. If a word
- is the expression following the word
- .B case
- in a case statement, the file name
- which follows a redirection symbol, or an assignment to the environment
- of a command, then the word cannot be split into multiple words. In
- these cases, the last two steps of the expansion process are omitted.
- .h "Variable Substitution"
- To be written.
- .h "Command Substitution"
- .I Ash
- accepts two syntaxes for command substitution:
- .b
- `\fIlist\fR`
- .e
- and
- .b
- $(\fIlist\fR)
- .e
- Either of these may be included in a word.
- During the command substitution process, the command (syntactly a
- .IR list )
- will be executed and anything that the command writes to the standard
- output will be captured by the shell. The final newline (if any) of
- the output will be deleted; the rest of the output will be substituted
- for the command in the word.
- .h "Word Splitting"
- When the value of a variable or the output of a command is substituted,
- the resulting text is subject to word splitting, unless the dollar sign
- introducing the variable or backquotes containing the text were enclosed
- in double quotes. In addition, ``$@'' is subject to a special type of
- splitting, even in the presence of double quotes.
- .PP
- Ash uses two different splitting algorithms. The normal approach, which
- is intended for splitting text separated by which space, is used if the
- first character of the shell variable IFS is a space. Otherwise an alternative
- experimental algorithm, which is useful for splitting (possibly empty)
- fields separated by a separator character, is used.
- .PP
- When performing splitting, the shell scans the replacement text looking
- for a character (when IFS does not begin with a space) or a sequence of
- characters (when IFS does begin with a space), deletes the character or
- sequence of characters, and spits the word into two strings at that
- point. When IFS begins with a space, the shell deletes either of the
- strings if they are null. As a special case, if the word containing
- the replacement text is the null string, the word is deleted.
- .PP
- The variable ``$@'' is special in two ways. First, splitting takes
- place between the positional parameters, even if the text is enclosed
- in double quotes. Second, if the word containing the replacement
- text is the null string and there are no positional parameters, then
- the word is deleted. The result of these rules is that "$@" is
- equivalent to "$1" "$2" ... "$\fIn\fR", where \fIn\fR is the number of
- positional parameters. (Note that this differs from the System V shell.
- The System V documentation claims that "$@" behaves this way; in fact
- on the System V shell "$@" is equivalent to "" when there are no
- positional paramteters.)
- .h "File Name Generation"
- Unless the
- .B -f
- flag is set, file name generation is performed after word splitting is
- complete. Each word is viewed as a series of patterns, separated by
- slashes. The process of expansion replaces the word with the names of
- all existing files whose names can be formed by replacing each pattern
- with a string that matches the specified pattern. There are two
- restrictions on this: first, a pattern cannot match a string containing
- a slash, and second, a pattern cannot match a string starting with a
- period unless the first character of the pattern is a period.
- .PP
- If a word fails to match any files and the
- .B -z
- flag is not set, then the word will be left unchanged (except that the
- meta-characters will be converted to normal characters). If the
- .B -z
- flag is set, then the word is only left unchanged if none
- of the patterns contain a character that can match anything besides
- itself. Otherwise the
- .B -z
- flag forces the word to be replaced with the names of the files that it
- matches, even if there are zero names.
- .h "Patterns"
- A
- .I pattern
- consists of normal characters, which match themselves, and meta-characters.
- The meta-characters are ``!'', ``*'', ``?'', and ``[''. These characters lose
- there special meanings if they are quoted. When command or variable
- substitution is performed and the dollar sign or back quotes are not
- double quoted, the value of the variable or the output of the command
- is scanned for these characters and they are turned into meta-characters.
- .PP
- Two exclamation points at the beginning of a pattern function as a ``not''
- operator, causing the pattern to match any string that the remainder of
- the pattern does
- .I not
- match. Other occurances of exclamation points in a pattern match
- exclamation points. Two exclamation points are required rather than one
- to decrease the incompatibility with the System V shell (which does not
- treat exclamation points specially).
- .PP
- An asterisk (``*'') matches any string of characters.
- A question mark matches any single character.
- A left bracket (``['') introduces a character class. The end of the
- character class is indicated by a ``]''; if the ``]'' is missing then
- the ``['' matches a ``['' rather than introducing a character class.
- A character class matches any of the characters between the square
- brackets. A range of characters may be specified using a minus sign.
- The character class may be complemented by making an exclamation point
- the first character of the character class.
- .PP
- To include a ``]'' in a character class, make it the first character listed
- (after the ``!'', if any).
- To include a minus sign, make it the first or last character listed.
- .h "The /u Directory"
- By convention, the name ``/u/user'' refers to the home directory of the
- specified user. There are good reasons why this feature should be supported
- by the file system (using a feature such as symbolic links) rather than
- by the shell, but
- .I ash
- is capable of performing this mapping if the file system doesn't.
- If the mapping is done by
- .IR ash ,
- setting the
- .B -f
- flag will turn it off.
- .h "Character Set"
- .I Ash
- silently discards nul characters. Any other character will be handled
- correctly by
- .IR ash ,
- including characters with the high order bit set.
- .h "Job Names and Job Control"
- The term
- .I job
- refers to a process created by a shell command, or in the case of a
- pipeline, to the set of processes in the pipeline. The ways to refer
- to a job are:
- .b
- %\fInumber\fR
- %\fIstring\fR
- %%
- \fIprocess_id\fR
- .e
- The first form identifies a job by job number.
- When a command is run,
- .I ash
- assigns it a job number
- (the lowest unused number is assigned).
- The second form identifies a job by giving a prefix of the command used
- to create the job. The prefix must be unique. If there is only one job,
- then the null prefix will identify the job, so you can refer to the job
- by writing ``%''. The third form refers to the \fIcurrent job\fR. The
- current job is the last job to be stopped while it was in the foreground.
- (See the next paragraph.) The last form identifies a job by giving the
- process id of the last process in the job.
- .PP
- If the operating system that
- .I ash
- is running on supports job control,
- .I ash
- will allow you to use it.
- In this case, typing the suspend character (typically ^Z) while running
- a command will return you to
- .I ash
- and will make the suspended command the current job. You can then continue
- the job in the background by typing
- .IR bg ,
- or you can continue it in the foreground by typing
- .IR fg .
- .h "Atty"
- If the shell variable ATTY is set, and the shell variable TERM is not
- set to ``emacs'', then \fIash\fR generates appropriate escape sequences
- to talk to
- .IR atty (1).
- .h "Exit Statuses"
- By tradition, an exit status of zero means that a command has succeeded
- and a nonzero exit status indicates that the command failed. This is
- better than no convention at all, but in practice it is extremely useful
- to allow commands that succeed to use the exit status to return information
- to the caller. A variety of better conventions have been proposed, but
- none of them has met with universal approval. The convention used by
- \fIash\fR and all the programs included in the \fIash\fR distribution is
- as follows:
- .ta 1i,2i
- .nf
- 0 Success.
- 1 Alternate success.
- 2 Failure.
- 129-... Command terminated by a signal.
- .fi
- The \fIalternate success\fR return is used by commands to indicate various
- conditions which are not errors but which can, with a little imagination,
- be conceived of as less successful than plain success. For example,
- .I test
- returns 1 when the tested condition is false and
- .I getopts
- returns 1 when there are no more options.
- Because this convention is not used universally, the
- .B -e
- option of
- .I ash
- causes the shell to exit when a command returns 1 even though that
- contradicts the convention described here.
- .PP
- When a command is terminated by a signal, the uses 128 plus the signal
- number as the exit code for the command.
- .h "Builtin Commands"
- This concluding section lists the builtin commands which are builtin
- because they need to perform some operation that can't be performed by a
- separate process. In addition to these, there are several other commands
- .RI ( catf ,
- .IR echo ,
- .IR expr ,
- .IR line ,
- .IR nlecho ,
- .IR test ,
- .RI `` : '',
- and
- .IR true )
- which can optionally be compiled into the shell. The builtin
- commands described below that accept options use the System V Release 2
- .IR getopt (3)
- syntax.
- .sp
- .b bg
- [
- .I job
- ] ...
- .br
- Continue the specified jobs (or the current job if no jobs are given)
- in the background.
- This command is only available on systems with Bekeley job control.
- .b bltin
- .IR "command arg" ...
- .br
- Execute the specified builtin command. (This is useful when you have a
- shell function with the same name as a builtin command.)
- .b cd
- [
- .I directory
- ]
- .br
- Switch to the specified directory (default $HOME).
- If the an entry for CDPATH appears in the environment of the cd command
- or the shell variable CDPATH is set and the directory name does not
- begin with a slash, then the directories listed in CDPATH will be
- searched for the specified directory. The format of CDPATH is the
- same as that of PATH.
- In an interactive shell, the cd command will print out the name of the
- directory that it actually switched to if this is different from the
- name that the user gave. These may be different either because
- the CDPATH mechanism was used or because a symbolic link was crossed.
- .b ".\fI\h'0.1i'file"
- .br
- The commands in the specified file are read and executed by the shell.
- A path search is not done to find the file because the directories in
- PATH generally contain files that are intended to be executed, not read.
- .b eval
- .IR string ...
- .br
- The strings are parsed as shell commands and executed.
- (This differs from the System V shell, which concatenates the arguments
- (separated by spaces) and parses the result as a single command.)
- .b exec
- [
- .IR "command arg" ...
- ]
- .br
- Unless
- .I command
- is omitted,
- the shell process is replaced with the specified program (which must be a real
- program, not a shell builtin or function).
- Any redirections on the exec command are marked as permanent, so that they
- are not undone when the exec command finishes.
- If the command is not found, the exec command causes the shell to exit.
- .b exit
- [
- .I exitstatus
- ]
- .br
- Terminate the shell process. If
- .I exitstatus
- is given it is used as the
- exit status of the shell; otherwise the exit status of the preceding
- command is used.
- .b export
- .IR name ...
- .br
- The specified names are exported so that they will appear in the environment
- of subsequent commands. The only way to un-export a variable is to unset it.
- .I Ash
- allows the value of a variable to be set at the same time it is exported
- by writing
- .d
- \fBexport\fR name=value
- .e
- With no arguments the export command lists the names of all exported variables.
- .b fg
- [
- .I job
- ]
- .br
- Move the specified job or the current job to the foreground.
- This command is only available on systems with Bekeley job control.
- .b getopts
- .I optstring
- .I var
- .br
- The System V
- .I getopts
- command.
- .b hash
- .B -rv
- .IR command ...
- .br
- The shell maintains a hash table which remembers the locations of
- commands. With no arguments whatsoever, the hash command prints
- out the contents of this table. Entries which have not been looked
- at since the last
- .I cd
- command are marked with an asterisk; it is possible for these entries
- to be invalid.
- .sp
- With arguments, the hash command removes the specified commands from
- the hash table (unless they are functions) and then locates them.
- With the
- .B -v
- option,
- .I hash
- prints the locations of the commands as it finds them.
- The
- .B -r
- option causes the
- .I hash
- command to delete all the entries in the hash table except for
- functions.
- .b jobid
- [
- .I job
- ]
- .br
- Print the process id's of the processes in the job. If the job argument
- is omitted, use the current job.
- .b jobs
- .br
- This command lists out all the background processes which are children
- of the current shell process.
- .b lc
- [
- .I function-name
- ]
- .br
- The function name is defined to execute the last command entered.
- If the function name is omitted, the last command executed is
- executed again. This command only works if the
- .B -i
- flag is set.
- .b pwd
- .br
- Print the current directory. The builtin command may differ from the
- program of the same name because the builtin command remembers what
- the current directory is rather than recomputing it each time. This
- makes it faster. However, if the current directory is renamed, the
- builtin version of pwd will continue to print the old name for the
- directory.
- .b read
- [
- .B -p
- .I prompt
- ]
- [
- .B -e
- ]
- .IR variable ...
- .br
- The prompt is printed if the
- .B -p
- option is specified and the standard input is a terminal. Then a
- line is read from the standard input. The trailing newline is deleted
- from the line and the line is split as described
- in the section on word splitting above, and the pieces are assigned to
- the variables in order. If there are more pieces than variables, the
- remaining pieces (along with the characters in IFS that separated them)
- are assigned to the last variable. If there are more variables than
- pieces, the remaining variables are assigned the null string.
- .sp
- The
- .B -e
- option causes any backslashes in the input to be treated specially.
- If a backslash is followed by a newline, the backslash and the newline
- will be deleted. If a backslash is followed by any other character,
- the backslash will be deleted and the following character will be treated
- as though it were not in IFS, even if it is.
- .b readonly
- .IR name ...
- .br
- The specified names are marked as read only, so that they cannot be
- subsequently modified or unset.
- .I Ash
- allows the value of a variable to be set at the same time it is marked
- read only by writing
- .d
- \fBreadonly\fR name=value
- .e
- With no arguments the readonly command lists the names of all
- read only variables.
- .b set
- [
- {
- .BI - options
- |
- .BI + options
- |
- .B --
- }
- ]
- .IR arg ...
- .br
- The
- .I set
- command performs three different functions.
- .sp
- With no arguments, it lists the values of all shell variables.
- .sp
- If options are given, it sets the specified option flags, or clears
- them if the option flags are introduced with a
- .B +
- rather than a
- .BR - .
- Only the first argument to
- .I set
- can contain options.
- The possible options are:
- .sp
- .ta 0.4i
- .in +0.4i
- .ti -0.4i
- \fB-e\fR Causes the shell to exit when a command terminates with
- a nonzero exit status, except when the exit status of the command is
- explicitly tested. The exit status of a command is considered to be
- explicitly tested if the command is used to control an
- .IR if ,
- .IR elif ,
- .IR while ,
- or
- .IR until ;
- or if the command is the left hand operand of an ``&&'' or ``||''
- operator.
- .sp
- .ti -0.4i
- \fB-f\fR Turn off file name generation.
- .sp
- .ti -0.4i
- \fB-I\fR Cause the shell to ignore end of file conditions.
- (This doesn't apply when the shell a script sourced using the ``.''
- command.) The shell will in fact exit if it gets 50 eof's in a
- row.
- .sp
- .ti -0.4i
- \fB-i\fR Make the shell interactive. This causes the shell to
- prompt for input, to trap interrupts, to ignore quit and terminate signals,
- and to return to the main command loop rather than exiting on error.
- .sp
- .ti -0.4i
- \fB-j\fR Turns on Berkeley job control, on systems that support it.
- When the shell starts up, the
- .B -j
- is set by default if the
- .B -i
- flag is set.
- .sp
- .ti -0.4i
- \fB-n\fR Causes the shell to read commands but not execute them.
- (This is marginally useful for checking the syntax of scripts.)
- .sp
- .ti -0.4i
- \fB-s\fR If this flag is set when the shell starts up, the shell
- reads commands from its standard input. The shell doesn't examine the
- value of this flag any other time.
- .sp
- .ti -0.4i
- \fB-x\fR If this flag is set, the shell will print out each
- command before executing it.
- .sp
- .ti -0.4i
- \fB-z\fR If this flag is set, the file name generation process
- may generate zero files. If it is not set, then a pattern which does
- not match any files will be replaced by a quoted version of the pattern.
- .in -0.4i
- .sp
- The third use of the set command is to set the values of the shell's
- positional parameters to the specified
- .IR args .
- To change the positional parameters without changing any options,
- use ``\fB--\fR'' as the first argument to
- .IR set .
- If no args are present, the set command will leave the value of the
- positional parameters unchanged, so to set the positional parameters
- to set of values that may be empty, execute the command
- .d
- shift $#
- .e
- first to clear out the old values of the positional parameters.
- .b setvar
- .I variable
- .I value
- .br
- Assigns
- .I value
- to
- .IR variable .
- (In general it is better to write
- .I variable=value
- rather than using
- .IR setvar .
- .I Setvar
- is intended to be used in functions that assign values to variables whose
- names are passed as parameters.)
- .b shift
- [
- .I n
- ]
- .br
- Shift the positional parameters
- .I n
- times.
- A shift sets the value of $1 to the value of $2, the value of $2 to
- the value of $3, and so on, decreasing the value of $# by one.
- If there are zero positional parameters, shifting doesn't do anything.
- .b trap
- [
- .I action
- ]
- .IR signal ...
- .br
- Cause the shell to parse and execute
- .I action
- when any of the specified signals are received.
- The signals are specified by signal number.
- .I Action
- may be null or omitted;
- the former causes the specified signal to be ignored and the latter
- causes the default action to be taken.
- When the shell forks off a subshell, it resets trapped (but not ignored)
- signals to the default action.
- The trap command has no effect on signals that were ignored on entry
- to the shell.
- .b umask
- [
- .I mask
- ]
- .br
- Set the value of umask (see
- .IR umask (2))
- to the specified octal value. If the argument is omitted, the umask
- value is printed.
- .b unset
- .IR name ...
- .br
- The specified variables and functions are unset and unexported.
- If a given name corresponds to both a variable and a function, both the
- variable and the function are unset.
- .b wait
- [
- .I job
- ]
- .br
- Wait for the specified job to complete and return the exit status of the
- last process in the job. If the argument is omitted, wait for all jobs
- to complete and the return an exit status of zero.
- .SH EXAMPLES
- The following function redefines the \fIcd\fR command:
- .d
- cd() {
- if bltin cd "$@"
- then if test -f .enter
- then . .enter
- else return 0
- fi
- fi
- }
- .e
- This function causes the file ``.enter'' to be read when you enter a
- directory, if it exists. The \fIbltin\fR command is used to access the
- real \fIcd\fR command. The ``return 0'' ensures that the function will
- return an exit status of zero if it successfully changes to a directory
- that does not contain a ``.enter'' file. Redefining existing commands
- is not always a good idea, but this example shows that you can do it if
- you want to.
- .PP
- The suspend function distributed with
- .I ash
- looks like
- .d
- # Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
- # This file is part of ash, which is distributed under the terms
- # specified by the Ash General Public License.
-
- suspend() {
- local -
- set +j
- kill -TSTP 0
- }
- .e
- This turns off job control and then sends a stop signal to the current
- process group, which suspends the shell. (When job control is turned
- on, the shell ignores the TSTP signal.) Job control will be turned back
- on when the function returns because ``-'' is local to the function.
- As an example of what \fInot\fR to do, consider an earlier version of
- \fIsuspend\fR:
- .d
- suspend() {
- suspend_flag=$-
- set +j
- kill -TSTP 0
- set -$suspend_flag
- }
- .e
- There are two problems with this. First, \fBsuspend_flag\fR is a global
- variable rather than a local one, which will cause problems in the
- (unlikely) circumstance that the user is using that variable for some
- other purpose. Second, consider what happens if shell received an interrupt
- signal after it executes the first \fIset\fR command but before it executes
- the second one. The interrupt signal will abort the shell function, so
- that the second \fIset\fR command will never be executed and job control
- will be left off. The first version of \fIsuspend\fR avoids this problem
- by turning job control off only in a local copy of the shell options. The
- local copy of the shell options is discarded when the function is terminated,
- no matter how it is terminated.
- .SH HINTS
- Shell variables can be used to provide abbreviations for things which
- you type frequently. For example, I set
- .br
- \h'1i'export h=$HOME
- .br
- in my .profile so that I can type the name of my home directory simply
- by typing ``$h''.
- .PP
- When writing shell procedures, try not to make assumptions about what is
- imported from the environment. Explicitly unset or initialize all variables,
- rather than assuming they will be unset. If you use cd, it is a good idea
- to unset CDPATH.
- .PP
- People sometimes use ``<&-'' or ``>&-'' to provide no input to a command
- or to discard the output of a command. A better way to do this is
- to redirect the input or output of the command to
- .BR /dev/null .
- .PP
- Word splitting and file name generation are performed by default,
- and you have to explicitly use double quotes to suppress it. This is
- backwards, but you can learn to live with it. Just get in the habit of
- writing double quotes around variable and command substitutions, and
- omit them only when you really want word splitting and file name generation.
- If you want word splitting but not file name generation, use the
- .B -f
- option.
- .SH AUTHORS
- Kenneth Almquist
- .SH "SEE ALSO"
- echo(1), expr(1), line(1), pwd(1), true(1).
- .SH BUGS
- When command substitution occurs inside a here document, the commands inside
- the here document are run with their standard input closed. For example,
- the following will not word because the standard input of the
- .I line
- command will be closed when the command is run:
- .d
- cat <<-!
- Line 1: $(line)
- Line 2: $(line)
- !
- .e
- .PP
- Unsetting a function which is currently being executed may cause strange
- behavior.
- .PP
- The shell syntax allows a here document to be terminated by an end of file
- as well as by a line containing the terminator word which follows the ``<<''.
- What this means is that if you mistype the terminator line, the shell
- will silently swallow up the rest of your shell script and stick it
- in the here document.
- EOF
- if test `wc -c < ash.1` -ne 35111
- then echo 'ash.1 is the wrong size'
- fi
- echo Archive 1 unpacked
- exit
-
-