blob: 108cbc6660617631e38d074faaf1993beef7de7a [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) \
Victor Stinnerdb719752019-05-01 05:35:33 +020010 ? _Py_INIT_ERR("cannot decode " NAME) \
Victor Stinner91b9ecf2019-03-01 17:52:56 +010011 : _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
Victor Stinnerf8ba6f52019-03-26 16:58:50 +010066/* Decode bytes_argv using Py_DecodeLocale() */
Victor Stinner91b9ecf2019-03-01 17:52:56 +010067_PyInitError
Victor Stinner74f65682019-03-15 15:08:05 +010068_PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list)
Victor Stinner91b9ecf2019-03-01 17:52:56 +010069{
Victor Stinner74f65682019-03-15 15:08:05 +010070 _PyWstrList wargv = _PyWstrList_INIT;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010071 if (args->use_bytes_argv) {
Victor Stinner74f65682019-03-15 15:08:05 +010072 size_t size = sizeof(wchar_t*) * args->argc;
73 wargv.items = (wchar_t **)PyMem_RawMalloc(size);
74 if (wargv.items == NULL) {
Victor Stinner91b9ecf2019-03-01 17:52:56 +010075 return _Py_INIT_NO_MEMORY();
76 }
77
Victor Stinner74f65682019-03-15 15:08:05 +010078 for (Py_ssize_t i = 0; i < args->argc; i++) {
Victor Stinner91b9ecf2019-03-01 17:52:56 +010079 size_t len;
80 wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
81 if (arg == NULL) {
Victor Stinner74f65682019-03-15 15:08:05 +010082 _PyWstrList_Clear(&wargv);
Victor Stinner91b9ecf2019-03-01 17:52:56 +010083 return DECODE_LOCALE_ERR("command line arguments",
84 (Py_ssize_t)len);
85 }
Victor Stinner74f65682019-03-15 15:08:05 +010086 wargv.items[i] = arg;
87 wargv.length++;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010088 }
Victor Stinner74f65682019-03-15 15:08:05 +010089
90 _PyWstrList_Clear(list);
91 *list = wargv;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010092 }
93 else {
Victor Stinner74f65682019-03-15 15:08:05 +010094 wargv.length = args->argc;
95 wargv.items = args->wchar_argv;
96 if (_PyWstrList_Copy(list, &wargv) < 0) {
97 return _Py_INIT_NO_MEMORY();
98 }
Victor Stinner91b9ecf2019-03-01 17:52:56 +010099 }
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100100 return _Py_INIT_OK();
101}
Victor Stinnercad1f742019-03-05 02:01:27 +0100102
103
Victor Stinner6dcb5422019-03-05 02:44:12 +0100104/* --- _PyPreCmdline ------------------------------------------------- */
105
Victor Stinnerfa153762019-03-20 04:25:38 +0100106void
107_PyPreCmdline_Clear(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100108{
Victor Stinner74f65682019-03-15 15:08:05 +0100109 _PyWstrList_Clear(&cmdline->argv);
110 _PyWstrList_Clear(&cmdline->xoptions);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100111}
112
113
Victor Stinnerfa153762019-03-20 04:25:38 +0100114_PyInitError
Victor Stinnerf72346c2019-03-25 17:54:58 +0100115_PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
Victor Stinnerfa153762019-03-20 04:25:38 +0100116{
117 return _PyArgv_AsWstrList(args, &cmdline->argv);
118}
119
120
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100121static void
Victor Stinnerf72346c2019-03-25 17:54:58 +0100122_PyPreCmdline_GetPreConfig(_PyPreCmdline *cmdline, const _PyPreConfig *config)
123{
124#define COPY_ATTR(ATTR) \
125 if (config->ATTR != -1) { \
126 cmdline->ATTR = config->ATTR; \
127 }
128
Victor Stinnerf72346c2019-03-25 17:54:58 +0100129 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100130 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100131 COPY_ATTR(dev_mode);
132
133#undef COPY_ATTR
134}
135
136
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100137static void
Victor Stinner20004952019-03-26 02:31:11 +0100138_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
139{
140#define COPY_ATTR(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100141 config->ATTR = cmdline->ATTR
Victor Stinner20004952019-03-26 02:31:11 +0100142
Victor Stinner20004952019-03-26 02:31:11 +0100143 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100144 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100145 COPY_ATTR(dev_mode);
Victor Stinnerf72346c2019-03-25 17:54:58 +0100146
147#undef COPY_ATTR
148}
149
150
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100151int
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100152_PyPreCmdline_SetCoreConfig(const _PyPreCmdline *cmdline, _PyCoreConfig *config)
153{
154#define COPY_ATTR(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100155 config->ATTR = cmdline->ATTR
156
157 if (_PyWstrList_Extend(&config->xoptions, &cmdline->xoptions) < 0) {
158 return -1;
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100159 }
160
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100161 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100162 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100163 COPY_ATTR(dev_mode);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100164 return 0;
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100165
166#undef COPY_ATTR
167}
168
169
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100170/* Parse the command line arguments */
171static _PyInitError
172precmdline_parse_cmdline(_PyPreCmdline *cmdline)
173{
174 _PyWstrList *argv = &cmdline->argv;
175
176 _PyOS_ResetGetOpt();
177 /* Don't log parsing errors into stderr here: _PyCoreConfig_Read()
178 is responsible for that */
179 _PyOS_opterr = 0;
180 do {
181 int longindex = -1;
182 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
183
184 if (c == EOF || c == 'c' || c == 'm') {
185 break;
186 }
187
188 switch (c) {
189 case 'E':
190 cmdline->use_environment = 0;
191 break;
192
193 case 'I':
194 cmdline->isolated = 1;
195 break;
196
197 case 'X':
198 {
199 if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) {
200 return _Py_INIT_NO_MEMORY();
201 }
202 break;
203 }
204
205 default:
206 /* ignore other argument:
207 handled by _PyCoreConfig_Read() */
208 break;
209 }
210 } while (1);
211
212 return _Py_INIT_OK();
213}
214
215
216_PyInitError
217_PyPreCmdline_Read(_PyPreCmdline *cmdline,
Victor Stinner5ac27a52019-03-27 13:40:14 +0100218 const _PyPreConfig *preconfig)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100219{
220 if (preconfig) {
221 _PyPreCmdline_GetPreConfig(cmdline, preconfig);
222 }
223
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100224 _PyInitError err = precmdline_parse_cmdline(cmdline);
225 if (_Py_INIT_FAILED(err)) {
226 return err;
227 }
228
229 /* isolated, use_environment */
230 if (cmdline->isolated < 0) {
231 cmdline->isolated = 0;
232 }
233 if (cmdline->isolated > 0) {
234 cmdline->use_environment = 0;
235 }
236 if (cmdline->use_environment < 0) {
237 cmdline->use_environment = 0;
238 }
239
240 /* dev_mode */
241 if ((cmdline && _Py_get_xoption(&cmdline->xoptions, L"dev"))
242 || _Py_GetEnv(cmdline->use_environment, "PYTHONDEVMODE"))
243 {
244 cmdline->dev_mode = 1;
245 }
246 if (cmdline->dev_mode < 0) {
247 cmdline->dev_mode = 0;
248 }
249
250 assert(cmdline->use_environment >= 0);
251 assert(cmdline->isolated >= 0);
252 assert(cmdline->dev_mode >= 0);
253
254 return _Py_INIT_OK();
255}
256
257
Victor Stinnercad1f742019-03-05 02:01:27 +0100258/* --- _PyPreConfig ----------------------------------------------- */
259
260void
261_PyPreConfig_Clear(_PyPreConfig *config)
262{
Victor Stinnerc656e252019-03-06 01:13:43 +0100263 PyMem_RawFree(config->allocator);
264 config->allocator = NULL;
Victor Stinnercad1f742019-03-05 02:01:27 +0100265}
266
267
268int
269_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
270{
271 _PyPreConfig_Clear(config);
272
273#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100274#define COPY_STR_ATTR(ATTR) \
275 do { \
276 if (config2->ATTR != NULL) { \
277 config->ATTR = _PyMem_RawStrdup(config2->ATTR); \
278 if (config->ATTR == NULL) { \
279 return -1; \
280 } \
281 } \
282 } while (0)
Victor Stinnercad1f742019-03-05 02:01:27 +0100283
284 COPY_ATTR(isolated);
285 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100286 COPY_ATTR(dev_mode);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100287 COPY_ATTR(coerce_c_locale);
288 COPY_ATTR(coerce_c_locale_warn);
289#ifdef MS_WINDOWS
290 COPY_ATTR(legacy_windows_fs_encoding);
291#endif
292 COPY_ATTR(utf8_mode);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100293 COPY_STR_ATTR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100294
295#undef COPY_ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100296#undef COPY_STR_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100297 return 0;
298}
299
300
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100301PyObject*
302_PyPreConfig_AsDict(const _PyPreConfig *config)
303{
304 PyObject *dict;
305
306 dict = PyDict_New();
307 if (dict == NULL) {
308 return NULL;
309 }
310
311#define SET_ITEM(KEY, EXPR) \
312 do { \
313 PyObject *obj = (EXPR); \
314 if (obj == NULL) { \
315 goto fail; \
316 } \
317 int res = PyDict_SetItemString(dict, (KEY), obj); \
318 Py_DECREF(obj); \
319 if (res < 0) { \
320 goto fail; \
321 } \
322 } while (0)
323#define SET_ITEM_INT(ATTR) \
324 SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
325#define FROM_STRING(STR) \
326 ((STR != NULL) ? \
327 PyUnicode_FromString(STR) \
328 : (Py_INCREF(Py_None), Py_None))
329#define SET_ITEM_STR(ATTR) \
330 SET_ITEM(#ATTR, FROM_STRING(config->ATTR))
331
332 SET_ITEM_INT(isolated);
333 SET_ITEM_INT(use_environment);
334 SET_ITEM_INT(coerce_c_locale);
335 SET_ITEM_INT(coerce_c_locale_warn);
336 SET_ITEM_INT(utf8_mode);
337#ifdef MS_WINDOWS
338 SET_ITEM_INT(legacy_windows_fs_encoding);
339#endif
340 SET_ITEM_INT(dev_mode);
341 SET_ITEM_STR(allocator);
342 return dict;
343
344fail:
345 Py_DECREF(dict);
346 return NULL;
347
348#undef FROM_STRING
349#undef SET_ITEM
350#undef SET_ITEM_INT
351#undef SET_ITEM_STR
352}
353
354
Victor Stinner5ac27a52019-03-27 13:40:14 +0100355void
356_PyCoreConfig_GetCoreConfig(_PyPreConfig *config,
357 const _PyCoreConfig *core_config)
358{
359#define COPY_ATTR(ATTR) \
360 if (core_config->ATTR != -1) { \
361 config->ATTR = core_config->ATTR; \
362 }
363
364 COPY_ATTR(isolated);
365 COPY_ATTR(use_environment);
366 COPY_ATTR(dev_mode);
367
368#undef COPY_ATTR
369}
370
371
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100372static void
Victor Stinnercad1f742019-03-05 02:01:27 +0100373_PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
374{
375#define COPY_FLAG(ATTR, VALUE) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100376 if (config->ATTR == -1) { \
377 config->ATTR = VALUE; \
378 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100379#define COPY_NOT_FLAG(ATTR, VALUE) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100380 if (config->ATTR == -1) { \
381 config->ATTR = !(VALUE); \
382 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100383
384 COPY_FLAG(isolated, Py_IsolatedFlag);
385 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100386#ifdef MS_WINDOWS
387 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
388#endif
Victor Stinnerd929f182019-03-27 18:28:46 +0100389 if (Py_UTF8Mode > 0) {
390 config->utf8_mode = 1;
391 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100392
393#undef COPY_FLAG
394#undef COPY_NOT_FLAG
395}
396
397
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100398static void
Victor Stinnercad1f742019-03-05 02:01:27 +0100399_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
400{
401#define COPY_FLAG(ATTR, VAR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100402 if (config->ATTR != -1) { \
403 VAR = config->ATTR; \
404 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100405#define COPY_NOT_FLAG(ATTR, VAR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100406 if (config->ATTR != -1) { \
407 VAR = !config->ATTR; \
408 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100409
410 COPY_FLAG(isolated, Py_IsolatedFlag);
411 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100412#ifdef MS_WINDOWS
413 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
414#endif
415 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100416
417#undef COPY_FLAG
418#undef COPY_NOT_FLAG
419}
420
421
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100422const char*
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100423_Py_GetEnv(int use_environment, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100424{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100425 assert(use_environment >= 0);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100426
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100427 if (!use_environment) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100428 return NULL;
429 }
430
431 const char *var = getenv(name);
432 if (var && var[0] != '\0') {
433 return var;
434 }
435 else {
436 return NULL;
437 }
438}
439
440
441int
442_Py_str_to_int(const char *str, int *result)
443{
444 const char *endptr = str;
445 errno = 0;
446 long value = strtol(str, (char **)&endptr, 10);
447 if (*endptr != '\0' || errno == ERANGE) {
448 return -1;
449 }
450 if (value < INT_MIN || value > INT_MAX) {
451 return -1;
452 }
453
454 *result = (int)value;
455 return 0;
456}
457
458
459void
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100460_Py_get_env_flag(int use_environment, int *flag, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100461{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100462 const char *var = _Py_GetEnv(use_environment, name);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100463 if (!var) {
464 return;
465 }
466 int value;
467 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
468 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
469 value = 1;
470 }
471 if (*flag < value) {
472 *flag = value;
473 }
474}
475
476
477const wchar_t*
Victor Stinner74f65682019-03-15 15:08:05 +0100478_Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100479{
Victor Stinner74f65682019-03-15 15:08:05 +0100480 for (Py_ssize_t i=0; i < xoptions->length; i++) {
481 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100482 size_t len;
483 wchar_t *sep = wcschr(option, L'=');
484 if (sep != NULL) {
485 len = (sep - option);
486 }
487 else {
488 len = wcslen(option);
489 }
490 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
491 return option;
492 }
493 }
494 return NULL;
495}
496
497
498static _PyInitError
499preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
500{
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100501#ifdef MS_WINDOWS
502 if (config->legacy_windows_fs_encoding) {
503 config->utf8_mode = 0;
504 }
505#endif
506
507 if (config->utf8_mode >= 0) {
508 return _Py_INIT_OK();
509 }
510
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100511 const wchar_t *xopt;
512 if (cmdline) {
Victor Stinner74f65682019-03-15 15:08:05 +0100513 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100514 }
515 else {
516 xopt = NULL;
517 }
518 if (xopt) {
519 wchar_t *sep = wcschr(xopt, L'=');
520 if (sep) {
521 xopt = sep + 1;
522 if (wcscmp(xopt, L"1") == 0) {
523 config->utf8_mode = 1;
524 }
525 else if (wcscmp(xopt, L"0") == 0) {
526 config->utf8_mode = 0;
527 }
528 else {
Victor Stinnerdb719752019-05-01 05:35:33 +0200529 return _Py_INIT_ERR("invalid -X utf8 option value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100530 }
531 }
532 else {
533 config->utf8_mode = 1;
534 }
535 return _Py_INIT_OK();
536 }
537
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100538 const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100539 if (opt) {
540 if (strcmp(opt, "1") == 0) {
541 config->utf8_mode = 1;
542 }
543 else if (strcmp(opt, "0") == 0) {
544 config->utf8_mode = 0;
545 }
546 else {
Victor Stinnerdb719752019-05-01 05:35:33 +0200547 return _Py_INIT_ERR("invalid PYTHONUTF8 environment "
548 "variable value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100549 }
550 return _Py_INIT_OK();
551 }
552
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100553
554#ifndef MS_WINDOWS
555 if (config->utf8_mode < 0) {
556 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
557 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
558 if (ctype_loc != NULL
559 && (strcmp(ctype_loc, "C") == 0
560 || strcmp(ctype_loc, "POSIX") == 0))
561 {
562 config->utf8_mode = 1;
563 }
564 }
565#endif
566
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100567 if (config->utf8_mode < 0) {
568 config->utf8_mode = 0;
569 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100570 return _Py_INIT_OK();
571}
572
573
574static void
575preconfig_init_coerce_c_locale(_PyPreConfig *config)
576{
577 const char *env = _Py_GetEnv(config->use_environment, "PYTHONCOERCECLOCALE");
578 if (env) {
579 if (strcmp(env, "0") == 0) {
580 if (config->coerce_c_locale < 0) {
581 config->coerce_c_locale = 0;
582 }
583 }
584 else if (strcmp(env, "warn") == 0) {
585 config->coerce_c_locale_warn = 1;
586 }
587 else {
588 if (config->coerce_c_locale < 0) {
589 config->coerce_c_locale = 1;
590 }
591 }
592 }
593
594 /* Test if coerce_c_locale equals to -1 or equals to 1:
595 PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.
596 It is only coerced if if the LC_CTYPE locale is "C". */
597 if (config->coerce_c_locale == 0 || config->coerce_c_locale == 2) {
598 return;
599 }
600
601 /* The C locale enables the C locale coercion (PEP 538) */
602 if (_Py_LegacyLocaleDetected()) {
603 config->coerce_c_locale = 2;
604 }
605 else {
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100606 config->coerce_c_locale = 0;
607 }
608
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100609 assert(config->coerce_c_locale >= 0);
610}
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100611
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100612
613static _PyInitError
614preconfig_init_allocator(_PyPreConfig *config)
615{
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100616 if (config->allocator == NULL) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100617 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
618 over PYTHONDEV env var and "-X dev" command line option.
619 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
620 allocators to "malloc" (and not to "debug"). */
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100621 const char *allocator = _Py_GetEnv(config->use_environment, "PYTHONMALLOC");
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100622 if (allocator) {
623 config->allocator = _PyMem_RawStrdup(allocator);
624 if (config->allocator == NULL) {
625 return _Py_INIT_NO_MEMORY();
626 }
627 }
628 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100629
Victor Stinner25d13f32019-03-06 12:51:53 +0100630 if (config->dev_mode && config->allocator == NULL) {
631 config->allocator = _PyMem_RawStrdup("debug");
632 if (config->allocator == NULL) {
633 return _Py_INIT_NO_MEMORY();
634 }
635 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100636 return _Py_INIT_OK();
637}
638
639
640static _PyInitError
Victor Stinner5ac27a52019-03-27 13:40:14 +0100641preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100642{
643 _PyInitError err;
644
Victor Stinner5ac27a52019-03-27 13:40:14 +0100645 err = _PyPreCmdline_Read(cmdline, config);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100646 if (_Py_INIT_FAILED(err)) {
647 return err;
648 }
649
650 _PyPreCmdline_SetPreConfig(cmdline, config);
651
652 /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
653#ifdef MS_WINDOWS
654 _Py_get_env_flag(config->use_environment,
655 &config->legacy_windows_fs_encoding,
656 "PYTHONLEGACYWINDOWSFSENCODING");
657#endif
658
659 preconfig_init_coerce_c_locale(config);
660
661 err = preconfig_init_utf8_mode(config, cmdline);
662 if (_Py_INIT_FAILED(err)) {
663 return err;
664 }
665
666 /* allocator */
667 err = preconfig_init_allocator(config);
668 if (_Py_INIT_FAILED(err)) {
669 return err;
670 }
Victor Stinner25d13f32019-03-06 12:51:53 +0100671
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100672 assert(config->coerce_c_locale >= 0);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100673#ifdef MS_WINDOWS
674 assert(config->legacy_windows_fs_encoding >= 0);
675#endif
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100676 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100677 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100678 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100679 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100680
681 return _Py_INIT_OK();
682}
683
684
Victor Stinner4fffd382019-03-06 01:44:31 +0100685/* Read the configuration from:
686
687 - command line arguments
688 - environment variables
689 - Py_xxx global configuration variables
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100690 - the LC_CTYPE locale */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100691_PyInitError
Victor Stinner5ac27a52019-03-27 13:40:14 +0100692_PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100693{
694 _PyInitError err;
695
696 err = _PyRuntime_Initialize();
697 if (_Py_INIT_FAILED(err)) {
698 return err;
699 }
700
Victor Stinnerf29084d2019-03-20 02:20:13 +0100701 _PyPreConfig_GetGlobalConfig(config);
702
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100703 /* Copy LC_CTYPE locale, since it's modified later */
704 const char *loc = setlocale(LC_CTYPE, NULL);
705 if (loc == NULL) {
706 return _Py_INIT_ERR("failed to LC_CTYPE locale");
707 }
708 char *init_ctype_locale = _PyMem_RawStrdup(loc);
709 if (init_ctype_locale == NULL) {
710 return _Py_INIT_NO_MEMORY();
711 }
712
713 /* Save the config to be able to restore it if encodings change */
714 _PyPreConfig save_config = _PyPreConfig_INIT;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100715 if (_PyPreConfig_Copy(&save_config, config) < 0) {
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100716 return _Py_INIT_NO_MEMORY();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100717 }
718
719 /* Set LC_CTYPE to the user preferred locale */
720 _Py_SetLocaleFromEnv(LC_CTYPE);
721
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100722 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinner6a8c3132019-04-05 11:44:04 +0200723 int init_utf8_mode = Py_UTF8Mode;
724#ifdef MS_WINDOWS
725 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
726#endif
727
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100728 if (args) {
729 err = _PyPreCmdline_SetArgv(&cmdline, args);
730 if (_Py_INIT_FAILED(err)) {
731 goto done;
732 }
733 }
734
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100735 int locale_coerced = 0;
736 int loops = 0;
737
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100738 while (1) {
739 int utf8_mode = config->utf8_mode;
740
741 /* Watchdog to prevent an infinite loop */
742 loops++;
743 if (loops == 3) {
744 err = _Py_INIT_ERR("Encoding changed twice while "
745 "reading the configuration");
746 goto done;
747 }
748
749 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
750 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
751 Py_UTF8Mode = config->utf8_mode;
752#ifdef MS_WINDOWS
753 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
754#endif
755
Victor Stinner5ac27a52019-03-27 13:40:14 +0100756 err = preconfig_read(config, &cmdline);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100757 if (_Py_INIT_FAILED(err)) {
758 goto done;
759 }
760
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100761 /* The legacy C locale assumes ASCII as the default text encoding, which
762 * causes problems not only for the CPython runtime, but also other
763 * components like GNU readline.
764 *
765 * Accordingly, when the CLI detects it, it attempts to coerce it to a
766 * more capable UTF-8 based alternative.
767 *
768 * See the documentation of the PYTHONCOERCECLOCALE setting for more
769 * details.
770 */
771 int encoding_changed = 0;
772 if (config->coerce_c_locale && !locale_coerced) {
773 locale_coerced = 1;
774 _Py_CoerceLegacyLocale(0);
775 encoding_changed = 1;
776 }
777
778 if (utf8_mode == -1) {
779 if (config->utf8_mode == 1) {
780 /* UTF-8 Mode enabled */
781 encoding_changed = 1;
782 }
783 }
784 else {
785 if (config->utf8_mode != utf8_mode) {
786 encoding_changed = 1;
787 }
788 }
789
790 if (!encoding_changed) {
791 break;
792 }
793
794 /* Reset the configuration before reading again the configuration,
795 just keep UTF-8 Mode value. */
796 int new_utf8_mode = config->utf8_mode;
797 int new_coerce_c_locale = config->coerce_c_locale;
798 if (_PyPreConfig_Copy(config, &save_config) < 0) {
799 err = _Py_INIT_NO_MEMORY();
800 goto done;
801 }
802 config->utf8_mode = new_utf8_mode;
803 config->coerce_c_locale = new_coerce_c_locale;
804
805 /* The encoding changed: read again the configuration
806 with the new encoding */
807 }
808 err = _Py_INIT_OK();
809
810done:
811 if (init_ctype_locale != NULL) {
812 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100813 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100814 }
815 _PyPreConfig_Clear(&save_config);
816 Py_UTF8Mode = init_utf8_mode ;
817#ifdef MS_WINDOWS
818 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
819#endif
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100820 _PyPreCmdline_Clear(&cmdline);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100821 return err;
822}
823
824
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100825static _PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100826_PyPreConfig_SetAllocator(_PyPreConfig *config)
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100827{
Victor Stinnerc656e252019-03-06 01:13:43 +0100828 assert(!_PyRuntime.core_initialized);
829
830 PyMemAllocatorEx old_alloc;
831 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
832
833 if (_PyMem_SetupAllocators(config->allocator) < 0) {
Victor Stinnerdb719752019-05-01 05:35:33 +0200834 return _Py_INIT_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100835 }
Victor Stinnerc656e252019-03-06 01:13:43 +0100836
837 /* Copy the pre-configuration with the new allocator */
838 _PyPreConfig config2 = _PyPreConfig_INIT;
839 if (_PyPreConfig_Copy(&config2, config) < 0) {
840 _PyPreConfig_Clear(&config2);
841 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
842 return _Py_INIT_NO_MEMORY();
843 }
844
845 /* Free the old config and replace config with config2. Since config now
846 owns the data, don't free config2. */
847 PyMemAllocatorEx new_alloc;
848 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
849 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
850 _PyPreConfig_Clear(config);
851 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &new_alloc);
852
853 *config = config2;
854
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100855 return _Py_INIT_OK();
856}
857
858
Victor Stinner4fffd382019-03-06 01:44:31 +0100859/* Write the pre-configuration:
860
861 - set the memory allocators
862 - set Py_xxx global configuration variables
863 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
864 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100865
866 If the memory allocator is changed, config is re-allocated with new
Victor Stinner4fffd382019-03-06 01:44:31 +0100867 allocator. So calling _PyPreConfig_Clear(config) is safe after this call.
868
869 Do nothing if called after Py_Initialize(): ignore the new
870 pre-configuration. */
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100871_PyInitError
Victor Stinnerc656e252019-03-06 01:13:43 +0100872_PyPreConfig_Write(_PyPreConfig *config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100873{
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100874 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100875 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100876 the new configuration. */
Victor Stinnerc656e252019-03-06 01:13:43 +0100877 return _Py_INIT_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100878 }
879
880 if (config->allocator != NULL) {
Victor Stinnerc656e252019-03-06 01:13:43 +0100881 _PyInitError err = _PyPreConfig_SetAllocator(config);
882 if (_Py_INIT_FAILED(err)) {
883 return err;
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100884 }
885 }
886
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100887 _PyPreConfig_SetGlobalConfig(config);
888
889 if (config->coerce_c_locale) {
890 _Py_CoerceLegacyLocale(config->coerce_c_locale_warn);
891 }
892
893 /* Set LC_CTYPE to the user preferred locale */
894 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100895
Victor Stinner6d5ee972019-03-23 12:05:43 +0100896 /* Write the new pre-configuration into _PyRuntime */
897 PyMemAllocatorEx old_alloc;
898 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
899 int res = _PyPreConfig_Copy(&_PyRuntime.preconfig, config);
900 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
901 if (res < 0) {
902 return _Py_INIT_NO_MEMORY();
903 }
904
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100905 return _Py_INIT_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100906}