141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** @file
241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Return the initial module search path.
341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Search in specified locations for the associated Python libraries.
541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Py_GetPath returns module_search_path.
741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Py_GetPrefix returns PREFIX
841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Py_GetExec_Prefix returns PREFIX
941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Py_GetProgramFullPath returns the full path to the python executable.
1041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
1141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    These are built dynamically so that the proper volume name can be prefixed
1241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    to the paths.
1341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
1441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    For the EDK II, UEFI, implementation of Python, PREFIX and EXEC_PREFIX
1541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    are set as follows:
1641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      PREFIX      = /Efi/StdLib
1741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      EXEC_PREFIX = PREFIX
1841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
1941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    The following final paths are assumed:
2041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      /Efi/Tools/Python.efi                     The Python executable.
2141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      /Efi/StdLib/lib/python.VERSION            The platform independent Python modules.
2241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      /Efi/StdLib/lib/python.VERSION/dynalib    Dynamically loadable Python extension modules.
2341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
24521527e0b63910d6d4d0d011e86738f21fbd32bfdarylm    Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
2541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    This program and the accompanying materials are licensed and made available under
2641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    the terms and conditions of the BSD License that accompanies this distribution.
2741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    The full text of the license may be found at
2841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    http://opensource.org/licenses/bsd-license.
2941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
3041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
3141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
3241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
3341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#include <Python.h>
3441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#include <osdefs.h>
35b410d6e4ce58c177569d42b51772f7bb239a24a3darylm#include  <ctype.h>
3641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
3741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifdef __cplusplus
3841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm extern "C" {
3941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
4041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
4141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/* VERSION must be at least two characters long. */
4241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifndef VERSION
4341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  #define VERSION     "27"
4441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
4541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
4641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifndef VPATH
4741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  #define VPATH       "."
4841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
4941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
5041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/* Search path entry delimiter */
5141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifdef DELIM
5241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  #define sDELIM        ";"
5341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
5441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
5541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifndef PREFIX
5641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  #define PREFIX      "/Efi/StdLib"
5741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
5841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
5941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifndef EXEC_PREFIX
6041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  #define EXEC_PREFIX PREFIX
6141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
6241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
6341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifndef   LIBPYTHON
6441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  #define   LIBPYTHON     "lib/python." VERSION
6541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
6641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
6741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifndef PYTHONPATH
68521527e0b63910d6d4d0d011e86738f21fbd32bfdarylm  #ifdef HAVE_ENVIRONMENT_OPS
69521527e0b63910d6d4d0d011e86738f21fbd32bfdarylm    #define PYTHONPATH  PREFIX LIBPYTHON sDELIM \
70521527e0b63910d6d4d0d011e86738f21fbd32bfdarylm                        EXEC_PREFIX LIBPYTHON "/lib-dynload"
71521527e0b63910d6d4d0d011e86738f21fbd32bfdarylm  #else
72521527e0b63910d6d4d0d011e86738f21fbd32bfdarylm    #define PYTHONPATH  LIBPYTHON
73521527e0b63910d6d4d0d011e86738f21fbd32bfdarylm  #endif
7441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
7541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
7641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifndef LANDMARK
7741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#define LANDMARK    "os.py"
7841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
7941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
8041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic char   prefix[MAXPATHLEN+1];
8141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic char   exec_prefix[MAXPATHLEN+1];
8241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic char   progpath[MAXPATHLEN+1];
8341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic char  *module_search_path          = NULL;
8441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic char   lib_python[]                = LIBPYTHON;
8541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic char   volume_name[32]             = { 0 };
8641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
8741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Determine if "ch" is a separator character.
8841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
8941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in]  ch      The character to test.
9041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
9141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval     TRUE    ch is a separator character.
9241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval     FALSE   ch is NOT a separator character.
9341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
9441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic int
9541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmis_sep(char ch)
9641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
9741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifdef ALTSEP
9841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  return ch == SEP || ch == ALTSEP;
9941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#else
10041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  return ch == SEP;
10141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
10241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
10341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
10441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Reduce a path by its last element.
10541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
10641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    The last element (everything to the right of the last separator character)
10741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    in the path, dir, is removed from the path.  Parameter dir is modified in place.
10841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
10941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in,out]    dir   Pointer to the path to modify.
11041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
11141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic void
11241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmreduce(char *dir)
11341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
11441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    size_t i = strlen(dir);
11541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    while (i > 0 && !is_sep(dir[i]))
11641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        --i;
11741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    dir[i] = '\0';
11841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
11941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
120521527e0b63910d6d4d0d011e86738f21fbd32bfdarylm#ifndef UEFI_C_SOURCE
12141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Does filename point to a file and not directory?
12241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
12341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in]    filename    The fully qualified path to the object to test.
12441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
12541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval       0     Filename was not found, or is a directory.
12641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval       1     Filename refers to a regular file.
12741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
12841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic int
12941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmisfile(char *filename)
13041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
13141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    struct stat buf;
13241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (stat(filename, &buf) != 0) {
13341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      return 0;
13441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
13541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    //if (!S_ISREG(buf.st_mode))
13641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (S_ISDIR(buf.st_mode)) {
13741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      return 0;
13841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
13941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    return 1;
14041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
14141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
14241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Determine if filename refers to a Python module.
14341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
14441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    A Python module is indicated if the file exists, or if the file with
14541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    'o' or 'c' appended exists.
14641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
14741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in]    filename    The fully qualified path to the object to test.
14841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
14941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval       0
15041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
15141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic int
15241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmismodule(char *filename)
15341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
15441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  if (isfile(filename)) {
15541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
15641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    return 1;
15741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  }
15841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
15941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    /* Check for the compiled version of prefix. */
16041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (strlen(filename) < MAXPATHLEN) {
16141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        strcat(filename, Py_OptimizeFlag ? "o" : "c");
16241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        if (isfile(filename)) {
16341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm          return 1;
16441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        }
16541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
16641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    return 0;
16741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
16841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
16941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Does filename point to a directory?
17041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
17141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in]    filename    The fully qualified path to the object to test.
17241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
17341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval       0     Filename was not found, or is not a regular file.
17441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval       1     Filename refers to a directory.
17541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
17641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic int
17741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmisdir(char *filename)
17841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
17941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    struct stat buf;
18041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
18141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (stat(filename, &buf) != 0)
18241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        return 0;
18341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
18441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (!S_ISDIR(buf.st_mode))
18541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        return 0;
18641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
18741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    return 1;
18841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
189521527e0b63910d6d4d0d011e86738f21fbd32bfdarylm#endif  /* UEFI_C_SOURCE */
19041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
19141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Determine if a path is absolute, or not.
19241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    An absolute path consists of a volume name, "VOL:", followed by a rooted path,
19341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    "/path/elements".  If both of these components are present, the path is absolute.
19441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
19541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Let P be a pointer to the path to test.
19641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Let A be a pointer to the first ':' in P.
19741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Let B be a pointer to the first '/' or '\\' in P.
19841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
19941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    If A and B are not NULL
20041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      If (A-P+1) == (B-P) then the path is absolute.
20141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Otherwise, the path is NOT absolute.
20241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
20341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in]  path    The path to test.
20441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
20541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval     -1      Path is absolute but lacking volume name.
20641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval      0      Path is NOT absolute.
20741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval      1      Path is absolute.
20841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm*/
20941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic int
21041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmis_absolute(char *path)
21141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
21241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  char  *A;
21341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  char  *B;
21441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
21541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  A = strchr(path, ':');
21641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  B = strpbrk(path, "/\\");
21741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
21841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  if(B != NULL) {
21941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if(A == NULL) {
22041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      if(B == path) {
22141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        return -1;
22241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      }
22341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
22441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    else {
22541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      if(((A - path) + 1) == (B - path)) {
22641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        return 1;
22741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      }
22841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
22941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  }
23041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  return 0;
23141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
23241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
23341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
23441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Add a path component, by appending stuff to buffer.
23541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
23641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    NUL-terminated string with no more than MAXPATHLEN characters (not counting
23741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    the trailing NUL).  It's a fatal error if it contains a string longer than
23841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    that (callers must be careful!).  If these requirements are met, it's
23941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    guaranteed that buffer will still be a NUL-terminated string with no more
24041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    than MAXPATHLEN characters at exit.  If stuff is too long, only as much of
24141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    stuff as fits will be appended.
24241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
24341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in,out]    buffer    The path to be extended.
24441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in]        stuff     The stuff to join onto the path.
24541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm*/
24641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic void
24741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmjoinpath(char *buffer, char *stuff)
24841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
24941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  size_t n, k;
25041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
25141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  k = 0;
25241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  if (is_absolute(stuff) == 1) {
25341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    n = 0;
25441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  }
25541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  else {
25641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    n = strlen(buffer);
25741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if(n == 0) {
25841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      strncpy(buffer, volume_name, MAXPATHLEN);
25941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      n = strlen(buffer);
26041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
26141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    /* We must not use an else clause here because we want to test n again.
26241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        volume_name may have been empty.
26341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    */
26441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (n > 0 && n < MAXPATHLEN) {
26541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      if(!is_sep(buffer[n-1])) {
26641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        buffer[n++] = SEP;
26741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      }
26841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      if(is_sep(stuff[0]))   ++stuff;
26941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
27041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  }
27141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  if (n > MAXPATHLEN)
27241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Py_FatalError("buffer overflow in getpath.c's joinpath()");
27341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  k = strlen(stuff);
27441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  if (n + k > MAXPATHLEN)
27541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    k = MAXPATHLEN - n;
27641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  strncpy(buffer+n, stuff, k);
27741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  buffer[n+k] = '\0';
27841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
27941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
28041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Is filename an executable file?
28141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
28241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    An executable file:
28341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      1) exists
28441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      2) is a file, not a directory
28541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      3) has a name ending with ".efi"
28641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      4) Only has a single '.' in the name.
28741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
28841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    If basename(filename) does not contain a '.', append ".efi" to filename
28941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    If filename ends in ".efi", it is executable, else it isn't.
29041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
29141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    This routine is used to when searching for the file named by argv[0].
29241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    As such, there is no need to search for extensions other than ".efi".
29341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
29441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in]    filename      The name of the file to test.  It may, or may not, have an extension.
29541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
29641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval       0     filename already has a path other than ".efi", or it doesn't exist, or is a directory.
29741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @retval       1     filename refers to an executable file.
29841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
29941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic int
30041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmisxfile(char *filename)
30141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
30241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    struct stat  buf;
30341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char        *bn;
30441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char        *newbn;
30541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    int          bnlen;
30641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
30741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    bn = basename(filename);            // Separate off the file name component
30841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    reduce(filename);                   // and isolate the path component
30941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    bnlen = strlen(bn);
31041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    newbn = strrchr(bn, '.');           // Does basename contain a period?
31141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if(newbn == NULL) {                   // Does NOT contain a period.
31241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      newbn = &bn[bnlen];
31341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      strncpyX(newbn, ".efi", MAXPATHLEN - bnlen);    // append ".efi" to basename
31441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      bnlen += 4;
31541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
31641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    else if(strcmp(newbn, ".efi") != 0) {
31741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      return 0;                         // File can not be executable.
31841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
31941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    joinpath(filename, bn);             // Stitch path and file name back together
32041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
32141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (stat(filename, &buf) != 0) {    // Now, verify that file exists
32241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      return 0;
32341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
32441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if(S_ISDIR(buf.st_mode)) {          // And it is not a directory.
32541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      return 0;
32641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
32741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
32841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    return 1;
32941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
33041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
33141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Copy p into path, ensuring that the result is an absolute path.
33241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
33341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    copy_absolute requires that path be allocated at least
33441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes.
33541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
33641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[out]     path    Destination to receive the absolute path.
33741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in]      p       Path to be tested and possibly converted.
33841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
33941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic void
34041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmcopy_absolute(char *path, char *p)
34141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
34241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  if (is_absolute(p) == 1)
34341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        strcpy(path, p);
34441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  else {
34541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (!getcwd(path, MAXPATHLEN)) {
34641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      /* unable to get the current directory */
34741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      if(volume_name[0] != 0) {
34841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        strcpy(path, volume_name);
34941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        joinpath(path, p);
35041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      }
35141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      else
35241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        strcpy(path, p);
35341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      return;
35441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
35541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (p[0] == '.' && is_sep(p[1]))
35641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        p += 2;
35741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    joinpath(path, p);
35841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  }
35941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
36041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
36141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Modify path so that the result is an absolute path.
36241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes.
36341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
36441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in,out]    path    The path to be made absolute.
36541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm*/
36641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic void
36741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmabsolutize(char *path)
36841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
36941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char buffer[MAXPATHLEN + 1];
37041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
37141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (is_absolute(path) == 1)
37241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        return;
37341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    copy_absolute(buffer, path);
37441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    strcpy(path, buffer);
37541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
37641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
37741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Extract the volume name from a path.
37841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
37941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[out]   Dest    Pointer to location in which to store the extracted volume name.
38041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    @param[in]    path    Pointer to the path to extract the volume name from.
38141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
38241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic void
38341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmset_volume(char *Dest, char *path)
38441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
38541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  size_t    VolLen;
38641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
38741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  if(is_absolute(path)) {
38841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    VolLen = strcspn(path, "/\\:");
38941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if((VolLen != 0) && (path[VolLen] == ':')) {
39041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      (void) strncpyX(Dest, path, VolLen + 1);
39141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
39241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm  }
39341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
39441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
39541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
39641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** Determine paths.
39741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
39841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Two directories must be found, the platform independent directory
39941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    (prefix), containing the common .py and .pyc files, and the platform
40041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    dependent directory (exec_prefix), containing the shared library
40141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    modules.  Note that prefix and exec_prefix are the same directory
40241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    for UEFI installations.
40341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
40441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Separate searches are carried out for prefix and exec_prefix.
40541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Each search tries a number of different locations until a ``landmark''
40641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    file or directory is found.  If no prefix or exec_prefix is found, a
40741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    warning message is issued and the preprocessor defined PREFIX and
40841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    EXEC_PREFIX are used (even though they may not work); python carries on
40941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    as best as is possible, but some imports may fail.
41041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
41141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Before any searches are done, the location of the executable is
41241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    determined.  If argv[0] has one or more slashes in it, it is used
41341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    unchanged.  Otherwise, it must have been invoked from the shell's path,
41441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    so we search %PATH% for the named executable and use that.  If the
41541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    executable was not found on %PATH% (or there was no %PATH% environment
41641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    variable), the original argv[0] string is used.
41741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
41841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Finally, argv0_path is set to the directory containing the executable
41941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    (i.e. the last component is stripped).
42041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
42141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    With argv0_path in hand, we perform a number of steps.  The same steps
42241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    are performed for prefix and for exec_prefix, but with a different
42341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    landmark.
42441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
42541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    The prefix landmark will always be lib/python.VERSION/os.py and the
42641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    exec_prefix will always be lib/python.VERSION/dynaload, where VERSION
42741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    is Python's version number as defined at the beginning of this file.
42841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
42941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    First. See if the %PYTHONHOME% environment variable points to the
43041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    installed location of the Python libraries.  If %PYTHONHOME% is set, then
43141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    it points to prefix and exec_prefix.  %PYTHONHOME% can be a single
43241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    directory, which is used for both, or the prefix and exec_prefix
43341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    directories separated by the DELIM character.
43441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
43541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Next. Search the directories pointed to by the preprocessor variables
43641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    PREFIX and EXEC_PREFIX.  These paths are prefixed with the volume name
43741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    extracted from argv0_path.  The volume names correspond to the UEFI
43841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    shell "map" names.
43941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
44041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    That's it!
44141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
44241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Well, almost.  Once we have determined prefix and exec_prefix, the
44341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    preprocessor variable PYTHONPATH is used to construct a path.  Each
44441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    relative path on PYTHONPATH is prefixed with prefix.  Then the directory
44541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    containing the shared library modules is appended.  The environment
44641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    variable $PYTHONPATH is inserted in front of it all.  Finally, the
44741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    prefix and exec_prefix globals are tweaked so they reflect the values
44841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    expected by other code, by stripping the "lib/python$VERSION/..." stuff
44941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    off.  This seems to make more sense given that currently the only
45041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    known use of sys.prefix and sys.exec_prefix is for the ILU installation
45141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    process to find the installed Python tree.
45241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
45341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    The final, fully resolved, paths should look something like:
45441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      fs0:/Efi/Tools/python.efi
45541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      fs0:/Efi/StdLib/lib/python27
45641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      fs0:/Efi/StdLib/lib/python27/dynaload
45741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
45841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
45941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmstatic void
46041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmcalculate_path(void)
46141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
46241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    extern char *Py_GetProgramName(void);
46341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
46441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    static char delimiter[2] = {DELIM, '\0'};
46541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    static char separator[2] = {SEP, '\0'};
46641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char *pythonpath = PYTHONPATH;
46741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char *rtpypath = Py_GETENV("PYTHONPATH");
46841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    //char *home = Py_GetPythonHome();
46941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char *path = getenv("PATH");
47041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char *prog = Py_GetProgramName();
47141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char argv0_path[MAXPATHLEN+1];
47241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char zip_path[MAXPATHLEN+1];
47341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char *buf;
47441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    size_t bufsz;
47541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    size_t prefixsz;
47641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    char *defpath;
47741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
47841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
47941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/* ###########################################################################
48041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      Determine path to the Python.efi binary.
48141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      Produces progpath, argv0_path, and volume_name.
48241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm########################################################################### */
48341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
48441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    /* If there is no slash in the argv0 path, then we have to
48541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm     * assume python is on the user's $PATH, since there's no
48641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm     * other way to find a directory to start the search from.  If
48741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm     * $PATH isn't exported, you lose.
48841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm     */
48941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (strchr(prog, SEP))
49041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            strncpy(progpath, prog, MAXPATHLEN);
49141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    else if (path) {
49241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      while (1) {
49341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        char *delim = strchr(path, DELIM);
49441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
49541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        if (delim) {
49641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                size_t len = delim - path;
49741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                if (len > MAXPATHLEN)
49841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                        len = MAXPATHLEN;
49941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                strncpy(progpath, path, len);
50041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                *(progpath + len) = '\0';
50141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        }
50241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        else
50341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                strncpy(progpath, path, MAXPATHLEN);
50441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
50541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        joinpath(progpath, prog);
50641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        if (isxfile(progpath))
50741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                break;
50841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
50941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        if (!delim) {
51041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                progpath[0] = '\0';
51141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                break;
51241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        }
51341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        path = delim + 1;
51441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      }
51541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
51641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    else
51741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            progpath[0] = '\0';
51841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if ( (!is_absolute(progpath)) && (progpath[0] != '\0') )
51941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            absolutize(progpath);
52041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    strncpy(argv0_path, progpath, MAXPATHLEN);
52141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    argv0_path[MAXPATHLEN] = '\0';
52241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    set_volume(volume_name, argv0_path);
52341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
52441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    reduce(argv0_path);
52541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    /* At this point, argv0_path is guaranteed to be less than
52641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm       MAXPATHLEN bytes long.
52741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    */
52841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
52941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/* ###########################################################################
53041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      Build the FULL prefix string, including volume name.
53141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      This is the full path to the platform independent libraries.
53241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm########################################################################### */
53341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
53441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        strncpy(prefix, volume_name, MAXPATHLEN);
53541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        joinpath(prefix, PREFIX);
53641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        joinpath(prefix, lib_python);
53741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
53841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/* ###########################################################################
53941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      Build the FULL path to the zipped-up Python library.
54041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm########################################################################### */
54141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
54241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    strncpy(zip_path, prefix, MAXPATHLEN);
54341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    zip_path[MAXPATHLEN] = '\0';
544b410d6e4ce58c177569d42b51772f7bb239a24a3darylm    reduce(zip_path);
54541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    joinpath(zip_path, "python00.zip");
54641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    bufsz = strlen(zip_path);   /* Replace "00" with version */
54741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    zip_path[bufsz - 6] = VERSION[0];
54841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    zip_path[bufsz - 5] = VERSION[1];
54941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
55041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/* ###########################################################################
55141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      Build the FULL path to dynamically loadable libraries.
55241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm########################################################################### */
55341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
55441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        strncpy(exec_prefix, volume_name, MAXPATHLEN);
55541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        joinpath(exec_prefix, EXEC_PREFIX);
55641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        joinpath(exec_prefix, lib_python);
557b410d6e4ce58c177569d42b51772f7bb239a24a3darylm        joinpath(exec_prefix, "lib-dynload");
55841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
55941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/* ###########################################################################
56041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      Build the module search path.
56141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm########################################################################### */
56241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
56341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    /* Reduce prefix and exec_prefix to their essence,
56441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm     * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
56541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm     * If we're loading relative to the build directory,
56641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm     * return the compiled-in defaults instead.
56741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm     */
56841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    reduce(prefix);
56941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    reduce(prefix);
57041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    /* The prefix is the root directory, but reduce() chopped
57141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm     * off the "/". */
57241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (!prefix[0]) {
57341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      strcpy(prefix, volume_name);
57441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
57541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    bufsz = strlen(prefix);
57641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if(prefix[bufsz-1] == ':') {
57741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      prefix[bufsz] = SEP;
57841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm      prefix[bufsz+1] = 0;
57941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
58041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
58141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    /* Calculate size of return buffer.
58241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm     */
58341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    defpath = pythonpath;
58441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    bufsz = 0;
58541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
58641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (rtpypath)
58741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        bufsz += strlen(rtpypath) + 1;
58841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
58941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    prefixsz = strlen(prefix) + 1;
59041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
59141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    while (1) {
59241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        char *delim = strchr(defpath, DELIM);
59341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
59441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        if (is_absolute(defpath) == 0)
59541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            /* Paths are relative to prefix */
59641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            bufsz += prefixsz;
59741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
59841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        if (delim)
59941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            bufsz += delim - defpath + 1;
60041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        else {
60141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            bufsz += strlen(defpath) + 1;
60241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            break;
60341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        }
60441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        defpath = delim + 1;
60541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
60641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
60741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    bufsz += strlen(zip_path) + 1;
60841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    bufsz += strlen(exec_prefix) + 1;
60941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
61041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    /* This is the only malloc call in this file */
61141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    buf = (char *)PyMem_Malloc(bufsz);
61241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
61341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (buf == NULL) {
61441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        /* We can't exit, so print a warning and limp along */
61541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        fprintf(stderr, "Not enough memory for dynamic PYTHONPATH.\n");
61641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        fprintf(stderr, "Using default static PYTHONPATH.\n");
61741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        module_search_path = PYTHONPATH;
61841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
61941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    else {
62041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        /* Run-time value of $PYTHONPATH goes first */
62141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        if (rtpypath) {
62241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            strcpy(buf, rtpypath);
62341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            strcat(buf, delimiter);
62441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        }
62541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        else
62641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            buf[0] = '\0';
62741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
62841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        /* Next is the default zip path */
62941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        strcat(buf, zip_path);
63041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        strcat(buf, delimiter);
63141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
63241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        /* Next goes merge of compile-time $PYTHONPATH with
63341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm         * dynamically located prefix.
63441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm         */
63541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        defpath = pythonpath;
63641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        while (1) {
63741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            char *delim = strchr(defpath, DELIM);
63841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
63941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            if (is_absolute(defpath) != 1) {
64041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                strcat(buf, prefix);
64141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                strcat(buf, separator);
64241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            }
64341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
64441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            if (delim) {
64541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                size_t len = delim - defpath + 1;
64641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                size_t end = strlen(buf) + len;
64741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                strncat(buf, defpath, len);
64841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                *(buf + end) = '\0';
64941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            }
65041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            else {
65141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                strcat(buf, defpath);
65241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm                break;
65341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            }
65441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            defpath = delim + 1;
65541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        }
65641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        strcat(buf, delimiter);
65741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
65841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        /* Finally, on goes the directory for dynamic-load modules */
65941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        strcat(buf, exec_prefix);
66041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
66141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        /* And publish the results */
66241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        module_search_path = buf;
66341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    }
66441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        /*  At this point, exec_prefix is set to VOL:/Efi/StdLib/lib/python.27/dynalib.
66541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            We want to get back to the root value, so we have to remove the final three
66641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            segments to get VOL:/Efi/StdLib.  Because we don't know what VOL is, and
66741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm            EXEC_PREFIX is also indeterminate, we just remove the three final segments.
66841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        */
66941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        reduce(exec_prefix);
67041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        reduce(exec_prefix);
67141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        reduce(exec_prefix);
67241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        if (!exec_prefix[0]) {
67341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm          strcpy(exec_prefix, volume_name);
67441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        }
67541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        bufsz = strlen(exec_prefix);
67641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        if(exec_prefix[bufsz-1] == ':') {
67741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm          exec_prefix[bufsz] = SEP;
67841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm          exec_prefix[bufsz+1] = 0;
67941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        }
68041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__, __LINE__, module_search_path);
68141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: prefix             = \"%s\"\n", __func__, __LINE__, prefix);
68241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: exec_prefix        = \"%s\"\n", __func__, __LINE__, exec_prefix);
68341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath           = \"%s\"\n", __func__, __LINE__, progpath);
68441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
68541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
68641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
68741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/* External interface */
68841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
68941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmchar *
69041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmPy_GetPath(void)
69141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
69241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (!module_search_path)
69341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        calculate_path();
69441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    return module_search_path;
69541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
69641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
69741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmchar *
69841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmPy_GetPrefix(void)
69941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
70041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (!module_search_path)
70141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        calculate_path();
70241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    return prefix;
70341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
70441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
70541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmchar *
70641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmPy_GetExecPrefix(void)
70741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
70841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (!module_search_path)
70941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        calculate_path();
71041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    return exec_prefix;
71141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
71241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
71341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmchar *
71441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylmPy_GetProgramFullPath(void)
71541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm{
71641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    if (!module_search_path)
71741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm        calculate_path();
71841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    return progpath;
71941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
72041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
72141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
72241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#ifdef __cplusplus
72341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm}
72441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm#endif
72541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
726