Back to index

python3.2  3.2.2
Defines | Functions | Variables
getpathp.c File Reference
#include "Python.h"
#include "osdefs.h"
#include <wchar.h>
#include <string.h>

Go to the source code of this file.

Defines

#define LANDMARK   L"lib\\os.py"

Functions

static int is_sep (wchar_t ch)
static void reduce (wchar_t *dir)
static int exists (wchar_t *filename)
static int ismodule (wchar_t *filename)
static void join (wchar_t *buffer, wchar_t *stuff)
static int gotlandmark (wchar_t *landmark)
static int search_for_prefix (wchar_t *argv0_path, wchar_t *landmark)
static void get_progpath (void)
static void calculate_path (void)
void Py_SetPath (const wchar_t *path)
wchar_t * Py_GetPath (void)
wchar_t * Py_GetPrefix (void)
wchar_t * Py_GetExecPrefix (void)
wchar_t * Py_GetProgramFullPath (void)
int _Py_CheckPython3 ()

Variables

static wchar_t prefix [MAXPATHLEN+1]
static wchar_t progpath [MAXPATHLEN+1]
static wchar_t dllpath [MAXPATHLEN+1]
static wchar_t * module_search_path = NULL
static int python3_checked = 0
static HANDLE hPython3

Define Documentation

#define LANDMARK   L"lib\\os.py"

Definition at line 91 of file getpathp.c.


Function Documentation

Definition at line 720 of file getpathp.c.

{
    wchar_t py3path[MAXPATHLEN+1];
    wchar_t *s;
    if (python3_checked)
        return hPython3 != NULL;
    python3_checked = 1;

    /* If there is a python3.dll next to the python3y.dll,
       assume this is a build tree; use that DLL */
    wcscpy(py3path, dllpath);
    s = wcsrchr(py3path, L'\\');
    if (!s)
        s = py3path;
    wcscpy(s, L"\\python3.dll");
    hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
    if (hPython3 != NULL)
        return 1;

    /* Check sys.prefix\DLLs\python3.dll */
    wcscpy(py3path, Py_GetPrefix());
    wcscat(py3path, L"\\DLLs\\python3.dll");
    hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
    return hPython3 != NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void calculate_path ( void  ) [static]

Definition at line 427 of file getpathp.c.

{
    wchar_t argv0_path[MAXPATHLEN+1];
    wchar_t *buf;
    size_t bufsz;
    wchar_t *pythonhome = Py_GetPythonHome();
    wchar_t *envpath = NULL;

#ifdef MS_WINDOWS
    int skiphome, skipdefault;
    wchar_t *machinepath = NULL;
    wchar_t *userpath = NULL;
    wchar_t zip_path[MAXPATHLEN+1];
    size_t len;

    if (!Py_IgnoreEnvironmentFlag) {
        envpath = _wgetenv(L"PYTHONPATH");
    }
#else
    char *_envpath = Py_GETENV("PYTHONPATH");
    wchar_t wenvpath[MAXPATHLEN+1];
    if (_envpath) {
        size_t r = mbstowcs(wenvpath, _envpath, MAXPATHLEN+1);
        envpath = wenvpath;
        if (r == (size_t)-1 || r >= MAXPATHLEN)
            envpath = NULL;
    }
#endif

    get_progpath();
    /* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */
    wcscpy(argv0_path, progpath);
    reduce(argv0_path);
    if (pythonhome == NULL || *pythonhome == '\0') {
        if (search_for_prefix(argv0_path, LANDMARK))
            pythonhome = prefix;
        else
            pythonhome = NULL;
    }
    else
        wcsncpy(prefix, pythonhome, MAXPATHLEN);

    if (envpath && *envpath == '\0')
        envpath = NULL;


#ifdef MS_WINDOWS
    /* Calculate zip archive path */
    if (dllpath[0])             /* use name of python DLL */
        wcsncpy(zip_path, dllpath, MAXPATHLEN);
    else                        /* use name of executable program */
        wcsncpy(zip_path, progpath, MAXPATHLEN);
    zip_path[MAXPATHLEN] = '\0';
    len = wcslen(zip_path);
    if (len > 4) {
        zip_path[len-3] = 'z';          /* change ending to "zip" */
        zip_path[len-2] = 'i';
        zip_path[len-1] = 'p';
    }
    else {
        zip_path[0] = 0;
    }

    skiphome = pythonhome==NULL ? 0 : 1;
#ifdef Py_ENABLE_SHARED
    machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome);
    userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome);
