blob: 4e0830f4cf9afb6b703f6cf1b76e728e5028068e [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"
5#include "internal/pystate.h"
Nick Coghland5d9e022018-03-25 23:03:10 +10006#include <wchar.h>
Victor Stinner31a83932017-12-04 13:39:15 +01007
8#ifdef __cplusplus
9extern "C" {
10#endif
11
12
13_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
14
15
Victor Stinnerb1147e42018-07-21 02:06:16 +020016static int
17copy_wstr(wchar_t **dst, const wchar_t *src)
18{
19 if (src != NULL) {
20 *dst = _PyMem_RawWcsdup(src);
21 if (*dst == NULL) {
22 return -1;
23 }
24 }
25 else {
26 *dst = NULL;
27 }
28 return 0;
29}
30
31
32static void
Victor Stinner31a83932017-12-04 13:39:15 +010033_PyPathConfig_Clear(_PyPathConfig *config)
34{
35 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
36 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
37 called before Py_Initialize() which can changes the memory allocator. */
38 PyMemAllocatorEx old_alloc;
39 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
40
41#define CLEAR(ATTR) \
42 do { \
43 PyMem_RawFree(ATTR); \
44 ATTR = NULL; \
45 } while (0)
46
47 CLEAR(config->prefix);
48 CLEAR(config->program_full_path);
49#ifdef MS_WINDOWS
50 CLEAR(config->dll_path);
51#else
52 CLEAR(config->exec_prefix);
53#endif
54 CLEAR(config->module_search_path);
55 CLEAR(config->home);
56 CLEAR(config->program_name);
57#undef CLEAR
58
59 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
60}
61
62
Victor Stinnerb1147e42018-07-21 02:06:16 +020063/* Calculate the path configuration: initialize path_config from core_config */
64static _PyInitError
65_PyPathConfig_Calculate(_PyPathConfig *path_config,
66 const _PyCoreConfig *core_config)
Victor Stinner31a83932017-12-04 13:39:15 +010067{
Victor Stinner31a83932017-12-04 13:39:15 +010068 _PyInitError err;
69 _PyPathConfig new_config = _PyPathConfig_INIT;
70
71 PyMemAllocatorEx old_alloc;
72 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
73
74 /* Calculate program_full_path, prefix, exec_prefix (Unix)
75 or dll_path (Windows), and module_search_path */
Victor Stinnerb1147e42018-07-21 02:06:16 +020076 err = _PyPathConfig_Calculate_impl(&new_config, core_config);
Victor Stinner31a83932017-12-04 13:39:15 +010077 if (_Py_INIT_FAILED(err)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +020078 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010079 }
80
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +010081 /* Copy home and program_name from core_config */
Victor Stinnerb1147e42018-07-21 02:06:16 +020082 if (copy_wstr(&new_config.home, core_config->home) < 0) {
83 err = _Py_INIT_NO_MEMORY();
84 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010085 }
Victor Stinnerb1147e42018-07-21 02:06:16 +020086 if (copy_wstr(&new_config.program_name, core_config->program_name) < 0) {
87 err = _Py_INIT_NO_MEMORY();
88 goto err;
Victor Stinner31a83932017-12-04 13:39:15 +010089 }
90
Victor Stinnerb1147e42018-07-21 02:06:16 +020091 _PyPathConfig_Clear(path_config);
92 *path_config = new_config;
93
94 err = _Py_INIT_OK();
95 goto done;
96
97err:
98 _PyPathConfig_Clear(&new_config);
99
100done:
101 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
102 return err;
103}
104
105
106_PyInitError
107_PyPathConfig_SetGlobal(const _PyPathConfig *config)
108{
109 _PyInitError err;
110 _PyPathConfig new_config = _PyPathConfig_INIT;
111
112 PyMemAllocatorEx old_alloc;
113 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
114
115#define COPY_ATTR(ATTR) \
116 do { \
117 if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \
118 _PyPathConfig_Clear(&new_config); \
119 err = _Py_INIT_NO_MEMORY(); \
120 goto done; \
121 } \
122 } while (0)
123
124 COPY_ATTR(program_full_path);
125 COPY_ATTR(prefix);
126#ifdef MS_WINDOWS
127 COPY_ATTR(dll_path);
128#else
129 COPY_ATTR(exec_prefix);
130#endif
131 COPY_ATTR(module_search_path);
132 COPY_ATTR(program_name);
133 COPY_ATTR(home);
Victor Stinner31a83932017-12-04 13:39:15 +0100134
135 _PyPathConfig_Clear(&_Py_path_config);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200136 /* Steal new_config strings; don't clear new_config */
Victor Stinner31a83932017-12-04 13:39:15 +0100137 _Py_path_config = new_config;
138
139 err = _Py_INIT_OK();
140
141done:
142 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
143 return err;
144}
145
146
Victor Stinnerb1147e42018-07-21 02:06:16 +0200147void
148_PyPathConfig_ClearGlobal(void)
149{
150 _PyPathConfig_Clear(&_Py_path_config);
151}
152
153
154static wchar_t*
155wstrlist_join(wchar_t sep, int count, wchar_t **list)
156{
157 size_t len = 1; /* NUL terminator */
158 for (int i=0; i < count; i++) {
159 if (i != 0) {
160 len++;
161 }
162 len += wcslen(list[i]);
163 }
164
165 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
166 if (text == NULL) {
167 return NULL;
168 }
169 wchar_t *str = text;
170 for (int i=0; i < count; i++) {
171 wchar_t *path = list[i];
172 if (i != 0) {
173 *str++ = SEP;
174 }
175 len = wcslen(path);
176 memcpy(str, path, len * sizeof(wchar_t));
177 str += len;
178 }
179 *str = L'\0';
180
181 return text;
182}
183
184
185/* Set the global path configuration from core_config. */
186_PyInitError
187_PyCoreConfig_SetPathConfig(const _PyCoreConfig *core_config)
188{
189 PyMemAllocatorEx old_alloc;
190 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
191
192 _PyInitError err;
193 _PyPathConfig path_config = _PyPathConfig_INIT;
194
195 path_config.module_search_path = wstrlist_join(DELIM,
196 core_config->nmodule_search_path,
197 core_config->module_search_paths);
198 if (path_config.module_search_path == NULL) {
199 goto no_memory;
200 }
201
202 if (copy_wstr(&path_config.program_full_path, core_config->executable) < 0) {
203 goto no_memory;
204 }
205 if (copy_wstr(&path_config.prefix, core_config->prefix) < 0) {
206 goto no_memory;
207 }
208#ifdef MS_WINDOWS
209 if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
210 goto no_memory;
211 }
212#else
213 if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
214 goto no_memory;
215 }
216#endif
217 if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) {
218 goto no_memory;
219 }
220 if (copy_wstr(&path_config.home, core_config->home) < 0) {
221 goto no_memory;
222 }
223
224 err = _PyPathConfig_SetGlobal(&path_config);
225 if (_Py_INIT_FAILED(err)) {
226 goto done;
227 }
228
229 err = _Py_INIT_OK();
230 goto done;
231
232no_memory:
233 err = _Py_INIT_NO_MEMORY();
234
235done:
236 _PyPathConfig_Clear(&path_config);
237 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
238 return err;
239}
240
241
242static _PyInitError
243core_config_init_module_search_paths(_PyCoreConfig *config,
244 _PyPathConfig *path_config)
245{
246 assert(config->module_search_paths == NULL);
247 assert(config->nmodule_search_path < 0);
248
249 config->nmodule_search_path = 0;
250
251 const wchar_t *sys_path = path_config->module_search_path;
252 const wchar_t delim = DELIM;
253 const wchar_t *p = sys_path;
254 while (1) {
255 p = wcschr(sys_path, delim);
256 if (p == NULL) {
257 p = sys_path + wcslen(sys_path); /* End of string */
258 }
259
260 size_t path_len = (p - sys_path);
261 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
262 if (path == NULL) {
263 return _Py_INIT_NO_MEMORY();
264 }
265 memcpy(path, sys_path, path_len * sizeof(wchar_t));
266 path[path_len] = L'\0';
267
268 _PyInitError err = _Py_wstrlist_append(&config->nmodule_search_path,
269 &config->module_search_paths,
270 path);
271 PyMem_RawFree(path);
272 if (_Py_INIT_FAILED(err)) {
273 return err;
274 }
275
276 if (*p == '\0') {
277 break;
278 }
279 sys_path = p + 1;
280 }
281 return _Py_INIT_OK();
282}
283
284
Victor Stinner1dc6e392018-07-25 02:49:17 +0200285static _PyInitError
286_PyCoreConfig_CalculatePathConfig(_PyCoreConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200287{
288 _PyPathConfig path_config = _PyPathConfig_INIT;
289 _PyInitError err;
290
291 err = _PyPathConfig_Calculate(&path_config, config);
292 if (_Py_INIT_FAILED(err)) {
293 goto error;
294 }
295
296 if (config->nmodule_search_path < 0) {
297 err = core_config_init_module_search_paths(config, &path_config);
298 if (_Py_INIT_FAILED(err)) {
299 goto error;
300 }
301 }
302
303 if (config->executable == NULL) {
304 if (copy_wstr(&config->executable,
305 path_config.program_full_path) < 0) {
306 goto no_memory;
307 }
308 }
309
310 if (config->prefix == NULL) {
311 if (copy_wstr(&config->prefix, path_config.prefix) < 0) {
312 goto no_memory;
313 }
314 }
315
316 if (config->exec_prefix == NULL) {
317#ifdef MS_WINDOWS
318 wchar_t *exec_prefix = path_config.prefix;
319#else
320 wchar_t *exec_prefix = path_config.exec_prefix;
321#endif
322 if (copy_wstr(&config->exec_prefix, exec_prefix) < 0) {
323 goto no_memory;
324 }
325 }
326
327#ifdef MS_WINDOWS
328 if (config->dll_path == NULL) {
329 if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
330 goto no_memory;
331 }
332 }
333#endif
334
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200335 if (path_config.isolated != -1) {
336 config->isolated = path_config.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200337 }
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200338 if (path_config.site_import != -1) {
339 config->site_import = path_config.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200340 }
341
Victor Stinnerb1147e42018-07-21 02:06:16 +0200342 _PyPathConfig_Clear(&path_config);
343 return _Py_INIT_OK();
344
345no_memory:
346 err = _Py_INIT_NO_MEMORY();
347
348error:
349 _PyPathConfig_Clear(&path_config);
350 return err;
351}
352
353
Victor Stinner1dc6e392018-07-25 02:49:17 +0200354_PyInitError
355_PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
356{
357 /* Do we need to calculate the path? */
358 if ((config->nmodule_search_path < 0)
359 || (config->executable == NULL)
360 || (config->prefix == NULL)
361#ifdef MS_WINDOWS
362 || (config->dll_path == NULL)
363#endif
364 || (config->exec_prefix == NULL))
365 {
366 _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
367 if (_Py_INIT_FAILED(err)) {
368 return err;
369 }
370 }
371
372 if (config->base_prefix == NULL) {
373 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
374 return _Py_INIT_NO_MEMORY();
375 }
376 }
377
378 if (config->base_exec_prefix == NULL) {
379 if (copy_wstr(&config->base_exec_prefix, config->exec_prefix) < 0) {
380 return _Py_INIT_NO_MEMORY();
381 }
382 }
383 return _Py_INIT_OK();
384}
385
386
Victor Stinner31a83932017-12-04 13:39:15 +0100387static void
388pathconfig_global_init(void)
389{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200390 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100391 /* Already initialized */
392 return;
393 }
394
395 _PyInitError err;
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100396 _PyCoreConfig config = _PyCoreConfig_INIT;
Victor Stinner31a83932017-12-04 13:39:15 +0100397
Victor Stinnerd19d8d52018-07-24 13:55:48 +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 Stinner31a83932017-12-04 13:39:15 +0100413 _Py_FatalInitError(err);
414}
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);
Victor Stinner31a83932017-12-04 13:39:15 +0100435#ifdef MS_WINDOWS
436 new_config.dll_path = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200437 alloc_error |= (new_config.dll_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100438#else
439 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200440 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100441#endif
442 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200443 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100444
445 /* steal the home and program_name values (to leave them unchanged) */
446 new_config.home = _Py_path_config.home;
447 _Py_path_config.home = NULL;
448 new_config.program_name = _Py_path_config.program_name;
449 _Py_path_config.program_name = NULL;
450
451 _PyPathConfig_Clear(&_Py_path_config);
452 _Py_path_config = new_config;
453
454 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200455
456 if (alloc_error) {
457 Py_FatalError("Py_SetPath() failed: out of memory");
458 }
Victor Stinner31a83932017-12-04 13:39:15 +0100459}
460
461
462void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200463Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100464{
465 if (home == NULL) {
466 return;
467 }
468
469 PyMemAllocatorEx old_alloc;
470 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
471
472 PyMem_RawFree(_Py_path_config.home);
473 _Py_path_config.home = _PyMem_RawWcsdup(home);
474
475 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
476
477 if (_Py_path_config.home == NULL) {
478 Py_FatalError("Py_SetPythonHome() failed: out of memory");
479 }
480}
481
482
483void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200484Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100485{
486 if (program_name == NULL || program_name[0] == L'\0') {
487 return;
488 }
489
490 PyMemAllocatorEx old_alloc;
491 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
492
493 PyMem_RawFree(_Py_path_config.program_name);
494 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
495
496 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
497
498 if (_Py_path_config.program_name == NULL) {
499 Py_FatalError("Py_SetProgramName() failed: out of memory");
500 }
501}
502
503
504wchar_t *
505Py_GetPath(void)
506{
507 pathconfig_global_init();
508 return _Py_path_config.module_search_path;
509}
510
511
512wchar_t *
513Py_GetPrefix(void)
514{
515 pathconfig_global_init();
516 return _Py_path_config.prefix;
517}
518
519
520wchar_t *
521Py_GetExecPrefix(void)
522{
523#ifdef MS_WINDOWS
524 return Py_GetPrefix();
525#else
526 pathconfig_global_init();
527 return _Py_path_config.exec_prefix;
528#endif
529}
530
531
532wchar_t *
533Py_GetProgramFullPath(void)
534{
535 pathconfig_global_init();
536 return _Py_path_config.program_full_path;
537}
538
539
540wchar_t*
541Py_GetPythonHome(void)
542{
543 pathconfig_global_init();
544 return _Py_path_config.home;
545}
546
547
548wchar_t *
549Py_GetProgramName(void)
550{
551 pathconfig_global_init();
552 return _Py_path_config.program_name;
553}
554
Victor Stinner11a247d2017-12-13 21:05:57 +0100555/* Compute argv[0] which will be prepended to sys.argv */
556PyObject*
557_PyPathConfig_ComputeArgv0(int argc, wchar_t **argv)
558{
559 wchar_t *argv0;
560 wchar_t *p = NULL;
561 Py_ssize_t n = 0;
Nick Coghland5d9e022018-03-25 23:03:10 +1000562 int have_script_arg = 0;
563 int have_module_arg = 0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100564#ifdef HAVE_READLINK
565 wchar_t link[MAXPATHLEN+1];
566 wchar_t argv0copy[2*MAXPATHLEN+1];
567 int nr = 0;
568#endif
569#if defined(HAVE_REALPATH)
570 wchar_t fullpath[MAXPATHLEN];
571#elif defined(MS_WINDOWS)
572 wchar_t fullpath[MAX_PATH];
573#endif
574
Victor Stinner11a247d2017-12-13 21:05:57 +0100575 argv0 = argv[0];
Nick Coghland5d9e022018-03-25 23:03:10 +1000576 if (argc > 0 && argv0 != NULL) {
577 have_module_arg = (wcscmp(argv0, L"-m") == 0);
578 have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
579 }
580
581 if (have_module_arg) {
582 #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
583 _Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath));
584 argv0 = fullpath;
585 n = wcslen(argv0);
586 #else
587 argv0 = L".";
588 n = 1;
589 #endif
590 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100591
592#ifdef HAVE_READLINK
Nick Coghland5d9e022018-03-25 23:03:10 +1000593 if (have_script_arg)
Victor Stinner11a247d2017-12-13 21:05:57 +0100594 nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
595 if (nr > 0) {
596 /* It's a symlink */
597 link[nr] = '\0';
598 if (link[0] == SEP)
599 argv0 = link; /* Link to absolute path */
600 else if (wcschr(link, SEP) == NULL)
601 ; /* Link without path */
602 else {
603 /* Must join(dirname(argv0), link) */
604 wchar_t *q = wcsrchr(argv0, SEP);
605 if (q == NULL)
606 argv0 = link; /* argv0 without path */
607 else {
608 /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
609 wcsncpy(argv0copy, argv0, MAXPATHLEN);
610 q = wcsrchr(argv0copy, SEP);
611 wcsncpy(q+1, link, MAXPATHLEN);
612 q[MAXPATHLEN + 1] = L'\0';
613 argv0 = argv0copy;
614 }
615 }
616 }
617#endif /* HAVE_READLINK */
618
619#if SEP == '\\'
620 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000621 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100622 wchar_t *q;
623#if defined(MS_WINDOWS)
624 /* Replace the first element in argv with the full path. */
625 wchar_t *ptemp;
626 if (GetFullPathNameW(argv0,
627 Py_ARRAY_LENGTH(fullpath),
628 fullpath,
629 &ptemp)) {
630 argv0 = fullpath;
631 }
632#endif
633 p = wcsrchr(argv0, SEP);
634 /* Test for alternate separator */
635 q = wcsrchr(p ? p : argv0, '/');
636 if (q != NULL)
637 p = q;
638 if (p != NULL) {
639 n = p + 1 - argv0;
640 if (n > 1 && p[-1] != ':')
641 n--; /* Drop trailing separator */
642 }
643 }
644#else /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000645 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100646#if defined(HAVE_REALPATH)
647 if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
648 argv0 = fullpath;
649 }
650#endif
651 p = wcsrchr(argv0, SEP);
652 }
653 if (p != NULL) {
654 n = p + 1 - argv0;
655#if SEP == '/' /* Special case for Unix filename syntax */
656 if (n > 1)
657 n--; /* Drop trailing separator */
658#endif /* Unix */
659 }
660#endif /* All others */
661
662 return PyUnicode_FromWideChar(argv0, n);
663}
664
Victor Stinner9bee3292017-12-21 16:49:13 +0100665
666/* Search for a prefix value in an environment file (pyvenv.cfg).
667 If found, copy it into the provided buffer. */
668int
669_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
670 wchar_t *value, size_t value_size)
671{
672 int result = 0; /* meaning not found */
673 char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */
674
675 fseek(env_file, 0, SEEK_SET);
676 while (!feof(env_file)) {
677 char * p = fgets(buffer, MAXPATHLEN*2, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100678
679 if (p == NULL) {
680 break;
681 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100682
683 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100684 if (p[n - 1] != '\n') {
685 /* line has overflowed - bail */
686 break;
687 }
688 if (p[0] == '#') {
689 /* Comment - skip */
690 continue;
691 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100692
693 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100694 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100695 wchar_t * state;
696 wchar_t * tok = wcstok(tmpbuffer, L" \t\r\n", &state);
697 if ((tok != NULL) && !wcscmp(tok, key)) {
698 tok = wcstok(NULL, L" \t", &state);
699 if ((tok != NULL) && !wcscmp(tok, L"=")) {
700 tok = wcstok(NULL, L"\r\n", &state);
701 if (tok != NULL) {
702 wcsncpy(value, tok, MAXPATHLEN);
703 result = 1;
704 PyMem_RawFree(tmpbuffer);
705 break;
706 }
707 }
708 }
709 PyMem_RawFree(tmpbuffer);
710 }
711 }
712 return result;
713}
714
Victor Stinner31a83932017-12-04 13:39:15 +0100715#ifdef __cplusplus
716}
717#endif