blob: 7dabe5f9644747723e4e313e04bd72800d207b33 [file] [log] [blame]
Victor Stinner6c785c02018-08-01 17:56:14 +02001#include "Python.h"
2#include "internal/import.h"
3#include "internal/pystate.h"
4
5
6#define DECODE_LOCALE_ERR(NAME, LEN) \
7 (((LEN) == -2) \
8 ? _Py_INIT_USER_ERR("cannot decode " NAME) \
9 : _Py_INIT_NO_MEMORY())
10
11
12/* Global configuration variables */
13
14/* The default encoding used by the platform file system APIs
15 Can remain NULL for all platforms that don't have such a concept
16
17 Don't forget to modify PyUnicode_DecodeFSDefault() if you touch any of the
18 values for Py_FileSystemDefaultEncoding!
19*/
20#if defined(__APPLE__)
21const char *Py_FileSystemDefaultEncoding = "utf-8";
22int Py_HasFileSystemDefaultEncoding = 1;
23#elif defined(MS_WINDOWS)
24/* may be changed by initfsencoding(), but should never be free()d */
25const char *Py_FileSystemDefaultEncoding = "utf-8";
26int Py_HasFileSystemDefaultEncoding = 1;
27#else
28const char *Py_FileSystemDefaultEncoding = NULL; /* set by initfsencoding() */
29int Py_HasFileSystemDefaultEncoding = 0;
30#endif
31const char *Py_FileSystemDefaultEncodeErrors = "surrogateescape";
32/* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change
33 stdin and stdout error handler to "surrogateescape". It is equal to
34 -1 by default: unknown, will be set by Py_Main() */
35int Py_UTF8Mode = -1;
36int Py_DebugFlag = 0; /* Needed by parser.c */
37int Py_VerboseFlag = 0; /* Needed by import.c */
38int Py_QuietFlag = 0; /* Needed by sysmodule.c */
39int Py_InteractiveFlag = 0; /* Needed by Py_FdIsInteractive() below */
40int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */
41int Py_OptimizeFlag = 0; /* Needed by compile.c */
42int Py_NoSiteFlag = 0; /* Suppress 'import site' */
43int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */
44int Py_FrozenFlag = 0; /* Needed by getpath.c */
45int Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */
46int Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */
47int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
48int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
49int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
50int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
51#ifdef MS_WINDOWS
52int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */
53int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */
54#endif
55const char *_Py_CheckHashBasedPycsMode = "default";
56
57
58void
59_Py_wstrlist_clear(int len, wchar_t **list)
60{
61 for (int i=0; i < len; i++) {
62 PyMem_RawFree(list[i]);
63 }
64 PyMem_RawFree(list);
65}
66
67
68wchar_t**
69_Py_wstrlist_copy(int len, wchar_t **list)
70{
71 assert((len > 0 && list != NULL) || len == 0);
72 size_t size = len * sizeof(list[0]);
73 wchar_t **list_copy = PyMem_RawMalloc(size);
74 for (int i=0; i < len; i++) {
75 wchar_t* arg = _PyMem_RawWcsdup(list[i]);
76 if (arg == NULL) {
77 _Py_wstrlist_clear(i, list);
78 return NULL;
79 }
80 list_copy[i] = arg;
81 }
82 return list_copy;
83}
84
85
86/* Free memory allocated in config, but don't clear all attributes */
87void
88_PyCoreConfig_Clear(_PyCoreConfig *config)
89{
90#define CLEAR(ATTR) \
91 do { \
92 PyMem_RawFree(ATTR); \
93 ATTR = NULL; \
94 } while (0)
95#define CLEAR_WSTRLIST(LEN, LIST) \
96 do { \
97 _Py_wstrlist_clear(LEN, LIST); \
98 LEN = 0; \
99 LIST = NULL; \
100 } while (0)
101
102 CLEAR(config->pycache_prefix);
103 CLEAR(config->module_search_path_env);
104 CLEAR(config->home);
105 CLEAR(config->program_name);
106 CLEAR(config->program);
107
108 CLEAR_WSTRLIST(config->argc, config->argv);
109 config->argc = -1;
110
111 CLEAR_WSTRLIST(config->nwarnoption, config->warnoptions);
112 CLEAR_WSTRLIST(config->nxoption, config->xoptions);
113 CLEAR_WSTRLIST(config->nmodule_search_path, config->module_search_paths);
114 config->nmodule_search_path = -1;
115
116 CLEAR(config->executable);
117 CLEAR(config->prefix);
118 CLEAR(config->base_prefix);
119 CLEAR(config->exec_prefix);
120#ifdef MS_WINDOWS
121 CLEAR(config->dll_path);
122#endif
123 CLEAR(config->base_exec_prefix);
124#undef CLEAR
125#undef CLEAR_WSTRLIST
126}
127
128
129int
130_PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
131{
132 _PyCoreConfig_Clear(config);
133
134#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
135#define COPY_STR_ATTR(ATTR) \
136 do { \
137 if (config2->ATTR != NULL) { \
138 config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \
139 if (config->ATTR == NULL) { \
140 return -1; \
141 } \
142 } \
143 } while (0)
144#define COPY_WSTRLIST(LEN, LIST) \
145 do { \
146 if (config2->LIST != NULL) { \
147 config->LIST = _Py_wstrlist_copy(config2->LEN, config2->LIST); \
148 if (config->LIST == NULL) { \
149 return -1; \
150 } \
151 } \
152 config->LEN = config2->LEN; \
153 } while (0)
154
155 COPY_ATTR(install_signal_handlers);
156 COPY_ATTR(use_environment);
157 COPY_ATTR(use_hash_seed);
158 COPY_ATTR(hash_seed);
159 COPY_ATTR(_install_importlib);
160 COPY_ATTR(allocator);
161 COPY_ATTR(dev_mode);
162 COPY_ATTR(faulthandler);
163 COPY_ATTR(tracemalloc);
164 COPY_ATTR(import_time);
165 COPY_ATTR(show_ref_count);
166 COPY_ATTR(show_alloc_count);
167 COPY_ATTR(dump_refs);
168 COPY_ATTR(malloc_stats);
169
170 COPY_ATTR(coerce_c_locale);
171 COPY_ATTR(coerce_c_locale_warn);
172 COPY_ATTR(utf8_mode);
173
174 COPY_STR_ATTR(pycache_prefix);
175 COPY_STR_ATTR(module_search_path_env);
176 COPY_STR_ATTR(home);
177 COPY_STR_ATTR(program_name);
178 COPY_STR_ATTR(program);
179
180 COPY_WSTRLIST(argc, argv);
181 COPY_WSTRLIST(nwarnoption, warnoptions);
182 COPY_WSTRLIST(nxoption, xoptions);
183 COPY_WSTRLIST(nmodule_search_path, module_search_paths);
184
185 COPY_STR_ATTR(executable);
186 COPY_STR_ATTR(prefix);
187 COPY_STR_ATTR(base_prefix);
188 COPY_STR_ATTR(exec_prefix);
189#ifdef MS_WINDOWS
190 COPY_STR_ATTR(dll_path);
191#endif
192 COPY_STR_ATTR(base_exec_prefix);
193
194 COPY_ATTR(isolated);
195 COPY_ATTR(site_import);
196 COPY_ATTR(bytes_warning);
197 COPY_ATTR(inspect);
198 COPY_ATTR(interactive);
199 COPY_ATTR(optimization_level);
200 COPY_ATTR(parser_debug);
201 COPY_ATTR(write_bytecode);
202 COPY_ATTR(verbose);
203 COPY_ATTR(quiet);
204 COPY_ATTR(user_site_directory);
205 COPY_ATTR(buffered_stdio);
206#ifdef MS_WINDOWS
207 COPY_ATTR(legacy_windows_fs_encoding);
208 COPY_ATTR(legacy_windows_stdio);
209#endif
210 COPY_ATTR(_check_hash_pycs_mode);
211 COPY_ATTR(_frozen);
212
213#undef COPY_ATTR
214#undef COPY_STR_ATTR
215#undef COPY_WSTRLIST
216 return 0;
217}
218
219
220const char*
221_PyCoreConfig_GetEnv(const _PyCoreConfig *config, const char *name)
222{
223 assert(config->use_environment >= 0);
224
225 if (!config->use_environment) {
226 return NULL;
227 }
228
229 const char *var = getenv(name);
230 if (var && var[0] != '\0') {
231 return var;
232 }
233 else {
234 return NULL;
235 }
236}
237
238
239int
240_PyCoreConfig_GetEnvDup(const _PyCoreConfig *config,
241 wchar_t **dest,
242 wchar_t *wname, char *name)
243{
244 assert(config->use_environment >= 0);
245
246 if (!config->use_environment) {
247 *dest = NULL;
248 return 0;
249 }
250
251#ifdef MS_WINDOWS
252 const wchar_t *var = _wgetenv(wname);
253 if (!var || var[0] == '\0') {
254 *dest = NULL;
255 return 0;
256 }
257
258 wchar_t *copy = _PyMem_RawWcsdup(var);
259 if (copy == NULL) {
260 return -1;
261 }
262
263 *dest = copy;
264#else
265 const char *var = getenv(name);
266 if (!var || var[0] == '\0') {
267 *dest = NULL;
268 return 0;
269 }
270
271 size_t len;
272 wchar_t *wvar = Py_DecodeLocale(var, &len);
273 if (!wvar) {
274 if (len == (size_t)-2) {
275 return -2;
276 }
277 else {
278 return -1;
279 }
280 }
281 *dest = wvar;
282#endif
283 return 0;
284}
285
286
287void
288_PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config)
289{
290#define COPY_FLAG(ATTR, VALUE) \
291 if (config->ATTR == -1) { \
292 config->ATTR = VALUE; \
293 }
294#define COPY_NOT_FLAG(ATTR, VALUE) \
295 if (config->ATTR == -1) { \
296 config->ATTR = !(VALUE); \
297 }
298
299 COPY_FLAG(utf8_mode, Py_UTF8Mode);
300 COPY_FLAG(isolated, Py_IsolatedFlag);
301 COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
302 COPY_FLAG(inspect, Py_InspectFlag);
303 COPY_FLAG(interactive, Py_InteractiveFlag);
304 COPY_FLAG(optimization_level, Py_OptimizeFlag);
305 COPY_FLAG(parser_debug, Py_DebugFlag);
306 COPY_FLAG(verbose, Py_VerboseFlag);
307 COPY_FLAG(quiet, Py_QuietFlag);
308#ifdef MS_WINDOWS
309 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
310 COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
311#endif
312 COPY_FLAG(_frozen, Py_FrozenFlag);
313
314 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
315 COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
316 COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
317 COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
318 COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
319
320 if (config->_check_hash_pycs_mode == NULL) {
321 config->_check_hash_pycs_mode = _Py_CheckHashBasedPycsMode;
322 }
323
324#undef COPY_FLAG
325#undef COPY_NOT_FLAG
326}
327
328
329/* Set Py_xxx global configuration variables from 'config' configuration. */
330void
331_PyCoreConfig_SetGlobalConfig(const _PyCoreConfig *config)
332{
333#define COPY_FLAG(ATTR, VAR) \
334 if (config->ATTR != -1) { \
335 VAR = config->ATTR; \
336 }
337#define COPY_NOT_FLAG(ATTR, VAR) \
338 if (config->ATTR != -1) { \
339 VAR = !config->ATTR; \
340 }
341
342 COPY_FLAG(utf8_mode, Py_UTF8Mode);
343 COPY_FLAG(isolated, Py_IsolatedFlag);
344 COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
345 COPY_FLAG(inspect, Py_InspectFlag);
346 COPY_FLAG(interactive, Py_InteractiveFlag);
347 COPY_FLAG(optimization_level, Py_OptimizeFlag);
348 COPY_FLAG(parser_debug, Py_DebugFlag);
349 COPY_FLAG(verbose, Py_VerboseFlag);
350 COPY_FLAG(quiet, Py_QuietFlag);
351#ifdef MS_WINDOWS
352 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
353 COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
354#endif
355
356 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
357 COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
358 COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
359 COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
360 COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
361
362 if (config->_check_hash_pycs_mode != NULL) {
363 _Py_CheckHashBasedPycsMode = config->_check_hash_pycs_mode;
364 }
365
366 /* Random or non-zero hash seed */
367 Py_HashRandomizationFlag = (config->use_hash_seed == 0 ||
368 config->hash_seed != 0);
369
370#undef COPY_FLAG
371#undef COPY_NOT_FLAG
372}
373
374
375/* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__
376 environment variables on macOS if available. */
377static _PyInitError
378config_init_program_name(_PyCoreConfig *config)
379{
380 /* If Py_SetProgramName() was called, use its value */
381 const wchar_t *program_name = _Py_path_config.program_name;
382 if (program_name != NULL) {
383 config->program_name = _PyMem_RawWcsdup(program_name);
384 if (config->program_name == NULL) {
385 return _Py_INIT_NO_MEMORY();
386 }
387 return _Py_INIT_OK();
388 }
389
390#ifdef __APPLE__
391 /* On MacOS X, when the Python interpreter is embedded in an
392 application bundle, it gets executed by a bootstrapping script
393 that does os.execve() with an argv[0] that's different from the
394 actual Python executable. This is needed to keep the Finder happy,
395 or rather, to work around Apple's overly strict requirements of
396 the process name. However, we still need a usable sys.executable,
397 so the actual executable path is passed in an environment variable.
398 See Lib/plat-mac/bundlebuiler.py for details about the bootstrap
399 script. */
400 const char *p = _PyCoreConfig_GetEnv(config, "PYTHONEXECUTABLE");
401 if (p != NULL) {
402 size_t len;
403 wchar_t* program_name = Py_DecodeLocale(p, &len);
404 if (program_name == NULL) {
405 return DECODE_LOCALE_ERR("PYTHONEXECUTABLE environment "
406 "variable", (Py_ssize_t)len);
407 }
408 config->program_name = program_name;
409 return _Py_INIT_OK();
410 }
411#ifdef WITH_NEXT_FRAMEWORK
412 else {
413 const char* pyvenv_launcher = getenv("__PYVENV_LAUNCHER__");
414 if (pyvenv_launcher && *pyvenv_launcher) {
415 /* Used by Mac/Tools/pythonw.c to forward
416 * the argv0 of the stub executable
417 */
418 size_t len;
419 wchar_t* program_name = Py_DecodeLocale(pyvenv_launcher, &len);
420 if (program_name == NULL) {
421 return DECODE_LOCALE_ERR("__PYVENV_LAUNCHER__ environment "
422 "variable", (Py_ssize_t)len);
423 }
424 config->program_name = program_name;
425 return _Py_INIT_OK();
426 }
427 }
428#endif /* WITH_NEXT_FRAMEWORK */
429#endif /* __APPLE__ */
430
431 /* Use argv[0] by default, if available */
432 if (config->program != NULL) {
433 config->program_name = _PyMem_RawWcsdup(config->program);
434 if (config->program_name == NULL) {
435 return _Py_INIT_NO_MEMORY();
436 }
437 return _Py_INIT_OK();
438 }
439
440 /* Last fall back: hardcoded string */
441#ifdef MS_WINDOWS
442 const wchar_t *default_program_name = L"python";
443#else
444 const wchar_t *default_program_name = L"python3";
445#endif
446 config->program_name = _PyMem_RawWcsdup(default_program_name);
447 if (config->program_name == NULL) {
448 return _Py_INIT_NO_MEMORY();
449 }
450 return _Py_INIT_OK();
451}
452
453
454static const wchar_t*
455config_get_xoption(const _PyCoreConfig *config, wchar_t *name)
456{
457 int nxoption = config->nxoption;
458 wchar_t **xoptions = config->xoptions;
459 for (int i=0; i < nxoption; i++) {
460 wchar_t *option = xoptions[i];
461 size_t len;
462 wchar_t *sep = wcschr(option, L'=');
463 if (sep != NULL) {
464 len = (sep - option);
465 }
466 else {
467 len = wcslen(option);
468 }
469 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
470 return option;
471 }
472 }
473 return NULL;
474}
475
476
477static _PyInitError
478config_init_home(_PyCoreConfig *config)
479{
480 wchar_t *home;
481
482 /* If Py_SetPythonHome() was called, use its value */
483 home = _Py_path_config.home;
484 if (home) {
485 config->home = _PyMem_RawWcsdup(home);
486 if (config->home == NULL) {
487 return _Py_INIT_NO_MEMORY();
488 }
489 return _Py_INIT_OK();
490 }
491
492 int res = _PyCoreConfig_GetEnvDup(config, &home,
493 L"PYTHONHOME", "PYTHONHOME");
494 if (res < 0) {
495 return DECODE_LOCALE_ERR("PYTHONHOME", res);
496 }
497 config->home = home;
498 return _Py_INIT_OK();
499}
500
501
502static _PyInitError
503config_init_hash_seed(_PyCoreConfig *config)
504{
505 const char *seed_text = _PyCoreConfig_GetEnv(config, "PYTHONHASHSEED");
506
507 Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc));
508 /* Convert a text seed to a numeric one */
509 if (seed_text && strcmp(seed_text, "random") != 0) {
510 const char *endptr = seed_text;
511 unsigned long seed;
512 errno = 0;
513 seed = strtoul(seed_text, (char **)&endptr, 10);
514 if (*endptr != '\0'
515 || seed > 4294967295UL
516 || (errno == ERANGE && seed == ULONG_MAX))
517 {
518 return _Py_INIT_USER_ERR("PYTHONHASHSEED must be \"random\" "
519 "or an integer in range [0; 4294967295]");
520 }
521 /* Use a specific hash */
522 config->use_hash_seed = 1;
523 config->hash_seed = seed;
524 }
525 else {
526 /* Use a random hash */
527 config->use_hash_seed = 0;
528 config->hash_seed = 0;
529 }
530 return _Py_INIT_OK();
531}
532
533
534static _PyInitError
535config_init_utf8_mode(_PyCoreConfig *config)
536{
537 const wchar_t *xopt = config_get_xoption(config, L"utf8");
538 if (xopt) {
539 wchar_t *sep = wcschr(xopt, L'=');
540 if (sep) {
541 xopt = sep + 1;
542 if (wcscmp(xopt, L"1") == 0) {
543 config->utf8_mode = 1;
544 }
545 else if (wcscmp(xopt, L"0") == 0) {
546 config->utf8_mode = 0;
547 }
548 else {
549 return _Py_INIT_USER_ERR("invalid -X utf8 option value");
550 }
551 }
552 else {
553 config->utf8_mode = 1;
554 }
555 return _Py_INIT_OK();
556 }
557
558 const char *opt = _PyCoreConfig_GetEnv(config, "PYTHONUTF8");
559 if (opt) {
560 if (strcmp(opt, "1") == 0) {
561 config->utf8_mode = 1;
562 }
563 else if (strcmp(opt, "0") == 0) {
564 config->utf8_mode = 0;
565 }
566 else {
567 return _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment "
568 "variable value");
569 }
570 return _Py_INIT_OK();
571 }
572
573 return _Py_INIT_OK();
574}
575
576
577static int
578config_str_to_int(const char *str, int *result)
579{
580 const char *endptr = str;
581 errno = 0;
582 long value = strtol(str, (char **)&endptr, 10);
583 if (*endptr != '\0' || errno == ERANGE) {
584 return -1;
585 }
586 if (value < INT_MIN || value > INT_MAX) {
587 return -1;
588 }
589
590 *result = (int)value;
591 return 0;
592}
593
594
595static int
596config_wstr_to_int(const wchar_t *wstr, int *result)
597{
598 const wchar_t *endptr = wstr;
599 errno = 0;
600 long value = wcstol(wstr, (wchar_t **)&endptr, 10);
601 if (*endptr != '\0' || errno == ERANGE) {
602 return -1;
603 }
604 if (value < INT_MIN || value > INT_MAX) {
605 return -1;
606 }
607
608 *result = (int)value;
609 return 0;
610}
611
612
613static void
614get_env_flag(_PyCoreConfig *config, int *flag, const char *name)
615{
616 const char *var = _PyCoreConfig_GetEnv(config, name);
617 if (!var) {
618 return;
619 }
620 int value;
621 if (config_str_to_int(var, &value) < 0 || value < 0) {
622 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
623 value = 1;
624 }
625 if (*flag < value) {
626 *flag = value;
627 }
628}
629
630
631static _PyInitError
632config_read_env_vars(_PyCoreConfig *config)
633{
634 assert(config->use_environment > 0);
635
636 /* Get environment variables */
637 get_env_flag(config, &config->parser_debug, "PYTHONDEBUG");
638 get_env_flag(config, &config->verbose, "PYTHONVERBOSE");
639 get_env_flag(config, &config->optimization_level, "PYTHONOPTIMIZE");
640 get_env_flag(config, &config->inspect, "PYTHONINSPECT");
641
642 int dont_write_bytecode = 0;
643 get_env_flag(config, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
644 if (dont_write_bytecode) {
645 config->write_bytecode = 0;
646 }
647
648 int no_user_site_directory = 0;
649 get_env_flag(config, &no_user_site_directory, "PYTHONNOUSERSITE");
650 if (no_user_site_directory) {
651 config->user_site_directory = 0;
652 }
653
654 int unbuffered_stdio = 0;
655 get_env_flag(config, &unbuffered_stdio, "PYTHONUNBUFFERED");
656 if (unbuffered_stdio) {
657 config->buffered_stdio = 0;
658 }
659
660#ifdef MS_WINDOWS
661 get_env_flag(config, &config->legacy_windows_fs_encoding,
662 "PYTHONLEGACYWINDOWSFSENCODING");
663 get_env_flag(config, &config->legacy_windows_stdio,
664 "PYTHONLEGACYWINDOWSSTDIO");
665#endif
666
667 if (config->allocator == NULL) {
668 config->allocator = _PyCoreConfig_GetEnv(config, "PYTHONMALLOC");
669 }
670
671 if (_PyCoreConfig_GetEnv(config, "PYTHONDUMPREFS")) {
672 config->dump_refs = 1;
673 }
674 if (_PyCoreConfig_GetEnv(config, "PYTHONMALLOCSTATS")) {
675 config->malloc_stats = 1;
676 }
677
678 const char *env = _PyCoreConfig_GetEnv(config, "PYTHONCOERCECLOCALE");
679 if (env) {
680 if (strcmp(env, "0") == 0) {
681 config->coerce_c_locale = 0;
682 }
683 else if (strcmp(env, "warn") == 0) {
684 config->coerce_c_locale_warn = 1;
685 }
686 else {
687 config->coerce_c_locale = 1;
688 }
689 }
690
691 wchar_t *path;
692 int res = _PyCoreConfig_GetEnvDup(config, &path,
693 L"PYTHONPATH", "PYTHONPATH");
694 if (res < 0) {
695 return DECODE_LOCALE_ERR("PYTHONPATH", res);
696 }
697 config->module_search_path_env = path;
698
699 if (config->use_hash_seed < 0) {
700 _PyInitError err = config_init_hash_seed(config);
701 if (_Py_INIT_FAILED(err)) {
702 return err;
703 }
704 }
705
706 return _Py_INIT_OK();
707}
708
709
710static _PyInitError
711config_init_tracemalloc(_PyCoreConfig *config)
712{
713 int nframe;
714 int valid;
715
716 const char *env = _PyCoreConfig_GetEnv(config, "PYTHONTRACEMALLOC");
717 if (env) {
718 if (!config_str_to_int(env, &nframe)) {
719 valid = (nframe >= 0);
720 }
721 else {
722 valid = 0;
723 }
724 if (!valid) {
725 return _Py_INIT_USER_ERR("PYTHONTRACEMALLOC: invalid number "
726 "of frames");
727 }
728 config->tracemalloc = nframe;
729 }
730
731 const wchar_t *xoption = config_get_xoption(config, L"tracemalloc");
732 if (xoption) {
733 const wchar_t *sep = wcschr(xoption, L'=');
734 if (sep) {
735 if (!config_wstr_to_int(sep + 1, &nframe)) {
736 valid = (nframe >= 0);
737 }
738 else {
739 valid = 0;
740 }
741 if (!valid) {
742 return _Py_INIT_USER_ERR("-X tracemalloc=NFRAME: "
743 "invalid number of frames");
744 }
745 }
746 else {
747 /* -X tracemalloc behaves as -X tracemalloc=1 */
748 nframe = 1;
749 }
750 config->tracemalloc = nframe;
751 }
752 return _Py_INIT_OK();
753}
754
755
756static _PyInitError
757config_init_pycache_prefix(_PyCoreConfig *config)
758{
759 assert(config->pycache_prefix == NULL);
760
761 const wchar_t *xoption = config_get_xoption(config, L"pycache_prefix");
762 if (xoption) {
763 const wchar_t *sep = wcschr(xoption, L'=');
764 if (sep && wcslen(sep) > 1) {
765 config->pycache_prefix = _PyMem_RawWcsdup(sep + 1);
766 if (config->pycache_prefix == NULL) {
767 return _Py_INIT_NO_MEMORY();
768 }
769 }
770 else {
771 // -X pycache_prefix= can cancel the env var
772 config->pycache_prefix = NULL;
773 }
774 }
775 else {
776 wchar_t *env;
777 int res = _PyCoreConfig_GetEnvDup(config, &env,
778 L"PYTHONPYCACHEPREFIX",
779 "PYTHONPYCACHEPREFIX");
780 if (res < 0) {
781 return DECODE_LOCALE_ERR("PYTHONPYCACHEPREFIX", res);
782 }
783
784 if (env) {
785 config->pycache_prefix = env;
786 }
787 }
788 return _Py_INIT_OK();
789}
790
791
792static _PyInitError
793config_read_complex_options(_PyCoreConfig *config)
794{
795 /* More complex options configured by env var and -X option */
796 if (config->faulthandler < 0) {
797 if (_PyCoreConfig_GetEnv(config, "PYTHONFAULTHANDLER")
798 || config_get_xoption(config, L"faulthandler")) {
799 config->faulthandler = 1;
800 }
801 }
802 if (_PyCoreConfig_GetEnv(config, "PYTHONPROFILEIMPORTTIME")
803 || config_get_xoption(config, L"importtime")) {
804 config->import_time = 1;
805 }
806 if (config_get_xoption(config, L"dev" ) ||
807 _PyCoreConfig_GetEnv(config, "PYTHONDEVMODE"))
808 {
809 config->dev_mode = 1;
810 }
811
812 _PyInitError err;
813 if (config->tracemalloc < 0) {
814 err = config_init_tracemalloc(config);
815 if (_Py_INIT_FAILED(err)) {
816 return err;
817 }
818 }
819
820 if (config->pycache_prefix == NULL) {
821 err = config_init_pycache_prefix(config);
822 if (_Py_INIT_FAILED(err)) {
823 return err;
824 }
825 }
826 return _Py_INIT_OK();
827}
828
829
830static void
831config_init_locale(_PyCoreConfig *config)
832{
833 if (config->utf8_mode >= 0 && config->coerce_c_locale >= 0) {
834 return;
835 }
836
837 if (_Py_LegacyLocaleDetected()) {
838 /* POSIX locale: enable C locale coercion and UTF-8 Mode */
839 if (config->utf8_mode < 0) {
840 config->utf8_mode = 1;
841 }
842 if (config->coerce_c_locale < 0) {
843 config->coerce_c_locale = 1;
844 }
845 return;
846 }
847}
848
849
850/* Read configuration settings from standard locations
851 *
852 * This function doesn't make any changes to the interpreter state - it
853 * merely populates any missing configuration settings. This allows an
854 * embedding application to completely override a config option by
855 * setting it before calling this function, or else modify the default
856 * setting before passing the fully populated config to Py_EndInitialization.
857 *
858 * More advanced selective initialization tricks are possible by calling
859 * this function multiple times with various preconfigured settings.
860 */
861
862_PyInitError
863_PyCoreConfig_Read(_PyCoreConfig *config)
864{
865 _PyInitError err;
866
867 _PyCoreConfig_GetGlobalConfig(config);
868
869 if (config->isolated > 0) {
870 config->use_environment = 0;
871 config->user_site_directory = 0;
872 }
873
874#ifdef MS_WINDOWS
875 if (config->legacy_windows_fs_encoding) {
876 config->utf8_mode = 0;
877 }
878#endif
879
880 assert(config->use_environment >= 0);
881 if (config->use_environment) {
882 err = config_read_env_vars(config);
883 if (_Py_INIT_FAILED(err)) {
884 return err;
885 }
886 }
887
888 /* -X options */
889 if (config_get_xoption(config, L"showrefcount")) {
890 config->show_ref_count = 1;
891 }
892 if (config_get_xoption(config, L"showalloccount")) {
893 config->show_alloc_count = 1;
894 }
895
896 err = config_read_complex_options(config);
897 if (_Py_INIT_FAILED(err)) {
898 return err;
899 }
900
901 if (config->utf8_mode < 0) {
902 err = config_init_utf8_mode(config);
903 if (_Py_INIT_FAILED(err)) {
904 return err;
905 }
906 }
907
908 if (config->home == NULL) {
909 err = config_init_home(config);
910 if (_Py_INIT_FAILED(err)) {
911 return err;
912 }
913 }
914
915 if (config->program_name == NULL) {
916 err = config_init_program_name(config);
917 if (_Py_INIT_FAILED(err)) {
918 return err;
919 }
920 }
921
922 config_init_locale(config);
923
924 if (config->_install_importlib) {
925 err = _PyCoreConfig_InitPathConfig(config);
926 if (_Py_INIT_FAILED(err)) {
927 return err;
928 }
929 }
930
931 /* default values */
932 if (config->dev_mode) {
933 if (config->faulthandler < 0) {
934 config->faulthandler = 1;
935 }
936 if (config->allocator == NULL) {
937 config->allocator = "debug";
938 }
939 }
940 if (config->use_hash_seed < 0) {
941 config->use_hash_seed = 0;
942 config->hash_seed = 0;
943 }
944 if (config->faulthandler < 0) {
945 config->faulthandler = 0;
946 }
947 if (config->tracemalloc < 0) {
948 config->tracemalloc = 0;
949 }
950 if (config->coerce_c_locale < 0) {
951 config->coerce_c_locale = 0;
952 }
953 if (config->utf8_mode < 0) {
954 config->utf8_mode = 0;
955 }
956 if (config->_frozen < 0) {
957 config->_frozen = 0;
958 }
959 if (config->argc < 0) {
960 config->argc = 0;
961 }
962
963 return _Py_INIT_OK();
964}