blob: 470aba75bea969081b42c758fb89c712689e81cd [file] [log] [blame]
Victor Stinner31a83932017-12-04 13:39:15 +01001/* Path configuration like module_search_path (sys.path) */
2
3#include "Python.h"
Victor Stinner361dcdc2020-04-15 03:24:57 +02004#include "osdefs.h" // DELIM
Victor Stinner331a6a52019-05-27 16:39:22 +02005#include "pycore_initconfig.h"
Victor Stinner9fc57a32018-11-07 00:44:03 +01006#include "pycore_fileutils.h"
Victor Stinnera1c249c2018-11-01 03:15:58 +01007#include "pycore_pathconfig.h"
Victor Stinnerd9ea5ca2020-04-15 02:57:50 +02008#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
Nick Coghland5d9e022018-03-25 23:03:10 +10009#include <wchar.h>
Victor Stinnere5014be2020-04-14 17:52:15 +020010#ifdef MS_WINDOWS
11# include <windows.h> // GetFullPathNameW(), MAX_PATH
12#endif
Victor Stinner31a83932017-12-04 13:39:15 +010013
14#ifdef __cplusplus
15extern "C" {
16#endif
17
18
19_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
20
21
Victor Stinnerb1147e42018-07-21 02:06:16 +020022static int
23copy_wstr(wchar_t **dst, const wchar_t *src)
24{
Victor Stinner1ce152a2019-09-24 17:44:15 +020025 assert(*dst == NULL);
Victor Stinnerb1147e42018-07-21 02:06:16 +020026 if (src != NULL) {
27 *dst = _PyMem_RawWcsdup(src);
28 if (*dst == NULL) {
29 return -1;
30 }
31 }
32 else {
33 *dst = NULL;
34 }
35 return 0;
36}
37
38
39static void
Victor Stinner331a6a52019-05-27 16:39:22 +020040pathconfig_clear(_PyPathConfig *config)
Victor Stinner31a83932017-12-04 13:39:15 +010041{
42 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
43 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
44 called before Py_Initialize() which can changes the memory allocator. */
45 PyMemAllocatorEx old_alloc;
46 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
47
48#define CLEAR(ATTR) \
49 do { \
50 PyMem_RawFree(ATTR); \
51 ATTR = NULL; \
52 } while (0)
53
Victor Stinner31a83932017-12-04 13:39:15 +010054 CLEAR(config->program_full_path);
Victor Stinner9c42f8c2019-09-23 18:47:29 +020055 CLEAR(config->prefix);
Steve Dower177a41a2018-11-17 20:41:48 -080056 CLEAR(config->exec_prefix);
Victor Stinner31a83932017-12-04 13:39:15 +010057 CLEAR(config->module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +010058 CLEAR(config->program_name);
Victor Stinner9c42f8c2019-09-23 18:47:29 +020059 CLEAR(config->home);
Victor Stinner8bf39b62019-09-26 02:22:35 +020060#ifdef MS_WINDOWS
Steve Dower9048c492019-06-29 10:34:11 -070061 CLEAR(config->base_executable);
Victor Stinner8bf39b62019-09-26 02:22:35 +020062#endif
63
Victor Stinner31a83932017-12-04 13:39:15 +010064#undef CLEAR
65
66 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
67}
68
69
Victor Stinner331a6a52019-05-27 16:39:22 +020070static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +020071pathconfig_copy(_PyPathConfig *config, const _PyPathConfig *config2)
Victor Stinner31a83932017-12-04 13:39:15 +010072{
Victor Stinner9c42f8c2019-09-23 18:47:29 +020073 pathconfig_clear(config);
Victor Stinner31a83932017-12-04 13:39:15 +010074
Victor Stinner9c42f8c2019-09-23 18:47:29 +020075#define COPY_ATTR(ATTR) \
76 do { \
77 if (copy_wstr(&config->ATTR, config2->ATTR) < 0) { \
78 return _PyStatus_NO_MEMORY(); \
79 } \
80 } while (0)
Victor Stinner31a83932017-12-04 13:39:15 +010081
Victor Stinner9c42f8c2019-09-23 18:47:29 +020082 COPY_ATTR(program_full_path);
83 COPY_ATTR(prefix);
84 COPY_ATTR(exec_prefix);
85 COPY_ATTR(module_search_path);
86 COPY_ATTR(program_name);
87 COPY_ATTR(home);
Victor Stinner8bf39b62019-09-26 02:22:35 +020088#ifdef MS_WINDOWS
Victor Stinner9c42f8c2019-09-23 18:47:29 +020089 config->isolated = config2->isolated;
90 config->site_import = config2->site_import;
91 COPY_ATTR(base_executable);
Victor Stinner8bf39b62019-09-26 02:22:35 +020092#endif
Victor Stinnere2677932019-09-21 01:50:16 +020093
Victor Stinner9c42f8c2019-09-23 18:47:29 +020094#undef COPY_ATTR
Victor Stinner31a83932017-12-04 13:39:15 +010095
Victor Stinner9c42f8c2019-09-23 18:47:29 +020096 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +020097}
98
99
Victor Stinnerb1147e42018-07-21 02:06:16 +0200100void
101_PyPathConfig_ClearGlobal(void)
102{
Victor Stinnerc1834442019-03-18 22:24:28 +0100103 PyMemAllocatorEx old_alloc;
104 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
105
Victor Stinner331a6a52019-05-27 16:39:22 +0200106 pathconfig_clear(&_Py_path_config);
Victor Stinnerc1834442019-03-18 22:24:28 +0100107
108 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200109}
110
111
112static wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200113_PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200114{
115 size_t len = 1; /* NUL terminator */
Victor Stinner74f65682019-03-15 15:08:05 +0100116 for (Py_ssize_t i=0; i < list->length; i++) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200117 if (i != 0) {
118 len++;
119 }
Victor Stinner74f65682019-03-15 15:08:05 +0100120 len += wcslen(list->items[i]);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200121 }
122
123 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
124 if (text == NULL) {
125 return NULL;
126 }
127 wchar_t *str = text;
Victor Stinner74f65682019-03-15 15:08:05 +0100128 for (Py_ssize_t i=0; i < list->length; i++) {
129 wchar_t *path = list->items[i];
Victor Stinnerb1147e42018-07-21 02:06:16 +0200130 if (i != 0) {
Victor Stinner12f2f172019-09-26 15:51:50 +0200131 *str++ = sep;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200132 }
133 len = wcslen(path);
134 memcpy(str, path, len * sizeof(wchar_t));
135 str += len;
136 }
137 *str = L'\0';
138
139 return text;
140}
141
142
Victor Stinnerc4221672019-09-21 01:02:56 +0200143static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200144pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config)
Victor Stinnerc4221672019-09-21 01:02:56 +0200145{
Victor Stinner331a6a52019-05-27 16:39:22 +0200146 PyStatus status;
Victor Stinnerc4221672019-09-21 01:02:56 +0200147 PyMemAllocatorEx old_alloc;
148 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
149
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200150 if (config->module_search_paths_set) {
Victor Stinner1ce152a2019-09-24 17:44:15 +0200151 PyMem_RawFree(pathconfig->module_search_path);
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200152 pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
153 if (pathconfig->module_search_path == NULL) {
154 goto no_memory;
155 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200156 }
157
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200158#define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \
159 if (config->CONFIG_ATTR) { \
Victor Stinner1ce152a2019-09-24 17:44:15 +0200160 PyMem_RawFree(pathconfig->PATH_ATTR); \
161 pathconfig->PATH_ATTR = NULL; \
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200162 if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \
163 goto no_memory; \
164 } \
165 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200166
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200167 COPY_CONFIG(program_full_path, executable);
168 COPY_CONFIG(prefix, prefix);
169 COPY_CONFIG(exec_prefix, exec_prefix);
170 COPY_CONFIG(program_name, program_name);
171 COPY_CONFIG(home, home);
Victor Stinner8bf39b62019-09-26 02:22:35 +0200172#ifdef MS_WINDOWS
173 COPY_CONFIG(base_executable, base_executable);
174#endif
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200175
176#undef COPY_CONFIG
Victor Stinnerb1147e42018-07-21 02:06:16 +0200177
Victor Stinner331a6a52019-05-27 16:39:22 +0200178 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200179 goto done;
180
181no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200182 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200183
184done:
Victor Stinnerb1147e42018-07-21 02:06:16 +0200185 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200186 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200187}
188
Victor Stinner8f427482020-07-08 00:20:37 +0200189PyObject *
190_PyPathConfig_AsDict(void)
191{
192 PyObject *dict = PyDict_New();
193 if (dict == NULL) {
194 return NULL;
195 }
196
197#define SET_ITEM(KEY, EXPR) \
198 do { \
199 PyObject *obj = (EXPR); \
200 if (obj == NULL) { \
201 goto fail; \
202 } \
203 int res = PyDict_SetItemString(dict, KEY, obj); \
204 Py_DECREF(obj); \
205 if (res < 0) { \
206 goto fail; \
207 } \
208 } while (0)
209#define SET_ITEM_STR(KEY) \
210 SET_ITEM(#KEY, \
211 (_Py_path_config.KEY \
212 ? PyUnicode_FromWideChar(_Py_path_config.KEY, -1) \
213 : (Py_INCREF(Py_None), Py_None)))
214#define SET_ITEM_INT(KEY) \
215 SET_ITEM(#KEY, PyLong_FromLong(_Py_path_config.KEY))
216
217 SET_ITEM_STR(program_full_path);
218 SET_ITEM_STR(prefix);
219 SET_ITEM_STR(exec_prefix);
220 SET_ITEM_STR(module_search_path);
221 SET_ITEM_STR(program_name);
222 SET_ITEM_STR(home);
223#ifdef MS_WINDOWS
224 SET_ITEM_INT(isolated);
225 SET_ITEM_INT(site_import);
226 SET_ITEM_STR(base_executable);
227
228 {
229 wchar_t py3path[MAX_PATH];
230 HMODULE hPython3 = GetModuleHandleW(PY3_DLLNAME);
231 PyObject *obj;
232 if (hPython3
233 && GetModuleFileNameW(hPython3, py3path, Py_ARRAY_LENGTH(py3path)))
234 {
235 obj = PyUnicode_FromWideChar(py3path, -1);
236 if (obj == NULL) {
237 goto fail;
238 }
239 }
240 else {
241 obj = Py_None;
242 Py_INCREF(obj);
243 }
244 if (PyDict_SetItemString(dict, "python3_dll", obj) < 0) {
245 Py_DECREF(obj);
246 goto fail;
247 }
248 Py_DECREF(obj);
249 }
250#endif
251
252#undef SET_ITEM
253#undef SET_ITEM_STR
254#undef SET_ITEM_INT
255
256 return dict;
257
258fail:
259 Py_DECREF(dict);
260 return NULL;
261}
262
Victor Stinnerb1147e42018-07-21 02:06:16 +0200263
Victor Stinner12f2f172019-09-26 15:51:50 +0200264PyStatus
265_PyConfig_WritePathConfig(const PyConfig *config)
266{
Victor Stinner12f2f172019-09-26 15:51:50 +0200267 return pathconfig_set_from_config(&_Py_path_config, config);
268}
269
270
Victor Stinner331a6a52019-05-27 16:39:22 +0200271static PyStatus
272config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200273{
Victor Stinner331a6a52019-05-27 16:39:22 +0200274 assert(!config->module_search_paths_set);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200275
Victor Stinner331a6a52019-05-27 16:39:22 +0200276 _PyWideStringList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200277
Victor Stinner331a6a52019-05-27 16:39:22 +0200278 const wchar_t *sys_path = pathconfig->module_search_path;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200279 const wchar_t delim = DELIM;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200280 while (1) {
Alex Henrief3e5e952020-01-09 09:14:11 +0000281 const wchar_t *p = wcschr(sys_path, delim);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200282 if (p == NULL) {
283 p = sys_path + wcslen(sys_path); /* End of string */
284 }
285
286 size_t path_len = (p - sys_path);
287 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
288 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200289 return _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200290 }
291 memcpy(path, sys_path, path_len * sizeof(wchar_t));
292 path[path_len] = L'\0';
293
Victor Stinner331a6a52019-05-27 16:39:22 +0200294 PyStatus status = PyWideStringList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200295 PyMem_RawFree(path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200296 if (_PyStatus_EXCEPTION(status)) {
297 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200298 }
299
300 if (*p == '\0') {
301 break;
302 }
303 sys_path = p + 1;
304 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200305 config->module_search_paths_set = 1;
306 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200307}
308
309
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200310/* Calculate the path configuration:
311
312 - exec_prefix
313 - module_search_path
314 - prefix
315 - program_full_path
316
317 On Windows, more fields are calculated:
318
319 - base_executable
320 - isolated
321 - site_import
322
323 On other platforms, isolated and site_import are left unchanged, and
324 _PyConfig_InitPathConfig() copies executable to base_executable (if it's not
325 set).
326
327 Priority, highest to lowest:
328
329 - PyConfig
330 - _Py_path_config: set by Py_SetPath(), Py_SetPythonHome()
331 and Py_SetProgramName()
332 - _PyPathConfig_Calculate()
333*/
334static PyStatus
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100335pathconfig_init(_PyPathConfig *pathconfig, const PyConfig *config,
336 int compute_path_config)
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200337{
338 PyStatus status;
339
340 PyMemAllocatorEx old_alloc;
341 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
342
343 status = pathconfig_copy(pathconfig, &_Py_path_config);
344 if (_PyStatus_EXCEPTION(status)) {
345 goto done;
346 }
347
348 status = pathconfig_set_from_config(pathconfig, config);
349 if (_PyStatus_EXCEPTION(status)) {
350 goto done;
351 }
352
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100353 if (compute_path_config) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200354 status = _PyPathConfig_Calculate(pathconfig, config);
355 }
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200356
357done:
358 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
359 return status;
360}
361
362
Victor Stinner331a6a52019-05-27 16:39:22 +0200363static PyStatus
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100364config_init_pathconfig(PyConfig *config, int compute_path_config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200365{
Victor Stinner331a6a52019-05-27 16:39:22 +0200366 _PyPathConfig pathconfig = _PyPathConfig_INIT;
367 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200368
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100369 status = pathconfig_init(&pathconfig, config, compute_path_config);
Victor Stinner331a6a52019-05-27 16:39:22 +0200370 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200371 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200372 }
373
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100374 if (!config->module_search_paths_set
375 && pathconfig.module_search_path != NULL)
376 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200377 status = config_init_module_search_paths(config, &pathconfig);
378 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200379 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200380 }
381 }
382
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200383#define COPY_ATTR(PATH_ATTR, CONFIG_ATTR) \
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100384 if (config->CONFIG_ATTR == NULL && pathconfig.PATH_ATTR != NULL) { \
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200385 if (copy_wstr(&config->CONFIG_ATTR, pathconfig.PATH_ATTR) < 0) { \
386 goto no_memory; \
387 } \
Victor Stinnerb1147e42018-07-21 02:06:16 +0200388 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200389
Victor Stinner8bf39b62019-09-26 02:22:35 +0200390#ifdef MS_WINDOWS
391 if (config->executable != NULL && config->base_executable == NULL) {
392 /* If executable is set explicitly in the configuration,
393 ignore calculated base_executable: _PyConfig_InitPathConfig()
394 will copy executable to base_executable */
395 }
396 else {
397 COPY_ATTR(base_executable, base_executable);
398 }
399#endif
400
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200401 COPY_ATTR(program_full_path, executable);
402 COPY_ATTR(prefix, prefix);
403 COPY_ATTR(exec_prefix, exec_prefix);
Victor Stinner8bf39b62019-09-26 02:22:35 +0200404
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200405#undef COPY_ATTR
Steve Dower9048c492019-06-29 10:34:11 -0700406
Victor Stinner8bf39b62019-09-26 02:22:35 +0200407#ifdef MS_WINDOWS
408 /* If a ._pth file is found: isolated and site_import are overriden */
Victor Stinner331a6a52019-05-27 16:39:22 +0200409 if (pathconfig.isolated != -1) {
410 config->isolated = pathconfig.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200411 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200412 if (pathconfig.site_import != -1) {
413 config->site_import = pathconfig.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200414 }
Victor Stinner8bf39b62019-09-26 02:22:35 +0200415#endif
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200416
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200417 status = _PyStatus_OK();
418 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200419
420no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200421 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200422
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200423done:
Victor Stinner331a6a52019-05-27 16:39:22 +0200424 pathconfig_clear(&pathconfig);
425 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200426}
427
428
Victor Stinner331a6a52019-05-27 16:39:22 +0200429PyStatus
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100430_PyConfig_InitPathConfig(PyConfig *config, int compute_path_config)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200431{
432 /* Do we need to calculate the path? */
Victor Stinner331a6a52019-05-27 16:39:22 +0200433 if (!config->module_search_paths_set
Victor Stinner8bf39b62019-09-26 02:22:35 +0200434 || config->executable == NULL
435 || config->prefix == NULL
436 || config->exec_prefix == NULL)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200437 {
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100438 PyStatus status = config_init_pathconfig(config, compute_path_config);
Victor Stinner331a6a52019-05-27 16:39:22 +0200439 if (_PyStatus_EXCEPTION(status)) {
440 return status;
Victor Stinner1dc6e392018-07-25 02:49:17 +0200441 }
442 }
443
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100444 if (config->base_prefix == NULL && config->prefix != NULL) {
Victor Stinner1dc6e392018-07-25 02:49:17 +0200445 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200446 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200447 }
448 }
449
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100450 if (config->base_exec_prefix == NULL && config->exec_prefix != NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800451 if (copy_wstr(&config->base_exec_prefix,
452 config->exec_prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200453 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200454 }
455 }
Steve Dower9048c492019-06-29 10:34:11 -0700456
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100457 if (config->base_executable == NULL && config->executable != NULL) {
Steve Dower9048c492019-06-29 10:34:11 -0700458 if (copy_wstr(&config->base_executable,
459 config->executable) < 0) {
460 return _PyStatus_NO_MEMORY();
461 }
462 }
463
Victor Stinner331a6a52019-05-27 16:39:22 +0200464 return _PyStatus_OK();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200465}
466
467
Victor Stinner31a83932017-12-04 13:39:15 +0100468/* External interface */
469
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100470static void _Py_NO_RETURN
471path_out_of_memory(const char *func)
472{
473 _Py_FatalErrorFunc(func, "out of memory");
474}
475
Victor Stinner31a83932017-12-04 13:39:15 +0100476void
477Py_SetPath(const wchar_t *path)
478{
479 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200480 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100481 return;
482 }
483
484 PyMemAllocatorEx old_alloc;
485 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
486
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200487 PyMem_RawFree(_Py_path_config.prefix);
488 PyMem_RawFree(_Py_path_config.exec_prefix);
489 PyMem_RawFree(_Py_path_config.module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +0100490
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200491 _Py_path_config.prefix = _PyMem_RawWcsdup(L"");
492 _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
493 _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinner31a83932017-12-04 13:39:15 +0100494
495 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200496
Victor Stinnerace3f9a2020-11-10 21:10:22 +0100497 if (_Py_path_config.prefix == NULL
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200498 || _Py_path_config.exec_prefix == NULL
499 || _Py_path_config.module_search_path == NULL)
500 {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100501 path_out_of_memory(__func__);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200502 }
Victor Stinner31a83932017-12-04 13:39:15 +0100503}
504
505
506void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200507Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100508{
509 if (home == NULL) {
510 return;
511 }
512
513 PyMemAllocatorEx old_alloc;
514 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
515
516 PyMem_RawFree(_Py_path_config.home);
517 _Py_path_config.home = _PyMem_RawWcsdup(home);
518
519 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
520
521 if (_Py_path_config.home == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100522 path_out_of_memory(__func__);
Victor Stinner31a83932017-12-04 13:39:15 +0100523 }
524}
525
526
527void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200528Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100529{
530 if (program_name == NULL || program_name[0] == L'\0') {
531 return;
532 }
533
534 PyMemAllocatorEx old_alloc;
535 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
536
537 PyMem_RawFree(_Py_path_config.program_name);
538 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
539
540 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
541
542 if (_Py_path_config.program_name == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100543 path_out_of_memory(__func__);
Victor Stinner31a83932017-12-04 13:39:15 +0100544 }
545}
546
Steve Dower177a41a2018-11-17 20:41:48 -0800547void
548_Py_SetProgramFullPath(const wchar_t *program_full_path)
549{
550 if (program_full_path == NULL || program_full_path[0] == L'\0') {
551 return;
552 }
553
554 PyMemAllocatorEx old_alloc;
555 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
556
557 PyMem_RawFree(_Py_path_config.program_full_path);
558 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
559
560 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
561
562 if (_Py_path_config.program_full_path == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100563 path_out_of_memory(__func__);
Steve Dower177a41a2018-11-17 20:41:48 -0800564 }
565}
566
Victor Stinner31a83932017-12-04 13:39:15 +0100567
568wchar_t *
569Py_GetPath(void)
570{
Victor Stinner31a83932017-12-04 13:39:15 +0100571 return _Py_path_config.module_search_path;
572}
573
574
575wchar_t *
576Py_GetPrefix(void)
577{
Victor Stinner31a83932017-12-04 13:39:15 +0100578 return _Py_path_config.prefix;
579}
580
581
582wchar_t *
583Py_GetExecPrefix(void)
584{
Victor Stinner31a83932017-12-04 13:39:15 +0100585 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100586}
587
588
589wchar_t *
590Py_GetProgramFullPath(void)
591{
Victor Stinner31a83932017-12-04 13:39:15 +0100592 return _Py_path_config.program_full_path;
593}
594
595
596wchar_t*
597Py_GetPythonHome(void)
598{
Victor Stinner31a83932017-12-04 13:39:15 +0100599 return _Py_path_config.home;
600}
601
602
603wchar_t *
604Py_GetProgramName(void)
605{
Victor Stinner31a83932017-12-04 13:39:15 +0100606 return _Py_path_config.program_name;
607}
608
Victor Stinnerdcf61712019-03-19 16:09:27 +0100609/* Compute module search path from argv[0] or the current working
610 directory ("-m module" case) which will be prepended to sys.argv:
611 sys.path[0].
612
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200613 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100614
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200615 Return 0 if it fails to resolve the full path. For example, return 0 if the
616 current working directory has been removed (bpo-36236) or if argv is empty.
617
618 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100619 */
620int
Victor Stinner331a6a52019-05-27 16:39:22 +0200621_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100622{
Victor Stinner331a6a52019-05-27 16:39:22 +0200623 assert(_PyWideStringList_CheckConsistency(argv));
Victor Stinner74f65682019-03-15 15:08:05 +0100624
Victor Stinnerfc96e542019-03-19 18:22:55 +0100625 if (argv->length == 0) {
626 /* Leave sys.path unchanged if sys.argv is empty */
627 return 0;
628 }
629
630 wchar_t *argv0 = argv->items[0];
631 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
632 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
633
634 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100635 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100636
637#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100638 wchar_t fullpath[MAXPATHLEN];
639#elif defined(MS_WINDOWS)
640 wchar_t fullpath[MAX_PATH];
641#endif
642
Nick Coghland5d9e022018-03-25 23:03:10 +1000643 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100644#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100645 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
646 return 0;
647 }
648 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100649#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100650 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100651#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100652 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000653 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100654
655#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100656 wchar_t link[MAXPATHLEN + 1];
657 int nr = 0;
Gregory P. Smith81328f32020-06-22 00:27:20 -0700658 wchar_t path0copy[2 * MAXPATHLEN + 1];
Victor Stinnerfc96e542019-03-19 18:22:55 +0100659
660 if (have_script_arg) {
661 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
662 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100663 if (nr > 0) {
664 /* It's a symlink */
665 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100666 if (link[0] == SEP) {
667 path0 = link; /* Link to absolute path */
668 }
669 else if (wcschr(link, SEP) == NULL) {
670 /* Link without path */
671 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100672 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100673 /* Must join(dirname(path0), link) */
674 wchar_t *q = wcsrchr(path0, SEP);
675 if (q == NULL) {
676 /* path0 without path */
677 path0 = link;
678 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100679 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100680 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100681 wcsncpy(path0copy, path0, MAXPATHLEN);
682 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100683 wcsncpy(q+1, link, MAXPATHLEN);
684 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100685 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100686 }
687 }
688 }
689#endif /* HAVE_READLINK */
690
Victor Stinnerfc96e542019-03-19 18:22:55 +0100691 wchar_t *p = NULL;
692
Victor Stinner11a247d2017-12-13 21:05:57 +0100693#if SEP == '\\'
694 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000695 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100696 wchar_t *q;
697#if defined(MS_WINDOWS)
698 /* Replace the first element in argv with the full path. */
699 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100700 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100701 Py_ARRAY_LENGTH(fullpath),
702 fullpath,
703 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100704 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100705 }
706#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100707 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100708 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100709 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100710 if (q != NULL)
711 p = q;
712 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100713 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100714 if (n > 1 && p[-1] != ':')
715 n--; /* Drop trailing separator */
716 }
717 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100718#else
719 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000720 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100721#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100722 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
723 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100724 }
725#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100726 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100727 }
728 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100729 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100730#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100731 if (n > 1) {
732 /* Drop trailing separator */
733 n--;
734 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100735#endif /* Unix */
736 }
737#endif /* All others */
738
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200739 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
740 if (path0_obj == NULL) {
741 return -1;
742 }
743
744 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100745 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100746}
747
Victor Stinner9bee3292017-12-21 16:49:13 +0100748
Minmin Gong8ebc6452019-02-02 20:26:55 -0800749#ifdef MS_WINDOWS
750#define WCSTOK wcstok_s
751#else
752#define WCSTOK wcstok
753#endif
754
Victor Stinner9bee3292017-12-21 16:49:13 +0100755/* Search for a prefix value in an environment file (pyvenv.cfg).
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200756
757 - If found, copy it into *value_p: string which must be freed by
758 PyMem_RawFree().
759 - If not found, *value_p is set to NULL.
760*/
761PyStatus
Victor Stinner9bee3292017-12-21 16:49:13 +0100762_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200763 wchar_t **value_p)
Victor Stinner9bee3292017-12-21 16:49:13 +0100764{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200765 *value_p = NULL;
766
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100767 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
768 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100769
Victor Stinner9bee3292017-12-21 16:49:13 +0100770 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100771 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100772
773 if (p == NULL) {
774 break;
775 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100776
777 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100778 if (p[n - 1] != '\n') {
779 /* line has overflowed - bail */
780 break;
781 }
782 if (p[0] == '#') {
783 /* Comment - skip */
784 continue;
785 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100786
Victor Stinner5f9cf232019-03-19 01:46:25 +0100787 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100788 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100789 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800790 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100791 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800792 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100793 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800794 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100795 if (tok != NULL) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200796 *value_p = _PyMem_RawWcsdup(tok);
Victor Stinner9bee3292017-12-21 16:49:13 +0100797 PyMem_RawFree(tmpbuffer);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200798
799 if (*value_p == NULL) {
800 return _PyStatus_NO_MEMORY();
801 }
802
803 /* found */
804 return _PyStatus_OK();
Victor Stinner9bee3292017-12-21 16:49:13 +0100805 }
806 }
807 }
808 PyMem_RawFree(tmpbuffer);
809 }
810 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200811
812 /* not found */
813 return _PyStatus_OK();
Victor Stinner9bee3292017-12-21 16:49:13 +0100814}
815
Victor Stinner31a83932017-12-04 13:39:15 +0100816#ifdef __cplusplus
817}
818#endif