blob: c16f34083ed67d69947252397865c17fc4268745 [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
Victor Stinnerf72346c2019-03-25 17:54:58 +0100114_PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
Victor Stinnerfa153762019-03-20 04:25:38 +0100115{
116 return _PyArgv_AsWstrList(args, &cmdline->argv);
117}
118
119
Victor Stinnerf72346c2019-03-25 17:54:58 +0100120static void
121_PyPreCmdline_GetPreConfig(_PyPreCmdline *cmdline, const _PyPreConfig *config)
122{
123#define COPY_ATTR(ATTR) \
124 if (config->ATTR != -1) { \
125 cmdline->ATTR = config->ATTR; \
126 }
127
128 COPY_ATTR(use_environment);
129 COPY_ATTR(isolated);
130
131#undef COPY_ATTR
132}
133
134
Victor Stinnercad1f742019-03-05 02:01:27 +0100135/* --- _PyPreConfig ----------------------------------------------- */
136
137void
138_PyPreConfig_Clear(_PyPreConfig *config)
139{
Victor Stinnerc656e252019-03-06 01:13:43 +0100140 PyMem_RawFree(config->allocator);
141 config->allocator = NULL;
Victor Stinnercad1f742019-03-05 02:01:27 +0100142}
143
144
145int
146_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
147{
148 _PyPreConfig_Clear(config);
149
150#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100151#define COPY_STR_ATTR(ATTR) \
152 do { \
153 if (config2->ATTR != NULL) { \
154 config->ATTR = _PyMem_RawStrdup(config2->ATTR); \
155 if (config->ATTR == NULL) { \
156 return -1; \
157 } \
158 } \
159 } while (0)
Victor Stinnercad1f742019-03-05 02:01:27 +0100160
161 COPY_ATTR(isolated);
162 COPY_ATTR(use_environment);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100163 COPY_ATTR(coerce_c_locale);
164 COPY_ATTR(coerce_c_locale_warn);
165#ifdef MS_WINDOWS
166 COPY_ATTR(legacy_windows_fs_encoding);
167#endif
168 COPY_ATTR(utf8_mode);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100169 COPY_ATTR(dev_mode);
170 COPY_STR_ATTR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100171
172#undef COPY_ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100173#undef COPY_STR_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100174 return 0;
175}
176
177
178void
179_PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
180{
181#define COPY_FLAG(ATTR, VALUE) \
182 if (config->ATTR == -1) { \
183 config->ATTR = VALUE; \
184 }
185#define COPY_NOT_FLAG(ATTR, VALUE) \
186 if (config->ATTR == -1) { \
187 config->ATTR = !(VALUE); \
188 }
189
190 COPY_FLAG(isolated, Py_IsolatedFlag);
191 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100192#ifdef MS_WINDOWS
193 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
194#endif
195 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100196
197#undef COPY_FLAG
198#undef COPY_NOT_FLAG
199}
200
201
202void
203_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
204{
205#define COPY_FLAG(ATTR, VAR) \
206 if (config->ATTR != -1) { \
207 VAR = config->ATTR; \
208 }
209#define COPY_NOT_FLAG(ATTR, VAR) \
210 if (config->ATTR != -1) { \
211 VAR = !config->ATTR; \
212 }
213
214 COPY_FLAG(isolated, Py_IsolatedFlag);
215 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100216#ifdef MS_WINDOWS
217 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
218#endif
219 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100220
221#undef COPY_FLAG
222#undef COPY_NOT_FLAG
223}
224
225
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100226const char*
227_PyPreConfig_GetEnv(const _PyPreConfig *config, const char *name)
228{
229 assert(config->use_environment >= 0);
230
231 if (!config->use_environment) {
232 return NULL;
233 }
234
235 const char *var = getenv(name);
236 if (var && var[0] != '\0') {
237 return var;
238 }
239 else {
240 return NULL;
241 }
242}
243
244
245int
246_Py_str_to_int(const char *str, int *result)
247{
248 const char *endptr = str;
249 errno = 0;
250 long value = strtol(str, (char **)&endptr, 10);
251 if (*endptr != '\0' || errno == ERANGE) {
252 return -1;
253 }
254 if (value < INT_MIN || value > INT_MAX) {
255 return -1;
256 }
257
258 *result = (int)value;
259 return 0;
260}
261
262
263void
264_Py_get_env_flag(_PyPreConfig *config, int *flag, const char *name)
265{
266 const char *var = _PyPreConfig_GetEnv(config, name);
267 if (!var) {
268 return;
269 }
270 int value;
271 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
272 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
273 value = 1;
274 }
275 if (*flag < value) {
276 *flag = value;
277 }
278}
279
280
281const wchar_t*
Victor Stinner74f65682019-03-15 15:08:05 +0100282_Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100283{
Victor Stinner74f65682019-03-15 15:08:05 +0100284 for (Py_ssize_t i=0; i < xoptions->length; i++) {
285 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100286 size_t len;
287 wchar_t *sep = wcschr(option, L'=');
288 if (sep != NULL) {
289 len = (sep - option);
290 }
291 else {
292 len = wcslen(option);
293 }
294 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
295 return option;
296 }
297 }
298 return NULL;
299}
300
301
302static _PyInitError
303preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
304{
305 const wchar_t *xopt;
306 if (cmdline) {
Victor Stinner74f65682019-03-15 15:08:05 +0100307 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100308 }
309 else {
310 xopt = NULL;
311 }
312 if (xopt) {
313 wchar_t *sep = wcschr(xopt, L'=');
314 if (sep) {
315 xopt = sep + 1;
316 if (wcscmp(xopt, L"1") == 0) {
317 config->utf8_mode = 1;
318 }
319 else if (wcscmp(xopt, L"0") == 0) {
320 config->utf8_mode = 0;
321 }
322 else {
323 return _Py_INIT_USER_ERR("invalid -X utf8 option value");
324 }
325 }
326 else {
327 config->utf8_mode = 1;
328 }
329 return _Py_INIT_OK();
330 }
331
332 const char *opt = _PyPreConfig_GetEnv(config, "PYTHONUTF8");
333 if (opt) {
334 if (strcmp(opt, "1") == 0) {
335 config->utf8_mode = 1;
336 }
337 else if (strcmp(opt, "0") == 0) {
338 config->utf8_mode = 0;
339 }
340 else {
341 return _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment "
342 "variable value");
343 }
344 return _Py_INIT_OK();
345 }
346
347 return _Py_INIT_OK();
348}
349
350
351static void
352preconfig_init_locale(_PyPreConfig *config)
353{
Victor Stinnerf72346c2019-03-25 17:54:58 +0100354 /* The C locale enables the C locale coercion (PEP 538) */
355 if (_Py_LegacyLocaleDetected()) {
356 config->coerce_c_locale = 2;
357 }
358 else {
359 config->coerce_c_locale = 0;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100360 }
361}
362
363
364static _PyInitError
Victor Stinnerf72346c2019-03-25 17:54:58 +0100365preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnercad1f742019-03-05 02:01:27 +0100366{
Victor Stinnerf72346c2019-03-25 17:54:58 +0100367 _PyInitError err;
368
369 err = _PyPreCmdline_Read(cmdline);
370 if (_Py_INIT_FAILED(err)) {
371 return err;
372 }
373
374 _PyPreCmdline_SetPreConfig(cmdline, config);
375
Victor Stinnercad1f742019-03-05 02:01:27 +0100376 _PyPreConfig_GetGlobalConfig(config);
377
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100378 /* isolated and use_environment */
Victor Stinnercad1f742019-03-05 02:01:27 +0100379 if (config->isolated > 0) {
380 config->use_environment = 0;
381 }
382
383 /* Default values */
384 if (config->use_environment < 0) {
385 config->use_environment = 0;
386 }
387
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100388 /* legacy_windows_fs_encoding, utf8_mode, coerce_c_locale */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100389 if (config->use_environment) {
390#ifdef MS_WINDOWS
391 _Py_get_env_flag(config, &config->legacy_windows_fs_encoding,
392 "PYTHONLEGACYWINDOWSFSENCODING");
393#endif
394
395 const char *env = _PyPreConfig_GetEnv(config, "PYTHONCOERCECLOCALE");
396 if (env) {
397 if (strcmp(env, "0") == 0) {
398 if (config->coerce_c_locale < 0) {
399 config->coerce_c_locale = 0;
400 }
401 }
402 else if (strcmp(env, "warn") == 0) {
403 config->coerce_c_locale_warn = 1;
404 }
405 else {
406 if (config->coerce_c_locale < 0) {
407 config->coerce_c_locale = 1;
408 }
409 }
410 }
411 }
412
413#ifdef MS_WINDOWS
414 if (config->legacy_windows_fs_encoding) {
415 config->utf8_mode = 0;
416 }
417#endif
418
419 if (config->utf8_mode < 0) {
Victor Stinnerf72346c2019-03-25 17:54:58 +0100420 err = preconfig_init_utf8_mode(config, cmdline);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100421 if (_Py_INIT_FAILED(err)) {
422 return err;
423 }
424 }
425
Victor Stinnerf72346c2019-03-25 17:54:58 +0100426 /* Test also if coerce_c_locale equals 1: PYTHONCOERCECLOCALE=1 doesn't
427 imply that the C locale is always coerced. It is only coerced if
428 if the LC_CTYPE locale is "C". */
429 if (config->coerce_c_locale != 0 && config->coerce_c_locale != 2) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100430 preconfig_init_locale(config);
431 }
432
433#ifndef MS_WINDOWS
434 if (config->utf8_mode < 0) {
435 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
436 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
437 if (ctype_loc != NULL
438 && (strcmp(ctype_loc, "C") == 0
439 || strcmp(ctype_loc, "POSIX") == 0))
440 {
441 config->utf8_mode = 1;
442 }
443 }
444#endif
445
446 if (config->coerce_c_locale < 0) {
447 config->coerce_c_locale = 0;
448 }
449 if (config->utf8_mode < 0) {
450 config->utf8_mode = 0;
451 }
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100452 if (config->coerce_c_locale < 0) {
453 config->coerce_c_locale = 0;
454 }
455
456 /* dev_mode */
Victor Stinner74f65682019-03-15 15:08:05 +0100457 if ((cmdline && _Py_get_xoption(&cmdline->xoptions, L"dev"))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100458 || _PyPreConfig_GetEnv(config, "PYTHONDEVMODE"))
459 {
460 config->dev_mode = 1;
461 }
462 if (config->dev_mode < 0) {
463 config->dev_mode = 0;
464 }
465
466 /* allocator */
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100467 if (config->allocator == NULL) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100468 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
469 over PYTHONDEV env var and "-X dev" command line option.
470 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
471 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100472 const char *allocator = _PyPreConfig_GetEnv(config, "PYTHONMALLOC");
473 if (allocator) {
474 config->allocator = _PyMem_RawStrdup(allocator);
475 if (config->allocator == NULL) {
476 return _Py_INIT_NO_MEMORY();
477 }
478 }
479 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100480
Victor Stinner25d13f32019-03-06 12:51:53 +0100481 if (config->dev_mode && config->allocator == NULL) {
482 config->allocator = _PyMem_RawStrdup("debug");
483 if (config->allocator == NULL) {
484 return _Py_INIT_NO_MEMORY();
485 }
486 }
487
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100488 assert(config->coerce_c_locale >= 0);
489 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100490 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100491 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100492 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100493
494 return _Py_INIT_OK();
495}
496
497
Victor Stinner4fffd382019-03-06 01:44:31 +0100498static _PyInitError
499get_ctype_locale(char **locale_p)
500{
501 const char *loc = setlocale(LC_CTYPE, NULL);
502 if (loc == NULL) {
503 return _Py_INIT_ERR("failed to LC_CTYPE locale");
504 }
505
506 char *copy = _PyMem_RawStrdup(loc);
507 if (copy == NULL) {
508 return _Py_INIT_NO_MEMORY();
509 }
510
511 *locale_p = copy;
512 return _Py_INIT_OK();
513}
514
515
Victor Stinnerfa153762019-03-20 04:25:38 +0100516void
517_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
518{
519#define COPY_ATTR(ATTR) \
520 if (cmdline->ATTR != -1) { \
521 config->ATTR = cmdline->ATTR; \
522 }
523
524 COPY_ATTR(use_environment);
525 COPY_ATTR(isolated);
526
527#undef COPY_ATTR
528}
529
530
Victor Stinnercad1f742019-03-05 02:01:27 +0100531int
532_PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict)
533{
534#define SET_ITEM(KEY, EXPR) \
535 do { \
536 PyObject *obj = (EXPR); \
537 if (obj == NULL) { \
538 goto fail; \
539 } \
540 int res = PyDict_SetItemString(dict, (KEY), obj); \
541 Py_DECREF(obj); \
542 if (res < 0) { \
543 goto fail; \
544 } \
545 } while (0)
546#define SET_ITEM_INT(ATTR) \
547 SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100548#define FROM_STRING(STR) \
549 ((STR != NULL) ? \
550 PyUnicode_FromString(STR) \
551 : (Py_INCREF(Py_None), Py_None))
552#define SET_ITEM_STR(ATTR) \
553 SET_ITEM(#ATTR, FROM_STRING(config->ATTR))
Victor Stinnercad1f742019-03-05 02:01:27 +0100554
555 SET_ITEM_INT(isolated);
556 SET_ITEM_INT(use_environment);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100557 SET_ITEM_INT(coerce_c_locale);
558 SET_ITEM_INT(coerce_c_locale_warn);
559 SET_ITEM_INT(utf8_mode);
560#ifdef MS_WINDOWS
561 SET_ITEM_INT(legacy_windows_fs_encoding);
562#endif
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100563 SET_ITEM_INT(dev_mode);
564 SET_ITEM_STR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100565 return 0;
566
567fail:
568 return -1;
569
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100570#undef FROM_STRING
Victor Stinnercad1f742019-03-05 02:01:27 +0100571#undef SET_ITEM
572#undef SET_ITEM_INT
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100573#undef SET_ITEM_STR
Victor Stinnercad1f742019-03-05 02:01:27 +0100574}
Victor Stinner6dcb5422019-03-05 02:44:12 +0100575
576
577/* Parse the command line arguments */
Victor Stinnerfa153762019-03-20 04:25:38 +0100578_PyInitError
579_PyPreCmdline_Read(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100580{
Victor Stinnerfa153762019-03-20 04:25:38 +0100581 _PyWstrList *argv = &cmdline->argv;
582
Victor Stinner6dcb5422019-03-05 02:44:12 +0100583 _PyOS_ResetGetOpt();
584 /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv()
585 is responsible for that */
586 _PyOS_opterr = 0;
587 do {
588 int longindex = -1;
Victor Stinnerfa153762019-03-20 04:25:38 +0100589 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100590
591 if (c == EOF || c == 'c' || c == 'm') {
592 break;
593 }
594
595 switch (c) {
596 case 'E':
Victor Stinnerfa153762019-03-20 04:25:38 +0100597 cmdline->use_environment = 0;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100598 break;
599
600 case 'I':
Victor Stinnerfa153762019-03-20 04:25:38 +0100601 cmdline->isolated = 1;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100602 break;
603
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100604 case 'X':
605 {
Victor Stinner74f65682019-03-15 15:08:05 +0100606 if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) {
607 return _Py_INIT_NO_MEMORY();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100608 }
609 break;
610 }
611
Victor Stinner6dcb5422019-03-05 02:44:12 +0100612 default:
613 /* ignore other argument:
614 handled by _PyCoreConfig_ReadFromArgv() */
615 break;
616 }
617 } while (1);
618
619 return _Py_INIT_OK();
620}
621
622
Victor Stinnerf72346c2019-03-25 17:54:58 +0100623/* Read the configuration from:
624
625 - environment variables
626 - Py_xxx global configuration variables
627 - the LC_CTYPE locale
628
629 See _PyPreConfig_ReadFromArgv() to parse also command line arguments. */
630_PyInitError
631_PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100632{
633 _PyInitError err;
Victor Stinnerfa153762019-03-20 04:25:38 +0100634 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinnerf72346c2019-03-25 17:54:58 +0100635 char *old_loc = NULL;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100636
Victor Stinnerf72346c2019-03-25 17:54:58 +0100637 err = get_ctype_locale(&old_loc);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100638 if (_Py_INIT_FAILED(err)) {
639 goto done;
640 }
641
Victor Stinnerf72346c2019-03-25 17:54:58 +0100642 /* Set LC_CTYPE to the user preferred locale */
643 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100644
Victor Stinnerf72346c2019-03-25 17:54:58 +0100645 _PyPreCmdline_GetPreConfig(&cmdline, config);
646
647 if (args) {
648 err = _PyPreCmdline_SetArgv(&cmdline, args);
649 if (_Py_INIT_FAILED(err)) {
650 goto done;
651 }
652 }
Victor Stinnerfa153762019-03-20 04:25:38 +0100653
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100654 err = preconfig_read(config, &cmdline);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100655
656done:
Victor Stinnerf72346c2019-03-25 17:54:58 +0100657 if (old_loc != NULL) {
658 setlocale(LC_CTYPE, old_loc);
659 PyMem_RawFree(old_loc);
660 }
Victor Stinnerfa153762019-03-20 04:25:38 +0100661 _PyPreCmdline_Clear(&cmdline);
Victor Stinnerf72346c2019-03-25 17:54:58 +0100662
Victor Stinner6dcb5422019-03-05 02:44:12 +0100663 return err;
664}
665
666
Victor Stinner4fffd382019-03-06 01:44:31 +0100667/* Read the configuration from:
668
669 - command line arguments
670 - environment variables
671 - Py_xxx global configuration variables
672 - the LC_CTYPE locale
673
674 See _PyPreConfig_ReadFromArgv() to parse also command line arguments. */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100675_PyInitError
676_PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
677{
678 _PyInitError err;
679
680 err = _PyRuntime_Initialize();
681 if (_Py_INIT_FAILED(err)) {
682 return err;
683 }
684
685 char *init_ctype_locale = NULL;
686 int init_utf8_mode = Py_UTF8Mode;
687#ifdef MS_WINDOWS
688 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
689#endif
690 _PyPreConfig save_config = _PyPreConfig_INIT;
691 int locale_coerced = 0;
692 int loops = 0;
693
Victor Stinner4fffd382019-03-06 01:44:31 +0100694 err = get_ctype_locale(&init_ctype_locale);
695 if (_Py_INIT_FAILED(err)) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100696 goto done;
697 }
698
Victor Stinnerf29084d2019-03-20 02:20:13 +0100699 _PyPreConfig_GetGlobalConfig(config);
700
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100701 if (_PyPreConfig_Copy(&save_config, config) < 0) {
702 err = _Py_INIT_NO_MEMORY();
703 goto done;
704 }
705
706 /* Set LC_CTYPE to the user preferred locale */
707 _Py_SetLocaleFromEnv(LC_CTYPE);
708
709 while (1) {
710 int utf8_mode = config->utf8_mode;
711
712 /* Watchdog to prevent an infinite loop */
713 loops++;
714 if (loops == 3) {
715 err = _Py_INIT_ERR("Encoding changed twice while "
716 "reading the configuration");
717 goto done;
718 }
719
720 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
721 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
722 Py_UTF8Mode = config->utf8_mode;
723#ifdef MS_WINDOWS
724 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
725#endif
726
Victor Stinnerf72346c2019-03-25 17:54:58 +0100727 err = _PyPreConfig_Read(config, args);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100728 if (_Py_INIT_FAILED(err)) {
729 goto done;
730 }
731
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100732 /* The legacy C locale assumes ASCII as the default text encoding, which
733 * causes problems not only for the CPython runtime, but also other
734 * components like GNU readline.
735 *
736 * Accordingly, when the CLI detects it, it attempts to coerce it to a
737 * more capable UTF-8 based alternative.
738 *
739 * See the documentation of the PYTHONCOERCECLOCALE setting for more
740 * details.
741 */
742 int encoding_changed = 0;
743 if (config->coerce_c_locale && !locale_coerced) {
744 locale_coerced = 1;
745 _Py_CoerceLegacyLocale(0);
746 encoding_changed = 1;
747 }
748
749 if (utf8_mode == -1) {
750 if (config->utf8_mode == 1) {
751 /* UTF-8 Mode enabled */
752 encoding_changed = 1;
753 }
754 }
755 else {
756 if (config->utf8_mode != utf8_mode) {
757 encoding_changed = 1;
758 }
759 }
760
761 if (!encoding_changed) {
762 break;
763 }
764
765 /* Reset the configuration before reading again the configuration,
766 just keep UTF-8 Mode value. */
767 int new_utf8_mode = config->utf8_mode;
768 int new_coerce_c_locale = config->coerce_c_locale;
769 if (_PyPreConfig_Copy(config, &save_config) < 0) {
770 err = _Py_INIT_NO_MEMORY();
771 goto done;
772 }
773 config->utf8_mode = new_utf8_mode;
774 config->coerce_c_locale = new_coerce_c_locale;
775
776 /* The encoding changed: read again the configuration
777 with the new encoding */
778 }
779 err = _Py_INIT_OK();
780
781done:
782 if (init_ctype_locale != NULL) {
783 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100784 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100785 }
786 _PyPreConfig_Clear(&save_config);
787 Py_UTF8Mode = init_utf8_mode ;
788#ifdef MS_WINDOWS
789 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
790#endif
791 return err;
792}
793
794
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100795static _PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100796_PyPreConfig_SetAllocator(_PyPreConfig *config)
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100797{
Victor Stinnerc656e252019-03-06 01:13:43 +0100798 assert(!_PyRuntime.core_initialized);
799
800 PyMemAllocatorEx old_alloc;
801 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
802
803 if (_PyMem_SetupAllocators(config->allocator) < 0) {
804 return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100805 }
Victor Stinnerc656e252019-03-06 01:13:43 +0100806
807 /* Copy the pre-configuration with the new allocator */
808 _PyPreConfig config2 = _PyPreConfig_INIT;
809 if (_PyPreConfig_Copy(&config2, config) < 0) {
810 _PyPreConfig_Clear(&config2);
811 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
812 return _Py_INIT_NO_MEMORY();
813 }
814
815 /* Free the old config and replace config with config2. Since config now
816 owns the data, don't free config2. */
817 PyMemAllocatorEx new_alloc;
818 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
819 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
820 _PyPreConfig_Clear(config);
821 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
822
823 *config = config2;
824
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100825 return _Py_INIT_OK();
826}
827
828
Victor Stinner4fffd382019-03-06 01:44:31 +0100829/* Write the pre-configuration:
830
831 - set the memory allocators
832 - set Py_xxx global configuration variables
833 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
834 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100835
836 If the memory allocator is changed, config is re-allocated with new
Victor Stinner4fffd382019-03-06 01:44:31 +0100837 allocator. So calling _PyPreConfig_Clear(config) is safe after this call.
838
839 Do nothing if called after Py_Initialize(): ignore the new
840 pre-configuration. */
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100841_PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100842_PyPreConfig_Write(_PyPreConfig *config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100843{
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100844 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100845 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100846 the new configuration. */
Victor Stinnerc656e252019-03-06 01:13:43 +0100847 return _Py_INIT_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100848 }
849
850 if (config->allocator != NULL) {
Victor Stinnerc656e252019-03-06 01:13:43 +0100851 _PyInitError err = _PyPreConfig_SetAllocator(config);
852 if (_Py_INIT_FAILED(err)) {
853 return err;
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100854 }
855 }
856
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100857 _PyPreConfig_SetGlobalConfig(config);
858
859 if (config->coerce_c_locale) {
860 _Py_CoerceLegacyLocale(config->coerce_c_locale_warn);
861 }
862
863 /* Set LC_CTYPE to the user preferred locale */
864 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100865
Victor Stinner6d5ee972019-03-23 12:05:43 +0100866 /* Write the new pre-configuration into _PyRuntime */
867 PyMemAllocatorEx old_alloc;
868 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
869 int res = _PyPreConfig_Copy(&_PyRuntime.preconfig, config);
870 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
871 if (res < 0) {
872 return _Py_INIT_NO_MEMORY();
873 }
874
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100875 return _Py_INIT_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100876}