Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 54 additions & 38 deletions Modules/getpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,7 @@ extern "C" {

typedef struct {
wchar_t *path_env; /* PATH environment variable */
wchar_t *home; /* PYTHONHOME environment variable */
wchar_t *module_search_path_env; /* PYTHONPATH environment variable */

wchar_t *program_name; /* Program name */
wchar_t *pythonpath; /* PYTHONPATH define */
wchar_t *prefix; /* PREFIX define */
wchar_t *exec_prefix; /* EXEC_PREFIX define */
Expand Down Expand Up @@ -360,14 +357,15 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value)
bytes long.
*/
static int
search_for_prefix(PyCalculatePath *calculate, wchar_t *prefix)
search_for_prefix(const _PyMainInterpreterConfig *main_config,
PyCalculatePath *calculate, wchar_t *prefix)
{
size_t n;
wchar_t *vpath;

/* If PYTHONHOME is set, we believe it unconditionally */
if (calculate->home) {
wcsncpy(prefix, calculate->home, MAXPATHLEN);
if (main_config->home) {
wcsncpy(prefix, main_config->home, MAXPATHLEN);
prefix[MAXPATHLEN] = L'\0';
wchar_t *delim = wcschr(prefix, DELIM);
if (delim) {
Expand Down Expand Up @@ -426,9 +424,10 @@ search_for_prefix(PyCalculatePath *calculate, wchar_t *prefix)


static void
calculate_prefix(PyCalculatePath *calculate, wchar_t *prefix)
calculate_prefix(const _PyMainInterpreterConfig *main_config,
PyCalculatePath *calculate, wchar_t *prefix)
{
calculate->prefix_found = search_for_prefix(calculate, prefix);
calculate->prefix_found = search_for_prefix(main_config, calculate, prefix);
if (!calculate->prefix_found) {
if (!Py_FrozenFlag) {
fprintf(stderr,
Expand Down Expand Up @@ -470,18 +469,19 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix)
MAXPATHLEN bytes long.
*/
static int
search_for_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
search_for_exec_prefix(const _PyMainInterpreterConfig *main_config,
PyCalculatePath *calculate, wchar_t *exec_prefix)
{
size_t n;

/* If PYTHONHOME is set, we believe it unconditionally */
if (calculate->home) {
wchar_t *delim = wcschr(calculate->home, DELIM);
if (main_config->home) {
wchar_t *delim = wcschr(main_config->home, DELIM);
if (delim) {
wcsncpy(exec_prefix, delim+1, MAXPATHLEN);
}
else {
wcsncpy(exec_prefix, calculate->home, MAXPATHLEN);
wcsncpy(exec_prefix, main_config->home, MAXPATHLEN);
}
exec_prefix[MAXPATHLEN] = L'\0';
joinpath(exec_prefix, calculate->lib_python);
Expand Down Expand Up @@ -552,9 +552,12 @@ search_for_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)


static void
calculate_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
calculate_exec_prefix(const _PyMainInterpreterConfig *main_config,
PyCalculatePath *calculate, wchar_t *exec_prefix)
{
calculate->exec_prefix_found = search_for_exec_prefix(calculate, exec_prefix);
calculate->exec_prefix_found = search_for_exec_prefix(main_config,
calculate,
exec_prefix);
if (!calculate->exec_prefix_found) {
if (!Py_FrozenFlag) {
fprintf(stderr,
Expand Down Expand Up @@ -585,7 +588,8 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)


static _PyInitError
calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config)
calculate_program_full_path(const _PyMainInterpreterConfig *main_config,
PyCalculatePath *calculate, _PyPathConfig *config)
{
wchar_t program_full_path[MAXPATHLEN+1];
memset(program_full_path, 0, sizeof(program_full_path));
Expand All @@ -604,8 +608,8 @@ calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config)
* other way to find a directory to start the search from. If
* $PATH isn't exported, you lose.
*/
if (wcschr(calculate->program_name, SEP)) {
wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN);
if (wcschr(main_config->program_name, SEP)) {
wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN);
}
#ifdef __APPLE__
/* On Mac OS X, if a script uses an interpreter of the form
Expand Down Expand Up @@ -645,7 +649,7 @@ calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config)
wcsncpy(program_full_path, path, MAXPATHLEN);
}

joinpath(program_full_path, calculate->program_name);
joinpath(program_full_path, main_config->program_name);
if (isxfile(program_full_path)) {
break;
}
Expand Down Expand Up @@ -810,14 +814,15 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix)


static _PyInitError
calculate_module_search_path(PyCalculatePath *calculate,
calculate_module_search_path(const _PyMainInterpreterConfig *main_config,
PyCalculatePath *calculate,
const wchar_t *prefix, const wchar_t *exec_prefix,
_PyPathConfig *config)
{
/* Calculate size of return buffer */
size_t bufsz = 0;
if (calculate->module_search_path_env != NULL) {
bufsz += wcslen(calculate->module_search_path_env) + 1;
if (main_config->module_search_path_env != NULL) {
bufsz += wcslen(main_config->module_search_path_env) + 1;
}

wchar_t *defpath = calculate->pythonpath;
Expand Down Expand Up @@ -851,8 +856,8 @@ calculate_module_search_path(PyCalculatePath *calculate,
buf[0] = '\0';

/* Run-time value of $PYTHONPATH goes first */
if (calculate->module_search_path_env) {
wcscpy(buf, calculate->module_search_path_env);
if (main_config->module_search_path_env) {
wcscpy(buf, main_config->module_search_path_env);
wcscat(buf, delimiter);
}

Expand Down Expand Up @@ -903,10 +908,6 @@ static _PyInitError
calculate_init(PyCalculatePath *calculate,
const _PyMainInterpreterConfig *main_config)
{
calculate->home = main_config->home;
calculate->module_search_path_env = main_config->module_search_path_env;
calculate->program_name = main_config->program_name;

size_t len;
char *path = getenv("PATH");
if (path) {
Expand Down Expand Up @@ -948,9 +949,12 @@ calculate_free(PyCalculatePath *calculate)


static _PyInitError
calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config)
calculate_path_impl(const _PyMainInterpreterConfig *main_config,
PyCalculatePath *calculate, _PyPathConfig *config)
{
_PyInitError err = calculate_program_full_path(calculate, config);
_PyInitError err;

err = calculate_program_full_path(main_config, calculate, config);
if (_Py_INIT_FAILED(err)) {
return err;
}
Expand All @@ -964,13 +968,13 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config)

wchar_t prefix[MAXPATHLEN+1];
memset(prefix, 0, sizeof(prefix));
calculate_prefix(calculate, prefix);
calculate_prefix(main_config, calculate, prefix);

calculate_zip_path(calculate, prefix);

wchar_t exec_prefix[MAXPATHLEN+1];
memset(exec_prefix, 0, sizeof(exec_prefix));
calculate_exec_prefix(calculate, exec_prefix);
calculate_exec_prefix(main_config, calculate, exec_prefix);

if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
!Py_FrozenFlag)
Expand All @@ -979,8 +983,8 @@ calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config)
"Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
}

err = calculate_module_search_path(calculate, prefix, exec_prefix,
config);
err = calculate_module_search_path(main_config, calculate,
prefix, exec_prefix, config);
if (_Py_INIT_FAILED(err)) {
return err;
}
Expand Down Expand Up @@ -1041,7 +1045,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
_PyPathConfig new_path_config;
memset(&new_path_config, 0, sizeof(new_path_config));

err = calculate_path_impl(&calculate, &new_path_config);
err = calculate_path_impl(main_config, &calculate, &new_path_config);
if (_Py_INIT_FAILED(err)) {
pathconfig_clear(&new_path_config);
goto done;
Expand All @@ -1068,14 +1072,26 @@ pathconfig_global_init(void)
_PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT;

err = _PyMainInterpreterConfig_ReadEnv(&config);
if (!_Py_INIT_FAILED(err)) {
err = _PyPathConfig_Init(&config);
if (_Py_INIT_FAILED(err)) {
goto error;
}

err = _PyMainInterpreterConfig_Read(&config);
if (_Py_INIT_FAILED(err)) {
goto error;
}
_PyMainInterpreterConfig_Clear(&config);

err = _PyPathConfig_Init(&config);
if (_Py_INIT_FAILED(err)) {
_Py_FatalInitError(err);
goto error;
}

_PyMainInterpreterConfig_Clear(&config);
return;

error:
_PyMainInterpreterConfig_Clear(&config);
_Py_FatalInitError(err);
}


Expand Down
69 changes: 32 additions & 37 deletions Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,6 @@ typedef struct {
/* non-zero if filename, command (-c) or module (-m) is set
on the command line */
int run_code;
wchar_t *program_name;
/* Error message if a function failed */
_PyInitError err;
/* PYTHONWARNINGS env var */
Expand All @@ -429,7 +428,6 @@ typedef struct {
.config = _PyMainInterpreterConfig_INIT, \
.main_importer_path = NULL, \
.run_code = -1, \
.program_name = NULL, \
.err = _Py_INIT_OK(), \
.env_warning_options = {0, NULL}}

Expand All @@ -455,7 +453,6 @@ pymain_free_impl(_PyMain *pymain)

pymain_optlist_clear(&pymain->env_warning_options);
Py_CLEAR(pymain->main_importer_path);
PyMem_RawFree(pymain->program_name);

_PyMainInterpreterConfig_Clear(&pymain->config);

Expand Down Expand Up @@ -874,14 +871,11 @@ pymain_init_stdio(_PyMain *pymain)


/* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__
environment variables on macOS if available, use argv[0] by default.

Return 0 on success.
Set pymain->err and return -1 on error. */
static int
pymain_get_program_name(_PyMain *pymain)
environment variables on macOS if available. */
static _PyInitError
config_get_program_name(_PyMainInterpreterConfig *config)
{
assert(pymain->program_name == NULL);
assert(config->program_name == NULL);
#ifdef __APPLE__
char *p;
/* On MacOS X, when the Python interpreter is embedded in an
Expand All @@ -899,12 +893,11 @@ pymain_get_program_name(_PyMain *pymain)

buffer = PyMem_RawMalloc(len * sizeof(wchar_t));
if (buffer == NULL) {
pymain->err = _Py_INIT_NO_MEMORY();
return -1;
return _Py_INIT_NO_MEMORY();
}

mbstowcs(buffer, p, len);
pymain->program_name = buffer;
pymain->config.program_name = buffer;
}
#ifdef WITH_NEXT_FRAMEWORK
else {
Expand All @@ -916,19 +909,26 @@ pymain_get_program_name(_PyMain *pymain)
size_t len;
wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, &len);
if (wbuf == NULL) {
SET_DECODE_ERROR("__PYVENV_LAUNCHER__", len);
return -1;
return SET_DECODE_ERROR("__PYVENV_LAUNCHER__", len);
}
pymain->program_name = wbuf;
pymain->config.program_name = wbuf;
}
}
#endif /* WITH_NEXT_FRAMEWORK */
#endif /* __APPLE__ */
return _Py_INIT_OK();
}

if (pymain->program_name == NULL) {

/* If config_get_program_name() found no program name: use argv[0] by default.
Return 0 on success. Set pymain->err and return -1 on error. */
static int
pymain_get_program_name(_PyMain *pymain)
{
if (pymain->config.program_name == NULL) {
/* Use argv[0] by default */
pymain->program_name = pymain_wstrdup(pymain, pymain->argv[0]);
if (pymain->program_name == NULL) {
pymain->config.program_name = pymain_wstrdup(pymain, pymain->argv[0]);
if (pymain->config.program_name == NULL) {
return -1;
}
}
Expand Down Expand Up @@ -1451,11 +1451,9 @@ _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config)
return err;
}

/* FIXME: _PyMainInterpreterConfig_Read() has the same code. Remove it
here? See also pymain_get_program_name() and pymain_parse_envvars(). */
config->program_name = _PyMem_RawWcsdup(Py_GetProgramName());
if (config->program_name == NULL) {
return _Py_INIT_NO_MEMORY();
err = config_get_program_name(config);
if (_Py_INIT_FAILED(err)) {
return err;
}

return _Py_INIT_OK();
Expand All @@ -1481,25 +1479,17 @@ pymain_parse_envvars(_PyMain *pymain)
if (pymain_warnings_envvar(pymain) < 0) {
return -1;
}
if (pymain_get_program_name(pymain) < 0) {
return -1;
}
core_config->allocator = Py_GETENV("PYTHONMALLOC");

/* FIXME: move pymain_get_program_name() code into
_PyMainInterpreterConfig_ReadEnv().
Problem: _PyMainInterpreterConfig_ReadEnv() doesn't have access
to argv[0]. */
Py_SetProgramName(pymain->program_name);
/* Don't free program_name here: the argument to Py_SetProgramName
must remain valid until Py_FinalizeEx is called. The string is freed
by pymain_free(). */

_PyInitError err = _PyMainInterpreterConfig_ReadEnv(&pymain->config);
if (_Py_INIT_FAILED(pymain->err)) {
pymain->err = err;
return -1;
}
if (pymain_get_program_name(pymain) < 0) {
return -1;
}

core_config->allocator = Py_GETENV("PYTHONMALLOC");

/* -X options */
if (pymain_get_xoption(pymain, L"showrefcount")) {
Expand Down Expand Up @@ -1578,6 +1568,11 @@ pymain_init_python(_PyMain *pymain)
{
pymain_init_stdio(pymain);

Py_SetProgramName(pymain->config.program_name);
/* Don't free program_name here: the argument to Py_SetProgramName
must remain valid until Py_FinalizeEx is called. The string is freed
by pymain_free(). */

pymain->err = _Py_InitializeCore(&pymain->core_config);
if (_Py_INIT_FAILED(pymain->err)) {
return -1;
Expand Down
Loading