static void calculate_path(void) { wchar_t argv0_path[MAXPATHLEN+1]; wchar_t *buf; size_t bufsz; wchar_t *pythonhome = Py_GetPythonHome(); wchar_t *envpath = NULL; int skiphome, skipdefault; wchar_t *machinepath = NULL; wchar_t *userpath = NULL; wchar_t zip_path[MAXPATHLEN+1]; if (!Py_IgnoreEnvironmentFlag) { envpath = _wgetenv(L"PYTHONPATH"); } get_progpath(); /* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */ wcscpy_s(argv0_path, MAXPATHLEN+1, progpath); reduce(argv0_path); /* Search for a sys.path file */ { wchar_t spbuffer[MAXPATHLEN+1]; if ((dllpath[0] && !change_ext(spbuffer, dllpath, L"._pth") && exists(spbuffer)) || (progpath[0] && !change_ext(spbuffer, progpath, L"._pth") && exists(spbuffer))) { if (!read_pth_file(spbuffer, prefix, &Py_IsolatedFlag, &Py_NoSiteFlag)) { return; } } } /* Search for an environment configuration file, first in the executable's directory and then in the parent directory. If found, open it for use when searching for prefixes. */ { wchar_t envbuffer[MAXPATHLEN+1]; wchar_t tmpbuffer[MAXPATHLEN+1]; const wchar_t *env_cfg = L"pyvenv.cfg"; FILE * env_file = NULL; wcscpy_s(envbuffer, MAXPATHLEN+1, argv0_path); join(envbuffer, env_cfg); env_file = _Py_wfopen(envbuffer, L"r"); if (env_file == NULL) { errno = 0; reduce(envbuffer); reduce(envbuffer); join(envbuffer, env_cfg); env_file = _Py_wfopen(envbuffer, L"r"); if (env_file == NULL) { errno = 0; } } if (env_file != NULL) { /* Look for a 'home' variable and set argv0_path to it, if found */ if (find_env_config_value(env_file, L"home", tmpbuffer)) { wcscpy_s(argv0_path, MAXPATHLEN+1, tmpbuffer); } fclose(env_file); env_file = NULL; } } /* Calculate zip archive path from DLL or exe path */ change_ext(zip_path, dllpath[0] ? dllpath : progpath, L".zip"); if (pythonhome == NULL || *pythonhome == '\0') { if (zip_path[0] && exists(zip_path)) { wcscpy_s(prefix, MAXPATHLEN+1, zip_path); reduce(prefix); pythonhome = prefix; } else if (search_for_prefix(argv0_path, LANDMARK)) pythonhome = prefix; else pythonhome = NULL; } else wcscpy_s(prefix, MAXPATHLEN+1, pythonhome); if (envpath && *envpath == '\0') envpath = NULL; 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; /* 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; if (userpath) bufsz += wcslen(userpath) + 1; if (machinepath) bufsz += wcslen(machinepath) + 1; bufsz += wcslen(zip_path) + 1; if (envpath != NULL) bufsz += wcslen(envpath) + 1; module_search_path = buf = PyMem_RawMalloc(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; } PyMem_RawFree(machinepath); PyMem_RawFree(userpath); return; } if (envpath) { if (wcscpy_s(buf, bufsz - (buf - module_search_path), envpath)) Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); *buf++ = DELIM; } if (zip_path[0]) { if (wcscpy_s(buf, bufsz - (buf - module_search_path), zip_path)) Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); *buf++ = DELIM; } if (userpath) { if (wcscpy_s(buf, bufsz - (buf - module_search_path), userpath)) Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); *buf++ = DELIM; PyMem_RawFree(userpath); } if (machinepath) { if (wcscpy_s(buf, bufsz - (buf - module_search_path), machinepath)) Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); *buf++ = DELIM; PyMem_RawFree(machinepath); } if (pythonhome == NULL) { if (!skipdefault) { if (wcscpy_s(buf, bufsz - (buf - module_search_path), PYTHONPATH)) Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); *buf++ = DELIM; } } 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])) { if (wcscpy_s(buf, bufsz - (buf - module_search_path), pythonhome)) Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); buf = wcschr(buf, L'\0'); p++; n--; } wcsncpy(buf, p, n); buf += n; *buf++ = DELIM; if (q == NULL) break; p = q+1; } } if (argv0_path) { wcscpy(buf, argv0_path); buf = wcschr(buf, L'\0'); *buf++ = DELIM; } *(buf - 1) = 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--; } } }
static void calculate_path(void) { char argv0_path[MAXPATHLEN+1]; char *buf; size_t bufsz; char *pythonhome = Py_GetPythonHome(); char *envpath = Py_GETENV("PYTHONPATH"); #ifdef MS_WINDOWS int skiphome, skipdefault; char *machinepath = NULL; char *userpath = NULL; char zip_path[MAXPATHLEN+1]; size_t len; #endif get_progpath(); /* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */ strcpy(argv0_path, progpath); reduce(argv0_path); if (pythonhome == NULL || *pythonhome == '\0') { if (search_for_prefix(argv0_path, LANDMARK)) pythonhome = prefix; else pythonhome = NULL; } else strncpy(prefix, pythonhome, MAXPATHLEN); if (envpath && *envpath == '\0') envpath = NULL; #ifdef MS_WINDOWS /* Calculate zip archive path */ if (dllpath[0]) /* use name of python DLL */ strncpy(zip_path, dllpath, MAXPATHLEN); else /* use name of executable program */ strncpy(zip_path, progpath, MAXPATHLEN); zip_path[MAXPATHLEN] = '\0'; len = strlen(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) { char *p; bufsz = 1; for (p = PYTHONPATH; *p; p++) { if (*p == DELIM) bufsz++; /* number of DELIM plus one */ } bufsz *= strlen(pythonhome); } else bufsz = 0; bufsz += strlen(PYTHONPATH) + 1; bufsz += strlen(argv0_path) + 1; #ifdef MS_WINDOWS if (userpath) bufsz += strlen(userpath) + 1; if (machinepath) bufsz += strlen(machinepath) + 1; bufsz += strlen(zip_path) + 1; #endif if (envpath != NULL) bufsz += strlen(envpath) + 1; module_search_path = buf = malloc(bufsz); 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) { strcpy(buf, envpath); buf = strchr(buf, '\0'); *buf++ = DELIM; } #ifdef MS_WINDOWS if (zip_path[0]) { strcpy(buf, zip_path); buf = strchr(buf, '\0'); *buf++ = DELIM; } if (userpath) { strcpy(buf, userpath); buf = strchr(buf, '\0'); *buf++ = DELIM; free(userpath); } if (machinepath) { strcpy(buf, machinepath); buf = strchr(buf, '\0'); *buf++ = DELIM; free(machinepath); } if (pythonhome == NULL) { if (!skipdefault) { strcpy(buf, PYTHONPATH); buf = strchr(buf, '\0'); } } #else if (pythonhome == NULL) { strcpy(buf, PYTHONPATH); buf = strchr(buf, '\0'); } #endif /* MS_WINDOWS */ else { char *p = PYTHONPATH; char *q; size_t n; for (;;) { q = strchr(p, DELIM); if (q == NULL) n = strlen(p); else n = q-p; if (p[0] == '.' && is_sep(p[1])) { strcpy(buf, pythonhome); buf = strchr(buf, '\0'); p++; n--; } strncpy(buf, p, n); buf += n; if (q == NULL) break; *buf++ = DELIM; p = q+1; } } if (argv0_path) { *buf++ = DELIM; strcpy(buf, argv0_path); buf = strchr(buf, '\0'); } *buf = '\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=='\0') { char lookBuf[MAXPATHLEN+1]; char *look = buf - 1; /* 'buf' is at the end of the buffer */ while (1) { Py_ssize_t nchars; char *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; strncpy(lookBuf, look+1, nchars); lookBuf[nchars] = '\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--; } } }
static _PyInitError calculate_module_search_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config, wchar_t *prefix) { int skiphome = calculate->home==NULL ? 0 : 1; #ifdef Py_ENABLE_SHARED calculate->machine_path = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome); calculate->user_path = getpythonregpath(HKEY_CURRENT_USER, skiphome); #endif /* We only use the default relative PYTHONPATH if we haven't anything better to use! */ int skipdefault = (core_config->module_search_path_env != NULL || calculate->home != NULL || calculate->machine_path != NULL || calculate->user_path != NULL); /* 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 machine_path and user_path, if set; (4) the PYTHONPATH config macro, with the leading "." of each component replaced with home, 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 */ size_t bufsz = 0; if (calculate->home != NULL) { const wchar_t *p; bufsz = 1; for (p = PYTHONPATH; *p; p++) { if (*p == DELIM) { bufsz++; /* number of DELIM plus one */ } } bufsz *= wcslen(calculate->home); } bufsz += wcslen(PYTHONPATH) + 1; bufsz += wcslen(calculate->argv0_path) + 1; if (calculate->user_path) { bufsz += wcslen(calculate->user_path) + 1; } if (calculate->machine_path) { bufsz += wcslen(calculate->machine_path) + 1; } bufsz += wcslen(calculate->zip_path) + 1; if (core_config->module_search_path_env != NULL) { bufsz += wcslen(core_config->module_search_path_env) + 1; } wchar_t *buf, *start_buf; buf = PyMem_RawMalloc(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 (core_config->module_search_path_env) { fprintf(stderr, "Using environment $PYTHONPATH.\n"); config->module_search_path = core_config->module_search_path_env; } else { fprintf(stderr, "Using default static path.\n"); config->module_search_path = PYTHONPATH; } return _Py_INIT_OK(); } start_buf = buf; if (core_config->module_search_path_env) { if (wcscpy_s(buf, bufsz - (buf - start_buf), core_config->module_search_path_env)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); *buf++ = DELIM; } if (calculate->zip_path[0]) { if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->zip_path)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); *buf++ = DELIM; } if (calculate->user_path) { if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->user_path)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); *buf++ = DELIM; } if (calculate->machine_path) { if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->machine_path)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); *buf++ = DELIM; } if (calculate->home == NULL) { if (!skipdefault) { if (wcscpy_s(buf, bufsz - (buf - start_buf), PYTHONPATH)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); *buf++ = DELIM; } } else { const wchar_t *p = PYTHONPATH; const 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])) { if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->home)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); p++; n--; } wcsncpy(buf, p, n); buf += n; *buf++ = DELIM; if (q == NULL) { break; } p = q+1; } } if (calculate->argv0_path) { wcscpy(buf, calculate->argv0_path); buf = wcschr(buf, L'\0'); *buf++ = DELIM; } *(buf - 1) = 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[0] == L'\0') { wchar_t lookBuf[MAXPATHLEN+1]; const wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */ while (1) { Py_ssize_t nchars; const 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 >= start_buf && *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(prefix, lookBuf, LANDMARK)) { break; } /* If we are out of paths to search - give up */ if (look < start_buf) { break; } look--; } } config->module_search_path = start_buf; return _Py_INIT_OK(); }