Back: Colon
Forward: Source
 
FastBack: Source
Up: Sh Implementation
FastForward: Environment
Top: Autoconf, Automake, and Libtool
Contents: Table of Contents
Index: Index
About: About this document

22.2.4 ()

There are still a great number of shells that, like Steve Bourne's original implementation, do not have functions! So, strictly speaking, you can't use shell functions in your scripts. Luckily, in this day and age, even though `/bin/sh' itself may not support shell functions, it is not too far from the truth to say that almost every machine will have some shell that does.

Taking this assumption to its logical conclusion, it is a simple matter of writing your script to find a suitable shell, and then feed itself to that shell so that the rest of the script can use functions with impunity:

 
#! /bin/sh

# Zsh is not Bourne compatible without the following:
if test -n "$ZSH_VERSION"; then
  emulate sh
  NULLCMD=:
fi

# Bash is not POSIX compliant without the following:
test -n "$BASH_VERSION" && set -o posix

SHELL="${SHELL-/bin/sh}"
if test x"$1" = x--re-executed; then
  # Functional shell was found.  Remove option and continue
  shift
elif "$SHELL" -c 'foo () { exit 0; }; foo' 2>/dev/null; then
  # The current shell works already!
  :
else
  # Try alternative shells that (sometimes) support functions
  for cmd in sh bash ash bsh ksh zsh sh5; do
    set IFS=:; X="$PATH:/bin:/usr/bin:/usr/afsws/bin:/usr/ucb"; echo $X`
    for dir
      shell="$dir/$cmd"
      if (test -f "$shell" || test -f "$shell.exe") &&
        "$shell" -c 'foo () { exit 0; }; foo 2>/dev/null
      then
        # Re-execute with discovered functional shell
        SHELL="$shell" exec "$shell" "$0" --re-executed ${1+"$@"}
      fi
    done
  done
  echo "Unable to locate a shell interpreter with function support" >&2
  exit 1
fi

foo () {
    echo "$SHELL: ta da!"
}

foo

exit 0

Note that this script finds a shell that supports functions of the following syntax, since the use of the function keyword is much less widely supported:

 
foo () { ... }

A notable exception to the assertion that all machines have a shell that can handle functions is 4.3BSD, which has only a single shell: a shell function deprived Bourne shell. There are two ways you can deal with this:

  1. Ask 4.3BSD users of your script to install a more featureful shell such as bash, so that the technique above will work.

  2. Have your script run itself through sed, chopping itself into pieces, with each function written to it's own script file, and then feed what's left into the original shell. Whenever a function call is encountered, one of the fragments from the original script will be executed in a subshell.

If you decide to split the script with sed, you will need to be careful not to rely on shell variables to communicate between functions, since each `function' will be executed in its own subshell.


This document was generated by Gary V. Vaughan on February, 8 2006 using texi2html