NB: The following information is known to be accurate as of revision 851.
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.
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
start_template
.
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.
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 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:
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
:
~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" "$@"
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:
start_template
but not to execute the next program in the chain (if, for example, it is restricted to the course accounts).