blob: 14dbba78af12e3c9601f0a89dfd01de0aa168456 [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 Stinnerf684d832019-03-01 03:44:13 +01005#include "pycore_coreconfig.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 Stinner621cebe2018-11-12 16:53:38 +01008#include "pycore_pymem.h"
9#include "pycore_pystate.h"
Nick Coghland5d9e022018-03-25 23:03:10 +100010#include <wchar.h>
Victor Stinner31a83932017-12-04 13:39:15 +010011
12#ifdef __cplusplus
13extern "C" {
14#endif
15
16
17_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
18
19
Victor Stinnerb1147e42018-07-21 02:06:16 +020020static int
21copy_wstr(wchar_t **dst, const wchar_t *src)
22{
23 if (src != NULL) {
24 *dst = _PyMem_RawWcsdup(src);
25 if (*dst == NULL) {
26 return -1;
27 }
28 }
29 else {
30 *dst = NULL;
31 }
32 return 0;
33}
34
35
36static void
Victor Stinner31a83932017-12-04 13:39:15 +010037_PyPathConfig_Clear(_PyPathConfig *config)
38{
39 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
40 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
41 called before Py_Initialize() which can changes the memory allocator. */
42 PyMemAllocatorEx old_alloc;
43 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
44
45#define CLEAR(ATTR) \
46 do { \
47 PyMem_RawFree(ATTR); \
48 ATTR = NULL; \
49 } while (0)
50
51 CLEAR(config->prefix);
52 CLEAR(config->program_full_path);
Steve Dower177a41a2018-11-17 20:41:48 -080053 CLEAR(config->exec_prefix);
Victor Stinner31a83932017-12-04 13:39:15 +010054#ifdef MS_WINDOWS
55 CLEAR(config->dll_path);
Victor Stinner31a83932017-12-04 13:39:15 +010056#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
Steve Dower177a41a2018-11-17 20:41:48 -080077 /* Calculate program_full_path, prefix, exec_prefix,
78 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);
Steve Dower177a41a2018-11-17 20:41:48 -0800129 COPY_ATTR(exec_prefix);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200130#ifdef MS_WINDOWS
131 COPY_ATTR(dll_path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200132#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 }
Steve Dower177a41a2018-11-17 20:41:48 -0800210 if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200211 goto no_memory;
212 }
Steve Dower177a41a2018-11-17 20:41:48 -0800213#ifdef MS_WINDOWS
214 if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200215 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) {
Steve Dower177a41a2018-11-17 20:41:48 -0800318 if (copy_wstr(&config->exec_prefix,
319 path_config.exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200320 goto no_memory;
321 }
322 }
323
324#ifdef MS_WINDOWS
325 if (config->dll_path == NULL) {
326 if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
327 goto no_memory;
328 }
329 }
330#endif
331
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200332 if (path_config.isolated != -1) {
Victor Stinnercad1f742019-03-05 02:01:27 +0100333 config->preconfig.isolated = path_config.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200334 }
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200335 if (path_config.site_import != -1) {
336 config->site_import = path_config.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200337 }
338
Victor Stinnerb1147e42018-07-21 02:06:16 +0200339 _PyPathConfig_Clear(&path_config);
340 return _Py_INIT_OK();
341
342no_memory:
343 err = _Py_INIT_NO_MEMORY();
344
345error:
346 _PyPathConfig_Clear(&path_config);
347 return err;
348}
349
350
Victor Stinner1dc6e392018-07-25 02:49:17 +0200351_PyInitError
352_PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
353{
354 /* Do we need to calculate the path? */
355 if ((config->nmodule_search_path < 0)
356 || (config->executable == NULL)
357 || (config->prefix == NULL)
358#ifdef MS_WINDOWS
359 || (config->dll_path == NULL)
360#endif
361 || (config->exec_prefix == NULL))
362 {
363 _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
364 if (_Py_INIT_FAILED(err)) {
365 return err;
366 }
367 }
368
369 if (config->base_prefix == NULL) {
370 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
371 return _Py_INIT_NO_MEMORY();
372 }
373 }
374
375 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800376 if (copy_wstr(&config->base_exec_prefix,
377 config->exec_prefix) < 0) {
Victor Stinner1dc6e392018-07-25 02:49:17 +0200378 return _Py_INIT_NO_MEMORY();
379 }
380 }
381 return _Py_INIT_OK();
382}
383
384
Victor Stinner31a83932017-12-04 13:39:15 +0100385static void
386pathconfig_global_init(void)
387{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200388 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100389 /* Already initialized */
390 return;
391 }
392
393 _PyInitError err;
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100394 _PyCoreConfig config = _PyCoreConfig_INIT;
Victor Stinner31a83932017-12-04 13:39:15 +0100395
Victor Stinner6dcb5422019-03-05 02:44:12 +0100396 err = _PyCoreConfig_Read(&config, NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100397 if (_Py_INIT_FAILED(err)) {
398 goto error;
399 }
400
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200401 err = _PyCoreConfig_SetPathConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100402 if (_Py_INIT_FAILED(err)) {
403 goto error;
404 }
405
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100406 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100407 return;
408
409error:
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100410 _PyCoreConfig_Clear(&config);
Victor Stinnerdfe88472019-03-01 12:14:41 +0100411 _Py_ExitInitError(err);
Victor Stinner31a83932017-12-04 13:39:15 +0100412}
413
414
415/* External interface */
416
417void
418Py_SetPath(const wchar_t *path)
419{
420 if (path == NULL) {
421 _PyPathConfig_Clear(&_Py_path_config);
422 return;
423 }
424
425 PyMemAllocatorEx old_alloc;
426 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
427
428 _PyPathConfig new_config;
429 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200430 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100431 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200432 alloc_error |= (new_config.prefix == NULL);
Steve Dower177a41a2018-11-17 20:41:48 -0800433 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
434 alloc_error |= (new_config.exec_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#endif
439 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200440 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100441
442 /* steal the home and program_name values (to leave them unchanged) */
443 new_config.home = _Py_path_config.home;
444 _Py_path_config.home = NULL;
445 new_config.program_name = _Py_path_config.program_name;
446 _Py_path_config.program_name = NULL;
447
448 _PyPathConfig_Clear(&_Py_path_config);
449 _Py_path_config = new_config;
450
451 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200452
453 if (alloc_error) {
454 Py_FatalError("Py_SetPath() failed: out of memory");
455 }
Victor Stinner31a83932017-12-04 13:39:15 +0100456}
457
458
459void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200460Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100461{
462 if (home == NULL) {
463 return;
464 }
465
466 PyMemAllocatorEx old_alloc;
467 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
468
469 PyMem_RawFree(_Py_path_config.home);
470 _Py_path_config.home = _PyMem_RawWcsdup(home);
471
472 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
473
474 if (_Py_path_config.home == NULL) {
475 Py_FatalError("Py_SetPythonHome() failed: out of memory");
476 }
477}
478
479
480void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200481Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100482{
483 if (program_name == NULL || program_name[0] == L'\0') {
484 return;
485 }
486
487 PyMemAllocatorEx old_alloc;
488 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
489
490 PyMem_RawFree(_Py_path_config.program_name);
491 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
492
493 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
494
495 if (_Py_path_config.program_name == NULL) {
496 Py_FatalError("Py_SetProgramName() failed: out of memory");
497 }
498}
499
Steve Dower177a41a2018-11-17 20:41:48 -0800500void
501_Py_SetProgramFullPath(const wchar_t *program_full_path)
502{
503 if (program_full_path == NULL || program_full_path[0] == L'\0') {
504 return;
505 }
506
507 PyMemAllocatorEx old_alloc;
508 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
509
510 PyMem_RawFree(_Py_path_config.program_full_path);
511 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
512
513 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
514
515 if (_Py_path_config.program_full_path == NULL) {
516 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
517 }
518}
519
Victor Stinner31a83932017-12-04 13:39:15 +0100520
521wchar_t *
522Py_GetPath(void)
523{
524 pathconfig_global_init();
525 return _Py_path_config.module_search_path;
526}
527
528
529wchar_t *
530Py_GetPrefix(void)
531{
532 pathconfig_global_init();
533 return _Py_path_config.prefix;
534}
535
536
537wchar_t *
538Py_GetExecPrefix(void)
539{
Victor Stinner31a83932017-12-04 13:39:15 +0100540 pathconfig_global_init();
541 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100542}
543
544
545wchar_t *
546Py_GetProgramFullPath(void)
547{
548 pathconfig_global_init();
549 return _Py_path_config.program_full_path;
550}
551
552
553wchar_t*
554Py_GetPythonHome(void)
555{
556 pathconfig_global_init();
557 return _Py_path_config.home;
558}
559
560
561wchar_t *
562Py_GetProgramName(void)
563{
564 pathconfig_global_init();
565 return _Py_path_config.program_name;
566}
567
Victor Stinner11a247d2017-12-13 21:05:57 +0100568/* Compute argv[0] which will be prepended to sys.argv */
569PyObject*
570_PyPathConfig_ComputeArgv0(int argc, wchar_t **argv)
571{
572 wchar_t *argv0;
573 wchar_t *p = NULL;
574 Py_ssize_t n = 0;
Nick Coghland5d9e022018-03-25 23:03:10 +1000575 int have_script_arg = 0;
576 int have_module_arg = 0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100577#ifdef HAVE_READLINK
578 wchar_t link[MAXPATHLEN+1];
579 wchar_t argv0copy[2*MAXPATHLEN+1];
580 int nr = 0;
581#endif
582#if defined(HAVE_REALPATH)
583 wchar_t fullpath[MAXPATHLEN];
584#elif defined(MS_WINDOWS)
585 wchar_t fullpath[MAX_PATH];
586#endif
587
Victor Stinner11a247d2017-12-13 21:05:57 +0100588 argv0 = argv[0];
Nick Coghland5d9e022018-03-25 23:03:10 +1000589 if (argc > 0 && argv0 != NULL) {
590 have_module_arg = (wcscmp(argv0, L"-m") == 0);
591 have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
592 }
593
594 if (have_module_arg) {
595 #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
596 _Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath));
597 argv0 = fullpath;
598 n = wcslen(argv0);
599 #else
600 argv0 = L".";
601 n = 1;
602 #endif
603 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100604
605#ifdef HAVE_READLINK
Nick Coghland5d9e022018-03-25 23:03:10 +1000606 if (have_script_arg)
Victor Stinner11a247d2017-12-13 21:05:57 +0100607 nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
608 if (nr > 0) {
609 /* It's a symlink */
610 link[nr] = '\0';
611 if (link[0] == SEP)
612 argv0 = link; /* Link to absolute path */
613 else if (wcschr(link, SEP) == NULL)
614 ; /* Link without path */
615 else {
616 /* Must join(dirname(argv0), link) */
617 wchar_t *q = wcsrchr(argv0, SEP);
618 if (q == NULL)
619 argv0 = link; /* argv0 without path */
620 else {
621 /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
622 wcsncpy(argv0copy, argv0, MAXPATHLEN);
623 q = wcsrchr(argv0copy, SEP);
624 wcsncpy(q+1, link, MAXPATHLEN);
625 q[MAXPATHLEN + 1] = L'\0';
626 argv0 = argv0copy;
627 }
628 }
629 }
630#endif /* HAVE_READLINK */
631
632#if SEP == '\\'
633 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000634 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100635 wchar_t *q;
636#if defined(MS_WINDOWS)
637 /* Replace the first element in argv with the full path. */
638 wchar_t *ptemp;
639 if (GetFullPathNameW(argv0,
640 Py_ARRAY_LENGTH(fullpath),
641 fullpath,
642 &ptemp)) {
643 argv0 = fullpath;
644 }
645#endif
646 p = wcsrchr(argv0, SEP);
647 /* Test for alternate separator */
648 q = wcsrchr(p ? p : argv0, '/');
649 if (q != NULL)
650 p = q;
651 if (p != NULL) {
652 n = p + 1 - argv0;
653 if (n > 1 && p[-1] != ':')
654 n--; /* Drop trailing separator */
655 }
656 }
657#else /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000658 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100659#if defined(HAVE_REALPATH)
660 if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
661 argv0 = fullpath;
662 }
663#endif
664 p = wcsrchr(argv0, SEP);
665 }
666 if (p != NULL) {
667 n = p + 1 - argv0;
668#if SEP == '/' /* Special case for Unix filename syntax */
669 if (n > 1)
670 n--; /* Drop trailing separator */
671#endif /* Unix */
672 }
673#endif /* All others */
674
675 return PyUnicode_FromWideChar(argv0, n);
676}
677
Victor Stinner9bee3292017-12-21 16:49:13 +0100678
Minmin Gong8ebc6452019-02-02 20:26:55 -0800679#ifdef MS_WINDOWS
680#define WCSTOK wcstok_s
681#else
682#define WCSTOK wcstok
683#endif
684
Victor Stinner9bee3292017-12-21 16:49:13 +0100685/* Search for a prefix value in an environment file (pyvenv.cfg).
686 If found, copy it into the provided buffer. */
687int
688_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
689 wchar_t *value, size_t value_size)
690{
691 int result = 0; /* meaning not found */
692 char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */
693
694 fseek(env_file, 0, SEEK_SET);
695 while (!feof(env_file)) {
696 char * p = fgets(buffer, MAXPATHLEN*2, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100697
698 if (p == NULL) {
699 break;
700 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100701
702 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100703 if (p[n - 1] != '\n') {
704 /* line has overflowed - bail */
705 break;
706 }
707 if (p[0] == '#') {
708 /* Comment - skip */
709 continue;
710 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100711
712 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100713 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100714 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800715 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100716 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800717 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100718 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800719 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100720 if (tok != NULL) {
721 wcsncpy(value, tok, MAXPATHLEN);
722 result = 1;
723 PyMem_RawFree(tmpbuffer);
724 break;
725 }
726 }
727 }
728 PyMem_RawFree(tmpbuffer);
729 }
730 }
731 return result;
732}
733
Victor Stinner31a83932017-12-04 13:39:15 +0100734#ifdef __cplusplus
735}
736#endif