ARG_MAX
| Shells
| portability
| permissions
| UUOC
| ancient
| -
| ../Various
| HOME
$() vs )
| IFS
| using siginfo
| nanosleep
| line charset
| locale
2010-09-01 (see recent changes)
This page is about all the variants of the original Bourne shell - it doesn't deal with bourne compatible shells like the korn (ksh), almquist (ash), bourne again (bash) or posix shell.
The Bourne shell, introduced with the "7th edition" of Unix, is an important part of the Unix history. Its grammar is the core of several modern shells. Even some later variants of the traditional Bourne shell are in use until today. However, there's little common knowledge about all these variants, because they never had been "versioned" -- this page tries to document their way.
Originally, this started with a rough english translation of <3B9529F8.2RV1IN16U@bigfoot.de> from de.comp.os.unix.shell. Credits for that posting and for countless further comments to Gunnar Ritter. Without The Unix Heritage Society (TUHS) the early releases couldn't have been documented in detail here. Many thanks also to Dennis Ritchie for access to the Version 8 shell and to Warren Toomey (TUHS) concerning the SVR1 shell. I inspected the Bourne shell on these unix systems (credits included). If you can provide further information, I really would like to hear from you.
Find more information about the origins of the Bourne shell at the bottom of this page.
How to identify a traditional Bourne shell?
1
A simple check for an often undocumented but characteristic feature:
You can use the circumflex ^ (caret) as replacement for | (pipe).
This was inherited from the predecessor, the Thompson shell, probably
for reasons of convenience
on early upper-case-only terminals.
See more common characteristics that are
unique to traditional Bourne shells. 2
| [1] |
Naturally, virtually all commercial systems provide
a traditional Bourne shell. Meanwhile, you'll find it at a different path
on some systems (e.g., HP-UX 10 ff., /usr/old/bin/sh)
or under the different name bsh (e.g., on AIX 4 ff. and
IRIX 6.4 ff.). On Ultrix you'll find a second variant as
/bin/sh5. On OSF1 there is the optional
/usr/opt/svr4/usr/bin/sh.
See also various system shells.
No rule without exception: HP stopped including it with release
"HP-UX 11i Version 1.5" (and Cray had stopped including it with
"Unicos 9").
|
| [2] | If you're interested in general script portability, then have a look at Paul Jarc's list of suspicious or nonportable constructs concerning modern portable script-writing. |
Some subpages will be referred to concerning selected issues.
Thanks to the OpenSolaris project, Gunnar Ritter could publish a source port of a SVR4 variant of the Bourne shell. This is the first officially available later Bourne shell on free unix flavours.
Todo: Bourne shell before Version 7 (unreleased) 3 , better differentiate SVR3.x and SVR4.x.
| [3] |
The Version 7 variant contains a char* version = "\nVERSION sys137 DATE 1978 Nov 6 14:29:22\n".
However, it's not used, remains unchanged in the source in following releases and disappears with SVR2 (when the source is de-algol68ized). |
Table of contents
· Version 7 (2.9BSD)
and 3/4BSD (and SunOS 2)
- Ultrix
- DomainOS 10.3
· System III (Plexus 1.0)
and SINIX
· SVR1
· SVR2 (MV/UX 3)
and Ultrix sh5
- Version 8
- SunOS 3
- OSF/1
- HP/UX
· SVR3 (MUNIX V3, SINIX 5.20, XENIX 2.3.4)
and SunOS 4
- AIX
- IRIX 3/4
- SCO Unix
- Interactive Unix
- DG/UX 40
- DomainOS 10.3
· SVR4 (Reliant 5.42, OSF1-SysV)
and SunOS 5
- Heirloom
- Schily
- IRIX 5/6
- DG/UX 42
- EP/IX
- Reliant UNIX
· SVR4.2 (UnixWare, OpenUnix)
A summary of some important changes
| · Version 7 | control structures, cmd substitution, () and {}, arbitrary variable names, trap, eval, special parameter substitutions, case
| ||
| · System III | #, [!...], colon parameter substitution, set --
| ||
| · SVR1 | shift n
| ||
| · SVR2 | functions, type built-in, redirection for builtins
| ||
| · SVR3 | modern "$@", 8-bit clean, getopts, functions don't modify positional parameters
| ||
| · SVR4.0 | job control | ||
| · SVR4.2 | read -r
|
The details are following here:
The item "Version 7" lists some important
differences to its predecessors and successors.
All subsequent items list the differences to their
predecessor as complete as possible.
if/switch/while, but called an
external goto to move the filepointer. As of mid'76, they were all built in.
>& <& and <&-
(especially proper handling of stderr)
`...` (command substitution)
() and {}
IFS
trap
(proper signal handling, onintr in the PWB shell
just called goto)
case
${-=?+}
eval
umask.
PS2 functionality
envx
A quick glance at differences to later variants:
unset" facility, i.e., no way to remove
variables from the environment (instead of assigning the empty value)
[" built-in available (even not as external command
on Version 7), but only the external "test"
#', is not a comment character yet
5
/etc/profile (i.e., no global profile)
set -- to separate options from arguments
| [4] |
The PWB aka Mashey shell also evolved from the Thompson shell. The main motivation
for its creation was providing for large amounts of procedural automation. |
| [5] |
Without '#', comments are only available by the null-command,
':' (colon),but naturally not without possible side effects. A special example is " : `echo output 1>&2`"
|
| [6] |
A Bourne shell not being 8-bit clean shows subtle bugs, e.g., when using the
special forms of parameter substitution in connection with double quotes:
The internal quoting mechanism sets the 8th bit for quoted characters and accidentally this is not removed afterwards.
|
/bin/csh if
the first character of an executable script is '#'
(the #! kernel
mechanism came later)
#' introduced.
uid=0 or if euid!=uid
| [7] |
In the traditional BSD line, the Bourne shell was shipped
until 4.3BSD-Reno (but not anymore with Net/2 and the following 4.4BSDs).
For license reasons it was then substituted with the bourne-compatible, svr4-like ash by Kenneth Almquist.
|
| [8] |
SINIX offers three universes: "ucb",
"sie"(mens) and "xopen" (aka "att").
These provide shells from 4.2BSD, SystemIII and SVR3, respectively. Here are some notes about the sinix universes. |
/bin/sh, see below for /bin/sh5)
ulimit [-f]" built-in (backported)
/etc/profile (global profile, backported, undocumented)
TIMEOUT changed from 2400 to 0
continue n" works (backport from SVR2)
trap statements with syntax errors (avoids "longjmp botch" error) (06-85)
continue n" works (backport from SVR2) (11-85)
IFS (05-86)
if false; then...") (07-89)
fork checking improved and new error messages
(probably backported from System V, that is, System III) (04-90)
SHENV: path of script
executed at invocation of each new shell
-Dname=value: supply environment variables
(for calling from binary executables)
| [9] | DomainOS offers two universes: "bsd4.3" and "sys5.3" each providing an according shell variant. |
/etc/profile
#'
${parameter:=word}"
[...]" , e.g., "[!0-9]"
(not documented yet)
set" recognizes "--" as option
delimiter, for arguments with a leading "-"
or "+"
set" knows "+" to unset a
respective switch
-" (turn off flags x and v) is not needed
anymore but (probably accidentally) remains active without being documented
anymore.
test", aka "[", added
(the latter actually was always existent in code, but commented out)
read" strips the leading IFS characters (undocumented)
read" recognizes multiple IFS characters as one
field delimiter when reading several variables (undocumented)
<<-" strips leading tabs
if false ;then :;fi;echo $?" formerly
wrongly yielded the exit status of false
(essential fix for the "-e" flag)
continue n" works (you couldn't jump to outer loops before)
echo */" resulted in a SEGV if there were filenames
with metacharacters
fork checking improved, new error messages
"cannot fork: too many processes" and "...: no swap space".
-r") added.
The environment variable "SHELL" is inspected at start-up.
-r" was accepted and even
listed under SYNOPSIS but neither implemented nor mentioned otherwise.
exit" allows leaving an interactive shell now
chdir" deactivated (undocumented)
read" doesn't strip the leading IFS characters
read" doesn't recognize multiple IFS characters
as one field delimiter when reading several variables
display" built-in identical to
the "echo" utility.
(The echo built-in comes in SVR2.)
chdir" not deactivated
ulimit" (show file size limit)
shift" accepts a number
cd" knows CDPATH
test" knows -p to check for named pipe
return" built-in).
positional parameters
are not local yet
type unset hash echo pwd"
set | pg" or "read variable < file"
"$@" (or ${1+"$@"}),
empty arguments are not discarded anymore (not to confuse with the
later, modern "$@")
& or ``)cat<<EOF& ..."
or "a=`cat<<EOF ...`"
(was: "/tmp/sh12345: cannot open")
"continue" and "break"
eval 'echo foo>a' >b" (was: "illegal io")
-afh"
readonly without arguments doesn't list the exported
variables anymore
MAILCHECK, MAILPATH
hash built-in introduces an internal limit
SHACCT
(not activated on Ultrix)
type output
for case in a function fixed
LOGNAME via getpwuid() (12-89)
sh5 )
HISTORY, pointing to a writable
file, providing a history mechanism by
"=(1)"
type is replaced by whatis,
which produces output that can be re-evaluated by the shell
builtin", assuring that nothing else is
called instead (e.g., a function),
also needed for "whatis"
echo test hash pwd ulimit" and their
implications are gone
* matches all files but . and ..
-p": removing function-definitions imported
from environment, setting IFS back to default value
{' and '}' are special
like '(' and ')',
i.e., syntactically equivalent (e.g., leading blank
and terminating delimiter aren't necessary anymore,
redirection may also appear at the left side)
[...]" with '^',
instead of '!', e.g., "[^0-9]"
:' and its side effects, or with
";;" in "case" )
^' is gone
/etc/profile
SHELL and "readonly" are also gone)
<<-" (strip leading tabs in here-documents)
cd" provides an automatic spell checker, for absolute paths only:
automatically take the next best matching directory (undocumented)
f()command>x" works (was: "syntax error").
Note that the redirection always, even with braces, ends
in the body, though. (also in POSIX.2)
type output
for case in a function fixed
MAILCHECK and MAILPATH are gone
(MAIL is kept)
| [10] |
Most modifications for the Version 8 shell were driven by the
motivation for a clean design.
Consequently, the fact that function calls overwrite the positional parameters was not changed. |
exec() fails, and before trying to interprete the file itself,
SunOS 3 checks in advance if the first character is
Cannot exec binary file".
test" knows -h to check for symbolic links
test: too many arguments" added
LC_CTYPE/LC_COLLATE
BIN_SH the shell
forks to a POSIX.2 compliant shell ("xpg4") or an optional SVR4-like
shell ("svr4").
ulimit" doesn't only know about file
size, but is implemented with the 4.2BSD/SVR4-like
getrlimit(2)
[...]"
cat <<`...`" anymore
(and the backquotes have no special meaning)
test" knows -L and -h to check
for symbolic links, and -e to check for existence
argv[0]
is rsh or -rsh
*/" and
".*/" to directories (apart from */.)
cd"
(linked in from libc) instead of only "bad directory"
type returns false on "not found"
whatis output
for case in a function fixed
cd: too many arguments added
umask: Improper mask" error message added
TIMEOUT mechanism activated
| [11] |
The Migration Guide
"
System V Environment for Digital UNIX Version 4.0." (560 kB PDF)
claims, that /bin/sh on OSF1/V4 and /V5 is a SVR3.2 shell.
However, it's missing some characteristic properties of this shell (modern "$@", " getopts", the PATH fix
and "read: missing arguments").
After all, it looks like a SVR2 shell with numerous fixes/backports from later variants. |
LC_CTYPE/LC_COLLATE
LINES and COLUMNS based
on SIGWINCH
[...]"
test" knows -h to check for symbolic links
pwd" knows "-H"
for socalled context dependent files, cdf(4)
argv[0]
is rsh or -rsh.
| [12] |
To try the unicode support on HP-UX with a remote connection, you need
an according font and the ability to insert multi-byte characters.
Try Thomas Dickey's XFree86 Xterm with Markus Kuhn's fonts. Set LC_COLLATE and LC_CTYPE after
looking at "locale -a" and also set "stty -istrip cs8".
|
cd" fails, system error messages are printed
(formerly, the shell only knew "bad directory")
getopts"
PATH
did not
mean "." before (however, it should behave like execvp(2))
[...]"
IFS='\' wrongly doesn't split anymore
(demonstrate with var='x\y';set $var;echo "x:$1 y:$2")
r' somewhere in
argv[0], but only for rsh and -rsh.
read" knows the error message
"missing arguments"
var=x;echo ${var-'$'} results in
"bad substitution"
(probably due to the changed internal quoting mechanism).
The same happens with '"' and '`' as values,
for all but the ":+" and "+" form of
parameter expansion.
/usr/5bin precedes /bin in
PATH, built-ins behave sysv-like
("test": string length with -l;
"echo": escape sequences,
-f checks for regular files instead of non-directories)
exec() fails, and before trying to interprete the file itself,
the shell checks in advance, if the first character
Cannot exec binary file". (like SunOS 3)
test" knows -h to check for symbolic links (like SunOS 3)
test: too many arguments" added (like SunOS 3)
ulimit" built-in 13
$SHELL). restricted functionality
even not documented anymore.
LC_CTYPE/LC_default
./(M-d): permission denied"
(instead of "./ä" - example assumes your browser
supports iso-8859-1)
type
output for case in a function almost fixed
chdir" reactivated (undocumented)
:/usr/ucb:/bin:/usr/bin"
| [13] |
On SunOS 4, the "ulimit" built-in is not implemented at all.
getrlimit(2) lists this under BUGS
(but in fact this origins from 4.2BSD).
File size limits are catched with quotas instead, and apparently Sun
didnt't want to add support by getrlimit(2) otherwise.
|
LC_CTYPE/LC_COLLATE
ulimit" is implemented with the 4.2BSD/SVR4-like
getrlimit(2)
test" knows -L to check for symbolic links
cat <<`...`" anymore
(and the backquotes have no special meaning)
[...]"
IFS='\' splits correctly again
TIMEOUT mechanism activated
${var-'$'} and related parameter expansions bugs
(which were introduced with SVR3)
type returns false on "not found"
migrate" for migrating processes to other "sites".
"setspath" for using different "sites".
"setxvers" for setting an
"experimental version prefix" (in connection with
using "hidden directories").
In contrast to the documentation, "onsite" is not
implemented.
read: missing arguments"
type output
for case in a function fixed
limit" and "unlimit"
as interface to getrlimit(2)
test" knows -l to check for symbolic links
-L" for "cd" and "pwd"
added, toggling between using logical or physical pathnames,
i.e., wether navigation along symbolic links is remembered
cd" provides a spell checker (inherited from Xenix)
test" knows -L and -h to check
for symbolic links
LC_CTYPE/LC_COLLATE
test" knows -H and -M to check
for a semaphore or shared memory, respectively
cat <<`...`" anymore
(and the backquotes have no special meaning instead)
umask -S" knows the symbolic notation.
"Bad umask" error message added.
ulimit" implemented with getrlimit(2)
argv[0]
is rshell or -rshell
DOSPATH for .exe, .cmd
and .bat
SHENV: path of script
executed at invocation of each new shell
-Dname=value: supply environment variables
(for calling from binary executables)
| [14] | DomainOS offers two universes: "bsd4.3" and "sys5.3" each providing an according shell variant. |
bg fg jobs kill stop suspend"
-m" to switch on/off
job control.
ulimit" now implemented with getrlimit(2)
-p"
trap" now accepts symbolic signal names
test" knows -h to check for symbolic links.
: > file") in a for- or while-loop is executed
only the first time
$-) when becoming restricted
by SHELL or argv[0]
env 'A B=1' sh"
("not an identifier").
Such variables are not passed on, though.
chdir" reactivated (probably inherited from SunOS 4
- Sun was involved in SVR4), but except for SunOS 5 not documented
type output
for case in a function fixed
| [15] |
If you run an older shell without job control:
Don't forget about nohup(1).
However, background jobs are not in a new process group,
which has again a strong influence on signal handling.
|
cat <<`...`" anymore
(and the backquotes are evaluated immediately)
case x in in)" doesn't fail anymore with
syntax error
/usr/ucb/
precedes /bin/, /usr/bin/ and
/usr/5bin/ (SunOS4/BSD compatibility):
echo" knows "-n" and disables backslash escape sequences,
test -f" doesn't check for a regular file but for "not a directory".
SYSV3 is present in the environment
(labeled "SCO x86 compatibility support").
type returns false on
"not found"
2>&1 program >/dev/null" doesn't redirect
stderr to /dev/null anymore.
echo a > file1 b > file2"
fixed.
<>" fixed and
documented (used in /etc/inittab f.i.). In fact this syntax was
accepted but incorrectly implemented and undocumented since V7.
Search for IORDW in the source: O_RDWR
was missing.
`( )`
(a subshell in cmd-substitution)
locks up the parent (SIGTTIN) after control returns to the parent
IFS not inherited from environment anymore
--" (end of options) becomes "-"
(undocumented since System III: turn off flags x and v)
pfsh functionality added
(profiles for extended access control management)
/tmp/sh{PID}{num}"), the shell doesn't follow
unresolved symbolic links with the same name anymore
if they already exist, but choses a different name instead.
test" knows "-L" (in addition
to "-h")
pfsh functionality removed)
ulimit" not implemented with getrlimit(2),
but still with "limit" and "unlimit"
test" knows -L and -l
in addition to -h
type returns false on "not found"
${parameter##pattern} expansion, for the
pattern "*/" only. The reason is: /sbin/builtin_exec
reads '${0##*/} "$@"' and there are softlinks pointing
to this file with the name of the POSIX.2 built-ins.
IFS not inherited from environment anymore if running with setuid/gid or as root
-p,
echo -n" (not very significant)
UX:sh", "ERROR:",
"WARNING", etc are
contained in the binary, but not activated
(contrary to the jsh(1) notes).
readt" built-in (timing out)
TIMEOUT mechanism activated
-p" removed,
because privileges are handled differently in DG/UX
UX:sh:" messages and
thus seems to originate from between SVR4.0 and SVR4.2
UX:sh:" messages and
might originate from between SVR4.0 and SVR4.2
I" prints a terse summary about
resource usage
of the current session after each command
J" activate job control (like "m")
E" EOF doesn't exit an interactive shell
B" mimics BSD echo built-in (see below)
T" activates tilde expansion
/usr/ucb/
precedes /bin/, /usr/bin/
in PATH:
echo" knows "-n" and disables backslash escape sequences,
test -f" doesn't check for a regular file but for "not a directory".
type output
for case in a function fixed
/usr/net:/usr/bin:/usr/ucb"
[:lower:]",
including the equivalence and collation symbol,
"[[=c=]]" and "[[.cc.]]"
suspend" sends SIGTSTOP
type output
for case in a function fixed
UX:sh: ERROR: ..."
(years after the first definition in the SVID)
test" knows -L to check for symbolic links
type returns false on "not found"
read" knows the flag "-r"
mldmode" and "priv"
umask -S" knows the
symbolic notation. "Bad umask" error message added.
foo=`echo $bar` bar=text" results in foo being empty:
"order of evaluation for variable assignments is changed to use
left to right expansion rules."
TIMEOUT mechanism activated
(the unit is seconds in contrast to minutes in previous shell versions)
Here is an interview with Steve Bourne (link to the australian Computerworld, '09).
See an article from John Mashey in net.unix-wizards ('86). By the way, the PWB (aka Mashey) shell from the Programmer's Workbench, about "PWB 1.0", is also archived by TUHS (see PDP-11/Distributions/usdl/).
See also an article by David Korn ('94) with an interesting second chapter concerning the Bourne shell history. 16
| [16] | The article mentions that functions were added to the Bourne shell in 1982. In the above interview Bourne tells that this was finished in 1983. The next release, SVR2, was published 1984. |
The Bourne shell would probably be in much wider interactive
use today, if it provided line editing (and a history mechanism).
Having the above article in mind, this was - like with ksh originally -
probably not done in the hope that these features would move into the
terminal driver. Kenneth Almquist even
intentionally released his ash without line
editing and history for this reasons.
See manual pages of two main predecessors of the Bourne shell, the "Thompson" and the PWB shell:
< and >.^ and |.
See Jeffrey A. Neitzel's pages for both an enhanced, backward-compatible port of the Thompson shell and a port of the original source, which compiles on current systems. As excellent illustration, you'll even find some example scripts there. For more details about Version 6, see also a V6 simh tape and an extensive V6 manual collection on Wolfgang Helbig's pages, or the software kit on the SIMH pages.
sbrk() vs. SEGVsbrk(2).
Meanwhile the early Unix variants have become available in source
under a BSD-like license from SCO/Caldera, have a look at
TUHS.
Usually you will not be able to
easily compile earlier Bourne shells on a modern unix variant, because
it is really oldfashioned C code with wild pointer management. You cannot
use libc because the shell internal memory management crashes malloc
which is even used libc-internally. Additionally, the methods for directory
access have changed.
Running a V7 shell:
However, you can run Version 7 in an emulator like SIMH.
There's a also a V7 kit.
See also Hellwig Geisse's
pages about details how to get V7 running.
With this V7 you can bootstrap a complete System III.
And here I was able to even compile the SVR1 and SVR2 shell.
An important advantage of running the complete system is having the related tools available.
But you can even run the V7 shell natively:
Geoff Collyer provides
a source package
of the V7 shell (local copy,
patch to fix a compiling problem)
which should compile on most POSIX systems.
He has updated the memory management and directory-access code with parts
from his V9 shell.
However he has added a few minor modifications, so this
variant is not completely original. The visible differences are:
He has also published
"a partial tour through
the unix shell" (local copy), which is quite helpful
if you want to get busy with the source.
It emphasizes the memory management but also contains general hints.
Nikola Vladov provides
an improved version of the above port.
He made the memory management completely robust, offers alternative versions,
and the shell is ready to be linked with dietlibc.
Additional visible differences to the original version are:
O_APPEND instead of seek()
O_NOFOLLOW
Running a recent Bourne shell:
Thanks to the OpenSolaris project, Gunnar Ritter could publish
a source port of
a current Bourne shell.
This is the first officially available up-to-date Bourne shell
on free unix flavours.
<http://www.in-ulm.de/~mascheck/bourne/>