blob: 8724681a79bc6165e40f612e254d73356f280a46 [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 Stinner2c8ddcf2018-08-29 00:16:53 +0200674 const char *env = _PyCoreConfig_GetEnv(config, "PYTHONCOERCECLOCALE");
675 if (env) {
676 if (strcmp(env, "0") == 0) {
677 if (config->coerce_c_locale < 0) {
Victor Stinner5a953fd2018-08-03 22:49:07 +0200678 config->coerce_c_locale = 0;
679 }
Victor Stinner2c8ddcf2018-08-29 00:16:53 +0200680 }
681 else if (strcmp(env, "warn") == 0) {
682 config->coerce_c_locale_warn = 1;
683 }
684 else {
685 if (config->coerce_c_locale < 0) {
Victor Stinner5a953fd2018-08-03 22:49:07 +0200686 config->coerce_c_locale = 1;
687 }
Victor Stinner6c785c02018-08-01 17:56:14 +0200688 }
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{
Victor Stinnerd500e532018-08-28 17:27:36 +0200833 if (config->coerce_c_locale < 0) {
Victor Stinner5cb25892018-08-28 12:35:44 +0200834 /* The C locale enables the C locale coercion (PEP 538) */
Victor Stinnerd500e532018-08-28 17:27:36 +0200835 if (_Py_LegacyLocaleDetected()) {
Victor Stinner6c785c02018-08-01 17:56:14 +0200836 config->coerce_c_locale = 1;
837 }
Victor Stinner6c785c02018-08-01 17:56:14 +0200838 }
Victor Stinnerd500e532018-08-28 17:27:36 +0200839
Victor Stinner5cb25892018-08-28 12:35:44 +0200840#ifndef MS_WINDOWS
Victor Stinnerd500e532018-08-28 17:27:36 +0200841 if (config->utf8_mode < 0) {
Victor Stinner5cb25892018-08-28 12:35:44 +0200842 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
Victor Stinnerd500e532018-08-28 17:27:36 +0200843 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
844 if (ctype_loc != NULL
845 && (strcmp(ctype_loc, "C") == 0
846 || strcmp(ctype_loc, "POSIX") == 0))
847 {
Victor Stinner5cb25892018-08-28 12:35:44 +0200848 config->utf8_mode = 1;
849 }
850 }
851#endif
Victor Stinner6c785c02018-08-01 17:56:14 +0200852}
853
854
855/* Read configuration settings from standard locations
856 *
857 * This function doesn't make any changes to the interpreter state - it
858 * merely populates any missing configuration settings. This allows an
859 * embedding application to completely override a config option by
860 * setting it before calling this function, or else modify the default
861 * setting before passing the fully populated config to Py_EndInitialization.
862 *
863 * More advanced selective initialization tricks are possible by calling
864 * this function multiple times with various preconfigured settings.
865 */
866
867_PyInitError
868_PyCoreConfig_Read(_PyCoreConfig *config)
869{
870 _PyInitError err;
871
872 _PyCoreConfig_GetGlobalConfig(config);
873
874 if (config->isolated > 0) {
875 config->use_environment = 0;
876 config->user_site_directory = 0;
877 }
878
879#ifdef MS_WINDOWS
880 if (config->legacy_windows_fs_encoding) {
881 config->utf8_mode = 0;
882 }
883#endif
884
885 assert(config->use_environment >= 0);
886 if (config->use_environment) {
887 err = config_read_env_vars(config);
888 if (_Py_INIT_FAILED(err)) {
889 return err;
890 }
891 }
892
893 /* -X options */
894 if (config_get_xoption(config, L"showrefcount")) {
895 config->show_ref_count = 1;
896 }
897 if (config_get_xoption(config, L"showalloccount")) {
898 config->show_alloc_count = 1;
899 }
900
901 err = config_read_complex_options(config);
902 if (_Py_INIT_FAILED(err)) {
903 return err;
904 }
905
906 if (config->utf8_mode < 0) {
907 err = config_init_utf8_mode(config);
908 if (_Py_INIT_FAILED(err)) {
909 return err;
910 }
911 }
912
913 if (config->home == NULL) {
914 err = config_init_home(config);
915 if (_Py_INIT_FAILED(err)) {
916 return err;
917 }
918 }
919
920 if (config->program_name == NULL) {
921 err = config_init_program_name(config);
922 if (_Py_INIT_FAILED(err)) {
923 return err;
924 }
925 }
926
Victor Stinner5a953fd2018-08-03 22:49:07 +0200927 if (config->utf8_mode < 0 || config->coerce_c_locale < 0) {
928 config_init_locale(config);
929 }
Victor Stinner6c785c02018-08-01 17:56:14 +0200930
931 if (config->_install_importlib) {
932 err = _PyCoreConfig_InitPathConfig(config);
933 if (_Py_INIT_FAILED(err)) {
934 return err;
935 }
936 }
937
938 /* default values */
939 if (config->dev_mode) {
940 if (config->faulthandler < 0) {
941 config->faulthandler = 1;
942 }
943 if (config->allocator == NULL) {
944 config->allocator = "debug";
945 }
946 }
947 if (config->use_hash_seed < 0) {
948 config->use_hash_seed = 0;
949 config->hash_seed = 0;
950 }
951 if (config->faulthandler < 0) {
952 config->faulthandler = 0;
953 }
954 if (config->tracemalloc < 0) {
955 config->tracemalloc = 0;
956 }
957 if (config->coerce_c_locale < 0) {
958 config->coerce_c_locale = 0;
959 }
960 if (config->utf8_mode < 0) {
961 config->utf8_mode = 0;
962 }
963 if (config->_frozen < 0) {
964 config->_frozen = 0;
965 }
966 if (config->argc < 0) {
967 config->argc = 0;
968 }
969
970 return _Py_INIT_OK();
971}