blob: d856c124f3e9b41343842da0a13616f3177455ca [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
Victor Stinner74f65682019-03-15 15:08:05 +010067_PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list)
Victor Stinner91b9ecf2019-03-01 17:52:56 +010068{
Victor Stinner74f65682019-03-15 15:08:05 +010069 _PyWstrList wargv = _PyWstrList_INIT;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010070 if (args->use_bytes_argv) {
Victor Stinner74f65682019-03-15 15:08:05 +010071 size_t size = sizeof(wchar_t*) * args->argc;
72 wargv.items = (wchar_t **)PyMem_RawMalloc(size);
73 if (wargv.items == NULL) {
Victor Stinner91b9ecf2019-03-01 17:52:56 +010074 return _Py_INIT_NO_MEMORY();
75 }
76
Victor Stinner74f65682019-03-15 15:08:05 +010077 for (Py_ssize_t i = 0; i < args->argc; i++) {
Victor Stinner91b9ecf2019-03-01 17:52:56 +010078 size_t len;
79 wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
80 if (arg == NULL) {
Victor Stinner74f65682019-03-15 15:08:05 +010081 _PyWstrList_Clear(&wargv);
Victor Stinner91b9ecf2019-03-01 17:52:56 +010082 return DECODE_LOCALE_ERR("command line arguments",
83 (Py_ssize_t)len);
84 }
Victor Stinner74f65682019-03-15 15:08:05 +010085 wargv.items[i] = arg;
86 wargv.length++;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010087 }
Victor Stinner74f65682019-03-15 15:08:05 +010088
89 _PyWstrList_Clear(list);
90 *list = wargv;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010091 }
92 else {
Victor Stinner74f65682019-03-15 15:08:05 +010093 wargv.length = args->argc;
94 wargv.items = args->wchar_argv;
95 if (_PyWstrList_Copy(list, &wargv) < 0) {
96 return _Py_INIT_NO_MEMORY();
97 }
Victor Stinner91b9ecf2019-03-01 17:52:56 +010098 }
Victor Stinner91b9ecf2019-03-01 17:52:56 +010099 return _Py_INIT_OK();
100}
Victor Stinnercad1f742019-03-05 02:01:27 +0100101
102
Victor Stinner6dcb5422019-03-05 02:44:12 +0100103/* --- _PyPreCmdline ------------------------------------------------- */
104
Victor Stinnerfa153762019-03-20 04:25:38 +0100105void
106_PyPreCmdline_Clear(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100107{
Victor Stinner74f65682019-03-15 15:08:05 +0100108 _PyWstrList_Clear(&cmdline->argv);
109 _PyWstrList_Clear(&cmdline->xoptions);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100110}
111
112
Victor Stinnerfa153762019-03-20 04:25:38 +0100113_PyInitError
114_PyPreCmdline_Init(_PyPreCmdline *cmdline, const _PyArgv *args)
115{
116 return _PyArgv_AsWstrList(args, &cmdline->argv);
117}
118
119
Victor Stinnercad1f742019-03-05 02:01:27 +0100120/* --- _PyPreConfig ----------------------------------------------- */
121
122void
123_PyPreConfig_Clear(_PyPreConfig *config)
124{
Victor Stinnerc656e252019-03-06 01:13:43 +0100125 PyMem_RawFree(config->allocator);
126 config->allocator = NULL;
Victor Stinnercad1f742019-03-05 02:01:27 +0100127}
128
129
130int
131_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
132{
133 _PyPreConfig_Clear(config);
134
135#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100136#define COPY_STR_ATTR(ATTR) \
137 do { \
138 if (config2->ATTR != NULL) { \
139 config->ATTR = _PyMem_RawStrdup(config2->ATTR); \
140 if (config->ATTR == NULL) { \
141 return -1; \
142 } \
143 } \
144 } while (0)
Victor Stinnercad1f742019-03-05 02:01:27 +0100145
146 COPY_ATTR(isolated);
147 COPY_ATTR(use_environment);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100148 COPY_ATTR(coerce_c_locale);
149 COPY_ATTR(coerce_c_locale_warn);
150#ifdef MS_WINDOWS
151 COPY_ATTR(legacy_windows_fs_encoding);
152#endif
153 COPY_ATTR(utf8_mode);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100154 COPY_ATTR(dev_mode);
155 COPY_STR_ATTR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100156
157#undef COPY_ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100158#undef COPY_STR_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100159 return 0;
160}
161
162
163void
164_PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
165{
166#define COPY_FLAG(ATTR, VALUE) \
167 if (config->ATTR == -1) { \
168 config->ATTR = VALUE; \
169 }
170#define COPY_NOT_FLAG(ATTR, VALUE) \
171 if (config->ATTR == -1) { \
172 config->ATTR = !(VALUE); \
173 }
174
175 COPY_FLAG(isolated, Py_IsolatedFlag);
176 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100177#ifdef MS_WINDOWS
178 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
179#endif
180 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100181
182#undef COPY_FLAG
183#undef COPY_NOT_FLAG
184}
185
186
187void
188_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
189{
190#define COPY_FLAG(ATTR, VAR) \
191 if (config->ATTR != -1) { \
192 VAR = config->ATTR; \
193 }
194#define COPY_NOT_FLAG(ATTR, VAR) \
195 if (config->ATTR != -1) { \
196 VAR = !config->ATTR; \
197 }
198
199 COPY_FLAG(isolated, Py_IsolatedFlag);
200 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100201#ifdef MS_WINDOWS
202 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
203#endif
204 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100205
206#undef COPY_FLAG
207#undef COPY_NOT_FLAG
208}
209
210
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100211const char*
212_PyPreConfig_GetEnv(const _PyPreConfig *config, const char *name)
213{
214 assert(config->use_environment >= 0);
215
216 if (!config->use_environment) {
217 return NULL;
218 }
219
220 const char *var = getenv(name);
221 if (var && var[0] != '\0') {
222 return var;
223 }
224 else {
225 return NULL;
226 }
227}
228
229
230int
231_Py_str_to_int(const char *str, int *result)
232{
233 const char *endptr = str;
234 errno = 0;
235 long value = strtol(str, (char **)&endptr, 10);
236 if (*endptr != '\0' || errno == ERANGE) {
237 return -1;
238 }
239 if (value < INT_MIN || value > INT_MAX) {
240 return -1;
241 }
242
243 *result = (int)value;
244 return 0;
245}
246
247
248void
249_Py_get_env_flag(_PyPreConfig *config, int *flag, const char *name)
250{
251 const char *var = _PyPreConfig_GetEnv(config, name);
252 if (!var) {
253 return;
254 }
255 int value;
256 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
257 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
258 value = 1;
259 }
260 if (*flag < value) {
261 *flag = value;
262 }
263}
264
265
266const wchar_t*
Victor Stinner74f65682019-03-15 15:08:05 +0100267_Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100268{
Victor Stinner74f65682019-03-15 15:08:05 +0100269 for (Py_ssize_t i=0; i < xoptions->length; i++) {
270 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100271 size_t len;
272 wchar_t *sep = wcschr(option, L'=');
273 if (sep != NULL) {
274 len = (sep - option);
275 }
276 else {
277 len = wcslen(option);
278 }
279 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
280 return option;
281 }
282 }
283 return NULL;
284}
285
286
287static _PyInitError
288preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
289{
290 const wchar_t *xopt;
291 if (cmdline) {
Victor Stinner74f65682019-03-15 15:08:05 +0100292 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100293 }
294 else {
295 xopt = NULL;
296 }
297 if (xopt) {
298 wchar_t *sep = wcschr(xopt, L'=');
299 if (sep) {
300 xopt = sep + 1;
301 if (wcscmp(xopt, L"1") == 0) {
302 config->utf8_mode = 1;
303 }
304 else if (wcscmp(xopt, L"0") == 0) {
305 config->utf8_mode = 0;
306 }
307 else {
308 return _Py_INIT_USER_ERR("invalid -X utf8 option value");
309 }
310 }
311 else {
312 config->utf8_mode = 1;
313 }
314 return _Py_INIT_OK();
315 }
316
317 const char *opt = _PyPreConfig_GetEnv(config, "PYTHONUTF8");
318 if (opt) {
319 if (strcmp(opt, "1") == 0) {
320 config->utf8_mode = 1;
321 }
322 else if (strcmp(opt, "0") == 0) {
323 config->utf8_mode = 0;
324 }
325 else {
326 return _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment "
327 "variable value");
328 }
329 return _Py_INIT_OK();
330 }
331
332 return _Py_INIT_OK();
333}
334
335
336static void
337preconfig_init_locale(_PyPreConfig *config)
338{
339 /* Test also if coerce_c_locale equals 1: PYTHONCOERCECLOCALE=1 doesn't
340 imply that the C locale is always coerced. It is only coerced if
341 if the LC_CTYPE locale is "C". */
342 if (config->coerce_c_locale != 0) {
343 /* The C locale enables the C locale coercion (PEP 538) */
344 if (_Py_LegacyLocaleDetected()) {
345 config->coerce_c_locale = 1;
346 }
347 else {
348 config->coerce_c_locale = 0;
349 }
350 }
351}
352
353
354static _PyInitError
355preconfig_read(_PyPreConfig *config, const _PyPreCmdline *cmdline)
Victor Stinnercad1f742019-03-05 02:01:27 +0100356{
357 _PyPreConfig_GetGlobalConfig(config);
358
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100359 /* isolated and use_environment */
Victor Stinnercad1f742019-03-05 02:01:27 +0100360 if (config->isolated > 0) {
361 config->use_environment = 0;
362 }
363
364 /* Default values */
365 if (config->use_environment < 0) {
366 config->use_environment = 0;
367 }
368
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100369 /* legacy_windows_fs_encoding, utf8_mode, coerce_c_locale */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100370 if (config->use_environment) {
371#ifdef MS_WINDOWS
372 _Py_get_env_flag(config, &config->legacy_windows_fs_encoding,
373 "PYTHONLEGACYWINDOWSFSENCODING");
374#endif
375
376 const char *env = _PyPreConfig_GetEnv(config, "PYTHONCOERCECLOCALE");
377 if (env) {
378 if (strcmp(env, "0") == 0) {
379 if (config->coerce_c_locale < 0) {
380 config->coerce_c_locale = 0;
381 }
382 }
383 else if (strcmp(env, "warn") == 0) {
384 config->coerce_c_locale_warn = 1;
385 }
386 else {
387 if (config->coerce_c_locale < 0) {
388 config->coerce_c_locale = 1;
389 }
390 }
391 }
392 }
393
394#ifdef MS_WINDOWS
395 if (config->legacy_windows_fs_encoding) {
396 config->utf8_mode = 0;
397 }
398#endif
399
400 if (config->utf8_mode < 0) {
401 _PyInitError err = preconfig_init_utf8_mode(config, cmdline);
402 if (_Py_INIT_FAILED(err)) {
403 return err;
404 }
405 }
406
407 if (config->coerce_c_locale != 0) {
408 preconfig_init_locale(config);
409 }
410
411#ifndef MS_WINDOWS
412 if (config->utf8_mode < 0) {
413 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
414 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
415 if (ctype_loc != NULL
416 && (strcmp(ctype_loc, "C") == 0
417 || strcmp(ctype_loc, "POSIX") == 0))
418 {
419 config->utf8_mode = 1;
420 }
421 }
422#endif
423
424 if (config->coerce_c_locale < 0) {
425 config->coerce_c_locale = 0;
426 }
427 if (config->utf8_mode < 0) {
428 config->utf8_mode = 0;
429 }
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100430 if (config->coerce_c_locale < 0) {
431 config->coerce_c_locale = 0;
432 }
433
434 /* dev_mode */
Victor Stinner74f65682019-03-15 15:08:05 +0100435 if ((cmdline && _Py_get_xoption(&cmdline->xoptions, L"dev"))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100436 || _PyPreConfig_GetEnv(config, "PYTHONDEVMODE"))
437 {
438 config->dev_mode = 1;
439 }
440 if (config->dev_mode < 0) {
441 config->dev_mode = 0;
442 }
443
444 /* allocator */
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100445 if (config->allocator == NULL) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100446 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
447 over PYTHONDEV env var and "-X dev" command line option.
448 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
449 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100450 const char *allocator = _PyPreConfig_GetEnv(config, "PYTHONMALLOC");
451 if (allocator) {
452 config->allocator = _PyMem_RawStrdup(allocator);
453 if (config->allocator == NULL) {
454 return _Py_INIT_NO_MEMORY();
455 }
456 }
457 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100458
Victor Stinner25d13f32019-03-06 12:51:53 +0100459 if (config->dev_mode && config->allocator == NULL) {
460 config->allocator = _PyMem_RawStrdup("debug");
461 if (config->allocator == NULL) {
462 return _Py_INIT_NO_MEMORY();
463 }
464 }
465
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100466 assert(config->coerce_c_locale >= 0);
467 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100468 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100469 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100470 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100471
472 return _Py_INIT_OK();
473}
474
475
Victor Stinner4fffd382019-03-06 01:44:31 +0100476static _PyInitError
477get_ctype_locale(char **locale_p)
478{
479 const char *loc = setlocale(LC_CTYPE, NULL);
480 if (loc == NULL) {
481 return _Py_INIT_ERR("failed to LC_CTYPE locale");
482 }
483
484 char *copy = _PyMem_RawStrdup(loc);
485 if (copy == NULL) {
486 return _Py_INIT_NO_MEMORY();
487 }
488
489 *locale_p = copy;
490 return _Py_INIT_OK();
491}
492
493
494/* Read the configuration from:
495
496 - environment variables
497 - Py_xxx global configuration variables
498 - the LC_CTYPE locale
499
500 See _PyPreConfig_ReadFromArgv() to parse also command line arguments. */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100501_PyInitError
502_PyPreConfig_Read(_PyPreConfig *config)
503{
Victor Stinner4fffd382019-03-06 01:44:31 +0100504 _PyInitError err;
505 char *old_loc;
506
507 err = get_ctype_locale(&old_loc);
508 if (_Py_INIT_FAILED(err)) {
509 return err;
510 }
511
512 /* Set LC_CTYPE to the user preferred locale */
513 _Py_SetLocaleFromEnv(LC_CTYPE);
514
515 err = preconfig_read(config, NULL);
516
517 setlocale(LC_CTYPE, old_loc);
btharpere130a072019-03-19 06:50:25 -0400518 PyMem_RawFree(old_loc);
Victor Stinner4fffd382019-03-06 01:44:31 +0100519
520 return err;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100521}
522
523
Victor Stinnerfa153762019-03-20 04:25:38 +0100524void
525_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
526{
527#define COPY_ATTR(ATTR) \
528 if (cmdline->ATTR != -1) { \
529 config->ATTR = cmdline->ATTR; \
530 }
531
532 COPY_ATTR(use_environment);
533 COPY_ATTR(isolated);
534
535#undef COPY_ATTR
536}
537
538
Victor Stinnercad1f742019-03-05 02:01:27 +0100539int
540_PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict)
541{
542#define SET_ITEM(KEY, EXPR) \
543 do { \
544 PyObject *obj = (EXPR); \
545 if (obj == NULL) { \
546 goto fail; \
547 } \
548 int res = PyDict_SetItemString(dict, (KEY), obj); \
549 Py_DECREF(obj); \
550 if (res < 0) { \
551 goto fail; \
552 } \
553 } while (0)
554#define SET_ITEM_INT(ATTR) \
555 SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100556#define FROM_STRING(STR) \
557 ((STR != NULL) ? \
558 PyUnicode_FromString(STR) \
559 : (Py_INCREF(Py_None), Py_None))
560#define SET_ITEM_STR(ATTR) \
561 SET_ITEM(#ATTR, FROM_STRING(config->ATTR))
Victor Stinnercad1f742019-03-05 02:01:27 +0100562
563 SET_ITEM_INT(isolated);
564 SET_ITEM_INT(use_environment);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100565 SET_ITEM_INT(coerce_c_locale);
566 SET_ITEM_INT(coerce_c_locale_warn);
567 SET_ITEM_INT(utf8_mode);
568#ifdef MS_WINDOWS
569 SET_ITEM_INT(legacy_windows_fs_encoding);
570#endif
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100571 SET_ITEM_INT(dev_mode);
572 SET_ITEM_STR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100573 return 0;
574
575fail:
576 return -1;
577
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100578#undef FROM_STRING
Victor Stinnercad1f742019-03-05 02:01:27 +0100579#undef SET_ITEM
580#undef SET_ITEM_INT
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100581#undef SET_ITEM_STR
Victor Stinnercad1f742019-03-05 02:01:27 +0100582}
Victor Stinner6dcb5422019-03-05 02:44:12 +0100583
584
585/* Parse the command line arguments */
Victor Stinnerfa153762019-03-20 04:25:38 +0100586_PyInitError
587_PyPreCmdline_Read(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100588{
Victor Stinnerfa153762019-03-20 04:25:38 +0100589 _PyWstrList *argv = &cmdline->argv;
590
Victor Stinner6dcb5422019-03-05 02:44:12 +0100591 _PyOS_ResetGetOpt();
592 /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv()
593 is responsible for that */
594 _PyOS_opterr = 0;
595 do {
596 int longindex = -1;
Victor Stinnerfa153762019-03-20 04:25:38 +0100597 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100598
599 if (c == EOF || c == 'c' || c == 'm') {
600 break;
601 }
602
603 switch (c) {
604 case 'E':
Victor Stinnerfa153762019-03-20 04:25:38 +0100605 cmdline->use_environment = 0;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100606 break;
607
608 case 'I':
Victor Stinnerfa153762019-03-20 04:25:38 +0100609 cmdline->isolated = 1;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100610 break;
611
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100612 case 'X':
613 {
Victor Stinner74f65682019-03-15 15:08:05 +0100614 if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) {
615 return _Py_INIT_NO_MEMORY();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100616 }
617 break;
618 }
619
Victor Stinner6dcb5422019-03-05 02:44:12 +0100620 default:
621 /* ignore other argument:
622 handled by _PyCoreConfig_ReadFromArgv() */
623 break;
624 }
625 } while (1);
626
627 return _Py_INIT_OK();
628}
629
630
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100631static _PyInitError
632preconfig_from_argv(_PyPreConfig *config, const _PyArgv *args)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100633{
634 _PyInitError err;
635
Victor Stinnerfa153762019-03-20 04:25:38 +0100636 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100637
Victor Stinnerfa153762019-03-20 04:25:38 +0100638 err = _PyPreCmdline_Init(&cmdline, args);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100639 if (_Py_INIT_FAILED(err)) {
640 goto done;
641 }
642
Victor Stinnerfa153762019-03-20 04:25:38 +0100643 err = _PyPreCmdline_Read(&cmdline);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100644 if (_Py_INIT_FAILED(err)) {
645 goto done;
646 }
647
Victor Stinnerfa153762019-03-20 04:25:38 +0100648 _PyPreCmdline_SetPreConfig(&cmdline, config);
649
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100650 err = preconfig_read(config, &cmdline);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100651 if (_Py_INIT_FAILED(err)) {
652 goto done;
653 }
654 err = _Py_INIT_OK();
655
656done:
Victor Stinnerfa153762019-03-20 04:25:38 +0100657 _PyPreCmdline_Clear(&cmdline);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100658 return err;
659}
660
661
Victor Stinner4fffd382019-03-06 01:44:31 +0100662/* Read the configuration from:
663
664 - command line arguments
665 - environment variables
666 - Py_xxx global configuration variables
667 - the LC_CTYPE locale
668
669 See _PyPreConfig_ReadFromArgv() to parse also command line arguments. */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100670_PyInitError
671_PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
672{
673 _PyInitError err;
674
675 err = _PyRuntime_Initialize();
676 if (_Py_INIT_FAILED(err)) {
677 return err;
678 }
679
680 char *init_ctype_locale = NULL;
681 int init_utf8_mode = Py_UTF8Mode;
682#ifdef MS_WINDOWS
683 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
684#endif
685 _PyPreConfig save_config = _PyPreConfig_INIT;
686 int locale_coerced = 0;
687 int loops = 0;
688
Victor Stinner4fffd382019-03-06 01:44:31 +0100689 err = get_ctype_locale(&init_ctype_locale);
690 if (_Py_INIT_FAILED(err)) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100691 goto done;
692 }
693
Victor Stinnerf29084d2019-03-20 02:20:13 +0100694 _PyPreConfig_GetGlobalConfig(config);
695
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100696 if (_PyPreConfig_Copy(&save_config, config) < 0) {
697 err = _Py_INIT_NO_MEMORY();
698 goto done;
699 }
700
701 /* Set LC_CTYPE to the user preferred locale */
702 _Py_SetLocaleFromEnv(LC_CTYPE);
703
704 while (1) {
705 int utf8_mode = config->utf8_mode;
706
707 /* Watchdog to prevent an infinite loop */
708 loops++;
709 if (loops == 3) {
710 err = _Py_INIT_ERR("Encoding changed twice while "
711 "reading the configuration");
712 goto done;
713 }
714
715 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
716 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
717 Py_UTF8Mode = config->utf8_mode;
718#ifdef MS_WINDOWS
719 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
720#endif
721
722 err = preconfig_from_argv(config, args);
723 if (_Py_INIT_FAILED(err)) {
724 goto done;
725 }
726
727 if (locale_coerced) {
728 config->coerce_c_locale = 1;
729 }
730
731 /* The legacy C locale assumes ASCII as the default text encoding, which
732 * causes problems not only for the CPython runtime, but also other
733 * components like GNU readline.
734 *
735 * Accordingly, when the CLI detects it, it attempts to coerce it to a
736 * more capable UTF-8 based alternative.
737 *
738 * See the documentation of the PYTHONCOERCECLOCALE setting for more
739 * details.
740 */
741 int encoding_changed = 0;
742 if (config->coerce_c_locale && !locale_coerced) {
743 locale_coerced = 1;
744 _Py_CoerceLegacyLocale(0);
745 encoding_changed = 1;
746 }
747
748 if (utf8_mode == -1) {
749 if (config->utf8_mode == 1) {
750 /* UTF-8 Mode enabled */
751 encoding_changed = 1;
752 }
753 }
754 else {
755 if (config->utf8_mode != utf8_mode) {
756 encoding_changed = 1;
757 }
758 }
759
760 if (!encoding_changed) {
761 break;
762 }
763
764 /* Reset the configuration before reading again the configuration,
765 just keep UTF-8 Mode value. */
766 int new_utf8_mode = config->utf8_mode;
767 int new_coerce_c_locale = config->coerce_c_locale;
768 if (_PyPreConfig_Copy(config, &save_config) < 0) {
769 err = _Py_INIT_NO_MEMORY();
770 goto done;
771 }
772 config->utf8_mode = new_utf8_mode;
773 config->coerce_c_locale = new_coerce_c_locale;
774
775 /* The encoding changed: read again the configuration
776 with the new encoding */
777 }
778 err = _Py_INIT_OK();
779
780done:
781 if (init_ctype_locale != NULL) {
782 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100783 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100784 }
785 _PyPreConfig_Clear(&save_config);
786 Py_UTF8Mode = init_utf8_mode ;
787#ifdef MS_WINDOWS
788 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
789#endif
790 return err;
791}
792
793
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100794static _PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100795_PyPreConfig_SetAllocator(_PyPreConfig *config)
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100796{
Victor Stinnerc656e252019-03-06 01:13:43 +0100797 assert(!_PyRuntime.core_initialized);
798
799 PyMemAllocatorEx old_alloc;
800 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
801
802 if (_PyMem_SetupAllocators(config->allocator) < 0) {
803 return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100804 }
Victor Stinnerc656e252019-03-06 01:13:43 +0100805
806 /* Copy the pre-configuration with the new allocator */
807 _PyPreConfig config2 = _PyPreConfig_INIT;
808 if (_PyPreConfig_Copy(&config2, config) < 0) {
809 _PyPreConfig_Clear(&config2);
810 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
811 return _Py_INIT_NO_MEMORY();
812 }
813
814 /* Free the old config and replace config with config2. Since config now
815 owns the data, don't free config2. */
816 PyMemAllocatorEx new_alloc;
817 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
818 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
819 _PyPreConfig_Clear(config);
820 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
821
822 *config = config2;
823
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100824 return _Py_INIT_OK();
825}
826
827
Victor Stinner4fffd382019-03-06 01:44:31 +0100828/* Write the pre-configuration:
829
830 - set the memory allocators
831 - set Py_xxx global configuration variables
832 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
833 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100834
835 If the memory allocator is changed, config is re-allocated with new
Victor Stinner4fffd382019-03-06 01:44:31 +0100836 allocator. So calling _PyPreConfig_Clear(config) is safe after this call.
837
838 Do nothing if called after Py_Initialize(): ignore the new
839 pre-configuration. */
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100840_PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100841_PyPreConfig_Write(_PyPreConfig *config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100842{
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100843 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100844 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100845 the new configuration. */
Victor Stinnerc656e252019-03-06 01:13:43 +0100846 return _Py_INIT_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100847 }
848
849 if (config->allocator != NULL) {
Victor Stinnerc656e252019-03-06 01:13:43 +0100850 _PyInitError err = _PyPreConfig_SetAllocator(config);
851 if (_Py_INIT_FAILED(err)) {
852 return err;
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100853 }
854 }
855
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100856 _PyPreConfig_SetGlobalConfig(config);
857
858 if (config->coerce_c_locale) {
859 _Py_CoerceLegacyLocale(config->coerce_c_locale_warn);
860 }
861
862 /* Set LC_CTYPE to the user preferred locale */
863 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100864
865 return _Py_INIT_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100866}