blob: efccb8d6bb8523982452ef58fbe17555c10176d7 [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 Stinner2be00d92018-10-31 20:19:24 +01005#include "internal/mem.h"
Victor Stinner31a83932017-12-04 13:39:15 +01006#include "internal/pystate.h"
Nick Coghland5d9e022018-03-25 23:03:10 +10007#include <wchar.h>
Victor Stinner31a83932017-12-04 13:39:15 +01008
9#ifdef __cplusplus
10extern "C" {
11#endif
12
13
14_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
15
16
Victor Stinnerb1147e42018-07-21 02:06:16 +020017static int
18copy_wstr(wchar_t **dst, const wchar_t *src)
19{
20 if (src != NULL) {
21 *dst = _PyMem_RawWcsdup(src);
22 if (*dst == NULL) {
23 return -1;
24 }
25 }
26 else {
27 *dst = NULL;
28 }
29 return 0;
30}
31
32
33static void
Victor Stinner31a83932017-12-04 13:39:15 +010034_PyPathConfig_Clear(_PyPathConfig *config)
35{
36 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
37 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
38 called before Py_Initialize() which can changes the memory allocator. */
39 PyMemAllocatorEx old_alloc;
40 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
41
42#define CLEAR(ATTR) \
43 do { \
44 PyMem_RawFree(ATTR); \
45 ATTR = NULL; \
46 } while (0)
47
48 CLEAR(config->prefix);
49 CLEAR(config->program_full_path);
50#ifdef MS_WINDOWS
51 CLEAR(config->dll_path);
52#else
53 CLEAR(config->exec_prefix);
54#endif
55 CLEAR(config->module_search_path);
56 CLEAR(config->home);
57 CLEAR(config->program_name);
58#undef CLEAR
59
60 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
61}
62
63
Victor Stinnerb1147e42018-07-21 02:06:16 +020064/* Calculate the path configuration: initialize path_config from core_config */
65static _PyInitError
66_PyPathConfig_Calculate(_PyPathConfig *path_config,
67 const _PyCoreConfig *core_config)
Victor Stinner31a83932017-12-04 13:39:15 +010068{
Victor Stinner31a83932017-12-04 13:39:15 +010069 _PyInitError err;
70 _PyPathConfig new_config = _PyPathConfig_INIT;
71
72 PyMemAllocatorEx old_alloc;
73 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
74
75 /* Calculate program_full_path, prefix, exec_prefix (Unix)
76 or dll_path (Windows), and module_search_path */
Victor Stinnerb1147e42018-07-21 02:06:16 +020077 err = _PyPathConfig_Calculate_impl(&new_config, core_config);
Victor Stinner31a83932017-12-04 13:39:15 +010078 if (_Py_INIT_FAILED(err)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +020079 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010080 }
81
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +010082 /* Copy home and program_name from core_config */
Victor Stinnerb1147e42018-07-21 02:06:16 +020083 if (copy_wstr(&new_config.home, core_config->home) < 0) {
84 err = _Py_INIT_NO_MEMORY();
85 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010086 }
Victor Stinnerb1147e42018-07-21 02:06:16 +020087 if (copy_wstr(&new_config.program_name, core_config->program_name) < 0) {
88 err = _Py_INIT_NO_MEMORY();
89 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010090 }
91
Victor Stinnerb1147e42018-07-21 02:06:16 +020092 _PyPathConfig_Clear(path_config);
93 *path_config = new_config;
94
95 err = _Py_INIT_OK();
96 goto done;
97
98err:
99 _PyPathConfig_Clear(&new_config);
100
101done:
102 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
103 return err;
104}
105
106
107_PyInitError
108_PyPathConfig_SetGlobal(const _PyPathConfig *config)
109{
110 _PyInitError err;
111 _PyPathConfig new_config = _PyPathConfig_INIT;
112
113 PyMemAllocatorEx old_alloc;
114 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
115
116#define COPY_ATTR(ATTR) \
117 do { \
118 if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \
119 _PyPathConfig_Clear(&new_config); \
120 err = _Py_INIT_NO_MEMORY(); \
121 goto done; \
122 } \
123 } while (0)
124
125 COPY_ATTR(program_full_path);
126 COPY_ATTR(prefix);
127#ifdef MS_WINDOWS
128 COPY_ATTR(dll_path);
129#else
130 COPY_ATTR(exec_prefix);
131#endif
132 COPY_ATTR(module_search_path);
133 COPY_ATTR(program_name);
134 COPY_ATTR(home);
Victor Stinner31a83932017-12-04 13:39:15 +0100135
136 _PyPathConfig_Clear(&_Py_path_config);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200137 /* Steal new_config strings; don't clear new_config */
Victor Stinner31a83932017-12-04 13:39:15 +0100138 _Py_path_config = new_config;
139
140 err = _Py_INIT_OK();
141
142done:
143 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
144 return err;
145}
146
147
Victor Stinnerb1147e42018-07-21 02:06:16 +0200148void
149_PyPathConfig_ClearGlobal(void)
150{
151 _PyPathConfig_Clear(&_Py_path_config);
152}
153
154
155static wchar_t*
156wstrlist_join(wchar_t sep, int count, wchar_t **list)
157{
158 size_t len = 1; /* NUL terminator */
159 for (int i=0; i < count; i++) {
160 if (i != 0) {
161 len++;
162 }
163 len += wcslen(list[i]);
164 }
165
166 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
167 if (text == NULL) {
168 return NULL;
169 }
170 wchar_t *str = text;
171 for (int i=0; i < count; i++) {
172 wchar_t *path = list[i];
173 if (i != 0) {
174 *str++ = SEP;
175 }
176 len = wcslen(path);
177 memcpy(str, path, len * sizeof(wchar_t));
178 str += len;
179 }
180 *str = L'\0';
181
182 return text;
183}
184
185
186/* Set the global path configuration from core_config. */
187_PyInitError
188_PyCoreConfig_SetPathConfig(const _PyCoreConfig *core_config)
189{
190 PyMemAllocatorEx old_alloc;
191 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
192
193 _PyInitError err;
194 _PyPathConfig path_config = _PyPathConfig_INIT;
195
196 path_config.module_search_path = wstrlist_join(DELIM,
197 core_config->nmodule_search_path,
198 core_config->module_search_paths);
199 if (path_config.module_search_path == NULL) {
200 goto no_memory;
201 }
202
203 if (copy_wstr(&path_config.program_full_path, core_config->executable) < 0) {
204 goto no_memory;
205 }
206 if (copy_wstr(&path_config.prefix, core_config->prefix) < 0) {
207 goto no_memory;
208 }
209#ifdef MS_WINDOWS
210 if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
211 goto no_memory;
212 }
213#else
214 if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
215 goto no_memory;
216 }
217#endif
218 if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) {
219 goto no_memory;
220 }
221 if (copy_wstr(&path_config.home, core_config->home) < 0) {
222 goto no_memory;
223 }
224
225 err = _PyPathConfig_SetGlobal(&path_config);
226 if (_Py_INIT_FAILED(err)) {
227 goto done;
228 }
229
230 err = _Py_INIT_OK();
231 goto done;
232
233no_memory:
234 err = _Py_INIT_NO_MEMORY();
235
236done:
237 _PyPathConfig_Clear(&path_config);
238 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
239 return err;
240}
241
242
243static _PyInitError
244core_config_init_module_search_paths(_PyCoreConfig *config,
245 _PyPathConfig *path_config)
246{
247 assert(config->module_search_paths == NULL);
248 assert(config->nmodule_search_path < 0);
249
250 config->nmodule_search_path = 0;
251
252 const wchar_t *sys_path = path_config->module_search_path;
253 const wchar_t delim = DELIM;
254 const wchar_t *p = sys_path;
255 while (1) {
256 p = wcschr(sys_path, delim);
257 if (p == NULL) {
258 p = sys_path + wcslen(sys_path); /* End of string */
259 }
260
261 size_t path_len = (p - sys_path);
262 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
263 if (path == NULL) {
264 return _Py_INIT_NO_MEMORY();
265 }
266 memcpy(path, sys_path, path_len * sizeof(wchar_t));
267 path[path_len] = L'\0';
268
269 _PyInitError err = _Py_wstrlist_append(&config->nmodule_search_path,
270 &config->module_search_paths,
271 path);
272 PyMem_RawFree(path);
273 if (_Py_INIT_FAILED(err)) {
274 return err;
275 }
276
277 if (*p == '\0') {
278 break;
279 }
280 sys_path = p + 1;
281 }
282 return _Py_INIT_OK();
283}
284
285
Victor Stinner1dc6e392018-07-25 02:49:17 +0200286static _PyInitError
287_PyCoreConfig_CalculatePathConfig(_PyCoreConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200288{
289 _PyPathConfig path_config = _PyPathConfig_INIT;
290 _PyInitError err;
291
292 err = _PyPathConfig_Calculate(&path_config, config);
293 if (_Py_INIT_FAILED(err)) {
294 goto error;
295 }
296
297 if (config->nmodule_search_path < 0) {
298 err = core_config_init_module_search_paths(config, &path_config);
299 if (_Py_INIT_FAILED(err)) {
300 goto error;
301 }
302 }
303
304 if (config->executable == NULL) {
305 if (copy_wstr(&config->executable,
306 path_config.program_full_path) < 0) {
307 goto no_memory;
308 }
309 }
310
311 if (config->prefix == NULL) {
312 if (copy_wstr(&config->prefix, path_config.prefix) < 0) {
313 goto no_memory;
314 }
315 }
316
317 if (config->exec_prefix == NULL) {
318#ifdef MS_WINDOWS
319 wchar_t *exec_prefix = path_config.prefix;
320#else
321 wchar_t *exec_prefix = path_config.exec_prefix;
322#endif
323 if (copy_wstr(&config->exec_prefix, exec_prefix) < 0) {
324 goto no_memory;
325 }
326 }
327
328#ifdef MS_WINDOWS
329 if (config->dll_path == NULL) {
330 if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
331 goto no_memory;
332 }
333 }
334#endif
335
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200336 if (path_config.isolated != -1) {
337 config->isolated = path_config.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200338 }
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200339 if (path_config.site_import != -1) {
340 config->site_import = path_config.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200341 }
342
Victor Stinnerb1147e42018-07-21 02:06:16 +0200343 _PyPathConfig_Clear(&path_config);
344 return _Py_INIT_OK();
345
346no_memory:
347 err = _Py_INIT_NO_MEMORY();
348
349error:
350 _PyPathConfig_Clear(&path_config);
351 return err;
352}
353
354
Victor Stinner1dc6e392018-07-25 02:49:17 +0200355_PyInitError
356_PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
357{
358 /* Do we need to calculate the path? */
359 if ((config->nmodule_search_path < 0)
360 || (config->executable == NULL)
361 || (config->prefix == NULL)
362#ifdef MS_WINDOWS
363 || (config->dll_path == NULL)
364#endif
365 || (config->exec_prefix == NULL))
366 {
367 _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
368 if (_Py_INIT_FAILED(err)) {
369 return err;
370 }
371 }
372
373 if (config->base_prefix == NULL) {
374 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
375 return _Py_INIT_NO_MEMORY();
376 }
377 }
378
379 if (config->base_exec_prefix == NULL) {
380 if (copy_wstr(&config->base_exec_prefix, config->exec_prefix) < 0) {
381 return _Py_INIT_NO_MEMORY();
382 }
383 }
384 return _Py_INIT_OK();
385}
386
387
Victor Stinner31a83932017-12-04 13:39:15 +0100388static void
389pathconfig_global_init(void)
390{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200391 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100392 /* Already initialized */
393 return;
394 }
395
396 _PyInitError err;
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100397 _PyCoreConfig config = _PyCoreConfig_INIT;
Victor Stinner31a83932017-12-04 13:39:15 +0100398
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200399 err = _PyCoreConfig_Read(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100400 if (_Py_INIT_FAILED(err)) {
401 goto error;
402 }
403
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200404 err = _PyCoreConfig_SetPathConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100405 if (_Py_INIT_FAILED(err)) {
406 goto error;
407 }
408
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100409 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100410 return;
411
412error:
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100413 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100414 _Py_FatalInitError(err);
415}
416
417
418/* External interface */
419
420void
421Py_SetPath(const wchar_t *path)
422{
423 if (path == NULL) {
424 _PyPathConfig_Clear(&_Py_path_config);
425 return;
426 }
427
428 PyMemAllocatorEx old_alloc;
429 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
430
431 _PyPathConfig new_config;
432 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200433 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100434 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200435 alloc_error |= (new_config.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#else
440 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200441 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100442#endif
443 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200444 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100445
446 /* steal the home and program_name values (to leave them unchanged) */
447 new_config.home = _Py_path_config.home;
448 _Py_path_config.home = NULL;
449 new_config.program_name = _Py_path_config.program_name;
450 _Py_path_config.program_name = NULL;
451
452 _PyPathConfig_Clear(&_Py_path_config);
453 _Py_path_config = new_config;
454
455 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200456
457 if (alloc_error) {
458 Py_FatalError("Py_SetPath() failed: out of memory");
459 }
Victor Stinner31a83932017-12-04 13:39:15 +0100460}
461
462
463void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200464Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100465{
466 if (home == NULL) {
467 return;
468 }
469
470 PyMemAllocatorEx old_alloc;
471 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
472
473 PyMem_RawFree(_Py_path_config.home);
474 _Py_path_config.home = _PyMem_RawWcsdup(home);
475
476 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
477
478 if (_Py_path_config.home == NULL) {
479 Py_FatalError("Py_SetPythonHome() failed: out of memory");
480 }
481}
482
483
484void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200485Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100486{
487 if (program_name == NULL || program_name[0] == L'\0') {
488 return;
489 }
490
491 PyMemAllocatorEx old_alloc;
492 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
493
494 PyMem_RawFree(_Py_path_config.program_name);
495 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
496
497 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
498
499 if (_Py_path_config.program_name == NULL) {
500 Py_FatalError("Py_SetProgramName() failed: out of memory");
501 }
502}
503
504
505wchar_t *
506Py_GetPath(void)
507{
508 pathconfig_global_init();
509 return _Py_path_config.module_search_path;
510}
511
512
513wchar_t *
514Py_GetPrefix(void)
515{
516 pathconfig_global_init();
517 return _Py_path_config.prefix;
518}
519
520
521wchar_t *
522Py_GetExecPrefix(void)
523{
524#ifdef MS_WINDOWS
525 return Py_GetPrefix();
526#else
527 pathconfig_global_init();
528 return _Py_path_config.exec_prefix;
529#endif
530}
531
532
533wchar_t *
534Py_GetProgramFullPath(void)
535{
536 pathconfig_global_init();
537 return _Py_path_config.program_full_path;
538}
539
540
541wchar_t*
542Py_GetPythonHome(void)
543{
544 pathconfig_global_init();
545 return _Py_path_config.home;
546}
547
548
549wchar_t *
550Py_GetProgramName(void)
551{
552 pathconfig_global_init();
553 return _Py_path_config.program_name;
554}
555
Victor Stinner11a247d2017-12-13 21:05:57 +0100556/* Compute argv[0] which will be prepended to sys.argv */
557PyObject*
558_PyPathConfig_ComputeArgv0(int argc, wchar_t **argv)
559{
560 wchar_t *argv0;
561 wchar_t *p = NULL;
562 Py_ssize_t n = 0;
Nick Coghland5d9e022018-03-25 23:03:10 +1000563 int have_script_arg = 0;
564 int have_module_arg = 0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100565#ifdef HAVE_READLINK
566 wchar_t link[MAXPATHLEN+1];
567 wchar_t argv0copy[2*MAXPATHLEN+1];
568 int nr = 0;
569#endif
570#if defined(HAVE_REALPATH)
571 wchar_t fullpath[MAXPATHLEN];
572#elif defined(MS_WINDOWS)
573 wchar_t fullpath[MAX_PATH];
574#endif
575
Victor Stinner11a247d2017-12-13 21:05:57 +0100576 argv0 = argv[0];
Nick Coghland5d9e022018-03-25 23:03:10 +1000577 if (argc > 0 && argv0 != NULL) {
578 have_module_arg = (wcscmp(argv0, L"-m") == 0);
579 have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
580 }
581
582 if (have_module_arg) {
583 #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
584 _Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath));
585 argv0 = fullpath;
586 n = wcslen(argv0);
587 #else
588 argv0 = L".";
589 n = 1;
590 #endif
591 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100592
593#ifdef HAVE_READLINK
Nick Coghland5d9e022018-03-25 23:03:10 +1000594 if (have_script_arg)
Victor Stinner11a247d2017-12-13 21:05:57 +0100595 nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
596 if (nr > 0) {
597 /* It's a symlink */
598 link[nr] = '\0';
599 if (link[0] == SEP)
600 argv0 = link; /* Link to absolute path */
601 else if (wcschr(link, SEP) == NULL)
602 ; /* Link without path */
603 else {
604 /* Must join(dirname(argv0), link) */
605 wchar_t *q = wcsrchr(argv0, SEP);
606 if (q == NULL)
607 argv0 = link; /* argv0 without path */
608 else {
609 /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
610 wcsncpy(argv0copy, argv0, MAXPATHLEN);
611 q = wcsrchr(argv0copy, SEP);
612 wcsncpy(q+1, link, MAXPATHLEN);
613 q[MAXPATHLEN + 1] = L'\0';
614 argv0 = argv0copy;
615 }
616 }
617 }
618#endif /* HAVE_READLINK */
619
620#if SEP == '\\'
621 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000622 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100623 wchar_t *q;
624#if defined(MS_WINDOWS)
625 /* Replace the first element in argv with the full path. */
626 wchar_t *ptemp;
627 if (GetFullPathNameW(argv0,
628 Py_ARRAY_LENGTH(fullpath),
629 fullpath,
630 &ptemp)) {
631 argv0 = fullpath;
632 }
633#endif
634 p = wcsrchr(argv0, SEP);
635 /* Test for alternate separator */
636 q = wcsrchr(p ? p : argv0, '/');
637 if (q != NULL)
638 p = q;
639 if (p != NULL) {
640 n = p + 1 - argv0;
641 if (n > 1 && p[-1] != ':')
642 n--; /* Drop trailing separator */
643 }
644 }
645#else /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000646 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100647#if defined(HAVE_REALPATH)
648 if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
649 argv0 = fullpath;
650 }
651#endif
652 p = wcsrchr(argv0, SEP);
653 }
654 if (p != NULL) {
655 n = p + 1 - argv0;
656#if SEP == '/' /* Special case for Unix filename syntax */
657 if (n > 1)
658 n--; /* Drop trailing separator */
659#endif /* Unix */
660 }
661#endif /* All others */
662
663 return PyUnicode_FromWideChar(argv0, n);
664}
665
Victor Stinner9bee3292017-12-21 16:49:13 +0100666
667/* Search for a prefix value in an environment file (pyvenv.cfg).
668 If found, copy it into the provided buffer. */
669int
670_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
671 wchar_t *value, size_t value_size)
672{
673 int result = 0; /* meaning not found */
674 char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */
675
676 fseek(env_file, 0, SEEK_SET);
677 while (!feof(env_file)) {
678 char * p = fgets(buffer, MAXPATHLEN*2, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100679
680 if (p == NULL) {
681 break;
682 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100683
684 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100685 if (p[n - 1] != '\n') {
686 /* line has overflowed - bail */
687 break;
688 }
689 if (p[0] == '#') {
690 /* Comment - skip */
691 continue;
692 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100693
694 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100695 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100696 wchar_t * state;
697 wchar_t * tok = wcstok(tmpbuffer, L" \t\r\n", &state);
698 if ((tok != NULL) && !wcscmp(tok, key)) {
699 tok = wcstok(NULL, L" \t", &state);
700 if ((tok != NULL) && !wcscmp(tok, L"=")) {
701 tok = wcstok(NULL, L"\r\n", &state);
702 if (tok != NULL) {
703 wcsncpy(value, tok, MAXPATHLEN);
704 result = 1;
705 PyMem_RawFree(tmpbuffer);
706 break;
707 }
708 }
709 }
710 PyMem_RawFree(tmpbuffer);
711 }
712 }
713 return result;
714}
715
Victor Stinner31a83932017-12-04 13:39:15 +0100716#ifdef __cplusplus
717}
718#endif