blob: fb2d19e2797a7d2ba1b5ed97fbd6ffa92c3d74a3 [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*
Victor Stinner74f65682019-03-15 15:08:05 +0100157_PyWstrList_Join(const _PyWstrList *list, wchar_t sep)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200158{
159 size_t len = 1; /* NUL terminator */
Victor Stinner74f65682019-03-15 15:08:05 +0100160 for (Py_ssize_t i=0; i < list->length; i++) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200161 if (i != 0) {
162 len++;
163 }
Victor Stinner74f65682019-03-15 15:08:05 +0100164 len += wcslen(list->items[i]);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200165 }
166
167 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
168 if (text == NULL) {
169 return NULL;
170 }
171 wchar_t *str = text;
Victor Stinner74f65682019-03-15 15:08:05 +0100172 for (Py_ssize_t i=0; i < list->length; i++) {
173 wchar_t *path = list->items[i];
Victor Stinnerb1147e42018-07-21 02:06:16 +0200174 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
Victor Stinner74f65682019-03-15 15:08:05 +0100197 path_config.module_search_path = _PyWstrList_Join(&core_config->module_search_paths, DELIM);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200198 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 }
Steve Dower177a41a2018-11-17 20:41:48 -0800208 if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200209 goto no_memory;
210 }
Steve Dower177a41a2018-11-17 20:41:48 -0800211#ifdef MS_WINDOWS
212 if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200213 goto no_memory;
214 }
215#endif
216 if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) {
217 goto no_memory;
218 }
219 if (copy_wstr(&path_config.home, core_config->home) < 0) {
220 goto no_memory;
221 }
222
223 err = _PyPathConfig_SetGlobal(&path_config);
224 if (_Py_INIT_FAILED(err)) {
225 goto done;
226 }
227
228 err = _Py_INIT_OK();
229 goto done;
230
231no_memory:
232 err = _Py_INIT_NO_MEMORY();
233
234done:
235 _PyPathConfig_Clear(&path_config);
236 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
237 return err;
238}
239
240
241static _PyInitError
242core_config_init_module_search_paths(_PyCoreConfig *config,
243 _PyPathConfig *path_config)
244{
Victor Stinner74f65682019-03-15 15:08:05 +0100245 assert(!config->use_module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200246
Victor Stinner74f65682019-03-15 15:08:05 +0100247 _PyWstrList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200248
249 const wchar_t *sys_path = path_config->module_search_path;
250 const wchar_t delim = DELIM;
251 const wchar_t *p = sys_path;
252 while (1) {
253 p = wcschr(sys_path, delim);
254 if (p == NULL) {
255 p = sys_path + wcslen(sys_path); /* End of string */
256 }
257
258 size_t path_len = (p - sys_path);
259 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
260 if (path == NULL) {
261 return _Py_INIT_NO_MEMORY();
262 }
263 memcpy(path, sys_path, path_len * sizeof(wchar_t));
264 path[path_len] = L'\0';
265
Victor Stinner74f65682019-03-15 15:08:05 +0100266 int res = _PyWstrList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200267 PyMem_RawFree(path);
Victor Stinner74f65682019-03-15 15:08:05 +0100268 if (res < 0) {
269 return _Py_INIT_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200270 }
271
272 if (*p == '\0') {
273 break;
274 }
275 sys_path = p + 1;
276 }
Victor Stinner74f65682019-03-15 15:08:05 +0100277 config->use_module_search_paths = 1;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200278 return _Py_INIT_OK();
279}
280
281
Victor Stinner1dc6e392018-07-25 02:49:17 +0200282static _PyInitError
283_PyCoreConfig_CalculatePathConfig(_PyCoreConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200284{
285 _PyPathConfig path_config = _PyPathConfig_INIT;
286 _PyInitError err;
287
288 err = _PyPathConfig_Calculate(&path_config, config);
289 if (_Py_INIT_FAILED(err)) {
290 goto error;
291 }
292
Victor Stinner74f65682019-03-15 15:08:05 +0100293 if (!config->use_module_search_paths) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200294 err = core_config_init_module_search_paths(config, &path_config);
295 if (_Py_INIT_FAILED(err)) {
296 goto error;
297 }
298 }
299
300 if (config->executable == NULL) {
301 if (copy_wstr(&config->executable,
302 path_config.program_full_path) < 0) {
303 goto no_memory;
304 }
305 }
306
307 if (config->prefix == NULL) {
308 if (copy_wstr(&config->prefix, path_config.prefix) < 0) {
309 goto no_memory;
310 }
311 }
312
313 if (config->exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800314 if (copy_wstr(&config->exec_prefix,
315 path_config.exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200316 goto no_memory;
317 }
318 }
319
320#ifdef MS_WINDOWS
321 if (config->dll_path == NULL) {
322 if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
323 goto no_memory;
324 }
325 }
326#endif
327
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200328 if (path_config.isolated != -1) {
Victor Stinnercad1f742019-03-05 02:01:27 +0100329 config->preconfig.isolated = path_config.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200330 }
Victor Stinnerd19d8d52018-07-24 13:55:48 +0200331 if (path_config.site_import != -1) {
332 config->site_import = path_config.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200333 }
334
Victor Stinnerb1147e42018-07-21 02:06:16 +0200335 _PyPathConfig_Clear(&path_config);
336 return _Py_INIT_OK();
337
338no_memory:
339 err = _Py_INIT_NO_MEMORY();
340
341error:
342 _PyPathConfig_Clear(&path_config);
343 return err;
344}
345
346
Victor Stinner1dc6e392018-07-25 02:49:17 +0200347_PyInitError
348_PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
349{
350 /* Do we need to calculate the path? */
Victor Stinner74f65682019-03-15 15:08:05 +0100351 if (!config->use_module_search_paths
Victor Stinner1dc6e392018-07-25 02:49:17 +0200352 || (config->executable == NULL)
353 || (config->prefix == NULL)
354#ifdef MS_WINDOWS
355 || (config->dll_path == NULL)
356#endif
357 || (config->exec_prefix == NULL))
358 {
359 _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
360 if (_Py_INIT_FAILED(err)) {
361 return err;
362 }
363 }
364
365 if (config->base_prefix == NULL) {
366 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
367 return _Py_INIT_NO_MEMORY();
368 }
369 }
370
371 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800372 if (copy_wstr(&config->base_exec_prefix,
373 config->exec_prefix) < 0) {
Victor Stinner1dc6e392018-07-25 02:49:17 +0200374 return _Py_INIT_NO_MEMORY();
375 }
376 }
377 return _Py_INIT_OK();
378}
379
380
Victor Stinner31a83932017-12-04 13:39:15 +0100381static void
382pathconfig_global_init(void)
383{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200384 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100385 /* Already initialized */
386 return;
387 }
388
389 _PyInitError err;
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100390 _PyCoreConfig config = _PyCoreConfig_INIT;
Victor Stinner31a83932017-12-04 13:39:15 +0100391
Victor Stinner6dcb5422019-03-05 02:44:12 +0100392 err = _PyCoreConfig_Read(&config, NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100393 if (_Py_INIT_FAILED(err)) {
394 goto error;
395 }
396
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200397 err = _PyCoreConfig_SetPathConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100398 if (_Py_INIT_FAILED(err)) {
399 goto error;
400 }
401
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100402 _PyCoreConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100403 return;
404
405error:
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100406 _PyCoreConfig_Clear(&config);
Victor Stinnerdfe88472019-03-01 12:14:41 +0100407 _Py_ExitInitError(err);
Victor Stinner31a83932017-12-04 13:39:15 +0100408}
409
410
411/* External interface */
412
413void
414Py_SetPath(const wchar_t *path)
415{
416 if (path == NULL) {
417 _PyPathConfig_Clear(&_Py_path_config);
418 return;
419 }
420
421 PyMemAllocatorEx old_alloc;
422 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
423
424 _PyPathConfig new_config;
425 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200426 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100427 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200428 alloc_error |= (new_config.prefix == NULL);
Steve Dower177a41a2018-11-17 20:41:48 -0800429 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
430 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100431#ifdef MS_WINDOWS
432 new_config.dll_path = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200433 alloc_error |= (new_config.dll_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100434#endif
435 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200436 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100437
438 /* steal the home and program_name values (to leave them unchanged) */
439 new_config.home = _Py_path_config.home;
440 _Py_path_config.home = NULL;
441 new_config.program_name = _Py_path_config.program_name;
442 _Py_path_config.program_name = NULL;
443
444 _PyPathConfig_Clear(&_Py_path_config);
445 _Py_path_config = new_config;
446
447 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200448
449 if (alloc_error) {
450 Py_FatalError("Py_SetPath() failed: out of memory");
451 }
Victor Stinner31a83932017-12-04 13:39:15 +0100452}
453
454
455void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200456Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100457{
458 if (home == NULL) {
459 return;
460 }
461
462 PyMemAllocatorEx old_alloc;
463 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
464
465 PyMem_RawFree(_Py_path_config.home);
466 _Py_path_config.home = _PyMem_RawWcsdup(home);
467
468 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
469
470 if (_Py_path_config.home == NULL) {
471 Py_FatalError("Py_SetPythonHome() failed: out of memory");
472 }
473}
474
475
476void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200477Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100478{
479 if (program_name == NULL || program_name[0] == L'\0') {
480 return;
481 }
482
483 PyMemAllocatorEx old_alloc;
484 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
485
486 PyMem_RawFree(_Py_path_config.program_name);
487 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
488
489 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
490
491 if (_Py_path_config.program_name == NULL) {
492 Py_FatalError("Py_SetProgramName() failed: out of memory");
493 }
494}
495
Steve Dower177a41a2018-11-17 20:41:48 -0800496void
497_Py_SetProgramFullPath(const wchar_t *program_full_path)
498{
499 if (program_full_path == NULL || program_full_path[0] == L'\0') {
500 return;
501 }
502
503 PyMemAllocatorEx old_alloc;
504 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
505
506 PyMem_RawFree(_Py_path_config.program_full_path);
507 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
508
509 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
510
511 if (_Py_path_config.program_full_path == NULL) {
512 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
513 }
514}
515
Victor Stinner31a83932017-12-04 13:39:15 +0100516
517wchar_t *
518Py_GetPath(void)
519{
520 pathconfig_global_init();
521 return _Py_path_config.module_search_path;
522}
523
524
525wchar_t *
526Py_GetPrefix(void)
527{
528 pathconfig_global_init();
529 return _Py_path_config.prefix;
530}
531
532
533wchar_t *
534Py_GetExecPrefix(void)
535{
Victor Stinner31a83932017-12-04 13:39:15 +0100536 pathconfig_global_init();
537 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100538}
539
540
541wchar_t *
542Py_GetProgramFullPath(void)
543{
544 pathconfig_global_init();
545 return _Py_path_config.program_full_path;
546}
547
548
549wchar_t*
550Py_GetPythonHome(void)
551{
552 pathconfig_global_init();
553 return _Py_path_config.home;
554}
555
556
557wchar_t *
558Py_GetProgramName(void)
559{
560 pathconfig_global_init();
561 return _Py_path_config.program_name;
562}
563
Victor Stinner11a247d2017-12-13 21:05:57 +0100564/* Compute argv[0] which will be prepended to sys.argv */
565PyObject*
Victor Stinner74f65682019-03-15 15:08:05 +0100566_PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
Victor Stinner11a247d2017-12-13 21:05:57 +0100567{
Victor Stinner74f65682019-03-15 15:08:05 +0100568 assert(_PyWstrList_CheckConsistency(argv));
569
Victor Stinner11a247d2017-12-13 21:05:57 +0100570 wchar_t *argv0;
571 wchar_t *p = NULL;
572 Py_ssize_t n = 0;
Nick Coghland5d9e022018-03-25 23:03:10 +1000573 int have_script_arg = 0;
574 int have_module_arg = 0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100575#ifdef HAVE_READLINK
576 wchar_t link[MAXPATHLEN+1];
577 wchar_t argv0copy[2*MAXPATHLEN+1];
578 int nr = 0;
579#endif
580#if defined(HAVE_REALPATH)
581 wchar_t fullpath[MAXPATHLEN];
582#elif defined(MS_WINDOWS)
583 wchar_t fullpath[MAX_PATH];
584#endif
585
Victor Stinner74f65682019-03-15 15:08:05 +0100586 if (argv->length > 0) {
587 argv0 = argv->items[0];
Nick Coghland5d9e022018-03-25 23:03:10 +1000588 have_module_arg = (wcscmp(argv0, L"-m") == 0);
589 have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
590 }
591
592 if (have_module_arg) {
593 #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
594 _Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath));
595 argv0 = fullpath;
596 n = wcslen(argv0);
597 #else
598 argv0 = L".";
599 n = 1;
600 #endif
601 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100602
603#ifdef HAVE_READLINK
Nick Coghland5d9e022018-03-25 23:03:10 +1000604 if (have_script_arg)
Victor Stinner11a247d2017-12-13 21:05:57 +0100605 nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
606 if (nr > 0) {
607 /* It's a symlink */
608 link[nr] = '\0';
609 if (link[0] == SEP)
610 argv0 = link; /* Link to absolute path */
611 else if (wcschr(link, SEP) == NULL)
612 ; /* Link without path */
613 else {
614 /* Must join(dirname(argv0), link) */
615 wchar_t *q = wcsrchr(argv0, SEP);
616 if (q == NULL)
617 argv0 = link; /* argv0 without path */
618 else {
619 /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
620 wcsncpy(argv0copy, argv0, MAXPATHLEN);
621 q = wcsrchr(argv0copy, SEP);
622 wcsncpy(q+1, link, MAXPATHLEN);
623 q[MAXPATHLEN + 1] = L'\0';
624 argv0 = argv0copy;
625 }
626 }
627 }
628#endif /* HAVE_READLINK */
629
630#if SEP == '\\'
631 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000632 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100633 wchar_t *q;
634#if defined(MS_WINDOWS)
635 /* Replace the first element in argv with the full path. */
636 wchar_t *ptemp;
637 if (GetFullPathNameW(argv0,
638 Py_ARRAY_LENGTH(fullpath),
639 fullpath,
640 &ptemp)) {
641 argv0 = fullpath;
642 }
643#endif
644 p = wcsrchr(argv0, SEP);
645 /* Test for alternate separator */
646 q = wcsrchr(p ? p : argv0, '/');
647 if (q != NULL)
648 p = q;
649 if (p != NULL) {
650 n = p + 1 - argv0;
651 if (n > 1 && p[-1] != ':')
652 n--; /* Drop trailing separator */
653 }
654 }
655#else /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000656 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100657#if defined(HAVE_REALPATH)
658 if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
659 argv0 = fullpath;
660 }
661#endif
662 p = wcsrchr(argv0, SEP);
663 }
664 if (p != NULL) {
665 n = p + 1 - argv0;
666#if SEP == '/' /* Special case for Unix filename syntax */
667 if (n > 1)
668 n--; /* Drop trailing separator */
669#endif /* Unix */
670 }
671#endif /* All others */
672
673 return PyUnicode_FromWideChar(argv0, n);
674}
675
Victor Stinner9bee3292017-12-21 16:49:13 +0100676
Minmin Gong8ebc6452019-02-02 20:26:55 -0800677#ifdef MS_WINDOWS
678#define WCSTOK wcstok_s
679#else
680#define WCSTOK wcstok
681#endif
682
Victor Stinner9bee3292017-12-21 16:49:13 +0100683/* Search for a prefix value in an environment file (pyvenv.cfg).
684 If found, copy it into the provided buffer. */
685int
686_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
687 wchar_t *value, size_t value_size)
688{
689 int result = 0; /* meaning not found */
690 char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */
691
692 fseek(env_file, 0, SEEK_SET);
693 while (!feof(env_file)) {
694 char * p = fgets(buffer, MAXPATHLEN*2, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100695
696 if (p == NULL) {
697 break;
698 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100699
700 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100701 if (p[n - 1] != '\n') {
702 /* line has overflowed - bail */
703 break;
704 }
705 if (p[0] == '#') {
706 /* Comment - skip */
707 continue;
708 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100709
710 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100711 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100712 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800713 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100714 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800715 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100716 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800717 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100718 if (tok != NULL) {
719 wcsncpy(value, tok, MAXPATHLEN);
720 result = 1;
721 PyMem_RawFree(tmpbuffer);
722 break;
723 }
724 }
725 }
726 PyMem_RawFree(tmpbuffer);
727 }
728 }
729 return result;
730}
731
Victor Stinner31a83932017-12-04 13:39:15 +0100732#ifdef __cplusplus
733}
734#endif