blob: d336352d93c2c2196e5dd93c5062b90e3c94f4e3 [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);
Victor Stinner20004952019-03-26 02:31:11 +0100146 COPY_ATTR(dev_mode);
147
148#undef COPY_ATTR
149}
150
151
152void
153_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
154{
155#define COPY_ATTR(ATTR) \
156 if (cmdline->ATTR != -1) { \
157 config->ATTR = cmdline->ATTR; \
158 }
159
160 COPY_ATTR(use_environment);
161 COPY_ATTR(isolated);
162 COPY_ATTR(dev_mode);
Victor Stinnerf72346c2019-03-25 17:54:58 +0100163
164#undef COPY_ATTR
165}
166
167
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100168void
169_PyPreCmdline_GetCoreConfig(_PyPreCmdline *cmdline, const _PyCoreConfig *config)
170{
171#define COPY_ATTR(ATTR) \
Victor Stinner20004952019-03-26 02:31:11 +0100172 if (config->ATTR != -1) { \
173 cmdline->ATTR = config->ATTR; \
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100174 }
175
176 COPY_ATTR(use_environment);
177 COPY_ATTR(isolated);
Victor Stinner20004952019-03-26 02:31:11 +0100178 COPY_ATTR(dev_mode);
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100179
180#undef COPY_ATTR
181}
182
183
184void
185_PyPreCmdline_SetCoreConfig(const _PyPreCmdline *cmdline, _PyCoreConfig *config)
186{
187#define COPY_ATTR(ATTR) \
Victor Stinner20004952019-03-26 02:31:11 +0100188 if (config->ATTR == -1 && cmdline->ATTR != -1) { \
189 config->ATTR = cmdline->ATTR; \
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100190 }
191
192 COPY_ATTR(use_environment);
193 COPY_ATTR(isolated);
Victor Stinner20004952019-03-26 02:31:11 +0100194 COPY_ATTR(dev_mode);
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100195
196#undef COPY_ATTR
197}
198
199
Victor Stinnercad1f742019-03-05 02:01:27 +0100200/* --- _PyPreConfig ----------------------------------------------- */
201
202void
203_PyPreConfig_Clear(_PyPreConfig *config)
204{
Victor Stinnerc656e252019-03-06 01:13:43 +0100205 PyMem_RawFree(config->allocator);
206 config->allocator = NULL;
Victor Stinnercad1f742019-03-05 02:01:27 +0100207}
208
209
210int
211_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
212{
213 _PyPreConfig_Clear(config);
214
215#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100216#define COPY_STR_ATTR(ATTR) \
217 do { \
218 if (config2->ATTR != NULL) { \
219 config->ATTR = _PyMem_RawStrdup(config2->ATTR); \
220 if (config->ATTR == NULL) { \
221 return -1; \
222 } \
223 } \
224 } while (0)
Victor Stinnercad1f742019-03-05 02:01:27 +0100225
226 COPY_ATTR(isolated);
227 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100228 COPY_ATTR(dev_mode);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100229 COPY_ATTR(coerce_c_locale);
230 COPY_ATTR(coerce_c_locale_warn);
231#ifdef MS_WINDOWS
232 COPY_ATTR(legacy_windows_fs_encoding);
233#endif
234 COPY_ATTR(utf8_mode);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100235 COPY_STR_ATTR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100236
237#undef COPY_ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100238#undef COPY_STR_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100239 return 0;
240}
241
242
243void
244_PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
245{
246#define COPY_FLAG(ATTR, VALUE) \
247 if (config->ATTR == -1) { \
248 config->ATTR = VALUE; \
249 }
250#define COPY_NOT_FLAG(ATTR, VALUE) \
251 if (config->ATTR == -1) { \
252 config->ATTR = !(VALUE); \
253 }
254
255 COPY_FLAG(isolated, Py_IsolatedFlag);
256 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100257#ifdef MS_WINDOWS
258 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
259#endif
260 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100261
262#undef COPY_FLAG
263#undef COPY_NOT_FLAG
264}
265
266
267void
268_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
269{
270#define COPY_FLAG(ATTR, VAR) \
271 if (config->ATTR != -1) { \
272 VAR = config->ATTR; \
273 }
274#define COPY_NOT_FLAG(ATTR, VAR) \
275 if (config->ATTR != -1) { \
276 VAR = !config->ATTR; \
277 }
278
279 COPY_FLAG(isolated, Py_IsolatedFlag);
280 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100281#ifdef MS_WINDOWS
282 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
283#endif
284 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100285
286#undef COPY_FLAG
287#undef COPY_NOT_FLAG
288}
289
290
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100291const char*
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100292_Py_GetEnv(int use_environment, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100293{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100294 assert(use_environment >= 0);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100295
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100296 if (!use_environment) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100297 return NULL;
298 }
299
300 const char *var = getenv(name);
301 if (var && var[0] != '\0') {
302 return var;
303 }
304 else {
305 return NULL;
306 }
307}
308
309
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100310static const char*
311_PyPreConfig_GetEnv(const _PyPreConfig *config, const char *name)
312{
313 return _Py_GetEnv(config->use_environment, name);
314}
315
316
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100317int
318_Py_str_to_int(const char *str, int *result)
319{
320 const char *endptr = str;
321 errno = 0;
322 long value = strtol(str, (char **)&endptr, 10);
323 if (*endptr != '\0' || errno == ERANGE) {
324 return -1;
325 }
326 if (value < INT_MIN || value > INT_MAX) {
327 return -1;
328 }
329
330 *result = (int)value;
331 return 0;
332}
333
334
335void
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100336_Py_get_env_flag(int use_environment, int *flag, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100337{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100338 const char *var = _Py_GetEnv(use_environment, name);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100339 if (!var) {
340 return;
341 }
342 int value;
343 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
344 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
345 value = 1;
346 }
347 if (*flag < value) {
348 *flag = value;
349 }
350}
351
352
353const wchar_t*
Victor Stinner74f65682019-03-15 15:08:05 +0100354_Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100355{
Victor Stinner74f65682019-03-15 15:08:05 +0100356 for (Py_ssize_t i=0; i < xoptions->length; i++) {
357 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100358 size_t len;
359 wchar_t *sep = wcschr(option, L'=');
360 if (sep != NULL) {
361 len = (sep - option);
362 }
363 else {
364 len = wcslen(option);
365 }
366 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
367 return option;
368 }
369 }
370 return NULL;
371}
372
373
374static _PyInitError
375preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
376{
377 const wchar_t *xopt;
378 if (cmdline) {
Victor Stinner74f65682019-03-15 15:08:05 +0100379 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100380 }
381 else {
382 xopt = NULL;
383 }
384 if (xopt) {
385 wchar_t *sep = wcschr(xopt, L'=');
386 if (sep) {
387 xopt = sep + 1;
388 if (wcscmp(xopt, L"1") == 0) {
389 config->utf8_mode = 1;
390 }
391 else if (wcscmp(xopt, L"0") == 0) {
392 config->utf8_mode = 0;
393 }
394 else {
395 return _Py_INIT_USER_ERR("invalid -X utf8 option value");
396 }
397 }
398 else {
399 config->utf8_mode = 1;
400 }
401 return _Py_INIT_OK();
402 }
403
404 const char *opt = _PyPreConfig_GetEnv(config, "PYTHONUTF8");
405 if (opt) {
406 if (strcmp(opt, "1") == 0) {
407 config->utf8_mode = 1;
408 }
409 else if (strcmp(opt, "0") == 0) {
410 config->utf8_mode = 0;
411 }
412 else {
413 return _Py_INIT_USER_ERR("invalid PYTHONUTF8 environment "
414 "variable value");
415 }
416 return _Py_INIT_OK();
417 }
418
419 return _Py_INIT_OK();
420}
421
422
423static void
424preconfig_init_locale(_PyPreConfig *config)
425{
Victor Stinnerf72346c2019-03-25 17:54:58 +0100426 /* The C locale enables the C locale coercion (PEP 538) */
427 if (_Py_LegacyLocaleDetected()) {
428 config->coerce_c_locale = 2;
429 }
430 else {
431 config->coerce_c_locale = 0;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100432 }
433}
434
435
436static _PyInitError
Victor Stinnerf72346c2019-03-25 17:54:58 +0100437preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnercad1f742019-03-05 02:01:27 +0100438{
Victor Stinnerf72346c2019-03-25 17:54:58 +0100439 _PyInitError err;
440
441 err = _PyPreCmdline_Read(cmdline);
442 if (_Py_INIT_FAILED(err)) {
443 return err;
444 }
445
446 _PyPreCmdline_SetPreConfig(cmdline, config);
447
Victor Stinnercad1f742019-03-05 02:01:27 +0100448 _PyPreConfig_GetGlobalConfig(config);
449
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100450 /* isolated and use_environment */
Victor Stinnercad1f742019-03-05 02:01:27 +0100451 if (config->isolated > 0) {
452 config->use_environment = 0;
453 }
454
455 /* Default values */
456 if (config->use_environment < 0) {
457 config->use_environment = 0;
458 }
459
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100460 /* legacy_windows_fs_encoding, utf8_mode, coerce_c_locale */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100461 if (config->use_environment) {
462#ifdef MS_WINDOWS
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100463 _Py_get_env_flag(config->use_environment,
464 &config->legacy_windows_fs_encoding,
465 "PYTHONLEGACYWINDOWSFSENCODING");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100466#endif
467
468 const char *env = _PyPreConfig_GetEnv(config, "PYTHONCOERCECLOCALE");
469 if (env) {
470 if (strcmp(env, "0") == 0) {
471 if (config->coerce_c_locale < 0) {
472 config->coerce_c_locale = 0;
473 }
474 }
475 else if (strcmp(env, "warn") == 0) {
476 config->coerce_c_locale_warn = 1;
477 }
478 else {
479 if (config->coerce_c_locale < 0) {
480 config->coerce_c_locale = 1;
481 }
482 }
483 }
484 }
485
486#ifdef MS_WINDOWS
487 if (config->legacy_windows_fs_encoding) {
488 config->utf8_mode = 0;
489 }
490#endif
491
492 if (config->utf8_mode < 0) {
Victor Stinnerf72346c2019-03-25 17:54:58 +0100493 err = preconfig_init_utf8_mode(config, cmdline);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100494 if (_Py_INIT_FAILED(err)) {
495 return err;
496 }
497 }
498
Victor Stinnerf72346c2019-03-25 17:54:58 +0100499 /* Test also if coerce_c_locale equals 1: PYTHONCOERCECLOCALE=1 doesn't
500 imply that the C locale is always coerced. It is only coerced if
501 if the LC_CTYPE locale is "C". */
502 if (config->coerce_c_locale != 0 && config->coerce_c_locale != 2) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100503 preconfig_init_locale(config);
504 }
505
506#ifndef MS_WINDOWS
507 if (config->utf8_mode < 0) {
508 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
509 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
510 if (ctype_loc != NULL
511 && (strcmp(ctype_loc, "C") == 0
512 || strcmp(ctype_loc, "POSIX") == 0))
513 {
514 config->utf8_mode = 1;
515 }
516 }
517#endif
518
519 if (config->coerce_c_locale < 0) {
520 config->coerce_c_locale = 0;
521 }
522 if (config->utf8_mode < 0) {
523 config->utf8_mode = 0;
524 }
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100525 if (config->coerce_c_locale < 0) {
526 config->coerce_c_locale = 0;
527 }
528
529 /* dev_mode */
Victor Stinner74f65682019-03-15 15:08:05 +0100530 if ((cmdline && _Py_get_xoption(&cmdline->xoptions, L"dev"))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100531 || _PyPreConfig_GetEnv(config, "PYTHONDEVMODE"))
532 {
533 config->dev_mode = 1;
534 }
535 if (config->dev_mode < 0) {
536 config->dev_mode = 0;
537 }
538
539 /* allocator */
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100540 if (config->allocator == NULL) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100541 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
542 over PYTHONDEV env var and "-X dev" command line option.
543 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
544 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100545 const char *allocator = _PyPreConfig_GetEnv(config, "PYTHONMALLOC");
546 if (allocator) {
547 config->allocator = _PyMem_RawStrdup(allocator);
548 if (config->allocator == NULL) {
549 return _Py_INIT_NO_MEMORY();
550 }
551 }
552 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100553
Victor Stinner25d13f32019-03-06 12:51:53 +0100554 if (config->dev_mode && config->allocator == NULL) {
555 config->allocator = _PyMem_RawStrdup("debug");
556 if (config->allocator == NULL) {
557 return _Py_INIT_NO_MEMORY();
558 }
559 }
560
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100561 assert(config->coerce_c_locale >= 0);
562 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100563 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100564 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100565 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100566
567 return _Py_INIT_OK();
568}
569
570
Victor Stinner4fffd382019-03-06 01:44:31 +0100571static _PyInitError
572get_ctype_locale(char **locale_p)
573{
574 const char *loc = setlocale(LC_CTYPE, NULL);
575 if (loc == NULL) {
576 return _Py_INIT_ERR("failed to LC_CTYPE locale");
577 }
578
579 char *copy = _PyMem_RawStrdup(loc);
580 if (copy == NULL) {
581 return _Py_INIT_NO_MEMORY();
582 }
583
584 *locale_p = copy;
585 return _Py_INIT_OK();
586}
587
588
Victor Stinner1075d162019-03-25 23:19:57 +0100589PyObject*
590_PyPreConfig_AsDict(const _PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100591{
Victor Stinner1075d162019-03-25 23:19:57 +0100592 PyObject *dict;
593
594 dict = PyDict_New();
595 if (dict == NULL) {
596 return NULL;
597 }
598
Victor Stinnercad1f742019-03-05 02:01:27 +0100599#define SET_ITEM(KEY, EXPR) \
600 do { \
601 PyObject *obj = (EXPR); \
602 if (obj == NULL) { \
603 goto fail; \
604 } \
605 int res = PyDict_SetItemString(dict, (KEY), obj); \
606 Py_DECREF(obj); \
607 if (res < 0) { \
608 goto fail; \
609 } \
610 } while (0)
611#define SET_ITEM_INT(ATTR) \
612 SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100613#define FROM_STRING(STR) \
614 ((STR != NULL) ? \
615 PyUnicode_FromString(STR) \
616 : (Py_INCREF(Py_None), Py_None))
617#define SET_ITEM_STR(ATTR) \
618 SET_ITEM(#ATTR, FROM_STRING(config->ATTR))
Victor Stinnercad1f742019-03-05 02:01:27 +0100619
620 SET_ITEM_INT(isolated);
621 SET_ITEM_INT(use_environment);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100622 SET_ITEM_INT(coerce_c_locale);
623 SET_ITEM_INT(coerce_c_locale_warn);
624 SET_ITEM_INT(utf8_mode);
625#ifdef MS_WINDOWS
626 SET_ITEM_INT(legacy_windows_fs_encoding);
627#endif
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100628 SET_ITEM_INT(dev_mode);
629 SET_ITEM_STR(allocator);
Victor Stinner1075d162019-03-25 23:19:57 +0100630 return dict;
Victor Stinnercad1f742019-03-05 02:01:27 +0100631
632fail:
Victor Stinner1075d162019-03-25 23:19:57 +0100633 Py_DECREF(dict);
634 return NULL;
Victor Stinnercad1f742019-03-05 02:01:27 +0100635
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100636#undef FROM_STRING
Victor Stinnercad1f742019-03-05 02:01:27 +0100637#undef SET_ITEM
638#undef SET_ITEM_INT
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100639#undef SET_ITEM_STR
Victor Stinnercad1f742019-03-05 02:01:27 +0100640}
Victor Stinner6dcb5422019-03-05 02:44:12 +0100641
642
643/* Parse the command line arguments */
Victor Stinnerfa153762019-03-20 04:25:38 +0100644_PyInitError
645_PyPreCmdline_Read(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100646{
Victor Stinnerfa153762019-03-20 04:25:38 +0100647 _PyWstrList *argv = &cmdline->argv;
648
Victor Stinner6dcb5422019-03-05 02:44:12 +0100649 _PyOS_ResetGetOpt();
650 /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv()
651 is responsible for that */
652 _PyOS_opterr = 0;
653 do {
654 int longindex = -1;
Victor Stinnerfa153762019-03-20 04:25:38 +0100655 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100656
657 if (c == EOF || c == 'c' || c == 'm') {
658 break;
659 }
660
661 switch (c) {
662 case 'E':
Victor Stinnerfa153762019-03-20 04:25:38 +0100663 cmdline->use_environment = 0;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100664 break;
665
666 case 'I':
Victor Stinnerfa153762019-03-20 04:25:38 +0100667 cmdline->isolated = 1;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100668 break;
669
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100670 case 'X':
671 {
Victor Stinner74f65682019-03-15 15:08:05 +0100672 if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) {
673 return _Py_INIT_NO_MEMORY();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100674 }
675 break;
676 }
677
Victor Stinner6dcb5422019-03-05 02:44:12 +0100678 default:
679 /* ignore other argument:
680 handled by _PyCoreConfig_ReadFromArgv() */
681 break;
682 }
683 } while (1);
684
685 return _Py_INIT_OK();
686}
687
688
Victor Stinnerf72346c2019-03-25 17:54:58 +0100689/* Read the configuration from:
690
691 - environment variables
692 - Py_xxx global configuration variables
693 - the LC_CTYPE locale
694
695 See _PyPreConfig_ReadFromArgv() to parse also command line arguments. */
696_PyInitError
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100697_PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args,
698 const _PyCoreConfig *coreconfig)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100699{
700 _PyInitError err;
Victor Stinnerfa153762019-03-20 04:25:38 +0100701 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinnerf72346c2019-03-25 17:54:58 +0100702 char *old_loc = NULL;
Victor Stinner6dcb5422019-03-05 02:44:12 +0100703
Victor Stinnerf72346c2019-03-25 17:54:58 +0100704 err = get_ctype_locale(&old_loc);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100705 if (_Py_INIT_FAILED(err)) {
706 goto done;
707 }
708
Victor Stinnerf72346c2019-03-25 17:54:58 +0100709 /* Set LC_CTYPE to the user preferred locale */
710 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100711
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100712 _PyPreConfig_GetGlobalConfig(config);
713
Victor Stinnerf72346c2019-03-25 17:54:58 +0100714 _PyPreCmdline_GetPreConfig(&cmdline, config);
715
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100716 if (coreconfig) {
717 _PyPreCmdline_GetCoreConfig(&cmdline, coreconfig);
718 if (config->dev_mode == -1) {
Victor Stinner20004952019-03-26 02:31:11 +0100719 config->dev_mode = coreconfig->dev_mode;
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100720 }
721 }
722
Victor Stinnerf72346c2019-03-25 17:54:58 +0100723 if (args) {
724 err = _PyPreCmdline_SetArgv(&cmdline, args);
725 if (_Py_INIT_FAILED(err)) {
726 goto done;
727 }
728 }
Victor Stinnerfa153762019-03-20 04:25:38 +0100729
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100730 err = preconfig_read(config, &cmdline);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100731
732done:
Victor Stinnerf72346c2019-03-25 17:54:58 +0100733 if (old_loc != NULL) {
734 setlocale(LC_CTYPE, old_loc);
735 PyMem_RawFree(old_loc);
736 }
Victor Stinnerfa153762019-03-20 04:25:38 +0100737 _PyPreCmdline_Clear(&cmdline);
Victor Stinnerf72346c2019-03-25 17:54:58 +0100738
Victor Stinner6dcb5422019-03-05 02:44:12 +0100739 return err;
740}
741
742
Victor Stinner4fffd382019-03-06 01:44:31 +0100743/* Read the configuration from:
744
745 - command line arguments
746 - environment variables
747 - Py_xxx global configuration variables
748 - the LC_CTYPE locale
749
750 See _PyPreConfig_ReadFromArgv() to parse also command line arguments. */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100751_PyInitError
752_PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
753{
754 _PyInitError err;
755
756 err = _PyRuntime_Initialize();
757 if (_Py_INIT_FAILED(err)) {
758 return err;
759 }
760
761 char *init_ctype_locale = NULL;
762 int init_utf8_mode = Py_UTF8Mode;
763#ifdef MS_WINDOWS
764 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
765#endif
766 _PyPreConfig save_config = _PyPreConfig_INIT;
767 int locale_coerced = 0;
768 int loops = 0;
769
Victor Stinner4fffd382019-03-06 01:44:31 +0100770 err = get_ctype_locale(&init_ctype_locale);
771 if (_Py_INIT_FAILED(err)) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100772 goto done;
773 }
774
Victor Stinnerf29084d2019-03-20 02:20:13 +0100775 _PyPreConfig_GetGlobalConfig(config);
776
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100777 if (_PyPreConfig_Copy(&save_config, config) < 0) {
778 err = _Py_INIT_NO_MEMORY();
779 goto done;
780 }
781
782 /* Set LC_CTYPE to the user preferred locale */
783 _Py_SetLocaleFromEnv(LC_CTYPE);
784
785 while (1) {
786 int utf8_mode = config->utf8_mode;
787
788 /* Watchdog to prevent an infinite loop */
789 loops++;
790 if (loops == 3) {
791 err = _Py_INIT_ERR("Encoding changed twice while "
792 "reading the configuration");
793 goto done;
794 }
795
796 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
797 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
798 Py_UTF8Mode = config->utf8_mode;
799#ifdef MS_WINDOWS
800 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
801#endif
802
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100803 err = _PyPreConfig_Read(config, args, NULL);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100804 if (_Py_INIT_FAILED(err)) {
805 goto done;
806 }
807
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100808 /* The legacy C locale assumes ASCII as the default text encoding, which
809 * causes problems not only for the CPython runtime, but also other
810 * components like GNU readline.
811 *
812 * Accordingly, when the CLI detects it, it attempts to coerce it to a
813 * more capable UTF-8 based alternative.
814 *
815 * See the documentation of the PYTHONCOERCECLOCALE setting for more
816 * details.
817 */
818 int encoding_changed = 0;
819 if (config->coerce_c_locale && !locale_coerced) {
820 locale_coerced = 1;
821 _Py_CoerceLegacyLocale(0);
822 encoding_changed = 1;
823 }
824
825 if (utf8_mode == -1) {
826 if (config->utf8_mode == 1) {
827 /* UTF-8 Mode enabled */
828 encoding_changed = 1;
829 }
830 }
831 else {
832 if (config->utf8_mode != utf8_mode) {
833 encoding_changed = 1;
834 }
835 }
836
837 if (!encoding_changed) {
838 break;
839 }
840
841 /* Reset the configuration before reading again the configuration,
842 just keep UTF-8 Mode value. */
843 int new_utf8_mode = config->utf8_mode;
844 int new_coerce_c_locale = config->coerce_c_locale;
845 if (_PyPreConfig_Copy(config, &save_config) < 0) {
846 err = _Py_INIT_NO_MEMORY();
847 goto done;
848 }
849 config->utf8_mode = new_utf8_mode;
850 config->coerce_c_locale = new_coerce_c_locale;
851
852 /* The encoding changed: read again the configuration
853 with the new encoding */
854 }
855 err = _Py_INIT_OK();
856
857done:
858 if (init_ctype_locale != NULL) {
859 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100860 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100861 }
862 _PyPreConfig_Clear(&save_config);
863 Py_UTF8Mode = init_utf8_mode ;
864#ifdef MS_WINDOWS
865 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
866#endif
867 return err;
868}
869
870
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100871static _PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100872_PyPreConfig_SetAllocator(_PyPreConfig *config)
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100873{
Victor Stinnerc656e252019-03-06 01:13:43 +0100874 assert(!_PyRuntime.core_initialized);
875
876 PyMemAllocatorEx old_alloc;
877 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
878
879 if (_PyMem_SetupAllocators(config->allocator) < 0) {
880 return _Py_INIT_USER_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100881 }
Victor Stinnerc656e252019-03-06 01:13:43 +0100882
883 /* Copy the pre-configuration with the new allocator */
884 _PyPreConfig config2 = _PyPreConfig_INIT;
885 if (_PyPreConfig_Copy(&config2, config) < 0) {
886 _PyPreConfig_Clear(&config2);
887 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
888 return _Py_INIT_NO_MEMORY();
889 }
890
891 /* Free the old config and replace config with config2. Since config now
892 owns the data, don't free config2. */
893 PyMemAllocatorEx new_alloc;
894 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
895 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
896 _PyPreConfig_Clear(config);
897 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
898
899 *config = config2;
900
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100901 return _Py_INIT_OK();
902}
903
904
Victor Stinner4fffd382019-03-06 01:44:31 +0100905/* Write the pre-configuration:
906
907 - set the memory allocators
908 - set Py_xxx global configuration variables
909 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
910 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100911
912 If the memory allocator is changed, config is re-allocated with new
Victor Stinner4fffd382019-03-06 01:44:31 +0100913 allocator. So calling _PyPreConfig_Clear(config) is safe after this call.
914
915 Do nothing if called after Py_Initialize(): ignore the new
916 pre-configuration. */
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100917_PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100918_PyPreConfig_Write(_PyPreConfig *config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100919{
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100920 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100921 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100922 the new configuration. */
Victor Stinnerc656e252019-03-06 01:13:43 +0100923 return _Py_INIT_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100924 }
925
926 if (config->allocator != NULL) {
Victor Stinnerc656e252019-03-06 01:13:43 +0100927 _PyInitError err = _PyPreConfig_SetAllocator(config);
928 if (_Py_INIT_FAILED(err)) {
929 return err;
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100930 }
931 }
932
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100933 _PyPreConfig_SetGlobalConfig(config);
934
935 if (config->coerce_c_locale) {
936 _Py_CoerceLegacyLocale(config->coerce_c_locale_warn);
937 }
938
939 /* Set LC_CTYPE to the user preferred locale */
940 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100941
Victor Stinner6d5ee972019-03-23 12:05:43 +0100942 /* Write the new pre-configuration into _PyRuntime */
943 PyMemAllocatorEx old_alloc;
944 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
945 int res = _PyPreConfig_Copy(&_PyRuntime.preconfig, config);
946 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
947 if (res < 0) {
948 return _Py_INIT_NO_MEMORY();
949 }
950
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100951 return _Py_INIT_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100952}