#endif
    /* We only use the default relative PYTHONPATH if we havent
       anything better to use! */
    skipdefault = envpath!=NULL || pythonhome!=NULL || \
                  machinepath!=NULL || userpath!=NULL;
#endif

    /* We need to construct a path from the following parts.
       (1) the PYTHONPATH environment variable, if set;
       (2) for Win32, the zip archive file path;
       (3) for Win32, the machinepath and userpath, if set;
       (4) the PYTHONPATH config macro, with the leading "."
           of each component replaced with pythonhome, if set;
       (5) the directory containing the executable (argv0_path).
       The length calculation calculates #4 first.
       Extra rules:
       - If PYTHONHOME is set (in any way) item (3) is ignored.
       - If registry values are used, (4) and (5) are ignored.
    */

    /* Calculate size of return buffer */
    if (pythonhome != NULL) {
        wchar_t *p;
        bufsz = 1;
        for (p = PYTHONPATH; *p; p++) {
            if (*p == DELIM)
                bufsz++; /* number of DELIM plus one */
        }
        bufsz *= wcslen(pythonhome);
    }
    else
        bufsz = 0;
    bufsz += wcslen(PYTHONPATH) + 1;
    bufsz += wcslen(argv0_path) + 1;
#ifdef MS_WINDOWS
    if (userpath)
        bufsz += wcslen(userpath) + 1;
    if (machinepath)
        bufsz += wcslen(machinepath) + 1;
    bufsz += wcslen(zip_path) + 1;
#endif
    if (envpath != NULL)
        bufsz += wcslen(envpath) + 1;

    module_search_path = buf = malloc(bufsz*sizeof(wchar_t));
    if (buf == NULL) {
        /* We can't exit, so print a warning and limp along */
        fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
        if (envpath) {
            fprintf(stderr, "Using environment $PYTHONPATH.\n");
            module_search_path = envpath;
        }
        else {
            fprintf(stderr, "Using default static path.\n");
            module_search_path = PYTHONPATH;
        }
#ifdef MS_WINDOWS
        if (machinepath)
            free(machinepath);
        if (userpath)
            free(userpath);
#endif /* MS_WINDOWS */
        return;
    }

    if (envpath) {
        wcscpy(buf, envpath);
        buf = wcschr(buf, L'\0');
        *buf++ = DELIM;
    }
#ifdef MS_WINDOWS
    if (zip_path[0]) {
        wcscpy(buf, zip_path);
        buf = wcschr(buf, L'\0');
        *buf++ = DELIM;
    }
    if (userpath) {
        wcscpy(buf, userpath);
        buf = wcschr(buf, L'\0');
        *buf++ = DELIM;
        free(userpath);
    }
    if (machinepath) {
        wcscpy(buf, machinepath);
        buf = wcschr(buf, L'\0');
        *buf++ = DELIM;
        free(machinepath);
    }
    if (pythonhome == NULL) {
        if (!skipdefault) {
            wcscpy(buf, PYTHONPATH);
            buf = wcschr(buf, L'\0');
        }
    }
#else
    if (pythonhome == NULL) {
        wcscpy(buf, PYTHONPATH);
        buf = wcschr(buf, L'\0');
    }
