blob: 342a9448f795a734f9e8555d9fce6c993c58e441 [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 Stinner9fc57a32018-11-07 00:44:03 +01005#include "pycore_fileutils.h"
Victor Stinnera1c249c2018-11-01 03:15:58 +01006#include "pycore_pathconfig.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01007#include "pycore_pymem.h"
8#include "pycore_pystate.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);
Steve Dower177a41a2018-11-17 20:41:48 -080052 CLEAR(config->exec_prefix);
Victor Stinner31a83932017-12-04 13:39:15 +010053#ifdef MS_WINDOWS
54 CLEAR(config->dll_path);
Victor Stinner31a83932017-12-04 13:39:15 +010055#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
Steve Dower177a41a2018-11-17 20:41:48 -080076 /* Calculate program_full_path, prefix, exec_prefix,
77 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);
Steve Dower177a41a2018-11-17 20:41:48 -0800128 COPY_ATTR(exec_prefix);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200129#ifdef MS_WINDOWS
130 COPY_ATTR(dll_path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200131#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 }
Steve Dower177a41a2018-11-17 20:41:48 -0800209 if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200210 goto no_memory;
211 }
Steve Dower177a41a2018-11-17 20:41:48 -0800212#ifdef MS_WINDOWS
213 if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200214 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) {
Steve Dower177a41a2018-11-17 20:41:48 -0800317 if (copy_wstr(&config->exec_prefix,
318 path_config.exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200319 goto no_memory;
320 }
321 }
322
323#ifdef MS_WINDOWS
324 if (config->dll_path == NULL) {
325 if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
326 goto no_memory;
327 }
328 }
329#endif
330
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200331 if (path_config.isolated != -1) {
332 config->isolated = path_config.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200333 }
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200334 if (path_config.site_import != -1) {
335 config->site_import = path_config.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200336 }
337
Victor Stinnerb1147e42018-07-21 02:06:16 +0200338 _PyPathConfig_Clear(&path_config);
339 return _Py_INIT_OK();
340
341no_memory:
342 err = _Py_INIT_NO_MEMORY();
343
344error:
345 _PyPathConfig_Clear(&path_config);
346 return err;
347}
348
349
Victor Stinner1dc6e392018-07-25 02:49:17 +0200350_PyInitError
351_PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
352{
353 /* Do we need to calculate the path? */
354 if ((config->nmodule_search_path < 0)
355 || (config->executable == NULL)
356 || (config->prefix == NULL)
357#ifdef MS_WINDOWS
358 || (config->dll_path == NULL)
359#endif
360 || (config->exec_prefix == NULL))
361 {
362 _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
363 if (_Py_INIT_FAILED(err)) {
364 return err;
365 }
366 }
367
368 if (config->base_prefix == NULL) {
369 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
370 return _Py_INIT_NO_MEMORY();
371 }
372 }
373
374 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800375 if (copy_wstr(&config->base_exec_prefix,
376 config->exec_prefix) < 0) {
Victor Stinner1dc6e392018-07-25 02:49:17 +0200377 return _Py_INIT_NO_MEMORY();
378 }
379 }
380 return _Py_INIT_OK();
381}
382
383
Victor Stinner31a83932017-12-04 13:39:15 +0100384static void
385pathconfig_global_init(void)
386{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200387 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100388 /* Already initialized */
389 return;
390 }
391
392 _PyInitError err;
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100393 _PyCoreConfig config = _PyCoreConfig_INIT;
Victor Stinner31a83932017-12-04 13:39:15 +0100394
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200395 err = _PyCoreConfig_Read(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100396 if (_Py_INIT_FAILED(err)) {
397 goto error;
398 }
399
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200400 err = _PyCoreConfig_SetPathConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100401 if (_Py_INIT_FAILED(err)) {
402 goto error;
403 }
404
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100405 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100406 return;
407
408error:
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100409 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100410 _Py_FatalInitError(err);
411}
412
413
414/* External interface */
415
416void
417Py_SetPath(const wchar_t *path)
418{
419 if (path == NULL) {
420 _PyPathConfig_Clear(&_Py_path_config);
421 return;
422 }
423
424 PyMemAllocatorEx old_alloc;
425 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
426
427 _PyPathConfig new_config;
428 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200429 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100430 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200431 alloc_error |= (new_config.prefix == NULL);
Steve Dower177a41a2018-11-17 20:41:48 -0800432 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
433 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100434#ifdef MS_WINDOWS
435 new_config.dll_path = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200436 alloc_error |= (new_config.dll_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100437#endif
438 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200439 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100440
441 /* steal the home and program_name values (to leave them unchanged) */
442 new_config.home = _Py_path_config.home;
443 _Py_path_config.home = NULL;
444 new_config.program_name = _Py_path_config.program_name;
445 _Py_path_config.program_name = NULL;
446
447 _PyPathConfig_Clear(&_Py_path_config);
448 _Py_path_config = new_config;
449
450 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200451
452 if (alloc_error) {
453 Py_FatalError("Py_SetPath() failed: out of memory");
454 }
Victor Stinner31a83932017-12-04 13:39:15 +0100455}
456
457
458void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200459Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100460{
461 if (home == NULL) {
462 return;
463 }
464
465 PyMemAllocatorEx old_alloc;
466 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
467
468 PyMem_RawFree(_Py_path_config.home);
469 _Py_path_config.home = _PyMem_RawWcsdup(home);
470
471 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
472
473 if (_Py_path_config.home == NULL) {
474 Py_FatalError("Py_SetPythonHome() failed: out of memory");
475 }
476}
477
478
479void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200480Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100481{
482 if (program_name == NULL || program_name[0] == L'\0') {
483 return;
484 }
485
486 PyMemAllocatorEx old_alloc;
487 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
488
489 PyMem_RawFree(_Py_path_config.program_name);
490 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
491
492 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
493
494 if (_Py_path_config.program_name == NULL) {
495 Py_FatalError("Py_SetProgramName() failed: out of memory");
496 }
497}
498
Steve Dower177a41a2018-11-17 20:41:48 -0800499void
500_Py_SetProgramFullPath(const wchar_t *program_full_path)
501{
502 if (program_full_path == NULL || program_full_path[0] == L'\0') {
503 return;
504 }
505
506 PyMemAllocatorEx old_alloc;
507 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
508
509 PyMem_RawFree(_Py_path_config.program_full_path);
510 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
511
512 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
513
514 if (_Py_path_config.program_full_path == NULL) {
515 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
516 }
517}
518
Victor Stinner31a83932017-12-04 13:39:15 +0100519
520wchar_t *
521Py_GetPath(void)
522{
523 pathconfig_global_init();
524 return _Py_path_config.module_search_path;
525}
526
527
528wchar_t *
529Py_GetPrefix(void)
530{
531 pathconfig_global_init();
532 return _Py_path_config.prefix;
533}
534
535
536wchar_t *
537Py_GetExecPrefix(void)
538{
Victor Stinner31a83932017-12-04 13:39:15 +0100539 pathconfig_global_init();
540 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100541}
542
543
544wchar_t *
545Py_GetProgramFullPath(void)
546{
547 pathconfig_global_init();
548 return _Py_path_config.program_full_path;
549}
550
551
552wchar_t*
553Py_GetPythonHome(void)
554{
555 pathconfig_global_init();
556 return _Py_path_config.home;
557}
558
559
560wchar_t *
561Py_GetProgramName(void)
562{
563 pathconfig_global_init();
564 return _Py_path_config.program_name;
565}
566
Victor Stinner11a247d2017-12-13 21:05:57 +0100567/* Compute argv[0] which will be prepended to sys.argv */
568PyObject*
569_PyPathConfig_ComputeArgv0(int argc, wchar_t **argv)
570{
571 wchar_t *argv0;
572 wchar_t *p = NULL;
573 Py_ssize_t n = 0;
Nick Coghland5d9e022018-03-25 23:03:10 +1000574 int have_script_arg = 0;
575 int have_module_arg = 0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100576#ifdef HAVE_READLINK
577 wchar_t link[MAXPATHLEN+1];
578 wchar_t argv0copy[2*MAXPATHLEN+1];
579 int nr = 0;
580#endif
581#if defined(HAVE_REALPATH)
582 wchar_t fullpath[MAXPATHLEN];
583#elif defined(MS_WINDOWS)
584 wchar_t fullpath[MAX_PATH];
585#endif
586
Victor Stinner11a247d2017-12-13 21:05:57 +0100587 argv0 = argv[0];
Nick Coghland5d9e022018-03-25 23:03:10 +1000588 if (argc > 0 && argv0 != NULL) {
589 have_module_arg = (wcscmp(argv0, L"-m") == 0);
590 have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
591 }
592
593 if (have_module_arg) {
594 #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
595 _Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath));
596 argv0 = fullpath;
597 n = wcslen(argv0);
598 #else
599 argv0 = L".";
600 n = 1;
601 #endif
602 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100603
604#ifdef HAVE_READLINK
Nick Coghland5d9e022018-03-25 23:03:10 +1000605 if (have_script_arg)
Victor Stinner11a247d2017-12-13 21:05:57 +0100606 nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
607 if (nr > 0) {
608 /* It's a symlink */
609 link[nr] = '\0';
610 if (link[0] == SEP)
611 argv0 = link; /* Link to absolute path */
612 else if (wcschr(link, SEP) == NULL)
613 ; /* Link without path */
614 else {
615 /* Must join(dirname(argv0), link) */
616 wchar_t *q = wcsrchr(argv0, SEP);
617 if (q == NULL)
618 argv0 = link; /* argv0 without path */
619 else {
620 /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
621 wcsncpy(argv0copy, argv0, MAXPATHLEN);
622 q = wcsrchr(argv0copy, SEP);
623 wcsncpy(q+1, link, MAXPATHLEN);
624 q[MAXPATHLEN + 1] = L'\0';
625 argv0 = argv0copy;
626 }
627 }
628 }
629#endif /* HAVE_READLINK */
630
631#if SEP == '\\'
632 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000633 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100634 wchar_t *q;
635#if defined(MS_WINDOWS)
636 /* Replace the first element in argv with the full path. */
637 wchar_t *ptemp;
638 if (GetFullPathNameW(argv0,
639 Py_ARRAY_LENGTH(fullpath),
640 fullpath,
641 &ptemp)) {
642 argv0 = fullpath;
643 }
644#endif
645 p = wcsrchr(argv0, SEP);
646 /* Test for alternate separator */
647 q = wcsrchr(p ? p : argv0, '/');
648 if (q != NULL)
649 p = q;
650 if (p != NULL) {
651 n = p + 1 - argv0;
652 if (n > 1 && p[-1] != ':')
653 n--; /* Drop trailing separator */
654 }
655 }
656#else /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000657 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100658#if defined(HAVE_REALPATH)
659 if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
660 argv0 = fullpath;
661 }
662#endif
663 p = wcsrchr(argv0, SEP);
664 }
665 if (p != NULL) {
666 n = p + 1 - argv0;
667#if SEP == '/' /* Special case for Unix filename syntax */
668 if (n > 1)
669 n--; /* Drop trailing separator */
670#endif /* Unix */
671 }
672#endif /* All others */
673
674 return PyUnicode_FromWideChar(argv0, n);
675}
676
Victor Stinner9bee3292017-12-21 16:49:13 +0100677
678/* Search for a prefix value in an environment file (pyvenv.cfg).
679 If found, copy it into the provided buffer. */
680int
681_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
682 wchar_t *value, size_t value_size)
683{
684 int result = 0; /* meaning not found */
685 char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */
686
687 fseek(env_file, 0, SEEK_SET);
688 while (!feof(env_file)) {
689 char * p = fgets(buffer, MAXPATHLEN*2, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100690
691 if (p == NULL) {
692 break;
693 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100694
695 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100696 if (p[n - 1] != '\n') {
697 /* line has overflowed - bail */
698 break;
699 }
700 if (p[0] == '#') {
701 /* Comment - skip */
702 continue;
703 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100704
705 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100706 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100707 wchar_t * state;
708 wchar_t * tok = wcstok(tmpbuffer, L" \t\r\n", &state);
709 if ((tok != NULL) && !wcscmp(tok, key)) {
710 tok = wcstok(NULL, L" \t", &state);
711 if ((tok != NULL) && !wcscmp(tok, L"=")) {
712 tok = wcstok(NULL, L"\r\n", &state);
713 if (tok != NULL) {
714 wcsncpy(value, tok, MAXPATHLEN);
715 result = 1;
716 PyMem_RawFree(tmpbuffer);
717 break;
718 }
719 }
720 }
721 PyMem_RawFree(tmpbuffer);
722 }
723 }
724 return result;
725}
726
Victor Stinner31a83932017-12-04 13:39:15 +0100727#ifdef __cplusplus
728}
729#endif