blob: f8bcc2886a1cb5b5d3b6fa7f202f91bbfe5715ca [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 Stinner27e2d1f2018-11-01 00:52:28 +01005#include "pycore_mem.h"
Victor Stinnera1c249c2018-11-01 03:15:58 +01006#include "pycore_pathconfig.h"
Victor Stinner27e2d1f2018-11-01 00:52:28 +01007#include "pycore_state.h"
Nick Coghland5d9e022018-03-25 23:03:10 +10008#include <wchar.h>
Victor Stinner31a83932017-12-04 13:39:15 +01009
10#ifdef __cplusplus
11extern "C" {
12#endif
13
14
15_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
16
17
Victor Stinnerb1147e42018-07-21 02:06:16 +020018static int
19copy_wstr(wchar_t **dst, const wchar_t *src)
20{
21 if (src != NULL) {
22 *dst = _PyMem_RawWcsdup(src);
23 if (*dst == NULL) {
24 return -1;
25 }
26 }
27 else {
28 *dst = NULL;
29 }
30 return 0;
31}
32
33
34static void
Victor Stinner31a83932017-12-04 13:39:15 +010035_PyPathConfig_Clear(_PyPathConfig *config)
36{
37 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
38 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
39 called before Py_Initialize() which can changes the memory allocator. */
40 PyMemAllocatorEx old_alloc;
41 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
42
43#define CLEAR(ATTR) \
44 do { \
45 PyMem_RawFree(ATTR); \
46 ATTR = NULL; \
47 } while (0)
48
49 CLEAR(config->prefix);
50 CLEAR(config->program_full_path);
51#ifdef MS_WINDOWS
52 CLEAR(config->dll_path);
53#else
54 CLEAR(config->exec_prefix);
55#endif
56 CLEAR(config->module_search_path);
57 CLEAR(config->home);
58 CLEAR(config->program_name);
59#undef CLEAR
60
61 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
62}
63
64
Victor Stinnerb1147e42018-07-21 02:06:16 +020065/* Calculate the path configuration: initialize path_config from core_config */
66static _PyInitError
67_PyPathConfig_Calculate(_PyPathConfig *path_config,
68 const _PyCoreConfig *core_config)
Victor Stinner31a83932017-12-04 13:39:15 +010069{
Victor Stinner31a83932017-12-04 13:39:15 +010070 _PyInitError err;
71 _PyPathConfig new_config = _PyPathConfig_INIT;
72
73 PyMemAllocatorEx old_alloc;
74 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
75
76 /* Calculate program_full_path, prefix, exec_prefix (Unix)
77 or dll_path (Windows), and module_search_path */
Victor Stinnerb1147e42018-07-21 02:06:16 +020078 err = _PyPathConfig_Calculate_impl(&new_config, core_config);
Victor Stinner31a83932017-12-04 13:39:15 +010079 if (_Py_INIT_FAILED(err)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +020080 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010081 }
82
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +010083 /* Copy home and program_name from core_config */
Victor Stinnerb1147e42018-07-21 02:06:16 +020084 if (copy_wstr(&new_config.home, core_config->home) < 0) {
85 err = _Py_INIT_NO_MEMORY();
86 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010087 }
Victor Stinnerb1147e42018-07-21 02:06:16 +020088 if (copy_wstr(&new_config.program_name, core_config->program_name) < 0) {
89 err = _Py_INIT_NO_MEMORY();
90 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010091 }
92
Victor Stinnerb1147e42018-07-21 02:06:16 +020093 _PyPathConfig_Clear(path_config);
94 *path_config = new_config;
95
96 err = _Py_INIT_OK();
97 goto done;
98
99err:
100 _PyPathConfig_Clear(&new_config);
101
102done:
103 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
104 return err;
105}
106
107
108_PyInitError
109_PyPathConfig_SetGlobal(const _PyPathConfig *config)
110{
111 _PyInitError err;
112 _PyPathConfig new_config = _PyPathConfig_INIT;
113
114 PyMemAllocatorEx old_alloc;
115 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
116
117#define COPY_ATTR(ATTR) \
118 do { \
119 if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \
120 _PyPathConfig_Clear(&new_config); \
121 err = _Py_INIT_NO_MEMORY(); \
122 goto done; \
123 } \
124 } while (0)
125
126 COPY_ATTR(program_full_path);
127 COPY_ATTR(prefix);
128#ifdef MS_WINDOWS
129 COPY_ATTR(dll_path);
130#else
131 COPY_ATTR(exec_prefix);
132#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{
152 _PyPathConfig_Clear(&_Py_path_config);
153}
154
155
156static wchar_t*
157wstrlist_join(wchar_t sep, int count, wchar_t **list)
158{
159 size_t len = 1; /* NUL terminator */
160 for (int i=0; i < count; i++) {
161 if (i != 0) {
162 len++;
163 }
164 len += wcslen(list[i]);
165 }
166
167 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
168 if (text == NULL) {
169 return NULL;
170 }
171 wchar_t *str = text;
172 for (int i=0; i < count; i++) {
173 wchar_t *path = list[i];
174 if (i != 0) {
175 *str++ = SEP;
176 }
177 len = wcslen(path);
178 memcpy(str, path, len * sizeof(wchar_t));
179 str += len;
180 }
181 *str = L'\0';
182
183 return text;
184}
185
186
187/* Set the global path configuration from core_config. */
188_PyInitError
189_PyCoreConfig_SetPathConfig(const _PyCoreConfig *core_config)
190{
191 PyMemAllocatorEx old_alloc;
192 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
193
194 _PyInitError err;
195 _PyPathConfig path_config = _PyPathConfig_INIT;
196
197 path_config.module_search_path = wstrlist_join(DELIM,
198 core_config->nmodule_search_path,
199 core_config->module_search_paths);
200 if (path_config.module_search_path == NULL) {
201 goto no_memory;
202 }
203
204 if (copy_wstr(&path_config.program_full_path, core_config->executable) < 0) {
205 goto no_memory;
206 }
207 if (copy_wstr(&path_config.prefix, core_config->prefix) < 0) {
208 goto no_memory;
209 }
210#ifdef MS_WINDOWS
211 if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
212 goto no_memory;
213 }
214#else
215 if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
216 goto no_memory;
217 }
218#endif
219 if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) {
220 goto no_memory;
221 }
222 if (copy_wstr(&path_config.home, core_config->home) < 0) {
223 goto no_memory;
224 }
225
226 err = _PyPathConfig_SetGlobal(&path_config);
227 if (_Py_INIT_FAILED(err)) {
228 goto done;
229 }
230
231 err = _Py_INIT_OK();
232 goto done;
233
234no_memory:
235 err = _Py_INIT_NO_MEMORY();
236
237done:
238 _PyPathConfig_Clear(&path_config);
239 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
240 return err;
241}
242
243
244static _PyInitError
245core_config_init_module_search_paths(_PyCoreConfig *config,
246 _PyPathConfig *path_config)
247{
248 assert(config->module_search_paths == NULL);
249 assert(config->nmodule_search_path < 0);
250
251 config->nmodule_search_path = 0;
252
253 const wchar_t *sys_path = path_config->module_search_path;
254 const wchar_t delim = DELIM;
255 const wchar_t *p = sys_path;
256 while (1) {
257 p = wcschr(sys_path, delim);
258 if (p == NULL) {
259 p = sys_path + wcslen(sys_path); /* End of string */
260 }
261
262 size_t path_len = (p - sys_path);
263 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
264 if (path == NULL) {
265 return _Py_INIT_NO_MEMORY();
266 }
267 memcpy(path, sys_path, path_len * sizeof(wchar_t));
268 path[path_len] = L'\0';
269
270 _PyInitError err = _Py_wstrlist_append(&config->nmodule_search_path,
271 &config->module_search_paths,
272 path);
273 PyMem_RawFree(path);
274 if (_Py_INIT_FAILED(err)) {
275 return err;
276 }
277
278 if (*p == '\0') {
279 break;
280 }
281 sys_path = p + 1;
282 }
283 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
298 if (config->nmodule_search_path < 0) {
299 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) {
319#ifdef MS_WINDOWS
320 wchar_t *exec_prefix = path_config.prefix;
321#else
322 wchar_t *exec_prefix = path_config.exec_prefix;
323#endif
324 if (copy_wstr(&config->exec_prefix, exec_prefix) < 0) {
325 goto no_memory;
326 }
327 }
328
329#ifdef MS_WINDOWS
330 if (config->dll_path == NULL) {
331 if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
332 goto no_memory;
333 }
334 }
335#endif
336
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200337 if (path_config.isolated != -1) {
338 config->isolated = path_config.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200339 }
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200340 if (path_config.site_import != -1) {
341 config->site_import = path_config.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200342 }
343
Victor Stinnerb1147e42018-07-21 02:06:16 +0200344 _PyPathConfig_Clear(&path_config);
345 return _Py_INIT_OK();
346
347no_memory:
348 err = _Py_INIT_NO_MEMORY();
349
350error:
351 _PyPathConfig_Clear(&path_config);
352 return err;
353}
354
355
Victor Stinner1dc6e392018-07-25 02:49:17 +0200356_PyInitError
357_PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
358{
359 /* Do we need to calculate the path? */
360 if ((config->nmodule_search_path < 0)
361 || (config->executable == NULL)
362 || (config->prefix == NULL)
363#ifdef MS_WINDOWS
364 || (config->dll_path == NULL)
365#endif
366 || (config->exec_prefix == NULL))
367 {
368 _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
369 if (_Py_INIT_FAILED(err)) {
370 return err;
371 }
372 }
373
374 if (config->base_prefix == NULL) {
375 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
376 return _Py_INIT_NO_MEMORY();
377 }
378 }
379
380 if (config->base_exec_prefix == NULL) {
381 if (copy_wstr(&config->base_exec_prefix, config->exec_prefix) < 0) {
382 return _Py_INIT_NO_MEMORY();
383 }
384 }
385 return _Py_INIT_OK();
386}
387
388
Victor Stinner31a83932017-12-04 13:39:15 +0100389static void
390pathconfig_global_init(void)
391{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200392 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100393 /* Already initialized */
394 return;
395 }
396
397 _PyInitError err;
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100398 _PyCoreConfig config = _PyCoreConfig_INIT;
Victor Stinner31a83932017-12-04 13:39:15 +0100399
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200400 err = _PyCoreConfig_Read(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100401 if (_Py_INIT_FAILED(err)) {
402 goto error;
403 }
404
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200405 err = _PyCoreConfig_SetPathConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100406 if (_Py_INIT_FAILED(err)) {
407 goto error;
408 }
409
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100410 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100411 return;
412
413error:
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100414 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100415 _Py_FatalInitError(err);
416}
417
418
419/* External interface */
420
421void
422Py_SetPath(const wchar_t *path)
423{
424 if (path == NULL) {
425 _PyPathConfig_Clear(&_Py_path_config);
426 return;
427 }
428
429 PyMemAllocatorEx old_alloc;
430 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
431
432 _PyPathConfig new_config;
433 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200434 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100435 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200436 alloc_error |= (new_config.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#else
441 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200442 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100443#endif
444 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200445 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100446
447 /* steal the home and program_name values (to leave them unchanged) */
448 new_config.home = _Py_path_config.home;
449 _Py_path_config.home = NULL;
450 new_config.program_name = _Py_path_config.program_name;
451 _Py_path_config.program_name = NULL;
452
453 _PyPathConfig_Clear(&_Py_path_config);
454 _Py_path_config = new_config;
455
456 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200457
458 if (alloc_error) {
459 Py_FatalError("Py_SetPath() failed: out of memory");
460 }
Victor Stinner31a83932017-12-04 13:39:15 +0100461}
462
463
464void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200465Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100466{
467 if (home == NULL) {
468 return;
469 }
470
471 PyMemAllocatorEx old_alloc;
472 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
473
474 PyMem_RawFree(_Py_path_config.home);
475 _Py_path_config.home = _PyMem_RawWcsdup(home);
476
477 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
478
479 if (_Py_path_config.home == NULL) {
480 Py_FatalError("Py_SetPythonHome() failed: out of memory");
481 }
482}
483
484
485void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200486Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100487{
488 if (program_name == NULL || program_name[0] == L'\0') {
489 return;
490 }
491
492 PyMemAllocatorEx old_alloc;
493 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
494
495 PyMem_RawFree(_Py_path_config.program_name);
496 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
497
498 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
499
500 if (_Py_path_config.program_name == NULL) {
501 Py_FatalError("Py_SetProgramName() failed: out of memory");
502 }
503}
504
505
506wchar_t *
507Py_GetPath(void)
508{
509 pathconfig_global_init();
510 return _Py_path_config.module_search_path;
511}
512
513
514wchar_t *
515Py_GetPrefix(void)
516{
517 pathconfig_global_init();
518 return _Py_path_config.prefix;
519}
520
521
522wchar_t *
523Py_GetExecPrefix(void)
524{
525#ifdef MS_WINDOWS
526 return Py_GetPrefix();
527#else
528 pathconfig_global_init();
529 return _Py_path_config.exec_prefix;
530#endif
531}
532
533
534wchar_t *
535Py_GetProgramFullPath(void)
536{
537 pathconfig_global_init();
538 return _Py_path_config.program_full_path;
539}
540
541
542wchar_t*
543Py_GetPythonHome(void)
544{
545 pathconfig_global_init();
546 return _Py_path_config.home;
547}
548
549
550wchar_t *
551Py_GetProgramName(void)
552{
553 pathconfig_global_init();
554 return _Py_path_config.program_name;
555}
556
Victor Stinner11a247d2017-12-13 21:05:57 +0100557/* Compute argv[0] which will be prepended to sys.argv */
558PyObject*
559_PyPathConfig_ComputeArgv0(int argc, wchar_t **argv)
560{
561 wchar_t *argv0;
562 wchar_t *p = NULL;
563 Py_ssize_t n = 0;
Nick Coghland5d9e022018-03-25 23:03:10 +1000564 int have_script_arg = 0;
565 int have_module_arg = 0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100566#ifdef HAVE_READLINK
567 wchar_t link[MAXPATHLEN+1];
568 wchar_t argv0copy[2*MAXPATHLEN+1];
569 int nr = 0;
570#endif
571#if defined(HAVE_REALPATH)
572 wchar_t fullpath[MAXPATHLEN];
573#elif defined(MS_WINDOWS)
574 wchar_t fullpath[MAX_PATH];
575#endif
576
Victor Stinner11a247d2017-12-13 21:05:57 +0100577 argv0 = argv[0];
Nick Coghland5d9e022018-03-25 23:03:10 +1000578 if (argc > 0 && argv0 != NULL) {
579 have_module_arg = (wcscmp(argv0, L"-m") == 0);
580 have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
581 }
582
583 if (have_module_arg) {
584 #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
585 _Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath));
586 argv0 = fullpath;
587 n = wcslen(argv0);
588 #else
589 argv0 = L".";
590 n = 1;
591 #endif
592 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100593
594#ifdef HAVE_READLINK
Nick Coghland5d9e022018-03-25 23:03:10 +1000595 if (have_script_arg)
Victor Stinner11a247d2017-12-13 21:05:57 +0100596 nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
597 if (nr > 0) {
598 /* It's a symlink */
599 link[nr] = '\0';
600 if (link[0] == SEP)
601 argv0 = link; /* Link to absolute path */
602 else if (wcschr(link, SEP) == NULL)
603 ; /* Link without path */
604 else {
605 /* Must join(dirname(argv0), link) */
606 wchar_t *q = wcsrchr(argv0, SEP);
607 if (q == NULL)
608 argv0 = link; /* argv0 without path */
609 else {
610 /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
611 wcsncpy(argv0copy, argv0, MAXPATHLEN);
612 q = wcsrchr(argv0copy, SEP);
613 wcsncpy(q+1, link, MAXPATHLEN);
614 q[MAXPATHLEN + 1] = L'\0';
615 argv0 = argv0copy;
616 }
617 }
618 }
619#endif /* HAVE_READLINK */
620
621#if SEP == '\\'
622 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000623 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100624 wchar_t *q;
625#if defined(MS_WINDOWS)
626 /* Replace the first element in argv with the full path. */
627 wchar_t *ptemp;
628 if (GetFullPathNameW(argv0,
629 Py_ARRAY_LENGTH(fullpath),
630 fullpath,
631 &ptemp)) {
632 argv0 = fullpath;
633 }
634#endif
635 p = wcsrchr(argv0, SEP);
636 /* Test for alternate separator */
637 q = wcsrchr(p ? p : argv0, '/');
638 if (q != NULL)
639 p = q;
640 if (p != NULL) {
641 n = p + 1 - argv0;
642 if (n > 1 && p[-1] != ':')
643 n--; /* Drop trailing separator */
644 }
645 }
646#else /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000647 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100648#if defined(HAVE_REALPATH)
649 if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
650 argv0 = fullpath;
651 }
652#endif
653 p = wcsrchr(argv0, SEP);
654 }
655 if (p != NULL) {
656 n = p + 1 - argv0;
657#if SEP == '/' /* Special case for Unix filename syntax */
658 if (n > 1)
659 n--; /* Drop trailing separator */
660#endif /* Unix */
661 }
662#endif /* All others */
663
664 return PyUnicode_FromWideChar(argv0, n);
665}
666
Victor Stinner9bee3292017-12-21 16:49:13 +0100667
668/* Search for a prefix value in an environment file (pyvenv.cfg).
669 If found, copy it into the provided buffer. */
670int
671_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
672 wchar_t *value, size_t value_size)
673{
674 int result = 0; /* meaning not found */
675 char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */
676
677 fseek(env_file, 0, SEEK_SET);
678 while (!feof(env_file)) {
679 char * p = fgets(buffer, MAXPATHLEN*2, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100680
681 if (p == NULL) {
682 break;
683 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100684
685 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100686 if (p[n - 1] != '\n') {
687 /* line has overflowed - bail */
688 break;
689 }
690 if (p[0] == '#') {
691 /* Comment - skip */
692 continue;
693 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100694
695 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100696 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100697 wchar_t * state;
698 wchar_t * tok = wcstok(tmpbuffer, L" \t\r\n", &state);
699 if ((tok != NULL) && !wcscmp(tok, key)) {
700 tok = wcstok(NULL, L" \t", &state);
701 if ((tok != NULL) && !wcscmp(tok, L"=")) {
702 tok = wcstok(NULL, L"\r\n", &state);
703 if (tok != NULL) {
704 wcsncpy(value, tok, MAXPATHLEN);
705 result = 1;
706 PyMem_RawFree(tmpbuffer);
707 break;
708 }
709 }
710 }
711 PyMem_RawFree(tmpbuffer);
712 }
713 }
714 return result;
715}
716
Victor Stinner31a83932017-12-04 13:39:15 +0100717#ifdef __cplusplus
718}
719#endif