#endif /* MS_WINDOWS */
    else {
        wchar_t *p = PYTHONPATH;
        wchar_t *q;
        size_t n;
        for (;;) {
            q = wcschr(p, DELIM);
            if (q == NULL)
                n = wcslen(p);
            else
                n = q-p;
            if (p[0] == '.' && is_sep(p[1])) {
                wcscpy(buf, pythonhome);
                buf = wcschr(buf, L'\0');
                p++;
                n--;
            }
            wcsncpy(buf, p, n);
            buf += n;
            if (q == NULL)
                break;
            *buf++ = DELIM;
            p = q+1;
        }
    }
    if (argv0_path) {
        *buf++ = DELIM;
        wcscpy(buf, argv0_path);
        buf = wcschr(buf, L'\0');
    }
    *buf = L'\0';
    /* Now to pull one last hack/trick.  If sys.prefix is
       empty, then try and find it somewhere on the paths
       we calculated.  We scan backwards, as our general policy
       is that Python core directories are at the *end* of
       sys.path.  We assume that our "lib" directory is
       on the path, and that our 'prefix' directory is
       the parent of that.
    */
    if (*prefix==L'\0') {
        wchar_t lookBuf[MAXPATHLEN+1];
        wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */
        while (1) {
            Py_ssize_t nchars;
            wchar_t *lookEnd = look;
            /* 'look' will end up one character before the
               start of the path in question - even if this
               is one character before the start of the buffer
            */
            while (look >= module_search_path && *look != DELIM)
                look--;
            nchars = lookEnd-look;
            wcsncpy(lookBuf, look+1, nchars);
            lookBuf[nchars] = L'\0';
            /* Up one level to the parent */
            reduce(lookBuf);
            if (search_for_prefix(lookBuf, LANDMARK)) {
                break;
            }
            /* If we are out of paths to search - give up */
            if (look < module_search_path)
                break;
            look--;
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int exists ( wchar_t *  filename) [static]

Definition at line 124 of file getpathp.c.

{
    return GetFileAttributesW(filename) != 0xFFFFFFFF;
}

Here is the caller graph for this function:

static void get_progpath ( void  ) [static]

Definition at line 363 of file getpathp.c.

{
    extern wchar_t *Py_GetProgramName(void);
    wchar_t *path = _wgetenv(L"PATH");
    wchar_t *prog = Py_GetProgramName();

#ifdef MS_WINDOWS
#ifdef Py_ENABLE_SHARED
    extern HANDLE PyWin_DLLhModule;
    /* static init of progpath ensures final char remains \0 */
    if (PyWin_DLLhModule)
        if (!GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN))
            dllpath[0] = 0;
#else
    dllpath[0] = 0;
#endif
    if (GetModuleFileNameW(NULL, progpath, MAXPATHLEN))
        return;
#endif
    if (prog == NULL || *prog == '\0')
        prog = L"python";

    /* 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.
     */
#ifdef ALTSEP
    if (wcschr(prog, SEP) || wcschr(prog, ALTSEP))
#else
    if (wcschr(prog, SEP))
#endif
        wcsncpy(progpath, prog, MAXPATHLEN);
    else if (path) {
        while (1) {
            wchar_t *delim = wcschr(path, DELIM);

            if (delim) {
                size_t len = delim - path;
                /* ensure we can't overwrite buffer */
                len = min(MAXPATHLEN,len);
                wcsncpy(progpath, path, len);
                *(progpath + len) = '\0';
            }
            else
                wcsncpy(progpath, path, MAXPATHLEN);

            /* join() is safe for MAXPATHLEN+1 size buffer */
            join(progpath, prog);
            if (exists(progpath))
                break;

            if (!delim) {
                progpath[0] = '\0';
                break;
            }
            path = delim + 1;
        }
    }
    else
        progpath[0] = '\0';
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gotlandmark ( wchar_t *  landmark) [static]

Definition at line 181 of file getpathp.c.

{
    int ok;
    Py_ssize_t n;

    n = wcslen(prefix);
    join(prefix, landmark);
    ok = ismodule(prefix);
    prefix[n] = '\0';
    return ok;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int is_sep ( wchar_t  ch) [static]

Definition at line 101 of file getpathp.c.

{
#ifdef ALTSEP
    return ch == SEP || ch == ALTSEP;
#else
    return ch == SEP;
#endif
}

Here is the caller graph for this function:

static int ismodule ( wchar_t *  filename) [static]

Definition at line 133 of file getpathp.c.

{
    if (exists(filename))
        return 1;

    /* Check for the compiled version of prefix. */
    if (wcslen(filename) < MAXPATHLEN) {
        wcscat(filename, Py_OptimizeFlag ? L"o" : L"c");
        if (exists(filename))
            return 1;
    }
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void join ( wchar_t *  buffer,
wchar_t *  stuff 
) [static]

Definition at line 157 of file getpathp.c.

{
    size_t n, k;
    if (is_sep(stuff[0]))
        n = 0;
    else {
        n = wcslen(buffer);
        if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
            buffer[n++] = SEP;
    }
    if (n > MAXPATHLEN)
        Py_FatalError("buffer overflow in getpathp.c's joinpath()");
    k = wcslen(stuff);
    if (n + k > MAXPATHLEN)
        k = MAXPATHLEN - n;
    wcsncpy(buffer+n, stuff, k);
    buffer[n+k] = '\0';
}

Here is the call graph for this function:

Here is the caller graph for this function:

wchar_t* Py_GetExecPrefix ( void  )

Definition at line 698 of file getpathp.c.

{
    return Py_GetPrefix();
}

Here is the call graph for this function:

wchar_t* Py_GetPath ( void  )

Definition at line 682 of file getpathp.c.

Here is the call graph for this function:

wchar_t* Py_GetPrefix ( void  )

Definition at line 690 of file getpathp.c.

Here is the call graph for this function:

wchar_t* Py_GetProgramFullPath ( void  )

Definition at line 704 of file getpathp.c.

Here is the call graph for this function:

void Py_SetPath ( const wchar_t *  path)

Definition at line 664 of file getpathp.c.

{
    if (module_search_path != NULL) {
        free(module_search_path);
        module_search_path = NULL;
    }
    if (path != NULL) {
        extern wchar_t *Py_GetProgramName(void);
        wchar_t *prog = Py_GetProgramName();
        wcsncpy(progpath, prog, MAXPATHLEN);
        prefix[0] = L'\0';
        module_search_path = malloc((wcslen(path) + 1) * sizeof(wchar_t));
        if (module_search_path != NULL)
            wcscpy(module_search_path, path);
       }
}

Here is the call graph for this function:

static void reduce ( wchar_t *  dir) [static]

Definition at line 114 of file getpathp.c.

{
    size_t i = wcslen(dir);
    while (i > 0 && !is_sep(dir[i]))
        --i;
    dir[i] = '\0';
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int search_for_prefix ( wchar_t *  argv0_path,
wchar_t *  landmark 
) [static]

Definition at line 196 of file getpathp.c.

{
    /* Search from argv0_path, until landmark is found */
    wcscpy(prefix, argv0_path);
    do {
        if (gotlandmark(landmark))
            return 1;
        reduce(prefix);
    } while (prefix[0]);
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

wchar_t dllpath[MAXPATHLEN+1] [static]

Definition at line 96 of file getpathp.c.

HANDLE hPython3 [static]

Definition at line 718 of file getpathp.c.

wchar_t* module_search_path = NULL [static]

Definition at line 97 of file getpathp.c.

wchar_t prefix[MAXPATHLEN+1] [static]

Definition at line 94 of file getpathp.c.

wchar_t progpath[MAXPATHLEN+1] [static]

Definition at line 95 of file getpathp.c.

int python3_checked = 0 [static]

Definition at line 717 of file getpathp.c.