blob: 12a684a66b718ea0e4d3b913039ca66c553788dd [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
335pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
336{
337 PyStatus status;
338
339 PyMemAllocatorEx old_alloc;
340 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
341
342 status = pathconfig_copy(pathconfig, &_Py_path_config);
343 if (_PyStatus_EXCEPTION(status)) {
344 goto done;
345 }
346
347 status = pathconfig_set_from_config(pathconfig, config);
348 if (_PyStatus_EXCEPTION(status)) {
349 goto done;
350 }
351
352 if (_Py_path_config.module_search_path == NULL) {
353 status = _PyPathConfig_Calculate(pathconfig, config);
354 }
355 else {
356 /* Py_SetPath() has been called: avoid _PyPathConfig_Calculate() */
357 }
358
359done:
360 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
361 return status;
362}
363
364
Victor Stinner331a6a52019-05-27 16:39:22 +0200365static PyStatus
366config_calculate_pathconfig(PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200367{
Victor Stinner331a6a52019-05-27 16:39:22 +0200368 _PyPathConfig pathconfig = _PyPathConfig_INIT;
369 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200370
Victor Stinner331a6a52019-05-27 16:39:22 +0200371 status = pathconfig_calculate(&pathconfig, config);
372 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200373 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200374 }
375
Victor Stinner331a6a52019-05-27 16:39:22 +0200376 if (!config->module_search_paths_set) {
377 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) \
384 if (config->CONFIG_ATTR == NULL) { \
385 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
430_PyConfig_InitPathConfig(PyConfig *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 Stinner331a6a52019-05-27 16:39:22 +0200438 PyStatus status = config_calculate_pathconfig(config);
439 if (_PyStatus_EXCEPTION(status)) {
440 return status;
Victor Stinner1dc6e392018-07-25 02:49:17 +0200441 }
442 }
443
444 if (config->base_prefix == NULL) {
445 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
450 if (config->base_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
457 if (config->base_executable == NULL) {
458 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 Stinner9c42f8c2019-09-23 18:47:29 +0200468static PyStatus
469pathconfig_global_read(_PyPathConfig *pathconfig)
470{
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200471 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200472 _PyConfig_InitCompatConfig(&config);
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200473
474 /* Call _PyConfig_InitPathConfig() */
Victor Stinner8462a492019-10-01 12:06:16 +0200475 PyStatus status = PyConfig_Read(&config);
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200476 if (_PyStatus_EXCEPTION(status)) {
477 goto done;
478 }
479
480 status = pathconfig_set_from_config(pathconfig, &config);
481
482done:
483 PyConfig_Clear(&config);
484 return status;
485}
486
487
Victor Stinner31a83932017-12-04 13:39:15 +0100488static void
489pathconfig_global_init(void)
490{
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200491 PyStatus status;
492
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200493 if (_Py_path_config.module_search_path == NULL) {
494 status = pathconfig_global_read(&_Py_path_config);
495 if (_PyStatus_EXCEPTION(status)) {
496 Py_ExitStatusException(status);
497 }
498 }
499 else {
500 /* Global configuration already initialized */
Victor Stinner31a83932017-12-04 13:39:15 +0100501 }
502
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200503 assert(_Py_path_config.program_full_path != NULL);
504 assert(_Py_path_config.prefix != NULL);
505 assert(_Py_path_config.exec_prefix != NULL);
506 assert(_Py_path_config.module_search_path != NULL);
507 assert(_Py_path_config.program_name != NULL);
508 /* home can be NULL */
Victor Stinner8bf39b62019-09-26 02:22:35 +0200509#ifdef MS_WINDOWS
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200510 assert(_Py_path_config.base_executable != NULL);
Victor Stinner8bf39b62019-09-26 02:22:35 +0200511#endif
Victor Stinner31a83932017-12-04 13:39:15 +0100512}
513
514
515/* External interface */
516
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100517static void _Py_NO_RETURN
518path_out_of_memory(const char *func)
519{
520 _Py_FatalErrorFunc(func, "out of memory");
521}
522
Victor Stinner31a83932017-12-04 13:39:15 +0100523void
524Py_SetPath(const wchar_t *path)
525{
526 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200527 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100528 return;
529 }
530
531 PyMemAllocatorEx old_alloc;
532 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
533
Victor Stinner1ce152a2019-09-24 17:44:15 +0200534 /* Getting the program full path calls pathconfig_global_init() */
535 wchar_t *program_full_path = _PyMem_RawWcsdup(Py_GetProgramFullPath());
Victor Stinner31a83932017-12-04 13:39:15 +0100536
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200537 PyMem_RawFree(_Py_path_config.program_full_path);
538 PyMem_RawFree(_Py_path_config.prefix);
539 PyMem_RawFree(_Py_path_config.exec_prefix);
540 PyMem_RawFree(_Py_path_config.module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +0100541
Victor Stinner1ce152a2019-09-24 17:44:15 +0200542 _Py_path_config.program_full_path = program_full_path;
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200543 _Py_path_config.prefix = _PyMem_RawWcsdup(L"");
544 _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
545 _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinner31a83932017-12-04 13:39:15 +0100546
547 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200548
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200549 if (_Py_path_config.program_full_path == NULL
550 || _Py_path_config.prefix == NULL
551 || _Py_path_config.exec_prefix == NULL
552 || _Py_path_config.module_search_path == NULL)
553 {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100554 path_out_of_memory(__func__);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200555 }
Victor Stinner31a83932017-12-04 13:39:15 +0100556}
557
558
559void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200560Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100561{
562 if (home == NULL) {
563 return;
564 }
565
566 PyMemAllocatorEx old_alloc;
567 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
568
569 PyMem_RawFree(_Py_path_config.home);
570 _Py_path_config.home = _PyMem_RawWcsdup(home);
571
572 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
573
574 if (_Py_path_config.home == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100575 path_out_of_memory(__func__);
Victor Stinner31a83932017-12-04 13:39:15 +0100576 }
577}
578
579
580void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200581Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100582{
583 if (program_name == NULL || program_name[0] == L'\0') {
584 return;
585 }
586
587 PyMemAllocatorEx old_alloc;
588 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
589
590 PyMem_RawFree(_Py_path_config.program_name);
591 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
592
593 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
594
595 if (_Py_path_config.program_name == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100596 path_out_of_memory(__func__);
Victor Stinner31a83932017-12-04 13:39:15 +0100597 }
598}
599
Steve Dower177a41a2018-11-17 20:41:48 -0800600void
601_Py_SetProgramFullPath(const wchar_t *program_full_path)
602{
603 if (program_full_path == NULL || program_full_path[0] == L'\0') {
604 return;
605 }
606
607 PyMemAllocatorEx old_alloc;
608 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
609
610 PyMem_RawFree(_Py_path_config.program_full_path);
611 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
612
613 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
614
615 if (_Py_path_config.program_full_path == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100616 path_out_of_memory(__func__);
Steve Dower177a41a2018-11-17 20:41:48 -0800617 }
618}
619
Victor Stinner31a83932017-12-04 13:39:15 +0100620
621wchar_t *
622Py_GetPath(void)
623{
624 pathconfig_global_init();
625 return _Py_path_config.module_search_path;
626}
627
628
629wchar_t *
630Py_GetPrefix(void)
631{
632 pathconfig_global_init();
633 return _Py_path_config.prefix;
634}
635
636
637wchar_t *
638Py_GetExecPrefix(void)
639{
Victor Stinner31a83932017-12-04 13:39:15 +0100640 pathconfig_global_init();
641 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100642}
643
644
645wchar_t *
646Py_GetProgramFullPath(void)
647{
648 pathconfig_global_init();
649 return _Py_path_config.program_full_path;
650}
651
652
653wchar_t*
654Py_GetPythonHome(void)
655{
656 pathconfig_global_init();
657 return _Py_path_config.home;
658}
659
660
661wchar_t *
662Py_GetProgramName(void)
663{
664 pathconfig_global_init();
665 return _Py_path_config.program_name;
666}
667
Victor Stinnerdcf61712019-03-19 16:09:27 +0100668/* Compute module search path from argv[0] or the current working
669 directory ("-m module" case) which will be prepended to sys.argv:
670 sys.path[0].
671
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200672 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100673
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200674 Return 0 if it fails to resolve the full path. For example, return 0 if the
675 current working directory has been removed (bpo-36236) or if argv is empty.
676
677 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100678 */
679int
Victor Stinner331a6a52019-05-27 16:39:22 +0200680_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100681{
Victor Stinner331a6a52019-05-27 16:39:22 +0200682 assert(_PyWideStringList_CheckConsistency(argv));
Victor Stinner74f65682019-03-15 15:08:05 +0100683
Victor Stinnerfc96e542019-03-19 18:22:55 +0100684 if (argv->length == 0) {
685 /* Leave sys.path unchanged if sys.argv is empty */
686 return 0;
687 }
688
689 wchar_t *argv0 = argv->items[0];
690 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
691 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
692
693 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100694 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100695
696#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100697 wchar_t fullpath[MAXPATHLEN];
698#elif defined(MS_WINDOWS)
699 wchar_t fullpath[MAX_PATH];
700#endif
701
Nick Coghland5d9e022018-03-25 23:03:10 +1000702 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100703#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100704 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
705 return 0;
706 }
707 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100708#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100709 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100710#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100711 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000712 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100713
714#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100715 wchar_t link[MAXPATHLEN + 1];
716 int nr = 0;
Gregory P. Smith81328f32020-06-22 00:27:20 -0700717 wchar_t path0copy[2 * MAXPATHLEN + 1];
Victor Stinnerfc96e542019-03-19 18:22:55 +0100718
719 if (have_script_arg) {
720 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
721 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100722 if (nr > 0) {
723 /* It's a symlink */
724 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100725 if (link[0] == SEP) {
726 path0 = link; /* Link to absolute path */
727 }
728 else if (wcschr(link, SEP) == NULL) {
729 /* Link without path */
730 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100731 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100732 /* Must join(dirname(path0), link) */
733 wchar_t *q = wcsrchr(path0, SEP);
734 if (q == NULL) {
735 /* path0 without path */
736 path0 = link;
737 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100738 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100739 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100740 wcsncpy(path0copy, path0, MAXPATHLEN);
741 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100742 wcsncpy(q+1, link, MAXPATHLEN);
743 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100744 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100745 }
746 }
747 }
748#endif /* HAVE_READLINK */
749
Victor Stinnerfc96e542019-03-19 18:22:55 +0100750 wchar_t *p = NULL;
751
Victor Stinner11a247d2017-12-13 21:05:57 +0100752#if SEP == '\\'
753 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000754 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100755 wchar_t *q;
756#if defined(MS_WINDOWS)
757 /* Replace the first element in argv with the full path. */
758 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100759 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100760 Py_ARRAY_LENGTH(fullpath),
761 fullpath,
762 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100763 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100764 }
765#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100766 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100767 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100768 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100769 if (q != NULL)
770 p = q;
771 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100772 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100773 if (n > 1 && p[-1] != ':')
774 n--; /* Drop trailing separator */
775 }
776 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100777#else
778 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000779 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100780#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100781 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
782 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100783 }
784#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100785 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100786 }
787 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100788 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100789#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100790 if (n > 1) {
791 /* Drop trailing separator */
792 n--;
793 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100794#endif /* Unix */
795 }
796#endif /* All others */
797
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200798 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
799 if (path0_obj == NULL) {
800 return -1;
801 }
802
803 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100804 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100805}
806
Victor Stinner9bee3292017-12-21 16:49:13 +0100807
Minmin Gong8ebc6452019-02-02 20:26:55 -0800808#ifdef MS_WINDOWS
809#define WCSTOK wcstok_s
810#else
811#define WCSTOK wcstok
812#endif
813
Victor Stinner9bee3292017-12-21 16:49:13 +0100814/* Search for a prefix value in an environment file (pyvenv.cfg).
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200815
816 - If found, copy it into *value_p: string which must be freed by
817 PyMem_RawFree().
818 - If not found, *value_p is set to NULL.
819*/
820PyStatus
Victor Stinner9bee3292017-12-21 16:49:13 +0100821_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200822 wchar_t **value_p)
Victor Stinner9bee3292017-12-21 16:49:13 +0100823{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200824 *value_p = NULL;
825
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100826 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
827 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100828
Victor Stinner9bee3292017-12-21 16:49:13 +0100829 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100830 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100831
832 if (p == NULL) {
833 break;
834 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100835
836 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100837 if (p[n - 1] != '\n') {
838 /* line has overflowed - bail */
839 break;
840 }
841 if (p[0] == '#') {
842 /* Comment - skip */
843 continue;
844 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100845
Victor Stinner5f9cf232019-03-19 01:46:25 +0100846 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100847 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100848 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800849 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100850 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800851 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100852 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800853 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100854 if (tok != NULL) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200855 *value_p = _PyMem_RawWcsdup(tok);
Victor Stinner9bee3292017-12-21 16:49:13 +0100856 PyMem_RawFree(tmpbuffer);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200857
858 if (*value_p == NULL) {
859 return _PyStatus_NO_MEMORY();
860 }
861
862 /* found */
863 return _PyStatus_OK();
Victor Stinner9bee3292017-12-21 16:49:13 +0100864 }
865 }
866 }
867 PyMem_RawFree(tmpbuffer);
868 }
869 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200870
871 /* not found */
872 return _PyStatus_OK();
Victor Stinner9bee3292017-12-21 16:49:13 +0100873}
874
Victor Stinner31a83932017-12-04 13:39:15 +0100875#ifdef __cplusplus
876}
877#endif