Bourne | Ash | #! | find | 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


The Traditional Bourne Shell Family

History and Development

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.


Content

1. Introduction
2. All the variants
3. Origins of the Bourne shell
4. Source Code
5. Running a Bourne shell
6. sbrk() bs SEGV


1. Introduction

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).


2. All The Variants

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.

  • Seventh Edition (aka Version 7) Unix shell, (1979), manual page
    Nowadays, this shell naturally looks rather old in comparison.
    However, here are differences to the Thompson and the PWB4 shell:
    • real control structures.
      the Thompson shell had none,
      the PWB shell initially had if/switch/while, but called an external goto to move the filepointer. As of mid'76, they were all built in.
    • scripts can be used as part of a pipeline. The Tompson shell always reads commands from STDIN, making this impossible.
    • redirections >& <& and <&- >&- (especially proper handling of stderr)
    • `...` (command substitution)
    • () and {}
    • arbitrary variable names (the PWB shell had variables, but only $a ... $m were available, apart from some more predefined internal variables, like $p for path, e.g.)
    • variables can be exported into the environment (this was new with V7)
    • IFS
    • trap (proper signal handling, onintr in the PWB shell just called goto)
    • case
    • here-documents (later versions of the PWB shell learned this from the Bourne shell)
    • parameter substitutions ${-=?+}
    • eval
    • The Thompson shell had no umask.
      The PWB shell might have added it in a later version.
    • PS2 functionality
    • flags envx

    A quick glance at differences to later variants:

    • no functions yet
    • with old "$@"
    • no "unset" facility, i.e., no way to remove variables from the environment (instead of assigning the empty value)
    • no "[" built-in available (even not as external command on Version 7), but only the external "test"
    • numbersign, '#', is not a comment character yet 5
    • not 8-bit clean, but internally using the 8th bit for the quoting mechanism 6
    • no /etc/profile (i.e., no global profile)
    • doesn't know set -- to separate options from arguments
    • exit status of a pipeline is determined by both first and last command
    • "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)
    ( Version 7, 2.9BSD )

    [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.

    • ... BSD variations of the Version 7 shell
      • 3-BSD ('80)
        • "csh-hack" (2/26/79): noninteractive shell execs /bin/csh if the first character of an executable script is '#'
          (The #! kernel mechanism from the Bell Labs came soon after)
        • TIMEOUT (hardcoded in the source) activated by changing from 0 to 2400 (seconds, that is, 40 minutes)
      • 4.0 BSD (CSRG) (10/'80):
        • /bin/csh is not called with the original arguments (argv[]), but with the scriptname
      • 4.1.snap (CSRG) (04/'81):
        • Comment character '#' introduced.
      • 4.1c1 BSD (CSRG) ('83):
        • Built-in "newgrp" removed.
        • check-in to rcs.
      • 4.2 BSD (09/83) (...and SINIX 5.20 (ucb universe), SunOS 1.x and 2.x)
        • signal fixes (set-/longjmp, SIGINT)
        • check-in to sccs.
      • 4.3 BSD (05/'86) (and thus 2.10 BSD ff):
        • comments only in noninteractive mode
        • does not import IFS if uid=0 or if euid!=uid
      • 4.3 BSD Tahoe (06/'88):
        • bugfix: "set -e" is disabled while executing an if/while/until condition
      • 4.3 BSD Reno ('90):
        • appending is implemented with O_APPEND instead of seek()
      ( 3BSD ('80) until 4.3BSD-Reno ('90) 7, SINIX 5.20 (ucb universe) 8, 2.10BSDff. "backport", SunOS 1.x and 2.x )

      [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.
    • ... Ultrix variant of BSD shells (/bin/sh, see below for /bin/sh5)
      • Ultrix-11 V3.1 ('87) derived from 3BSD
        • "ulimit [-f]" built-in (backported)
        • /etc/profile (global profile, backported, undocumented)
        • comment character '#' introduced
        • TIMEOUT (hardcoded in the source) deactivated again by changing back from 2400 to 0
        • bugfix: "continue n" works (backport from SVR2?)
      • Ultrix-32 V2.0-1 ('86) derived from 4.2BSD
        • short code comments for macros in ctype.h, defs.h, mode.h (04-84)
        • bugfix for trap statements with syntax errors (avoids "longjmp botch" error) (06-85)
        • do not import invalid entries from the environment (but do pass them on) (07-85)
        • bugfix: "continue n" works (backport from SVR2?) (11-85)
        • do not import IFS (05-86)
      • Ultrix V4.2 ('91) apparently a descendant of the Ultrix-32 V2 variant above
        • comments only in non-interactive mode (backport from 4.3BSD)
        • for error messages, if needed, print the correct argv[0] instead of the command name (07-89)
        • bugfix for flag "-e": do not exit upon boolean tests ("if false; then...") (07-89)
        • bugfix for here-documents (avoid premature unlinking of temp files) (09-89)
        • fork checking improved and new error messages (probably backported from System V, that is, System III) (04-90)
        • internal FDs to save stdin and stdout moved from 10 and 11 to directly below OPEN_MAX (06-90)
        • fixes for "wait" (06-90)
        • use own signal() instead of system version, so that system calls are not restarted after interruption (06-90)
        • bugfix about checking for traps when exiting (06-90)
      • Ultrix V4.3 ('92)
        • fix: try to detect running out of memory before SEGV triggers (01-92)

    • ... Dynix "ucb" variant based on 4.2 BSD (see below for the "att" 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)
      • environment variable PARALLEL controls the number of executed background jobs (for usage with parallel make) (see the according section in the release notes)
      • upon ENOEXEC the magic is inspected, and a diagnostic message is printed if the binary has been compiled for a different hardware (i386 vs ns32000)
      • use "csh-hack" (exec csh upon # magic) only in ucb universe
      • "shift" accepts a number (backport from Dynix/PTX, i.e., post-SVR1)
      • bugfix: "break n" doesn't exit script if n is higher than the actual nesting level
      • bugfix: "continue n" works
      • bugfix: "set -e" is disabled while executing an if/while/until condition
      ( Dynix 3.2.0 /.bin/sh )

    • ... DomainOS variant based on 4.3 BSD
      • environment variable SHENV: path of script executed at invocation of each new shell
      • system specific built-ins ver (handle universes) rootnode (managing the distributed aegis base) and inlib (attach a library, for then-called programs)
      • option -Dname=value: supply environment variables (for calling from binary executables)
      • default PATH is ":/bin:/usr/bin:/usr/ucb:/usr/apollo/bin"
      ( DomainOS SR 10.3/10.4 9 )

      [9] DomainOS offers two universes: "bsd4.3" and "sys5.3" each providing an according shell variant.


  • System III shell (1981), manual page
    • /etc/profile (always executed, not only for login shells; disctinction possible by leading "-" in 0ドル)
    • comment character '#'
    • test for NULL, i.e., the empty value (in contrast to unset) with "colon" in parameter expansion, e.g., "${parameter:=word}"
    • negation in "[...]" , 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
    • ...thus the flag "-" (turn off flags x and v) is not needed anymore but (probably accidentally) remains active without being documented anymore.
      Instead, it's often abused for terminating options from now on.
    • built-in "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)
    • here-document with trailing dash "<<-" strips leading tabs
    • bugfix: "if false ;then :;fi;echo $?" formerly wrongly yielded the exit status of false (essential fix for the "-e" flag)
    • bugfix: "continue n" works (you couldn't jump to outer loops before)
    • bugfix: "echo */" resulted in a SEGV if there were filenames with metacharacters
    • exit status of a pipeline is still determined by first and last command, but now the first has precedence.
    • fork checking improved, new error messages "cannot fork: too many processes" and "...: no swap space".
    • "restricted" functionality (and flag "-r") added. The environment variable SHELL is inspected at start-up.
      In V7, the flag "-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)
    • bugfix: superfluous ';' (and '; ;' etc.) are not accepted anymore
    • "login" removed
    • compile time macro RES ("research unix"), which deactivates restricted functionality, umask, [ alias for test,
      and includes login
    ( System III, PLEXUS 1.0 )

    • ... SINIX variant based on System III (sie universe),
      • "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.)
      • error messages compiled in the system wide language ("sysname -l").
      • "chdir" not deactivated
      ( SINIX 5.20 (sie universe) [6] )


  • SVR1 shell (1983), manual page
    • new built-in "ulimit" (show file size limit)
    • "shift" accepts a number
    • "cd" knows CDPATH
    • "test" knows -p to check for named pipe
    • the value for SIGFAIL changed from 03 to 02000 (decimal 208)
    • when exiting upon the regular check if an untrapped signal has been caught, use the last internally safed status if available, instead of always SIGFAIL
    • bugfix: "set -e" is not passed on to forked child scripts (because a script called like a command is not execed but forked)
    • bug: "set -e" has no influence on commands in the same line ("set -e; false")
    • bugfix for problem deleting here-documents (todo: how to provoke?)
    • bugfix about checking for traps when exiting
    ( SVR1 )
    • ... IRIS GL2 variant based on SVR1
      • bugfix: avoid dereferencing a null pointer if "read" is called w/o arguments
      • bugfix: avoid dereferencing a null pointer if "ulimit" is called w/o arguments
      • restricted shell functionality disabled
      • login built-in activated (usually available by compiling a research version)
      ( SGI IRIS GL-2 3.7 aka IRIX 0.7)


  • SVR2 shell (1984),
    • shell functions (and "return" built-in)
    • ... positional parameters are not local (yet)
    • new built-ins: "type unset hash echo pwd"
    • input/output redirection also for built-ins, e.g., "set | pg" or "read variable < file"
    • exit status of a pipeline is determined by the last command (formerly determined by both the first and the last command)
    • bugfix: when expanding "$@" (or ${1+"$@"}), empty arguments are not discarded anymore (not to confuse with the later, modern "$@")
    • bugfix: here-documents now work in connection with asynchronous commands (i.e., using & or ``)
      reproduce with, e.g., "cat<<EOF& ..." or "a=`cat<<EOF ...`" (was: "/tmp/sh12345: cannot open")
    • ... bug: there's a race condition remaining:
      if the here-document is piped into another command (all still part of the command substitution),
      then the command might start before the temporary file containing the here-document is created.
    • bugfix: "break n" doesn't exit script if n is higher than the actual nesting level
    • bugfix: "continue n" works
    • bugfix: the same file descriptor now can be redirected again, e.g., "eval 'echo foo>a'>b" (was: "illegal io")
    • bugfix: command substitution works if stdout is closed
    • new flags: "-afh"
    • bugfix: readonly without arguments doesn't list the exported variables anymore
    • new environment variables MAILCHECK, MAILPATH. Bug: Mailcheck must not be empty
    • bug: the hash built-in introduces an (academic) internal limit
    • cornercase bug: "break 0" in a one-fold loop renders an interactive shell dysfunctional
    • background jobs are spawned with a nice value of 4 (undocumented and often deactivated in the makefile in later releases)
    • accounting and environment variable SHACCT
    • code for $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).
    • source code de-ALGOL68ized, and original (unused) "VERSION sys137 DATE 1978 Nov 6 14:29:22" disappeared
    ( MV/UX 3.01 )

    • ... Ultrix sh5 variant based on SVR2, manual page (see above for BSD variant /bin/sh )
      • until Ultrix-32 V2.0-1: directory access code to modern interface updated (formerly with 14 character limit)
      • until Ultrix 4.2: type output for case in a function fixed
      • several fixes about potential dereferencing of null pointers (11-88)
      • changes concerning wide character support (03-88)
      • avoid dereferencing a null pointer if "ulimit" is called w/o arguments (05-89)
      • commands with temporary asignments are not handled for hash to avoid some bug (08-89)
      • use own signal() instead of system version, so that system calls do not restart after interruption (11-89)
      • for error messages, if needed, print the correct argv[0] instead of the command name (07-89)
      • sets environment variable LOGNAME via getpwuid() (12-89)
      • Ultrix 4.3(/A): fix about setting LOGNAME (early enough so that user can overwrite it) (05-92)
      • SHACCT not activated on Ultrix
      ( Ultrix /bin/sh5 )

    • ... "8th Edition Research Unix" variant 10 based on SVR2, aka Version 8 shell (1984)
      • environment variable 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
      • new built-in "builtin", assuring that nothing else is called instead (e.g., a function), also needed for "whatis"
      • functions can be exported (in the same ways like variables)
      • built-ins "echo test hash pwd ulimit" and their implications are gone
      • modern "$@"
      • * matches all files but . and ..
      • new flag "-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)
      • negation in "[...]" with '^', instead of '!', e.g., "[^0-9]"
      • unnecessary semicolons are ignored (not to confuse with the null-command ':' and its side effects, or with ";;" in "case" )
      • alternative pipeline character '^' is gone
      • no /etc/profile
      • no "restricted functionality" (thus SHELL and "readonly" are also gone)
      • no "<<-" (strip leading tabs in here-documents)
      • "cd" provides an automatic spell checker, for absolute paths only: automatically take the next best matching directory (undocumented)
      • bugfix: "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)
      ( Version 8 )

      [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.

    • ... SunOS 3 variant based on SVR2,
      • after an exec() fails, and before trying to interprete the file itself, SunOS 3 checks in advance if the first character is
        printable or a newline/tabulator/formfeed
        . Otherwise it prints "Cannot exec binary file".
      • "test" knows -h to check for symbolic links
      • "test: too many arguments" added
      ( SunOS 3 )

    • ... OSF/1 variant based on SVR2 11,
      • 8-bit clean and national language support; evaluation of range expressions and character classes (e.g. [:lower:]) according to LC_CTYPE/LC_COLLATE
        (and flag -D for debugging as compile time option)
      • depending on the environment variable BIN_SH the shell forks to a POSIX.2 compliant shell ("xpg4") or an optional SVR4-like shell ("svr4").
      • (backported from SVR3?) "fix": calling a function doesn't overwrite the positional parameters anymore. The documentation still describes the old behaviour, though.
      • (backported from SVR4?) "ulimit" doesn't only know about file size, but is implemented with the 4.2BSD/SVR4-like getrlimit(2)
      • "echo" knows "-n"
      • parameter substitution inside here-document inside command substitution fixed
      • (backported from SVR3?) modern variant of bracket expression "[...]"
      • bugfix: shell doesn't crash on "cat <<`...`" anymore (and the backquotes have no special meaning)
      • (backported from SVR4?) the shell doesn't refuse to start with invalid environment variables
      • "test" knows -L and -h to check for symbolic links, and -e to check for existence
      • (backported from SVR3?) bugfix: The shell only becomes restricted if argv[0] is rsh or -rsh
      • probably the only Bourne shell expanding "*/" and ".*/" to directories (apart from */.)
      • more detailed error messages for "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)
      • fix: improve error message (use original argv[0] instead of current one) if opening a file for execution fails, that is,
        for a call "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)"
      • built-in default path (if PATH is unset) is ":/usr/bin" instead of ":/bin:/usr/bin"
        (as /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
      • temp files are names shxxx instead of sh-xxx
      • "login" reactivated (undocumented), because:
      • compile time macro RES removed
      • system wide functions "inlib" and "rmlib" as built-ins (documented as unsupported)
      • OSF/1 V4: "inlib" and "rmlib" not documented anymore (still active)
      ( OSF/1 V1,V4,V5 aka Digital UNIX aka Tru64 )

      [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.

    • ... HP-UX variant based on SVR2, at least from HP-UX 8 on:
      • 8-bit clean; evaluation of range expressions and character classes (e.g. [:lower:]) according to LC_CTYPE/LC_COLLATE
      • ...and support for multibyte locales 12.
      • shell tracks LINES and COLUMNS based on SIGWINCH
      • (backported from SVR3?) modern variant of bracket expression "[...]"
      • parameter substitution inside here-document inside command substitution fixed
      • "test" knows -h to check for symbolic links
      • HP-UX 8 and 9: "pwd" knows "-H" for socalled context dependent files, cdf(4)
      • you can't trap SIGCHLD (used internally)
      • "bugfix": (not consequently) file descriptor 59 is used instead of file descriptor 19 for internal purposes.
      • (backported from SVR3?) bugfix: The shell only becomes restricted if argv[0] is rsh or -rsh.
      ( HP-UX (at least)8 - 11i Version 1.5 (aka 11.20), where the Bourne shell was withdrawn )

      [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".

    • ... Dynix "att" variant based on SVR2(.2) (see above for the "ucb" BSD variant) (1992/93)
      • bugfix: The shell only becomes restricted if argv[0] is rsh or -rsh
      • SIGTSTP SIGTTIN SIGTTOU are ignored in interactive mode (for correctly "interacting with the ucb universe")
      • fix in argument list generation concerning '/' (todo)
      ( Dynix 3.2.0 (/usr/att)/bin/sh )


  • SVR3 shell (1986),
    • modern "$@"
    • 8-bit clean, that is, not using the 8th bit for quoting anymore
    • "fix": calling a function doesn't overwrite the positional parameters anymore (implicitly documented)
    • if "cd" fails, system error messages are printed (formerly, the shell only knew "bad directory")
    • new built-in "getopts"
    • bugfix: a trailing colon in PATH did not mean "." before (however, it should behave like execvp(2))
    • modern variant of bracket expression "[...]"
    • IFS='\' wrongly doesn't split anymore (demonstrate with var='x\y';set $var;echo "x:1ドル y:2ドル")
    • bugfix: the shell doesn't become restricted with 'r' somewhere in argv[0], but only for rsh and -rsh.
    • "read" knows the error message "missing arguments"
    • bug: 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.
    ( SCO Xenix 2.3.4, SINIX 5.20 (att universe) [6], MUNIX V3 )

    • ... SunOS 4 variant based on SVR3 (SunOS 4.0.x: SVR3.x?, SunOS 4.1.x: SVR3.1),
      • if /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)
      • after an exec() fails, and before trying to interprete the file itself, the shell checks in advance, if the first character
        is printable or a newline/tabulator/formfeed
        . Otherwise it prints "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)
      • no "ulimit" built-in 13
      • the shell cannot become restricted by argv[0] anymore (but only by flag or $SHELL). restricted functionality even not documented anymore.
      • (backported from SVR4?) the shell doesn't refuse to start with invalid environment variables.
      • SunOS 4.1.x: character classification via LC_CTYPE/LC_default
      • SunOS 4.1.x: 8bit characters in diagnostics are written in a meta notation, if they're considered unprintable according to LC_CTYPE;
        for example "./(M-d): permission denied" (instead of "./ä" - example assumes your browser supports iso-8859-1)
      • SunOS 4.1.x: type output for case in a function almost fixed
      • SunOS 4.1.x: "chdir" reactivated (undocumented)
      • built-in default path (if PATH is unset) is ":/usr/ucb:/bin:/usr/bin"
      ( SunOS 4 )

      [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.

    • ... AIX variant based on SVR3,
      • (at least from AIX 3.2 on) evaluation of range expressions and character classes (e.g. [:lower:]) according to LC_CTYPE/LC_COLLATE
      • (at least from AIX 3.2 on) (backported from SVR4?) "ulimit" is implemented with the 4.2BSD/SVR4-like getrlimit(2)
      • "test" knows -L to check for symbolic links
      • bugfix (at least from AIX 3.2 on): shell doesn't crash on "cat <<`...`" anymore (and the backquotes have no special meaning)
      • parameter substitution inside here-document inside command substitution fixed
      • mixed variant of bracket expression "[...]"
      • bugfix: IFS='\' splits correctly again
      • behaviour about trailing colon in PATH not fixed
      • multibyte-aware version in /usr/mbin
      • fix: improve error message (use original argv[0] instead of current one) if opening a file for execution fails, that is,
        for a call "sh notexist" print "sh: notexist: cannot open" instead of "notexist: notexist: cannot open"
      • (at least from AIX 3.2 on) TIMEOUT dynamic environment variable mechanism (unit is minutes)
      • bugfix: ${var-'$'} and related parameter expansions bugs (which were introduced with SVR3)
      • type returns false on "not found"
      • AIX 1.3 (but not anymore at least from 3.2 on): "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.
      • AIX 1.2 ff.: the only SVR3 variant that lacks "read: missing arguments"
      • type output for case in a function fixed
      • built-in default path (if PATH is unset) is ":/usr/bin" instead of ":/bin:/usr/bin"
        (as /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"
      ( AIX 1.2 ff. )

    • ... IRIX variant based on SVR3,
      • additional built-ins "limit" and "unlimit" as interface to getrlimit(2)
      • "test" knows -l to check for symbolic links
      ( IRIX 3.3, 4.0.1 )

    • ... SCO Unix / OpenServer variant based on SVR3,
      SCO Unix 3.2x, about '92:
      • flag "-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)
      • possible setting of EUID/EGID to the RUID/RGID disabled
      SCO Unix 3.2v4.2 / Open Desktop 3.0, '93:
      • bugfix: Bourne shells use file descriptor 19 for internal purposes without error checking.
        Now the highest fd is taken instead (if available) or the error message "cannot open any more files" is printed.
      • "test" knows -L and -h to check for symbolic links
      • evaluation of range expressions and character classes (e.g. [:lower:]) according to LC_CTYPE/LC_COLLATE
      OpenServer 5.0.0, '95:
      • "test" knows -H and -M to check for a semaphore or shared memory, respectively
      • bugfix: shell doesn't crash on "cat <<`...`" anymore (and the backquotes have no special meaning instead)
      • "umask -S" knows the symbolic notation. "Bad umask" error message added.
      OpenServer 5.0.5, '98:
      • shell tracks LINES and COLUMNS based on SIGWINCH
      OpenServer 5.0.7, early '03:
      • shell tries to avoid SIGSEGV for internal memory management to better recognize real SIGSEGVs. Instead it's checking and expanding in advance.
      OpenServer 6.0.0
      • "ulimit" implemented with getrlimit(2) (underlying UnixWare 7 SVR4.2 kernel)
      • The shell also becomes restricted if argv[0] is rshell or -rshell
      ( SCO Unix 3.2, Open Desktop 3, OpenServer 3, 5, 6 )

    • ... Interactive Unix variant based on SVR3,
      • searches DOSPATH for .exe, .cmd and .bat
      ( Interactive Unix 4.0 )

    • ... DG/UX 4.0 variant based on SVR3 (probably a DG/UX 3.9 shell),
      • provides command line editing & history, called EDITREAD
      ( DG/UX 4.0 )

    • ... DomainOS variant based on SVR3,
      • environment variable SHENV: path of script executed at invocation of each new shell
      • system specific built-ins ver (handle universes) rootnode (managing the distributed aegis base) and inlib (attach a library, for then-called programs).
        These built-ins are undocumented in the SVR3 universe; the links show the BSD manpages.
      • option -Dname=value: supply environment variables (for calling from binary executables)
      • default PATH is ":/bin:/usr/bin:/usr/apollo/bin"
      ( DomainOS SR 10.3/10.4 14 )

      [14] DomainOS offers two universes: "bsd4.3" and "sys5.3" each providing an according shell variant.

    • ... Dynix PTX variant based on SVR3 (1990..93),
      • localized messages
      • multibyte support
      • environment variable PARALLEL controls the number of executed background jobs (for usage with parallel make)
      • octal sequences for unprintable characters in diagnostic messages
      ( Dynix PTX 1.2.0 )


  • SVR4 shell (1989),
    • job control 15 and the according built-ins "bg fg jobs kill stop suspend"
    • undocumented flag "-m" to switch on/off job control.
    • "ulimit" now implemented with getrlimit(2)
    • new flag "-p"
      If this flag is present, system and global profile are not run (undocumented).
      If this flag is not present and the effective uid is smaller than 100 and different from the real uid, then the euid is reset to the ruid; similarly for the e/rgid (undocumented).
    • "trap" now accepts symbolic signal names
    • "test" knows -h to check for symbolic links.
    • mimics BSD built-ins if /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".
    • bug: redirection after the colon command (": > file") in a for- or while-loop is executed only the first time (although the colon command is executed each time)
    • bug: redirection with exec ("exec > file") in a loop works only the first time, that is, all subsequent output shows up in the first place
    • bugfix: the shell now also adds 'r' to its flags (i.e., to $-) when becoming restricted by SHELL or argv[0]
    • the shell doesn't refuse to start with invalid environment variables, e.g., for "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
    • running a built-in as last command in `( )` (a sub-shell in cmd-substitution) might lock up the parent (SIGTTIN) after control returns to the parent.
      Force this by running the shell under control of a syscall tracer and type echo `(:)`
    • due to job control, signals are checked after <newline> has been received. Before that they were only checked when a command (at least the null-command) got executed.
    • catches SIGSTOP if running as login shell (pid, pgid, sid are the same)
    • SVR4.0 v2.1: exec redirection bug is fixed, but not the colon redirection bug. (OSF/1 hasn't fixed this yet.)
    ( AT&T SVR4, OSF/1: optional "System V Environment" )

    [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.

    • ... SunOS 5 variant based on a later SVR4.0,
      • SunOS 5.1: fixed: exec redirection bug (but not the colon redirection bug)
      • SunOS 5.1: bugfix: shell doesn't crash on "cat <<`...`" anymore (and the backquotes are evaluated immediately)
      • SunOS 5.1: bugfix: "case x in in)" doesn't fail anymore with syntax error
      • SunOS 5.1: BSD builtin compatibility (from SVR4) triggered, if /usr/ucb/ precedes /bin/, /usr/bin/ and /usr/5bin/.
        On "Solaris x86" this is also triggered if SYSV3 is present in the environment (labeled "SCO x86 compatibility support").
      • SunOS 5.1: type returns false on "not found"
      • SunOS 5.1: when trying to exit while there are stopped jobs, the shell warns once not only upon EOF aka <ctrl-d> but also upon "exit"
      • SunOS 5.3: bugfix "getopts" in connection with a function might have looped
      • SunOS 5.5: bugfix: set -e also affects commands on the same line again ("set -e; false") (broken since SVR1)
      • SunOS 5.5: bugfix for a race condition about command substitution containing a here-document being piped into a command (and the command being started too early)
      • SunOS 5.5.1: bugfix: trap handler with another process in the foreground (and this process receiving the signal) is not run anymore until the foreground process has finished
      • SunOS 5.6: bugfix: "2>&1 program >/dev/null" doesn't redirect stderr to /dev/null anymore.
      • SunOS 5.6: redirection "echo a> file1 b> file2" fixed.
      • SunOS 5.6: redirection "<>" fixed and documented (used in /etc/inittab f.i.).
        In fact this syntax was accepted but incorrectly implemented and undocumented since 7th edition:
        Search for IORDW (and O_RDWR) in the source, it's missing in service.c, initio().
      • SunOS 5.7: IFS not inherited from environment anymore
      • SunOS 5.7: bugfix: loops are not running forever with flag "n" anymore
      • SunOS 5.7: manpage bug: "--" (end of options) becomes "-" (undocumented since System III: turn off flags x and v)
      • SunOS 5.8: pfsh functionality added (profiles for extended access control management)
      • SunOS 5.9: bugfix: When creating temporary files for here-documents ("/tmp/sh{PID}{num}"),
        the shell checks if the file already exists (avoiding to follow unresolved symbolic links) and choses a different name instead, incrementing num.
      • SunOS 5.9: "test" knows "-L" (in addition to "-h")
      • SunOS 5.10: only do locale processing if /usr/lib/locale exists (that is, if /usr is mounted)
      ( SunOS 5 )

      • ... Heirloom variant based on OpenSolaris (2005年06月08日, ~SunOS 5.10),
        • 050614: initial release (with pfsh functionality removed)
        • 050615:
          • "read" knows SVR4.2-like "-r"
          • SVR4.2-like dynamic "TIMEOUT" environment variable mechanism added (unit is minutes)
          • temporary files for here-documents are now created with mode 0600
          • "umask" accepts the "-S" option (symbolic mode strings)
          • built-in default path is "/usr/5bin:/bin:/usr/bin:" (for maximum SysV compatibility if the Heirloom toolchest is also installed)
        • 050616: built-in default path (if PATH is unset) is "/bin:/usr/bin:" instead of ":/bin:/usr/bin"
        • 050617: code converted to ANSI C
        • 050621: "ulimit" knows the flags "lmu" for portability
        • 050621: SHACCT (shell accounting) enabled
        • 050702: locale processing not dependent on presence of /usr/lib/locale
        • 050706: spell checking for "cd" optionally available at compile time
        • 050712: "hash -r" documented
        • 050801: smaller binary by avoiding snprintf() for "getopt"
        • 050818: fix in memory allocation realloc (no symptoms so far)
        • 060824: compiling fixes
        • 070317: compiling fixes
        • 090118: compiling fixes

      • ... Schily variant (on Sourceforge), (freshcode site), and the Schillix OS distribution based on OpenSolaris, manual page
        • 2008年02月01日: Schillix 0.6.1 (OpenSolaris variant, Nevada Build 81 2008/01) with history and filename completion
        • 2008年03月28日: initial portable Schily release
        • 2008年03月28日: prints "<EOF>" when exiting with EOF (ctrl-d)
        • 2008年07月14日: flag "-P" to toggle pfsh functionality
        • 2008年08月14日: fix for child handling bug (zombies), introduced 2008-02
        • 2009年06月10日: history editor supports multi byte locales
        • 2009年09月20日: Sun's man page has become open source and was added
        • 2012年03月30日:
          • prints a version string with -version/--version/-V
          • built-in "alloc" allows to check the storage for corruption.
          • fix: remote session shell process not terminating if terminal window is closed
          • fix: echo built-in misinterpreted arguments beginning with -n if /usr/ucb precedes /usr/bin in $PATH
          • fix: Sun id 6776989 Custom backup script core dumping in Bourne shell, this in turn introduces a bug so that "f(){}; type f" prints "f() {f() { }}"
          • enhancements of OpenSolaris sh (ONNV Build 144) incoroporated
        • 2012年04月05日: memory management has been converted from sbrk() to malloc() based on the ideas from Geoff Collyer (see below)
        • 2012年04月05日: bug introduced: a trailing ":" in $PATH might inhibit path search
        • 2012年04月12日: ...and a fix so that ": ${NAME=value}" works again on Linux/Cygwin
        • 2012年04月12日: "set -m" and "set -P" are documented
        • 2012年04月19日:
          • "umask" implements the chmod(1) like symbolic notation to set and print (umask -S) the umask
          • SVR4.2/POSIX read -r implemented
          • variable assignments (e.g. var2=val2 var1=val1) are avaluated from left to right now (SVR4.2MP, POSIX)
          • fix: "read VAR" auto-exports VAR after "set -a"
          • "ulimit" implements -l, -m, -u for compatibility with *BSD and Linux
          • fix: SVR4.0 colon redirection bug
          • option "-version" is documented
          • man page documents "getopts" (and its variables), "read", "test", "history" command (and the variables it uses)
        • 2012年05月06日:
          • fix: SVR3 ${var-'$'} bug
          • fix: "f(){}; type f" bug introduced with 2012年03月30日/Sun id 6776989
          • command history editor implements "savehistory" and "map"
          • "repeat" built-in added
          • "cd" and "pwd" set $PWD
        • 2012年05月16日:
          • "pushd/popd/dirs" built-ins added
          • "times" produces POSIX compliant output
          • memory leak for "repeat" fixed
        • 2012年06月10日:
          • implements POSIX options "set -o ..." and "set +o ..." and
          • POSIX aliases implemented, and the commands alias, unalias
          • bug: "type" doesn't know about aliases
          • alias support is enhanced, which includes "set -o globalaliases"
          • built-in "dosh" added, behaves similar to "sh -c 'command'" without launching a new shell, supports aliases
          • interactive shell automatically set "-i" option
          • fix: shell doesn't try to read directory when a directory name is given where a script name is expected
          • interactive shell reads /etc/sh.shrc and $HOME/.shrc at startup, and implements $ENV (POSIX)
        • 2012年12月11日: implements "for i; do" and "for i;<newline> do" (see also the endnote in ${1+"$@"} and an austin group discussion)
        • 2013年01月15日: fix for trailing colon bug in $PATH (introduced earlier by the sbrk() to malloc() conversion)
        • 2013年07月08日: fix: "type" knows about aliases
        • 2013年07月08日: fixes in the job management code (introduced earlier by the sbrk() to malloc() conversion)
        • 2013年07月29日: option "-o aliasowner=name" allows for implementing su aliases
        • 2013年10月10日: ...and some fixes for this option
        • 2013年10月10日: the shell recognizes its special variants also by argv[0]
        • 2014年04月22日:
          • distribution allows for compiling a shell variant without Schily specific features, but including the sbrk() to malloc() conversion,
            and the following features: version option, pfexec, ulimit options -l -m -u, SVR4.0 colon redirection bugfix, SVR3 ${var-'$'} bugfix,
            type bugfix about functions with case, times output, avoid reading directories with the name of a script.
          • fix for the shell option "aliasowner"
          • fix: interactive state disabled while reading startup files
        • 2016年02月02日: implements $() command substitution (the only traditional bourne variant doing so)
        • 2016年05月24日: implements $(()) arithemtic expansion (the only traditional bourne variant doing so).
          With this change the shell aims at being POSIX conformant.
        • 2016年06月20日: "break 0" bug from SVR2 fixed
        • 2016年08月08日: option "-o posix" implements a strict posix mode, as a few features are incomatible (e.g. accepting ^ as |)
        • 2021年10月21日: R.I.P. Joerg Schilling

    • ... Irix 5/6 variant based on SVR4.x,
      • provides several built-ins for resource limits, both implemented with 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"
      • provides ${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.
      • knows error message "POSIX shell builtin - cannot execute"
        for the commands "alias", "unalias", "builtin_exec", "command" and "fc".
        These are POSIX shell built-ins, but have to be available also as external commands (in /sbin on IRIX).
        These commands are not built into the Bourne shell and otherwise the external commands wrongly would be called.
      • IFS not inherited from environment anymore if running with setuid/gid or as root
      • a euid smaller than 100 is not reset back to the uid, if called without flag -p,
        with the reasoning, that 100 is arbitrary and an attacker could set the uid to the euid in advance
      • fixed: exec redirection bug (but not the colon redirection bug)
      • built-in default path (if PATH is unset) is "/usr/sbin:/usr/bsd:/bin:/usr/bin:"
      • doesn't implement BSD built-in compatibility mode (from SVR4)
      • fix: handle empty MAILCHECK (like default 600s) on start, instead of erroring out
      • apparently this variant is derived from between SVR4 and SVR4.2:
        • "type" reports "priv" and "mldmode" as built-ins.
          But in fact they are not implemented and you get the error "Unknown builtin".
        • the SVID strings "UX:sh", "ERROR:", "WARNING", etc are contained in the binary, but not activated (contrary to the jsh(1) notes).
      ( IRIX 5 and 6 )

    • ... DG/UX variant based on SVR4.x,
      • provides command line editing & history, called EDITREAD
      • "readt" built-in (timing out)
      • TIMEOUT dynamic environment variable mechanism (unit is minutes)
      • flag "-p" removed, because privileges are handled differently in DG/UX
      • knows about the SVID "UX:sh:" messages and thus seems to originate from between SVR4.0 and SVR4.2
      ( DG/UX 4.2 )

    • ... EP/IX variant based on SVR4.x,
      • knows about the SVID "UX:sh:" messages and might originate from between SVR4.0 and SVR4.2
      • ...also, it has the SVR4 colon-redirection-in-loop bug fixed
      • additional flags (only documented in the printed manual):
        • "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
      • BSD built-in compatibility (from SVR4) is triggered if /usr/ucb/ precedes /bin/ and /usr/bin/ in PATH.
      • bug: "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
      • default PATH is "/usr/net:/usr/bin:/usr/ucb"
      ( EP/IX 2.2.1AA )

    • ... Reliant UNIX variant based on SVR4.x,
      • provides character classes like "[:lower:]", including the equivalence and collation symbol, "[[=c=]]" and "[[.cc.]]"
      • builtin "suspend" sends SIGTSTOP
      • manual page considerably enhanced
      • type output for case in a function fixed
      • bugfix: shell doesn't crash on "cat <<`...`" anymore (at least>> 5.42)
      ( Reliant UNIX 4.32, 5.42 )


  • SVR4.2 shell (1992),
    • with the SVID error message "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
    • bugfix: colon redirection bug (from SVR4.0)
    • bugfix for flag "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.
    • job control is switched off permanently in sub-shells
    • localized messages
    • multibyte support
    • if neither LC_CTYPE nor LANG is set, then CHRCLASS is inspected (backwards compatibility)
    • tracks LANG and LC_MESSAGES at run time
    • handles the environment variable TFADMIN (for the "trusted facility management")
    • the problem from SVR4.0 about running a built-in as last command in `( )` seems to be gone
    • SVR4.2MP216/UnixWare 2?: read knows the flag -r
    • SVR4.2MP2 /UnixWare 2?: "umask -S" knows the symbolic notation. "Bad umask" error message added.
    • SVR4.2MP2 /UnixWare 2?: "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."
    ( UnixWare 1 '92, UnixWare 2 '95/'96, UnixWare 7, OpenUnix 8)
    [16] MP means maintenance pack


3. Origins of the Bourne shell

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.

Predecessors

See manual pages of two main predecessors of the Bourne shell, the "Thompson" and the PWB shell:

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.

4. Source Code

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

5. Running a Bourne shell

However, there are some other methods to get a running shell
  • 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:

    • pattern matching like in 9th edition: * matches all files but . and ..
    • "set -a" added
    • comments with #
    • doesn't complain about functions in the environment
    • renounces set-id privileges at startup
    • doesn't inherit IFS

    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:

    • appending is implemented with O_APPEND instead of seek()
    • temporary files are created with 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.

  • Jörg Schilling published his schily tool box (Sourceforge, Freshcode) which among various other tools also contains an extended Bourne shell port based on the OpenSolaris variant.

6. sbrk() vs. SEGV

I collected some enlightening notes from the usenet about the famous memory management implemented by means of trapping SIGSEGV and calling 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/>

Sven Mascheck <mascheck@in-ulm.de>

AltStyle によって変換されたページ (->オリジナル) /