blob: 89a6227fa67218dc428eeb53815eb1fb82e6a3b8 [file] [log] [blame]
Victor Stinner91b9ecf2019-03-01 17:52:56 +01001#include "Python.h"
Victor Stinner331a6a52019-05-27 16:39:22 +02002#include "pycore_initconfig.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 Stinner331a6a52019-05-27 16:39:22 +020010 ? _PyStatus_ERR("cannot decode " NAME) \
11 : _PyStatus_NO_MEMORY())
12
13
14/* Forward declarations */
15static void
16preconfig_copy(PyPreConfig *config, const PyPreConfig *config2);
Victor Stinner91b9ecf2019-03-01 17:52:56 +010017
18
19/* --- File system encoding/errors -------------------------------- */
20
21/* The filesystem encoding is chosen by config_init_fs_encoding(),
Victor Stinner709d23d2019-05-02 14:56:30 -040022 see also initfsencoding().
23
24 Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
25 are encoded to UTF-8. */
Victor Stinner91b9ecf2019-03-01 17:52:56 +010026const char *Py_FileSystemDefaultEncoding = NULL;
27int Py_HasFileSystemDefaultEncoding = 0;
28const char *Py_FileSystemDefaultEncodeErrors = NULL;
29int _Py_HasFileSystemDefaultEncodeErrors = 0;
30
31void
32_Py_ClearFileSystemEncoding(void)
33{
34 if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
35 PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
36 Py_FileSystemDefaultEncoding = NULL;
37 }
38 if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
39 PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
40 Py_FileSystemDefaultEncodeErrors = NULL;
41 }
42}
43
44
45/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
46 global configuration variables. */
47int
48_Py_SetFileSystemEncoding(const char *encoding, const char *errors)
49{
50 char *encoding2 = _PyMem_RawStrdup(encoding);
51 if (encoding2 == NULL) {
52 return -1;
53 }
54
55 char *errors2 = _PyMem_RawStrdup(errors);
56 if (errors2 == NULL) {
57 PyMem_RawFree(encoding2);
58 return -1;
59 }
60
61 _Py_ClearFileSystemEncoding();
62
63 Py_FileSystemDefaultEncoding = encoding2;
64 Py_HasFileSystemDefaultEncoding = 0;
65
66 Py_FileSystemDefaultEncodeErrors = errors2;
67 _Py_HasFileSystemDefaultEncodeErrors = 0;
68 return 0;
69}
70
71
72/* --- _PyArgv ---------------------------------------------------- */
73
Victor Stinnerf8ba6f52019-03-26 16:58:50 +010074/* Decode bytes_argv using Py_DecodeLocale() */
Victor Stinner331a6a52019-05-27 16:39:22 +020075PyStatus
76_PyArgv_AsWstrList(const _PyArgv *args, PyWideStringList *list)
Victor Stinner91b9ecf2019-03-01 17:52:56 +010077{
Miss Islington (bot)c9ed9e62019-09-29 16:58:57 -070078 PyWideStringList wargv = _PyWideStringList_INIT;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010079 if (args->use_bytes_argv) {
Victor Stinner74f65682019-03-15 15:08:05 +010080 size_t size = sizeof(wchar_t*) * args->argc;
81 wargv.items = (wchar_t **)PyMem_RawMalloc(size);
82 if (wargv.items == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +020083 return _PyStatus_NO_MEMORY();
Victor Stinner91b9ecf2019-03-01 17:52:56 +010084 }
85
Victor Stinner74f65682019-03-15 15:08:05 +010086 for (Py_ssize_t i = 0; i < args->argc; i++) {
Victor Stinner91b9ecf2019-03-01 17:52:56 +010087 size_t len;
88 wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
89 if (arg == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +020090 _PyWideStringList_Clear(&wargv);
Victor Stinner91b9ecf2019-03-01 17:52:56 +010091 return DECODE_LOCALE_ERR("command line arguments",
92 (Py_ssize_t)len);
93 }
Victor Stinner74f65682019-03-15 15:08:05 +010094 wargv.items[i] = arg;
95 wargv.length++;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010096 }
Victor Stinner74f65682019-03-15 15:08:05 +010097
Victor Stinner331a6a52019-05-27 16:39:22 +020098 _PyWideStringList_Clear(list);
Victor Stinner74f65682019-03-15 15:08:05 +010099 *list = wargv;
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100100 }
101 else {
Victor Stinner74f65682019-03-15 15:08:05 +0100102 wargv.length = args->argc;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200103 wargv.items = (wchar_t **)args->wchar_argv;
Victor Stinner331a6a52019-05-27 16:39:22 +0200104 if (_PyWideStringList_Copy(list, &wargv) < 0) {
105 return _PyStatus_NO_MEMORY();
Victor Stinner74f65682019-03-15 15:08:05 +0100106 }
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100107 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200108 return _PyStatus_OK();
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100109}
Victor Stinnercad1f742019-03-05 02:01:27 +0100110
111
Victor Stinner6dcb5422019-03-05 02:44:12 +0100112/* --- _PyPreCmdline ------------------------------------------------- */
113
Victor Stinnerfa153762019-03-20 04:25:38 +0100114void
115_PyPreCmdline_Clear(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100116{
Victor Stinner331a6a52019-05-27 16:39:22 +0200117 _PyWideStringList_Clear(&cmdline->argv);
118 _PyWideStringList_Clear(&cmdline->xoptions);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100119}
120
121
Victor Stinner331a6a52019-05-27 16:39:22 +0200122PyStatus
Victor Stinnerf72346c2019-03-25 17:54:58 +0100123_PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
Victor Stinnerfa153762019-03-20 04:25:38 +0100124{
125 return _PyArgv_AsWstrList(args, &cmdline->argv);
126}
127
128
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100129static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200130precmdline_get_preconfig(_PyPreCmdline *cmdline, const PyPreConfig *config)
Victor Stinnerf72346c2019-03-25 17:54:58 +0100131{
132#define COPY_ATTR(ATTR) \
133 if (config->ATTR != -1) { \
134 cmdline->ATTR = config->ATTR; \
135 }
136
Victor Stinnerf72346c2019-03-25 17:54:58 +0100137 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100138 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100139 COPY_ATTR(dev_mode);
140
141#undef COPY_ATTR
142}
143
144
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100145static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200146precmdline_set_preconfig(const _PyPreCmdline *cmdline, PyPreConfig *config)
Victor Stinner20004952019-03-26 02:31:11 +0100147{
148#define COPY_ATTR(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100149 config->ATTR = cmdline->ATTR
Victor Stinner20004952019-03-26 02:31:11 +0100150
Victor Stinner20004952019-03-26 02:31:11 +0100151 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100152 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100153 COPY_ATTR(dev_mode);
Victor Stinnerf72346c2019-03-25 17:54:58 +0100154
155#undef COPY_ATTR
156}
157
158
Victor Stinner331a6a52019-05-27 16:39:22 +0200159PyStatus
160_PyPreCmdline_SetConfig(const _PyPreCmdline *cmdline, PyConfig *config)
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100161{
162#define COPY_ATTR(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100163 config->ATTR = cmdline->ATTR
164
Victor Stinner331a6a52019-05-27 16:39:22 +0200165 PyStatus status = _PyWideStringList_Extend(&config->xoptions, &cmdline->xoptions);
166 if (_PyStatus_EXCEPTION(status)) {
167 return status;
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100168 }
169
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100170 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100171 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100172 COPY_ATTR(dev_mode);
Victor Stinner331a6a52019-05-27 16:39:22 +0200173 return _PyStatus_OK();
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100174
175#undef COPY_ATTR
176}
177
178
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100179/* Parse the command line arguments */
Victor Stinner331a6a52019-05-27 16:39:22 +0200180static PyStatus
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100181precmdline_parse_cmdline(_PyPreCmdline *cmdline)
182{
Victor Stinner331a6a52019-05-27 16:39:22 +0200183 const PyWideStringList *argv = &cmdline->argv;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100184
185 _PyOS_ResetGetOpt();
Victor Stinner331a6a52019-05-27 16:39:22 +0200186 /* Don't log parsing errors into stderr here: PyConfig_Read()
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100187 is responsible for that */
188 _PyOS_opterr = 0;
189 do {
190 int longindex = -1;
191 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
192
193 if (c == EOF || c == 'c' || c == 'm') {
194 break;
195 }
196
197 switch (c) {
198 case 'E':
199 cmdline->use_environment = 0;
200 break;
201
202 case 'I':
203 cmdline->isolated = 1;
204 break;
205
206 case 'X':
207 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200208 PyStatus status = PyWideStringList_Append(&cmdline->xoptions,
209 _PyOS_optarg);
210 if (_PyStatus_EXCEPTION(status)) {
211 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100212 }
213 break;
214 }
215
216 default:
217 /* ignore other argument:
Victor Stinner331a6a52019-05-27 16:39:22 +0200218 handled by PyConfig_Read() */
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100219 break;
220 }
221 } while (1);
222
Victor Stinner331a6a52019-05-27 16:39:22 +0200223 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100224}
225
226
Victor Stinner331a6a52019-05-27 16:39:22 +0200227PyStatus
228_PyPreCmdline_Read(_PyPreCmdline *cmdline, const PyPreConfig *preconfig)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100229{
Victor Stinner331a6a52019-05-27 16:39:22 +0200230 precmdline_get_preconfig(cmdline, preconfig);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100231
Victor Stinner6d1c4672019-05-20 11:02:00 +0200232 if (preconfig->parse_argv) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200233 PyStatus status = precmdline_parse_cmdline(cmdline);
234 if (_PyStatus_EXCEPTION(status)) {
235 return status;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200236 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100237 }
238
239 /* isolated, use_environment */
240 if (cmdline->isolated < 0) {
241 cmdline->isolated = 0;
242 }
243 if (cmdline->isolated > 0) {
244 cmdline->use_environment = 0;
245 }
246 if (cmdline->use_environment < 0) {
247 cmdline->use_environment = 0;
248 }
249
250 /* dev_mode */
Victor Stinnerbab0db62019-05-18 03:21:27 +0200251 if ((cmdline->dev_mode < 0)
252 && (_Py_get_xoption(&cmdline->xoptions, L"dev")
253 || _Py_GetEnv(cmdline->use_environment, "PYTHONDEVMODE")))
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100254 {
255 cmdline->dev_mode = 1;
256 }
257 if (cmdline->dev_mode < 0) {
258 cmdline->dev_mode = 0;
259 }
260
261 assert(cmdline->use_environment >= 0);
262 assert(cmdline->isolated >= 0);
263 assert(cmdline->dev_mode >= 0);
264
Victor Stinner331a6a52019-05-27 16:39:22 +0200265 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100266}
267
268
Victor Stinner331a6a52019-05-27 16:39:22 +0200269/* --- PyPreConfig ----------------------------------------------- */
Victor Stinnercad1f742019-03-05 02:01:27 +0100270
Victor Stinnerbab0db62019-05-18 03:21:27 +0200271
Victor Stinnerbdace212019-10-01 00:46:42 +0200272void
Victor Stinner331a6a52019-05-27 16:39:22 +0200273_PyPreConfig_InitCompatConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200274{
Victor Stinnerbab0db62019-05-18 03:21:27 +0200275 memset(config, 0, sizeof(*config));
Victor Stinner6e128382019-09-28 04:50:43 +0200276
Victor Stinner022be022019-05-22 23:58:50 +0200277 config->_config_init = (int)_PyConfig_INIT_COMPAT;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200278 config->parse_argv = 0;
Victor Stinnerbab0db62019-05-18 03:21:27 +0200279 config->isolated = -1;
280 config->use_environment = -1;
281 config->configure_locale = 1;
Victor Stinner20e1e252019-05-23 04:12:27 +0200282
283 /* bpo-36443: C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
284 are disabled by default using the Compat configuration.
285
286 Py_UTF8Mode=1 enables the UTF-8 mode. PYTHONUTF8 environment variable
287 is ignored (even if use_environment=1). */
288 config->utf8_mode = 0;
289 config->coerce_c_locale = 0;
290 config->coerce_c_locale_warn = 0;
291
Victor Stinnerbab0db62019-05-18 03:21:27 +0200292 config->dev_mode = -1;
293 config->allocator = PYMEM_ALLOCATOR_NOT_SET;
294#ifdef MS_WINDOWS
295 config->legacy_windows_fs_encoding = -1;
296#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200297}
298
299
Victor Stinnerbdace212019-10-01 00:46:42 +0200300void
Victor Stinner331a6a52019-05-27 16:39:22 +0200301PyPreConfig_InitPythonConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200302{
Victor Stinnerbdace212019-10-01 00:46:42 +0200303 _PyPreConfig_InitCompatConfig(config);
Victor Stinnercab5d072019-05-17 19:01:14 +0200304
Victor Stinner022be022019-05-22 23:58:50 +0200305 config->_config_init = (int)_PyConfig_INIT_PYTHON;
306 config->isolated = 0;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200307 config->parse_argv = 1;
Victor Stinner022be022019-05-22 23:58:50 +0200308 config->use_environment = 1;
Victor Stinnercab5d072019-05-17 19:01:14 +0200309 /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
310 depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE
311 environment variables. */
312 config->coerce_c_locale = -1;
313 config->coerce_c_locale_warn = -1;
314 config->utf8_mode = -1;
Victor Stinner022be022019-05-22 23:58:50 +0200315#ifdef MS_WINDOWS
316 config->legacy_windows_fs_encoding = 0;
317#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200318}
319
320
Victor Stinnerbdace212019-10-01 00:46:42 +0200321void
Victor Stinner331a6a52019-05-27 16:39:22 +0200322PyPreConfig_InitIsolatedConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200323{
Victor Stinnerbdace212019-10-01 00:46:42 +0200324 _PyPreConfig_InitCompatConfig(config);
Victor Stinnercab5d072019-05-17 19:01:14 +0200325
Victor Stinner022be022019-05-22 23:58:50 +0200326 config->_config_init = (int)_PyConfig_INIT_ISOLATED;
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200327 config->configure_locale = 0;
Victor Stinnercab5d072019-05-17 19:01:14 +0200328 config->isolated = 1;
329 config->use_environment = 0;
Victor Stinnerbab0db62019-05-18 03:21:27 +0200330 config->utf8_mode = 0;
331 config->dev_mode = 0;
Victor Stinnercab5d072019-05-17 19:01:14 +0200332#ifdef MS_WINDOWS
333 config->legacy_windows_fs_encoding = 0;
334#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200335}
336
337
Victor Stinner6e128382019-09-28 04:50:43 +0200338PyStatus
Victor Stinner331a6a52019-05-27 16:39:22 +0200339_PyPreConfig_InitFromPreConfig(PyPreConfig *config,
340 const PyPreConfig *config2)
Victor Stinner6d1c4672019-05-20 11:02:00 +0200341{
Victor Stinnerbdace212019-10-01 00:46:42 +0200342 PyPreConfig_InitPythonConfig(config);
Victor Stinner331a6a52019-05-27 16:39:22 +0200343 preconfig_copy(config, config2);
Victor Stinner6e128382019-09-28 04:50:43 +0200344 return _PyStatus_OK();
Victor Stinner6d1c4672019-05-20 11:02:00 +0200345}
346
347
Victor Stinnerbdace212019-10-01 00:46:42 +0200348void
Victor Stinner331a6a52019-05-27 16:39:22 +0200349_PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config)
Victor Stinner6d1c4672019-05-20 11:02:00 +0200350{
Victor Stinner331a6a52019-05-27 16:39:22 +0200351 _PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200352 switch (config_init) {
Victor Stinner022be022019-05-22 23:58:50 +0200353 case _PyConfig_INIT_PYTHON:
Victor Stinnerbdace212019-10-01 00:46:42 +0200354 PyPreConfig_InitPythonConfig(preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200355 break;
Victor Stinner022be022019-05-22 23:58:50 +0200356 case _PyConfig_INIT_ISOLATED:
Victor Stinnerbdace212019-10-01 00:46:42 +0200357 PyPreConfig_InitIsolatedConfig(preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200358 break;
Victor Stinner022be022019-05-22 23:58:50 +0200359 case _PyConfig_INIT_COMPAT:
Victor Stinner6d1c4672019-05-20 11:02:00 +0200360 default:
Victor Stinnerbdace212019-10-01 00:46:42 +0200361 _PyPreConfig_InitCompatConfig(preconfig);
Victor Stinner6e128382019-09-28 04:50:43 +0200362 }
363
Victor Stinner331a6a52019-05-27 16:39:22 +0200364 _PyPreConfig_GetConfig(preconfig, config);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200365}
366
367
Victor Stinner331a6a52019-05-27 16:39:22 +0200368static void
369preconfig_copy(PyPreConfig *config, const PyPreConfig *config2)
Victor Stinnercad1f742019-03-05 02:01:27 +0100370{
Victor Stinnercad1f742019-03-05 02:01:27 +0100371#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
372
Victor Stinner20e1e252019-05-23 04:12:27 +0200373 COPY_ATTR(_config_init);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200374 COPY_ATTR(parse_argv);
Victor Stinnercad1f742019-03-05 02:01:27 +0100375 COPY_ATTR(isolated);
376 COPY_ATTR(use_environment);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200377 COPY_ATTR(configure_locale);
Victor Stinner20004952019-03-26 02:31:11 +0100378 COPY_ATTR(dev_mode);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100379 COPY_ATTR(coerce_c_locale);
380 COPY_ATTR(coerce_c_locale_warn);
Victor Stinnerb5947842019-05-18 00:38:16 +0200381 COPY_ATTR(utf8_mode);
382 COPY_ATTR(allocator);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100383#ifdef MS_WINDOWS
384 COPY_ATTR(legacy_windows_fs_encoding);
385#endif
Victor Stinnercad1f742019-03-05 02:01:27 +0100386
387#undef COPY_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100388}
389
390
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100391PyObject*
Victor Stinner331a6a52019-05-27 16:39:22 +0200392_PyPreConfig_AsDict(const PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100393{
394 PyObject *dict;
395
396 dict = PyDict_New();
397 if (dict == NULL) {
398 return NULL;
399 }
400
Victor Stinner6d1c4672019-05-20 11:02:00 +0200401#define SET_ITEM_INT(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100402 do { \
Victor Stinner6d1c4672019-05-20 11:02:00 +0200403 PyObject *obj = PyLong_FromLong(config->ATTR); \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100404 if (obj == NULL) { \
405 goto fail; \
406 } \
Victor Stinner6d1c4672019-05-20 11:02:00 +0200407 int res = PyDict_SetItemString(dict, #ATTR, obj); \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100408 Py_DECREF(obj); \
409 if (res < 0) { \
410 goto fail; \
411 } \
412 } while (0)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100413
Victor Stinner20e1e252019-05-23 04:12:27 +0200414 SET_ITEM_INT(_config_init);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200415 SET_ITEM_INT(parse_argv);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100416 SET_ITEM_INT(isolated);
417 SET_ITEM_INT(use_environment);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200418 SET_ITEM_INT(configure_locale);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100419 SET_ITEM_INT(coerce_c_locale);
420 SET_ITEM_INT(coerce_c_locale_warn);
421 SET_ITEM_INT(utf8_mode);
422#ifdef MS_WINDOWS
423 SET_ITEM_INT(legacy_windows_fs_encoding);
424#endif
425 SET_ITEM_INT(dev_mode);
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200426 SET_ITEM_INT(allocator);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100427 return dict;
428
429fail:
430 Py_DECREF(dict);
431 return NULL;
432
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100433#undef SET_ITEM_INT
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100434}
435
436
Victor Stinner5ac27a52019-03-27 13:40:14 +0100437void
Victor Stinner331a6a52019-05-27 16:39:22 +0200438_PyPreConfig_GetConfig(PyPreConfig *preconfig, const PyConfig *config)
Victor Stinner5ac27a52019-03-27 13:40:14 +0100439{
440#define COPY_ATTR(ATTR) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200441 if (config->ATTR != -1) { \
442 preconfig->ATTR = config->ATTR; \
Victor Stinner5ac27a52019-03-27 13:40:14 +0100443 }
444
Victor Stinner6d1c4672019-05-20 11:02:00 +0200445 COPY_ATTR(parse_argv);
Victor Stinner5ac27a52019-03-27 13:40:14 +0100446 COPY_ATTR(isolated);
447 COPY_ATTR(use_environment);
448 COPY_ATTR(dev_mode);
449
450#undef COPY_ATTR
451}
452
453
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100454static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200455preconfig_get_global_vars(PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100456{
Victor Stinner022be022019-05-22 23:58:50 +0200457 if (config->_config_init != _PyConfig_INIT_COMPAT) {
458 /* Python and Isolated configuration ignore global variables */
459 return;
460 }
461
Victor Stinnercad1f742019-03-05 02:01:27 +0100462#define COPY_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200463 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100464 config->ATTR = VALUE; \
465 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100466#define COPY_NOT_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200467 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100468 config->ATTR = !(VALUE); \
469 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100470
471 COPY_FLAG(isolated, Py_IsolatedFlag);
472 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner20e1e252019-05-23 04:12:27 +0200473 if (Py_UTF8Mode > 0) {
474 config->utf8_mode = Py_UTF8Mode;
475 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100476#ifdef MS_WINDOWS
477 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
478#endif
Victor Stinnercad1f742019-03-05 02:01:27 +0100479
480#undef COPY_FLAG
481#undef COPY_NOT_FLAG
482}
483
484
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100485static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200486preconfig_set_global_vars(const PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100487{
488#define COPY_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200489 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100490 VAR = config->ATTR; \
491 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100492#define COPY_NOT_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200493 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100494 VAR = !config->ATTR; \
495 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100496
497 COPY_FLAG(isolated, Py_IsolatedFlag);
498 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100499#ifdef MS_WINDOWS
500 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
501#endif
502 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100503
504#undef COPY_FLAG
505#undef COPY_NOT_FLAG
506}
507
508
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100509const char*
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100510_Py_GetEnv(int use_environment, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100511{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100512 assert(use_environment >= 0);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100513
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100514 if (!use_environment) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100515 return NULL;
516 }
517
518 const char *var = getenv(name);
519 if (var && var[0] != '\0') {
520 return var;
521 }
522 else {
523 return NULL;
524 }
525}
526
527
528int
529_Py_str_to_int(const char *str, int *result)
530{
531 const char *endptr = str;
532 errno = 0;
533 long value = strtol(str, (char **)&endptr, 10);
534 if (*endptr != '\0' || errno == ERANGE) {
535 return -1;
536 }
537 if (value < INT_MIN || value > INT_MAX) {
538 return -1;
539 }
540
541 *result = (int)value;
542 return 0;
543}
544
545
546void
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100547_Py_get_env_flag(int use_environment, int *flag, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100548{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100549 const char *var = _Py_GetEnv(use_environment, name);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100550 if (!var) {
551 return;
552 }
553 int value;
554 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
555 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
556 value = 1;
557 }
558 if (*flag < value) {
559 *flag = value;
560 }
561}
562
563
564const wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200565_Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100566{
Victor Stinner74f65682019-03-15 15:08:05 +0100567 for (Py_ssize_t i=0; i < xoptions->length; i++) {
568 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100569 size_t len;
570 wchar_t *sep = wcschr(option, L'=');
571 if (sep != NULL) {
572 len = (sep - option);
573 }
574 else {
575 len = wcslen(option);
576 }
577 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
578 return option;
579 }
580 }
581 return NULL;
582}
583
584
Victor Stinner331a6a52019-05-27 16:39:22 +0200585static PyStatus
586preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100587{
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100588#ifdef MS_WINDOWS
589 if (config->legacy_windows_fs_encoding) {
590 config->utf8_mode = 0;
591 }
592#endif
593
594 if (config->utf8_mode >= 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200595 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100596 }
597
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100598 const wchar_t *xopt;
Victor Stinner022be022019-05-22 23:58:50 +0200599 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100600 if (xopt) {
601 wchar_t *sep = wcschr(xopt, L'=');
602 if (sep) {
603 xopt = sep + 1;
604 if (wcscmp(xopt, L"1") == 0) {
605 config->utf8_mode = 1;
606 }
607 else if (wcscmp(xopt, L"0") == 0) {
608 config->utf8_mode = 0;
609 }
610 else {
Victor Stinner331a6a52019-05-27 16:39:22 +0200611 return _PyStatus_ERR("invalid -X utf8 option value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100612 }
613 }
614 else {
615 config->utf8_mode = 1;
616 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200617 return _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100618 }
619
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100620 const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100621 if (opt) {
622 if (strcmp(opt, "1") == 0) {
623 config->utf8_mode = 1;
624 }
625 else if (strcmp(opt, "0") == 0) {
626 config->utf8_mode = 0;
627 }
628 else {
Victor Stinner331a6a52019-05-27 16:39:22 +0200629 return _PyStatus_ERR("invalid PYTHONUTF8 environment "
Victor Stinnerdb719752019-05-01 05:35:33 +0200630 "variable value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100631 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200632 return _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100633 }
634
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100635
636#ifndef MS_WINDOWS
637 if (config->utf8_mode < 0) {
638 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
639 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
640 if (ctype_loc != NULL
641 && (strcmp(ctype_loc, "C") == 0
642 || strcmp(ctype_loc, "POSIX") == 0))
643 {
644 config->utf8_mode = 1;
645 }
646 }
647#endif
648
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100649 if (config->utf8_mode < 0) {
650 config->utf8_mode = 0;
651 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200652 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100653}
654
655
656static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200657preconfig_init_coerce_c_locale(PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100658{
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200659 if (!config->configure_locale) {
660 config->coerce_c_locale = 0;
661 config->coerce_c_locale_warn = 0;
662 return;
663 }
664
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100665 const char *env = _Py_GetEnv(config->use_environment, "PYTHONCOERCECLOCALE");
666 if (env) {
667 if (strcmp(env, "0") == 0) {
668 if (config->coerce_c_locale < 0) {
669 config->coerce_c_locale = 0;
670 }
671 }
672 else if (strcmp(env, "warn") == 0) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200673 if (config->coerce_c_locale_warn < 0) {
674 config->coerce_c_locale_warn = 1;
675 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100676 }
677 else {
678 if (config->coerce_c_locale < 0) {
679 config->coerce_c_locale = 1;
680 }
681 }
682 }
683
684 /* Test if coerce_c_locale equals to -1 or equals to 1:
685 PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.
686 It is only coerced if if the LC_CTYPE locale is "C". */
Victor Stinnercab5d072019-05-17 19:01:14 +0200687 if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) {
688 /* The C locale enables the C locale coercion (PEP 538) */
Victor Stinner0f721472019-05-20 17:16:38 +0200689 if (_Py_LegacyLocaleDetected(0)) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200690 config->coerce_c_locale = 2;
691 }
692 else {
693 config->coerce_c_locale = 0;
694 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100695 }
696
Victor Stinnercab5d072019-05-17 19:01:14 +0200697 if (config->coerce_c_locale_warn < 0) {
698 config->coerce_c_locale_warn = 0;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100699 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100700}
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100701
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100702
Victor Stinner331a6a52019-05-27 16:39:22 +0200703static PyStatus
704preconfig_init_allocator(PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100705{
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200706 if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100707 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
708 over PYTHONDEV env var and "-X dev" command line option.
709 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
710 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200711 const char *envvar = _Py_GetEnv(config->use_environment, "PYTHONMALLOC");
712 if (envvar) {
Victor Stinner6d1c4672019-05-20 11:02:00 +0200713 PyMemAllocatorName name;
714 if (_PyMem_GetAllocatorName(envvar, &name) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200715 return _PyStatus_ERR("PYTHONMALLOC: unknown allocator");
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100716 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200717 config->allocator = (int)name;
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100718 }
719 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100720
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200721 if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
722 config->allocator = PYMEM_ALLOCATOR_DEBUG;
Victor Stinner25d13f32019-03-06 12:51:53 +0100723 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200724 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100725}
726
727
Victor Stinner331a6a52019-05-27 16:39:22 +0200728static PyStatus
729preconfig_read(PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100730{
Victor Stinner331a6a52019-05-27 16:39:22 +0200731 PyStatus status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100732
Victor Stinner331a6a52019-05-27 16:39:22 +0200733 status = _PyPreCmdline_Read(cmdline, config);
734 if (_PyStatus_EXCEPTION(status)) {
735 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100736 }
737
Victor Stinner331a6a52019-05-27 16:39:22 +0200738 precmdline_set_preconfig(cmdline, config);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100739
740 /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
741#ifdef MS_WINDOWS
742 _Py_get_env_flag(config->use_environment,
743 &config->legacy_windows_fs_encoding,
744 "PYTHONLEGACYWINDOWSFSENCODING");
745#endif
746
747 preconfig_init_coerce_c_locale(config);
748
Victor Stinner331a6a52019-05-27 16:39:22 +0200749 status = preconfig_init_utf8_mode(config, cmdline);
750 if (_PyStatus_EXCEPTION(status)) {
751 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100752 }
753
754 /* allocator */
Victor Stinner331a6a52019-05-27 16:39:22 +0200755 status = preconfig_init_allocator(config);
756 if (_PyStatus_EXCEPTION(status)) {
757 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100758 }
Victor Stinner25d13f32019-03-06 12:51:53 +0100759
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100760 assert(config->coerce_c_locale >= 0);
Victor Stinnercab5d072019-05-17 19:01:14 +0200761 assert(config->coerce_c_locale_warn >= 0);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100762#ifdef MS_WINDOWS
763 assert(config->legacy_windows_fs_encoding >= 0);
764#endif
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100765 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100766 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100767 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100768 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100769
Victor Stinner331a6a52019-05-27 16:39:22 +0200770 return _PyStatus_OK();
Victor Stinnercad1f742019-03-05 02:01:27 +0100771}
772
773
Victor Stinner4fffd382019-03-06 01:44:31 +0100774/* Read the configuration from:
775
776 - command line arguments
777 - environment variables
778 - Py_xxx global configuration variables
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100779 - the LC_CTYPE locale */
Victor Stinner331a6a52019-05-27 16:39:22 +0200780PyStatus
781_PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100782{
Victor Stinner331a6a52019-05-27 16:39:22 +0200783 PyStatus status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100784
Victor Stinner331a6a52019-05-27 16:39:22 +0200785 status = _PyRuntime_Initialize();
786 if (_PyStatus_EXCEPTION(status)) {
787 return status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100788 }
789
Victor Stinner331a6a52019-05-27 16:39:22 +0200790 preconfig_get_global_vars(config);
Victor Stinnerf29084d2019-03-20 02:20:13 +0100791
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100792 /* Copy LC_CTYPE locale, since it's modified later */
793 const char *loc = setlocale(LC_CTYPE, NULL);
794 if (loc == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200795 return _PyStatus_ERR("failed to LC_CTYPE locale");
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100796 }
797 char *init_ctype_locale = _PyMem_RawStrdup(loc);
798 if (init_ctype_locale == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200799 return _PyStatus_NO_MEMORY();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100800 }
801
802 /* Save the config to be able to restore it if encodings change */
Victor Stinner331a6a52019-05-27 16:39:22 +0200803 PyPreConfig save_config;
Victor Stinner6e128382019-09-28 04:50:43 +0200804
805 status = _PyPreConfig_InitFromPreConfig(&save_config, config);
806 if (_PyStatus_EXCEPTION(status)) {
807 return status;
808 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100809
810 /* Set LC_CTYPE to the user preferred locale */
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200811 if (config->configure_locale) {
812 _Py_SetLocaleFromEnv(LC_CTYPE);
813 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100814
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100815 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinner6a8c3132019-04-05 11:44:04 +0200816 int init_utf8_mode = Py_UTF8Mode;
817#ifdef MS_WINDOWS
818 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
819#endif
820
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100821 if (args) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200822 status = _PyPreCmdline_SetArgv(&cmdline, args);
823 if (_PyStatus_EXCEPTION(status)) {
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100824 goto done;
825 }
826 }
827
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100828 int locale_coerced = 0;
829 int loops = 0;
830
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100831 while (1) {
832 int utf8_mode = config->utf8_mode;
833
834 /* Watchdog to prevent an infinite loop */
835 loops++;
836 if (loops == 3) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200837 status = _PyStatus_ERR("Encoding changed twice while "
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100838 "reading the configuration");
839 goto done;
840 }
841
842 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
843 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
844 Py_UTF8Mode = config->utf8_mode;
845#ifdef MS_WINDOWS
846 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
847#endif
848
Victor Stinner331a6a52019-05-27 16:39:22 +0200849 status = preconfig_read(config, &cmdline);
850 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100851 goto done;
852 }
853
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100854 /* The legacy C locale assumes ASCII as the default text encoding, which
855 * causes problems not only for the CPython runtime, but also other
856 * components like GNU readline.
857 *
858 * Accordingly, when the CLI detects it, it attempts to coerce it to a
859 * more capable UTF-8 based alternative.
860 *
861 * See the documentation of the PYTHONCOERCECLOCALE setting for more
862 * details.
863 */
864 int encoding_changed = 0;
865 if (config->coerce_c_locale && !locale_coerced) {
866 locale_coerced = 1;
867 _Py_CoerceLegacyLocale(0);
868 encoding_changed = 1;
869 }
870
871 if (utf8_mode == -1) {
872 if (config->utf8_mode == 1) {
873 /* UTF-8 Mode enabled */
874 encoding_changed = 1;
875 }
876 }
877 else {
878 if (config->utf8_mode != utf8_mode) {
879 encoding_changed = 1;
880 }
881 }
882
883 if (!encoding_changed) {
884 break;
885 }
886
887 /* Reset the configuration before reading again the configuration,
888 just keep UTF-8 Mode value. */
889 int new_utf8_mode = config->utf8_mode;
890 int new_coerce_c_locale = config->coerce_c_locale;
Victor Stinner331a6a52019-05-27 16:39:22 +0200891 preconfig_copy(config, &save_config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100892 config->utf8_mode = new_utf8_mode;
893 config->coerce_c_locale = new_coerce_c_locale;
894
895 /* The encoding changed: read again the configuration
896 with the new encoding */
897 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200898 status = _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100899
900done:
901 if (init_ctype_locale != NULL) {
902 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100903 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100904 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100905 Py_UTF8Mode = init_utf8_mode ;
906#ifdef MS_WINDOWS
907 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
908#endif
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100909 _PyPreCmdline_Clear(&cmdline);
Victor Stinner331a6a52019-05-27 16:39:22 +0200910 return status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100911}
912
913
Victor Stinner4fffd382019-03-06 01:44:31 +0100914/* Write the pre-configuration:
915
916 - set the memory allocators
917 - set Py_xxx global configuration variables
918 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
919 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100920
Victor Stinner0f721472019-05-20 17:16:38 +0200921 The applied configuration is written into _PyRuntime.preconfig.
922 If the C locale cannot be coerced, set coerce_c_locale to 0.
Victor Stinner4fffd382019-03-06 01:44:31 +0100923
924 Do nothing if called after Py_Initialize(): ignore the new
925 pre-configuration. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200926PyStatus
927_PyPreConfig_Write(const PyPreConfig *src_config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100928{
Victor Stinner331a6a52019-05-27 16:39:22 +0200929 PyPreConfig config;
Victor Stinner6e128382019-09-28 04:50:43 +0200930
931 PyStatus status = _PyPreConfig_InitFromPreConfig(&config, src_config);
932 if (_PyStatus_EXCEPTION(status)) {
933 return status;
934 }
Victor Stinner0f721472019-05-20 17:16:38 +0200935
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100936 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100937 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100938 the new configuration. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200939 return _PyStatus_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100940 }
941
Victor Stinner0f721472019-05-20 17:16:38 +0200942 PyMemAllocatorName name = (PyMemAllocatorName)config.allocator;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200943 if (name != PYMEM_ALLOCATOR_NOT_SET) {
944 if (_PyMem_SetupAllocators(name) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200945 return _PyStatus_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100946 }
947 }
948
Victor Stinner331a6a52019-05-27 16:39:22 +0200949 preconfig_set_global_vars(&config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100950
Victor Stinner0f721472019-05-20 17:16:38 +0200951 if (config.configure_locale) {
952 if (config.coerce_c_locale) {
953 if (!_Py_CoerceLegacyLocale(config.coerce_c_locale_warn)) {
954 /* C locale not coerced */
955 config.coerce_c_locale = 0;
956 }
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200957 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100958
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200959 /* Set LC_CTYPE to the user preferred locale */
960 _Py_SetLocaleFromEnv(LC_CTYPE);
961 }
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100962
Victor Stinner6d5ee972019-03-23 12:05:43 +0100963 /* Write the new pre-configuration into _PyRuntime */
Victor Stinner331a6a52019-05-27 16:39:22 +0200964 preconfig_copy(&_PyRuntime.preconfig, &config);
Victor Stinner6d5ee972019-03-23 12:05:43 +0100965
Victor Stinner331a6a52019-05-27 16:39:22 +0200966 return _PyStatus_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100967}