blob: 8f76fa50c9710dd6e2e12b93b67b68b51ed3d8bc [file] [log] [blame]
Victor Stinner31a83932017-12-04 13:39:15 +01001/* Path configuration like module_search_path (sys.path) */
2
3#include "Python.h"
4#include "osdefs.h"
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 Stinner621cebe2018-11-12 16:53:38 +01008#include "pycore_pymem.h"
9#include "pycore_pystate.h"
Nick Coghland5d9e022018-03-25 23:03:10 +100010#include <wchar.h>
Victor Stinner31a83932017-12-04 13:39:15 +010011
12#ifdef __cplusplus
13extern "C" {
14#endif
15
16
17_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
Victor Stinnerc4221672019-09-21 01:02:56 +020018#ifdef MS_WINDOWS
19wchar_t *_Py_dll_path = NULL;
20#endif
Victor Stinner31a83932017-12-04 13:39:15 +010021
22
Victor Stinnerb1147e42018-07-21 02:06:16 +020023static int
24copy_wstr(wchar_t **dst, const wchar_t *src)
25{
Victor Stinner1ce152a2019-09-24 17:44:15 +020026 assert(*dst == NULL);
Victor Stinnerb1147e42018-07-21 02:06:16 +020027 if (src != NULL) {
28 *dst = _PyMem_RawWcsdup(src);
29 if (*dst == NULL) {
30 return -1;
31 }
32 }
33 else {
34 *dst = NULL;
35 }
36 return 0;
37}
38
39
40static void
Victor Stinner331a6a52019-05-27 16:39:22 +020041pathconfig_clear(_PyPathConfig *config)
Victor Stinner31a83932017-12-04 13:39:15 +010042{
43 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
44 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
45 called before Py_Initialize() which can changes the memory allocator. */
46 PyMemAllocatorEx old_alloc;
47 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
48
49#define CLEAR(ATTR) \
50 do { \
51 PyMem_RawFree(ATTR); \
52 ATTR = NULL; \
53 } while (0)
54
Victor Stinner31a83932017-12-04 13:39:15 +010055 CLEAR(config->program_full_path);
Victor Stinner9c42f8c2019-09-23 18:47:29 +020056 CLEAR(config->prefix);
Steve Dower177a41a2018-11-17 20:41:48 -080057 CLEAR(config->exec_prefix);
Victor Stinner31a83932017-12-04 13:39:15 +010058 CLEAR(config->module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +010059 CLEAR(config->program_name);
Victor Stinner9c42f8c2019-09-23 18:47:29 +020060 CLEAR(config->home);
Steve Dower9048c492019-06-29 10:34:11 -070061 CLEAR(config->base_executable);
Victor Stinner31a83932017-12-04 13:39:15 +010062#undef CLEAR
63
64 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
65}
66
67
Victor Stinner331a6a52019-05-27 16:39:22 +020068static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +020069pathconfig_copy(_PyPathConfig *config, const _PyPathConfig *config2)
Victor Stinner31a83932017-12-04 13:39:15 +010070{
Victor Stinner9c42f8c2019-09-23 18:47:29 +020071 pathconfig_clear(config);
Victor Stinner31a83932017-12-04 13:39:15 +010072
Victor Stinner9c42f8c2019-09-23 18:47:29 +020073#define COPY_ATTR(ATTR) \
74 do { \
75 if (copy_wstr(&config->ATTR, config2->ATTR) < 0) { \
76 return _PyStatus_NO_MEMORY(); \
77 } \
78 } while (0)
Victor Stinner31a83932017-12-04 13:39:15 +010079
Victor Stinner9c42f8c2019-09-23 18:47:29 +020080 COPY_ATTR(program_full_path);
81 COPY_ATTR(prefix);
82 COPY_ATTR(exec_prefix);
83 COPY_ATTR(module_search_path);
84 COPY_ATTR(program_name);
85 COPY_ATTR(home);
86 config->isolated = config2->isolated;
87 config->site_import = config2->site_import;
88 COPY_ATTR(base_executable);
Victor Stinnere2677932019-09-21 01:50:16 +020089
Victor Stinner9c42f8c2019-09-23 18:47:29 +020090#undef COPY_ATTR
Victor Stinner31a83932017-12-04 13:39:15 +010091
Victor Stinner9c42f8c2019-09-23 18:47:29 +020092 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +020093}
94
95
Victor Stinnerb1147e42018-07-21 02:06:16 +020096void
97_PyPathConfig_ClearGlobal(void)
98{
Victor Stinnerc1834442019-03-18 22:24:28 +010099 PyMemAllocatorEx old_alloc;
100 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
101
Victor Stinner331a6a52019-05-27 16:39:22 +0200102 pathconfig_clear(&_Py_path_config);
Victor Stinnerc4221672019-09-21 01:02:56 +0200103#ifdef MS_WINDOWS
104 PyMem_RawFree(_Py_dll_path);
105 _Py_dll_path = NULL;
106#endif
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) {
131 *str++ = SEP;
132 }
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 Stinner9c42f8c2019-09-23 18:47:29 +0200143/* Initialize _Py_dll_path on Windows. Do nothing on other platforms. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200144PyStatus
Victor Stinnerc4221672019-09-21 01:02:56 +0200145_PyPathConfig_Init(void)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200146{
Victor Stinnerc4221672019-09-21 01:02:56 +0200147#ifdef MS_WINDOWS
148 if (_Py_dll_path == NULL) {
149 /* Already set: nothing to do */
150 return _PyStatus_OK();
151 }
152
Victor Stinnerb1147e42018-07-21 02:06:16 +0200153 PyMemAllocatorEx old_alloc;
154 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
155
Victor Stinnerc4221672019-09-21 01:02:56 +0200156 _Py_dll_path = _Py_GetDLLPath();
157
158 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
159
160 if (_Py_dll_path == NULL) {
161 return _PyStatus_NO_MEMORY();
162 }
163#endif
164 return _PyStatus_OK();
165}
166
167
168static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200169pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config)
Victor Stinnerc4221672019-09-21 01:02:56 +0200170{
Victor Stinner331a6a52019-05-27 16:39:22 +0200171 PyStatus status;
Victor Stinnerc4221672019-09-21 01:02:56 +0200172 PyMemAllocatorEx old_alloc;
173 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
174
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200175 if (config->module_search_paths_set) {
Victor Stinner1ce152a2019-09-24 17:44:15 +0200176 PyMem_RawFree(pathconfig->module_search_path);
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200177 pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
178 if (pathconfig->module_search_path == NULL) {
179 goto no_memory;
180 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200181 }
182
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200183#define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \
184 if (config->CONFIG_ATTR) { \
Victor Stinner1ce152a2019-09-24 17:44:15 +0200185 PyMem_RawFree(pathconfig->PATH_ATTR); \
186 pathconfig->PATH_ATTR = NULL; \
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200187 if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \
188 goto no_memory; \
189 } \
190 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200191
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200192 COPY_CONFIG(base_executable, base_executable);
193 COPY_CONFIG(program_full_path, executable);
194 COPY_CONFIG(prefix, prefix);
195 COPY_CONFIG(exec_prefix, exec_prefix);
196 COPY_CONFIG(program_name, program_name);
197 COPY_CONFIG(home, home);
198
199#undef COPY_CONFIG
Victor Stinnerb1147e42018-07-21 02:06:16 +0200200
Victor Stinner331a6a52019-05-27 16:39:22 +0200201 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200202 goto done;
203
204no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200205 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200206
207done:
Victor Stinnerb1147e42018-07-21 02:06:16 +0200208 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200209 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200210}
211
212
Victor Stinner331a6a52019-05-27 16:39:22 +0200213static PyStatus
214config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200215{
Victor Stinner331a6a52019-05-27 16:39:22 +0200216 assert(!config->module_search_paths_set);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200217
Victor Stinner331a6a52019-05-27 16:39:22 +0200218 _PyWideStringList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200219
Victor Stinner331a6a52019-05-27 16:39:22 +0200220 const wchar_t *sys_path = pathconfig->module_search_path;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200221 const wchar_t delim = DELIM;
222 const wchar_t *p = sys_path;
223 while (1) {
224 p = wcschr(sys_path, delim);
225 if (p == NULL) {
226 p = sys_path + wcslen(sys_path); /* End of string */
227 }
228
229 size_t path_len = (p - sys_path);
230 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
231 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200232 return _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200233 }
234 memcpy(path, sys_path, path_len * sizeof(wchar_t));
235 path[path_len] = L'\0';
236
Victor Stinner331a6a52019-05-27 16:39:22 +0200237 PyStatus status = PyWideStringList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200238 PyMem_RawFree(path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200239 if (_PyStatus_EXCEPTION(status)) {
240 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200241 }
242
243 if (*p == '\0') {
244 break;
245 }
246 sys_path = p + 1;
247 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200248 config->module_search_paths_set = 1;
249 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200250}
251
252
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200253/* Calculate the path configuration:
254
255 - exec_prefix
256 - module_search_path
257 - prefix
258 - program_full_path
259
260 On Windows, more fields are calculated:
261
262 - base_executable
263 - isolated
264 - site_import
265
266 On other platforms, isolated and site_import are left unchanged, and
267 _PyConfig_InitPathConfig() copies executable to base_executable (if it's not
268 set).
269
270 Priority, highest to lowest:
271
272 - PyConfig
273 - _Py_path_config: set by Py_SetPath(), Py_SetPythonHome()
274 and Py_SetProgramName()
275 - _PyPathConfig_Calculate()
276*/
277static PyStatus
278pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
279{
280 PyStatus status;
281
282 PyMemAllocatorEx old_alloc;
283 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
284
285 status = pathconfig_copy(pathconfig, &_Py_path_config);
286 if (_PyStatus_EXCEPTION(status)) {
287 goto done;
288 }
289
290 status = pathconfig_set_from_config(pathconfig, config);
291 if (_PyStatus_EXCEPTION(status)) {
292 goto done;
293 }
294
295 if (_Py_path_config.module_search_path == NULL) {
296 status = _PyPathConfig_Calculate(pathconfig, config);
297 }
298 else {
299 /* Py_SetPath() has been called: avoid _PyPathConfig_Calculate() */
300 }
301
302done:
303 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
304 return status;
305}
306
307
Victor Stinner331a6a52019-05-27 16:39:22 +0200308static PyStatus
309config_calculate_pathconfig(PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200310{
Victor Stinner331a6a52019-05-27 16:39:22 +0200311 _PyPathConfig pathconfig = _PyPathConfig_INIT;
312 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200313
Victor Stinner331a6a52019-05-27 16:39:22 +0200314 status = pathconfig_calculate(&pathconfig, config);
315 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200316 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200317 }
318
Victor Stinner331a6a52019-05-27 16:39:22 +0200319 if (!config->module_search_paths_set) {
320 status = config_init_module_search_paths(config, &pathconfig);
321 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200322 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200323 }
324 }
325
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200326#define COPY_ATTR(PATH_ATTR, CONFIG_ATTR) \
327 if (config->CONFIG_ATTR == NULL) { \
328 if (copy_wstr(&config->CONFIG_ATTR, pathconfig.PATH_ATTR) < 0) { \
329 goto no_memory; \
330 } \
Victor Stinnerb1147e42018-07-21 02:06:16 +0200331 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200332
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200333 COPY_ATTR(program_full_path, executable);
334 COPY_ATTR(prefix, prefix);
335 COPY_ATTR(exec_prefix, exec_prefix);
336 COPY_ATTR(base_executable, base_executable);
337#undef COPY_ATTR
Steve Dower9048c492019-06-29 10:34:11 -0700338
Victor Stinner331a6a52019-05-27 16:39:22 +0200339 if (pathconfig.isolated != -1) {
340 config->isolated = pathconfig.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200341 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200342 if (pathconfig.site_import != -1) {
343 config->site_import = pathconfig.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200344 }
345
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200346 status = _PyStatus_OK();
347 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200348
349no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200350 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200351
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200352done:
Victor Stinner331a6a52019-05-27 16:39:22 +0200353 pathconfig_clear(&pathconfig);
354 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200355}
356
357
Victor Stinner331a6a52019-05-27 16:39:22 +0200358PyStatus
359_PyConfig_InitPathConfig(PyConfig *config)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200360{
361 /* Do we need to calculate the path? */
Victor Stinner331a6a52019-05-27 16:39:22 +0200362 if (!config->module_search_paths_set
Victor Stinner1dc6e392018-07-25 02:49:17 +0200363 || (config->executable == NULL)
364 || (config->prefix == NULL)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200365 || (config->exec_prefix == NULL))
366 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200367 PyStatus status = config_calculate_pathconfig(config);
368 if (_PyStatus_EXCEPTION(status)) {
369 return status;
Victor Stinner1dc6e392018-07-25 02:49:17 +0200370 }
371 }
372
373 if (config->base_prefix == NULL) {
374 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200375 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200376 }
377 }
378
379 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800380 if (copy_wstr(&config->base_exec_prefix,
381 config->exec_prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200382 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200383 }
384 }
Steve Dower9048c492019-06-29 10:34:11 -0700385
386 if (config->base_executable == NULL) {
387 if (copy_wstr(&config->base_executable,
388 config->executable) < 0) {
389 return _PyStatus_NO_MEMORY();
390 }
391 }
392
Victor Stinner331a6a52019-05-27 16:39:22 +0200393 return _PyStatus_OK();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200394}
395
396
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200397static PyStatus
398pathconfig_global_read(_PyPathConfig *pathconfig)
399{
400 PyStatus status;
401 PyConfig config;
402 _PyConfig_InitCompatConfig(&config);
403
404 /* Call _PyConfig_InitPathConfig() */
405 status = PyConfig_Read(&config);
406 if (_PyStatus_EXCEPTION(status)) {
407 goto done;
408 }
409
410 status = pathconfig_set_from_config(pathconfig, &config);
411
412done:
413 PyConfig_Clear(&config);
414 return status;
415}
416
417
Victor Stinner31a83932017-12-04 13:39:15 +0100418static void
419pathconfig_global_init(void)
420{
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200421 PyStatus status;
422
Victor Stinnerc4221672019-09-21 01:02:56 +0200423 /* Initialize _Py_dll_path if needed */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200424 status = _PyPathConfig_Init();
Victor Stinnerc4221672019-09-21 01:02:56 +0200425 if (_PyStatus_EXCEPTION(status)) {
426 Py_ExitStatusException(status);
427 }
428
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200429 if (_Py_path_config.module_search_path == NULL) {
430 status = pathconfig_global_read(&_Py_path_config);
431 if (_PyStatus_EXCEPTION(status)) {
432 Py_ExitStatusException(status);
433 }
434 }
435 else {
436 /* Global configuration already initialized */
Victor Stinner31a83932017-12-04 13:39:15 +0100437 }
438
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200439 assert(_Py_path_config.program_full_path != NULL);
440 assert(_Py_path_config.prefix != NULL);
441 assert(_Py_path_config.exec_prefix != NULL);
442 assert(_Py_path_config.module_search_path != NULL);
443 assert(_Py_path_config.program_name != NULL);
444 /* home can be NULL */
445 assert(_Py_path_config.base_executable != NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100446}
447
448
449/* External interface */
450
451void
452Py_SetPath(const wchar_t *path)
453{
454 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200455 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100456 return;
457 }
458
459 PyMemAllocatorEx old_alloc;
460 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
461
Victor Stinner1ce152a2019-09-24 17:44:15 +0200462 /* Getting the program full path calls pathconfig_global_init() */
463 wchar_t *program_full_path = _PyMem_RawWcsdup(Py_GetProgramFullPath());
Victor Stinner31a83932017-12-04 13:39:15 +0100464
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200465 PyMem_RawFree(_Py_path_config.program_full_path);
466 PyMem_RawFree(_Py_path_config.prefix);
467 PyMem_RawFree(_Py_path_config.exec_prefix);
468 PyMem_RawFree(_Py_path_config.module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +0100469
Victor Stinner1ce152a2019-09-24 17:44:15 +0200470 _Py_path_config.program_full_path = program_full_path;
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200471 _Py_path_config.prefix = _PyMem_RawWcsdup(L"");
472 _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
473 _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinner31a83932017-12-04 13:39:15 +0100474
475 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200476
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200477 if (_Py_path_config.program_full_path == NULL
478 || _Py_path_config.prefix == NULL
479 || _Py_path_config.exec_prefix == NULL
480 || _Py_path_config.module_search_path == NULL)
481 {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200482 Py_FatalError("Py_SetPath() failed: out of memory");
483 }
Victor Stinner31a83932017-12-04 13:39:15 +0100484}
485
486
487void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200488Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100489{
490 if (home == NULL) {
491 return;
492 }
493
494 PyMemAllocatorEx old_alloc;
495 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
496
497 PyMem_RawFree(_Py_path_config.home);
498 _Py_path_config.home = _PyMem_RawWcsdup(home);
499
500 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
501
502 if (_Py_path_config.home == NULL) {
503 Py_FatalError("Py_SetPythonHome() failed: out of memory");
504 }
505}
506
507
508void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200509Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100510{
511 if (program_name == NULL || program_name[0] == L'\0') {
512 return;
513 }
514
515 PyMemAllocatorEx old_alloc;
516 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
517
518 PyMem_RawFree(_Py_path_config.program_name);
519 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
520
521 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
522
523 if (_Py_path_config.program_name == NULL) {
524 Py_FatalError("Py_SetProgramName() failed: out of memory");
525 }
526}
527
Steve Dower177a41a2018-11-17 20:41:48 -0800528void
529_Py_SetProgramFullPath(const wchar_t *program_full_path)
530{
531 if (program_full_path == NULL || program_full_path[0] == L'\0') {
532 return;
533 }
534
535 PyMemAllocatorEx old_alloc;
536 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
537
538 PyMem_RawFree(_Py_path_config.program_full_path);
539 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
540
541 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
542
543 if (_Py_path_config.program_full_path == NULL) {
544 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
545 }
546}
547
Victor Stinner31a83932017-12-04 13:39:15 +0100548
549wchar_t *
550Py_GetPath(void)
551{
552 pathconfig_global_init();
553 return _Py_path_config.module_search_path;
554}
555
556
557wchar_t *
558Py_GetPrefix(void)
559{
560 pathconfig_global_init();
561 return _Py_path_config.prefix;
562}
563
564
565wchar_t *
566Py_GetExecPrefix(void)
567{
Victor Stinner31a83932017-12-04 13:39:15 +0100568 pathconfig_global_init();
569 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100570}
571
572
573wchar_t *
574Py_GetProgramFullPath(void)
575{
576 pathconfig_global_init();
577 return _Py_path_config.program_full_path;
578}
579
580
581wchar_t*
582Py_GetPythonHome(void)
583{
584 pathconfig_global_init();
585 return _Py_path_config.home;
586}
587
588
589wchar_t *
590Py_GetProgramName(void)
591{
592 pathconfig_global_init();
593 return _Py_path_config.program_name;
594}
595
Victor Stinnerdcf61712019-03-19 16:09:27 +0100596/* Compute module search path from argv[0] or the current working
597 directory ("-m module" case) which will be prepended to sys.argv:
598 sys.path[0].
599
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200600 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100601
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200602 Return 0 if it fails to resolve the full path. For example, return 0 if the
603 current working directory has been removed (bpo-36236) or if argv is empty.
604
605 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100606 */
607int
Victor Stinner331a6a52019-05-27 16:39:22 +0200608_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100609{
Victor Stinner331a6a52019-05-27 16:39:22 +0200610 assert(_PyWideStringList_CheckConsistency(argv));
Victor Stinner74f65682019-03-15 15:08:05 +0100611
Victor Stinnerfc96e542019-03-19 18:22:55 +0100612 if (argv->length == 0) {
613 /* Leave sys.path unchanged if sys.argv is empty */
614 return 0;
615 }
616
617 wchar_t *argv0 = argv->items[0];
618 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
619 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
620
621 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100622 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100623
624#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100625 wchar_t fullpath[MAXPATHLEN];
626#elif defined(MS_WINDOWS)
627 wchar_t fullpath[MAX_PATH];
628#endif
629
Nick Coghland5d9e022018-03-25 23:03:10 +1000630 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100631#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100632 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
633 return 0;
634 }
635 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100636#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100637 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100638#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100639 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000640 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100641
642#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100643 wchar_t link[MAXPATHLEN + 1];
644 int nr = 0;
645
646 if (have_script_arg) {
647 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
648 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100649 if (nr > 0) {
650 /* It's a symlink */
651 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100652 if (link[0] == SEP) {
653 path0 = link; /* Link to absolute path */
654 }
655 else if (wcschr(link, SEP) == NULL) {
656 /* Link without path */
657 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100658 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100659 /* Must join(dirname(path0), link) */
660 wchar_t *q = wcsrchr(path0, SEP);
661 if (q == NULL) {
662 /* path0 without path */
663 path0 = link;
664 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100665 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100666 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
667 wchar_t path0copy[2 * MAXPATHLEN + 1];
668 wcsncpy(path0copy, path0, MAXPATHLEN);
669 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100670 wcsncpy(q+1, link, MAXPATHLEN);
671 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100672 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100673 }
674 }
675 }
676#endif /* HAVE_READLINK */
677
Victor Stinnerfc96e542019-03-19 18:22:55 +0100678 wchar_t *p = NULL;
679
Victor Stinner11a247d2017-12-13 21:05:57 +0100680#if SEP == '\\'
681 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000682 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100683 wchar_t *q;
684#if defined(MS_WINDOWS)
685 /* Replace the first element in argv with the full path. */
686 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100687 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100688 Py_ARRAY_LENGTH(fullpath),
689 fullpath,
690 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100691 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100692 }
693#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100694 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100695 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100696 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100697 if (q != NULL)
698 p = q;
699 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100700 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100701 if (n > 1 && p[-1] != ':')
702 n--; /* Drop trailing separator */
703 }
704 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100705#else
706 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000707 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100708#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100709 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
710 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100711 }
712#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100713 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100714 }
715 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100716 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100717#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100718 if (n > 1) {
719 /* Drop trailing separator */
720 n--;
721 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100722#endif /* Unix */
723 }
724#endif /* All others */
725
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200726 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
727 if (path0_obj == NULL) {
728 return -1;
729 }
730
731 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100732 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100733}
734
Victor Stinner9bee3292017-12-21 16:49:13 +0100735
Minmin Gong8ebc6452019-02-02 20:26:55 -0800736#ifdef MS_WINDOWS
737#define WCSTOK wcstok_s
738#else
739#define WCSTOK wcstok
740#endif
741
Victor Stinner9bee3292017-12-21 16:49:13 +0100742/* Search for a prefix value in an environment file (pyvenv.cfg).
743 If found, copy it into the provided buffer. */
744int
745_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
746 wchar_t *value, size_t value_size)
747{
748 int result = 0; /* meaning not found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100749 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
750 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100751
Victor Stinner9bee3292017-12-21 16:49:13 +0100752 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100753 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100754
755 if (p == NULL) {
756 break;
757 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100758
759 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100760 if (p[n - 1] != '\n') {
761 /* line has overflowed - bail */
762 break;
763 }
764 if (p[0] == '#') {
765 /* Comment - skip */
766 continue;
767 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100768
Victor Stinner5f9cf232019-03-19 01:46:25 +0100769 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100770 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100771 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800772 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100773 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800774 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100775 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800776 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100777 if (tok != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100778 wcsncpy(value, tok, value_size - 1);
779 value[value_size - 1] = L'\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100780 result = 1;
781 PyMem_RawFree(tmpbuffer);
782 break;
783 }
784 }
785 }
786 PyMem_RawFree(tmpbuffer);
787 }
788 }
789 return result;
790}
791
Victor Stinner31a83932017-12-04 13:39:15 +0100792#ifdef __cplusplus
793}
794#endif