blob: c8c69ebad6a032bf6b4d3ef675943a115ad2a8b3 [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 Stinnercab5d072019-05-17 19:01:14 +0200395 _PyCoreConfig config;
396 _PyCoreConfig_Init(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100397
Victor Stinner5f38b842019-05-01 02:30:12 +0200398 err = _PyCoreConfig_Read(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100399 if (_Py_INIT_FAILED(err)) {
400 goto error;
401 }
402
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200403 err = _PyCoreConfig_SetPathConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100404 if (_Py_INIT_FAILED(err)) {
405 goto error;
406 }
407
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100408 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100409 return;
410
411error:
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100412 _PyCoreConfig_Clear(&config);
Victor Stinnerdfe88472019-03-01 12:14:41 +0100413 _Py_ExitInitError(err);
Victor Stinner31a83932017-12-04 13:39:15 +0100414}
415
416
417/* External interface */
418
419void
420Py_SetPath(const wchar_t *path)
421{
422 if (path == NULL) {
423 _PyPathConfig_Clear(&_Py_path_config);
424 return;
425 }
426
427 PyMemAllocatorEx old_alloc;
428 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
429
430 _PyPathConfig new_config;
431 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200432 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100433 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200434 alloc_error |= (new_config.prefix == NULL);
Steve Dower177a41a2018-11-17 20:41:48 -0800435 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
436 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100437#ifdef MS_WINDOWS
438 new_config.dll_path = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200439 alloc_error |= (new_config.dll_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100440#endif
441 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200442 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100443
444 /* steal the home and program_name values (to leave them unchanged) */
445 new_config.home = _Py_path_config.home;
446 _Py_path_config.home = NULL;
447 new_config.program_name = _Py_path_config.program_name;
448 _Py_path_config.program_name = NULL;
449
450 _PyPathConfig_Clear(&_Py_path_config);
451 _Py_path_config = new_config;
452
453 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200454
455 if (alloc_error) {
456 Py_FatalError("Py_SetPath() failed: out of memory");
457 }
Victor Stinner31a83932017-12-04 13:39:15 +0100458}
459
460
461void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200462Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100463{
464 if (home == NULL) {
465 return;
466 }
467
468 PyMemAllocatorEx old_alloc;
469 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
470
471 PyMem_RawFree(_Py_path_config.home);
472 _Py_path_config.home = _PyMem_RawWcsdup(home);
473
474 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
475
476 if (_Py_path_config.home == NULL) {
477 Py_FatalError("Py_SetPythonHome() failed: out of memory");
478 }
479}
480
481
482void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200483Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100484{
485 if (program_name == NULL || program_name[0] == L'\0') {
486 return;
487 }
488
489 PyMemAllocatorEx old_alloc;
490 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
491
492 PyMem_RawFree(_Py_path_config.program_name);
493 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
494
495 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
496
497 if (_Py_path_config.program_name == NULL) {
498 Py_FatalError("Py_SetProgramName() failed: out of memory");
499 }
500}
501
Steve Dower177a41a2018-11-17 20:41:48 -0800502void
503_Py_SetProgramFullPath(const wchar_t *program_full_path)
504{
505 if (program_full_path == NULL || program_full_path[0] == L'\0') {
506 return;
507 }
508
509 PyMemAllocatorEx old_alloc;
510 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
511
512 PyMem_RawFree(_Py_path_config.program_full_path);
513 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
514
515 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
516
517 if (_Py_path_config.program_full_path == NULL) {
518 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
519 }
520}
521
Victor Stinner31a83932017-12-04 13:39:15 +0100522
523wchar_t *
524Py_GetPath(void)
525{
526 pathconfig_global_init();
527 return _Py_path_config.module_search_path;
528}
529
530
531wchar_t *
532Py_GetPrefix(void)
533{
534 pathconfig_global_init();
535 return _Py_path_config.prefix;
536}
537
538
539wchar_t *
540Py_GetExecPrefix(void)
541{
Victor Stinner31a83932017-12-04 13:39:15 +0100542 pathconfig_global_init();
543 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100544}
545
546
547wchar_t *
548Py_GetProgramFullPath(void)
549{
550 pathconfig_global_init();
551 return _Py_path_config.program_full_path;
552}
553
554
555wchar_t*
556Py_GetPythonHome(void)
557{
558 pathconfig_global_init();
559 return _Py_path_config.home;
560}
561
562
563wchar_t *
564Py_GetProgramName(void)
565{
566 pathconfig_global_init();
567 return _Py_path_config.program_name;
568}
569
Victor Stinnerdcf61712019-03-19 16:09:27 +0100570/* Compute module search path from argv[0] or the current working
571 directory ("-m module" case) which will be prepended to sys.argv:
572 sys.path[0].
573
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200574 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100575
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200576 Return 0 if it fails to resolve the full path. For example, return 0 if the
577 current working directory has been removed (bpo-36236) or if argv is empty.
578
579 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100580 */
581int
582_PyPathConfig_ComputeSysPath0(const _PyWstrList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100583{
Victor Stinner74f65682019-03-15 15:08:05 +0100584 assert(_PyWstrList_CheckConsistency(argv));
585
Victor Stinnerfc96e542019-03-19 18:22:55 +0100586 if (argv->length == 0) {
587 /* Leave sys.path unchanged if sys.argv is empty */
588 return 0;
589 }
590
591 wchar_t *argv0 = argv->items[0];
592 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
593 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
594
595 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100596 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100597
598#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100599 wchar_t fullpath[MAXPATHLEN];
600#elif defined(MS_WINDOWS)
601 wchar_t fullpath[MAX_PATH];
602#endif
603
Nick Coghland5d9e022018-03-25 23:03:10 +1000604 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100605#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100606 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
607 return 0;
608 }
609 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100610#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100611 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100612#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100613 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000614 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100615
616#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100617 wchar_t link[MAXPATHLEN + 1];
618 int nr = 0;
619
620 if (have_script_arg) {
621 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
622 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100623 if (nr > 0) {
624 /* It's a symlink */
625 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100626 if (link[0] == SEP) {
627 path0 = link; /* Link to absolute path */
628 }
629 else if (wcschr(link, SEP) == NULL) {
630 /* Link without path */
631 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100632 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100633 /* Must join(dirname(path0), link) */
634 wchar_t *q = wcsrchr(path0, SEP);
635 if (q == NULL) {
636 /* path0 without path */
637 path0 = link;
638 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100639 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100640 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
641 wchar_t path0copy[2 * MAXPATHLEN + 1];
642 wcsncpy(path0copy, path0, MAXPATHLEN);
643 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100644 wcsncpy(q+1, link, MAXPATHLEN);
645 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100646 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100647 }
648 }
649 }
650#endif /* HAVE_READLINK */
651
Victor Stinnerfc96e542019-03-19 18:22:55 +0100652 wchar_t *p = NULL;
653
Victor Stinner11a247d2017-12-13 21:05:57 +0100654#if SEP == '\\'
655 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000656 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100657 wchar_t *q;
658#if defined(MS_WINDOWS)
659 /* Replace the first element in argv with the full path. */
660 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100661 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100662 Py_ARRAY_LENGTH(fullpath),
663 fullpath,
664 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100665 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100666 }
667#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100668 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100669 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100670 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100671 if (q != NULL)
672 p = q;
673 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100674 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100675 if (n > 1 && p[-1] != ':')
676 n--; /* Drop trailing separator */
677 }
678 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100679#else
680 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000681 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100682#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100683 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
684 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100685 }
686#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100687 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100688 }
689 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100690 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100691#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100692 if (n > 1) {
693 /* Drop trailing separator */
694 n--;
695 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100696#endif /* Unix */
697 }
698#endif /* All others */
699
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200700 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
701 if (path0_obj == NULL) {
702 return -1;
703 }
704
705 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100706 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100707}
708
Victor Stinner9bee3292017-12-21 16:49:13 +0100709
Minmin Gong8ebc6452019-02-02 20:26:55 -0800710#ifdef MS_WINDOWS
711#define WCSTOK wcstok_s
712#else
713#define WCSTOK wcstok
714#endif
715
Victor Stinner9bee3292017-12-21 16:49:13 +0100716/* Search for a prefix value in an environment file (pyvenv.cfg).
717 If found, copy it into the provided buffer. */
718int
719_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
720 wchar_t *value, size_t value_size)
721{
722 int result = 0; /* meaning not found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100723 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
724 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100725
726 fseek(env_file, 0, SEEK_SET);
727 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100728 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100729
730 if (p == NULL) {
731 break;
732 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100733
734 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100735 if (p[n - 1] != '\n') {
736 /* line has overflowed - bail */
737 break;
738 }
739 if (p[0] == '#') {
740 /* Comment - skip */
741 continue;
742 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100743
Victor Stinner5f9cf232019-03-19 01:46:25 +0100744 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100745 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100746 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800747 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100748 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800749 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100750 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800751 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100752 if (tok != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100753 wcsncpy(value, tok, value_size - 1);
754 value[value_size - 1] = L'\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100755 result = 1;
756 PyMem_RawFree(tmpbuffer);
757 break;
758 }
759 }
760 }
761 PyMem_RawFree(tmpbuffer);
762 }
763 }
764 return result;
765}
766
Victor Stinner31a83932017-12-04 13:39:15 +0100767#ifdef __cplusplus
768}
769#endif