blob: 2fcb81605805ecf45f1d20bf8921eb6586c236bb [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 Stinnerf684d832019-03-01 03:44:13 +01005#include "pycore_coreconfig.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;
18
19
Victor Stinnerb1147e42018-07-21 02:06:16 +020020static int
21copy_wstr(wchar_t **dst, const wchar_t *src)
22{
23 if (src != NULL) {
24 *dst = _PyMem_RawWcsdup(src);
25 if (*dst == NULL) {
26 return -1;
27 }
28 }
29 else {
30 *dst = NULL;
31 }
32 return 0;
33}
34
35
36static void
Victor Stinner31a83932017-12-04 13:39:15 +010037_PyPathConfig_Clear(_PyPathConfig *config)
38{
39 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
40 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
41 called before Py_Initialize() which can changes the memory allocator. */
42 PyMemAllocatorEx old_alloc;
43 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
44
45#define CLEAR(ATTR) \
46 do { \
47 PyMem_RawFree(ATTR); \
48 ATTR = NULL; \
49 } while (0)
50
51 CLEAR(config->prefix);
52 CLEAR(config->program_full_path);
Steve Dower177a41a2018-11-17 20:41:48 -080053 CLEAR(config->exec_prefix);
Victor Stinner31a83932017-12-04 13:39:15 +010054#ifdef MS_WINDOWS
55 CLEAR(config->dll_path);
Victor Stinner31a83932017-12-04 13:39:15 +010056#endif
57 CLEAR(config->module_search_path);
58 CLEAR(config->home);
59 CLEAR(config->program_name);
60#undef CLEAR
61
62 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
63}
64
65
Victor Stinnerb1147e42018-07-21 02:06:16 +020066/* Calculate the path configuration: initialize path_config from core_config */
67static _PyInitError
68_PyPathConfig_Calculate(_PyPathConfig *path_config,
69 const _PyCoreConfig *core_config)
Victor Stinner31a83932017-12-04 13:39:15 +010070{
Victor Stinner31a83932017-12-04 13:39:15 +010071 _PyInitError err;
72 _PyPathConfig new_config = _PyPathConfig_INIT;
73
74 PyMemAllocatorEx old_alloc;
75 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
76
Steve Dower177a41a2018-11-17 20:41:48 -080077 /* Calculate program_full_path, prefix, exec_prefix,
78 dll_path (Windows), and module_search_path */
Victor Stinnerb1147e42018-07-21 02:06:16 +020079 err = _PyPathConfig_Calculate_impl(&new_config, core_config);
Victor Stinner31a83932017-12-04 13:39:15 +010080 if (_Py_INIT_FAILED(err)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +020081 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010082 }
83
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +010084 /* Copy home and program_name from core_config */
Victor Stinnerb1147e42018-07-21 02:06:16 +020085 if (copy_wstr(&new_config.home, core_config->home) < 0) {
86 err = _Py_INIT_NO_MEMORY();
87 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010088 }
Victor Stinnerb1147e42018-07-21 02:06:16 +020089 if (copy_wstr(&new_config.program_name, core_config->program_name) < 0) {
90 err = _Py_INIT_NO_MEMORY();
91 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010092 }
93
Victor Stinnerb1147e42018-07-21 02:06:16 +020094 _PyPathConfig_Clear(path_config);
95 *path_config = new_config;
96
97 err = _Py_INIT_OK();
98 goto done;
99
100err:
101 _PyPathConfig_Clear(&new_config);
102
103done:
104 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
105 return err;
106}
107
108
109_PyInitError
110_PyPathConfig_SetGlobal(const _PyPathConfig *config)
111{
112 _PyInitError err;
113 _PyPathConfig new_config = _PyPathConfig_INIT;
114
115 PyMemAllocatorEx old_alloc;
116 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
117
118#define COPY_ATTR(ATTR) \
119 do { \
120 if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \
121 _PyPathConfig_Clear(&new_config); \
122 err = _Py_INIT_NO_MEMORY(); \
123 goto done; \
124 } \
125 } while (0)
126
127 COPY_ATTR(program_full_path);
128 COPY_ATTR(prefix);
Steve Dower177a41a2018-11-17 20:41:48 -0800129 COPY_ATTR(exec_prefix);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200130#ifdef MS_WINDOWS
131 COPY_ATTR(dll_path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200132#endif
133 COPY_ATTR(module_search_path);
134 COPY_ATTR(program_name);
135 COPY_ATTR(home);
Victor Stinner31a83932017-12-04 13:39:15 +0100136
137 _PyPathConfig_Clear(&_Py_path_config);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200138 /* Steal new_config strings; don't clear new_config */
Victor Stinner31a83932017-12-04 13:39:15 +0100139 _Py_path_config = new_config;
140
141 err = _Py_INIT_OK();
142
143done:
144 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
145 return err;
146}
147
148
Victor Stinnerb1147e42018-07-21 02:06:16 +0200149void
150_PyPathConfig_ClearGlobal(void)
151{
Victor Stinnerc1834442019-03-18 22:24:28 +0100152 PyMemAllocatorEx old_alloc;
153 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
154
Victor Stinnerb1147e42018-07-21 02:06:16 +0200155 _PyPathConfig_Clear(&_Py_path_config);
Victor Stinnerc1834442019-03-18 22:24:28 +0100156
157 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200158}
159
160
161static wchar_t*
Victor Stinner74f65682019-03-15 15:08:05 +0100162_PyWstrList_Join(const _PyWstrList *list, wchar_t sep)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200163{
164 size_t len = 1; /* NUL terminator */
Victor Stinner74f65682019-03-15 15:08:05 +0100165 for (Py_ssize_t i=0; i < list->length; i++) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200166 if (i != 0) {
167 len++;
168 }
Victor Stinner74f65682019-03-15 15:08:05 +0100169 len += wcslen(list->items[i]);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200170 }
171
172 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
173 if (text == NULL) {
174 return NULL;
175 }
176 wchar_t *str = text;
Victor Stinner74f65682019-03-15 15:08:05 +0100177 for (Py_ssize_t i=0; i < list->length; i++) {
178 wchar_t *path = list->items[i];
Victor Stinnerb1147e42018-07-21 02:06:16 +0200179 if (i != 0) {
180 *str++ = SEP;
181 }
182 len = wcslen(path);
183 memcpy(str, path, len * sizeof(wchar_t));
184 str += len;
185 }
186 *str = L'\0';
187
188 return text;
189}
190
191
192/* Set the global path configuration from core_config. */
193_PyInitError
194_PyCoreConfig_SetPathConfig(const _PyCoreConfig *core_config)
195{
196 PyMemAllocatorEx old_alloc;
197 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
198
199 _PyInitError err;
200 _PyPathConfig path_config = _PyPathConfig_INIT;
201
Victor Stinner74f65682019-03-15 15:08:05 +0100202 path_config.module_search_path = _PyWstrList_Join(&core_config->module_search_paths, DELIM);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200203 if (path_config.module_search_path == NULL) {
204 goto no_memory;
205 }
206
207 if (copy_wstr(&path_config.program_full_path, core_config->executable) < 0) {
208 goto no_memory;
209 }
210 if (copy_wstr(&path_config.prefix, core_config->prefix) < 0) {
211 goto no_memory;
212 }
Steve Dower177a41a2018-11-17 20:41:48 -0800213 if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200214 goto no_memory;
215 }
Steve Dower177a41a2018-11-17 20:41:48 -0800216#ifdef MS_WINDOWS
217 if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200218 goto no_memory;
219 }
220#endif
221 if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) {
222 goto no_memory;
223 }
224 if (copy_wstr(&path_config.home, core_config->home) < 0) {
225 goto no_memory;
226 }
227
228 err = _PyPathConfig_SetGlobal(&path_config);
229 if (_Py_INIT_FAILED(err)) {
230 goto done;
231 }
232
233 err = _Py_INIT_OK();
234 goto done;
235
236no_memory:
237 err = _Py_INIT_NO_MEMORY();
238
239done:
240 _PyPathConfig_Clear(&path_config);
241 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
242 return err;
243}
244
245
246static _PyInitError
247core_config_init_module_search_paths(_PyCoreConfig *config,
248 _PyPathConfig *path_config)
249{
Victor Stinner74f65682019-03-15 15:08:05 +0100250 assert(!config->use_module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200251
Victor Stinner74f65682019-03-15 15:08:05 +0100252 _PyWstrList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200253
254 const wchar_t *sys_path = path_config->module_search_path;
255 const wchar_t delim = DELIM;
256 const wchar_t *p = sys_path;
257 while (1) {
258 p = wcschr(sys_path, delim);
259 if (p == NULL) {
260 p = sys_path + wcslen(sys_path); /* End of string */
261 }
262
263 size_t path_len = (p - sys_path);
264 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
265 if (path == NULL) {
266 return _Py_INIT_NO_MEMORY();
267 }
268 memcpy(path, sys_path, path_len * sizeof(wchar_t));
269 path[path_len] = L'\0';
270
Victor Stinner74f65682019-03-15 15:08:05 +0100271 int res = _PyWstrList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200272 PyMem_RawFree(path);
Victor Stinner74f65682019-03-15 15:08:05 +0100273 if (res < 0) {
274 return _Py_INIT_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200275 }
276
277 if (*p == '\0') {
278 break;
279 }
280 sys_path = p + 1;
281 }
Victor Stinner74f65682019-03-15 15:08:05 +0100282 config->use_module_search_paths = 1;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200283 return _Py_INIT_OK();
284}
285
286
Victor Stinner1dc6e392018-07-25 02:49:17 +0200287static _PyInitError
288_PyCoreConfig_CalculatePathConfig(_PyCoreConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200289{
290 _PyPathConfig path_config = _PyPathConfig_INIT;
291 _PyInitError err;
292
293 err = _PyPathConfig_Calculate(&path_config, config);
294 if (_Py_INIT_FAILED(err)) {
295 goto error;
296 }
297
Victor Stinner74f65682019-03-15 15:08:05 +0100298 if (!config->use_module_search_paths) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200299 err = core_config_init_module_search_paths(config, &path_config);
300 if (_Py_INIT_FAILED(err)) {
301 goto error;
302 }
303 }
304
305 if (config->executable == NULL) {
306 if (copy_wstr(&config->executable,
307 path_config.program_full_path) < 0) {
308 goto no_memory;
309 }
310 }
311
312 if (config->prefix == NULL) {
313 if (copy_wstr(&config->prefix, path_config.prefix) < 0) {
314 goto no_memory;
315 }
316 }
317
318 if (config->exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800319 if (copy_wstr(&config->exec_prefix,
320 path_config.exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200321 goto no_memory;
322 }
323 }
324
325#ifdef MS_WINDOWS
326 if (config->dll_path == NULL) {
327 if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
328 goto no_memory;
329 }
330 }
331#endif
332
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200333 if (path_config.isolated != -1) {
Victor Stinner20004952019-03-26 02:31:11 +0100334 config->isolated = path_config.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200335 }
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200336 if (path_config.site_import != -1) {
337 config->site_import = path_config.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200338 }
339
Victor Stinnerb1147e42018-07-21 02:06:16 +0200340 _PyPathConfig_Clear(&path_config);
341 return _Py_INIT_OK();
342
343no_memory:
344 err = _Py_INIT_NO_MEMORY();
345
346error:
347 _PyPathConfig_Clear(&path_config);
348 return err;
349}
350
351
Victor Stinner1dc6e392018-07-25 02:49:17 +0200352_PyInitError
353_PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
354{
355 /* Do we need to calculate the path? */
Victor Stinner74f65682019-03-15 15:08:05 +0100356 if (!config->use_module_search_paths
Victor Stinner1dc6e392018-07-25 02:49:17 +0200357 || (config->executable == NULL)
358 || (config->prefix == NULL)
359#ifdef MS_WINDOWS
360 || (config->dll_path == NULL)
361#endif
362 || (config->exec_prefix == NULL))
363 {
364 _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
365 if (_Py_INIT_FAILED(err)) {
366 return err;
367 }
368 }
369
370 if (config->base_prefix == NULL) {
371 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
372 return _Py_INIT_NO_MEMORY();
373 }
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 Stinner1dc6e392018-07-25 02:49:17 +0200379 return _Py_INIT_NO_MEMORY();
380 }
381 }
382 return _Py_INIT_OK();
383}
384
385
Victor Stinner31a83932017-12-04 13:39:15 +0100386static void
387pathconfig_global_init(void)
388{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200389 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100390 /* Already initialized */
391 return;
392 }
393
394 _PyInitError err;
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100395 _PyCoreConfig config = _PyCoreConfig_INIT;
Victor Stinner31a83932017-12-04 13:39:15 +0100396
Victor Stinner5f38b842019-05-01 02:30:12 +0200397 err = _PyCoreConfig_Read(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100398 if (_Py_INIT_FAILED(err)) {
399 goto error;
400 }
401
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200402 err = _PyCoreConfig_SetPathConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100403 if (_Py_INIT_FAILED(err)) {
404 goto error;
405 }
406
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100407 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100408 return;
409
410error:
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100411 _PyCoreConfig_Clear(&config);
Victor Stinnerdfe88472019-03-01 12:14:41 +0100412 _Py_ExitInitError(err);
Victor Stinner31a83932017-12-04 13:39:15 +0100413}
414
415
416/* External interface */
417
418void
419Py_SetPath(const wchar_t *path)
420{
421 if (path == NULL) {
422 _PyPathConfig_Clear(&_Py_path_config);
423 return;
424 }
425
426 PyMemAllocatorEx old_alloc;
427 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
428
429 _PyPathConfig new_config;
430 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200431 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100432 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200433 alloc_error |= (new_config.prefix == NULL);
Steve Dower177a41a2018-11-17 20:41:48 -0800434 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
435 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100436#ifdef MS_WINDOWS
437 new_config.dll_path = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200438 alloc_error |= (new_config.dll_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100439#endif
440 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200441 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100442
443 /* steal the home and program_name values (to leave them unchanged) */
444 new_config.home = _Py_path_config.home;
445 _Py_path_config.home = NULL;
446 new_config.program_name = _Py_path_config.program_name;
447 _Py_path_config.program_name = NULL;
448
449 _PyPathConfig_Clear(&_Py_path_config);
450 _Py_path_config = new_config;
451
452 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200453
454 if (alloc_error) {
455 Py_FatalError("Py_SetPath() failed: out of memory");
456 }
Victor Stinner31a83932017-12-04 13:39:15 +0100457}
458
459
460void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200461Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100462{
463 if (home == NULL) {
464 return;
465 }
466
467 PyMemAllocatorEx old_alloc;
468 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
469
470 PyMem_RawFree(_Py_path_config.home);
471 _Py_path_config.home = _PyMem_RawWcsdup(home);
472
473 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
474
475 if (_Py_path_config.home == NULL) {
476 Py_FatalError("Py_SetPythonHome() failed: out of memory");
477 }
478}
479
480
481void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200482Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100483{
484 if (program_name == NULL || program_name[0] == L'\0') {
485 return;
486 }
487
488 PyMemAllocatorEx old_alloc;
489 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
490
491 PyMem_RawFree(_Py_path_config.program_name);
492 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
493
494 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
495
496 if (_Py_path_config.program_name == NULL) {
497 Py_FatalError("Py_SetProgramName() failed: out of memory");
498 }
499}
500
Steve Dower177a41a2018-11-17 20:41:48 -0800501void
502_Py_SetProgramFullPath(const wchar_t *program_full_path)
503{
504 if (program_full_path == NULL || program_full_path[0] == L'\0') {
505 return;
506 }
507
508 PyMemAllocatorEx old_alloc;
509 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
510
511 PyMem_RawFree(_Py_path_config.program_full_path);
512 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
513
514 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
515
516 if (_Py_path_config.program_full_path == NULL) {
517 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
518 }
519}
520
Victor Stinner31a83932017-12-04 13:39:15 +0100521
522wchar_t *
523Py_GetPath(void)
524{
525 pathconfig_global_init();
526 return _Py_path_config.module_search_path;
527}
528
529
530wchar_t *
531Py_GetPrefix(void)
532{
533 pathconfig_global_init();
534 return _Py_path_config.prefix;
535}
536
537
538wchar_t *
539Py_GetExecPrefix(void)
540{
Victor Stinner31a83932017-12-04 13:39:15 +0100541 pathconfig_global_init();
542 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100543}
544
545
546wchar_t *
547Py_GetProgramFullPath(void)
548{
549 pathconfig_global_init();
550 return _Py_path_config.program_full_path;
551}
552
553
554wchar_t*
555Py_GetPythonHome(void)
556{
557 pathconfig_global_init();
558 return _Py_path_config.home;
559}
560
561
562wchar_t *
563Py_GetProgramName(void)
564{
565 pathconfig_global_init();
566 return _Py_path_config.program_name;
567}
568
Victor Stinnerdcf61712019-03-19 16:09:27 +0100569/* Compute module search path from argv[0] or the current working
570 directory ("-m module" case) which will be prepended to sys.argv:
571 sys.path[0].
572
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200573 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100574
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200575 Return 0 if it fails to resolve the full path. For example, return 0 if the
576 current working directory has been removed (bpo-36236) or if argv is empty.
577
578 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100579 */
580int
581_PyPathConfig_ComputeSysPath0(const _PyWstrList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100582{
Victor Stinner74f65682019-03-15 15:08:05 +0100583 assert(_PyWstrList_CheckConsistency(argv));
584
Victor Stinnerfc96e542019-03-19 18:22:55 +0100585 if (argv->length == 0) {
586 /* Leave sys.path unchanged if sys.argv is empty */
587 return 0;
588 }
589
590 wchar_t *argv0 = argv->items[0];
591 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
592 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
593
594 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100595 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100596
597#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100598 wchar_t fullpath[MAXPATHLEN];
599#elif defined(MS_WINDOWS)
600 wchar_t fullpath[MAX_PATH];
601#endif
602
Nick Coghland5d9e022018-03-25 23:03:10 +1000603 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100604#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100605 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
606 return 0;
607 }
608 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100609#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100610 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100611#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100612 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000613 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100614
615#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100616 wchar_t link[MAXPATHLEN + 1];
617 int nr = 0;
618
619 if (have_script_arg) {
620 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
621 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100622 if (nr > 0) {
623 /* It's a symlink */
624 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100625 if (link[0] == SEP) {
626 path0 = link; /* Link to absolute path */
627 }
628 else if (wcschr(link, SEP) == NULL) {
629 /* Link without path */
630 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100631 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100632 /* Must join(dirname(path0), link) */
633 wchar_t *q = wcsrchr(path0, SEP);
634 if (q == NULL) {
635 /* path0 without path */
636 path0 = link;
637 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100638 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100639 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
640 wchar_t path0copy[2 * MAXPATHLEN + 1];
641 wcsncpy(path0copy, path0, MAXPATHLEN);
642 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100643 wcsncpy(q+1, link, MAXPATHLEN);
644 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100645 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100646 }
647 }
648 }
649#endif /* HAVE_READLINK */
650
Victor Stinnerfc96e542019-03-19 18:22:55 +0100651 wchar_t *p = NULL;
652
Victor Stinner11a247d2017-12-13 21:05:57 +0100653#if SEP == '\\'
654 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000655 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100656 wchar_t *q;
657#if defined(MS_WINDOWS)
658 /* Replace the first element in argv with the full path. */
659 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100660 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100661 Py_ARRAY_LENGTH(fullpath),
662 fullpath,
663 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100664 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100665 }
666#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100667 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100668 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100669 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100670 if (q != NULL)
671 p = q;
672 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100673 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100674 if (n > 1 && p[-1] != ':')
675 n--; /* Drop trailing separator */
676 }
677 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100678#else
679 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000680 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100681#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100682 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
683 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100684 }
685#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100686 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100687 }
688 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100689 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100690#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100691 if (n > 1) {
692 /* Drop trailing separator */
693 n--;
694 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100695#endif /* Unix */
696 }
697#endif /* All others */
698
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200699 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
700 if (path0_obj == NULL) {
701 return -1;
702 }
703
704 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100705 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100706}
707
Victor Stinner9bee3292017-12-21 16:49:13 +0100708
Minmin Gong8ebc6452019-02-02 20:26:55 -0800709#ifdef MS_WINDOWS
710#define WCSTOK wcstok_s
711#else
712#define WCSTOK wcstok
713#endif
714
Victor Stinner9bee3292017-12-21 16:49:13 +0100715/* Search for a prefix value in an environment file (pyvenv.cfg).
716 If found, copy it into the provided buffer. */
717int
718_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
719 wchar_t *value, size_t value_size)
720{
721 int result = 0; /* meaning not found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100722 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
723 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100724
725 fseek(env_file, 0, SEEK_SET);
726 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100727 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100728
729 if (p == NULL) {
730 break;
731 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100732
733 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100734 if (p[n - 1] != '\n') {
735 /* line has overflowed - bail */
736 break;
737 }
738 if (p[0] == '#') {
739 /* Comment - skip */
740 continue;
741 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100742
Victor Stinner5f9cf232019-03-19 01:46:25 +0100743 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100744 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100745 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800746 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100747 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800748 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100749 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800750 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100751 if (tok != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100752 wcsncpy(value, tok, value_size - 1);
753 value[value_size - 1] = L'\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100754 result = 1;
755 PyMem_RawFree(tmpbuffer);
756 break;
757 }
758 }
759 }
760 PyMem_RawFree(tmpbuffer);
761 }
762 }
763 return result;
764}
765
Victor Stinner31a83932017-12-04 13:39:15 +0100766#ifdef __cplusplus
767}
768#endif