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