ARG_MAX
| Shells
| whatshell
| portability
| permissions
| UUOC
| ancient
| -
| ../Various
| HOME
$@
"
| echo/printf
| set -e
| test
| tty defs
| tty chars
| $()
vs )
| IFS
| using siginfo
| nanosleep
| line charset
| locale
2001-10-07 .. 2019-09-16 (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 in 1979, 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 these traditional Bourne shell variants, because they never had been "versioned". This page tries to document their way.
Originally, this page 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
And how to identify the very version? As no version info has been compiled in 3, you have to test for specific features. Running the script whatshell helps to unravel the version. The script is a consequence of this page.
Thanks to the OpenSolaris project, Gunnar Ritter could publish
a source port of
a SVR4 variant of the Bourne shell. This was the first officially
available later Bourne shell on free unix flavours.
Jörg Schilling has also published a
port
of the OpenSolaris variant and he has added numerous extensions.
Some issues are covered in more detail on subpages and linked inline below; here is a list of all these subpages.
Unsolved: Bourne shell before3 the well known 7th edition (~3 years of unreleased development). Better differentiate among SVR3.x and SVR4.2x.
[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 OSF/1 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. |
[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). |
A summary of the most important changes
· Version 7 | (1979) | control structures, cmd substitution, () and {} , arbitrary variable names, trap , eval , special parameter substitutions, case
| ||
· System III | (1981) | # , [!...] , colon parameter substitution, set --
| ||
· SVR1 | (1983) | shift n
| ||
· SVR2 | (1984) | functions, built-ins: unset echo type , redirection for builtins
| ||
· SVR3 | (1986) | modern " ,
8-bit clean,
getopts ,
functions do not modify positional parameters
| ||
· SVR4.0 | (1989) | job control | ||
· SVR4.2 | (1992) | read -r
|
Table of contents
· Version 7 (and 2.9BSD)
and 3BSD and 4.xBSD (and Sinix 5.20 (ucb universe), SunOS 2)
- Ultrix
- Dynix 3.2 (ucb)
- DomainOS 10.3
· System III (and Plexus 1.0)
and SINIX 5.20 (sie)
· SVR1
and Iris 3.7
· SVR2 (and MV/UX 3)
and Ultrix sh5
- Version 8
- SunOS 3
- OSF/1
- HP/UX
- Dynix 3.2 (att)
· SVR3 (and MUNIX V3, SINIX 5.20 (att), SCO Xenix 2.3.4)
and SunOS 4
- AIX
- IRIX 3/4
- SCO Unix
- Interactive Unix
- DG/UX 40
- DomainOS 10.3
- Dynix PTX
· SVR4 (and OSF/1-SysV)
and SunOS 5
- Heirloom
- Schily
- IRIX 5/6
- DG/UX 42
- EP/IX
- Reliant UNIX
· SVR4.2 (UnixWare, OpenUnix)
And now all the very details:
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
chdir
" is an undocumented alias for "cd
" (compatibility to Thompson shell)
break n
" exits script if n is higher than the actual nesting level
continue n
" doesn't work, it behaves like continue 1
(missing code)
[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 very special example is " : `echo output 1>&2` ".
Enclosing the comment in single quotes protects against side effects. |
[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. - One example: ${var?abcde} expands to "var: abcde ",
while ${var?"abcde"} incorrectly expands to "var: áâãäå ".
- Another example: after expanding ${var="$value"} with $value containing spaces,
$var won't contain real spaces, but non-breakable spaces.
This might become relevant with subsequent word splitting. Side note: bash before release 1.13 also made use of the 8th bit for internal quoting. |
/bin/csh
if
the first character of an executable script is '#
'
TIMEOUT
(hardcoded in the source) activated by changing from 0 to 2400 (seconds, that is, 40 minutes)
#
' introduced.
uid=0
or if euid!=uid
set -e
" is disabled while executing an if/while/until
condition
O_APPEND
instead of seek()
[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 sh by Kenneth Almquist
(often called ash ).
|
[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
(hardcoded in the source) deactivated again by changing back 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)
signal()
instead of system version, so that system calls are
not restarted after interruption (06-90)
SVR2
variant) (1992/93)
/etc/profile
(only executed if login shell)
>
and >>
redirections set APPEND
bit on file descriptor,
for usage with dynix parallel make
(see the according section in the release notes)
set
" recognizes "--
" as option
delimiter, for arguments with a leading "-
"
or "+
" (backport from Dynix/PTX, i.e., post-SystemIII
)
PARALLEL
controls the number of executed background jobs
(for usage with parallel make)
(see the according section in the release notes)
ENOEXEC
the magic is inspected,
and a diagnostic message is printed if the binary has been compiled for
a different hardware (i386
vs ns32000
)
csh
upon #
magic) only in ucb
universe
shift
" accepts a number (backport from Dynix/PTX, i.e., post-SVR1
)
break n
" doesn't exit script if n is higher than the actual nesting level
continue n
" works
set -e
" is disabled while executing an if/while/until
condition
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
(always executed, not only for login shells; disctinction possible by leading "-" in $0)
#
'
${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 listed under SYNOPSIS
and accepted by the shell, but no functionality was implemented
and it was not mentioned otherwise.
exit
" allows leaving an interactive shell now
chdir
" deactivated (undocumented)
login
" removed
RES
("research unix"), which deactivates
restricted functionality, umask
, [
alias for test
,
login
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
set -e
" is not passed on to forked child scripts
(because a script called like a command is not execed but forked)
set -e
" has no influence on commands in the same line ("set -e; false
")
read
" is called w/o arguments
ulimit
" is called w/o arguments
return
" built-in)
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")
break n
" doesn't exit script if n is higher than the actual nesting level
continue n
" works
eval 'echo foo>a' >b
" (was: "illegal io")
-afh
"
readonly
without arguments doesn't list the exported
variables anymore
MAILCHECK, MAILPATH
. Bug: Mailcheck must not be empty
hash
built-in introduces an (academic) internal limit
break 0
" in a one-fold loop renders an interactive shell dysfunctional
SHACCT
$FILEMATCH
removed, which had never been active.
If the code were active, the variable would contain the last element
of a line after word splitting at each time (even while splitting).
/bin/sh
)
type
output
for case
in a function fixed
signal()
instead of system version,
so that system calls do not restart after interruption (11-89)
LOGNAME
via getpwuid()
(12-89)
SHACCT
not activated on Ultrix
/bin/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
-D
for debugging as compile time option)
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)
echo
" knows "-n
"
[...]
"
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",
and additionally "cd: too many arguments
"
type
" returns false on "not found
"
type
" doesn't write "...is a function
" anymore
but only the function definition itself
type
" speciality: if both a command and a function exist, "type
" reports both
type
output
for case in a function fixed
umask: Improper mask
" error message added
TIMEOUT
dynamic environment variable mechanism (unit is minutes)
argv[0]
instead of current one)
if opening a file for execution fails, that is,
sh notexist
" print
"sh: notexist: cannot open
" instead of "notexist: notexist: cannot open
"
hash
": error message "bad hash options"
instead of standard "bad option(s)"
PATH
is unset) is
":/usr/bin
" instead of ":/bin:/usr/bin
"
/bin
is a symbolic link to /usr/bin
like on most commercial flavours).
uid 0
has a different built-in path: "/usr/sbin:/usr/bin:/usr/bin:/sbin
",
though /usr/bin appears twice by mistake
login
" reactivated (undocumented), because:
RES
removed
inlib
" and "rmlib
" as built-ins (documented as unsupported)
inlib
" and "rmlib
" not documented anymore (still active)
[11] |
The Migration Guide
"
System V Environment for Digital UNIX Version 4.0." (560 kB PDF)
claims, that /bin/sh on OSF/1 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. All source files contain a copyright from "International Business Machines Corp. 1989" and several fixes are coded like the SVR3 variant on AIX. |
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 multibyte 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".
|
argv[0]
is rsh
or -rsh
SIGTSTP SIGTTIN SIGTTOU
are ignored in interactive mode
(for correctly "interacting with the ucb universe")
'/'
(todo)
(/usr/att)/bin/sh
)
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).
'"'
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)
PATH
is unset) is ":/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
argv[0]
instead of current one)
if opening a file for execution fails, that is,
sh notexist
" print
"sh: notexist: cannot open
" instead of "notexist: notexist: cannot open
"
TIMEOUT
dynamic environment variable mechanism (unit is minutes)
${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
PATH
is unset) is
":/usr/bin
" instead of ":/bin:/usr/bin
"
/bin
is a symbolic link to /usr/bin
like on most commercial flavours).
uid 0
has a different built-in path: "/usr/sbin:/usr/bin:/sbin
"
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.
LINES
and COLUMNS
based on SIGWINCH
SIGSEGV
for internal memory management
to better recognize real SIGSEGV
s. Instead it's checking and
expanding in advance.
ulimit
" implemented with getrlimit(2)
(underlying UnixWare 7 SVR4.2 kernel)
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. |
PARALLEL
controls the number of executed background jobs
(for usage with parallel make)
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.
/usr/ucb/
precedes
/usr/bin/
in PATH
(BSD compatibility):
echo
" knows "-n
" and disables backslash escape sequences,
test -f
" doesn't check for a regular file but for "not a directory".
: > file
") in a for- or while-loop is executed
only the first time (although the colon command is executed each time)
exec > file
")
in a loop works only the first time,
that is, all subsequent output shows up in the first place
$-
) 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
`( )`
(a sub-shell in cmd-substitution)
might lock up the parent (SIGTTIN) after control returns to the parent.
echo `(:)`
[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/
.
SYSV3
is present in the environment
(labeled "SCO x86 compatibility support").
type
returns false on
"not found
"
EOF
aka <ctrl-d>
but also upon "exit
"
getopts
" in connection with a function might have looped
set -e
also affects commands on the same line again
("set -e; false
") (broken since SVR1)
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.).
IORDW
(and O_RDWR
) in the source,
it's missing in service.c
, initio()
.
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}
"),
num
.
test
" knows "-L"
(in addition
to "-h"
)
pfsh
functionality removed)
read
" knows SVR4.2-like "-r
"
TIMEOUT
" environment variable mechanism added (unit is minutes)
0600
umask
" accepts the "-S
" option (symbolic mode strings)
/usr/5bin:/bin:/usr/bin:
"
(for maximum SysV compatibility if the Heirloom toolchest is also installed)
PATH
is unset) is
"/bin:/usr/bin:
" instead of ":/bin:/usr/bin
"
ulimit
" knows the flags "lmu
" for portability
SHACCT
(shell accounting) enabled
/usr/lib/locale
cd
" optionally available at compile time
hash -r
" documented
snprintf()
for "getopt
"
realloc
(no symptoms so far)
<EOF>
" when exiting with EOF
(ctrl-d
)
-version/--version/-V
"alloc"
allows to check the storage for corruption.
/usr/ucb
precedes /usr/bin
in $PATH
"f(){}; type f
" prints "f() {f() { }}"
sbrk()
to malloc()
based on the ideas from Geoff Collyer (see below)
:
" in $PATH
might inhibit path search
": ${NAME=value}"
works again on Linux/Cygwin
"set -m"
and "set -P"
are documented
"umask"
implements the chmod(1)
like symbolic notation to set and print (umask -S
) the umask
var2=val2 var1=val1
) are avaluated from left to right now (SVR4.2MP, POSIX)
"read VAR"
auto-exports VAR
after "set -a"
"ulimit"
implements -l
, -m
, -u
for compatibility with *BSD and Linux
"-version"
is documented
"getopts"
(and its variables), "read"
, "test"
, "history"
command (and the variables it uses)
${var-'$'}
bug
"f(){}; type f"
bug introduced with 2012-03-30/Sun id 6776989
"savehistory"
and "map"
"repeat"
built-in added
"cd"
and "pwd"
set $PWD
pushd/popd/dirs
" built-ins added
times
" produces POSIX compliant output
repeat
" fixed
set -o ...
" and "set +o ...
" and
alias
, unalias
type
" doesn't know about aliases
set -o globalaliases
"
dosh
" added, behaves similar to "sh -c 'command'
" without launching a new shell, supports aliases
-i
" option
/etc/sh.shrc
and $HOME/.shrc
at startup, and implements $ENV
(POSIX)
"for i; do"
and "for i;<newline> do"
(see also the endnote in ${1+"$@"}
and an austin group discussion)
$PATH
(introduced earlier by the sbrk()
to malloc()
conversion)
type
" knows about aliases
sbrk()
to malloc()
conversion)
-o aliasowner=name
" allows for implementing su aliases
argv[0]
sbrk()
to malloc()
conversion,
pfexec
, ulimit options -l -m -u, SVR4.0 colon redirection bugfix, SVR3 ${var-'$'}
bugfix,
times
output, avoid reading directories with the name of a script.
aliasowner
"
$()
command substitution (the only traditional bourne variant doing so)
$(())
arithemtic expansion (the only traditional bourne variant doing so).
break 0
" bug from SVR2 fixed
-o posix
" implements a strict posix mode, as a few features are incomatible (e.g. accepting ^
as |
)
get/setrlimit(2)
,
limit/unlimit
"
with the flag "h
" for hardlimit and the resources
"cputime", "filesize", "datasize", "stacksize", "coredumpsize", "memoryuse" (rss), "descriptors", and "vmemory" (vsz)
ulimit
"
with the flags "HSacdfnstv
" for hard/softlimit, for print all, and for
the resources from above, except "memoryuse"
test
" knows -L
and -l
in addition to -h
type
" returns false on "not found
"
${parameter##pattern}
expansion, for the pattern "*/" only.
/sbin/builtin_exec
reads '${0##*/} "$@"
'
"POSIX shell builtin - cannot execute"
alias
", "unalias
", "builtin_exec
",
"command
" and "fc
".
/sbin
on IRIX).
IFS
not inherited from environment anymore if running with setuid/gid or as root
-p
,
PATH
is unset) is "/usr/sbin:/usr/bsd:/bin:/usr/bin:
"
MAILCHECK
(like default 600s) on start, instead of erroring out
type
" reports "priv
" and "mldmode
" as built-ins.Unknown builtin
".
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
dynamic environment variable mechanism (unit is minutes)
-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
" print 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
" mimic BSD built-in compatibility (from SVR4)
T
" activate tilde expansion
test
" knows -L
to check for symbolic links
/usr/ucb/
precedes /bin/
and /usr/bin/
in PATH
.
kill
" doesn't accept a signal number/name in connection
with a job id ("UX:kill: ERROR: Invalid tid or signal
")
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
"
mldmode
" and "priv
" built-ins
a
": variables set with "read
" are also exported
TIMEOUT
dynamic environment variable mechanism
(the unit is seconds in contrast to minutes in other variants).
The variable is readonly and set site-wide in /etc/default/sh
.
LC_CTYPE
nor LANG
is set,
then CHRCLASS
is inspected (backwards compatibility)
LANG
and LC_MESSAGES
at run time
TFADMIN
(for the "trusted facility management")
`( )`
seems to be gone
read
knows the flag -r
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."
[16] | MP means maintenance pack |
Stephen Bourne's talk (at BSDCan 2015) "Early days of Unix and design of sh" (youtube) with both enlightening and entertaining background about his shell.
See 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. 17
[17] | 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.
Louis Pouzin explains how the concept and name
of a "shell" was introduced in Multics in 1964/65.
He was inspired by Christopher Strachey's macro-generator (and its quoting and passing of arguments).
I don't know how much Bourne borrowed from this but it's an interesting connection to the re-parsing of expanded variables.
See manual pages of two main predecessors of the Bourne shell, the "Thompson" and the PWB shell:
<
and >
.
Some comments
from Norman Wilson (on the TUHS list).
^
and |
.
Dennis Ritchie about this (on his pages)
and on the
TUHS list.
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.
Meanwhile the early Unix variants (research Unix until 7th
ed and 32V) have become available in source under a BSD-like
license
from SCO/Caldera.
Have a look at TUHS,
i.e., the archive mirror site list (for complete distributions),
and the source code web interface (for a quick view at individual files).
For example the 7th edition source web interface is located here: minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh, for System III here, for Ultrix-3.1 here (v7-derived) and here (svr2-derived).
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 also used libc-internally
- additionally, the methods for directory access have changed
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.
You can even run the V7 shell natively, as port:
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
There's also a FreeBSD port of the v7sh,
however it incorporates also fixes from BSDs, Ultrix and System III
Running a recent Bourne shell:
Thanks to the OpenSolaris project, Gunnar Ritter could publish
a source port of
a current Bourne shell as part of his Heirloom Toolchest.
This was the first officially available up-to-date Bourne shell
on free unix flavours.
sbrk()
vs. SEGV
sbrk(2)
.
Some very informative details about the implementation are contained in Geoff Collyer's paper (see above), who rewrote the V7 sh memory management to run on later systems.
<http://www.in-ulm.de/~mascheck/bourne/>