blob: ac87a7a3c7e97a0ed15404748b533dbd97f7b7d7 [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 Stinnera6fbc4e2019-03-25 18:37:10 +0100113int
114_PyPreCmdline_Copy(_PyPreCmdline *cmdline, const _PyPreCmdline *cmdline2)
115{
116 _PyPreCmdline_Clear(cmdline);
117 if (_PyWstrList_Copy(&cmdline->argv, &cmdline2->argv) < 0) {
118 return -1;
119 }
120 if (_PyWstrList_Copy(&cmdline->xoptions, &cmdline2->xoptions) < 0) {
121 return -1;
122 }
123 cmdline->use_environment = cmdline2->use_environment;
124 cmdline->isolated = cmdline2->isolated;
125 return 0;
126}
127
128
Victor Stinnerfa153762019-03-20 04:25:38 +0100129_PyInitError
Victor Stinnerf72346c2019-03-25 17:54:58 +0100130_PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
Victor Stinnerfa153762019-03-20 04:25:38 +0100131{
132 return _PyArgv_AsWstrList(args, &cmdline->argv);
133}
134
135
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100136void
Victor Stinnerf72346c2019-03-25 17:54:58 +0100137_PyPreCmdline_GetPreConfig(_PyPreCmdline *cmdline, const _PyPreConfig *config)
138{
139#define COPY_ATTR(ATTR) \
140 if (config->ATTR != -1) { \
141 cmdline->ATTR = config->ATTR; \
142 }
143
144 COPY_ATTR(use_environment);
145 COPY_ATTR(isolated);
146
147#undef COPY_ATTR
148}
149
150
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100151void
152_PyPreCmdline_GetCoreConfig(_PyPreCmdline *cmdline, const _PyCoreConfig *config)
153{
154#define COPY_ATTR(ATTR) \
155 if (config->preconfig.ATTR != -1) { \
156 cmdline->ATTR = config->preconfig.ATTR; \
157 }
158
159 COPY_ATTR(use_environment);
160 COPY_ATTR(isolated);
161
162#undef COPY_ATTR
163}
164
165
166void
167_PyPreCmdline_SetCoreConfig(const _PyPreCmdline *cmdline, _PyCoreConfig *config)
168{
169#define COPY_ATTR(ATTR) \
170 if (config->preconfig.ATTR == -1 && cmdline->ATTR != -1) { \
171 config->preconfig.ATTR = cmdline->ATTR; \
172 }
173
174 COPY_ATTR(use_environment);
175 COPY_ATTR(isolated);
176
177#undef COPY_ATTR
178}
179
180
Victor Stinnercad1f742019-03-05 02:01:27 +0100181/* --- _PyPreConfig ----------------------------------------------- */
182
183void
184_PyPreConfig_Clear(_PyPreConfig *config)
185{
Victor Stinnerc656e252019-03-06 01:13:43 +0100186 PyMem_RawFree(config->allocator);
187 config->allocator = NULL;
Victor Stinnercad1f742019-03-05 02:01:27 +0100188}
189
190
191int
192_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
193{
194 _PyPreConfig_Clear(config);
195
196#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100197#define COPY_STR_ATTR(ATTR) \
198 do { \
199 if (config2->ATTR != NULL) { \
200 config->ATTR = _PyMem_RawStrdup(config2->ATTR); \
201 if (config->ATTR == NULL) { \
202 return -1; \
203 } \
204 } \
205 } while (0)
Victor Stinnercad1f742019-03-05 02:01:27 +0100206
207 COPY_ATTR(isolated);
208 COPY_ATTR(use_environment);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100209 COPY_ATTR(coerce_c_locale);
210 COPY_ATTR(coerce_c_locale_warn);
211#ifdef MS_WINDOWS
212 COPY_ATTR(legacy_windows_fs_encoding);
213#endif
214 COPY_ATTR(utf8_mode);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100215 COPY_ATTR(dev_mode);
216 COPY_STR_ATTR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100217
218#undef COPY_ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100219#undef COPY_STR_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100220 return 0;
221}
222
223
224void
225_PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
226{
227#define COPY_FLAG(ATTR, VALUE) \
228 if (config->ATTR == -1) { \
229 config->ATTR = VALUE; \
230 }
231#define COPY_NOT_FLAG(ATTR, VALUE) \
232 if (config->ATTR == -1) { \
233 config->ATTR = !(VALUE); \
234 }
235
236 COPY_FLAG(isolated, Py_IsolatedFlag);
237 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100238#ifdef MS_WINDOWS
239 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
240#endif
241 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100242
243#undef COPY_FLAG
244#undef COPY_NOT_FLAG
245}
246
247
248void
249_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
250{
251#define COPY_FLAG(ATTR, VAR) \
252 if (config->ATTR != -1) { \
253 VAR = config->ATTR; \
254 }
255#define COPY_NOT_FLAG(ATTR, VAR) \
256 if (config->ATTR != -1) { \
257 VAR = !config->ATTR; \
258 }
259
260 COPY_FLAG(isolated, Py_IsolatedFlag);
261 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100262#ifdef MS_WINDOWS
263 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
264#endif
265 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100266
267#undef COPY_FLAG
268#undef COPY_NOT_FLAG
269}
270
271
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100272const char*
273_PyPreConfig_GetEnv(const _PyPreConfig *config, const char *name)
274{
275 assert(config->use_environment >= 0);
276
277 if (!config->use_environment) {
278 return NULL;
279 }
280
281 const char *var = getenv(name);
282 if (var && var[0] != '\0') {
283 return var;
284 }
285 else {
286 return NULL;
287 }
288}
289
290
291int
292_Py_str_to_int(const char *str, int *result)
293{
294 const char *endptr = str;
295 errno = 0;
296 long value = strtol(str, (char **)&endptr, 10);
297 if (*endptr != '\0' || errno == ERANGE) {
298 return -1;
299 }
300 if (value < INT_MIN || value > INT_MAX) {
301 return -1;
302 }
303
304 *result = (int)value;
305 return 0;
306}
307
308
309void
310_Py_get_env_flag(_PyPreConfig *config, int *flag, const char *name)
311{
312 const char *var = _PyPreConfig_GetEnv(config, name);
313 if (!var) {
314 return;
315 }
316 int value;
317 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
318 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
319 value = 1;
320 }
321 if (*flag < value) {
322 *flag = value;
323 }
324}
325
326
327const wchar_t*
Victor Stinner74f65682019-03-15 15:08:05 +0100328_Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100329{
Victor Stinner74f65682019-03-15 15:08:05 +0100330 for (Py_ssize_t i=0; i < xoptions->length; i++) {
331 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100332 size_t len;
333 wchar_t *sep = wcschr(option, L'=');
334 if (sep != NULL) {
335 len = (sep - option);
336 }
337 else {
338 len = wcslen(option);
339 }
340 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
341 return option;
342 }
343 }
344 return NULL;
345}
346
347
348static _PyInitError
349preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
350{
351 const wchar_t *xopt;
352 if (cmdline) {
Victor Stinner74f65682019-03-15 15:08:05 +0100353 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100354 }
355 else {
356 xopt = NULL;
357 }
358 if (xopt) {
359 wchar_t *sep = wcschr(xopt, L'=');
360 if (sep) {
361 xopt = sep + 1;
362 if (wcscmp(xopt, L"1") == 0) {
363 config->utf8_mode = 1;
364 }
365 else if (wcscmp(xopt, L"0") == 0) {
366 config->utf8_mode = 0;
367 }
368 else {
369 return _Py_INIT_USER_ERR("invalid -X utf8 option value");
370 }
371 }
372 else {
373 config->utf8_mode = 1;
374 }
375 return _Py_INIT_OK();
376 }
377
378 const char *opt = _PyPreConfig_GetEnv(config, "PYTHONUTF8");
379 if (opt) {
380 if (strcmp(opt, "1") == 0) {
381 config->utf8_mode = 1;
382 }
383 else if (strcmp(opt, "0") == 0) {
384 config->utf8_mode = 0;
385 }
386 else {
387 return _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment "
388 "variable value");
389 }
390 return _Py_INIT_OK();
391 }
392
393 return _Py_INIT_OK();
394}
395
396
397static void
398preconfig_init_locale(_PyPreConfig *config)
399{
Victor Stinnerf72346c2019-03-25 17:54:58 +0100400 /* The C locale enables the C locale coercion (PEP 538) */
401 if (_Py_LegacyLocaleDetected()) {
402 config->coerce_c_locale = 2;
403 }
404 else {
405 config->coerce_c_locale = 0;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100406 }
407}
408
409
410static _PyInitError
Victor Stinnerf72346c2019-03-25 17:54:58 +0100411preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnercad1f742019-03-05 02:01:27 +0100412{
Victor Stinnerf72346c2019-03-25 17:54:58 +0100413 _PyInitError err;
414
415 err = _PyPreCmdline_Read(cmdline);
416 if (_Py_INIT_FAILED(err)) {
417 return err;
418 }
419
420 _PyPreCmdline_SetPreConfig(cmdline, config);
421
Victor Stinnercad1f742019-03-05 02:01:27 +0100422 _PyPreConfig_GetGlobalConfig(config);
423
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100424 /* isolated and use_environment */
Victor Stinnercad1f742019-03-05 02:01:27 +0100425 if (config->isolated > 0) {
426 config->use_environment = 0;
427 }
428
429 /* Default values */
430 if (config->use_environment < 0) {
431 config->use_environment = 0;
432 }
433
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100434 /* legacy_windows_fs_encoding, utf8_mode, coerce_c_locale */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100435 if (config->use_environment) {
436#ifdef MS_WINDOWS
437 _Py_get_env_flag(config, &config->legacy_windows_fs_encoding,
438 "PYTHONLEGACYWINDOWSFSENCODING");
439#endif
440
441 const char *env = _PyPreConfig_GetEnv(config, "PYTHONCOERCECLOCALE");
442 if (env) {
443 if (strcmp(env, "0") == 0) {
444 if (config->coerce_c_locale < 0) {
445 config->coerce_c_locale = 0;
446 }
447 }
448 else if (strcmp(env, "warn") == 0) {
449 config->coerce_c_locale_warn = 1;
450 }
451 else {
452 if (config->coerce_c_locale < 0) {
453 config->coerce_c_locale = 1;
454 }
455 }
456 }
457 }
458
459#ifdef MS_WINDOWS
460 if (config->legacy_windows_fs_encoding) {
461 config->utf8_mode = 0;
462 }
463#endif
464
465 if (config->utf8_mode < 0) {
Victor Stinnerf72346c2019-03-25 17:54:58 +0100466 err = preconfig_init_utf8_mode(config, cmdline);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100467 if (_Py_INIT_FAILED(err)) {
468 return err;
469 }
470 }
471
Victor Stinnerf72346c2019-03-25 17:54:58 +0100472 /* Test also if coerce_c_locale equals 1: PYTHONCOERCECLOCALE=1 doesn't
473 imply that the C locale is always coerced. It is only coerced if
474 if the LC_CTYPE locale is "C". */
475 if (config->coerce_c_locale != 0 && config->coerce_c_locale != 2) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100476 preconfig_init_locale(config);
477 }
478
479#ifndef MS_WINDOWS
480 if (config->utf8_mode < 0) {
481 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
482 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
483 if (ctype_loc != NULL
484 && (strcmp(ctype_loc, "C") == 0
485 || strcmp(ctype_loc, "POSIX") == 0))
486 {
487 config->utf8_mode = 1;
488 }
489 }
490#endif
491
492 if (config->coerce_c_locale < 0) {
493 config->coerce_c_locale = 0;
494 }
495 if (config->utf8_mode < 0) {
496 config->utf8_mode = 0;
497 }
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100498 if (config->coerce_c_locale < 0) {
499 config->coerce_c_locale = 0;
500 }
501
502 /* dev_mode */
Victor Stinner74f65682019-03-15 15:08:05 +0100503 if ((cmdline && _Py_get_xoption(&cmdline->xoptions, L"dev"))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100504 || _PyPreConfig_GetEnv(config, "PYTHONDEVMODE"))
505 {
506 config->dev_mode = 1;
507 }
508 if (config->dev_mode < 0) {
509 config->dev_mode = 0;
510 }
511
512 /* allocator */
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100513 if (config->allocator == NULL) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100514 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
515 over PYTHONDEV env var and "-X dev" command line option.
516 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
517 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100518 const char *allocator = _PyPreConfig_GetEnv(config, "PYTHONMALLOC");
519 if (allocator) {
520 config->allocator = _PyMem_RawStrdup(allocator);
521 if (config->allocator == NULL) {
522 return _Py_INIT_NO_MEMORY();
523 }
524 }
525 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100526
Victor Stinner25d13f32019-03-06 12:51:53 +0100527 if (config->dev_mode && config->allocator == NULL) {
528 config->allocator = _PyMem_RawStrdup("debug");
529 if (config->allocator == NULL) {
530 return _Py_INIT_NO_MEMORY();
531 }
532 }
533
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100534 assert(config->coerce_c_locale >= 0);
535 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100536 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100537 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100538 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100539
540 return _Py_INIT_OK();
541}
542
543
Victor Stinner4fffd382019-03-06 01:44:31 +0100544static _PyInitError
545get_ctype_locale(char **locale_p)
546{
547 const char *loc = setlocale(LC_CTYPE, NULL);
548 if (loc == NULL) {
549 return _Py_INIT_ERR("failed to LC_CTYPE locale");
550 }
551
552 char *copy = _PyMem_RawStrdup(loc);
553 if (copy == NULL) {
554 return _Py_INIT_NO_MEMORY();
555 }
556
557 *locale_p = copy;
558 return _Py_INIT_OK();
559}
560
561
Victor Stinnerfa153762019-03-20 04:25:38 +0100562void
563_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
564{
565#define COPY_ATTR(ATTR) \
566 if (cmdline->ATTR != -1) { \
567 config->ATTR = cmdline->ATTR; \
568 }
569
570 COPY_ATTR(use_environment);
571 COPY_ATTR(isolated);
572
573#undef COPY_ATTR
574}
575
576
Victor Stinnercad1f742019-03-05 02:01:27 +0100577int
578_PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict)
579{
580#define SET_ITEM(KEY, EXPR) \
581 do { \
582 PyObject *obj = (EXPR); \
583 if (obj == NULL) { \
584 goto fail; \
585 } \
586 int res = PyDict_SetItemString(dict, (KEY), obj); \
587 Py_DECREF(obj); \
588 if (res < 0) { \
589 goto fail; \
590 } \
591 } while (0)
592#define SET_ITEM_INT(ATTR) \
593 SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100594#define FROM_STRING(STR) \
595 ((STR != NULL) ? \
596 PyUnicode_FromString(STR) \
597 : (Py_INCREF(Py_None), Py_None))
598#define SET_ITEM_STR(ATTR) \
599 SET_ITEM(#ATTR, FROM_STRING(config->ATTR))
Victor Stinnercad1f742019-03-05 02:01:27 +0100600
601 SET_ITEM_INT(isolated);
602 SET_ITEM_INT(use_environment);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100603 SET_ITEM_INT(coerce_c_locale);
604 SET_ITEM_INT(coerce_c_locale_warn);
605 SET_ITEM_INT(utf8_mode);
606#ifdef MS_WINDOWS
607 SET_ITEM_INT(legacy_windows_fs_encoding);
608#endif
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100609 SET_ITEM_INT(dev_mode);
610 SET_ITEM_STR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100611 return 0;
612
613fail:
614 return -1;
615
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100616#undef FROM_STRING
Victor Stinnercad1f742019-03-05 02:01:27 +0100617#undef SET_ITEM
618#undef SET_ITEM_INT
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100619#undef SET_ITEM_STR
Victor Stinnercad1f742019-03-05 02:01:27 +0100620}
Victor Stinner6dcb5422019-03-05 02:44:12 +0100621
622
623/* Parse the command line arguments */
Victor Stinnerfa153762019-03-20 04:25:38 +0100624_PyInitError
625_PyPreCmdline_Read(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100626{
Victor Stinnerfa153762019-03-20 04:25:38 +0100627 _PyWstrList *argv = &cmdline->argv;
628
Victor Stinner6dcb5422019-03-05 02:44:12 +0100629 _PyOS_ResetGetOpt();
630 /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv()
631 is responsible for that */
632 _PyOS_opterr = 0;
633 do {
634 int longindex = -1;
Victor Stinnerfa153762019-03-20 04:25:38 +0100635 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100636
637 if (c == EOF || c == 'c' || c == 'm') {
638 break;
639 }
640
641 switch (c) {
642 case 'E':
Victor Stinnerfa153762019-03-20 04:25:38 +0100643 cmdline->use_environment = 0;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100644 break;
645
646 case 'I':
Victor Stinnerfa153762019-03-20 04:25:38 +0100647 cmdline->isolated = 1;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100648 break;
649
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100650 case 'X':
651 {
Victor Stinner74f65682019-03-15 15:08:05 +0100652 if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) {
653 return _Py_INIT_NO_MEMORY();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100654 }
655 break;
656 }
657
Victor Stinner6dcb5422019-03-05 02:44:12 +0100658 default:
659 /* ignore other argument:
660 handled by _PyCoreConfig_ReadFromArgv() */
661 break;
662 }
663 } while (1);
664
665 return _Py_INIT_OK();
666}
667
668
Victor Stinnerf72346c2019-03-25 17:54:58 +0100669/* Read the configuration from:
670
671 - environment variables
672 - Py_xxx global configuration variables
673 - the LC_CTYPE locale
674
675 See _PyPreConfig_ReadFromArgv() to parse also command line arguments. */
676_PyInitError
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100677_PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args,
678 const _PyCoreConfig *coreconfig)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100679{
680 _PyInitError err;
Victor Stinnerfa153762019-03-20 04:25:38 +0100681 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinnerf72346c2019-03-25 17:54:58 +0100682 char *old_loc = NULL;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100683
Victor Stinnerf72346c2019-03-25 17:54:58 +0100684 err = get_ctype_locale(&old_loc);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100685 if (_Py_INIT_FAILED(err)) {
686 goto done;
687 }
688
Victor Stinnerf72346c2019-03-25 17:54:58 +0100689 /* Set LC_CTYPE to the user preferred locale */
690 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100691
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100692 _PyPreConfig_GetGlobalConfig(config);
693
Victor Stinnerf72346c2019-03-25 17:54:58 +0100694 _PyPreCmdline_GetPreConfig(&cmdline, config);
695
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100696 if (coreconfig) {
697 _PyPreCmdline_GetCoreConfig(&cmdline, coreconfig);
698 if (config->dev_mode == -1) {
699 config->dev_mode = coreconfig->preconfig.dev_mode;
700 }
701 }
702
Victor Stinnerf72346c2019-03-25 17:54:58 +0100703 if (args) {
704 err = _PyPreCmdline_SetArgv(&cmdline, args);
705 if (_Py_INIT_FAILED(err)) {
706 goto done;
707 }
708 }
Victor Stinnerfa153762019-03-20 04:25:38 +0100709
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100710 err = preconfig_read(config, &cmdline);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100711
712done:
Victor Stinnerf72346c2019-03-25 17:54:58 +0100713 if (old_loc != NULL) {
714 setlocale(LC_CTYPE, old_loc);
715 PyMem_RawFree(old_loc);
716 }
Victor Stinnerfa153762019-03-20 04:25:38 +0100717 _PyPreCmdline_Clear(&cmdline);
Victor Stinnerf72346c2019-03-25 17:54:58 +0100718
Victor Stinner6dcb5422019-03-05 02:44:12 +0100719 return err;
720}
721
722
Victor Stinner4fffd382019-03-06 01:44:31 +0100723/* Read the configuration from:
724
725 - command line arguments
726 - environment variables
727 - Py_xxx global configuration variables
728 - the LC_CTYPE locale
729
730 See _PyPreConfig_ReadFromArgv() to parse also command line arguments. */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100731_PyInitError
732_PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
733{
734 _PyInitError err;
735
736 err = _PyRuntime_Initialize();
737 if (_Py_INIT_FAILED(err)) {
738 return err;
739 }
740
741 char *init_ctype_locale = NULL;
742 int init_utf8_mode = Py_UTF8Mode;
743#ifdef MS_WINDOWS
744 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
745#endif
746 _PyPreConfig save_config = _PyPreConfig_INIT;
747 int locale_coerced = 0;
748 int loops = 0;
749
Victor Stinner4fffd382019-03-06 01:44:31 +0100750 err = get_ctype_locale(&init_ctype_locale);
751 if (_Py_INIT_FAILED(err)) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100752 goto done;
753 }
754
Victor Stinnerf29084d2019-03-20 02:20:13 +0100755 _PyPreConfig_GetGlobalConfig(config);
756
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100757 if (_PyPreConfig_Copy(&save_config, config) < 0) {
758 err = _Py_INIT_NO_MEMORY();
759 goto done;
760 }
761
762 /* Set LC_CTYPE to the user preferred locale */
763 _Py_SetLocaleFromEnv(LC_CTYPE);
764
765 while (1) {
766 int utf8_mode = config->utf8_mode;
767
768 /* Watchdog to prevent an infinite loop */
769 loops++;
770 if (loops == 3) {
771 err = _Py_INIT_ERR("Encoding changed twice while "
772 "reading the configuration");
773 goto done;
774 }
775
776 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
777 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
778 Py_UTF8Mode = config->utf8_mode;
779#ifdef MS_WINDOWS
780 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
781#endif
782
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100783 err = _PyPreConfig_Read(config, args, NULL);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100784 if (_Py_INIT_FAILED(err)) {
785 goto done;
786 }
787
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100788 /* The legacy C locale assumes ASCII as the default text encoding, which
789 * causes problems not only for the CPython runtime, but also other
790 * components like GNU readline.
791 *
792 * Accordingly, when the CLI detects it, it attempts to coerce it to a
793 * more capable UTF-8 based alternative.
794 *
795 * See the documentation of the PYTHONCOERCECLOCALE setting for more
796 * details.
797 */
798 int encoding_changed = 0;
799 if (config->coerce_c_locale && !locale_coerced) {
800 locale_coerced = 1;
801 _Py_CoerceLegacyLocale(0);
802 encoding_changed = 1;
803 }
804
805 if (utf8_mode == -1) {
806 if (config->utf8_mode == 1) {
807 /* UTF-8 Mode enabled */
808 encoding_changed = 1;
809 }
810 }
811 else {
812 if (config->utf8_mode != utf8_mode) {
813 encoding_changed = 1;
814 }
815 }
816
817 if (!encoding_changed) {
818 break;
819 }
820
821 /* Reset the configuration before reading again the configuration,
822 just keep UTF-8 Mode value. */
823 int new_utf8_mode = config->utf8_mode;
824 int new_coerce_c_locale = config->coerce_c_locale;
825 if (_PyPreConfig_Copy(config, &save_config) < 0) {
826 err = _Py_INIT_NO_MEMORY();
827 goto done;
828 }
829 config->utf8_mode = new_utf8_mode;
830 config->coerce_c_locale = new_coerce_c_locale;
831
832 /* The encoding changed: read again the configuration
833 with the new encoding */
834 }
835 err = _Py_INIT_OK();
836
837done:
838 if (init_ctype_locale != NULL) {
839 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100840 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100841 }
842 _PyPreConfig_Clear(&save_config);
843 Py_UTF8Mode = init_utf8_mode ;
844#ifdef MS_WINDOWS
845 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
846#endif
847 return err;
848}
849
850
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100851static _PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100852_PyPreConfig_SetAllocator(_PyPreConfig *config)
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100853{
Victor Stinnerc656e252019-03-06 01:13:43 +0100854 assert(!_PyRuntime.core_initialized);
855
856 PyMemAllocatorEx old_alloc;
857 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
858
859 if (_PyMem_SetupAllocators(config->allocator) < 0) {
860 return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100861 }
Victor Stinnerc656e252019-03-06 01:13:43 +0100862
863 /* Copy the pre-configuration with the new allocator */
864 _PyPreConfig config2 = _PyPreConfig_INIT;
865 if (_PyPreConfig_Copy(&config2, config) < 0) {
866 _PyPreConfig_Clear(&config2);
867 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
868 return _Py_INIT_NO_MEMORY();
869 }
870
871 /* Free the old config and replace config with config2. Since config now
872 owns the data, don't free config2. */
873 PyMemAllocatorEx new_alloc;
874 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
875 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
876 _PyPreConfig_Clear(config);
877 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
878
879 *config = config2;
880
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100881 return _Py_INIT_OK();
882}
883
884
Victor Stinner4fffd382019-03-06 01:44:31 +0100885/* Write the pre-configuration:
886
887 - set the memory allocators
888 - set Py_xxx global configuration variables
889 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
890 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100891
892 If the memory allocator is changed, config is re-allocated with new
Victor Stinner4fffd382019-03-06 01:44:31 +0100893 allocator. So calling _PyPreConfig_Clear(config) is safe after this call.
894
895 Do nothing if called after Py_Initialize(): ignore the new
896 pre-configuration. */
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100897_PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100898_PyPreConfig_Write(_PyPreConfig *config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100899{
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100900 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100901 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100902 the new configuration. */
Victor Stinnerc656e252019-03-06 01:13:43 +0100903 return _Py_INIT_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100904 }
905
906 if (config->allocator != NULL) {
Victor Stinnerc656e252019-03-06 01:13:43 +0100907 _PyInitError err = _PyPreConfig_SetAllocator(config);
908 if (_Py_INIT_FAILED(err)) {
909 return err;
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100910 }
911 }
912
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100913 _PyPreConfig_SetGlobalConfig(config);
914
915 if (config->coerce_c_locale) {
916 _Py_CoerceLegacyLocale(config->coerce_c_locale_warn);
917 }
918
919 /* Set LC_CTYPE to the user preferred locale */
920 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100921
Victor Stinner6d5ee972019-03-23 12:05:43 +0100922 /* Write the new pre-configuration into _PyRuntime */
923 PyMemAllocatorEx old_alloc;
924 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
925 int res = _PyPreConfig_Copy(&_PyRuntime.preconfig, config);
926 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
927 if (res < 0) {
928 return _Py_INIT_NO_MEMORY();
929 }
930
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100931 return _Py_INIT_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100932}