blob: 8b685ce42d044ee7265ec598968b82dbdf584c34 [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*
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100273_Py_GetEnv(int use_environment, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100274{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100275 assert(use_environment >= 0);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100276
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100277 if (!use_environment) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100278 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
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100291static const char*
292_PyPreConfig_GetEnv(const _PyPreConfig *config, const char *name)
293{
294 return _Py_GetEnv(config->use_environment, name);
295}
296
297
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100298int
299_Py_str_to_int(const char *str, int *result)
300{
301 const char *endptr = str;
302 errno = 0;
303 long value = strtol(str, (char **)&endptr, 10);
304 if (*endptr != '\0' || errno == ERANGE) {
305 return -1;
306 }
307 if (value < INT_MIN || value > INT_MAX) {
308 return -1;
309 }
310
311 *result = (int)value;
312 return 0;
313}
314
315
316void
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100317_Py_get_env_flag(int use_environment, int *flag, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100318{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100319 const char *var = _Py_GetEnv(use_environment, name);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100320 if (!var) {
321 return;
322 }
323 int value;
324 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
325 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
326 value = 1;
327 }
328 if (*flag < value) {
329 *flag = value;
330 }
331}
332
333
334const wchar_t*
Victor Stinner74f65682019-03-15 15:08:05 +0100335_Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100336{
Victor Stinner74f65682019-03-15 15:08:05 +0100337 for (Py_ssize_t i=0; i < xoptions->length; i++) {
338 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100339 size_t len;
340 wchar_t *sep = wcschr(option, L'=');
341 if (sep != NULL) {
342 len = (sep - option);
343 }
344 else {
345 len = wcslen(option);
346 }
347 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
348 return option;
349 }
350 }
351 return NULL;
352}
353
354
355static _PyInitError
356preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
357{
358 const wchar_t *xopt;
359 if (cmdline) {
Victor Stinner74f65682019-03-15 15:08:05 +0100360 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100361 }
362 else {
363 xopt = NULL;
364 }
365 if (xopt) {
366 wchar_t *sep = wcschr(xopt, L'=');
367 if (sep) {
368 xopt = sep + 1;
369 if (wcscmp(xopt, L"1") == 0) {
370 config->utf8_mode = 1;
371 }
372 else if (wcscmp(xopt, L"0") == 0) {
373 config->utf8_mode = 0;
374 }
375 else {
376 return _Py_INIT_USER_ERR("invalid -X utf8 option value");
377 }
378 }
379 else {
380 config->utf8_mode = 1;
381 }
382 return _Py_INIT_OK();
383 }
384
385 const char *opt = _PyPreConfig_GetEnv(config, "PYTHONUTF8");
386 if (opt) {
387 if (strcmp(opt, "1") == 0) {
388 config->utf8_mode = 1;
389 }
390 else if (strcmp(opt, "0") == 0) {
391 config->utf8_mode = 0;
392 }
393 else {
394 return _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment "
395 "variable value");
396 }
397 return _Py_INIT_OK();
398 }
399
400 return _Py_INIT_OK();
401}
402
403
404static void
405preconfig_init_locale(_PyPreConfig *config)
406{
Victor Stinnerf72346c2019-03-25 17:54:58 +0100407 /* The C locale enables the C locale coercion (PEP 538) */
408 if (_Py_LegacyLocaleDetected()) {
409 config->coerce_c_locale = 2;
410 }
411 else {
412 config->coerce_c_locale = 0;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100413 }
414}
415
416
417static _PyInitError
Victor Stinnerf72346c2019-03-25 17:54:58 +0100418preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnercad1f742019-03-05 02:01:27 +0100419{
Victor Stinnerf72346c2019-03-25 17:54:58 +0100420 _PyInitError err;
421
422 err = _PyPreCmdline_Read(cmdline);
423 if (_Py_INIT_FAILED(err)) {
424 return err;
425 }
426
427 _PyPreCmdline_SetPreConfig(cmdline, config);
428
Victor Stinnercad1f742019-03-05 02:01:27 +0100429 _PyPreConfig_GetGlobalConfig(config);
430
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100431 /* isolated and use_environment */
Victor Stinnercad1f742019-03-05 02:01:27 +0100432 if (config->isolated > 0) {
433 config->use_environment = 0;
434 }
435
436 /* Default values */
437 if (config->use_environment < 0) {
438 config->use_environment = 0;
439 }
440
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100441 /* legacy_windows_fs_encoding, utf8_mode, coerce_c_locale */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100442 if (config->use_environment) {
443#ifdef MS_WINDOWS
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100444 _Py_get_env_flag(config->use_environment,
445 &config->legacy_windows_fs_encoding,
446 "PYTHONLEGACYWINDOWSFSENCODING");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100447#endif
448
449 const char *env = _PyPreConfig_GetEnv(config, "PYTHONCOERCECLOCALE");
450 if (env) {
451 if (strcmp(env, "0") == 0) {
452 if (config->coerce_c_locale < 0) {
453 config->coerce_c_locale = 0;
454 }
455 }
456 else if (strcmp(env, "warn") == 0) {
457 config->coerce_c_locale_warn = 1;
458 }
459 else {
460 if (config->coerce_c_locale < 0) {
461 config->coerce_c_locale = 1;
462 }
463 }
464 }
465 }
466
467#ifdef MS_WINDOWS
468 if (config->legacy_windows_fs_encoding) {
469 config->utf8_mode = 0;
470 }
471#endif
472
473 if (config->utf8_mode < 0) {
Victor Stinnerf72346c2019-03-25 17:54:58 +0100474 err = preconfig_init_utf8_mode(config, cmdline);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100475 if (_Py_INIT_FAILED(err)) {
476 return err;
477 }
478 }
479
Victor Stinnerf72346c2019-03-25 17:54:58 +0100480 /* Test also if coerce_c_locale equals 1: PYTHONCOERCECLOCALE=1 doesn't
481 imply that the C locale is always coerced. It is only coerced if
482 if the LC_CTYPE locale is "C". */
483 if (config->coerce_c_locale != 0 && config->coerce_c_locale != 2) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100484 preconfig_init_locale(config);
485 }
486
487#ifndef MS_WINDOWS
488 if (config->utf8_mode < 0) {
489 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
490 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
491 if (ctype_loc != NULL
492 && (strcmp(ctype_loc, "C") == 0
493 || strcmp(ctype_loc, "POSIX") == 0))
494 {
495 config->utf8_mode = 1;
496 }
497 }
498#endif
499
500 if (config->coerce_c_locale < 0) {
501 config->coerce_c_locale = 0;
502 }
503 if (config->utf8_mode < 0) {
504 config->utf8_mode = 0;
505 }
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100506 if (config->coerce_c_locale < 0) {
507 config->coerce_c_locale = 0;
508 }
509
510 /* dev_mode */
Victor Stinner74f65682019-03-15 15:08:05 +0100511 if ((cmdline && _Py_get_xoption(&cmdline->xoptions, L"dev"))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100512 || _PyPreConfig_GetEnv(config, "PYTHONDEVMODE"))
513 {
514 config->dev_mode = 1;
515 }
516 if (config->dev_mode < 0) {
517 config->dev_mode = 0;
518 }
519
520 /* allocator */
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100521 if (config->allocator == NULL) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100522 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
523 over PYTHONDEV env var and "-X dev" command line option.
524 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
525 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100526 const char *allocator = _PyPreConfig_GetEnv(config, "PYTHONMALLOC");
527 if (allocator) {
528 config->allocator = _PyMem_RawStrdup(allocator);
529 if (config->allocator == NULL) {
530 return _Py_INIT_NO_MEMORY();
531 }
532 }
533 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100534
Victor Stinner25d13f32019-03-06 12:51:53 +0100535 if (config->dev_mode && config->allocator == NULL) {
536 config->allocator = _PyMem_RawStrdup("debug");
537 if (config->allocator == NULL) {
538 return _Py_INIT_NO_MEMORY();
539 }
540 }
541
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100542 assert(config->coerce_c_locale >= 0);
543 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100544 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100545 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100546 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100547
548 return _Py_INIT_OK();
549}
550
551
Victor Stinner4fffd382019-03-06 01:44:31 +0100552static _PyInitError
553get_ctype_locale(char **locale_p)
554{
555 const char *loc = setlocale(LC_CTYPE, NULL);
556 if (loc == NULL) {
557 return _Py_INIT_ERR("failed to LC_CTYPE locale");
558 }
559
560 char *copy = _PyMem_RawStrdup(loc);
561 if (copy == NULL) {
562 return _Py_INIT_NO_MEMORY();
563 }
564
565 *locale_p = copy;
566 return _Py_INIT_OK();
567}
568
569
Victor Stinnerfa153762019-03-20 04:25:38 +0100570void
571_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
572{
573#define COPY_ATTR(ATTR) \
574 if (cmdline->ATTR != -1) { \
575 config->ATTR = cmdline->ATTR; \
576 }
577
578 COPY_ATTR(use_environment);
579 COPY_ATTR(isolated);
580
581#undef COPY_ATTR
582}
583
584
Victor Stinner1075d162019-03-25 23:19:57 +0100585PyObject*
586_PyPreConfig_AsDict(const _PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100587{
Victor Stinner1075d162019-03-25 23:19:57 +0100588 PyObject *dict;
589
590 dict = PyDict_New();
591 if (dict == NULL) {
592 return NULL;
593 }
594
Victor Stinnercad1f742019-03-05 02:01:27 +0100595#define SET_ITEM(KEY, EXPR) \
596 do { \
597 PyObject *obj = (EXPR); \
598 if (obj == NULL) { \
599 goto fail; \
600 } \
601 int res = PyDict_SetItemString(dict, (KEY), obj); \
602 Py_DECREF(obj); \
603 if (res < 0) { \
604 goto fail; \
605 } \
606 } while (0)
607#define SET_ITEM_INT(ATTR) \
608 SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100609#define FROM_STRING(STR) \
610 ((STR != NULL) ? \
611 PyUnicode_FromString(STR) \
612 : (Py_INCREF(Py_None), Py_None))
613#define SET_ITEM_STR(ATTR) \
614 SET_ITEM(#ATTR, FROM_STRING(config->ATTR))
Victor Stinnercad1f742019-03-05 02:01:27 +0100615
616 SET_ITEM_INT(isolated);
617 SET_ITEM_INT(use_environment);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100618 SET_ITEM_INT(coerce_c_locale);
619 SET_ITEM_INT(coerce_c_locale_warn);
620 SET_ITEM_INT(utf8_mode);
621#ifdef MS_WINDOWS
622 SET_ITEM_INT(legacy_windows_fs_encoding);
623#endif
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100624 SET_ITEM_INT(dev_mode);
625 SET_ITEM_STR(allocator);
Victor Stinner1075d162019-03-25 23:19:57 +0100626 return dict;
Victor Stinnercad1f742019-03-05 02:01:27 +0100627
628fail:
Victor Stinner1075d162019-03-25 23:19:57 +0100629 Py_DECREF(dict);
630 return NULL;
Victor Stinnercad1f742019-03-05 02:01:27 +0100631
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100632#undef FROM_STRING
Victor Stinnercad1f742019-03-05 02:01:27 +0100633#undef SET_ITEM
634#undef SET_ITEM_INT
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100635#undef SET_ITEM_STR
Victor Stinnercad1f742019-03-05 02:01:27 +0100636}
Victor Stinner6dcb5422019-03-05 02:44:12 +0100637
638
639/* Parse the command line arguments */
Victor Stinnerfa153762019-03-20 04:25:38 +0100640_PyInitError
641_PyPreCmdline_Read(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100642{
Victor Stinnerfa153762019-03-20 04:25:38 +0100643 _PyWstrList *argv = &cmdline->argv;
644
Victor Stinner6dcb5422019-03-05 02:44:12 +0100645 _PyOS_ResetGetOpt();
646 /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv()
647 is responsible for that */
648 _PyOS_opterr = 0;
649 do {
650 int longindex = -1;
Victor Stinnerfa153762019-03-20 04:25:38 +0100651 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100652
653 if (c == EOF || c == 'c' || c == 'm') {
654 break;
655 }
656
657 switch (c) {
658 case 'E':
Victor Stinnerfa153762019-03-20 04:25:38 +0100659 cmdline->use_environment = 0;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100660 break;
661
662 case 'I':
Victor Stinnerfa153762019-03-20 04:25:38 +0100663 cmdline->isolated = 1;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100664 break;
665
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100666 case 'X':
667 {
Victor Stinner74f65682019-03-15 15:08:05 +0100668 if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) {
669 return _Py_INIT_NO_MEMORY();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100670 }
671 break;
672 }
673
Victor Stinner6dcb5422019-03-05 02:44:12 +0100674 default:
675 /* ignore other argument:
676 handled by _PyCoreConfig_ReadFromArgv() */
677 break;
678 }
679 } while (1);
680
681 return _Py_INIT_OK();
682}
683
684
Victor Stinnerf72346c2019-03-25 17:54:58 +0100685/* Read the configuration from:
686
687 - environment variables
688 - Py_xxx global configuration variables
689 - the LC_CTYPE locale
690
691 See _PyPreConfig_ReadFromArgv() to parse also command line arguments. */
692_PyInitError
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100693_PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args,
694 const _PyCoreConfig *coreconfig)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100695{
696 _PyInitError err;
Victor Stinnerfa153762019-03-20 04:25:38 +0100697 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinnerf72346c2019-03-25 17:54:58 +0100698 char *old_loc = NULL;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100699
Victor Stinnerf72346c2019-03-25 17:54:58 +0100700 err = get_ctype_locale(&old_loc);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100701 if (_Py_INIT_FAILED(err)) {
702 goto done;
703 }
704
Victor Stinnerf72346c2019-03-25 17:54:58 +0100705 /* Set LC_CTYPE to the user preferred locale */
706 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100707
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100708 _PyPreConfig_GetGlobalConfig(config);
709
Victor Stinnerf72346c2019-03-25 17:54:58 +0100710 _PyPreCmdline_GetPreConfig(&cmdline, config);
711
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100712 if (coreconfig) {
713 _PyPreCmdline_GetCoreConfig(&cmdline, coreconfig);
714 if (config->dev_mode == -1) {
715 config->dev_mode = coreconfig->preconfig.dev_mode;
716 }
717 }
718
Victor Stinnerf72346c2019-03-25 17:54:58 +0100719 if (args) {
720 err = _PyPreCmdline_SetArgv(&cmdline, args);
721 if (_Py_INIT_FAILED(err)) {
722 goto done;
723 }
724 }
Victor Stinnerfa153762019-03-20 04:25:38 +0100725
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100726 err = preconfig_read(config, &cmdline);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100727
728done:
Victor Stinnerf72346c2019-03-25 17:54:58 +0100729 if (old_loc != NULL) {
730 setlocale(LC_CTYPE, old_loc);
731 PyMem_RawFree(old_loc);
732 }
Victor Stinnerfa153762019-03-20 04:25:38 +0100733 _PyPreCmdline_Clear(&cmdline);
Victor Stinnerf72346c2019-03-25 17:54:58 +0100734
Victor Stinner6dcb5422019-03-05 02:44:12 +0100735 return err;
736}
737
738
Victor Stinner4fffd382019-03-06 01:44:31 +0100739/* Read the configuration from:
740
741 - command line arguments
742 - environment variables
743 - Py_xxx global configuration variables
744 - the LC_CTYPE locale
745
746 See _PyPreConfig_ReadFromArgv() to parse also command line arguments. */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100747_PyInitError
748_PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
749{
750 _PyInitError err;
751
752 err = _PyRuntime_Initialize();
753 if (_Py_INIT_FAILED(err)) {
754 return err;
755 }
756
757 char *init_ctype_locale = NULL;
758 int init_utf8_mode = Py_UTF8Mode;
759#ifdef MS_WINDOWS
760 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
761#endif
762 _PyPreConfig save_config = _PyPreConfig_INIT;
763 int locale_coerced = 0;
764 int loops = 0;
765
Victor Stinner4fffd382019-03-06 01:44:31 +0100766 err = get_ctype_locale(&init_ctype_locale);
767 if (_Py_INIT_FAILED(err)) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100768 goto done;
769 }
770
Victor Stinnerf29084d2019-03-20 02:20:13 +0100771 _PyPreConfig_GetGlobalConfig(config);
772
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100773 if (_PyPreConfig_Copy(&save_config, config) < 0) {
774 err = _Py_INIT_NO_MEMORY();
775 goto done;
776 }
777
778 /* Set LC_CTYPE to the user preferred locale */
779 _Py_SetLocaleFromEnv(LC_CTYPE);
780
781 while (1) {
782 int utf8_mode = config->utf8_mode;
783
784 /* Watchdog to prevent an infinite loop */
785 loops++;
786 if (loops == 3) {
787 err = _Py_INIT_ERR("Encoding changed twice while "
788 "reading the configuration");
789 goto done;
790 }
791
792 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
793 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
794 Py_UTF8Mode = config->utf8_mode;
795#ifdef MS_WINDOWS
796 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
797#endif
798
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100799 err = _PyPreConfig_Read(config, args, NULL);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100800 if (_Py_INIT_FAILED(err)) {
801 goto done;
802 }
803
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100804 /* The legacy C locale assumes ASCII as the default text encoding, which
805 * causes problems not only for the CPython runtime, but also other
806 * components like GNU readline.
807 *
808 * Accordingly, when the CLI detects it, it attempts to coerce it to a
809 * more capable UTF-8 based alternative.
810 *
811 * See the documentation of the PYTHONCOERCECLOCALE setting for more
812 * details.
813 */
814 int encoding_changed = 0;
815 if (config->coerce_c_locale && !locale_coerced) {
816 locale_coerced = 1;
817 _Py_CoerceLegacyLocale(0);
818 encoding_changed = 1;
819 }
820
821 if (utf8_mode == -1) {
822 if (config->utf8_mode == 1) {
823 /* UTF-8 Mode enabled */
824 encoding_changed = 1;
825 }
826 }
827 else {
828 if (config->utf8_mode != utf8_mode) {
829 encoding_changed = 1;
830 }
831 }
832
833 if (!encoding_changed) {
834 break;
835 }
836
837 /* Reset the configuration before reading again the configuration,
838 just keep UTF-8 Mode value. */
839 int new_utf8_mode = config->utf8_mode;
840 int new_coerce_c_locale = config->coerce_c_locale;
841 if (_PyPreConfig_Copy(config, &save_config) < 0) {
842 err = _Py_INIT_NO_MEMORY();
843 goto done;
844 }
845 config->utf8_mode = new_utf8_mode;
846 config->coerce_c_locale = new_coerce_c_locale;
847
848 /* The encoding changed: read again the configuration
849 with the new encoding */
850 }
851 err = _Py_INIT_OK();
852
853done:
854 if (init_ctype_locale != NULL) {
855 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100856 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100857 }
858 _PyPreConfig_Clear(&save_config);
859 Py_UTF8Mode = init_utf8_mode ;
860#ifdef MS_WINDOWS
861 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
862#endif
863 return err;
864}
865
866
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100867static _PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100868_PyPreConfig_SetAllocator(_PyPreConfig *config)
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100869{
Victor Stinnerc656e252019-03-06 01:13:43 +0100870 assert(!_PyRuntime.core_initialized);
871
872 PyMemAllocatorEx old_alloc;
873 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
874
875 if (_PyMem_SetupAllocators(config->allocator) < 0) {
876 return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100877 }
Victor Stinnerc656e252019-03-06 01:13:43 +0100878
879 /* Copy the pre-configuration with the new allocator */
880 _PyPreConfig config2 = _PyPreConfig_INIT;
881 if (_PyPreConfig_Copy(&config2, config) < 0) {
882 _PyPreConfig_Clear(&config2);
883 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
884 return _Py_INIT_NO_MEMORY();
885 }
886
887 /* Free the old config and replace config with config2. Since config now
888 owns the data, don't free config2. */
889 PyMemAllocatorEx new_alloc;
890 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
891 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
892 _PyPreConfig_Clear(config);
893 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
894
895 *config = config2;
896
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100897 return _Py_INIT_OK();
898}
899
900
Victor Stinner4fffd382019-03-06 01:44:31 +0100901/* Write the pre-configuration:
902
903 - set the memory allocators
904 - set Py_xxx global configuration variables
905 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
906 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100907
908 If the memory allocator is changed, config is re-allocated with new
Victor Stinner4fffd382019-03-06 01:44:31 +0100909 allocator. So calling _PyPreConfig_Clear(config) is safe after this call.
910
911 Do nothing if called after Py_Initialize(): ignore the new
912 pre-configuration. */
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100913_PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100914_PyPreConfig_Write(_PyPreConfig *config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100915{
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100916 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100917 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100918 the new configuration. */
Victor Stinnerc656e252019-03-06 01:13:43 +0100919 return _Py_INIT_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100920 }
921
922 if (config->allocator != NULL) {
Victor Stinnerc656e252019-03-06 01:13:43 +0100923 _PyInitError err = _PyPreConfig_SetAllocator(config);
924 if (_Py_INIT_FAILED(err)) {
925 return err;
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100926 }
927 }
928
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100929 _PyPreConfig_SetGlobalConfig(config);
930
931 if (config->coerce_c_locale) {
932 _Py_CoerceLegacyLocale(config->coerce_c_locale_warn);
933 }
934
935 /* Set LC_CTYPE to the user preferred locale */
936 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100937
Victor Stinner6d5ee972019-03-23 12:05:43 +0100938 /* Write the new pre-configuration into _PyRuntime */
939 PyMemAllocatorEx old_alloc;
940 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
941 int res = _PyPreConfig_Copy(&_PyRuntime.preconfig, config);
942 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
943 if (res < 0) {
944 return _Py_INIT_NO_MEMORY();
945 }
946
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100947 return _Py_INIT_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100948}