blob: bbf29b2fa598193919c668ed56ebe5cda6ce7a52 [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
Victor Stinner410759f2019-05-18 04:17:01 +0200217 path_config.dll_path = _Py_GetDLLPath();
218 if (path_config.dll_path == NULL) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200219 goto no_memory;
220 }
221#endif
222 if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) {
223 goto no_memory;
224 }
225 if (copy_wstr(&path_config.home, core_config->home) < 0) {
226 goto no_memory;
227 }
228
229 err = _PyPathConfig_SetGlobal(&path_config);
230 if (_Py_INIT_FAILED(err)) {
231 goto done;
232 }
233
234 err = _Py_INIT_OK();
235 goto done;
236
237no_memory:
238 err = _Py_INIT_NO_MEMORY();
239
240done:
241 _PyPathConfig_Clear(&path_config);
242 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
243 return err;
244}
245
246
247static _PyInitError
248core_config_init_module_search_paths(_PyCoreConfig *config,
249 _PyPathConfig *path_config)
250{
Victor Stinner74f65682019-03-15 15:08:05 +0100251 assert(!config->use_module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200252
Victor Stinner74f65682019-03-15 15:08:05 +0100253 _PyWstrList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200254
255 const wchar_t *sys_path = path_config->module_search_path;
256 const wchar_t delim = DELIM;
257 const wchar_t *p = sys_path;
258 while (1) {
259 p = wcschr(sys_path, delim);
260 if (p == NULL) {
261 p = sys_path + wcslen(sys_path); /* End of string */
262 }
263
264 size_t path_len = (p - sys_path);
265 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
266 if (path == NULL) {
267 return _Py_INIT_NO_MEMORY();
268 }
269 memcpy(path, sys_path, path_len * sizeof(wchar_t));
270 path[path_len] = L'\0';
271
Victor Stinner74f65682019-03-15 15:08:05 +0100272 int res = _PyWstrList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200273 PyMem_RawFree(path);
Victor Stinner74f65682019-03-15 15:08:05 +0100274 if (res < 0) {
275 return _Py_INIT_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200276 }
277
278 if (*p == '\0') {
279 break;
280 }
281 sys_path = p + 1;
282 }
Victor Stinner74f65682019-03-15 15:08:05 +0100283 config->use_module_search_paths = 1;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200284 return _Py_INIT_OK();
285}
286
287
Victor Stinner1dc6e392018-07-25 02:49:17 +0200288static _PyInitError
289_PyCoreConfig_CalculatePathConfig(_PyCoreConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200290{
291 _PyPathConfig path_config = _PyPathConfig_INIT;
292 _PyInitError err;
293
294 err = _PyPathConfig_Calculate(&path_config, config);
295 if (_Py_INIT_FAILED(err)) {
296 goto error;
297 }
298
Victor Stinner74f65682019-03-15 15:08:05 +0100299 if (!config->use_module_search_paths) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200300 err = core_config_init_module_search_paths(config, &path_config);
301 if (_Py_INIT_FAILED(err)) {
302 goto error;
303 }
304 }
305
306 if (config->executable == NULL) {
307 if (copy_wstr(&config->executable,
308 path_config.program_full_path) < 0) {
309 goto no_memory;
310 }
311 }
312
313 if (config->prefix == NULL) {
314 if (copy_wstr(&config->prefix, path_config.prefix) < 0) {
315 goto no_memory;
316 }
317 }
318
319 if (config->exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800320 if (copy_wstr(&config->exec_prefix,
321 path_config.exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200322 goto no_memory;
323 }
324 }
325
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200326 if (path_config.isolated != -1) {
Victor Stinner20004952019-03-26 02:31:11 +0100327 config->isolated = path_config.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200328 }
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200329 if (path_config.site_import != -1) {
330 config->site_import = path_config.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200331 }
332
Victor Stinnerb1147e42018-07-21 02:06:16 +0200333 _PyPathConfig_Clear(&path_config);
334 return _Py_INIT_OK();
335
336no_memory:
337 err = _Py_INIT_NO_MEMORY();
338
339error:
340 _PyPathConfig_Clear(&path_config);
341 return err;
342}
343
344
Victor Stinner1dc6e392018-07-25 02:49:17 +0200345_PyInitError
346_PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
347{
348 /* Do we need to calculate the path? */
Victor Stinner74f65682019-03-15 15:08:05 +0100349 if (!config->use_module_search_paths
Victor Stinner1dc6e392018-07-25 02:49:17 +0200350 || (config->executable == NULL)
351 || (config->prefix == NULL)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200352 || (config->exec_prefix == NULL))
353 {
354 _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
355 if (_Py_INIT_FAILED(err)) {
356 return err;
357 }
358 }
359
360 if (config->base_prefix == NULL) {
361 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
362 return _Py_INIT_NO_MEMORY();
363 }
364 }
365
366 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800367 if (copy_wstr(&config->base_exec_prefix,
368 config->exec_prefix) < 0) {
Victor Stinner1dc6e392018-07-25 02:49:17 +0200369 return _Py_INIT_NO_MEMORY();
370 }
371 }
372 return _Py_INIT_OK();
373}
374
375
Victor Stinner31a83932017-12-04 13:39:15 +0100376static void
377pathconfig_global_init(void)
378{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200379 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100380 /* Already initialized */
381 return;
382 }
383
384 _PyInitError err;
Victor Stinnercab5d072019-05-17 19:01:14 +0200385 _PyCoreConfig config;
Victor Stinner022be022019-05-22 23:58:50 +0200386 _PyCoreConfig_InitCompatConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100387
Victor Stinner5f38b842019-05-01 02:30:12 +0200388 err = _PyCoreConfig_Read(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100389 if (_Py_INIT_FAILED(err)) {
390 goto error;
391 }
392
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200393 err = _PyCoreConfig_SetPathConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100394 if (_Py_INIT_FAILED(err)) {
395 goto error;
396 }
397
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100398 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100399 return;
400
401error:
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100402 _PyCoreConfig_Clear(&config);
Victor Stinnerdfe88472019-03-01 12:14:41 +0100403 _Py_ExitInitError(err);
Victor Stinner31a83932017-12-04 13:39:15 +0100404}
405
406
407/* External interface */
408
409void
410Py_SetPath(const wchar_t *path)
411{
412 if (path == NULL) {
413 _PyPathConfig_Clear(&_Py_path_config);
414 return;
415 }
416
417 PyMemAllocatorEx old_alloc;
418 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
419
420 _PyPathConfig new_config;
421 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200422 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100423 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200424 alloc_error |= (new_config.prefix == NULL);
Steve Dower177a41a2018-11-17 20:41:48 -0800425 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
426 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100427#ifdef MS_WINDOWS
Victor Stinner410759f2019-05-18 04:17:01 +0200428 new_config.dll_path = _Py_GetDLLPath();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200429 alloc_error |= (new_config.dll_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100430#endif
431 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200432 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100433
434 /* steal the home and program_name values (to leave them unchanged) */
435 new_config.home = _Py_path_config.home;
436 _Py_path_config.home = NULL;
437 new_config.program_name = _Py_path_config.program_name;
438 _Py_path_config.program_name = NULL;
439
440 _PyPathConfig_Clear(&_Py_path_config);
441 _Py_path_config = new_config;
442
443 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200444
445 if (alloc_error) {
446 Py_FatalError("Py_SetPath() failed: out of memory");
447 }
Victor Stinner31a83932017-12-04 13:39:15 +0100448}
449
450
451void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200452Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100453{
454 if (home == NULL) {
455 return;
456 }
457
458 PyMemAllocatorEx old_alloc;
459 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
460
461 PyMem_RawFree(_Py_path_config.home);
462 _Py_path_config.home = _PyMem_RawWcsdup(home);
463
464 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
465
466 if (_Py_path_config.home == NULL) {
467 Py_FatalError("Py_SetPythonHome() failed: out of memory");
468 }
469}
470
471
472void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200473Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100474{
475 if (program_name == NULL || program_name[0] == L'\0') {
476 return;
477 }
478
479 PyMemAllocatorEx old_alloc;
480 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
481
482 PyMem_RawFree(_Py_path_config.program_name);
483 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
484
485 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
486
487 if (_Py_path_config.program_name == NULL) {
488 Py_FatalError("Py_SetProgramName() failed: out of memory");
489 }
490}
491
Steve Dower177a41a2018-11-17 20:41:48 -0800492void
493_Py_SetProgramFullPath(const wchar_t *program_full_path)
494{
495 if (program_full_path == NULL || program_full_path[0] == L'\0') {
496 return;
497 }
498
499 PyMemAllocatorEx old_alloc;
500 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
501
502 PyMem_RawFree(_Py_path_config.program_full_path);
503 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
504
505 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
506
507 if (_Py_path_config.program_full_path == NULL) {
508 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
509 }
510}
511
Victor Stinner31a83932017-12-04 13:39:15 +0100512
513wchar_t *
514Py_GetPath(void)
515{
516 pathconfig_global_init();
517 return _Py_path_config.module_search_path;
518}
519
520
521wchar_t *
522Py_GetPrefix(void)
523{
524 pathconfig_global_init();
525 return _Py_path_config.prefix;
526}
527
528
529wchar_t *
530Py_GetExecPrefix(void)
531{
Victor Stinner31a83932017-12-04 13:39:15 +0100532 pathconfig_global_init();
533 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100534}
535
536
537wchar_t *
538Py_GetProgramFullPath(void)
539{
540 pathconfig_global_init();
541 return _Py_path_config.program_full_path;
542}
543
544
545wchar_t*
546Py_GetPythonHome(void)
547{
548 pathconfig_global_init();
549 return _Py_path_config.home;
550}
551
552
553wchar_t *
554Py_GetProgramName(void)
555{
556 pathconfig_global_init();
557 return _Py_path_config.program_name;
558}
559
Victor Stinnerdcf61712019-03-19 16:09:27 +0100560/* Compute module search path from argv[0] or the current working
561 directory ("-m module" case) which will be prepended to sys.argv:
562 sys.path[0].
563
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200564 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100565
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200566 Return 0 if it fails to resolve the full path. For example, return 0 if the
567 current working directory has been removed (bpo-36236) or if argv is empty.
568
569 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100570 */
571int
572_PyPathConfig_ComputeSysPath0(const _PyWstrList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100573{
Victor Stinner74f65682019-03-15 15:08:05 +0100574 assert(_PyWstrList_CheckConsistency(argv));
575
Victor Stinnerfc96e542019-03-19 18:22:55 +0100576 if (argv->length == 0) {
577 /* Leave sys.path unchanged if sys.argv is empty */
578 return 0;
579 }
580
581 wchar_t *argv0 = argv->items[0];
582 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
583 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
584
585 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100586 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100587
588#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100589 wchar_t fullpath[MAXPATHLEN];
590#elif defined(MS_WINDOWS)
591 wchar_t fullpath[MAX_PATH];
592#endif
593
Nick Coghland5d9e022018-03-25 23:03:10 +1000594 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100595#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100596 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
597 return 0;
598 }
599 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100600#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100601 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100602#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100603 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000604 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100605
606#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100607 wchar_t link[MAXPATHLEN + 1];
608 int nr = 0;
609
610 if (have_script_arg) {
611 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
612 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100613 if (nr > 0) {
614 /* It's a symlink */
615 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100616 if (link[0] == SEP) {
617 path0 = link; /* Link to absolute path */
618 }
619 else if (wcschr(link, SEP) == NULL) {
620 /* Link without path */
621 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100622 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100623 /* Must join(dirname(path0), link) */
624 wchar_t *q = wcsrchr(path0, SEP);
625 if (q == NULL) {
626 /* path0 without path */
627 path0 = link;
628 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100629 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100630 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
631 wchar_t path0copy[2 * MAXPATHLEN + 1];
632 wcsncpy(path0copy, path0, MAXPATHLEN);
633 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100634 wcsncpy(q+1, link, MAXPATHLEN);
635 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100636 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100637 }
638 }
639 }
640#endif /* HAVE_READLINK */
641
Victor Stinnerfc96e542019-03-19 18:22:55 +0100642 wchar_t *p = NULL;
643
Victor Stinner11a247d2017-12-13 21:05:57 +0100644#if SEP == '\\'
645 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000646 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100647 wchar_t *q;
648#if defined(MS_WINDOWS)
649 /* Replace the first element in argv with the full path. */
650 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100651 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100652 Py_ARRAY_LENGTH(fullpath),
653 fullpath,
654 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100655 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100656 }
657#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100658 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100659 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100660 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100661 if (q != NULL)
662 p = q;
663 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100664 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100665 if (n > 1 && p[-1] != ':')
666 n--; /* Drop trailing separator */
667 }
668 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100669#else
670 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000671 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100672#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100673 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
674 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100675 }
676#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100677 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100678 }
679 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100680 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100681#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100682 if (n > 1) {
683 /* Drop trailing separator */
684 n--;
685 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100686#endif /* Unix */
687 }
688#endif /* All others */
689
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200690 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
691 if (path0_obj == NULL) {
692 return -1;
693 }
694
695 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100696 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100697}
698
Victor Stinner9bee3292017-12-21 16:49:13 +0100699
Minmin Gong8ebc6452019-02-02 20:26:55 -0800700#ifdef MS_WINDOWS
701#define WCSTOK wcstok_s
702#else
703#define WCSTOK wcstok
704#endif
705
Victor Stinner9bee3292017-12-21 16:49:13 +0100706/* Search for a prefix value in an environment file (pyvenv.cfg).
707 If found, copy it into the provided buffer. */
708int
709_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
710 wchar_t *value, size_t value_size)
711{
712 int result = 0; /* meaning not found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100713 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
714 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100715
716 fseek(env_file, 0, SEEK_SET);
717 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100718 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100719
720 if (p == NULL) {
721 break;
722 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100723
724 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100725 if (p[n - 1] != '\n') {
726 /* line has overflowed - bail */
727 break;
728 }
729 if (p[0] == '#') {
730 /* Comment - skip */
731 continue;
732 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100733
Victor Stinner5f9cf232019-03-19 01:46:25 +0100734 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100735 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100736 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800737 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100738 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800739 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100740 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800741 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100742 if (tok != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100743 wcsncpy(value, tok, value_size - 1);
744 value[value_size - 1] = L'\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100745 result = 1;
746 PyMem_RawFree(tmpbuffer);
747 break;
748 }
749 }
750 }
751 PyMem_RawFree(tmpbuffer);
752 }
753 }
754 return result;
755}
756
Victor Stinner31a83932017-12-04 13:39:15 +0100757#ifdef __cplusplus
758}
759#endif