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