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