blob: 69242032151ab60f05d9993957a6660e0384ce19 [file] [log] [blame]
Victor Stinner91b9ecf2019-03-01 17:52:56 +01001#include "Python.h"
2#include "pycore_coreconfig.h"
Victor Stinner6dcb5422019-03-05 02:44:12 +01003#include "pycore_getopt.h"
Victor Stinner5a02e0d2019-03-05 12:32:09 +01004#include "pycore_pystate.h" /* _PyRuntime_Initialize() */
5#include <locale.h> /* setlocale() */
Victor Stinner91b9ecf2019-03-01 17:52:56 +01006
7
8#define DECODE_LOCALE_ERR(NAME, LEN) \
9 (((LEN) == -2) \
10 ? _Py_INIT_USER_ERR("cannot decode " NAME) \
11 : _Py_INIT_NO_MEMORY())
12
13
14/* --- File system encoding/errors -------------------------------- */
15
16/* The filesystem encoding is chosen by config_init_fs_encoding(),
17 see also initfsencoding(). */
18const char *Py_FileSystemDefaultEncoding = NULL;
19int Py_HasFileSystemDefaultEncoding = 0;
20const char *Py_FileSystemDefaultEncodeErrors = NULL;
21int _Py_HasFileSystemDefaultEncodeErrors = 0;
22
23void
24_Py_ClearFileSystemEncoding(void)
25{
26 if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
27 PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
28 Py_FileSystemDefaultEncoding = NULL;
29 }
30 if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
31 PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
32 Py_FileSystemDefaultEncodeErrors = NULL;
33 }
34}
35
36
37/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
38 global configuration variables. */
39int
40_Py_SetFileSystemEncoding(const char *encoding, const char *errors)
41{
42 char *encoding2 = _PyMem_RawStrdup(encoding);
43 if (encoding2 == NULL) {
44 return -1;
45 }
46
47 char *errors2 = _PyMem_RawStrdup(errors);
48 if (errors2 == NULL) {
49 PyMem_RawFree(encoding2);
50 return -1;
51 }
52
53 _Py_ClearFileSystemEncoding();
54
55 Py_FileSystemDefaultEncoding = encoding2;
56 Py_HasFileSystemDefaultEncoding = 0;
57
58 Py_FileSystemDefaultEncodeErrors = errors2;
59 _Py_HasFileSystemDefaultEncodeErrors = 0;
60 return 0;
61}
62
63
64/* --- _PyArgv ---------------------------------------------------- */
65
66_PyInitError
67_PyArgv_Decode(const _PyArgv *args, wchar_t*** argv_p)
68{
69 wchar_t** argv;
70 if (args->use_bytes_argv) {
71 /* +1 for a the NULL terminator */
72 size_t size = sizeof(wchar_t*) * (args->argc + 1);
73 argv = (wchar_t **)PyMem_RawMalloc(size);
74 if (argv == NULL) {
75 return _Py_INIT_NO_MEMORY();
76 }
77
78 for (int i = 0; i < args->argc; i++) {
79 size_t len;
80 wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
81 if (arg == NULL) {
82 _Py_wstrlist_clear(i, argv);
83 return DECODE_LOCALE_ERR("command line arguments",
84 (Py_ssize_t)len);
85 }
86 argv[i] = arg;
87 }
88 argv[args->argc] = NULL;
89 }
90 else {
91 argv = args->wchar_argv;
92 }
93 *argv_p = argv;
94 return _Py_INIT_OK();
95}
Victor Stinnercad1f742019-03-05 02:01:27 +010096
97
Victor Stinner6dcb5422019-03-05 02:44:12 +010098/* --- _PyPreCmdline ------------------------------------------------- */
99
100typedef struct {
101 const _PyArgv *args;
102 int argc;
103 wchar_t **argv;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100104 int nxoption; /* Number of -X options */
105 wchar_t **xoptions; /* -X options */
Victor Stinner6dcb5422019-03-05 02:44:12 +0100106} _PyPreCmdline;
107
108
109static void
110precmdline_clear(_PyPreCmdline *cmdline)
111{
112 if (cmdline->args->use_bytes_argv && cmdline->argv != NULL) {
113 _Py_wstrlist_clear(cmdline->args->argc, cmdline->argv);
114 }
115 cmdline->argv = NULL;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100116
117 _Py_wstrlist_clear(cmdline->nxoption, cmdline->xoptions);
118 cmdline->nxoption = 0;
119 cmdline->xoptions = NULL;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100120}
121
122
Victor Stinnercad1f742019-03-05 02:01:27 +0100123/* --- _PyPreConfig ----------------------------------------------- */
124
125void
126_PyPreConfig_Clear(_PyPreConfig *config)
127{
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100128#define CLEAR(ATTR) \
129 do { \
130 PyMem_RawFree(ATTR); \
131 ATTR = NULL; \
132 } while (0)
133
134 CLEAR(config->allocator);
135
136#undef CLEAR
Victor Stinnercad1f742019-03-05 02:01:27 +0100137}
138
139
140int
141_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
142{
143 _PyPreConfig_Clear(config);
144
145#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100146#define COPY_STR_ATTR(ATTR) \
147 do { \
148 if (config2->ATTR != NULL) { \
149 config->ATTR = _PyMem_RawStrdup(config2->ATTR); \
150 if (config->ATTR == NULL) { \
151 return -1; \
152 } \
153 } \
154 } while (0)
Victor Stinnercad1f742019-03-05 02:01:27 +0100155
156 COPY_ATTR(isolated);
157 COPY_ATTR(use_environment);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100158 COPY_ATTR(coerce_c_locale);
159 COPY_ATTR(coerce_c_locale_warn);
160#ifdef MS_WINDOWS
161 COPY_ATTR(legacy_windows_fs_encoding);
162#endif
163 COPY_ATTR(utf8_mode);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100164 COPY_ATTR(dev_mode);
165 COPY_STR_ATTR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100166
167#undef COPY_ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100168#undef COPY_STR_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100169 return 0;
170}
171
172
173void
174_PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
175{
176#define COPY_FLAG(ATTR, VALUE) \
177 if (config->ATTR == -1) { \
178 config->ATTR = VALUE; \
179 }
180#define COPY_NOT_FLAG(ATTR, VALUE) \
181 if (config->ATTR == -1) { \
182 config->ATTR = !(VALUE); \
183 }
184
185 COPY_FLAG(isolated, Py_IsolatedFlag);
186 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100187#ifdef MS_WINDOWS
188 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
189#endif
190 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100191
192#undef COPY_FLAG
193#undef COPY_NOT_FLAG
194}
195
196
197void
198_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
199{
200#define COPY_FLAG(ATTR, VAR) \
201 if (config->ATTR != -1) { \
202 VAR = config->ATTR; \
203 }
204#define COPY_NOT_FLAG(ATTR, VAR) \
205 if (config->ATTR != -1) { \
206 VAR = !config->ATTR; \
207 }
208
209 COPY_FLAG(isolated, Py_IsolatedFlag);
210 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100211#ifdef MS_WINDOWS
212 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
213#endif
214 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100215
216#undef COPY_FLAG
217#undef COPY_NOT_FLAG
218}
219
220
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100221const char*
222_PyPreConfig_GetEnv(const _PyPreConfig *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_Py_str_to_int(const char *str, int *result)
242{
243 const char *endptr = str;
244 errno = 0;
245 long value = strtol(str, (char **)&endptr, 10);
246 if (*endptr != '\0' || errno == ERANGE) {
247 return -1;
248 }
249 if (value < INT_MIN || value > INT_MAX) {
250 return -1;
251 }
252
253 *result = (int)value;
254 return 0;
255}
256
257
258void
259_Py_get_env_flag(_PyPreConfig *config, int *flag, const char *name)
260{
261 const char *var = _PyPreConfig_GetEnv(config, name);
262 if (!var) {
263 return;
264 }
265 int value;
266 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
267 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
268 value = 1;
269 }
270 if (*flag < value) {
271 *flag = value;
272 }
273}
274
275
276const wchar_t*
277_Py_get_xoption(int nxoption, wchar_t * const *xoptions, const wchar_t *name)
278{
279 for (int i=0; i < nxoption; i++) {
280 const wchar_t *option = xoptions[i];
281 size_t len;
282 wchar_t *sep = wcschr(option, L'=');
283 if (sep != NULL) {
284 len = (sep - option);
285 }
286 else {
287 len = wcslen(option);
288 }
289 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
290 return option;
291 }
292 }
293 return NULL;
294}
295
296
297static _PyInitError
298preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
299{
300 const wchar_t *xopt;
301 if (cmdline) {
302 xopt = _Py_get_xoption(cmdline->nxoption, cmdline->xoptions, L"utf8");
303 }
304 else {
305 xopt = NULL;
306 }
307 if (xopt) {
308 wchar_t *sep = wcschr(xopt, L'=');
309 if (sep) {
310 xopt = sep + 1;
311 if (wcscmp(xopt, L"1") == 0) {
312 config->utf8_mode = 1;
313 }
314 else if (wcscmp(xopt, L"0") == 0) {
315 config->utf8_mode = 0;
316 }
317 else {
318 return _Py_INIT_USER_ERR("invalid -X utf8 option value");
319 }
320 }
321 else {
322 config->utf8_mode = 1;
323 }
324 return _Py_INIT_OK();
325 }
326
327 const char *opt = _PyPreConfig_GetEnv(config, "PYTHONUTF8");
328 if (opt) {
329 if (strcmp(opt, "1") == 0) {
330 config->utf8_mode = 1;
331 }
332 else if (strcmp(opt, "0") == 0) {
333 config->utf8_mode = 0;
334 }
335 else {
336 return _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment "
337 "variable value");
338 }
339 return _Py_INIT_OK();
340 }
341
342 return _Py_INIT_OK();
343}
344
345
346static void
347preconfig_init_locale(_PyPreConfig *config)
348{
349 /* Test also if coerce_c_locale equals 1: PYTHONCOERCECLOCALE=1 doesn't
350 imply that the C locale is always coerced. It is only coerced if
351 if the LC_CTYPE locale is "C". */
352 if (config->coerce_c_locale != 0) {
353 /* The C locale enables the C locale coercion (PEP 538) */
354 if (_Py_LegacyLocaleDetected()) {
355 config->coerce_c_locale = 1;
356 }
357 else {
358 config->coerce_c_locale = 0;
359 }
360 }
361}
362
363
364static _PyInitError
365preconfig_read(_PyPreConfig *config, const _PyPreCmdline *cmdline)
Victor Stinnercad1f742019-03-05 02:01:27 +0100366{
367 _PyPreConfig_GetGlobalConfig(config);
368
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100369 /* isolated and use_environment */
Victor Stinnercad1f742019-03-05 02:01:27 +0100370 if (config->isolated > 0) {
371 config->use_environment = 0;
372 }
373
374 /* Default values */
375 if (config->use_environment < 0) {
376 config->use_environment = 0;
377 }
378
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100379 /* legacy_windows_fs_encoding, utf8_mode, coerce_c_locale */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100380 if (config->use_environment) {
381#ifdef MS_WINDOWS
382 _Py_get_env_flag(config, &config->legacy_windows_fs_encoding,
383 "PYTHONLEGACYWINDOWSFSENCODING");
384#endif
385
386 const char *env = _PyPreConfig_GetEnv(config, "PYTHONCOERCECLOCALE");
387 if (env) {
388 if (strcmp(env, "0") == 0) {
389 if (config->coerce_c_locale < 0) {
390 config->coerce_c_locale = 0;
391 }
392 }
393 else if (strcmp(env, "warn") == 0) {
394 config->coerce_c_locale_warn = 1;
395 }
396 else {
397 if (config->coerce_c_locale < 0) {
398 config->coerce_c_locale = 1;
399 }
400 }
401 }
402 }
403
404#ifdef MS_WINDOWS
405 if (config->legacy_windows_fs_encoding) {
406 config->utf8_mode = 0;
407 }
408#endif
409
410 if (config->utf8_mode < 0) {
411 _PyInitError err = preconfig_init_utf8_mode(config, cmdline);
412 if (_Py_INIT_FAILED(err)) {
413 return err;
414 }
415 }
416
417 if (config->coerce_c_locale != 0) {
418 preconfig_init_locale(config);
419 }
420
421#ifndef MS_WINDOWS
422 if (config->utf8_mode < 0) {
423 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
424 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
425 if (ctype_loc != NULL
426 && (strcmp(ctype_loc, "C") == 0
427 || strcmp(ctype_loc, "POSIX") == 0))
428 {
429 config->utf8_mode = 1;
430 }
431 }
432#endif
433
434 if (config->coerce_c_locale < 0) {
435 config->coerce_c_locale = 0;
436 }
437 if (config->utf8_mode < 0) {
438 config->utf8_mode = 0;
439 }
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100440 if (config->coerce_c_locale < 0) {
441 config->coerce_c_locale = 0;
442 }
443
444 /* dev_mode */
445 if ((cmdline && _Py_get_xoption(cmdline->nxoption, cmdline->xoptions, L"dev"))
446 || _PyPreConfig_GetEnv(config, "PYTHONDEVMODE"))
447 {
448 config->dev_mode = 1;
449 }
450 if (config->dev_mode < 0) {
451 config->dev_mode = 0;
452 }
453
454 /* allocator */
455 if (config->dev_mode && config->allocator == NULL) {
Victor Stinnera9df6512019-03-05 23:31:54 +0100456 const char *allocator = _PyMem_GetDebugAllocatorsName();
457 config->allocator = _PyMem_RawStrdup(allocator);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100458 if (config->allocator == NULL) {
459 return _Py_INIT_NO_MEMORY();
460 }
461 }
462
463 if (config->allocator == NULL) {
464 const char *allocator = _PyPreConfig_GetEnv(config, "PYTHONMALLOC");
465 if (allocator) {
466 config->allocator = _PyMem_RawStrdup(allocator);
467 if (config->allocator == NULL) {
468 return _Py_INIT_NO_MEMORY();
469 }
470 }
471 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100472
473 assert(config->coerce_c_locale >= 0);
474 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100475 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100476 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100477 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100478
479 return _Py_INIT_OK();
480}
481
482
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100483_PyInitError
484_PyPreConfig_Read(_PyPreConfig *config)
485{
486 return preconfig_read(config, NULL);
487}
488
489
Victor Stinnercad1f742019-03-05 02:01:27 +0100490int
491_PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict)
492{
493#define SET_ITEM(KEY, EXPR) \
494 do { \
495 PyObject *obj = (EXPR); \
496 if (obj == NULL) { \
497 goto fail; \
498 } \
499 int res = PyDict_SetItemString(dict, (KEY), obj); \
500 Py_DECREF(obj); \
501 if (res < 0) { \
502 goto fail; \
503 } \
504 } while (0)
505#define SET_ITEM_INT(ATTR) \
506 SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100507#define FROM_STRING(STR) \
508 ((STR != NULL) ? \
509 PyUnicode_FromString(STR) \
510 : (Py_INCREF(Py_None), Py_None))
511#define SET_ITEM_STR(ATTR) \
512 SET_ITEM(#ATTR, FROM_STRING(config->ATTR))
Victor Stinnercad1f742019-03-05 02:01:27 +0100513
514 SET_ITEM_INT(isolated);
515 SET_ITEM_INT(use_environment);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100516 SET_ITEM_INT(coerce_c_locale);
517 SET_ITEM_INT(coerce_c_locale_warn);
518 SET_ITEM_INT(utf8_mode);
519#ifdef MS_WINDOWS
520 SET_ITEM_INT(legacy_windows_fs_encoding);
521#endif
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100522 SET_ITEM_INT(dev_mode);
523 SET_ITEM_STR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100524 return 0;
525
526fail:
527 return -1;
528
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100529#undef FROM_STRING
Victor Stinnercad1f742019-03-05 02:01:27 +0100530#undef SET_ITEM
531#undef SET_ITEM_INT
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100532#undef SET_ITEM_STR
Victor Stinnercad1f742019-03-05 02:01:27 +0100533}
Victor Stinner6dcb5422019-03-05 02:44:12 +0100534
535
536/* Parse the command line arguments */
537static _PyInitError
538preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline)
539{
540 _PyOS_ResetGetOpt();
541 /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv()
542 is responsible for that */
543 _PyOS_opterr = 0;
544 do {
545 int longindex = -1;
546 int c = _PyOS_GetOpt(cmdline->args->argc, cmdline->argv, &longindex);
547
548 if (c == EOF || c == 'c' || c == 'm') {
549 break;
550 }
551
552 switch (c) {
553 case 'E':
554 config->use_environment = 0;
555 break;
556
557 case 'I':
558 config->isolated++;
559 break;
560
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100561 case 'X':
562 {
563 _PyInitError err;
564 err = _Py_wstrlist_append(&cmdline->nxoption,
565 &cmdline->xoptions,
566 _PyOS_optarg);
567 if (_Py_INIT_FAILED(err)) {
568 return err;
569 }
570 break;
571 }
572
Victor Stinner6dcb5422019-03-05 02:44:12 +0100573 default:
574 /* ignore other argument:
575 handled by _PyCoreConfig_ReadFromArgv() */
576 break;
577 }
578 } while (1);
579
580 return _Py_INIT_OK();
581}
582
583
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100584static _PyInitError
585preconfig_from_argv(_PyPreConfig *config, const _PyArgv *args)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100586{
587 _PyInitError err;
588
589 _PyPreCmdline cmdline;
590 memset(&cmdline, 0, sizeof(cmdline));
591 cmdline.args = args;
592
593 err = _PyArgv_Decode(cmdline.args, &cmdline.argv);
594 if (_Py_INIT_FAILED(err)) {
595 goto done;
596 }
597
598 err = preconfig_parse_cmdline(config, &cmdline);
599 if (_Py_INIT_FAILED(err)) {
600 goto done;
601 }
602
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100603 err = preconfig_read(config, &cmdline);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100604 if (_Py_INIT_FAILED(err)) {
605 goto done;
606 }
607 err = _Py_INIT_OK();
608
609done:
610 precmdline_clear(&cmdline);
611 return err;
612}
613
614
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100615/* Read the preconfiguration. */
616_PyInitError
617_PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
618{
619 _PyInitError err;
620
621 err = _PyRuntime_Initialize();
622 if (_Py_INIT_FAILED(err)) {
623 return err;
624 }
625
626 char *init_ctype_locale = NULL;
627 int init_utf8_mode = Py_UTF8Mode;
628#ifdef MS_WINDOWS
629 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
630#endif
631 _PyPreConfig save_config = _PyPreConfig_INIT;
632 int locale_coerced = 0;
633 int loops = 0;
634
635 /* copy LC_CTYPE locale */
636 const char *loc = setlocale(LC_CTYPE, NULL);
637 if (loc == NULL) {
638 err = _Py_INIT_ERR("failed to LC_CTYPE locale");
639 goto done;
640 }
641 init_ctype_locale = _PyMem_RawStrdup(loc);
642 if (init_ctype_locale == NULL) {
643 err = _Py_INIT_NO_MEMORY();
644 goto done;
645 }
646
647 if (_PyPreConfig_Copy(&save_config, config) < 0) {
648 err = _Py_INIT_NO_MEMORY();
649 goto done;
650 }
651
652 /* Set LC_CTYPE to the user preferred locale */
653 _Py_SetLocaleFromEnv(LC_CTYPE);
654
655 while (1) {
656 int utf8_mode = config->utf8_mode;
657
658 /* Watchdog to prevent an infinite loop */
659 loops++;
660 if (loops == 3) {
661 err = _Py_INIT_ERR("Encoding changed twice while "
662 "reading the configuration");
663 goto done;
664 }
665
666 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
667 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
668 Py_UTF8Mode = config->utf8_mode;
669#ifdef MS_WINDOWS
670 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
671#endif
672
673 err = preconfig_from_argv(config, args);
674 if (_Py_INIT_FAILED(err)) {
675 goto done;
676 }
677
678 if (locale_coerced) {
679 config->coerce_c_locale = 1;
680 }
681
682 /* The legacy C locale assumes ASCII as the default text encoding, which
683 * causes problems not only for the CPython runtime, but also other
684 * components like GNU readline.
685 *
686 * Accordingly, when the CLI detects it, it attempts to coerce it to a
687 * more capable UTF-8 based alternative.
688 *
689 * See the documentation of the PYTHONCOERCECLOCALE setting for more
690 * details.
691 */
692 int encoding_changed = 0;
693 if (config->coerce_c_locale && !locale_coerced) {
694 locale_coerced = 1;
695 _Py_CoerceLegacyLocale(0);
696 encoding_changed = 1;
697 }
698
699 if (utf8_mode == -1) {
700 if (config->utf8_mode == 1) {
701 /* UTF-8 Mode enabled */
702 encoding_changed = 1;
703 }
704 }
705 else {
706 if (config->utf8_mode != utf8_mode) {
707 encoding_changed = 1;
708 }
709 }
710
711 if (!encoding_changed) {
712 break;
713 }
714
715 /* Reset the configuration before reading again the configuration,
716 just keep UTF-8 Mode value. */
717 int new_utf8_mode = config->utf8_mode;
718 int new_coerce_c_locale = config->coerce_c_locale;
719 if (_PyPreConfig_Copy(config, &save_config) < 0) {
720 err = _Py_INIT_NO_MEMORY();
721 goto done;
722 }
723 config->utf8_mode = new_utf8_mode;
724 config->coerce_c_locale = new_coerce_c_locale;
725
726 /* The encoding changed: read again the configuration
727 with the new encoding */
728 }
729 err = _Py_INIT_OK();
730
731done:
732 if (init_ctype_locale != NULL) {
733 setlocale(LC_CTYPE, init_ctype_locale);
734 }
735 _PyPreConfig_Clear(&save_config);
736 Py_UTF8Mode = init_utf8_mode ;
737#ifdef MS_WINDOWS
738 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
739#endif
740 return err;
741}
742
743
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100744static _PyInitError
745_PyPreConfig_Reconfigure(const _PyPreConfig *config)
746{
747 if (config->allocator != NULL) {
748 const char *allocator = _PyMem_GetAllocatorsName();
749 if (allocator == NULL || strcmp(config->allocator, allocator) != 0) {
750 return _Py_INIT_USER_ERR("cannot modify memory allocator "
751 "after first Py_Initialize()");
752 }
753 }
754 return _Py_INIT_OK();
755}
756
757
758_PyInitError
Victor Stinner6dcb5422019-03-05 02:44:12 +0100759_PyPreConfig_Write(const _PyPreConfig *config)
760{
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100761 if (_PyRuntime.core_initialized) {
762 /* bpo-34008: Calling Py_Main() after Py_Initialize() ignores
763 the new configuration. */
764 return _PyPreConfig_Reconfigure(config);
765 }
766
767 if (config->allocator != NULL) {
768 if (_PyMem_SetupAllocators(config->allocator) < 0) {
769 return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
770 }
771 }
772
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100773 _PyPreConfig_SetGlobalConfig(config);
774
775 if (config->coerce_c_locale) {
776 _Py_CoerceLegacyLocale(config->coerce_c_locale_warn);
777 }
778
779 /* Set LC_CTYPE to the user preferred locale */
780 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100781
782 return _Py_INIT_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100783}