blob: b8b0c3a0775ca857d9c68e038b6bdced6f767f5b [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
Victor Stinner91b9ecf2019-03-01 17:52:56 +010022const char *Py_FileSystemDefaultEncoding = NULL;
23int Py_HasFileSystemDefaultEncoding = 0;
24const char *Py_FileSystemDefaultEncodeErrors = NULL;
25int _Py_HasFileSystemDefaultEncodeErrors = 0;
26
27void
28_Py_ClearFileSystemEncoding(void)
29{
30 if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
31 PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
32 Py_FileSystemDefaultEncoding = NULL;
33 }
34 if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
35 PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
36 Py_FileSystemDefaultEncodeErrors = NULL;
37 }
38}
39
40
41/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
Victor Stinner4b9aad42020-11-02 16:49:54 +010042 global configuration variables to PyConfig.filesystem_encoding and
43 PyConfig.filesystem_errors (encoded to UTF-8).
44
45 Function called by _PyUnicode_InitEncodings(). */
Victor Stinner91b9ecf2019-03-01 17:52:56 +010046int
47_Py_SetFileSystemEncoding(const char *encoding, const char *errors)
48{
49 char *encoding2 = _PyMem_RawStrdup(encoding);
50 if (encoding2 == NULL) {
51 return -1;
52 }
53
54 char *errors2 = _PyMem_RawStrdup(errors);
55 if (errors2 == NULL) {
56 PyMem_RawFree(encoding2);
57 return -1;
58 }
59
60 _Py_ClearFileSystemEncoding();
61
62 Py_FileSystemDefaultEncoding = encoding2;
63 Py_HasFileSystemDefaultEncoding = 0;
64
65 Py_FileSystemDefaultEncodeErrors = errors2;
66 _Py_HasFileSystemDefaultEncodeErrors = 0;
67 return 0;
68}
69
70
71/* --- _PyArgv ---------------------------------------------------- */
72
Victor Stinnerf8ba6f52019-03-26 16:58:50 +010073/* Decode bytes_argv using Py_DecodeLocale() */
Victor Stinner331a6a52019-05-27 16:39:22 +020074PyStatus
75_PyArgv_AsWstrList(const _PyArgv *args, PyWideStringList *list)
Victor Stinner91b9ecf2019-03-01 17:52:56 +010076{
Victor Stinnerfb4ae152019-09-30 01:40:17 +020077 PyWideStringList wargv = _PyWideStringList_INIT;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010078 if (args->use_bytes_argv) {
Victor Stinner74f65682019-03-15 15:08:05 +010079 size_t size = sizeof(wchar_t*) * args->argc;
80 wargv.items = (wchar_t **)PyMem_RawMalloc(size);
81 if (wargv.items == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +020082 return _PyStatus_NO_MEMORY();
Victor Stinner91b9ecf2019-03-01 17:52:56 +010083 }
84
Victor Stinner74f65682019-03-15 15:08:05 +010085 for (Py_ssize_t i = 0; i < args->argc; i++) {
Victor Stinner91b9ecf2019-03-01 17:52:56 +010086 size_t len;
87 wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
88 if (arg == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +020089 _PyWideStringList_Clear(&wargv);
Victor Stinner91b9ecf2019-03-01 17:52:56 +010090 return DECODE_LOCALE_ERR("command line arguments",
91 (Py_ssize_t)len);
92 }
Victor Stinner74f65682019-03-15 15:08:05 +010093 wargv.items[i] = arg;
94 wargv.length++;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010095 }
Victor Stinner74f65682019-03-15 15:08:05 +010096
Victor Stinner331a6a52019-05-27 16:39:22 +020097 _PyWideStringList_Clear(list);
Victor Stinner74f65682019-03-15 15:08:05 +010098 *list = wargv;
Victor Stinner91b9ecf2019-03-01 17:52:56 +010099 }
100 else {
Victor Stinner74f65682019-03-15 15:08:05 +0100101 wargv.length = args->argc;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200102 wargv.items = (wchar_t **)args->wchar_argv;
Victor Stinner331a6a52019-05-27 16:39:22 +0200103 if (_PyWideStringList_Copy(list, &wargv) < 0) {
104 return _PyStatus_NO_MEMORY();
Victor Stinner74f65682019-03-15 15:08:05 +0100105 }
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100106 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200107 return _PyStatus_OK();
Victor Stinner91b9ecf2019-03-01 17:52:56 +0100108}
Victor Stinnercad1f742019-03-05 02:01:27 +0100109
110
Victor Stinner6dcb5422019-03-05 02:44:12 +0100111/* --- _PyPreCmdline ------------------------------------------------- */
112
Victor Stinnerfa153762019-03-20 04:25:38 +0100113void
114_PyPreCmdline_Clear(_PyPreCmdline *cmdline)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100115{
Victor Stinner331a6a52019-05-27 16:39:22 +0200116 _PyWideStringList_Clear(&cmdline->argv);
117 _PyWideStringList_Clear(&cmdline->xoptions);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100118}
119
120
Victor Stinner331a6a52019-05-27 16:39:22 +0200121PyStatus
Victor Stinnerf72346c2019-03-25 17:54:58 +0100122_PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
Victor Stinnerfa153762019-03-20 04:25:38 +0100123{
124 return _PyArgv_AsWstrList(args, &cmdline->argv);
125}
126
127
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100128static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200129precmdline_get_preconfig(_PyPreCmdline *cmdline, const PyPreConfig *config)
Victor Stinnerf72346c2019-03-25 17:54:58 +0100130{
131#define COPY_ATTR(ATTR) \
132 if (config->ATTR != -1) { \
133 cmdline->ATTR = config->ATTR; \
134 }
135
Victor Stinnerf72346c2019-03-25 17:54:58 +0100136 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100137 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100138 COPY_ATTR(dev_mode);
139
140#undef COPY_ATTR
141}
142
143
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100144static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200145precmdline_set_preconfig(const _PyPreCmdline *cmdline, PyPreConfig *config)
Victor Stinner20004952019-03-26 02:31:11 +0100146{
147#define COPY_ATTR(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100148 config->ATTR = cmdline->ATTR
Victor Stinner20004952019-03-26 02:31:11 +0100149
Victor Stinner20004952019-03-26 02:31:11 +0100150 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100151 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100152 COPY_ATTR(dev_mode);
Victor Stinnerf72346c2019-03-25 17:54:58 +0100153
154#undef COPY_ATTR
155}
156
157
Victor Stinner331a6a52019-05-27 16:39:22 +0200158PyStatus
159_PyPreCmdline_SetConfig(const _PyPreCmdline *cmdline, PyConfig *config)
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100160{
161#define COPY_ATTR(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100162 config->ATTR = cmdline->ATTR
163
Victor Stinner331a6a52019-05-27 16:39:22 +0200164 PyStatus status = _PyWideStringList_Extend(&config->xoptions, &cmdline->xoptions);
165 if (_PyStatus_EXCEPTION(status)) {
166 return status;
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100167 }
168
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100169 COPY_ATTR(isolated);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100170 COPY_ATTR(use_environment);
Victor Stinner20004952019-03-26 02:31:11 +0100171 COPY_ATTR(dev_mode);
Victor Stinner331a6a52019-05-27 16:39:22 +0200172 return _PyStatus_OK();
Victor Stinnera6fbc4e2019-03-25 18:37:10 +0100173
174#undef COPY_ATTR
175}
176
177
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100178/* Parse the command line arguments */
Victor Stinner331a6a52019-05-27 16:39:22 +0200179static PyStatus
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100180precmdline_parse_cmdline(_PyPreCmdline *cmdline)
181{
Victor Stinner331a6a52019-05-27 16:39:22 +0200182 const PyWideStringList *argv = &cmdline->argv;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100183
184 _PyOS_ResetGetOpt();
Victor Stinner331a6a52019-05-27 16:39:22 +0200185 /* Don't log parsing errors into stderr here: PyConfig_Read()
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100186 is responsible for that */
187 _PyOS_opterr = 0;
188 do {
189 int longindex = -1;
190 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
191
192 if (c == EOF || c == 'c' || c == 'm') {
193 break;
194 }
195
196 switch (c) {
197 case 'E':
198 cmdline->use_environment = 0;
199 break;
200
201 case 'I':
202 cmdline->isolated = 1;
203 break;
204
205 case 'X':
206 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200207 PyStatus status = PyWideStringList_Append(&cmdline->xoptions,
208 _PyOS_optarg);
209 if (_PyStatus_EXCEPTION(status)) {
210 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100211 }
212 break;
213 }
214
215 default:
216 /* ignore other argument:
Victor Stinner331a6a52019-05-27 16:39:22 +0200217 handled by PyConfig_Read() */
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100218 break;
219 }
220 } while (1);
221
Victor Stinner331a6a52019-05-27 16:39:22 +0200222 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100223}
224
225
Victor Stinner331a6a52019-05-27 16:39:22 +0200226PyStatus
227_PyPreCmdline_Read(_PyPreCmdline *cmdline, const PyPreConfig *preconfig)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100228{
Victor Stinner331a6a52019-05-27 16:39:22 +0200229 precmdline_get_preconfig(cmdline, preconfig);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100230
Victor Stinner6d1c4672019-05-20 11:02:00 +0200231 if (preconfig->parse_argv) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200232 PyStatus status = precmdline_parse_cmdline(cmdline);
233 if (_PyStatus_EXCEPTION(status)) {
234 return status;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200235 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100236 }
237
238 /* isolated, use_environment */
239 if (cmdline->isolated < 0) {
240 cmdline->isolated = 0;
241 }
242 if (cmdline->isolated > 0) {
243 cmdline->use_environment = 0;
244 }
245 if (cmdline->use_environment < 0) {
246 cmdline->use_environment = 0;
247 }
248
249 /* dev_mode */
Victor Stinnerbab0db62019-05-18 03:21:27 +0200250 if ((cmdline->dev_mode < 0)
251 && (_Py_get_xoption(&cmdline->xoptions, L"dev")
252 || _Py_GetEnv(cmdline->use_environment, "PYTHONDEVMODE")))
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100253 {
254 cmdline->dev_mode = 1;
255 }
256 if (cmdline->dev_mode < 0) {
257 cmdline->dev_mode = 0;
258 }
259
260 assert(cmdline->use_environment >= 0);
261 assert(cmdline->isolated >= 0);
262 assert(cmdline->dev_mode >= 0);
263
Victor Stinner331a6a52019-05-27 16:39:22 +0200264 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100265}
266
267
Victor Stinner331a6a52019-05-27 16:39:22 +0200268/* --- PyPreConfig ----------------------------------------------- */
Victor Stinnercad1f742019-03-05 02:01:27 +0100269
Victor Stinnerbab0db62019-05-18 03:21:27 +0200270
Victor Stinner3c30a762019-10-01 10:56:37 +0200271void
Victor Stinner331a6a52019-05-27 16:39:22 +0200272_PyPreConfig_InitCompatConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200273{
Victor Stinnerbab0db62019-05-18 03:21:27 +0200274 memset(config, 0, sizeof(*config));
Victor Stinner441b10c2019-09-28 04:28:35 +0200275
Victor Stinner022be022019-05-22 23:58:50 +0200276 config->_config_init = (int)_PyConfig_INIT_COMPAT;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200277 config->parse_argv = 0;
Victor Stinnerbab0db62019-05-18 03:21:27 +0200278 config->isolated = -1;
279 config->use_environment = -1;
280 config->configure_locale = 1;
Victor Stinner20e1e252019-05-23 04:12:27 +0200281
282 /* bpo-36443: C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
283 are disabled by default using the Compat configuration.
284
285 Py_UTF8Mode=1 enables the UTF-8 mode. PYTHONUTF8 environment variable
286 is ignored (even if use_environment=1). */
287 config->utf8_mode = 0;
288 config->coerce_c_locale = 0;
289 config->coerce_c_locale_warn = 0;
290
Victor Stinnerbab0db62019-05-18 03:21:27 +0200291 config->dev_mode = -1;
Victor Stinnerc5fa3642020-05-05 16:41:11 +0200292#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
293 /* bpo-40512: pymalloc is not compatible with subinterpreters,
294 force usage of libc malloc() which is thread-safe. */
295#ifdef Py_DEBUG
296 config->allocator = PYMEM_ALLOCATOR_MALLOC_DEBUG;
297#else
298 config->allocator = PYMEM_ALLOCATOR_MALLOC;
299#endif
300#else
Victor Stinnerbab0db62019-05-18 03:21:27 +0200301 config->allocator = PYMEM_ALLOCATOR_NOT_SET;
Victor Stinnerc5fa3642020-05-05 16:41:11 +0200302#endif
Victor Stinnerbab0db62019-05-18 03:21:27 +0200303#ifdef MS_WINDOWS
304 config->legacy_windows_fs_encoding = -1;
305#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200306}
307
308
Victor Stinner3c30a762019-10-01 10:56:37 +0200309void
Victor Stinner331a6a52019-05-27 16:39:22 +0200310PyPreConfig_InitPythonConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200311{
Victor Stinner3c30a762019-10-01 10:56:37 +0200312 _PyPreConfig_InitCompatConfig(config);
Victor Stinnercab5d072019-05-17 19:01:14 +0200313
Victor Stinner022be022019-05-22 23:58:50 +0200314 config->_config_init = (int)_PyConfig_INIT_PYTHON;
315 config->isolated = 0;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200316 config->parse_argv = 1;
Victor Stinner022be022019-05-22 23:58:50 +0200317 config->use_environment = 1;
Victor Stinnercab5d072019-05-17 19:01:14 +0200318 /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
319 depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE
320 environment variables. */
321 config->coerce_c_locale = -1;
322 config->coerce_c_locale_warn = -1;
323 config->utf8_mode = -1;
Victor Stinner022be022019-05-22 23:58:50 +0200324#ifdef MS_WINDOWS
325 config->legacy_windows_fs_encoding = 0;
326#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200327}
328
329
Victor Stinner3c30a762019-10-01 10:56:37 +0200330void
Victor Stinner331a6a52019-05-27 16:39:22 +0200331PyPreConfig_InitIsolatedConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200332{
Victor Stinner3c30a762019-10-01 10:56:37 +0200333 _PyPreConfig_InitCompatConfig(config);
Victor Stinnercab5d072019-05-17 19:01:14 +0200334
Victor Stinner022be022019-05-22 23:58:50 +0200335 config->_config_init = (int)_PyConfig_INIT_ISOLATED;
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200336 config->configure_locale = 0;
Victor Stinnercab5d072019-05-17 19:01:14 +0200337 config->isolated = 1;
338 config->use_environment = 0;
Victor Stinnerbab0db62019-05-18 03:21:27 +0200339 config->utf8_mode = 0;
340 config->dev_mode = 0;
Victor Stinnercab5d072019-05-17 19:01:14 +0200341#ifdef MS_WINDOWS
342 config->legacy_windows_fs_encoding = 0;
343#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200344}
345
346
Victor Stinner441b10c2019-09-28 04:28:35 +0200347PyStatus
Victor Stinner331a6a52019-05-27 16:39:22 +0200348_PyPreConfig_InitFromPreConfig(PyPreConfig *config,
349 const PyPreConfig *config2)
Victor Stinner6d1c4672019-05-20 11:02:00 +0200350{
Victor Stinner3c30a762019-10-01 10:56:37 +0200351 PyPreConfig_InitPythonConfig(config);
Victor Stinner331a6a52019-05-27 16:39:22 +0200352 preconfig_copy(config, config2);
Victor Stinner441b10c2019-09-28 04:28:35 +0200353 return _PyStatus_OK();
Victor Stinner6d1c4672019-05-20 11:02:00 +0200354}
355
356
Victor Stinner3c30a762019-10-01 10:56:37 +0200357void
Victor Stinner331a6a52019-05-27 16:39:22 +0200358_PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config)
Victor Stinner6d1c4672019-05-20 11:02:00 +0200359{
Victor Stinner331a6a52019-05-27 16:39:22 +0200360 _PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200361 switch (config_init) {
Victor Stinner022be022019-05-22 23:58:50 +0200362 case _PyConfig_INIT_PYTHON:
Victor Stinner3c30a762019-10-01 10:56:37 +0200363 PyPreConfig_InitPythonConfig(preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200364 break;
Victor Stinner022be022019-05-22 23:58:50 +0200365 case _PyConfig_INIT_ISOLATED:
Victor Stinner3c30a762019-10-01 10:56:37 +0200366 PyPreConfig_InitIsolatedConfig(preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200367 break;
Victor Stinner022be022019-05-22 23:58:50 +0200368 case _PyConfig_INIT_COMPAT:
Victor Stinner6d1c4672019-05-20 11:02:00 +0200369 default:
Victor Stinner3c30a762019-10-01 10:56:37 +0200370 _PyPreConfig_InitCompatConfig(preconfig);
Victor Stinner441b10c2019-09-28 04:28:35 +0200371 }
372
Victor Stinner331a6a52019-05-27 16:39:22 +0200373 _PyPreConfig_GetConfig(preconfig, config);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200374}
375
376
Victor Stinner331a6a52019-05-27 16:39:22 +0200377static void
378preconfig_copy(PyPreConfig *config, const PyPreConfig *config2)
Victor Stinnercad1f742019-03-05 02:01:27 +0100379{
Victor Stinnercad1f742019-03-05 02:01:27 +0100380#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
381
Victor Stinner20e1e252019-05-23 04:12:27 +0200382 COPY_ATTR(_config_init);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200383 COPY_ATTR(parse_argv);
Victor Stinnercad1f742019-03-05 02:01:27 +0100384 COPY_ATTR(isolated);
385 COPY_ATTR(use_environment);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200386 COPY_ATTR(configure_locale);
Victor Stinner20004952019-03-26 02:31:11 +0100387 COPY_ATTR(dev_mode);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100388 COPY_ATTR(coerce_c_locale);
389 COPY_ATTR(coerce_c_locale_warn);
Victor Stinnerb5947842019-05-18 00:38:16 +0200390 COPY_ATTR(utf8_mode);
391 COPY_ATTR(allocator);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100392#ifdef MS_WINDOWS
393 COPY_ATTR(legacy_windows_fs_encoding);
394#endif
Victor Stinnercad1f742019-03-05 02:01:27 +0100395
396#undef COPY_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100397}
398
399
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100400PyObject*
Victor Stinner331a6a52019-05-27 16:39:22 +0200401_PyPreConfig_AsDict(const PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100402{
403 PyObject *dict;
404
405 dict = PyDict_New();
406 if (dict == NULL) {
407 return NULL;
408 }
409
Victor Stinner6d1c4672019-05-20 11:02:00 +0200410#define SET_ITEM_INT(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100411 do { \
Victor Stinner6d1c4672019-05-20 11:02:00 +0200412 PyObject *obj = PyLong_FromLong(config->ATTR); \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100413 if (obj == NULL) { \
414 goto fail; \
415 } \
Victor Stinner6d1c4672019-05-20 11:02:00 +0200416 int res = PyDict_SetItemString(dict, #ATTR, obj); \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100417 Py_DECREF(obj); \
418 if (res < 0) { \
419 goto fail; \
420 } \
421 } while (0)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100422
Victor Stinner20e1e252019-05-23 04:12:27 +0200423 SET_ITEM_INT(_config_init);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200424 SET_ITEM_INT(parse_argv);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100425 SET_ITEM_INT(isolated);
426 SET_ITEM_INT(use_environment);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200427 SET_ITEM_INT(configure_locale);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100428 SET_ITEM_INT(coerce_c_locale);
429 SET_ITEM_INT(coerce_c_locale_warn);
430 SET_ITEM_INT(utf8_mode);
431#ifdef MS_WINDOWS
432 SET_ITEM_INT(legacy_windows_fs_encoding);
433#endif
434 SET_ITEM_INT(dev_mode);
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200435 SET_ITEM_INT(allocator);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100436 return dict;
437
438fail:
439 Py_DECREF(dict);
440 return NULL;
441
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100442#undef SET_ITEM_INT
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100443}
444
445
Victor Stinner5ac27a52019-03-27 13:40:14 +0100446void
Victor Stinner331a6a52019-05-27 16:39:22 +0200447_PyPreConfig_GetConfig(PyPreConfig *preconfig, const PyConfig *config)
Victor Stinner5ac27a52019-03-27 13:40:14 +0100448{
449#define COPY_ATTR(ATTR) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200450 if (config->ATTR != -1) { \
451 preconfig->ATTR = config->ATTR; \
Victor Stinner5ac27a52019-03-27 13:40:14 +0100452 }
453
Victor Stinner6d1c4672019-05-20 11:02:00 +0200454 COPY_ATTR(parse_argv);
Victor Stinner5ac27a52019-03-27 13:40:14 +0100455 COPY_ATTR(isolated);
456 COPY_ATTR(use_environment);
457 COPY_ATTR(dev_mode);
458
459#undef COPY_ATTR
460}
461
462
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100463static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200464preconfig_get_global_vars(PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100465{
Victor Stinner022be022019-05-22 23:58:50 +0200466 if (config->_config_init != _PyConfig_INIT_COMPAT) {
467 /* Python and Isolated configuration ignore global variables */
468 return;
469 }
470
Victor Stinnercad1f742019-03-05 02:01:27 +0100471#define COPY_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200472 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100473 config->ATTR = VALUE; \
474 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100475#define COPY_NOT_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200476 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100477 config->ATTR = !(VALUE); \
478 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100479
480 COPY_FLAG(isolated, Py_IsolatedFlag);
481 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner20e1e252019-05-23 04:12:27 +0200482 if (Py_UTF8Mode > 0) {
483 config->utf8_mode = Py_UTF8Mode;
484 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100485#ifdef MS_WINDOWS
486 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
487#endif
Victor Stinnercad1f742019-03-05 02:01:27 +0100488
489#undef COPY_FLAG
490#undef COPY_NOT_FLAG
491}
492
493
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100494static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200495preconfig_set_global_vars(const PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100496{
497#define COPY_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200498 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100499 VAR = config->ATTR; \
500 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100501#define COPY_NOT_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200502 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100503 VAR = !config->ATTR; \
504 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100505
506 COPY_FLAG(isolated, Py_IsolatedFlag);
507 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100508#ifdef MS_WINDOWS
509 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
510#endif
511 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100512
513#undef COPY_FLAG
514#undef COPY_NOT_FLAG
515}
516
517
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100518const char*
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100519_Py_GetEnv(int use_environment, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100520{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100521 assert(use_environment >= 0);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100522
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100523 if (!use_environment) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100524 return NULL;
525 }
526
527 const char *var = getenv(name);
528 if (var && var[0] != '\0') {
529 return var;
530 }
531 else {
532 return NULL;
533 }
534}
535
536
537int
538_Py_str_to_int(const char *str, int *result)
539{
540 const char *endptr = str;
541 errno = 0;
542 long value = strtol(str, (char **)&endptr, 10);
543 if (*endptr != '\0' || errno == ERANGE) {
544 return -1;
545 }
546 if (value < INT_MIN || value > INT_MAX) {
547 return -1;
548 }
549
550 *result = (int)value;
551 return 0;
552}
553
554
555void
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100556_Py_get_env_flag(int use_environment, int *flag, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100557{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100558 const char *var = _Py_GetEnv(use_environment, name);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100559 if (!var) {
560 return;
561 }
562 int value;
563 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
564 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
565 value = 1;
566 }
567 if (*flag < value) {
568 *flag = value;
569 }
570}
571
572
573const wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200574_Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100575{
Victor Stinner74f65682019-03-15 15:08:05 +0100576 for (Py_ssize_t i=0; i < xoptions->length; i++) {
577 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100578 size_t len;
579 wchar_t *sep = wcschr(option, L'=');
580 if (sep != NULL) {
581 len = (sep - option);
582 }
583 else {
584 len = wcslen(option);
585 }
586 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
587 return option;
588 }
589 }
590 return NULL;
591}
592
593
Victor Stinner331a6a52019-05-27 16:39:22 +0200594static PyStatus
595preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100596{
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100597#ifdef MS_WINDOWS
598 if (config->legacy_windows_fs_encoding) {
599 config->utf8_mode = 0;
600 }
601#endif
602
603 if (config->utf8_mode >= 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200604 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100605 }
606
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100607 const wchar_t *xopt;
Victor Stinner022be022019-05-22 23:58:50 +0200608 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100609 if (xopt) {
610 wchar_t *sep = wcschr(xopt, L'=');
611 if (sep) {
612 xopt = sep + 1;
613 if (wcscmp(xopt, L"1") == 0) {
614 config->utf8_mode = 1;
615 }
616 else if (wcscmp(xopt, L"0") == 0) {
617 config->utf8_mode = 0;
618 }
619 else {
Victor Stinner331a6a52019-05-27 16:39:22 +0200620 return _PyStatus_ERR("invalid -X utf8 option value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100621 }
622 }
623 else {
624 config->utf8_mode = 1;
625 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200626 return _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100627 }
628
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100629 const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100630 if (opt) {
631 if (strcmp(opt, "1") == 0) {
632 config->utf8_mode = 1;
633 }
634 else if (strcmp(opt, "0") == 0) {
635 config->utf8_mode = 0;
636 }
637 else {
Victor Stinner331a6a52019-05-27 16:39:22 +0200638 return _PyStatus_ERR("invalid PYTHONUTF8 environment "
Victor Stinnerdb719752019-05-01 05:35:33 +0200639 "variable value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100640 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200641 return _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100642 }
643
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100644
645#ifndef MS_WINDOWS
646 if (config->utf8_mode < 0) {
647 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
648 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
649 if (ctype_loc != NULL
650 && (strcmp(ctype_loc, "C") == 0
651 || strcmp(ctype_loc, "POSIX") == 0))
652 {
653 config->utf8_mode = 1;
654 }
655 }
656#endif
657
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100658 if (config->utf8_mode < 0) {
659 config->utf8_mode = 0;
660 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200661 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100662}
663
664
665static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200666preconfig_init_coerce_c_locale(PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100667{
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200668 if (!config->configure_locale) {
669 config->coerce_c_locale = 0;
670 config->coerce_c_locale_warn = 0;
671 return;
672 }
673
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100674 const char *env = _Py_GetEnv(config->use_environment, "PYTHONCOERCECLOCALE");
675 if (env) {
676 if (strcmp(env, "0") == 0) {
677 if (config->coerce_c_locale < 0) {
678 config->coerce_c_locale = 0;
679 }
680 }
681 else if (strcmp(env, "warn") == 0) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200682 if (config->coerce_c_locale_warn < 0) {
683 config->coerce_c_locale_warn = 1;
684 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100685 }
686 else {
687 if (config->coerce_c_locale < 0) {
688 config->coerce_c_locale = 1;
689 }
690 }
691 }
692
693 /* Test if coerce_c_locale equals to -1 or equals to 1:
694 PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.
695 It is only coerced if if the LC_CTYPE locale is "C". */
Victor Stinnercab5d072019-05-17 19:01:14 +0200696 if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) {
697 /* The C locale enables the C locale coercion (PEP 538) */
Victor Stinner0f721472019-05-20 17:16:38 +0200698 if (_Py_LegacyLocaleDetected(0)) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200699 config->coerce_c_locale = 2;
700 }
701 else {
702 config->coerce_c_locale = 0;
703 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100704 }
705
Victor Stinnercab5d072019-05-17 19:01:14 +0200706 if (config->coerce_c_locale_warn < 0) {
707 config->coerce_c_locale_warn = 0;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100708 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100709}
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100710
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100711
Victor Stinner331a6a52019-05-27 16:39:22 +0200712static PyStatus
713preconfig_init_allocator(PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100714{
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200715 if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100716 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
717 over PYTHONDEV env var and "-X dev" command line option.
718 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
719 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200720 const char *envvar = _Py_GetEnv(config->use_environment, "PYTHONMALLOC");
721 if (envvar) {
Victor Stinner6d1c4672019-05-20 11:02:00 +0200722 PyMemAllocatorName name;
723 if (_PyMem_GetAllocatorName(envvar, &name) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200724 return _PyStatus_ERR("PYTHONMALLOC: unknown allocator");
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100725 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200726 config->allocator = (int)name;
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100727 }
728 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100729
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200730 if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
731 config->allocator = PYMEM_ALLOCATOR_DEBUG;
Victor Stinner25d13f32019-03-06 12:51:53 +0100732 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200733 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100734}
735
736
Victor Stinner331a6a52019-05-27 16:39:22 +0200737static PyStatus
738preconfig_read(PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100739{
Victor Stinner331a6a52019-05-27 16:39:22 +0200740 PyStatus status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100741
Victor Stinner331a6a52019-05-27 16:39:22 +0200742 status = _PyPreCmdline_Read(cmdline, config);
743 if (_PyStatus_EXCEPTION(status)) {
744 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100745 }
746
Victor Stinner331a6a52019-05-27 16:39:22 +0200747 precmdline_set_preconfig(cmdline, config);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100748
749 /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
750#ifdef MS_WINDOWS
751 _Py_get_env_flag(config->use_environment,
752 &config->legacy_windows_fs_encoding,
753 "PYTHONLEGACYWINDOWSFSENCODING");
754#endif
755
756 preconfig_init_coerce_c_locale(config);
757
Victor Stinner331a6a52019-05-27 16:39:22 +0200758 status = preconfig_init_utf8_mode(config, cmdline);
759 if (_PyStatus_EXCEPTION(status)) {
760 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100761 }
762
763 /* allocator */
Victor Stinner331a6a52019-05-27 16:39:22 +0200764 status = preconfig_init_allocator(config);
765 if (_PyStatus_EXCEPTION(status)) {
766 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100767 }
Victor Stinner25d13f32019-03-06 12:51:53 +0100768
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100769 assert(config->coerce_c_locale >= 0);
Victor Stinnercab5d072019-05-17 19:01:14 +0200770 assert(config->coerce_c_locale_warn >= 0);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100771#ifdef MS_WINDOWS
772 assert(config->legacy_windows_fs_encoding >= 0);
773#endif
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100774 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100775 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100776 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100777 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100778
Victor Stinner331a6a52019-05-27 16:39:22 +0200779 return _PyStatus_OK();
Victor Stinnercad1f742019-03-05 02:01:27 +0100780}
781
782
Victor Stinner4fffd382019-03-06 01:44:31 +0100783/* Read the configuration from:
784
785 - command line arguments
786 - environment variables
787 - Py_xxx global configuration variables
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100788 - the LC_CTYPE locale */
Victor Stinner331a6a52019-05-27 16:39:22 +0200789PyStatus
790_PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100791{
Victor Stinner331a6a52019-05-27 16:39:22 +0200792 PyStatus status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100793
Victor Stinner331a6a52019-05-27 16:39:22 +0200794 status = _PyRuntime_Initialize();
795 if (_PyStatus_EXCEPTION(status)) {
796 return status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100797 }
798
Victor Stinner331a6a52019-05-27 16:39:22 +0200799 preconfig_get_global_vars(config);
Victor Stinnerf29084d2019-03-20 02:20:13 +0100800
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100801 /* Copy LC_CTYPE locale, since it's modified later */
802 const char *loc = setlocale(LC_CTYPE, NULL);
803 if (loc == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200804 return _PyStatus_ERR("failed to LC_CTYPE locale");
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100805 }
806 char *init_ctype_locale = _PyMem_RawStrdup(loc);
807 if (init_ctype_locale == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200808 return _PyStatus_NO_MEMORY();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100809 }
810
811 /* Save the config to be able to restore it if encodings change */
Victor Stinner331a6a52019-05-27 16:39:22 +0200812 PyPreConfig save_config;
Victor Stinner441b10c2019-09-28 04:28:35 +0200813
814 status = _PyPreConfig_InitFromPreConfig(&save_config, config);
815 if (_PyStatus_EXCEPTION(status)) {
816 return status;
817 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100818
819 /* Set LC_CTYPE to the user preferred locale */
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200820 if (config->configure_locale) {
821 _Py_SetLocaleFromEnv(LC_CTYPE);
822 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100823
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100824 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinner6a8c3132019-04-05 11:44:04 +0200825 int init_utf8_mode = Py_UTF8Mode;
826#ifdef MS_WINDOWS
827 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
828#endif
829
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100830 int locale_coerced = 0;
831 int loops = 0;
832
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100833 while (1) {
834 int utf8_mode = config->utf8_mode;
835
836 /* Watchdog to prevent an infinite loop */
837 loops++;
838 if (loops == 3) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200839 status = _PyStatus_ERR("Encoding changed twice while "
Victor Stinner8eb4aea2020-06-10 19:33:11 +0200840 "reading the configuration");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100841 goto done;
842 }
843
844 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
845 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
846 Py_UTF8Mode = config->utf8_mode;
847#ifdef MS_WINDOWS
848 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
849#endif
850
Victor Stinner8eb4aea2020-06-10 19:33:11 +0200851 if (args) {
852 // Set command line arguments at each iteration. If they are bytes
853 // strings, they are decoded from the new encoding.
854 status = _PyPreCmdline_SetArgv(&cmdline, args);
855 if (_PyStatus_EXCEPTION(status)) {
856 goto done;
857 }
858 }
859
Victor Stinner331a6a52019-05-27 16:39:22 +0200860 status = preconfig_read(config, &cmdline);
861 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100862 goto done;
863 }
864
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100865 /* The legacy C locale assumes ASCII as the default text encoding, which
866 * causes problems not only for the CPython runtime, but also other
867 * components like GNU readline.
868 *
869 * Accordingly, when the CLI detects it, it attempts to coerce it to a
870 * more capable UTF-8 based alternative.
871 *
872 * See the documentation of the PYTHONCOERCECLOCALE setting for more
873 * details.
874 */
875 int encoding_changed = 0;
876 if (config->coerce_c_locale && !locale_coerced) {
877 locale_coerced = 1;
878 _Py_CoerceLegacyLocale(0);
879 encoding_changed = 1;
880 }
881
882 if (utf8_mode == -1) {
883 if (config->utf8_mode == 1) {
884 /* UTF-8 Mode enabled */
885 encoding_changed = 1;
886 }
887 }
888 else {
889 if (config->utf8_mode != utf8_mode) {
890 encoding_changed = 1;
891 }
892 }
893
894 if (!encoding_changed) {
895 break;
896 }
897
898 /* Reset the configuration before reading again the configuration,
Victor Stinner8eb4aea2020-06-10 19:33:11 +0200899 just keep UTF-8 Mode and coerce C locale value. */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100900 int new_utf8_mode = config->utf8_mode;
901 int new_coerce_c_locale = config->coerce_c_locale;
Victor Stinner331a6a52019-05-27 16:39:22 +0200902 preconfig_copy(config, &save_config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100903 config->utf8_mode = new_utf8_mode;
904 config->coerce_c_locale = new_coerce_c_locale;
905
906 /* The encoding changed: read again the configuration
907 with the new encoding */
908 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200909 status = _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100910
911done:
912 if (init_ctype_locale != NULL) {
913 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100914 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100915 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100916 Py_UTF8Mode = init_utf8_mode ;
917#ifdef MS_WINDOWS
918 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
919#endif
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100920 _PyPreCmdline_Clear(&cmdline);
Victor Stinner331a6a52019-05-27 16:39:22 +0200921 return status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100922}
923
924
Victor Stinner4fffd382019-03-06 01:44:31 +0100925/* Write the pre-configuration:
926
927 - set the memory allocators
928 - set Py_xxx global configuration variables
929 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
930 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100931
Victor Stinner0f721472019-05-20 17:16:38 +0200932 The applied configuration is written into _PyRuntime.preconfig.
933 If the C locale cannot be coerced, set coerce_c_locale to 0.
Victor Stinner4fffd382019-03-06 01:44:31 +0100934
935 Do nothing if called after Py_Initialize(): ignore the new
936 pre-configuration. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200937PyStatus
938_PyPreConfig_Write(const PyPreConfig *src_config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100939{
Victor Stinner331a6a52019-05-27 16:39:22 +0200940 PyPreConfig config;
Victor Stinner441b10c2019-09-28 04:28:35 +0200941
942 PyStatus status = _PyPreConfig_InitFromPreConfig(&config, src_config);
943 if (_PyStatus_EXCEPTION(status)) {
944 return status;
945 }
Victor Stinner0f721472019-05-20 17:16:38 +0200946
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100947 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100948 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100949 the new configuration. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200950 return _PyStatus_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100951 }
952
Victor Stinner0f721472019-05-20 17:16:38 +0200953 PyMemAllocatorName name = (PyMemAllocatorName)config.allocator;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200954 if (name != PYMEM_ALLOCATOR_NOT_SET) {
955 if (_PyMem_SetupAllocators(name) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200956 return _PyStatus_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100957 }
958 }
959
Victor Stinner331a6a52019-05-27 16:39:22 +0200960 preconfig_set_global_vars(&config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100961
Victor Stinner0f721472019-05-20 17:16:38 +0200962 if (config.configure_locale) {
963 if (config.coerce_c_locale) {
964 if (!_Py_CoerceLegacyLocale(config.coerce_c_locale_warn)) {
965 /* C locale not coerced */
966 config.coerce_c_locale = 0;
967 }
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200968 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100969
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200970 /* Set LC_CTYPE to the user preferred locale */
971 _Py_SetLocaleFromEnv(LC_CTYPE);
972 }
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100973
Victor Stinner6d5ee972019-03-23 12:05:43 +0100974 /* Write the new pre-configuration into _PyRuntime */
Victor Stinner331a6a52019-05-27 16:39:22 +0200975 preconfig_copy(&_PyRuntime.preconfig, &config);
Victor Stinner6d5ee972019-03-23 12:05:43 +0100976
Victor Stinner331a6a52019-05-27 16:39:22 +0200977 return _PyStatus_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100978}