blob: 2d8b417d31f7facad0b62c3095d1c4153421b3a2 [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 Stinner9fc57a32018-11-07 00:44:03 +01006#include "pycore_fileutils.h"
Victor Stinnera1c249c2018-11-01 03:15:58 +01007#include "pycore_pathconfig.h"
Victor Stinner27e2d1f2018-11-01 00:52:28 +01008#include "pycore_state.h"
Nick Coghland5d9e022018-03-25 23:03:10 +10009#include <wchar.h>
Victor Stinner31a83932017-12-04 13:39:15 +010010
11#ifdef __cplusplus
12extern "C" {
13#endif
14
15
16_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
17
18
Victor Stinnerb1147e42018-07-21 02:06:16 +020019static int
20copy_wstr(wchar_t **dst, const wchar_t *src)
21{
22 if (src != NULL) {
23 *dst = _PyMem_RawWcsdup(src);
24 if (*dst == NULL) {
25 return -1;
26 }
27 }
28 else {
29 *dst = NULL;
30 }
31 return 0;
32}
33
34
35static void
Victor Stinner31a83932017-12-04 13:39:15 +010036_PyPathConfig_Clear(_PyPathConfig *config)
37{
38 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
39 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
40 called before Py_Initialize() which can changes the memory allocator. */
41 PyMemAllocatorEx old_alloc;
42 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
43
44#define CLEAR(ATTR) \
45 do { \
46 PyMem_RawFree(ATTR); \
47 ATTR = NULL; \
48 } while (0)
49
50 CLEAR(config->prefix);
51 CLEAR(config->program_full_path);
52#ifdef MS_WINDOWS
53 CLEAR(config->dll_path);
54#else
55 CLEAR(config->exec_prefix);
56#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
77 /* Calculate program_full_path, prefix, exec_prefix (Unix)
78 or 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);
129#ifdef MS_WINDOWS
130 COPY_ATTR(dll_path);
131#else
132 COPY_ATTR(exec_prefix);
133#endif
134 COPY_ATTR(module_search_path);
135 COPY_ATTR(program_name);
136 COPY_ATTR(home);
Victor Stinner31a83932017-12-04 13:39:15 +0100137
138 _PyPathConfig_Clear(&_Py_path_config);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200139 /* Steal new_config strings; don't clear new_config */
Victor Stinner31a83932017-12-04 13:39:15 +0100140 _Py_path_config = new_config;
141
142 err = _Py_INIT_OK();
143
144done:
145 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
146 return err;
147}
148
149
Victor Stinnerb1147e42018-07-21 02:06:16 +0200150void
151_PyPathConfig_ClearGlobal(void)
152{
153 _PyPathConfig_Clear(&_Py_path_config);
154}
155
156
157static wchar_t*
158wstrlist_join(wchar_t sep, int count, wchar_t **list)
159{
160 size_t len = 1; /* NUL terminator */
161 for (int i=0; i < count; i++) {
162 if (i != 0) {
163 len++;
164 }
165 len += wcslen(list[i]);
166 }
167
168 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
169 if (text == NULL) {
170 return NULL;
171 }
172 wchar_t *str = text;
173 for (int i=0; i < count; i++) {
174 wchar_t *path = list[i];
175 if (i != 0) {
176 *str++ = SEP;
177 }
178 len = wcslen(path);
179 memcpy(str, path, len * sizeof(wchar_t));
180 str += len;
181 }
182 *str = L'\0';
183
184 return text;
185}
186
187
188/* Set the global path configuration from core_config. */
189_PyInitError
190_PyCoreConfig_SetPathConfig(const _PyCoreConfig *core_config)
191{
192 PyMemAllocatorEx old_alloc;
193 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
194
195 _PyInitError err;
196 _PyPathConfig path_config = _PyPathConfig_INIT;
197
198 path_config.module_search_path = wstrlist_join(DELIM,
199 core_config->nmodule_search_path,
200 core_config->module_search_paths);
201 if (path_config.module_search_path == NULL) {
202 goto no_memory;
203 }
204
205 if (copy_wstr(&path_config.program_full_path, core_config->executable) < 0) {
206 goto no_memory;
207 }
208 if (copy_wstr(&path_config.prefix, core_config->prefix) < 0) {
209 goto no_memory;
210 }
211#ifdef MS_WINDOWS
212 if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
213 goto no_memory;
214 }
215#else
216 if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
217 goto no_memory;
218 }
219#endif
220 if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) {
221 goto no_memory;
222 }
223 if (copy_wstr(&path_config.home, core_config->home) < 0) {
224 goto no_memory;
225 }
226
227 err = _PyPathConfig_SetGlobal(&path_config);
228 if (_Py_INIT_FAILED(err)) {
229 goto done;
230 }
231
232 err = _Py_INIT_OK();
233 goto done;
234
235no_memory:
236 err = _Py_INIT_NO_MEMORY();
237
238done:
239 _PyPathConfig_Clear(&path_config);
240 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
241 return err;
242}
243
244
245static _PyInitError
246core_config_init_module_search_paths(_PyCoreConfig *config,
247 _PyPathConfig *path_config)
248{
249 assert(config->module_search_paths == NULL);
250 assert(config->nmodule_search_path < 0);
251
252 config->nmodule_search_path = 0;
253
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
271 _PyInitError err = _Py_wstrlist_append(&config->nmodule_search_path,
272 &config->module_search_paths,
273 path);
274 PyMem_RawFree(path);
275 if (_Py_INIT_FAILED(err)) {
276 return err;
277 }
278
279 if (*p == '\0') {
280 break;
281 }
282 sys_path = p + 1;
283 }
284 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
299 if (config->nmodule_search_path < 0) {
300 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) {
320#ifdef MS_WINDOWS
321 wchar_t *exec_prefix = path_config.prefix;
322#else
323 wchar_t *exec_prefix = path_config.exec_prefix;
324#endif
325 if (copy_wstr(&config->exec_prefix, exec_prefix) < 0) {
326 goto no_memory;
327 }
328 }
329
330#ifdef MS_WINDOWS
331 if (config->dll_path == NULL) {
332 if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
333 goto no_memory;
334 }
335 }
336#endif
337
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200338 if (path_config.isolated != -1) {
339 config->isolated = path_config.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200340 }
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200341 if (path_config.site_import != -1) {
342 config->site_import = path_config.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200343 }
344
Victor Stinnerb1147e42018-07-21 02:06:16 +0200345 _PyPathConfig_Clear(&path_config);
346 return _Py_INIT_OK();
347
348no_memory:
349 err = _Py_INIT_NO_MEMORY();
350
351error:
352 _PyPathConfig_Clear(&path_config);
353 return err;
354}
355
356
Victor Stinner1dc6e392018-07-25 02:49:17 +0200357_PyInitError
358_PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
359{
360 /* Do we need to calculate the path? */
361 if ((config->nmodule_search_path < 0)
362 || (config->executable == NULL)
363 || (config->prefix == NULL)
364#ifdef MS_WINDOWS
365 || (config->dll_path == NULL)
366#endif
367 || (config->exec_prefix == NULL))
368 {
369 _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
370 if (_Py_INIT_FAILED(err)) {
371 return err;
372 }
373 }
374
375 if (config->base_prefix == NULL) {
376 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
377 return _Py_INIT_NO_MEMORY();
378 }
379 }
380
381 if (config->base_exec_prefix == NULL) {
382 if (copy_wstr(&config->base_exec_prefix, config->exec_prefix) < 0) {
383 return _Py_INIT_NO_MEMORY();
384 }
385 }
386 return _Py_INIT_OK();
387}
388
389
Victor Stinner31a83932017-12-04 13:39:15 +0100390static void
391pathconfig_global_init(void)
392{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200393 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100394 /* Already initialized */
395 return;
396 }
397
398 _PyInitError err;
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100399 _PyCoreConfig config = _PyCoreConfig_INIT;
Victor Stinner31a83932017-12-04 13:39:15 +0100400
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200401 err = _PyCoreConfig_Read(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100402 if (_Py_INIT_FAILED(err)) {
403 goto error;
404 }
405
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200406 err = _PyCoreConfig_SetPathConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100407 if (_Py_INIT_FAILED(err)) {
408 goto error;
409 }
410
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100411 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100412 return;
413
414error:
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100415 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100416 _Py_FatalInitError(err);
417}
418
419
420/* External interface */
421
422void
423Py_SetPath(const wchar_t *path)
424{
425 if (path == NULL) {
426 _PyPathConfig_Clear(&_Py_path_config);
427 return;
428 }
429
430 PyMemAllocatorEx old_alloc;
431 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
432
433 _PyPathConfig new_config;
434 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200435 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100436 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200437 alloc_error |= (new_config.prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100438#ifdef MS_WINDOWS
439 new_config.dll_path = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200440 alloc_error |= (new_config.dll_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100441#else
442 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200443 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100444#endif
445 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200446 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100447
448 /* steal the home and program_name values (to leave them unchanged) */
449 new_config.home = _Py_path_config.home;
450 _Py_path_config.home = NULL;
451 new_config.program_name = _Py_path_config.program_name;
452 _Py_path_config.program_name = NULL;
453
454 _PyPathConfig_Clear(&_Py_path_config);
455 _Py_path_config = new_config;
456
457 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200458
459 if (alloc_error) {
460 Py_FatalError("Py_SetPath() failed: out of memory");
461 }
Victor Stinner31a83932017-12-04 13:39:15 +0100462}
463
464
465void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200466Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100467{
468 if (home == NULL) {
469 return;
470 }
471
472 PyMemAllocatorEx old_alloc;
473 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
474
475 PyMem_RawFree(_Py_path_config.home);
476 _Py_path_config.home = _PyMem_RawWcsdup(home);
477
478 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
479
480 if (_Py_path_config.home == NULL) {
481 Py_FatalError("Py_SetPythonHome() failed: out of memory");
482 }
483}
484
485
486void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200487Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100488{
489 if (program_name == NULL || program_name[0] == L'\0') {
490 return;
491 }
492
493 PyMemAllocatorEx old_alloc;
494 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
495
496 PyMem_RawFree(_Py_path_config.program_name);
497 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
498
499 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
500
501 if (_Py_path_config.program_name == NULL) {
502 Py_FatalError("Py_SetProgramName() failed: out of memory");
503 }
504}
505
506
507wchar_t *
508Py_GetPath(void)
509{
510 pathconfig_global_init();
511 return _Py_path_config.module_search_path;
512}
513
514
515wchar_t *
516Py_GetPrefix(void)
517{
518 pathconfig_global_init();
519 return _Py_path_config.prefix;
520}
521
522
523wchar_t *
524Py_GetExecPrefix(void)
525{
526#ifdef MS_WINDOWS
527 return Py_GetPrefix();
528#else
529 pathconfig_global_init();
530 return _Py_path_config.exec_prefix;
531#endif
532}
533
534
535wchar_t *
536Py_GetProgramFullPath(void)
537{
538 pathconfig_global_init();
539 return _Py_path_config.program_full_path;
540}
541
542
543wchar_t*
544Py_GetPythonHome(void)
545{
546 pathconfig_global_init();
547 return _Py_path_config.home;
548}
549
550
551wchar_t *
552Py_GetProgramName(void)
553{
554 pathconfig_global_init();
555 return _Py_path_config.program_name;
556}
557
Victor Stinner11a247d2017-12-13 21:05:57 +0100558/* Compute argv[0] which will be prepended to sys.argv */
559PyObject*
560_PyPathConfig_ComputeArgv0(int argc, wchar_t **argv)
561{
562 wchar_t *argv0;
563 wchar_t *p = NULL;
564 Py_ssize_t n = 0;
Nick Coghland5d9e022018-03-25 23:03:10 +1000565 int have_script_arg = 0;
566 int have_module_arg = 0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100567#ifdef HAVE_READLINK
568 wchar_t link[MAXPATHLEN+1];
569 wchar_t argv0copy[2*MAXPATHLEN+1];
570 int nr = 0;
571#endif
572#if defined(HAVE_REALPATH)
573 wchar_t fullpath[MAXPATHLEN];
574#elif defined(MS_WINDOWS)
575 wchar_t fullpath[MAX_PATH];
576#endif
577
Victor Stinner11a247d2017-12-13 21:05:57 +0100578 argv0 = argv[0];
Nick Coghland5d9e022018-03-25 23:03:10 +1000579 if (argc > 0 && argv0 != NULL) {
580 have_module_arg = (wcscmp(argv0, L"-m") == 0);
581 have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
582 }
583
584 if (have_module_arg) {
585 #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
586 _Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath));
587 argv0 = fullpath;
588 n = wcslen(argv0);
589 #else
590 argv0 = L".";
591 n = 1;
592 #endif
593 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100594
595#ifdef HAVE_READLINK
Nick Coghland5d9e022018-03-25 23:03:10 +1000596 if (have_script_arg)
Victor Stinner11a247d2017-12-13 21:05:57 +0100597 nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
598 if (nr > 0) {
599 /* It's a symlink */
600 link[nr] = '\0';
601 if (link[0] == SEP)
602 argv0 = link; /* Link to absolute path */
603 else if (wcschr(link, SEP) == NULL)
604 ; /* Link without path */
605 else {
606 /* Must join(dirname(argv0), link) */
607 wchar_t *q = wcsrchr(argv0, SEP);
608 if (q == NULL)
609 argv0 = link; /* argv0 without path */
610 else {
611 /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
612 wcsncpy(argv0copy, argv0, MAXPATHLEN);
613 q = wcsrchr(argv0copy, SEP);
614 wcsncpy(q+1, link, MAXPATHLEN);
615 q[MAXPATHLEN + 1] = L'\0';
616 argv0 = argv0copy;
617 }
618 }
619 }
620#endif /* HAVE_READLINK */
621
622#if SEP == '\\'
623 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000624 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100625 wchar_t *q;
626#if defined(MS_WINDOWS)
627 /* Replace the first element in argv with the full path. */
628 wchar_t *ptemp;
629 if (GetFullPathNameW(argv0,
630 Py_ARRAY_LENGTH(fullpath),
631 fullpath,
632 &ptemp)) {
633 argv0 = fullpath;
634 }
635#endif
636 p = wcsrchr(argv0, SEP);
637 /* Test for alternate separator */
638 q = wcsrchr(p ? p : argv0, '/');
639 if (q != NULL)
640 p = q;
641 if (p != NULL) {
642 n = p + 1 - argv0;
643 if (n > 1 && p[-1] != ':')
644 n--; /* Drop trailing separator */
645 }
646 }
647#else /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000648 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100649#if defined(HAVE_REALPATH)
650 if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
651 argv0 = fullpath;
652 }
653#endif
654 p = wcsrchr(argv0, SEP);
655 }
656 if (p != NULL) {
657 n = p + 1 - argv0;
658#if SEP == '/' /* Special case for Unix filename syntax */
659 if (n > 1)
660 n--; /* Drop trailing separator */
661#endif /* Unix */
662 }
663#endif /* All others */
664
665 return PyUnicode_FromWideChar(argv0, n);
666}
667
Victor Stinner9bee3292017-12-21 16:49:13 +0100668
669/* Search for a prefix value in an environment file (pyvenv.cfg).
670 If found, copy it into the provided buffer. */
671int
672_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
673 wchar_t *value, size_t value_size)
674{
675 int result = 0; /* meaning not found */
676 char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */
677
678 fseek(env_file, 0, SEEK_SET);
679 while (!feof(env_file)) {
680 char * p = fgets(buffer, MAXPATHLEN*2, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100681
682 if (p == NULL) {
683 break;
684 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100685
686 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100687 if (p[n - 1] != '\n') {
688 /* line has overflowed - bail */
689 break;
690 }
691 if (p[0] == '#') {
692 /* Comment - skip */
693 continue;
694 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100695
696 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100697 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100698 wchar_t * state;
699 wchar_t * tok = wcstok(tmpbuffer, L" \t\r\n", &state);
700 if ((tok != NULL) && !wcscmp(tok, key)) {
701 tok = wcstok(NULL, L" \t", &state);
702 if ((tok != NULL) && !wcscmp(tok, L"=")) {
703 tok = wcstok(NULL, L"\r\n", &state);
704 if (tok != NULL) {
705 wcsncpy(value, tok, MAXPATHLEN);
706 result = 1;
707 PyMem_RawFree(tmpbuffer);
708 break;
709 }
710 }
711 }
712 PyMem_RawFree(tmpbuffer);
713 }
714 }
715 return result;
716}
717
Victor Stinner31a83932017-12-04 13:39:15 +0100718#ifdef __cplusplus
719}
720#endif