NB: The following information is known to be accurate as of revision 851.

Start Template

All programs in ~isg/bin should really be symlinks to ~isg/bin/symlink_template/start_template. This utility is designed to attempt to work in any hostile user environment long enough to exec ISGScriptSetup. It runs in /bin/bash to avoid dependencies on Xhierisms (/xhbin/bash) or the user environment to determine the location of bash. This carries a cost; the version of bash on Solaris is 2, which means this has to work in a very old version.

Because of the distrust of the environment, this command takes actions that may be difficult to read; they are broken down here.

Determining the next executable

Because every entry point is a symlink to the same script, it is not clear how it can determine what to execute next. This is done by looking for a script with the same name, but with _impl appended; this script will then be what actually takes the actions of the command being executed. It can exist anywhere in the subdirectories of ~isg/bin.

For example,

  • ~isg/bin/runMoss will run ~isg/bin/moss-files/runMoss_impl
  • ~isg/bin/getpermissions will run ~isg/bin/util/impl/getpermissions_impl
  • ~isg/bin/printOut will run ~isg/bin/rst-files/postprocess/printOut_impl
All of this is handled automatically by start_template.

Fail function

This script makes use of a fail function to provide generic abort capability.

fail () {
   msg=${1-:Failed to execute setup properly}
   echo "$msg; aborting" >&2 
   exit 125

This accepts a number of strings as parameters (supplying "Failed to execute setup properly" as a default if none are provided), prints them to standard error, and then exits with a non-zero return code.

Else case: Setup has been run

This happens if the condition [ -z "$ISG_BIN_SETUP_DIRS" ] fails; see ISGScriptSetup for details. If this is the case, we assume that setup already ran in this process or a parent process and that we have already been given a sane environment. Because of this, we immediately try to find the name of the executable being run:

   basename "$0" >/dev/null || fail "No runnable basename executable found in inherited path $PATH"

If this presumed sane environment does not contain an executable called basename (which it may not), we cannot continue, so this should cause an error. Otherwise, this should return the name of the currently running executable. Because of this, all we then have to do is:

   exec "$(basename "$0")_impl" "$@"

If case: Setup has not been run

If the setup utility has not already been run (see ISGScriptSetup), then we have a more complicated situation.

First, we know that we cannot trust any default utilities, so the PATH should be set to something minimal and safe, and the hash of run commands should be wiped clean. Note that it is assumed bash will always erase the hash when the PATH is changed like this (modern versions at least guarantee it), but it's safer to be explicit.

   PATH='/bin:/usr/bin'; hash -r

Next, we check for dirname in our minimal PATH, similar to how we checked for basename in the case above. If it is not in the path, there is no clear course of action, so we have no choice but to abort.

   dirname "$0">/dev/null || fail "Could not run dirname in path $PATH"

If dirname exists, then we know we can look in the same directory to find the setup program. The setup program, among other things, will provide us with a path with the following properties:

  • bash version 3 is the default, so we can assume we have access to its features
  • this path also hopefully contains a version of basename

Because of this, we can have setup launch bash, and then in turn bash can run basename on the current executable and append '_impl' to the name; this result is saved in a variable for use next.

   nextexe="$("$(dirname "$0")/setup" bash -c "eval echo '\$(basename "$0")_impl'")" || fail

If this succeeds, we rely on one additional property of setup:

  • all subdirectories of ~isg/bin are included, so it can help us find the _impl version of the current program

So we run it again, knowing it will execute the _impl utility this time.

   exec "$(dirname "$0")/setup" "$nextexe" "$@"

Potential Improvements

One thing that stands out above, and is documented in RT #74634, is that it is wasteful to call setup twice like this.

It should be possible to do the following:

  • combine the setup lines into a single more convoluted line... but with the advantage that setup does not have to be called twice serially like this, which will greatly improve the runtime hit of the startup code.
  • improve error handling if the executable does not exist, so if this does fail the reason can be determined more easily. This includes the calling user having permission to execute start_template but not to execute the next program in the chain (if, for example, it is restricted to the course accounts).
Topic revision: r1 - 2010-10-18 - TerryVaskor
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback