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