Use of "trampoline" executables
Making products such as perl, tk, and python
into ups products adversely affects their usability as scripting
langauages.
Previous attempts at solving this problem have involved using the
/usr/local/products
convention, have proven administratively difficult, epecially
in the area of creating a sitewide products area in AFS space, and
for off-site users who do not neccesarily have write access to
/usr/local.
This document proposes a new approach to solving these problems, the
use of trampoline executables.
The Goal
The goal of this proposal is that scripting languages like perl,
tk, and python, will be usable via executable scripts
which are stored in a file beginning with:
#!/usr/local/bin/perl
or
#!/usr/local/bin/python
etc.;
This is what users of those scripting languages from places other
than Fermilab are used to.
The problem
Making products such as perl, tk, and python
into ups products adversely affects their usability as above,
because things like libraries, configuration files, etc. are only
locatable if the product has been setup, or if some other method of
locating the product's required files is established.
So even if you copy
or link the executable to /usr/local/bin, the product still
doesn't work, because it can't find its initialization files, libraries,
etc.
This also makes other approaches, like using:
#!/bin/env perl
problematic. Once again, the script doesn't work unless the product
is already setup.
The /usr/local/products "solution"
Previous attempts at solving this problem have involved using the
ups configure
facility, to create a symlink forest down in
/usr/local/products
so that those products do not have to be set up to work.
Instead, they have a compiled-in pathname rooted at /usr/local/products,
which is used to locate library files, config files, etc.
Once this approach was adopted, this was the only mechanism used to
locate the config files, library files, etc. so that if the
symbolic link was missing the product wouldn't work, regardless if
it was set up.
This meant that people who did not have write permission in
/usr/local/products could not install these products and make them
useful, meaning that these products were in general not usable by
off-site users.
It also lead to problems where products areas are shared by multiple systems;
each separate /usr/local area needs to have the ups configure
run on it. So, depending on the configuration of systems, you would get the
product working on one node and not on others. As a final bit of confusion,
there is no way to un-configure the product on more than one node, (since
unconfigure is a side effect of undeclare), so the old symbolic links
never get cleaned up in general.
The sharing problems above makes using these products in a site-wide
product server system, such as the OSS department is trying to build
in AFS space, quite impractical.
The "trampoline" executable approach
An alternative is to build a trampoline executable, which
can be put in directories like /usr/local/bin (or anywhere
else that is convenient for or writable by the installer), which allows
the:
#!/usr/local/bin/perl
header on the script to work.
A trampoline executable looks something like:
#include <stdlib.h>
#define MAXPATHLEN 1024
char python_dir[MAXPATHLEN] =
"PYTHON_DIR_PUT_HERE_WHEN_PYTHON_IS_CONFIGURED"
char python[MAXPATHLEN];
char pythonpath[MAXPATHLEN*5];
char pythonhome[MAXPATHLEN];
char error[MAXPATHLEN+10];
int
main(int argc, char **argv) {
sprintf (pythonpath,
"PYTHONPATH=%s/lib/python1.5:%s/lib/python1.5/lib-dynload:%s/lib/python1.5/lib-stdwin:%s/lib/python1.5/lib-tk:%s/lib/python1.5/plat",
python_dir,
python_dir,
python_dir,
python_dir,
python_dir);
sprintf(pythonhome,"PYTHONHOME=%s",python_dir);
sprintf(python, "%s/bin/python", python_dir );
putenv(pythonhome);
putenv(pythonpath);
execv(python, argv );
sprintf(error, "can't exec %s:", python);
perror(error);
}
In other words, it sets the environment variables that the product setup
script would have set, and exec's the interpreter executable in the
product;
in effect "bouncing" the exec() off of the first executable and onto
the interpreter, hence the name trampoline.
A similar, although slower, alternative is to have an "always run the
current version" trampoline script, which execs a shell which
actually sources the "setups" script, and sets up the product before
executing the interpreter.
Solution Strategies
For backwards compatability with past "shells" product installations,
the new, standlone, perl product will provide a trampoline executable that
can be installed in /usr/local/bin. Similar trampoline scripts can
be provided for other interpreted languages.
In addition the following concrete proposals are being implemented:
- Symlinks to trampoline executables for perl and python are
being put in /usr/local/bin.
On systems using AFS Space, the trampoline executables themselves
are put in:
/afs/fnal.gov/products/share/flavor
so that other systems following this convention are automatically
updated when the central AFS fileserver product "current" instance
is changed.
On non-AFS systems, the trampoline executables are put directly in
/usr/local/bin.
- The installation happens automatically upon declare of the product
as current. Currently the AFS shared trampoline installation above
is only followed when ALTBIN is set in the environment to the
appropriate share area.
A warning will be issued if ALTBIN is not set on an AFS install.
- Trampoline executables setup exactly the version or versions
that were in force when the product was configured. The product
must be reconfigured and redeclared current to force updates of
the trampoline scripts (for example if they also setup dependencies).
24 April 1998
Comments? Send them to uas-group@fnal.gov