blob: 7814ee08a63f914597d699866b04d44dbe62b24a [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(),
Victor Stinner709d23d2019-05-02 14:56:30 -040017 see also initfsencoding().
18
19 Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
20 are encoded to UTF-8. */
Victor Stinner91b9ecf2019-03-01 17:52:56 +010021const char *Py_FileSystemDefaultEncoding = NULL;
22int Py_HasFileSystemDefaultEncoding = 0;
23const char *Py_FileSystemDefaultEncodeErrors = NULL;
24int _Py_HasFileSystemDefaultEncodeErrors = 0;
25
26void
27_Py_ClearFileSystemEncoding(void)
28{
29 if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
30 PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
31 Py_FileSystemDefaultEncoding = NULL;
32 }
33 if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
34 PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
35 Py_FileSystemDefaultEncodeErrors = NULL;
36 }
37}
38
39
40/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
41 global configuration variables. */
42int
43_Py_SetFileSystemEncoding(const char *encoding, const char *errors)
44{
45 char *encoding2 = _PyMem_RawStrdup(encoding);
46 if (encoding2 == NULL) {
47 return -1;
48 }
49
50 char *errors2 = _PyMem_RawStrdup(errors);
51 if (errors2 == NULL) {
52 PyMem_RawFree(encoding2);
53 return -1;
54 }
55
56 _Py_ClearFileSystemEncoding();
57
58 Py_FileSystemDefaultEncoding = encoding2;
59 Py_HasFileSystemDefaultEncoding = 0;
60
61 Py_FileSystemDefaultEncodeErrors = errors2;
62 _Py_HasFileSystemDefaultEncodeErrors = 0;
63 return 0;
64}
65
66
67/* --- _PyArgv ---------------------------------------------------- */
68
Victor Stinnerf8ba6f52019-03-26 16:58:50 +010069/* Decode bytes_argv using Py_DecodeLocale() */
Victor Stinner91b9ecf2019-03-01 17:52:56 +010070_PyInitError
Victor Stinner74f65682019-03-15 15:08:05 +010071_PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list)
Victor Stinner91b9ecf2019-03-01 17:52:56 +010072{
Victor Stinner74f65682019-03-15 15:08:05 +010073 _PyWstrList wargv = _PyWstrList_INIT;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010074 if (args->use_bytes_argv) {
Victor Stinner74f65682019-03-15 15:08:05 +010075 size_t size = sizeof(wchar_t*) * args->argc;
76 wargv.items = (wchar_t **)PyMem_RawMalloc(size);
77 if (wargv.items == NULL) {
Victor Stinner91b9ecf2019-03-01 17:52:56 +010078 return _Py_INIT_NO_MEMORY();
79 }
80
Victor Stinner74f65682019-03-15 15:08:05 +010081 for (Py_ssize_t i = 0; i < args->argc; i++) {
Victor Stinner91b9ecf2019-03-01 17:52:56 +010082 size_t len;
83 wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
84 if (arg == NULL) {
Victor Stinner74f65682019-03-15 15:08:05 +010085 _PyWstrList_Clear(&wargv);
Victor Stinner91b9ecf2019-03-01 17:52:56 +010086 return DECODE_LOCALE_ERR("command line arguments",
87 (Py_ssize_t)len);
88 }
Victor Stinner74f65682019-03-15 15:08:05 +010089 wargv.items[i] = arg;
90 wargv.length++;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010091 }
Victor Stinner74f65682019-03-15 15:08:05 +010092
93 _PyWstrList_Clear(list);
94 *list = wargv;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010095 }
96 else {
Victor Stinner74f65682019-03-15 15:08:05 +010097 wargv.length = args->argc;
98 wargv.items = args->wchar_argv;
99 if (_PyWstrList_Copy(list, &wargv) < 0) {
100 return _Py_INIT_NO_MEMORY();
101 }
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100102 }
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100103 return _Py_INIT_OK();
104}
Victor Stinnercad1f742019-03-05 02:01:27 +0100105
106
Victor Stinner6dcb5422019-03-05 02:44:12 +0100107/* --- _PyPreCmdline ------------------------------------------------- */
108
Victor Stinnerfa153762019-03-20 04:25:38 +0100109void
110_PyPreCmdline_Clear(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100111{
Victor Stinner74f65682019-03-15 15:08:05 +0100112 _PyWstrList_Clear(&cmdline->argv);
113 _PyWstrList_Clear(&cmdline->xoptions);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100114}
115
116
Victor Stinnerfa153762019-03-20 04:25:38 +0100117_PyInitError
Victor Stinnerf72346c2019-03-25 17:54:58 +0100118_PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
Victor Stinnerfa153762019-03-20 04:25:38 +0100119{
120 return _PyArgv_AsWstrList(args, &cmdline->argv);
121}
122
123
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100124static void
Victor Stinnerf72346c2019-03-25 17:54:58 +0100125_PyPreCmdline_GetPreConfig(_PyPreCmdline *cmdline, const _PyPreConfig *config)
126{
127#define COPY_ATTR(ATTR) \
128 if (config->ATTR != -1) { \
129 cmdline->ATTR = config->ATTR; \
130 }
131
Victor Stinnerf72346c2019-03-25 17:54:58 +0100132 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100133 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100134 COPY_ATTR(dev_mode);
135
136#undef COPY_ATTR
137}
138
139
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100140static void
Victor Stinner20004952019-03-26 02:31:11 +0100141_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
142{
143#define COPY_ATTR(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100144 config->ATTR = cmdline->ATTR
Victor Stinner20004952019-03-26 02:31:11 +0100145
Victor Stinner20004952019-03-26 02:31:11 +0100146 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100147 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100148 COPY_ATTR(dev_mode);
Victor Stinnerf72346c2019-03-25 17:54:58 +0100149
150#undef COPY_ATTR
151}
152
153
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100154int
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100155_PyPreCmdline_SetCoreConfig(const _PyPreCmdline *cmdline, _PyCoreConfig *config)
156{
157#define COPY_ATTR(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100158 config->ATTR = cmdline->ATTR
159
160 if (_PyWstrList_Extend(&config->xoptions, &cmdline->xoptions) < 0) {
161 return -1;
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100162 }
163
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100164 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100165 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100166 COPY_ATTR(dev_mode);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100167 return 0;
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100168
169#undef COPY_ATTR
170}
171
172
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100173/* Parse the command line arguments */
174static _PyInitError
175precmdline_parse_cmdline(_PyPreCmdline *cmdline)
176{
Victor Stinner870b0352019-05-17 03:15:12 +0200177 const _PyWstrList *argv = &cmdline->argv;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100178
179 _PyOS_ResetGetOpt();
180 /* Don't log parsing errors into stderr here: _PyCoreConfig_Read()
181 is responsible for that */
182 _PyOS_opterr = 0;
183 do {
184 int longindex = -1;
185 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
186
187 if (c == EOF || c == 'c' || c == 'm') {
188 break;
189 }
190
191 switch (c) {
192 case 'E':
193 cmdline->use_environment = 0;
194 break;
195
196 case 'I':
197 cmdline->isolated = 1;
198 break;
199
200 case 'X':
201 {
202 if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) {
203 return _Py_INIT_NO_MEMORY();
204 }
205 break;
206 }
207
208 default:
209 /* ignore other argument:
210 handled by _PyCoreConfig_Read() */
211 break;
212 }
213 } while (1);
214
215 return _Py_INIT_OK();
216}
217
218
219_PyInitError
220_PyPreCmdline_Read(_PyPreCmdline *cmdline,
Victor Stinner5ac27a52019-03-27 13:40:14 +0100221 const _PyPreConfig *preconfig)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100222{
223 if (preconfig) {
224 _PyPreCmdline_GetPreConfig(cmdline, preconfig);
225 }
226
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100227 _PyInitError err = precmdline_parse_cmdline(cmdline);
228 if (_Py_INIT_FAILED(err)) {
229 return err;
230 }
231
232 /* isolated, use_environment */
233 if (cmdline->isolated < 0) {
234 cmdline->isolated = 0;
235 }
236 if (cmdline->isolated > 0) {
237 cmdline->use_environment = 0;
238 }
239 if (cmdline->use_environment < 0) {
240 cmdline->use_environment = 0;
241 }
242
243 /* dev_mode */
244 if ((cmdline && _Py_get_xoption(&cmdline->xoptions, L"dev"))
245 || _Py_GetEnv(cmdline->use_environment, "PYTHONDEVMODE"))
246 {
247 cmdline->dev_mode = 1;
248 }
249 if (cmdline->dev_mode < 0) {
250 cmdline->dev_mode = 0;
251 }
252
253 assert(cmdline->use_environment >= 0);
254 assert(cmdline->isolated >= 0);
255 assert(cmdline->dev_mode >= 0);
256
257 return _Py_INIT_OK();
258}
259
260
Victor Stinnercad1f742019-03-05 02:01:27 +0100261/* --- _PyPreConfig ----------------------------------------------- */
262
Victor Stinnercab5d072019-05-17 19:01:14 +0200263void
264_PyPreConfig_Init(_PyPreConfig *config)
265{
266 *config = _PyPreConfig_INIT;
267}
268
269
270void
271_PyPreConfig_InitPythonConfig(_PyPreConfig *config)
272{
273 _PyPreConfig_Init(config);
274
275 /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
276 depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE
277 environment variables. */
278 config->coerce_c_locale = -1;
279 config->coerce_c_locale_warn = -1;
280 config->utf8_mode = -1;
281}
282
283
284void
285_PyPreConfig_InitIsolatedConfig(_PyPreConfig *config)
286{
287 _PyPreConfig_Init(config);
288
289 config->isolated = 1;
290 config->use_environment = 0;
291#ifdef MS_WINDOWS
292 config->legacy_windows_fs_encoding = 0;
293#endif
294 config->utf8_mode = 0;
295 config->dev_mode = 0;
296}
297
298
Victor Stinnercad1f742019-03-05 02:01:27 +0100299int
300_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
301{
Victor Stinnercad1f742019-03-05 02:01:27 +0100302#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100303#define COPY_STR_ATTR(ATTR) \
304 do { \
305 if (config2->ATTR != NULL) { \
306 config->ATTR = _PyMem_RawStrdup(config2->ATTR); \
307 if (config->ATTR == NULL) { \
308 return -1; \
309 } \
310 } \
311 } while (0)
Victor Stinnercad1f742019-03-05 02:01:27 +0100312
313 COPY_ATTR(isolated);
314 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100315 COPY_ATTR(dev_mode);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100316 COPY_ATTR(coerce_c_locale);
317 COPY_ATTR(coerce_c_locale_warn);
318#ifdef MS_WINDOWS
319 COPY_ATTR(legacy_windows_fs_encoding);
320#endif
321 COPY_ATTR(utf8_mode);
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200322 COPY_ATTR(allocator);
Victor Stinnercad1f742019-03-05 02:01:27 +0100323
324#undef COPY_ATTR
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100325#undef COPY_STR_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100326 return 0;
327}
328
329
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100330PyObject*
331_PyPreConfig_AsDict(const _PyPreConfig *config)
332{
333 PyObject *dict;
334
335 dict = PyDict_New();
336 if (dict == NULL) {
337 return NULL;
338 }
339
340#define SET_ITEM(KEY, EXPR) \
341 do { \
342 PyObject *obj = (EXPR); \
343 if (obj == NULL) { \
344 goto fail; \
345 } \
346 int res = PyDict_SetItemString(dict, (KEY), obj); \
347 Py_DECREF(obj); \
348 if (res < 0) { \
349 goto fail; \
350 } \
351 } while (0)
352#define SET_ITEM_INT(ATTR) \
353 SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
354#define FROM_STRING(STR) \
355 ((STR != NULL) ? \
356 PyUnicode_FromString(STR) \
357 : (Py_INCREF(Py_None), Py_None))
358#define SET_ITEM_STR(ATTR) \
359 SET_ITEM(#ATTR, FROM_STRING(config->ATTR))
360
361 SET_ITEM_INT(isolated);
362 SET_ITEM_INT(use_environment);
363 SET_ITEM_INT(coerce_c_locale);
364 SET_ITEM_INT(coerce_c_locale_warn);
365 SET_ITEM_INT(utf8_mode);
366#ifdef MS_WINDOWS
367 SET_ITEM_INT(legacy_windows_fs_encoding);
368#endif
369 SET_ITEM_INT(dev_mode);
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200370 SET_ITEM_INT(allocator);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100371 return dict;
372
373fail:
374 Py_DECREF(dict);
375 return NULL;
376
377#undef FROM_STRING
378#undef SET_ITEM
379#undef SET_ITEM_INT
380#undef SET_ITEM_STR
381}
382
383
Victor Stinner5ac27a52019-03-27 13:40:14 +0100384void
Victor Stinnercab5d072019-05-17 19:01:14 +0200385_PyPreConfig_GetCoreConfig(_PyPreConfig *config,
Victor Stinner5ac27a52019-03-27 13:40:14 +0100386 const _PyCoreConfig *core_config)
387{
388#define COPY_ATTR(ATTR) \
389 if (core_config->ATTR != -1) { \
390 config->ATTR = core_config->ATTR; \
391 }
392
393 COPY_ATTR(isolated);
394 COPY_ATTR(use_environment);
395 COPY_ATTR(dev_mode);
396
397#undef COPY_ATTR
398}
399
400
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100401static void
Victor Stinnercad1f742019-03-05 02:01:27 +0100402_PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
403{
404#define COPY_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200405 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100406 config->ATTR = VALUE; \
407 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100408#define COPY_NOT_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200409 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100410 config->ATTR = !(VALUE); \
411 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100412
413 COPY_FLAG(isolated, Py_IsolatedFlag);
414 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100415#ifdef MS_WINDOWS
416 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
417#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200418 if (config->utf8_mode == -2) {
419 config->utf8_mode = Py_UTF8Mode;
Victor Stinnerd929f182019-03-27 18:28:46 +0100420 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100421
422#undef COPY_FLAG
423#undef COPY_NOT_FLAG
424}
425
426
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100427static void
Victor Stinnercad1f742019-03-05 02:01:27 +0100428_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
429{
430#define COPY_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200431 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100432 VAR = config->ATTR; \
433 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100434#define COPY_NOT_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200435 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100436 VAR = !config->ATTR; \
437 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100438
439 COPY_FLAG(isolated, Py_IsolatedFlag);
440 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100441#ifdef MS_WINDOWS
442 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
443#endif
444 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100445
446#undef COPY_FLAG
447#undef COPY_NOT_FLAG
448}
449
450
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100451const char*
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100452_Py_GetEnv(int use_environment, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100453{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100454 assert(use_environment >= 0);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100455
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100456 if (!use_environment) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100457 return NULL;
458 }
459
460 const char *var = getenv(name);
461 if (var && var[0] != '\0') {
462 return var;
463 }
464 else {
465 return NULL;
466 }
467}
468
469
470int
471_Py_str_to_int(const char *str, int *result)
472{
473 const char *endptr = str;
474 errno = 0;
475 long value = strtol(str, (char **)&endptr, 10);
476 if (*endptr != '\0' || errno == ERANGE) {
477 return -1;
478 }
479 if (value < INT_MIN || value > INT_MAX) {
480 return -1;
481 }
482
483 *result = (int)value;
484 return 0;
485}
486
487
488void
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100489_Py_get_env_flag(int use_environment, int *flag, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100490{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100491 const char *var = _Py_GetEnv(use_environment, name);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100492 if (!var) {
493 return;
494 }
495 int value;
496 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
497 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
498 value = 1;
499 }
500 if (*flag < value) {
501 *flag = value;
502 }
503}
504
505
506const wchar_t*
Victor Stinner74f65682019-03-15 15:08:05 +0100507_Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100508{
Victor Stinner74f65682019-03-15 15:08:05 +0100509 for (Py_ssize_t i=0; i < xoptions->length; i++) {
510 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100511 size_t len;
512 wchar_t *sep = wcschr(option, L'=');
513 if (sep != NULL) {
514 len = (sep - option);
515 }
516 else {
517 len = wcslen(option);
518 }
519 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
520 return option;
521 }
522 }
523 return NULL;
524}
525
526
527static _PyInitError
528preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
529{
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100530#ifdef MS_WINDOWS
531 if (config->legacy_windows_fs_encoding) {
532 config->utf8_mode = 0;
533 }
534#endif
535
536 if (config->utf8_mode >= 0) {
537 return _Py_INIT_OK();
538 }
539
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100540 const wchar_t *xopt;
541 if (cmdline) {
Victor Stinner74f65682019-03-15 15:08:05 +0100542 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100543 }
544 else {
545 xopt = NULL;
546 }
547 if (xopt) {
548 wchar_t *sep = wcschr(xopt, L'=');
549 if (sep) {
550 xopt = sep + 1;
551 if (wcscmp(xopt, L"1") == 0) {
552 config->utf8_mode = 1;
553 }
554 else if (wcscmp(xopt, L"0") == 0) {
555 config->utf8_mode = 0;
556 }
557 else {
Victor Stinnerdb719752019-05-01 05:35:33 +0200558 return _Py_INIT_ERR("invalid -X utf8 option value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100559 }
560 }
561 else {
562 config->utf8_mode = 1;
563 }
564 return _Py_INIT_OK();
565 }
566
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100567 const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100568 if (opt) {
569 if (strcmp(opt, "1") == 0) {
570 config->utf8_mode = 1;
571 }
572 else if (strcmp(opt, "0") == 0) {
573 config->utf8_mode = 0;
574 }
575 else {
Victor Stinnerdb719752019-05-01 05:35:33 +0200576 return _Py_INIT_ERR("invalid PYTHONUTF8 environment "
577 "variable value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100578 }
579 return _Py_INIT_OK();
580 }
581
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100582
583#ifndef MS_WINDOWS
584 if (config->utf8_mode < 0) {
585 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
586 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
587 if (ctype_loc != NULL
588 && (strcmp(ctype_loc, "C") == 0
589 || strcmp(ctype_loc, "POSIX") == 0))
590 {
591 config->utf8_mode = 1;
592 }
593 }
594#endif
595
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100596 if (config->utf8_mode < 0) {
597 config->utf8_mode = 0;
598 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100599 return _Py_INIT_OK();
600}
601
602
603static void
604preconfig_init_coerce_c_locale(_PyPreConfig *config)
605{
606 const char *env = _Py_GetEnv(config->use_environment, "PYTHONCOERCECLOCALE");
607 if (env) {
608 if (strcmp(env, "0") == 0) {
609 if (config->coerce_c_locale < 0) {
610 config->coerce_c_locale = 0;
611 }
612 }
613 else if (strcmp(env, "warn") == 0) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200614 if (config->coerce_c_locale_warn < 0) {
615 config->coerce_c_locale_warn = 1;
616 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100617 }
618 else {
619 if (config->coerce_c_locale < 0) {
620 config->coerce_c_locale = 1;
621 }
622 }
623 }
624
625 /* Test if coerce_c_locale equals to -1 or equals to 1:
626 PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.
627 It is only coerced if if the LC_CTYPE locale is "C". */
Victor Stinnercab5d072019-05-17 19:01:14 +0200628 if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) {
629 /* The C locale enables the C locale coercion (PEP 538) */
630 if (_Py_LegacyLocaleDetected()) {
631 config->coerce_c_locale = 2;
632 }
633 else {
634 config->coerce_c_locale = 0;
635 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100636 }
637
Victor Stinnercab5d072019-05-17 19:01:14 +0200638 if (config->coerce_c_locale_warn < 0) {
639 config->coerce_c_locale_warn = 0;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100640 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100641}
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100642
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100643
644static _PyInitError
645preconfig_init_allocator(_PyPreConfig *config)
646{
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200647 if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100648 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
649 over PYTHONDEV env var and "-X dev" command line option.
650 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
651 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200652 const char *envvar = _Py_GetEnv(config->use_environment, "PYTHONMALLOC");
653 if (envvar) {
654 if (_PyMem_GetAllocatorName(envvar, &config->allocator) < 0) {
655 return _Py_INIT_ERR("PYTHONMALLOC: unknown allocator");
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100656 }
657 }
658 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100659
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200660 if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
661 config->allocator = PYMEM_ALLOCATOR_DEBUG;
Victor Stinner25d13f32019-03-06 12:51:53 +0100662 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100663 return _Py_INIT_OK();
664}
665
666
667static _PyInitError
Victor Stinner5ac27a52019-03-27 13:40:14 +0100668preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100669{
670 _PyInitError err;
671
Victor Stinner5ac27a52019-03-27 13:40:14 +0100672 err = _PyPreCmdline_Read(cmdline, config);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100673 if (_Py_INIT_FAILED(err)) {
674 return err;
675 }
676
677 _PyPreCmdline_SetPreConfig(cmdline, config);
678
679 /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
680#ifdef MS_WINDOWS
681 _Py_get_env_flag(config->use_environment,
682 &config->legacy_windows_fs_encoding,
683 "PYTHONLEGACYWINDOWSFSENCODING");
684#endif
685
686 preconfig_init_coerce_c_locale(config);
687
688 err = preconfig_init_utf8_mode(config, cmdline);
689 if (_Py_INIT_FAILED(err)) {
690 return err;
691 }
692
693 /* allocator */
694 err = preconfig_init_allocator(config);
695 if (_Py_INIT_FAILED(err)) {
696 return err;
697 }
Victor Stinner25d13f32019-03-06 12:51:53 +0100698
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100699 assert(config->coerce_c_locale >= 0);
Victor Stinnercab5d072019-05-17 19:01:14 +0200700 assert(config->coerce_c_locale_warn >= 0);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100701#ifdef MS_WINDOWS
702 assert(config->legacy_windows_fs_encoding >= 0);
703#endif
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100704 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100705 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100706 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100707 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100708
709 return _Py_INIT_OK();
710}
711
712
Victor Stinner4fffd382019-03-06 01:44:31 +0100713/* Read the configuration from:
714
715 - command line arguments
716 - environment variables
717 - Py_xxx global configuration variables
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100718 - the LC_CTYPE locale */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100719_PyInitError
Victor Stinner5ac27a52019-03-27 13:40:14 +0100720_PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100721{
722 _PyInitError err;
723
724 err = _PyRuntime_Initialize();
725 if (_Py_INIT_FAILED(err)) {
726 return err;
727 }
728
Victor Stinnerf29084d2019-03-20 02:20:13 +0100729 _PyPreConfig_GetGlobalConfig(config);
730
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100731 /* Copy LC_CTYPE locale, since it's modified later */
732 const char *loc = setlocale(LC_CTYPE, NULL);
733 if (loc == NULL) {
734 return _Py_INIT_ERR("failed to LC_CTYPE locale");
735 }
736 char *init_ctype_locale = _PyMem_RawStrdup(loc);
737 if (init_ctype_locale == NULL) {
738 return _Py_INIT_NO_MEMORY();
739 }
740
741 /* Save the config to be able to restore it if encodings change */
Victor Stinnercab5d072019-05-17 19:01:14 +0200742 _PyPreConfig save_config;
743 _PyPreConfig_Init(&save_config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100744 if (_PyPreConfig_Copy(&save_config, config) < 0) {
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100745 return _Py_INIT_NO_MEMORY();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100746 }
747
748 /* Set LC_CTYPE to the user preferred locale */
749 _Py_SetLocaleFromEnv(LC_CTYPE);
750
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100751 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinner6a8c3132019-04-05 11:44:04 +0200752 int init_utf8_mode = Py_UTF8Mode;
753#ifdef MS_WINDOWS
754 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
755#endif
756
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100757 if (args) {
758 err = _PyPreCmdline_SetArgv(&cmdline, args);
759 if (_Py_INIT_FAILED(err)) {
760 goto done;
761 }
762 }
763
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100764 int locale_coerced = 0;
765 int loops = 0;
766
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100767 while (1) {
768 int utf8_mode = config->utf8_mode;
769
770 /* Watchdog to prevent an infinite loop */
771 loops++;
772 if (loops == 3) {
773 err = _Py_INIT_ERR("Encoding changed twice while "
774 "reading the configuration");
775 goto done;
776 }
777
778 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
779 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
780 Py_UTF8Mode = config->utf8_mode;
781#ifdef MS_WINDOWS
782 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
783#endif
784
Victor Stinner5ac27a52019-03-27 13:40:14 +0100785 err = preconfig_read(config, &cmdline);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100786 if (_Py_INIT_FAILED(err)) {
787 goto done;
788 }
789
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100790 /* The legacy C locale assumes ASCII as the default text encoding, which
791 * causes problems not only for the CPython runtime, but also other
792 * components like GNU readline.
793 *
794 * Accordingly, when the CLI detects it, it attempts to coerce it to a
795 * more capable UTF-8 based alternative.
796 *
797 * See the documentation of the PYTHONCOERCECLOCALE setting for more
798 * details.
799 */
800 int encoding_changed = 0;
801 if (config->coerce_c_locale && !locale_coerced) {
802 locale_coerced = 1;
803 _Py_CoerceLegacyLocale(0);
804 encoding_changed = 1;
805 }
806
807 if (utf8_mode == -1) {
808 if (config->utf8_mode == 1) {
809 /* UTF-8 Mode enabled */
810 encoding_changed = 1;
811 }
812 }
813 else {
814 if (config->utf8_mode != utf8_mode) {
815 encoding_changed = 1;
816 }
817 }
818
819 if (!encoding_changed) {
820 break;
821 }
822
823 /* Reset the configuration before reading again the configuration,
824 just keep UTF-8 Mode value. */
825 int new_utf8_mode = config->utf8_mode;
826 int new_coerce_c_locale = config->coerce_c_locale;
827 if (_PyPreConfig_Copy(config, &save_config) < 0) {
828 err = _Py_INIT_NO_MEMORY();
829 goto done;
830 }
831 config->utf8_mode = new_utf8_mode;
832 config->coerce_c_locale = new_coerce_c_locale;
833
834 /* The encoding changed: read again the configuration
835 with the new encoding */
836 }
837 err = _Py_INIT_OK();
838
839done:
840 if (init_ctype_locale != NULL) {
841 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100842 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100843 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100844 Py_UTF8Mode = init_utf8_mode ;
845#ifdef MS_WINDOWS
846 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
847#endif
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100848 _PyPreCmdline_Clear(&cmdline);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100849 return err;
850}
851
852
Victor Stinner4fffd382019-03-06 01:44:31 +0100853/* Write the pre-configuration:
854
855 - set the memory allocators
856 - set Py_xxx global configuration variables
857 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
858 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100859
860 If the memory allocator is changed, config is re-allocated with new
Victor Stinner4fffd382019-03-06 01:44:31 +0100861 allocator. So calling _PyPreConfig_Clear(config) is safe after this call.
862
863 Do nothing if called after Py_Initialize(): ignore the new
864 pre-configuration. */
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100865_PyInitError
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200866_PyPreConfig_Write(const _PyPreConfig *config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100867{
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100868 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100869 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100870 the new configuration. */
Victor Stinnerc656e252019-03-06 01:13:43 +0100871 return _Py_INIT_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100872 }
873
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200874 if (config->allocator != PYMEM_ALLOCATOR_NOT_SET) {
875 if (_PyMem_SetupAllocators(config->allocator) < 0) {
876 return _Py_INIT_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100877 }
878 }
879
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100880 _PyPreConfig_SetGlobalConfig(config);
881
882 if (config->coerce_c_locale) {
883 _Py_CoerceLegacyLocale(config->coerce_c_locale_warn);
884 }
885
886 /* Set LC_CTYPE to the user preferred locale */
887 _Py_SetLocaleFromEnv(LC_CTYPE);
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100888
Victor Stinner6d5ee972019-03-23 12:05:43 +0100889 /* Write the new pre-configuration into _PyRuntime */
890 PyMemAllocatorEx old_alloc;
891 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
892 int res = _PyPreConfig_Copy(&_PyRuntime.preconfig, config);
893 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
894 if (res < 0) {
895 return _Py_INIT_NO_MEMORY();
896 }
897
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100898 return _Py_INIT_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100899}