blob: 262738fa57da56f676ca55e43faf6545d070243b [file] [log] [blame]
Victor Stinner91b9ecf2019-03-01 17:52:56 +01001#include "Python.h"
Victor Stinner4f98f462020-04-15 04:01:58 +02002#include "pycore_getopt.h" // _PyOS_GetOpt()
3#include "pycore_initconfig.h" // _PyArgv
Victor Stinnerd9ea5ca2020-04-15 02:57:50 +02004#include "pycore_pymem.h" // _PyMem_GetAllocatorName()
5#include "pycore_runtime.h" // _PyRuntime_Initialize()
6#include <locale.h> // setlocale()
Victor Stinner91b9ecf2019-03-01 17:52:56 +01007
8
9#define DECODE_LOCALE_ERR(NAME, LEN) \
10 (((LEN) == -2) \
Victor Stinner331a6a52019-05-27 16:39:22 +020011 ? _PyStatus_ERR("cannot decode " NAME) \
12 : _PyStatus_NO_MEMORY())
13
14
15/* Forward declarations */
16static void
17preconfig_copy(PyPreConfig *config, const PyPreConfig *config2);
Victor Stinner91b9ecf2019-03-01 17:52:56 +010018
19
20/* --- File system encoding/errors -------------------------------- */
21
22/* The filesystem encoding is chosen by config_init_fs_encoding(),
Victor Stinner709d23d2019-05-02 14:56:30 -040023 see also initfsencoding().
24
25 Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
26 are encoded to UTF-8. */
Victor Stinner91b9ecf2019-03-01 17:52:56 +010027const char *Py_FileSystemDefaultEncoding = NULL;
28int Py_HasFileSystemDefaultEncoding = 0;
29const char *Py_FileSystemDefaultEncodeErrors = NULL;
30int _Py_HasFileSystemDefaultEncodeErrors = 0;
31
32void
33_Py_ClearFileSystemEncoding(void)
34{
35 if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
36 PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
37 Py_FileSystemDefaultEncoding = NULL;
38 }
39 if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
40 PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
41 Py_FileSystemDefaultEncodeErrors = NULL;
42 }
43}
44
45
46/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
47 global configuration variables. */
48int
49_Py_SetFileSystemEncoding(const char *encoding, const char *errors)
50{
51 char *encoding2 = _PyMem_RawStrdup(encoding);
52 if (encoding2 == NULL) {
53 return -1;
54 }
55
56 char *errors2 = _PyMem_RawStrdup(errors);
57 if (errors2 == NULL) {
58 PyMem_RawFree(encoding2);
59 return -1;
60 }
61
62 _Py_ClearFileSystemEncoding();
63
64 Py_FileSystemDefaultEncoding = encoding2;
65 Py_HasFileSystemDefaultEncoding = 0;
66
67 Py_FileSystemDefaultEncodeErrors = errors2;
68 _Py_HasFileSystemDefaultEncodeErrors = 0;
69 return 0;
70}
71
72
73/* --- _PyArgv ---------------------------------------------------- */
74
Victor Stinnerf8ba6f52019-03-26 16:58:50 +010075/* Decode bytes_argv using Py_DecodeLocale() */
Victor Stinner331a6a52019-05-27 16:39:22 +020076PyStatus
77_PyArgv_AsWstrList(const _PyArgv *args, PyWideStringList *list)
Victor Stinner91b9ecf2019-03-01 17:52:56 +010078{
Victor Stinnerfb4ae152019-09-30 01:40:17 +020079 PyWideStringList wargv = _PyWideStringList_INIT;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010080 if (args->use_bytes_argv) {
Victor Stinner74f65682019-03-15 15:08:05 +010081 size_t size = sizeof(wchar_t*) * args->argc;
82 wargv.items = (wchar_t **)PyMem_RawMalloc(size);
83 if (wargv.items == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +020084 return _PyStatus_NO_MEMORY();
Victor Stinner91b9ecf2019-03-01 17:52:56 +010085 }
86
Victor Stinner74f65682019-03-15 15:08:05 +010087 for (Py_ssize_t i = 0; i < args->argc; i++) {
Victor Stinner91b9ecf2019-03-01 17:52:56 +010088 size_t len;
89 wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
90 if (arg == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +020091 _PyWideStringList_Clear(&wargv);
Victor Stinner91b9ecf2019-03-01 17:52:56 +010092 return DECODE_LOCALE_ERR("command line arguments",
93 (Py_ssize_t)len);
94 }
Victor Stinner74f65682019-03-15 15:08:05 +010095 wargv.items[i] = arg;
96 wargv.length++;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010097 }
Victor Stinner74f65682019-03-15 15:08:05 +010098
Victor Stinner331a6a52019-05-27 16:39:22 +020099 _PyWideStringList_Clear(list);
Victor Stinner74f65682019-03-15 15:08:05 +0100100 *list = wargv;
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100101 }
102 else {
Victor Stinner74f65682019-03-15 15:08:05 +0100103 wargv.length = args->argc;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200104 wargv.items = (wchar_t **)args->wchar_argv;
Victor Stinner331a6a52019-05-27 16:39:22 +0200105 if (_PyWideStringList_Copy(list, &wargv) < 0) {
106 return _PyStatus_NO_MEMORY();
Victor Stinner74f65682019-03-15 15:08:05 +0100107 }
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100108 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200109 return _PyStatus_OK();
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100110}
Victor Stinnercad1f742019-03-05 02:01:27 +0100111
112
Victor Stinner6dcb5422019-03-05 02:44:12 +0100113/* --- _PyPreCmdline ------------------------------------------------- */
114
Victor Stinnerfa153762019-03-20 04:25:38 +0100115void
116_PyPreCmdline_Clear(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100117{
Victor Stinner331a6a52019-05-27 16:39:22 +0200118 _PyWideStringList_Clear(&cmdline->argv);
119 _PyWideStringList_Clear(&cmdline->xoptions);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100120}
121
122
Victor Stinner331a6a52019-05-27 16:39:22 +0200123PyStatus
Victor Stinnerf72346c2019-03-25 17:54:58 +0100124_PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
Victor Stinnerfa153762019-03-20 04:25:38 +0100125{
126 return _PyArgv_AsWstrList(args, &cmdline->argv);
127}
128
129
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100130static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200131precmdline_get_preconfig(_PyPreCmdline *cmdline, const PyPreConfig *config)
Victor Stinnerf72346c2019-03-25 17:54:58 +0100132{
133#define COPY_ATTR(ATTR) \
134 if (config->ATTR != -1) { \
135 cmdline->ATTR = config->ATTR; \
136 }
137
Victor Stinnerf72346c2019-03-25 17:54:58 +0100138 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100139 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100140 COPY_ATTR(dev_mode);
141
142#undef COPY_ATTR
143}
144
145
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100146static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200147precmdline_set_preconfig(const _PyPreCmdline *cmdline, PyPreConfig *config)
Victor Stinner20004952019-03-26 02:31:11 +0100148{
149#define COPY_ATTR(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100150 config->ATTR = cmdline->ATTR
Victor Stinner20004952019-03-26 02:31:11 +0100151
Victor Stinner20004952019-03-26 02:31:11 +0100152 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100153 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100154 COPY_ATTR(dev_mode);
Victor Stinnerf72346c2019-03-25 17:54:58 +0100155
156#undef COPY_ATTR
157}
158
159
Victor Stinner331a6a52019-05-27 16:39:22 +0200160PyStatus
161_PyPreCmdline_SetConfig(const _PyPreCmdline *cmdline, PyConfig *config)
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100162{
163#define COPY_ATTR(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100164 config->ATTR = cmdline->ATTR
165
Victor Stinner331a6a52019-05-27 16:39:22 +0200166 PyStatus status = _PyWideStringList_Extend(&config->xoptions, &cmdline->xoptions);
167 if (_PyStatus_EXCEPTION(status)) {
168 return status;
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100169 }
170
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100171 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100172 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100173 COPY_ATTR(dev_mode);
Victor Stinner331a6a52019-05-27 16:39:22 +0200174 return _PyStatus_OK();
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100175
176#undef COPY_ATTR
177}
178
179
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100180/* Parse the command line arguments */
Victor Stinner331a6a52019-05-27 16:39:22 +0200181static PyStatus
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100182precmdline_parse_cmdline(_PyPreCmdline *cmdline)
183{
Victor Stinner331a6a52019-05-27 16:39:22 +0200184 const PyWideStringList *argv = &cmdline->argv;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100185
186 _PyOS_ResetGetOpt();
Victor Stinner331a6a52019-05-27 16:39:22 +0200187 /* Don't log parsing errors into stderr here: PyConfig_Read()
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100188 is responsible for that */
189 _PyOS_opterr = 0;
190 do {
191 int longindex = -1;
192 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
193
194 if (c == EOF || c == 'c' || c == 'm') {
195 break;
196 }
197
198 switch (c) {
199 case 'E':
200 cmdline->use_environment = 0;
201 break;
202
203 case 'I':
204 cmdline->isolated = 1;
205 break;
206
207 case 'X':
208 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200209 PyStatus status = PyWideStringList_Append(&cmdline->xoptions,
210 _PyOS_optarg);
211 if (_PyStatus_EXCEPTION(status)) {
212 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100213 }
214 break;
215 }
216
217 default:
218 /* ignore other argument:
Victor Stinner331a6a52019-05-27 16:39:22 +0200219 handled by PyConfig_Read() */
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100220 break;
221 }
222 } while (1);
223
Victor Stinner331a6a52019-05-27 16:39:22 +0200224 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100225}
226
227
Victor Stinner331a6a52019-05-27 16:39:22 +0200228PyStatus
229_PyPreCmdline_Read(_PyPreCmdline *cmdline, const PyPreConfig *preconfig)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100230{
Victor Stinner331a6a52019-05-27 16:39:22 +0200231 precmdline_get_preconfig(cmdline, preconfig);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100232
Victor Stinner6d1c4672019-05-20 11:02:00 +0200233 if (preconfig->parse_argv) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200234 PyStatus status = precmdline_parse_cmdline(cmdline);
235 if (_PyStatus_EXCEPTION(status)) {
236 return status;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200237 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100238 }
239
240 /* isolated, use_environment */
241 if (cmdline->isolated < 0) {
242 cmdline->isolated = 0;
243 }
244 if (cmdline->isolated > 0) {
245 cmdline->use_environment = 0;
246 }
247 if (cmdline->use_environment < 0) {
248 cmdline->use_environment = 0;
249 }
250
251 /* dev_mode */
Victor Stinnerbab0db62019-05-18 03:21:27 +0200252 if ((cmdline->dev_mode < 0)
253 && (_Py_get_xoption(&cmdline->xoptions, L"dev")
254 || _Py_GetEnv(cmdline->use_environment, "PYTHONDEVMODE")))
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100255 {
256 cmdline->dev_mode = 1;
257 }
258 if (cmdline->dev_mode < 0) {
259 cmdline->dev_mode = 0;
260 }
261
262 assert(cmdline->use_environment >= 0);
263 assert(cmdline->isolated >= 0);
264 assert(cmdline->dev_mode >= 0);
265
Victor Stinner331a6a52019-05-27 16:39:22 +0200266 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100267}
268
269
Victor Stinner331a6a52019-05-27 16:39:22 +0200270/* --- PyPreConfig ----------------------------------------------- */
Victor Stinnercad1f742019-03-05 02:01:27 +0100271
Victor Stinnerbab0db62019-05-18 03:21:27 +0200272
Victor Stinner3c30a762019-10-01 10:56:37 +0200273void
Victor Stinner331a6a52019-05-27 16:39:22 +0200274_PyPreConfig_InitCompatConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200275{
Victor Stinnerbab0db62019-05-18 03:21:27 +0200276 memset(config, 0, sizeof(*config));
Victor Stinner441b10c2019-09-28 04:28:35 +0200277
Victor Stinner022be022019-05-22 23:58:50 +0200278 config->_config_init = (int)_PyConfig_INIT_COMPAT;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200279 config->parse_argv = 0;
Victor Stinnerbab0db62019-05-18 03:21:27 +0200280 config->isolated = -1;
281 config->use_environment = -1;
282 config->configure_locale = 1;
Victor Stinner20e1e252019-05-23 04:12:27 +0200283
284 /* bpo-36443: C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
285 are disabled by default using the Compat configuration.
286
287 Py_UTF8Mode=1 enables the UTF-8 mode. PYTHONUTF8 environment variable
288 is ignored (even if use_environment=1). */
289 config->utf8_mode = 0;
290 config->coerce_c_locale = 0;
291 config->coerce_c_locale_warn = 0;
292
Victor Stinnerbab0db62019-05-18 03:21:27 +0200293 config->dev_mode = -1;
294 config->allocator = PYMEM_ALLOCATOR_NOT_SET;
295#ifdef MS_WINDOWS
296 config->legacy_windows_fs_encoding = -1;
297#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200298}
299
300
Victor Stinner3c30a762019-10-01 10:56:37 +0200301void
Victor Stinner331a6a52019-05-27 16:39:22 +0200302PyPreConfig_InitPythonConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200303{
Victor Stinner3c30a762019-10-01 10:56:37 +0200304 _PyPreConfig_InitCompatConfig(config);
Victor Stinnercab5d072019-05-17 19:01:14 +0200305
Victor Stinner022be022019-05-22 23:58:50 +0200306 config->_config_init = (int)_PyConfig_INIT_PYTHON;
307 config->isolated = 0;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200308 config->parse_argv = 1;
Victor Stinner022be022019-05-22 23:58:50 +0200309 config->use_environment = 1;
Victor Stinnercab5d072019-05-17 19:01:14 +0200310 /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
311 depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE
312 environment variables. */
313 config->coerce_c_locale = -1;
314 config->coerce_c_locale_warn = -1;
315 config->utf8_mode = -1;
Victor Stinner022be022019-05-22 23:58:50 +0200316#ifdef MS_WINDOWS
317 config->legacy_windows_fs_encoding = 0;
318#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200319}
320
321
Victor Stinner3c30a762019-10-01 10:56:37 +0200322void
Victor Stinner331a6a52019-05-27 16:39:22 +0200323PyPreConfig_InitIsolatedConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200324{
Victor Stinner3c30a762019-10-01 10:56:37 +0200325 _PyPreConfig_InitCompatConfig(config);
Victor Stinnercab5d072019-05-17 19:01:14 +0200326
Victor Stinner022be022019-05-22 23:58:50 +0200327 config->_config_init = (int)_PyConfig_INIT_ISOLATED;
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200328 config->configure_locale = 0;
Victor Stinnercab5d072019-05-17 19:01:14 +0200329 config->isolated = 1;
330 config->use_environment = 0;
Victor Stinnerbab0db62019-05-18 03:21:27 +0200331 config->utf8_mode = 0;
332 config->dev_mode = 0;
Victor Stinnercab5d072019-05-17 19:01:14 +0200333#ifdef MS_WINDOWS
334 config->legacy_windows_fs_encoding = 0;
335#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200336}
337
338
Victor Stinner441b10c2019-09-28 04:28:35 +0200339PyStatus
Victor Stinner331a6a52019-05-27 16:39:22 +0200340_PyPreConfig_InitFromPreConfig(PyPreConfig *config,
341 const PyPreConfig *config2)
Victor Stinner6d1c4672019-05-20 11:02:00 +0200342{
Victor Stinner3c30a762019-10-01 10:56:37 +0200343 PyPreConfig_InitPythonConfig(config);
Victor Stinner331a6a52019-05-27 16:39:22 +0200344 preconfig_copy(config, config2);
Victor Stinner441b10c2019-09-28 04:28:35 +0200345 return _PyStatus_OK();
Victor Stinner6d1c4672019-05-20 11:02:00 +0200346}
347
348
Victor Stinner3c30a762019-10-01 10:56:37 +0200349void
Victor Stinner331a6a52019-05-27 16:39:22 +0200350_PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config)
Victor Stinner6d1c4672019-05-20 11:02:00 +0200351{
Victor Stinner331a6a52019-05-27 16:39:22 +0200352 _PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200353 switch (config_init) {
Victor Stinner022be022019-05-22 23:58:50 +0200354 case _PyConfig_INIT_PYTHON:
Victor Stinner3c30a762019-10-01 10:56:37 +0200355 PyPreConfig_InitPythonConfig(preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200356 break;
Victor Stinner022be022019-05-22 23:58:50 +0200357 case _PyConfig_INIT_ISOLATED:
Victor Stinner3c30a762019-10-01 10:56:37 +0200358 PyPreConfig_InitIsolatedConfig(preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200359 break;
Victor Stinner022be022019-05-22 23:58:50 +0200360 case _PyConfig_INIT_COMPAT:
Victor Stinner6d1c4672019-05-20 11:02:00 +0200361 default:
Victor Stinner3c30a762019-10-01 10:56:37 +0200362 _PyPreConfig_InitCompatConfig(preconfig);
Victor Stinner441b10c2019-09-28 04:28:35 +0200363 }
364
Victor Stinner331a6a52019-05-27 16:39:22 +0200365 _PyPreConfig_GetConfig(preconfig, config);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200366}
367
368
Victor Stinner331a6a52019-05-27 16:39:22 +0200369static void
370preconfig_copy(PyPreConfig *config, const PyPreConfig *config2)
Victor Stinnercad1f742019-03-05 02:01:27 +0100371{
Victor Stinnercad1f742019-03-05 02:01:27 +0100372#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
373
Victor Stinner20e1e252019-05-23 04:12:27 +0200374 COPY_ATTR(_config_init);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200375 COPY_ATTR(parse_argv);
Victor Stinnercad1f742019-03-05 02:01:27 +0100376 COPY_ATTR(isolated);
377 COPY_ATTR(use_environment);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200378 COPY_ATTR(configure_locale);
Victor Stinner20004952019-03-26 02:31:11 +0100379 COPY_ATTR(dev_mode);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100380 COPY_ATTR(coerce_c_locale);
381 COPY_ATTR(coerce_c_locale_warn);
Victor Stinnerb5947842019-05-18 00:38:16 +0200382 COPY_ATTR(utf8_mode);
383 COPY_ATTR(allocator);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100384#ifdef MS_WINDOWS
385 COPY_ATTR(legacy_windows_fs_encoding);
386#endif
Victor Stinnercad1f742019-03-05 02:01:27 +0100387
388#undef COPY_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100389}
390
391
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100392PyObject*
Victor Stinner331a6a52019-05-27 16:39:22 +0200393_PyPreConfig_AsDict(const PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100394{
395 PyObject *dict;
396
397 dict = PyDict_New();
398 if (dict == NULL) {
399 return NULL;
400 }
401
Victor Stinner6d1c4672019-05-20 11:02:00 +0200402#define SET_ITEM_INT(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100403 do { \
Victor Stinner6d1c4672019-05-20 11:02:00 +0200404 PyObject *obj = PyLong_FromLong(config->ATTR); \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100405 if (obj == NULL) { \
406 goto fail; \
407 } \
Victor Stinner6d1c4672019-05-20 11:02:00 +0200408 int res = PyDict_SetItemString(dict, #ATTR, obj); \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100409 Py_DECREF(obj); \
410 if (res < 0) { \
411 goto fail; \
412 } \
413 } while (0)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100414
Victor Stinner20e1e252019-05-23 04:12:27 +0200415 SET_ITEM_INT(_config_init);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200416 SET_ITEM_INT(parse_argv);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100417 SET_ITEM_INT(isolated);
418 SET_ITEM_INT(use_environment);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200419 SET_ITEM_INT(configure_locale);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100420 SET_ITEM_INT(coerce_c_locale);
421 SET_ITEM_INT(coerce_c_locale_warn);
422 SET_ITEM_INT(utf8_mode);
423#ifdef MS_WINDOWS
424 SET_ITEM_INT(legacy_windows_fs_encoding);
425#endif
426 SET_ITEM_INT(dev_mode);
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200427 SET_ITEM_INT(allocator);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100428 return dict;
429
430fail:
431 Py_DECREF(dict);
432 return NULL;
433
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100434#undef SET_ITEM_INT
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100435}
436
437
Victor Stinner5ac27a52019-03-27 13:40:14 +0100438void
Victor Stinner331a6a52019-05-27 16:39:22 +0200439_PyPreConfig_GetConfig(PyPreConfig *preconfig, const PyConfig *config)
Victor Stinner5ac27a52019-03-27 13:40:14 +0100440{
441#define COPY_ATTR(ATTR) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200442 if (config->ATTR != -1) { \
443 preconfig->ATTR = config->ATTR; \
Victor Stinner5ac27a52019-03-27 13:40:14 +0100444 }
445
Victor Stinner6d1c4672019-05-20 11:02:00 +0200446 COPY_ATTR(parse_argv);
Victor Stinner5ac27a52019-03-27 13:40:14 +0100447 COPY_ATTR(isolated);
448 COPY_ATTR(use_environment);
449 COPY_ATTR(dev_mode);
450
451#undef COPY_ATTR
452}
453
454
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100455static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200456preconfig_get_global_vars(PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100457{
Victor Stinner022be022019-05-22 23:58:50 +0200458 if (config->_config_init != _PyConfig_INIT_COMPAT) {
459 /* Python and Isolated configuration ignore global variables */
460 return;
461 }
462
Victor Stinnercad1f742019-03-05 02:01:27 +0100463#define COPY_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200464 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100465 config->ATTR = VALUE; \
466 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100467#define COPY_NOT_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200468 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100469 config->ATTR = !(VALUE); \
470 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100471
472 COPY_FLAG(isolated, Py_IsolatedFlag);
473 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner20e1e252019-05-23 04:12:27 +0200474 if (Py_UTF8Mode > 0) {
475 config->utf8_mode = Py_UTF8Mode;
476 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100477#ifdef MS_WINDOWS
478 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
479#endif
Victor Stinnercad1f742019-03-05 02:01:27 +0100480
481#undef COPY_FLAG
482#undef COPY_NOT_FLAG
483}
484
485
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100486static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200487preconfig_set_global_vars(const PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100488{
489#define COPY_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200490 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100491 VAR = config->ATTR; \
492 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100493#define COPY_NOT_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200494 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100495 VAR = !config->ATTR; \
496 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100497
498 COPY_FLAG(isolated, Py_IsolatedFlag);
499 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100500#ifdef MS_WINDOWS
501 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
502#endif
503 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100504
505#undef COPY_FLAG
506#undef COPY_NOT_FLAG
507}
508
509
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100510const char*
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100511_Py_GetEnv(int use_environment, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100512{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100513 assert(use_environment >= 0);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100514
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100515 if (!use_environment) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100516 return NULL;
517 }
518
519 const char *var = getenv(name);
520 if (var && var[0] != '\0') {
521 return var;
522 }
523 else {
524 return NULL;
525 }
526}
527
528
529int
530_Py_str_to_int(const char *str, int *result)
531{
532 const char *endptr = str;
533 errno = 0;
534 long value = strtol(str, (char **)&endptr, 10);
535 if (*endptr != '\0' || errno == ERANGE) {
536 return -1;
537 }
538 if (value < INT_MIN || value > INT_MAX) {
539 return -1;
540 }
541
542 *result = (int)value;
543 return 0;
544}
545
546
547void
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100548_Py_get_env_flag(int use_environment, int *flag, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100549{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100550 const char *var = _Py_GetEnv(use_environment, name);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100551 if (!var) {
552 return;
553 }
554 int value;
555 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
556 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
557 value = 1;
558 }
559 if (*flag < value) {
560 *flag = value;
561 }
562}
563
564
565const wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200566_Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100567{
Victor Stinner74f65682019-03-15 15:08:05 +0100568 for (Py_ssize_t i=0; i < xoptions->length; i++) {
569 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100570 size_t len;
571 wchar_t *sep = wcschr(option, L'=');
572 if (sep != NULL) {
573 len = (sep - option);
574 }
575 else {
576 len = wcslen(option);
577 }
578 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
579 return option;
580 }
581 }
582 return NULL;
583}
584
585
Victor Stinner331a6a52019-05-27 16:39:22 +0200586static PyStatus
587preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100588{
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100589#ifdef MS_WINDOWS
590 if (config->legacy_windows_fs_encoding) {
591 config->utf8_mode = 0;
592 }
593#endif
594
595 if (config->utf8_mode >= 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200596 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100597 }
598
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100599 const wchar_t *xopt;
Victor Stinner022be022019-05-22 23:58:50 +0200600 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100601 if (xopt) {
602 wchar_t *sep = wcschr(xopt, L'=');
603 if (sep) {
604 xopt = sep + 1;
605 if (wcscmp(xopt, L"1") == 0) {
606 config->utf8_mode = 1;
607 }
608 else if (wcscmp(xopt, L"0") == 0) {
609 config->utf8_mode = 0;
610 }
611 else {
Victor Stinner331a6a52019-05-27 16:39:22 +0200612 return _PyStatus_ERR("invalid -X utf8 option value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100613 }
614 }
615 else {
616 config->utf8_mode = 1;
617 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200618 return _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100619 }
620
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100621 const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100622 if (opt) {
623 if (strcmp(opt, "1") == 0) {
624 config->utf8_mode = 1;
625 }
626 else if (strcmp(opt, "0") == 0) {
627 config->utf8_mode = 0;
628 }
629 else {
Victor Stinner331a6a52019-05-27 16:39:22 +0200630 return _PyStatus_ERR("invalid PYTHONUTF8 environment "
Victor Stinnerdb719752019-05-01 05:35:33 +0200631 "variable value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100632 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200633 return _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100634 }
635
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100636
637#ifndef MS_WINDOWS
638 if (config->utf8_mode < 0) {
639 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
640 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
641 if (ctype_loc != NULL
642 && (strcmp(ctype_loc, "C") == 0
643 || strcmp(ctype_loc, "POSIX") == 0))
644 {
645 config->utf8_mode = 1;
646 }
647 }
648#endif
649
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100650 if (config->utf8_mode < 0) {
651 config->utf8_mode = 0;
652 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200653 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100654}
655
656
657static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200658preconfig_init_coerce_c_locale(PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100659{
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200660 if (!config->configure_locale) {
661 config->coerce_c_locale = 0;
662 config->coerce_c_locale_warn = 0;
663 return;
664 }
665
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100666 const char *env = _Py_GetEnv(config->use_environment, "PYTHONCOERCECLOCALE");
667 if (env) {
668 if (strcmp(env, "0") == 0) {
669 if (config->coerce_c_locale < 0) {
670 config->coerce_c_locale = 0;
671 }
672 }
673 else if (strcmp(env, "warn") == 0) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200674 if (config->coerce_c_locale_warn < 0) {
675 config->coerce_c_locale_warn = 1;
676 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100677 }
678 else {
679 if (config->coerce_c_locale < 0) {
680 config->coerce_c_locale = 1;
681 }
682 }
683 }
684
685 /* Test if coerce_c_locale equals to -1 or equals to 1:
686 PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.
687 It is only coerced if if the LC_CTYPE locale is "C". */
Victor Stinnercab5d072019-05-17 19:01:14 +0200688 if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) {
689 /* The C locale enables the C locale coercion (PEP 538) */
Victor Stinner0f721472019-05-20 17:16:38 +0200690 if (_Py_LegacyLocaleDetected(0)) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200691 config->coerce_c_locale = 2;
692 }
693 else {
694 config->coerce_c_locale = 0;
695 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100696 }
697
Victor Stinnercab5d072019-05-17 19:01:14 +0200698 if (config->coerce_c_locale_warn < 0) {
699 config->coerce_c_locale_warn = 0;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100700 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100701}
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100702
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100703
Victor Stinner331a6a52019-05-27 16:39:22 +0200704static PyStatus
705preconfig_init_allocator(PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100706{
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200707 if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100708 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
709 over PYTHONDEV env var and "-X dev" command line option.
710 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
711 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200712 const char *envvar = _Py_GetEnv(config->use_environment, "PYTHONMALLOC");
713 if (envvar) {
Victor Stinner6d1c4672019-05-20 11:02:00 +0200714 PyMemAllocatorName name;
715 if (_PyMem_GetAllocatorName(envvar, &name) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200716 return _PyStatus_ERR("PYTHONMALLOC: unknown allocator");
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100717 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200718 config->allocator = (int)name;
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100719 }
720 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100721
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200722 if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
723 config->allocator = PYMEM_ALLOCATOR_DEBUG;
Victor Stinner25d13f32019-03-06 12:51:53 +0100724 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200725 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100726}
727
728
Victor Stinner331a6a52019-05-27 16:39:22 +0200729static PyStatus
730preconfig_read(PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100731{
Victor Stinner331a6a52019-05-27 16:39:22 +0200732 PyStatus status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100733
Victor Stinner331a6a52019-05-27 16:39:22 +0200734 status = _PyPreCmdline_Read(cmdline, config);
735 if (_PyStatus_EXCEPTION(status)) {
736 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100737 }
738
Victor Stinner331a6a52019-05-27 16:39:22 +0200739 precmdline_set_preconfig(cmdline, config);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100740
741 /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
742#ifdef MS_WINDOWS
743 _Py_get_env_flag(config->use_environment,
744 &config->legacy_windows_fs_encoding,
745 "PYTHONLEGACYWINDOWSFSENCODING");
746#endif
747
748 preconfig_init_coerce_c_locale(config);
749
Victor Stinner331a6a52019-05-27 16:39:22 +0200750 status = preconfig_init_utf8_mode(config, cmdline);
751 if (_PyStatus_EXCEPTION(status)) {
752 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100753 }
754
755 /* allocator */
Victor Stinner331a6a52019-05-27 16:39:22 +0200756 status = preconfig_init_allocator(config);
757 if (_PyStatus_EXCEPTION(status)) {
758 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100759 }
Victor Stinner25d13f32019-03-06 12:51:53 +0100760
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100761 assert(config->coerce_c_locale >= 0);
Victor Stinnercab5d072019-05-17 19:01:14 +0200762 assert(config->coerce_c_locale_warn >= 0);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100763#ifdef MS_WINDOWS
764 assert(config->legacy_windows_fs_encoding >= 0);
765#endif
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100766 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100767 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100768 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100769 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100770
Victor Stinner331a6a52019-05-27 16:39:22 +0200771 return _PyStatus_OK();
Victor Stinnercad1f742019-03-05 02:01:27 +0100772}
773
774
Victor Stinner4fffd382019-03-06 01:44:31 +0100775/* Read the configuration from:
776
777 - command line arguments
778 - environment variables
779 - Py_xxx global configuration variables
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100780 - the LC_CTYPE locale */
Victor Stinner331a6a52019-05-27 16:39:22 +0200781PyStatus
782_PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100783{
Victor Stinner331a6a52019-05-27 16:39:22 +0200784 PyStatus status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100785
Victor Stinner331a6a52019-05-27 16:39:22 +0200786 status = _PyRuntime_Initialize();
787 if (_PyStatus_EXCEPTION(status)) {
788 return status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100789 }
790
Victor Stinner331a6a52019-05-27 16:39:22 +0200791 preconfig_get_global_vars(config);
Victor Stinnerf29084d2019-03-20 02:20:13 +0100792
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100793 /* Copy LC_CTYPE locale, since it's modified later */
794 const char *loc = setlocale(LC_CTYPE, NULL);
795 if (loc == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200796 return _PyStatus_ERR("failed to LC_CTYPE locale");
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100797 }
798 char *init_ctype_locale = _PyMem_RawStrdup(loc);
799 if (init_ctype_locale == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200800 return _PyStatus_NO_MEMORY();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100801 }
802
803 /* Save the config to be able to restore it if encodings change */
Victor Stinner331a6a52019-05-27 16:39:22 +0200804 PyPreConfig save_config;
Victor Stinner441b10c2019-09-28 04:28:35 +0200805
806 status = _PyPreConfig_InitFromPreConfig(&save_config, config);
807 if (_PyStatus_EXCEPTION(status)) {
808 return status;
809 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100810
811 /* Set LC_CTYPE to the user preferred locale */
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200812 if (config->configure_locale) {
813 _Py_SetLocaleFromEnv(LC_CTYPE);
814 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100815
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100816 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinner6a8c3132019-04-05 11:44:04 +0200817 int init_utf8_mode = Py_UTF8Mode;
818#ifdef MS_WINDOWS
819 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
820#endif
821
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100822 if (args) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200823 status = _PyPreCmdline_SetArgv(&cmdline, args);
824 if (_PyStatus_EXCEPTION(status)) {
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100825 goto done;
826 }
827 }
828
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100829 int locale_coerced = 0;
830 int loops = 0;
831
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100832 while (1) {
833 int utf8_mode = config->utf8_mode;
834
835 /* Watchdog to prevent an infinite loop */
836 loops++;
837 if (loops == 3) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200838 status = _PyStatus_ERR("Encoding changed twice while "
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100839 "reading the configuration");
840 goto done;
841 }
842
843 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
844 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
845 Py_UTF8Mode = config->utf8_mode;
846#ifdef MS_WINDOWS
847 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
848#endif
849
Victor Stinner331a6a52019-05-27 16:39:22 +0200850 status = preconfig_read(config, &cmdline);
851 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100852 goto done;
853 }
854
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100855 /* The legacy C locale assumes ASCII as the default text encoding, which
856 * causes problems not only for the CPython runtime, but also other
857 * components like GNU readline.
858 *
859 * Accordingly, when the CLI detects it, it attempts to coerce it to a
860 * more capable UTF-8 based alternative.
861 *
862 * See the documentation of the PYTHONCOERCECLOCALE setting for more
863 * details.
864 */
865 int encoding_changed = 0;
866 if (config->coerce_c_locale && !locale_coerced) {
867 locale_coerced = 1;
868 _Py_CoerceLegacyLocale(0);
869 encoding_changed = 1;
870 }
871
872 if (utf8_mode == -1) {
873 if (config->utf8_mode == 1) {
874 /* UTF-8 Mode enabled */
875 encoding_changed = 1;
876 }
877 }
878 else {
879 if (config->utf8_mode != utf8_mode) {
880 encoding_changed = 1;
881 }
882 }
883
884 if (!encoding_changed) {
885 break;
886 }
887
888 /* Reset the configuration before reading again the configuration,
889 just keep UTF-8 Mode value. */
890 int new_utf8_mode = config->utf8_mode;
891 int new_coerce_c_locale = config->coerce_c_locale;
Victor Stinner331a6a52019-05-27 16:39:22 +0200892 preconfig_copy(config, &save_config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100893 config->utf8_mode = new_utf8_mode;
894 config->coerce_c_locale = new_coerce_c_locale;
895
896 /* The encoding changed: read again the configuration
897 with the new encoding */
898 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200899 status = _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100900
901done:
902 if (init_ctype_locale != NULL) {
903 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100904 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100905 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100906 Py_UTF8Mode = init_utf8_mode ;
907#ifdef MS_WINDOWS
908 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
909#endif
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100910 _PyPreCmdline_Clear(&cmdline);
Victor Stinner331a6a52019-05-27 16:39:22 +0200911 return status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100912}
913
914
Victor Stinner4fffd382019-03-06 01:44:31 +0100915/* Write the pre-configuration:
916
917 - set the memory allocators
918 - set Py_xxx global configuration variables
919 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
920 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100921
Victor Stinner0f721472019-05-20 17:16:38 +0200922 The applied configuration is written into _PyRuntime.preconfig.
923 If the C locale cannot be coerced, set coerce_c_locale to 0.
Victor Stinner4fffd382019-03-06 01:44:31 +0100924
925 Do nothing if called after Py_Initialize(): ignore the new
926 pre-configuration. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200927PyStatus
928_PyPreConfig_Write(const PyPreConfig *src_config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100929{
Victor Stinner331a6a52019-05-27 16:39:22 +0200930 PyPreConfig config;
Victor Stinner441b10c2019-09-28 04:28:35 +0200931
932 PyStatus status = _PyPreConfig_InitFromPreConfig(&config, src_config);
933 if (_PyStatus_EXCEPTION(status)) {
934 return status;
935 }
Victor Stinner0f721472019-05-20 17:16:38 +0200936
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100937 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100938 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100939 the new configuration. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200940 return _PyStatus_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100941 }
942
Victor Stinner0f721472019-05-20 17:16:38 +0200943 PyMemAllocatorName name = (PyMemAllocatorName)config.allocator;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200944 if (name != PYMEM_ALLOCATOR_NOT_SET) {
945 if (_PyMem_SetupAllocators(name) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200946 return _PyStatus_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100947 }
948 }
949
Victor Stinner331a6a52019-05-27 16:39:22 +0200950 preconfig_set_global_vars(&config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100951
Victor Stinner0f721472019-05-20 17:16:38 +0200952 if (config.configure_locale) {
953 if (config.coerce_c_locale) {
954 if (!_Py_CoerceLegacyLocale(config.coerce_c_locale_warn)) {
955 /* C locale not coerced */
956 config.coerce_c_locale = 0;
957 }
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200958 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100959
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200960 /* Set LC_CTYPE to the user preferred locale */
961 _Py_SetLocaleFromEnv(LC_CTYPE);
962 }
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100963
Victor Stinner6d5ee972019-03-23 12:05:43 +0100964 /* Write the new pre-configuration into _PyRuntime */
Victor Stinner331a6a52019-05-27 16:39:22 +0200965 preconfig_copy(&_PyRuntime.preconfig, &config);
Victor Stinner6d5ee972019-03-23 12:05:43 +0100966
Victor Stinner331a6a52019-05-27 16:39:22 +0200967 return _PyStatus_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100968}