blob: 5c38041d7667bdb3df1607fde2d22d02bd36d211 [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;
Victor Stinnerc4221672019-09-21 01:02:56 +020020#ifdef MS_WINDOWS
21wchar_t *_Py_dll_path = NULL;
22#endif
Victor Stinner31a83932017-12-04 13:39:15 +010023
24
Victor Stinnerb1147e42018-07-21 02:06:16 +020025static int
26copy_wstr(wchar_t **dst, const wchar_t *src)
27{
Victor Stinner1ce152a2019-09-24 17:44:15 +020028 assert(*dst == NULL);
Victor Stinnerb1147e42018-07-21 02:06:16 +020029 if (src != NULL) {
30 *dst = _PyMem_RawWcsdup(src);
31 if (*dst == NULL) {
32 return -1;
33 }
34 }
35 else {
36 *dst = NULL;
37 }
38 return 0;
39}
40
41
42static void
Victor Stinner331a6a52019-05-27 16:39:22 +020043pathconfig_clear(_PyPathConfig *config)
Victor Stinner31a83932017-12-04 13:39:15 +010044{
45 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
46 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
47 called before Py_Initialize() which can changes the memory allocator. */
48 PyMemAllocatorEx old_alloc;
49 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
50
51#define CLEAR(ATTR) \
52 do { \
53 PyMem_RawFree(ATTR); \
54 ATTR = NULL; \
55 } while (0)
56
Victor Stinner31a83932017-12-04 13:39:15 +010057 CLEAR(config->program_full_path);
Victor Stinner9c42f8c2019-09-23 18:47:29 +020058 CLEAR(config->prefix);
Steve Dower177a41a2018-11-17 20:41:48 -080059 CLEAR(config->exec_prefix);
Victor Stinner31a83932017-12-04 13:39:15 +010060 CLEAR(config->module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +010061 CLEAR(config->program_name);
Victor Stinner9c42f8c2019-09-23 18:47:29 +020062 CLEAR(config->home);
Victor Stinner8bf39b62019-09-26 02:22:35 +020063#ifdef MS_WINDOWS
Steve Dower9048c492019-06-29 10:34:11 -070064 CLEAR(config->base_executable);
Victor Stinner8bf39b62019-09-26 02:22:35 +020065#endif
66
Victor Stinner31a83932017-12-04 13:39:15 +010067#undef CLEAR
68
69 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
70}
71
72
Victor Stinner331a6a52019-05-27 16:39:22 +020073static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +020074pathconfig_copy(_PyPathConfig *config, const _PyPathConfig *config2)
Victor Stinner31a83932017-12-04 13:39:15 +010075{
Victor Stinner9c42f8c2019-09-23 18:47:29 +020076 pathconfig_clear(config);
Victor Stinner31a83932017-12-04 13:39:15 +010077
Victor Stinner9c42f8c2019-09-23 18:47:29 +020078#define COPY_ATTR(ATTR) \
79 do { \
80 if (copy_wstr(&config->ATTR, config2->ATTR) < 0) { \
81 return _PyStatus_NO_MEMORY(); \
82 } \
83 } while (0)
Victor Stinner31a83932017-12-04 13:39:15 +010084
Victor Stinner9c42f8c2019-09-23 18:47:29 +020085 COPY_ATTR(program_full_path);
86 COPY_ATTR(prefix);
87 COPY_ATTR(exec_prefix);
88 COPY_ATTR(module_search_path);
89 COPY_ATTR(program_name);
90 COPY_ATTR(home);
Victor Stinner8bf39b62019-09-26 02:22:35 +020091#ifdef MS_WINDOWS
Victor Stinner9c42f8c2019-09-23 18:47:29 +020092 config->isolated = config2->isolated;
93 config->site_import = config2->site_import;
94 COPY_ATTR(base_executable);
Victor Stinner8bf39b62019-09-26 02:22:35 +020095#endif
Victor Stinnere2677932019-09-21 01:50:16 +020096
Victor Stinner9c42f8c2019-09-23 18:47:29 +020097#undef COPY_ATTR
Victor Stinner31a83932017-12-04 13:39:15 +010098
Victor Stinner9c42f8c2019-09-23 18:47:29 +020099 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200100}
101
102
Victor Stinnerb1147e42018-07-21 02:06:16 +0200103void
104_PyPathConfig_ClearGlobal(void)
105{
Victor Stinnerc1834442019-03-18 22:24:28 +0100106 PyMemAllocatorEx old_alloc;
107 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
108
Victor Stinner331a6a52019-05-27 16:39:22 +0200109 pathconfig_clear(&_Py_path_config);
Victor Stinnerc4221672019-09-21 01:02:56 +0200110#ifdef MS_WINDOWS
111 PyMem_RawFree(_Py_dll_path);
112 _Py_dll_path = NULL;
113#endif
Victor Stinnerc1834442019-03-18 22:24:28 +0100114
115 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200116}
117
118
119static wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200120_PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200121{
122 size_t len = 1; /* NUL terminator */
Victor Stinner74f65682019-03-15 15:08:05 +0100123 for (Py_ssize_t i=0; i < list->length; i++) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200124 if (i != 0) {
125 len++;
126 }
Victor Stinner74f65682019-03-15 15:08:05 +0100127 len += wcslen(list->items[i]);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200128 }
129
130 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
131 if (text == NULL) {
132 return NULL;
133 }
134 wchar_t *str = text;
Victor Stinner74f65682019-03-15 15:08:05 +0100135 for (Py_ssize_t i=0; i < list->length; i++) {
136 wchar_t *path = list->items[i];
Victor Stinnerb1147e42018-07-21 02:06:16 +0200137 if (i != 0) {
Victor Stinner12f2f172019-09-26 15:51:50 +0200138 *str++ = sep;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200139 }
140 len = wcslen(path);
141 memcpy(str, path, len * sizeof(wchar_t));
142 str += len;
143 }
144 *str = L'\0';
145
146 return text;
147}
148
149
Victor Stinnerc4221672019-09-21 01:02:56 +0200150#ifdef MS_WINDOWS
Victor Stinner12f2f172019-09-26 15:51:50 +0200151/* Initialize _Py_dll_path on Windows. Do nothing on other platforms. */
152static PyStatus
153_PyPathConfig_InitDLLPath(void)
154{
Anthony Wee7b79dc92020-01-06 08:57:34 -0800155 if (_Py_dll_path != NULL) {
Victor Stinnerc4221672019-09-21 01:02:56 +0200156 /* Already set: nothing to do */
157 return _PyStatus_OK();
158 }
159
Victor Stinnerb1147e42018-07-21 02:06:16 +0200160 PyMemAllocatorEx old_alloc;
161 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
162
Victor Stinnerc4221672019-09-21 01:02:56 +0200163 _Py_dll_path = _Py_GetDLLPath();
164
165 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
166
167 if (_Py_dll_path == NULL) {
168 return _PyStatus_NO_MEMORY();
169 }
Victor Stinnerc4221672019-09-21 01:02:56 +0200170 return _PyStatus_OK();
171}
Victor Stinner12f2f172019-09-26 15:51:50 +0200172#endif
Victor Stinnerc4221672019-09-21 01:02:56 +0200173
174
175static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200176pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config)
Victor Stinnerc4221672019-09-21 01:02:56 +0200177{
Victor Stinner331a6a52019-05-27 16:39:22 +0200178 PyStatus status;
Victor Stinnerc4221672019-09-21 01:02:56 +0200179 PyMemAllocatorEx old_alloc;
180 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
181
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200182 if (config->module_search_paths_set) {
Victor Stinner1ce152a2019-09-24 17:44:15 +0200183 PyMem_RawFree(pathconfig->module_search_path);
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200184 pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
185 if (pathconfig->module_search_path == NULL) {
186 goto no_memory;
187 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200188 }
189
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200190#define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \
191 if (config->CONFIG_ATTR) { \
Victor Stinner1ce152a2019-09-24 17:44:15 +0200192 PyMem_RawFree(pathconfig->PATH_ATTR); \
193 pathconfig->PATH_ATTR = NULL; \
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200194 if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \
195 goto no_memory; \
196 } \
197 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200198
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200199 COPY_CONFIG(program_full_path, executable);
200 COPY_CONFIG(prefix, prefix);
201 COPY_CONFIG(exec_prefix, exec_prefix);
202 COPY_CONFIG(program_name, program_name);
203 COPY_CONFIG(home, home);
Victor Stinner8bf39b62019-09-26 02:22:35 +0200204#ifdef MS_WINDOWS
205 COPY_CONFIG(base_executable, base_executable);
206#endif
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200207
208#undef COPY_CONFIG
Victor Stinnerb1147e42018-07-21 02:06:16 +0200209
Victor Stinner331a6a52019-05-27 16:39:22 +0200210 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200211 goto done;
212
213no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200214 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200215
216done:
Victor Stinnerb1147e42018-07-21 02:06:16 +0200217 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200218 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200219}
220
221
Victor Stinner12f2f172019-09-26 15:51:50 +0200222PyStatus
223_PyConfig_WritePathConfig(const PyConfig *config)
224{
225#ifdef MS_WINDOWS
226 PyStatus status = _PyPathConfig_InitDLLPath();
227 if (_PyStatus_EXCEPTION(status)) {
228 return status;
229 }
230#endif
231
232 return pathconfig_set_from_config(&_Py_path_config, config);
233}
234
235
Victor Stinner331a6a52019-05-27 16:39:22 +0200236static PyStatus
237config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200238{
Victor Stinner331a6a52019-05-27 16:39:22 +0200239 assert(!config->module_search_paths_set);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200240
Victor Stinner331a6a52019-05-27 16:39:22 +0200241 _PyWideStringList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200242
Victor Stinner331a6a52019-05-27 16:39:22 +0200243 const wchar_t *sys_path = pathconfig->module_search_path;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200244 const wchar_t delim = DELIM;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200245 while (1) {
Alex Henrief3e5e952020-01-09 09:14:11 +0000246 const wchar_t *p = wcschr(sys_path, delim);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200247 if (p == NULL) {
248 p = sys_path + wcslen(sys_path); /* End of string */
249 }
250
251 size_t path_len = (p - sys_path);
252 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
253 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200254 return _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200255 }
256 memcpy(path, sys_path, path_len * sizeof(wchar_t));
257 path[path_len] = L'\0';
258
Victor Stinner331a6a52019-05-27 16:39:22 +0200259 PyStatus status = PyWideStringList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200260 PyMem_RawFree(path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200261 if (_PyStatus_EXCEPTION(status)) {
262 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200263 }
264
265 if (*p == '\0') {
266 break;
267 }
268 sys_path = p + 1;
269 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200270 config->module_search_paths_set = 1;
271 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200272}
273
274
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200275/* Calculate the path configuration:
276
277 - exec_prefix
278 - module_search_path
279 - prefix
280 - program_full_path
281
282 On Windows, more fields are calculated:
283
284 - base_executable
285 - isolated
286 - site_import
287
288 On other platforms, isolated and site_import are left unchanged, and
289 _PyConfig_InitPathConfig() copies executable to base_executable (if it's not
290 set).
291
292 Priority, highest to lowest:
293
294 - PyConfig
295 - _Py_path_config: set by Py_SetPath(), Py_SetPythonHome()
296 and Py_SetProgramName()
297 - _PyPathConfig_Calculate()
298*/
299static PyStatus
300pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
301{
302 PyStatus status;
303
304 PyMemAllocatorEx old_alloc;
305 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
306
307 status = pathconfig_copy(pathconfig, &_Py_path_config);
308 if (_PyStatus_EXCEPTION(status)) {
309 goto done;
310 }
311
312 status = pathconfig_set_from_config(pathconfig, config);
313 if (_PyStatus_EXCEPTION(status)) {
314 goto done;
315 }
316
317 if (_Py_path_config.module_search_path == NULL) {
318 status = _PyPathConfig_Calculate(pathconfig, config);
319 }
320 else {
321 /* Py_SetPath() has been called: avoid _PyPathConfig_Calculate() */
322 }
323
324done:
325 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
326 return status;
327}
328
329
Victor Stinner331a6a52019-05-27 16:39:22 +0200330static PyStatus
331config_calculate_pathconfig(PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200332{
Victor Stinner331a6a52019-05-27 16:39:22 +0200333 _PyPathConfig pathconfig = _PyPathConfig_INIT;
334 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200335
Victor Stinner331a6a52019-05-27 16:39:22 +0200336 status = pathconfig_calculate(&pathconfig, config);
337 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200338 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200339 }
340
Victor Stinner331a6a52019-05-27 16:39:22 +0200341 if (!config->module_search_paths_set) {
342 status = config_init_module_search_paths(config, &pathconfig);
343 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200344 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200345 }
346 }
347
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200348#define COPY_ATTR(PATH_ATTR, CONFIG_ATTR) \
349 if (config->CONFIG_ATTR == NULL) { \
350 if (copy_wstr(&config->CONFIG_ATTR, pathconfig.PATH_ATTR) < 0) { \
351 goto no_memory; \
352 } \
Victor Stinnerb1147e42018-07-21 02:06:16 +0200353 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200354
Victor Stinner8bf39b62019-09-26 02:22:35 +0200355#ifdef MS_WINDOWS
356 if (config->executable != NULL && config->base_executable == NULL) {
357 /* If executable is set explicitly in the configuration,
358 ignore calculated base_executable: _PyConfig_InitPathConfig()
359 will copy executable to base_executable */
360 }
361 else {
362 COPY_ATTR(base_executable, base_executable);
363 }
364#endif
365
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200366 COPY_ATTR(program_full_path, executable);
367 COPY_ATTR(prefix, prefix);
368 COPY_ATTR(exec_prefix, exec_prefix);
Victor Stinner8bf39b62019-09-26 02:22:35 +0200369
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200370#undef COPY_ATTR
Steve Dower9048c492019-06-29 10:34:11 -0700371
Victor Stinner8bf39b62019-09-26 02:22:35 +0200372#ifdef MS_WINDOWS
373 /* If a ._pth file is found: isolated and site_import are overriden */
Victor Stinner331a6a52019-05-27 16:39:22 +0200374 if (pathconfig.isolated != -1) {
375 config->isolated = pathconfig.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200376 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200377 if (pathconfig.site_import != -1) {
378 config->site_import = pathconfig.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200379 }
Victor Stinner8bf39b62019-09-26 02:22:35 +0200380#endif
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200381
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200382 status = _PyStatus_OK();
383 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200384
385no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200386 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200387
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200388done:
Victor Stinner331a6a52019-05-27 16:39:22 +0200389 pathconfig_clear(&pathconfig);
390 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200391}
392
393
Victor Stinner331a6a52019-05-27 16:39:22 +0200394PyStatus
395_PyConfig_InitPathConfig(PyConfig *config)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200396{
397 /* Do we need to calculate the path? */
Victor Stinner331a6a52019-05-27 16:39:22 +0200398 if (!config->module_search_paths_set
Victor Stinner8bf39b62019-09-26 02:22:35 +0200399 || config->executable == NULL
400 || config->prefix == NULL
401 || config->exec_prefix == NULL)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200402 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200403 PyStatus status = config_calculate_pathconfig(config);
404 if (_PyStatus_EXCEPTION(status)) {
405 return status;
Victor Stinner1dc6e392018-07-25 02:49:17 +0200406 }
407 }
408
409 if (config->base_prefix == NULL) {
410 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200411 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200412 }
413 }
414
415 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800416 if (copy_wstr(&config->base_exec_prefix,
417 config->exec_prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200418 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200419 }
420 }
Steve Dower9048c492019-06-29 10:34:11 -0700421
422 if (config->base_executable == NULL) {
423 if (copy_wstr(&config->base_executable,
424 config->executable) < 0) {
425 return _PyStatus_NO_MEMORY();
426 }
427 }
428
Victor Stinner331a6a52019-05-27 16:39:22 +0200429 return _PyStatus_OK();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200430}
431
432
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200433static PyStatus
434pathconfig_global_read(_PyPathConfig *pathconfig)
435{
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200436 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200437 _PyConfig_InitCompatConfig(&config);
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200438
439 /* Call _PyConfig_InitPathConfig() */
Victor Stinner8462a492019-10-01 12:06:16 +0200440 PyStatus status = PyConfig_Read(&config);
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200441 if (_PyStatus_EXCEPTION(status)) {
442 goto done;
443 }
444
445 status = pathconfig_set_from_config(pathconfig, &config);
446
447done:
448 PyConfig_Clear(&config);
449 return status;
450}
451
452
Victor Stinner31a83932017-12-04 13:39:15 +0100453static void
454pathconfig_global_init(void)
455{
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200456 PyStatus status;
457
Victor Stinner12f2f172019-09-26 15:51:50 +0200458#ifdef MS_WINDOWS
459 status = _PyPathConfig_InitDLLPath();
Victor Stinnerc4221672019-09-21 01:02:56 +0200460 if (_PyStatus_EXCEPTION(status)) {
461 Py_ExitStatusException(status);
462 }
Victor Stinner12f2f172019-09-26 15:51:50 +0200463#endif
Victor Stinnerc4221672019-09-21 01:02:56 +0200464
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200465 if (_Py_path_config.module_search_path == NULL) {
466 status = pathconfig_global_read(&_Py_path_config);
467 if (_PyStatus_EXCEPTION(status)) {
468 Py_ExitStatusException(status);
469 }
470 }
471 else {
472 /* Global configuration already initialized */
Victor Stinner31a83932017-12-04 13:39:15 +0100473 }
474
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200475 assert(_Py_path_config.program_full_path != NULL);
476 assert(_Py_path_config.prefix != NULL);
477 assert(_Py_path_config.exec_prefix != NULL);
478 assert(_Py_path_config.module_search_path != NULL);
479 assert(_Py_path_config.program_name != NULL);
480 /* home can be NULL */
Victor Stinner8bf39b62019-09-26 02:22:35 +0200481#ifdef MS_WINDOWS
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200482 assert(_Py_path_config.base_executable != NULL);
Victor Stinner8bf39b62019-09-26 02:22:35 +0200483#endif
Victor Stinner31a83932017-12-04 13:39:15 +0100484}
485
486
487/* External interface */
488
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100489static void _Py_NO_RETURN
490path_out_of_memory(const char *func)
491{
492 _Py_FatalErrorFunc(func, "out of memory");
493}
494
Victor Stinner31a83932017-12-04 13:39:15 +0100495void
496Py_SetPath(const wchar_t *path)
497{
498 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200499 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100500 return;
501 }
502
503 PyMemAllocatorEx old_alloc;
504 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
505
Victor Stinner1ce152a2019-09-24 17:44:15 +0200506 /* Getting the program full path calls pathconfig_global_init() */
507 wchar_t *program_full_path = _PyMem_RawWcsdup(Py_GetProgramFullPath());
Victor Stinner31a83932017-12-04 13:39:15 +0100508
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200509 PyMem_RawFree(_Py_path_config.program_full_path);
510 PyMem_RawFree(_Py_path_config.prefix);
511 PyMem_RawFree(_Py_path_config.exec_prefix);
512 PyMem_RawFree(_Py_path_config.module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +0100513
Victor Stinner1ce152a2019-09-24 17:44:15 +0200514 _Py_path_config.program_full_path = program_full_path;
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200515 _Py_path_config.prefix = _PyMem_RawWcsdup(L"");
516 _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
517 _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinner31a83932017-12-04 13:39:15 +0100518
519 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200520
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200521 if (_Py_path_config.program_full_path == NULL
522 || _Py_path_config.prefix == NULL
523 || _Py_path_config.exec_prefix == NULL
524 || _Py_path_config.module_search_path == NULL)
525 {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100526 path_out_of_memory(__func__);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200527 }
Victor Stinner31a83932017-12-04 13:39:15 +0100528}
529
530
531void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200532Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100533{
534 if (home == NULL) {
535 return;
536 }
537
538 PyMemAllocatorEx old_alloc;
539 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
540
541 PyMem_RawFree(_Py_path_config.home);
542 _Py_path_config.home = _PyMem_RawWcsdup(home);
543
544 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
545
546 if (_Py_path_config.home == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100547 path_out_of_memory(__func__);
Victor Stinner31a83932017-12-04 13:39:15 +0100548 }
549}
550
551
552void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200553Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100554{
555 if (program_name == NULL || program_name[0] == L'\0') {
556 return;
557 }
558
559 PyMemAllocatorEx old_alloc;
560 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
561
562 PyMem_RawFree(_Py_path_config.program_name);
563 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
564
565 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
566
567 if (_Py_path_config.program_name == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100568 path_out_of_memory(__func__);
Victor Stinner31a83932017-12-04 13:39:15 +0100569 }
570}
571
Steve Dower177a41a2018-11-17 20:41:48 -0800572void
573_Py_SetProgramFullPath(const wchar_t *program_full_path)
574{
575 if (program_full_path == NULL || program_full_path[0] == L'\0') {
576 return;
577 }
578
579 PyMemAllocatorEx old_alloc;
580 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
581
582 PyMem_RawFree(_Py_path_config.program_full_path);
583 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
584
585 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
586
587 if (_Py_path_config.program_full_path == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100588 path_out_of_memory(__func__);
Steve Dower177a41a2018-11-17 20:41:48 -0800589 }
590}
591
Victor Stinner31a83932017-12-04 13:39:15 +0100592
593wchar_t *
594Py_GetPath(void)
595{
596 pathconfig_global_init();
597 return _Py_path_config.module_search_path;
598}
599
600
601wchar_t *
602Py_GetPrefix(void)
603{
604 pathconfig_global_init();
605 return _Py_path_config.prefix;
606}
607
608
609wchar_t *
610Py_GetExecPrefix(void)
611{
Victor Stinner31a83932017-12-04 13:39:15 +0100612 pathconfig_global_init();
613 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100614}
615
616
617wchar_t *
618Py_GetProgramFullPath(void)
619{
620 pathconfig_global_init();
621 return _Py_path_config.program_full_path;
622}
623
624
625wchar_t*
626Py_GetPythonHome(void)
627{
628 pathconfig_global_init();
629 return _Py_path_config.home;
630}
631
632
633wchar_t *
634Py_GetProgramName(void)
635{
636 pathconfig_global_init();
637 return _Py_path_config.program_name;
638}
639
Victor Stinnerdcf61712019-03-19 16:09:27 +0100640/* Compute module search path from argv[0] or the current working
641 directory ("-m module" case) which will be prepended to sys.argv:
642 sys.path[0].
643
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200644 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100645
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200646 Return 0 if it fails to resolve the full path. For example, return 0 if the
647 current working directory has been removed (bpo-36236) or if argv is empty.
648
649 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100650 */
651int
Victor Stinner331a6a52019-05-27 16:39:22 +0200652_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100653{
Victor Stinner331a6a52019-05-27 16:39:22 +0200654 assert(_PyWideStringList_CheckConsistency(argv));
Victor Stinner74f65682019-03-15 15:08:05 +0100655
Victor Stinnerfc96e542019-03-19 18:22:55 +0100656 if (argv->length == 0) {
657 /* Leave sys.path unchanged if sys.argv is empty */
658 return 0;
659 }
660
661 wchar_t *argv0 = argv->items[0];
662 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
663 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
664
665 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100666 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100667
668#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100669 wchar_t fullpath[MAXPATHLEN];
670#elif defined(MS_WINDOWS)
671 wchar_t fullpath[MAX_PATH];
672#endif
673
Nick Coghland5d9e022018-03-25 23:03:10 +1000674 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100675#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100676 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
677 return 0;
678 }
679 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100680#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100681 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100682#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100683 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000684 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100685
686#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100687 wchar_t link[MAXPATHLEN + 1];
688 int nr = 0;
Gregory P. Smith81328f32020-06-22 00:27:20 -0700689 wchar_t path0copy[2 * MAXPATHLEN + 1];
Victor Stinnerfc96e542019-03-19 18:22:55 +0100690
691 if (have_script_arg) {
692 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
693 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100694 if (nr > 0) {
695 /* It's a symlink */
696 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100697 if (link[0] == SEP) {
698 path0 = link; /* Link to absolute path */
699 }
700 else if (wcschr(link, SEP) == NULL) {
701 /* Link without path */
702 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100703 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100704 /* Must join(dirname(path0), link) */
705 wchar_t *q = wcsrchr(path0, SEP);
706 if (q == NULL) {
707 /* path0 without path */
708 path0 = link;
709 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100710 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100711 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100712 wcsncpy(path0copy, path0, MAXPATHLEN);
713 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100714 wcsncpy(q+1, link, MAXPATHLEN);
715 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100716 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100717 }
718 }
719 }
720#endif /* HAVE_READLINK */
721
Victor Stinnerfc96e542019-03-19 18:22:55 +0100722 wchar_t *p = NULL;
723
Victor Stinner11a247d2017-12-13 21:05:57 +0100724#if SEP == '\\'
725 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000726 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100727 wchar_t *q;
728#if defined(MS_WINDOWS)
729 /* Replace the first element in argv with the full path. */
730 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100731 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100732 Py_ARRAY_LENGTH(fullpath),
733 fullpath,
734 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100735 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100736 }
737#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100738 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100739 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100740 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100741 if (q != NULL)
742 p = q;
743 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100744 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100745 if (n > 1 && p[-1] != ':')
746 n--; /* Drop trailing separator */
747 }
748 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100749#else
750 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000751 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100752#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100753 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
754 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100755 }
756#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100757 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100758 }
759 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100760 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100761#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100762 if (n > 1) {
763 /* Drop trailing separator */
764 n--;
765 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100766#endif /* Unix */
767 }
768#endif /* All others */
769
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200770 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
771 if (path0_obj == NULL) {
772 return -1;
773 }
774
775 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100776 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100777}
778
Victor Stinner9bee3292017-12-21 16:49:13 +0100779
Minmin Gong8ebc6452019-02-02 20:26:55 -0800780#ifdef MS_WINDOWS
781#define WCSTOK wcstok_s
782#else
783#define WCSTOK wcstok
784#endif
785
Victor Stinner9bee3292017-12-21 16:49:13 +0100786/* Search for a prefix value in an environment file (pyvenv.cfg).
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200787
788 - If found, copy it into *value_p: string which must be freed by
789 PyMem_RawFree().
790 - If not found, *value_p is set to NULL.
791*/
792PyStatus
Victor Stinner9bee3292017-12-21 16:49:13 +0100793_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200794 wchar_t **value_p)
Victor Stinner9bee3292017-12-21 16:49:13 +0100795{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200796 *value_p = NULL;
797
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100798 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
799 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100800
Victor Stinner9bee3292017-12-21 16:49:13 +0100801 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100802 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100803
804 if (p == NULL) {
805 break;
806 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100807
808 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100809 if (p[n - 1] != '\n') {
810 /* line has overflowed - bail */
811 break;
812 }
813 if (p[0] == '#') {
814 /* Comment - skip */
815 continue;
816 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100817
Victor Stinner5f9cf232019-03-19 01:46:25 +0100818 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100819 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100820 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800821 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100822 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800823 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100824 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800825 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100826 if (tok != NULL) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200827 *value_p = _PyMem_RawWcsdup(tok);
Victor Stinner9bee3292017-12-21 16:49:13 +0100828 PyMem_RawFree(tmpbuffer);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200829
830 if (*value_p == NULL) {
831 return _PyStatus_NO_MEMORY();
832 }
833
834 /* found */
835 return _PyStatus_OK();
Victor Stinner9bee3292017-12-21 16:49:13 +0100836 }
837 }
838 }
839 PyMem_RawFree(tmpbuffer);
840 }
841 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200842
843 /* not found */
844 return _PyStatus_OK();
Victor Stinner9bee3292017-12-21 16:49:13 +0100845}
846
Victor Stinner31a83932017-12-04 13:39:15 +0100847#ifdef __cplusplus
848}
849#endif