blob: 9a302213e77b654cee0595bd448b263d91c22e10 [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
189
Victor Stinner12f2f172019-09-26 15:51:50 +0200190PyStatus
191_PyConfig_WritePathConfig(const PyConfig *config)
192{
Victor Stinner12f2f172019-09-26 15:51:50 +0200193 return pathconfig_set_from_config(&_Py_path_config, config);
194}
195
196
Victor Stinner331a6a52019-05-27 16:39:22 +0200197static PyStatus
198config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200199{
Victor Stinner331a6a52019-05-27 16:39:22 +0200200 assert(!config->module_search_paths_set);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200201
Victor Stinner331a6a52019-05-27 16:39:22 +0200202 _PyWideStringList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200203
Victor Stinner331a6a52019-05-27 16:39:22 +0200204 const wchar_t *sys_path = pathconfig->module_search_path;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200205 const wchar_t delim = DELIM;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200206 while (1) {
Alex Henrief3e5e952020-01-09 09:14:11 +0000207 const wchar_t *p = wcschr(sys_path, delim);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200208 if (p == NULL) {
209 p = sys_path + wcslen(sys_path); /* End of string */
210 }
211
212 size_t path_len = (p - sys_path);
213 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
214 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200215 return _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200216 }
217 memcpy(path, sys_path, path_len * sizeof(wchar_t));
218 path[path_len] = L'\0';
219
Victor Stinner331a6a52019-05-27 16:39:22 +0200220 PyStatus status = PyWideStringList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200221 PyMem_RawFree(path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200222 if (_PyStatus_EXCEPTION(status)) {
223 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200224 }
225
226 if (*p == '\0') {
227 break;
228 }
229 sys_path = p + 1;
230 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200231 config->module_search_paths_set = 1;
232 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200233}
234
235
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200236/* Calculate the path configuration:
237
238 - exec_prefix
239 - module_search_path
240 - prefix
241 - program_full_path
242
243 On Windows, more fields are calculated:
244
245 - base_executable
246 - isolated
247 - site_import
248
249 On other platforms, isolated and site_import are left unchanged, and
250 _PyConfig_InitPathConfig() copies executable to base_executable (if it's not
251 set).
252
253 Priority, highest to lowest:
254
255 - PyConfig
256 - _Py_path_config: set by Py_SetPath(), Py_SetPythonHome()
257 and Py_SetProgramName()
258 - _PyPathConfig_Calculate()
259*/
260static PyStatus
261pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
262{
263 PyStatus status;
264
265 PyMemAllocatorEx old_alloc;
266 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
267
268 status = pathconfig_copy(pathconfig, &_Py_path_config);
269 if (_PyStatus_EXCEPTION(status)) {
270 goto done;
271 }
272
273 status = pathconfig_set_from_config(pathconfig, config);
274 if (_PyStatus_EXCEPTION(status)) {
275 goto done;
276 }
277
278 if (_Py_path_config.module_search_path == NULL) {
279 status = _PyPathConfig_Calculate(pathconfig, config);
280 }
281 else {
282 /* Py_SetPath() has been called: avoid _PyPathConfig_Calculate() */
283 }
284
285done:
286 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
287 return status;
288}
289
290
Victor Stinner331a6a52019-05-27 16:39:22 +0200291static PyStatus
292config_calculate_pathconfig(PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200293{
Victor Stinner331a6a52019-05-27 16:39:22 +0200294 _PyPathConfig pathconfig = _PyPathConfig_INIT;
295 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200296
Victor Stinner331a6a52019-05-27 16:39:22 +0200297 status = pathconfig_calculate(&pathconfig, config);
298 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200299 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200300 }
301
Victor Stinner331a6a52019-05-27 16:39:22 +0200302 if (!config->module_search_paths_set) {
303 status = config_init_module_search_paths(config, &pathconfig);
304 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200305 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200306 }
307 }
308
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200309#define COPY_ATTR(PATH_ATTR, CONFIG_ATTR) \
310 if (config->CONFIG_ATTR == NULL) { \
311 if (copy_wstr(&config->CONFIG_ATTR, pathconfig.PATH_ATTR) < 0) { \
312 goto no_memory; \
313 } \
Victor Stinnerb1147e42018-07-21 02:06:16 +0200314 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200315
Victor Stinner8bf39b62019-09-26 02:22:35 +0200316#ifdef MS_WINDOWS
317 if (config->executable != NULL && config->base_executable == NULL) {
318 /* If executable is set explicitly in the configuration,
319 ignore calculated base_executable: _PyConfig_InitPathConfig()
320 will copy executable to base_executable */
321 }
322 else {
323 COPY_ATTR(base_executable, base_executable);
324 }
325#endif
326
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200327 COPY_ATTR(program_full_path, executable);
328 COPY_ATTR(prefix, prefix);
329 COPY_ATTR(exec_prefix, exec_prefix);
Victor Stinner8bf39b62019-09-26 02:22:35 +0200330
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200331#undef COPY_ATTR
Steve Dower9048c492019-06-29 10:34:11 -0700332
Victor Stinner8bf39b62019-09-26 02:22:35 +0200333#ifdef MS_WINDOWS
334 /* If a ._pth file is found: isolated and site_import are overriden */
Victor Stinner331a6a52019-05-27 16:39:22 +0200335 if (pathconfig.isolated != -1) {
336 config->isolated = pathconfig.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200337 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200338 if (pathconfig.site_import != -1) {
339 config->site_import = pathconfig.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200340 }
Victor Stinner8bf39b62019-09-26 02:22:35 +0200341#endif
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200342
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200343 status = _PyStatus_OK();
344 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200345
346no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200347 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200348
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200349done:
Victor Stinner331a6a52019-05-27 16:39:22 +0200350 pathconfig_clear(&pathconfig);
351 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200352}
353
354
Victor Stinner331a6a52019-05-27 16:39:22 +0200355PyStatus
356_PyConfig_InitPathConfig(PyConfig *config)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200357{
358 /* Do we need to calculate the path? */
Victor Stinner331a6a52019-05-27 16:39:22 +0200359 if (!config->module_search_paths_set
Victor Stinner8bf39b62019-09-26 02:22:35 +0200360 || config->executable == NULL
361 || config->prefix == NULL
362 || config->exec_prefix == NULL)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200363 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200364 PyStatus status = config_calculate_pathconfig(config);
365 if (_PyStatus_EXCEPTION(status)) {
366 return status;
Victor Stinner1dc6e392018-07-25 02:49:17 +0200367 }
368 }
369
370 if (config->base_prefix == NULL) {
371 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200372 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200373 }
374 }
375
376 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800377 if (copy_wstr(&config->base_exec_prefix,
378 config->exec_prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200379 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200380 }
381 }
Steve Dower9048c492019-06-29 10:34:11 -0700382
383 if (config->base_executable == NULL) {
384 if (copy_wstr(&config->base_executable,
385 config->executable) < 0) {
386 return _PyStatus_NO_MEMORY();
387 }
388 }
389
Victor Stinner331a6a52019-05-27 16:39:22 +0200390 return _PyStatus_OK();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200391}
392
393
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200394static PyStatus
395pathconfig_global_read(_PyPathConfig *pathconfig)
396{
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200397 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200398 _PyConfig_InitCompatConfig(&config);
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200399
400 /* Call _PyConfig_InitPathConfig() */
Victor Stinner8462a492019-10-01 12:06:16 +0200401 PyStatus status = PyConfig_Read(&config);
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200402 if (_PyStatus_EXCEPTION(status)) {
403 goto done;
404 }
405
406 status = pathconfig_set_from_config(pathconfig, &config);
407
408done:
409 PyConfig_Clear(&config);
410 return status;
411}
412
413
Victor Stinner31a83932017-12-04 13:39:15 +0100414static void
415pathconfig_global_init(void)
416{
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200417 PyStatus status;
418
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200419 if (_Py_path_config.module_search_path == NULL) {
420 status = pathconfig_global_read(&_Py_path_config);
421 if (_PyStatus_EXCEPTION(status)) {
422 Py_ExitStatusException(status);
423 }
424 }
425 else {
426 /* Global configuration already initialized */
Victor Stinner31a83932017-12-04 13:39:15 +0100427 }
428
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200429 assert(_Py_path_config.program_full_path != NULL);
430 assert(_Py_path_config.prefix != NULL);
431 assert(_Py_path_config.exec_prefix != NULL);
432 assert(_Py_path_config.module_search_path != NULL);
433 assert(_Py_path_config.program_name != NULL);
434 /* home can be NULL */
Victor Stinner8bf39b62019-09-26 02:22:35 +0200435#ifdef MS_WINDOWS
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200436 assert(_Py_path_config.base_executable != NULL);
Victor Stinner8bf39b62019-09-26 02:22:35 +0200437#endif
Victor Stinner31a83932017-12-04 13:39:15 +0100438}
439
440
441/* External interface */
442
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100443static void _Py_NO_RETURN
444path_out_of_memory(const char *func)
445{
446 _Py_FatalErrorFunc(func, "out of memory");
447}
448
Victor Stinner31a83932017-12-04 13:39:15 +0100449void
450Py_SetPath(const wchar_t *path)
451{
452 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200453 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100454 return;
455 }
456
457 PyMemAllocatorEx old_alloc;
458 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
459
Victor Stinner1ce152a2019-09-24 17:44:15 +0200460 /* Getting the program full path calls pathconfig_global_init() */
461 wchar_t *program_full_path = _PyMem_RawWcsdup(Py_GetProgramFullPath());
Victor Stinner31a83932017-12-04 13:39:15 +0100462
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200463 PyMem_RawFree(_Py_path_config.program_full_path);
464 PyMem_RawFree(_Py_path_config.prefix);
465 PyMem_RawFree(_Py_path_config.exec_prefix);
466 PyMem_RawFree(_Py_path_config.module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +0100467
Victor Stinner1ce152a2019-09-24 17:44:15 +0200468 _Py_path_config.program_full_path = program_full_path;
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200469 _Py_path_config.prefix = _PyMem_RawWcsdup(L"");
470 _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
471 _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinner31a83932017-12-04 13:39:15 +0100472
473 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200474
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200475 if (_Py_path_config.program_full_path == NULL
476 || _Py_path_config.prefix == NULL
477 || _Py_path_config.exec_prefix == NULL
478 || _Py_path_config.module_search_path == NULL)
479 {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100480 path_out_of_memory(__func__);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200481 }
Victor Stinner31a83932017-12-04 13:39:15 +0100482}
483
484
485void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200486Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100487{
488 if (home == NULL) {
489 return;
490 }
491
492 PyMemAllocatorEx old_alloc;
493 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
494
495 PyMem_RawFree(_Py_path_config.home);
496 _Py_path_config.home = _PyMem_RawWcsdup(home);
497
498 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
499
500 if (_Py_path_config.home == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100501 path_out_of_memory(__func__);
Victor Stinner31a83932017-12-04 13:39:15 +0100502 }
503}
504
505
506void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200507Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100508{
509 if (program_name == NULL || program_name[0] == L'\0') {
510 return;
511 }
512
513 PyMemAllocatorEx old_alloc;
514 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
515
516 PyMem_RawFree(_Py_path_config.program_name);
517 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
518
519 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
520
521 if (_Py_path_config.program_name == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100522 path_out_of_memory(__func__);
Victor Stinner31a83932017-12-04 13:39:15 +0100523 }
524}
525
Steve Dower177a41a2018-11-17 20:41:48 -0800526void
527_Py_SetProgramFullPath(const wchar_t *program_full_path)
528{
529 if (program_full_path == NULL || program_full_path[0] == L'\0') {
530 return;
531 }
532
533 PyMemAllocatorEx old_alloc;
534 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
535
536 PyMem_RawFree(_Py_path_config.program_full_path);
537 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
538
539 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
540
541 if (_Py_path_config.program_full_path == NULL) {
Victor Stinner87d3b9d2020-03-25 19:27:36 +0100542 path_out_of_memory(__func__);
Steve Dower177a41a2018-11-17 20:41:48 -0800543 }
544}
545
Victor Stinner31a83932017-12-04 13:39:15 +0100546
547wchar_t *
548Py_GetPath(void)
549{
550 pathconfig_global_init();
551 return _Py_path_config.module_search_path;
552}
553
554
555wchar_t *
556Py_GetPrefix(void)
557{
558 pathconfig_global_init();
559 return _Py_path_config.prefix;
560}
561
562
563wchar_t *
564Py_GetExecPrefix(void)
565{
Victor Stinner31a83932017-12-04 13:39:15 +0100566 pathconfig_global_init();
567 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100568}
569
570
571wchar_t *
572Py_GetProgramFullPath(void)
573{
574 pathconfig_global_init();
575 return _Py_path_config.program_full_path;
576}
577
578
579wchar_t*
580Py_GetPythonHome(void)
581{
582 pathconfig_global_init();
583 return _Py_path_config.home;
584}
585
586
587wchar_t *
588Py_GetProgramName(void)
589{
590 pathconfig_global_init();
591 return _Py_path_config.program_name;
592}
593
Victor Stinnerdcf61712019-03-19 16:09:27 +0100594/* Compute module search path from argv[0] or the current working
595 directory ("-m module" case) which will be prepended to sys.argv:
596 sys.path[0].
597
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200598 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100599
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200600 Return 0 if it fails to resolve the full path. For example, return 0 if the
601 current working directory has been removed (bpo-36236) or if argv is empty.
602
603 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100604 */
605int
Victor Stinner331a6a52019-05-27 16:39:22 +0200606_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100607{
Victor Stinner331a6a52019-05-27 16:39:22 +0200608 assert(_PyWideStringList_CheckConsistency(argv));
Victor Stinner74f65682019-03-15 15:08:05 +0100609
Victor Stinnerfc96e542019-03-19 18:22:55 +0100610 if (argv->length == 0) {
611 /* Leave sys.path unchanged if sys.argv is empty */
612 return 0;
613 }
614
615 wchar_t *argv0 = argv->items[0];
616 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
617 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
618
619 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100620 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100621
622#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100623 wchar_t fullpath[MAXPATHLEN];
624#elif defined(MS_WINDOWS)
625 wchar_t fullpath[MAX_PATH];
626#endif
627
Nick Coghland5d9e022018-03-25 23:03:10 +1000628 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100629#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100630 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
631 return 0;
632 }
633 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100634#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100635 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100636#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100637 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000638 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100639
640#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100641 wchar_t link[MAXPATHLEN + 1];
642 int nr = 0;
Miss Islington (bot)9fe5dec2020-06-22 00:47:54 -0700643 wchar_t path0copy[2 * MAXPATHLEN + 1];
Victor Stinnerfc96e542019-03-19 18:22:55 +0100644
645 if (have_script_arg) {
646 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
647 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100648 if (nr > 0) {
649 /* It's a symlink */
650 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100651 if (link[0] == SEP) {
652 path0 = link; /* Link to absolute path */
653 }
654 else if (wcschr(link, SEP) == NULL) {
655 /* Link without path */
656 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100657 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100658 /* Must join(dirname(path0), link) */
659 wchar_t *q = wcsrchr(path0, SEP);
660 if (q == NULL) {
661 /* path0 without path */
662 path0 = link;
663 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100664 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100665 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100666 wcsncpy(path0copy, path0, MAXPATHLEN);
667 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100668 wcsncpy(q+1, link, MAXPATHLEN);
669 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100670 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100671 }
672 }
673 }
674#endif /* HAVE_READLINK */
675
Victor Stinnerfc96e542019-03-19 18:22:55 +0100676 wchar_t *p = NULL;
677
Victor Stinner11a247d2017-12-13 21:05:57 +0100678#if SEP == '\\'
679 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000680 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100681 wchar_t *q;
682#if defined(MS_WINDOWS)
683 /* Replace the first element in argv with the full path. */
684 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100685 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100686 Py_ARRAY_LENGTH(fullpath),
687 fullpath,
688 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100689 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100690 }
691#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100692 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100693 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100694 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100695 if (q != NULL)
696 p = q;
697 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100698 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100699 if (n > 1 && p[-1] != ':')
700 n--; /* Drop trailing separator */
701 }
702 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100703#else
704 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000705 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100706#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100707 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
708 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100709 }
710#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100711 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100712 }
713 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100714 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100715#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100716 if (n > 1) {
717 /* Drop trailing separator */
718 n--;
719 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100720#endif /* Unix */
721 }
722#endif /* All others */
723
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200724 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
725 if (path0_obj == NULL) {
726 return -1;
727 }
728
729 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100730 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100731}
732
Victor Stinner9bee3292017-12-21 16:49:13 +0100733
Minmin Gong8ebc6452019-02-02 20:26:55 -0800734#ifdef MS_WINDOWS
735#define WCSTOK wcstok_s
736#else
737#define WCSTOK wcstok
738#endif
739
Victor Stinner9bee3292017-12-21 16:49:13 +0100740/* Search for a prefix value in an environment file (pyvenv.cfg).
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200741
742 - If found, copy it into *value_p: string which must be freed by
743 PyMem_RawFree().
744 - If not found, *value_p is set to NULL.
745*/
746PyStatus
Victor Stinner9bee3292017-12-21 16:49:13 +0100747_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200748 wchar_t **value_p)
Victor Stinner9bee3292017-12-21 16:49:13 +0100749{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200750 *value_p = NULL;
751
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100752 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
753 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100754
Victor Stinner9bee3292017-12-21 16:49:13 +0100755 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100756 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100757
758 if (p == NULL) {
759 break;
760 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100761
762 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100763 if (p[n - 1] != '\n') {
764 /* line has overflowed - bail */
765 break;
766 }
767 if (p[0] == '#') {
768 /* Comment - skip */
769 continue;
770 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100771
Victor Stinner5f9cf232019-03-19 01:46:25 +0100772 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100773 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100774 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800775 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100776 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800777 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100778 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800779 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100780 if (tok != NULL) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200781 *value_p = _PyMem_RawWcsdup(tok);
Victor Stinner9bee3292017-12-21 16:49:13 +0100782 PyMem_RawFree(tmpbuffer);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200783
784 if (*value_p == NULL) {
785 return _PyStatus_NO_MEMORY();
786 }
787
788 /* found */
789 return _PyStatus_OK();
Victor Stinner9bee3292017-12-21 16:49:13 +0100790 }
791 }
792 }
793 PyMem_RawFree(tmpbuffer);
794 }
795 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200796
797 /* not found */
798 return _PyStatus_OK();
Victor Stinner9bee3292017-12-21 16:49:13 +0100799}
800
Victor Stinner31a83932017-12-04 13:39:15 +0100801#ifdef __cplusplus
802}
803#endif