2011-10-03 20:54:12 +02:00
|
|
|
/** @file
|
|
|
|
Return the initial module search path.
|
|
|
|
|
|
|
|
Search in specified locations for the associated Python libraries.
|
|
|
|
|
|
|
|
Py_GetPath returns module_search_path.
|
|
|
|
Py_GetPrefix returns PREFIX
|
|
|
|
Py_GetExec_Prefix returns PREFIX
|
|
|
|
Py_GetProgramFullPath returns the full path to the python executable.
|
|
|
|
|
|
|
|
These are built dynamically so that the proper volume name can be prefixed
|
|
|
|
to the paths.
|
|
|
|
|
|
|
|
For the EDK II, UEFI, implementation of Python, PREFIX and EXEC_PREFIX
|
|
|
|
are set as follows:
|
|
|
|
PREFIX = /Efi/StdLib
|
|
|
|
EXEC_PREFIX = PREFIX
|
|
|
|
|
|
|
|
The following final paths are assumed:
|
|
|
|
/Efi/Tools/Python.efi The Python executable.
|
|
|
|
/Efi/StdLib/lib/python.VERSION The platform independent Python modules.
|
|
|
|
/Efi/StdLib/lib/python.VERSION/dynalib Dynamically loadable Python extension modules.
|
|
|
|
|
2012-03-29 00:17:44 +02:00
|
|
|
Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
|
2011-10-03 20:54:12 +02:00
|
|
|
This program and the accompanying materials are licensed and made available under
|
|
|
|
the terms and conditions of the BSD License that accompanies this distribution.
|
|
|
|
The full text of the license may be found at
|
|
|
|
http://opensource.org/licenses/bsd-license.
|
|
|
|
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include <Python.h>
|
|
|
|
#include <osdefs.h>
|
2012-01-26 23:04:41 +01:00
|
|
|
#include <ctype.h>
|
2011-10-03 20:54:12 +02:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* VERSION must be at least two characters long. */
|
|
|
|
#ifndef VERSION
|
|
|
|
#define VERSION "27"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef VPATH
|
|
|
|
#define VPATH "."
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Search path entry delimiter */
|
|
|
|
#ifdef DELIM
|
|
|
|
#define sDELIM ";"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef PREFIX
|
|
|
|
#define PREFIX "/Efi/StdLib"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EXEC_PREFIX
|
|
|
|
#define EXEC_PREFIX PREFIX
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef LIBPYTHON
|
|
|
|
#define LIBPYTHON "lib/python." VERSION
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef PYTHONPATH
|
2012-03-29 00:17:44 +02:00
|
|
|
#ifdef HAVE_ENVIRONMENT_OPS
|
|
|
|
#define PYTHONPATH PREFIX LIBPYTHON sDELIM \
|
|
|
|
EXEC_PREFIX LIBPYTHON "/lib-dynload"
|
|
|
|
#else
|
|
|
|
#define PYTHONPATH LIBPYTHON
|
|
|
|
#endif
|
2011-10-03 20:54:12 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef LANDMARK
|
|
|
|
#define LANDMARK "os.py"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static char prefix[MAXPATHLEN+1];
|
|
|
|
static char exec_prefix[MAXPATHLEN+1];
|
|
|
|
static char progpath[MAXPATHLEN+1];
|
|
|
|
static char *module_search_path = NULL;
|
|
|
|
static char lib_python[] = LIBPYTHON;
|
|
|
|
static char volume_name[32] = { 0 };
|
|
|
|
|
|
|
|
/** Determine if "ch" is a separator character.
|
|
|
|
|
|
|
|
@param[in] ch The character to test.
|
|
|
|
|
|
|
|
@retval TRUE ch is a separator character.
|
|
|
|
@retval FALSE ch is NOT a separator character.
|
|
|
|
**/
|
|
|
|
static int
|
|
|
|
is_sep(char ch)
|
|
|
|
{
|
|
|
|
#ifdef ALTSEP
|
|
|
|
return ch == SEP || ch == ALTSEP;
|
|
|
|
#else
|
|
|
|
return ch == SEP;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Reduce a path by its last element.
|
|
|
|
|
|
|
|
The last element (everything to the right of the last separator character)
|
|
|
|
in the path, dir, is removed from the path. Parameter dir is modified in place.
|
|
|
|
|
|
|
|
@param[in,out] dir Pointer to the path to modify.
|
|
|
|
**/
|
|
|
|
static void
|
|
|
|
reduce(char *dir)
|
|
|
|
{
|
|
|
|
size_t i = strlen(dir);
|
|
|
|
while (i > 0 && !is_sep(dir[i]))
|
|
|
|
--i;
|
|
|
|
dir[i] = '\0';
|
|
|
|
}
|
|
|
|
|
2012-03-29 00:17:44 +02:00
|
|
|
#ifndef UEFI_C_SOURCE
|
2011-10-03 20:54:12 +02:00
|
|
|
/** Does filename point to a file and not directory?
|
|
|
|
|
|
|
|
@param[in] filename The fully qualified path to the object to test.
|
|
|
|
|
|
|
|
@retval 0 Filename was not found, or is a directory.
|
|
|
|
@retval 1 Filename refers to a regular file.
|
|
|
|
**/
|
|
|
|
static int
|
|
|
|
isfile(char *filename)
|
|
|
|
{
|
|
|
|
struct stat buf;
|
|
|
|
if (stat(filename, &buf) != 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
//if (!S_ISREG(buf.st_mode))
|
|
|
|
if (S_ISDIR(buf.st_mode)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Determine if filename refers to a Python module.
|
|
|
|
|
|
|
|
A Python module is indicated if the file exists, or if the file with
|
|
|
|
'o' or 'c' appended exists.
|
|
|
|
|
|
|
|
@param[in] filename The fully qualified path to the object to test.
|
|
|
|
|
|
|
|
@retval 0
|
|
|
|
**/
|
|
|
|
static int
|
|
|
|
ismodule(char *filename)
|
|
|
|
{
|
|
|
|
if (isfile(filename)) {
|
|
|
|
//if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for the compiled version of prefix. */
|
|
|
|
if (strlen(filename) < MAXPATHLEN) {
|
|
|
|
strcat(filename, Py_OptimizeFlag ? "o" : "c");
|
|
|
|
if (isfile(filename)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Does filename point to a directory?
|
|
|
|
|
|
|
|
@param[in] filename The fully qualified path to the object to test.
|
|
|
|
|
|
|
|
@retval 0 Filename was not found, or is not a regular file.
|
|
|
|
@retval 1 Filename refers to a directory.
|
|
|
|
**/
|
|
|
|
static int
|
|
|
|
isdir(char *filename)
|
|
|
|
{
|
|
|
|
struct stat buf;
|
|
|
|
|
|
|
|
if (stat(filename, &buf) != 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!S_ISDIR(buf.st_mode))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2012-03-29 00:17:44 +02:00
|
|
|
#endif /* UEFI_C_SOURCE */
|
2011-10-03 20:54:12 +02:00
|
|
|
|
|
|
|
/** Determine if a path is absolute, or not.
|
|
|
|
An absolute path consists of a volume name, "VOL:", followed by a rooted path,
|
|
|
|
"/path/elements". If both of these components are present, the path is absolute.
|
|
|
|
|
|
|
|
Let P be a pointer to the path to test.
|
|
|
|
Let A be a pointer to the first ':' in P.
|
|
|
|
Let B be a pointer to the first '/' or '\\' in P.
|
|
|
|
|
|
|
|
If A and B are not NULL
|
|
|
|
If (A-P+1) == (B-P) then the path is absolute.
|
|
|
|
Otherwise, the path is NOT absolute.
|
|
|
|
|
|
|
|
@param[in] path The path to test.
|
|
|
|
|
|
|
|
@retval -1 Path is absolute but lacking volume name.
|
|
|
|
@retval 0 Path is NOT absolute.
|
|
|
|
@retval 1 Path is absolute.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
is_absolute(char *path)
|
|
|
|
{
|
|
|
|
char *A;
|
|
|
|
char *B;
|
|
|
|
|
|
|
|
A = strchr(path, ':');
|
|
|
|
B = strpbrk(path, "/\\");
|
|
|
|
|
|
|
|
if(B != NULL) {
|
|
|
|
if(A == NULL) {
|
|
|
|
if(B == path) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(((A - path) + 1) == (B - path)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Add a path component, by appending stuff to buffer.
|
|
|
|
buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
|
|
|
|
NUL-terminated string with no more than MAXPATHLEN characters (not counting
|
|
|
|
the trailing NUL). It's a fatal error if it contains a string longer than
|
|
|
|
that (callers must be careful!). If these requirements are met, it's
|
|
|
|
guaranteed that buffer will still be a NUL-terminated string with no more
|
|
|
|
than MAXPATHLEN characters at exit. If stuff is too long, only as much of
|
|
|
|
stuff as fits will be appended.
|
|
|
|
|
|
|
|
@param[in,out] buffer The path to be extended.
|
|
|
|
@param[in] stuff The stuff to join onto the path.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
joinpath(char *buffer, char *stuff)
|
|
|
|
{
|
|
|
|
size_t n, k;
|
|
|
|
|
|
|
|
k = 0;
|
|
|
|
if (is_absolute(stuff) == 1) {
|
|
|
|
n = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
n = strlen(buffer);
|
|
|
|
if(n == 0) {
|
|
|
|
strncpy(buffer, volume_name, MAXPATHLEN);
|
|
|
|
n = strlen(buffer);
|
|
|
|
}
|
|
|
|
/* We must not use an else clause here because we want to test n again.
|
|
|
|
volume_name may have been empty.
|
|
|
|
*/
|
|
|
|
if (n > 0 && n < MAXPATHLEN) {
|
|
|
|
if(!is_sep(buffer[n-1])) {
|
|
|
|
buffer[n++] = SEP;
|
|
|
|
}
|
|
|
|
if(is_sep(stuff[0])) ++stuff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (n > MAXPATHLEN)
|
|
|
|
Py_FatalError("buffer overflow in getpath.c's joinpath()");
|
|
|
|
k = strlen(stuff);
|
|
|
|
if (n + k > MAXPATHLEN)
|
|
|
|
k = MAXPATHLEN - n;
|
|
|
|
strncpy(buffer+n, stuff, k);
|
|
|
|
buffer[n+k] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Is filename an executable file?
|
|
|
|
|
|
|
|
An executable file:
|
|
|
|
1) exists
|
|
|
|
2) is a file, not a directory
|
|
|
|
3) has a name ending with ".efi"
|
|
|
|
4) Only has a single '.' in the name.
|
|
|
|
|
|
|
|
If basename(filename) does not contain a '.', append ".efi" to filename
|
|
|
|
If filename ends in ".efi", it is executable, else it isn't.
|
|
|
|
|
|
|
|
This routine is used to when searching for the file named by argv[0].
|
|
|
|
As such, there is no need to search for extensions other than ".efi".
|
|
|
|
|
|
|
|
@param[in] filename The name of the file to test. It may, or may not, have an extension.
|
|
|
|
|
|
|
|
@retval 0 filename already has a path other than ".efi", or it doesn't exist, or is a directory.
|
|
|
|
@retval 1 filename refers to an executable file.
|
|
|
|
**/
|
|
|
|
static int
|
|
|
|
isxfile(char *filename)
|
|
|
|
{
|
|
|
|
struct stat buf;
|
|
|
|
char *bn;
|
|
|
|
char *newbn;
|
|
|
|
int bnlen;
|
|
|
|
|
|
|
|
bn = basename(filename); // Separate off the file name component
|
|
|
|
reduce(filename); // and isolate the path component
|
|
|
|
bnlen = strlen(bn);
|
|
|
|
newbn = strrchr(bn, '.'); // Does basename contain a period?
|
|
|
|
if(newbn == NULL) { // Does NOT contain a period.
|
|
|
|
newbn = &bn[bnlen];
|
|
|
|
strncpyX(newbn, ".efi", MAXPATHLEN - bnlen); // append ".efi" to basename
|
|
|
|
bnlen += 4;
|
|
|
|
}
|
|
|
|
else if(strcmp(newbn, ".efi") != 0) {
|
|
|
|
return 0; // File can not be executable.
|
|
|
|
}
|
|
|
|
joinpath(filename, bn); // Stitch path and file name back together
|
|
|
|
|
|
|
|
if (stat(filename, &buf) != 0) { // Now, verify that file exists
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(S_ISDIR(buf.st_mode)) { // And it is not a directory.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Copy p into path, ensuring that the result is an absolute path.
|
|
|
|
|
|
|
|
copy_absolute requires that path be allocated at least
|
|
|
|
MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes.
|
|
|
|
|
|
|
|
@param[out] path Destination to receive the absolute path.
|
|
|
|
@param[in] p Path to be tested and possibly converted.
|
|
|
|
**/
|
|
|
|
static void
|
|
|
|
copy_absolute(char *path, char *p)
|
|
|
|
{
|
|
|
|
if (is_absolute(p) == 1)
|
|
|
|
strcpy(path, p);
|
|
|
|
else {
|
|
|
|
if (!getcwd(path, MAXPATHLEN)) {
|
|
|
|
/* unable to get the current directory */
|
|
|
|
if(volume_name[0] != 0) {
|
|
|
|
strcpy(path, volume_name);
|
|
|
|
joinpath(path, p);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strcpy(path, p);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (p[0] == '.' && is_sep(p[1]))
|
|
|
|
p += 2;
|
|
|
|
joinpath(path, p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Modify path so that the result is an absolute path.
|
|
|
|
absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes.
|
|
|
|
|
|
|
|
@param[in,out] path The path to be made absolute.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
absolutize(char *path)
|
|
|
|
{
|
|
|
|
char buffer[MAXPATHLEN + 1];
|
|
|
|
|
|
|
|
if (is_absolute(path) == 1)
|
|
|
|
return;
|
|
|
|
copy_absolute(buffer, path);
|
|
|
|
strcpy(path, buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Extract the volume name from a path.
|
|
|
|
|
|
|
|
@param[out] Dest Pointer to location in which to store the extracted volume name.
|
|
|
|
@param[in] path Pointer to the path to extract the volume name from.
|
|
|
|
**/
|
|
|
|
static void
|
|
|
|
set_volume(char *Dest, char *path)
|
|
|
|
{
|
|
|
|
size_t VolLen;
|
|
|
|
|
|
|
|
if(is_absolute(path)) {
|
|
|
|
VolLen = strcspn(path, "/\\:");
|
|
|
|
if((VolLen != 0) && (path[VolLen] == ':')) {
|
|
|
|
(void) strncpyX(Dest, path, VolLen + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Determine paths.
|
|
|
|
|
|
|
|
Two directories must be found, the platform independent directory
|
|
|
|
(prefix), containing the common .py and .pyc files, and the platform
|
|
|
|
dependent directory (exec_prefix), containing the shared library
|
|
|
|
modules. Note that prefix and exec_prefix are the same directory
|
|
|
|
for UEFI installations.
|
|
|
|
|
|
|
|
Separate searches are carried out for prefix and exec_prefix.
|
|
|
|
Each search tries a number of different locations until a ``landmark''
|
|
|
|
file or directory is found. If no prefix or exec_prefix is found, a
|
|
|
|
warning message is issued and the preprocessor defined PREFIX and
|
|
|
|
EXEC_PREFIX are used (even though they may not work); python carries on
|
|
|
|
as best as is possible, but some imports may fail.
|
|
|
|
|
|
|
|
Before any searches are done, the location of the executable is
|
|
|
|
determined. If argv[0] has one or more slashes in it, it is used
|
|
|
|
unchanged. Otherwise, it must have been invoked from the shell's path,
|
|
|
|
so we search %PATH% for the named executable and use that. If the
|
|
|
|
executable was not found on %PATH% (or there was no %PATH% environment
|
|
|
|
variable), the original argv[0] string is used.
|
|
|
|
|
|
|
|
Finally, argv0_path is set to the directory containing the executable
|
|
|
|
(i.e. the last component is stripped).
|
|
|
|
|
|
|
|
With argv0_path in hand, we perform a number of steps. The same steps
|
|
|
|
are performed for prefix and for exec_prefix, but with a different
|
|
|
|
landmark.
|
|
|
|
|
|
|
|
The prefix landmark will always be lib/python.VERSION/os.py and the
|
|
|
|
exec_prefix will always be lib/python.VERSION/dynaload, where VERSION
|
|
|
|
is Python's version number as defined at the beginning of this file.
|
|
|
|
|
|
|
|
First. See if the %PYTHONHOME% environment variable points to the
|
|
|
|
installed location of the Python libraries. If %PYTHONHOME% is set, then
|
|
|
|
it points to prefix and exec_prefix. %PYTHONHOME% can be a single
|
|
|
|
directory, which is used for both, or the prefix and exec_prefix
|
|
|
|
directories separated by the DELIM character.
|
|
|
|
|
|
|
|
Next. Search the directories pointed to by the preprocessor variables
|
|
|
|
PREFIX and EXEC_PREFIX. These paths are prefixed with the volume name
|
|
|
|
extracted from argv0_path. The volume names correspond to the UEFI
|
|
|
|
shell "map" names.
|
|
|
|
|
|
|
|
That's it!
|
|
|
|
|
|
|
|
Well, almost. Once we have determined prefix and exec_prefix, the
|
|
|
|
preprocessor variable PYTHONPATH is used to construct a path. Each
|
|
|
|
relative path on PYTHONPATH is prefixed with prefix. Then the directory
|
|
|
|
containing the shared library modules is appended. The environment
|
|
|
|
variable $PYTHONPATH is inserted in front of it all. Finally, the
|
|
|
|
prefix and exec_prefix globals are tweaked so they reflect the values
|
|
|
|
expected by other code, by stripping the "lib/python$VERSION/..." stuff
|
|
|
|
off. This seems to make more sense given that currently the only
|
|
|
|
known use of sys.prefix and sys.exec_prefix is for the ILU installation
|
|
|
|
process to find the installed Python tree.
|
|
|
|
|
|
|
|
The final, fully resolved, paths should look something like:
|
|
|
|
fs0:/Efi/Tools/python.efi
|
|
|
|
fs0:/Efi/StdLib/lib/python27
|
|
|
|
fs0:/Efi/StdLib/lib/python27/dynaload
|
|
|
|
|
|
|
|
**/
|
|
|
|
static void
|
|
|
|
calculate_path(void)
|
|
|
|
{
|
|
|
|
extern char *Py_GetProgramName(void);
|
|
|
|
|
|
|
|
static char delimiter[2] = {DELIM, '\0'};
|
|
|
|
static char separator[2] = {SEP, '\0'};
|
|
|
|
char *pythonpath = PYTHONPATH;
|
|
|
|
char *rtpypath = Py_GETENV("PYTHONPATH");
|
|
|
|
//char *home = Py_GetPythonHome();
|
|
|
|
char *path = getenv("PATH");
|
|
|
|
char *prog = Py_GetProgramName();
|
|
|
|
char argv0_path[MAXPATHLEN+1];
|
|
|
|
char zip_path[MAXPATHLEN+1];
|
|
|
|
char *buf;
|
|
|
|
size_t bufsz;
|
|
|
|
size_t prefixsz;
|
|
|
|
char *defpath;
|
|
|
|
|
|
|
|
|
|
|
|
/* ###########################################################################
|
|
|
|
Determine path to the Python.efi binary.
|
|
|
|
Produces progpath, argv0_path, and volume_name.
|
|
|
|
########################################################################### */
|
|
|
|
|
|
|
|
/* If there is no slash in the argv0 path, then we have to
|
|
|
|
* assume python is on the user's $PATH, since there's no
|
|
|
|
* other way to find a directory to start the search from. If
|
|
|
|
* $PATH isn't exported, you lose.
|
|
|
|
*/
|
|
|
|
if (strchr(prog, SEP))
|
|
|
|
strncpy(progpath, prog, MAXPATHLEN);
|
|
|
|
else if (path) {
|
|
|
|
while (1) {
|
|
|
|
char *delim = strchr(path, DELIM);
|
|
|
|
|
|
|
|
if (delim) {
|
|
|
|
size_t len = delim - path;
|
|
|
|
if (len > MAXPATHLEN)
|
|
|
|
len = MAXPATHLEN;
|
|
|
|
strncpy(progpath, path, len);
|
|
|
|
*(progpath + len) = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strncpy(progpath, path, MAXPATHLEN);
|
|
|
|
|
|
|
|
joinpath(progpath, prog);
|
|
|
|
if (isxfile(progpath))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (!delim) {
|
|
|
|
progpath[0] = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
path = delim + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
progpath[0] = '\0';
|
|
|
|
if ( (!is_absolute(progpath)) && (progpath[0] != '\0') )
|
|
|
|
absolutize(progpath);
|
|
|
|
strncpy(argv0_path, progpath, MAXPATHLEN);
|
|
|
|
argv0_path[MAXPATHLEN] = '\0';
|
|
|
|
set_volume(volume_name, argv0_path);
|
|
|
|
|
|
|
|
reduce(argv0_path);
|
|
|
|
/* At this point, argv0_path is guaranteed to be less than
|
|
|
|
MAXPATHLEN bytes long.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* ###########################################################################
|
|
|
|
Build the FULL prefix string, including volume name.
|
|
|
|
This is the full path to the platform independent libraries.
|
|
|
|
########################################################################### */
|
|
|
|
|
|
|
|
strncpy(prefix, volume_name, MAXPATHLEN);
|
|
|
|
joinpath(prefix, PREFIX);
|
|
|
|
joinpath(prefix, lib_python);
|
|
|
|
|
|
|
|
/* ###########################################################################
|
|
|
|
Build the FULL path to the zipped-up Python library.
|
|
|
|
########################################################################### */
|
|
|
|
|
|
|
|
strncpy(zip_path, prefix, MAXPATHLEN);
|
|
|
|
zip_path[MAXPATHLEN] = '\0';
|
2012-01-26 23:04:41 +01:00
|
|
|
reduce(zip_path);
|
2011-10-03 20:54:12 +02:00
|
|
|
joinpath(zip_path, "python00.zip");
|
|
|
|
bufsz = strlen(zip_path); /* Replace "00" with version */
|
|
|
|
zip_path[bufsz - 6] = VERSION[0];
|
|
|
|
zip_path[bufsz - 5] = VERSION[1];
|
|
|
|
|
|
|
|
/* ###########################################################################
|
|
|
|
Build the FULL path to dynamically loadable libraries.
|
|
|
|
########################################################################### */
|
|
|
|
|
|
|
|
strncpy(exec_prefix, volume_name, MAXPATHLEN);
|
|
|
|
joinpath(exec_prefix, EXEC_PREFIX);
|
|
|
|
joinpath(exec_prefix, lib_python);
|
2012-01-26 23:04:41 +01:00
|
|
|
joinpath(exec_prefix, "lib-dynload");
|
2011-10-03 20:54:12 +02:00
|
|
|
|
|
|
|
/* ###########################################################################
|
|
|
|
Build the module search path.
|
|
|
|
########################################################################### */
|
|
|
|
|
|
|
|
/* Reduce prefix and exec_prefix to their essence,
|
|
|
|
* e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
|
|
|
|
* If we're loading relative to the build directory,
|
|
|
|
* return the compiled-in defaults instead.
|
|
|
|
*/
|
|
|
|
reduce(prefix);
|
|
|
|
reduce(prefix);
|
|
|
|
/* The prefix is the root directory, but reduce() chopped
|
|
|
|
* off the "/". */
|
|
|
|
if (!prefix[0]) {
|
|
|
|
strcpy(prefix, volume_name);
|
|
|
|
}
|
|
|
|
bufsz = strlen(prefix);
|
|
|
|
if(prefix[bufsz-1] == ':') {
|
|
|
|
prefix[bufsz] = SEP;
|
|
|
|
prefix[bufsz+1] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate size of return buffer.
|
|
|
|
*/
|
|
|
|
defpath = pythonpath;
|
|
|
|
bufsz = 0;
|
|
|
|
|
|
|
|
if (rtpypath)
|
|
|
|
bufsz += strlen(rtpypath) + 1;
|
|
|
|
|
|
|
|
prefixsz = strlen(prefix) + 1;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
char *delim = strchr(defpath, DELIM);
|
|
|
|
|
|
|
|
if (is_absolute(defpath) == 0)
|
|
|
|
/* Paths are relative to prefix */
|
|
|
|
bufsz += prefixsz;
|
|
|
|
|
|
|
|
if (delim)
|
|
|
|
bufsz += delim - defpath + 1;
|
|
|
|
else {
|
|
|
|
bufsz += strlen(defpath) + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
defpath = delim + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bufsz += strlen(zip_path) + 1;
|
|
|
|
bufsz += strlen(exec_prefix) + 1;
|
|
|
|
|
|
|
|
/* This is the only malloc call in this file */
|
|
|
|
buf = (char *)PyMem_Malloc(bufsz);
|
|
|
|
|
|
|
|
if (buf == NULL) {
|
|
|
|
/* We can't exit, so print a warning and limp along */
|
|
|
|
fprintf(stderr, "Not enough memory for dynamic PYTHONPATH.\n");
|
|
|
|
fprintf(stderr, "Using default static PYTHONPATH.\n");
|
|
|
|
module_search_path = PYTHONPATH;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Run-time value of $PYTHONPATH goes first */
|
|
|
|
if (rtpypath) {
|
|
|
|
strcpy(buf, rtpypath);
|
|
|
|
strcat(buf, delimiter);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
buf[0] = '\0';
|
|
|
|
|
|
|
|
/* Next is the default zip path */
|
|
|
|
strcat(buf, zip_path);
|
|
|
|
strcat(buf, delimiter);
|
|
|
|
|
|
|
|
/* Next goes merge of compile-time $PYTHONPATH with
|
|
|
|
* dynamically located prefix.
|
|
|
|
*/
|
|
|
|
defpath = pythonpath;
|
|
|
|
while (1) {
|
|
|
|
char *delim = strchr(defpath, DELIM);
|
|
|
|
|
|
|
|
if (is_absolute(defpath) != 1) {
|
|
|
|
strcat(buf, prefix);
|
|
|
|
strcat(buf, separator);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (delim) {
|
|
|
|
size_t len = delim - defpath + 1;
|
|
|
|
size_t end = strlen(buf) + len;
|
|
|
|
strncat(buf, defpath, len);
|
|
|
|
*(buf + end) = '\0';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
strcat(buf, defpath);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
defpath = delim + 1;
|
|
|
|
}
|
|
|
|
strcat(buf, delimiter);
|
|
|
|
|
|
|
|
/* Finally, on goes the directory for dynamic-load modules */
|
|
|
|
strcat(buf, exec_prefix);
|
|
|
|
|
|
|
|
/* And publish the results */
|
|
|
|
module_search_path = buf;
|
|
|
|
}
|
|
|
|
/* At this point, exec_prefix is set to VOL:/Efi/StdLib/lib/python.27/dynalib.
|
|
|
|
We want to get back to the root value, so we have to remove the final three
|
|
|
|
segments to get VOL:/Efi/StdLib. Because we don't know what VOL is, and
|
|
|
|
EXEC_PREFIX is also indeterminate, we just remove the three final segments.
|
|
|
|
*/
|
|
|
|
reduce(exec_prefix);
|
|
|
|
reduce(exec_prefix);
|
|
|
|
reduce(exec_prefix);
|
|
|
|
if (!exec_prefix[0]) {
|
|
|
|
strcpy(exec_prefix, volume_name);
|
|
|
|
}
|
|
|
|
bufsz = strlen(exec_prefix);
|
|
|
|
if(exec_prefix[bufsz-1] == ':') {
|
|
|
|
exec_prefix[bufsz] = SEP;
|
|
|
|
exec_prefix[bufsz+1] = 0;
|
|
|
|
}
|
|
|
|
if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__, __LINE__, module_search_path);
|
|
|
|
if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: prefix = \"%s\"\n", __func__, __LINE__, prefix);
|
|
|
|
if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: exec_prefix = \"%s\"\n", __func__, __LINE__, exec_prefix);
|
|
|
|
if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__, __LINE__, progpath);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* External interface */
|
|
|
|
|
|
|
|
char *
|
|
|
|
Py_GetPath(void)
|
|
|
|
{
|
|
|
|
if (!module_search_path)
|
|
|
|
calculate_path();
|
|
|
|
return module_search_path;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
Py_GetPrefix(void)
|
|
|
|
{
|
|
|
|
if (!module_search_path)
|
|
|
|
calculate_path();
|
|
|
|
return prefix;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
Py_GetExecPrefix(void)
|
|
|
|
{
|
|
|
|
if (!module_search_path)
|
|
|
|
calculate_path();
|
|
|
|
return exec_prefix;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
Py_GetProgramFullPath(void)
|
|
|
|
{
|
|
|
|
if (!module_search_path)
|
|
|
|
calculate_path();
|
|
|
|
return progpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|