blob: 149afcd99ab32f47b42376b7b58b959f54706343 [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;
Victor Stinnerc5fa3642020-05-05 16:41:11 +0200294#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
295 /* bpo-40512: pymalloc is not compatible with subinterpreters,
296 force usage of libc malloc() which is thread-safe. */
297#ifdef Py_DEBUG
298 config->allocator = PYMEM_ALLOCATOR_MALLOC_DEBUG;
299#else
300 config->allocator = PYMEM_ALLOCATOR_MALLOC;
301#endif
302#else
Victor Stinnerbab0db62019-05-18 03:21:27 +0200303 config->allocator = PYMEM_ALLOCATOR_NOT_SET;
Victor Stinnerc5fa3642020-05-05 16:41:11 +0200304#endif
Victor Stinnerbab0db62019-05-18 03:21:27 +0200305#ifdef MS_WINDOWS
306 config->legacy_windows_fs_encoding = -1;
307#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200308}
309
310
Victor Stinner3c30a762019-10-01 10:56:37 +0200311void
Victor Stinner331a6a52019-05-27 16:39:22 +0200312PyPreConfig_InitPythonConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200313{
Victor Stinner3c30a762019-10-01 10:56:37 +0200314 _PyPreConfig_InitCompatConfig(config);
Victor Stinnercab5d072019-05-17 19:01:14 +0200315
Victor Stinner022be022019-05-22 23:58:50 +0200316 config->_config_init = (int)_PyConfig_INIT_PYTHON;
317 config->isolated = 0;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200318 config->parse_argv = 1;
Victor Stinner022be022019-05-22 23:58:50 +0200319 config->use_environment = 1;
Victor Stinnercab5d072019-05-17 19:01:14 +0200320 /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
321 depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE
322 environment variables. */
323 config->coerce_c_locale = -1;
324 config->coerce_c_locale_warn = -1;
325 config->utf8_mode = -1;
Victor Stinner022be022019-05-22 23:58:50 +0200326#ifdef MS_WINDOWS
327 config->legacy_windows_fs_encoding = 0;
328#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200329}
330
331
Victor Stinner3c30a762019-10-01 10:56:37 +0200332void
Victor Stinner331a6a52019-05-27 16:39:22 +0200333PyPreConfig_InitIsolatedConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200334{
Victor Stinner3c30a762019-10-01 10:56:37 +0200335 _PyPreConfig_InitCompatConfig(config);
Victor Stinnercab5d072019-05-17 19:01:14 +0200336
Victor Stinner022be022019-05-22 23:58:50 +0200337 config->_config_init = (int)_PyConfig_INIT_ISOLATED;
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200338 config->configure_locale = 0;
Victor Stinnercab5d072019-05-17 19:01:14 +0200339 config->isolated = 1;
340 config->use_environment = 0;
Victor Stinnerbab0db62019-05-18 03:21:27 +0200341 config->utf8_mode = 0;
342 config->dev_mode = 0;
Victor Stinnercab5d072019-05-17 19:01:14 +0200343#ifdef MS_WINDOWS
344 config->legacy_windows_fs_encoding = 0;
345#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200346}
347
348
Victor Stinner441b10c2019-09-28 04:28:35 +0200349PyStatus
Victor Stinner331a6a52019-05-27 16:39:22 +0200350_PyPreConfig_InitFromPreConfig(PyPreConfig *config,
351 const PyPreConfig *config2)
Victor Stinner6d1c4672019-05-20 11:02:00 +0200352{
Victor Stinner3c30a762019-10-01 10:56:37 +0200353 PyPreConfig_InitPythonConfig(config);
Victor Stinner331a6a52019-05-27 16:39:22 +0200354 preconfig_copy(config, config2);
Victor Stinner441b10c2019-09-28 04:28:35 +0200355 return _PyStatus_OK();
Victor Stinner6d1c4672019-05-20 11:02:00 +0200356}
357
358
Victor Stinner3c30a762019-10-01 10:56:37 +0200359void
Victor Stinner331a6a52019-05-27 16:39:22 +0200360_PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config)
Victor Stinner6d1c4672019-05-20 11:02:00 +0200361{
Victor Stinner331a6a52019-05-27 16:39:22 +0200362 _PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200363 switch (config_init) {
Victor Stinner022be022019-05-22 23:58:50 +0200364 case _PyConfig_INIT_PYTHON:
Victor Stinner3c30a762019-10-01 10:56:37 +0200365 PyPreConfig_InitPythonConfig(preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200366 break;
Victor Stinner022be022019-05-22 23:58:50 +0200367 case _PyConfig_INIT_ISOLATED:
Victor Stinner3c30a762019-10-01 10:56:37 +0200368 PyPreConfig_InitIsolatedConfig(preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200369 break;
Victor Stinner022be022019-05-22 23:58:50 +0200370 case _PyConfig_INIT_COMPAT:
Victor Stinner6d1c4672019-05-20 11:02:00 +0200371 default:
Victor Stinner3c30a762019-10-01 10:56:37 +0200372 _PyPreConfig_InitCompatConfig(preconfig);
Victor Stinner441b10c2019-09-28 04:28:35 +0200373 }
374
Victor Stinner331a6a52019-05-27 16:39:22 +0200375 _PyPreConfig_GetConfig(preconfig, config);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200376}
377
378
Victor Stinner331a6a52019-05-27 16:39:22 +0200379static void
380preconfig_copy(PyPreConfig *config, const PyPreConfig *config2)
Victor Stinnercad1f742019-03-05 02:01:27 +0100381{
Victor Stinnercad1f742019-03-05 02:01:27 +0100382#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
383
Victor Stinner20e1e252019-05-23 04:12:27 +0200384 COPY_ATTR(_config_init);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200385 COPY_ATTR(parse_argv);
Victor Stinnercad1f742019-03-05 02:01:27 +0100386 COPY_ATTR(isolated);
387 COPY_ATTR(use_environment);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200388 COPY_ATTR(configure_locale);
Victor Stinner20004952019-03-26 02:31:11 +0100389 COPY_ATTR(dev_mode);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100390 COPY_ATTR(coerce_c_locale);
391 COPY_ATTR(coerce_c_locale_warn);
Victor Stinnerb5947842019-05-18 00:38:16 +0200392 COPY_ATTR(utf8_mode);
393 COPY_ATTR(allocator);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100394#ifdef MS_WINDOWS
395 COPY_ATTR(legacy_windows_fs_encoding);
396#endif
Victor Stinnercad1f742019-03-05 02:01:27 +0100397
398#undef COPY_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100399}
400
401
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100402PyObject*
Victor Stinner331a6a52019-05-27 16:39:22 +0200403_PyPreConfig_AsDict(const PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100404{
405 PyObject *dict;
406
407 dict = PyDict_New();
408 if (dict == NULL) {
409 return NULL;
410 }
411
Victor Stinner6d1c4672019-05-20 11:02:00 +0200412#define SET_ITEM_INT(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100413 do { \
Victor Stinner6d1c4672019-05-20 11:02:00 +0200414 PyObject *obj = PyLong_FromLong(config->ATTR); \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100415 if (obj == NULL) { \
416 goto fail; \
417 } \
Victor Stinner6d1c4672019-05-20 11:02:00 +0200418 int res = PyDict_SetItemString(dict, #ATTR, obj); \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100419 Py_DECREF(obj); \
420 if (res < 0) { \
421 goto fail; \
422 } \
423 } while (0)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100424
Victor Stinner20e1e252019-05-23 04:12:27 +0200425 SET_ITEM_INT(_config_init);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200426 SET_ITEM_INT(parse_argv);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100427 SET_ITEM_INT(isolated);
428 SET_ITEM_INT(use_environment);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200429 SET_ITEM_INT(configure_locale);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100430 SET_ITEM_INT(coerce_c_locale);
431 SET_ITEM_INT(coerce_c_locale_warn);
432 SET_ITEM_INT(utf8_mode);
433#ifdef MS_WINDOWS
434 SET_ITEM_INT(legacy_windows_fs_encoding);
435#endif
436 SET_ITEM_INT(dev_mode);
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200437 SET_ITEM_INT(allocator);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100438 return dict;
439
440fail:
441 Py_DECREF(dict);
442 return NULL;
443
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100444#undef SET_ITEM_INT
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100445}
446
447
Victor Stinner5ac27a52019-03-27 13:40:14 +0100448void
Victor Stinner331a6a52019-05-27 16:39:22 +0200449_PyPreConfig_GetConfig(PyPreConfig *preconfig, const PyConfig *config)
Victor Stinner5ac27a52019-03-27 13:40:14 +0100450{
451#define COPY_ATTR(ATTR) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200452 if (config->ATTR != -1) { \
453 preconfig->ATTR = config->ATTR; \
Victor Stinner5ac27a52019-03-27 13:40:14 +0100454 }
455
Victor Stinner6d1c4672019-05-20 11:02:00 +0200456 COPY_ATTR(parse_argv);
Victor Stinner5ac27a52019-03-27 13:40:14 +0100457 COPY_ATTR(isolated);
458 COPY_ATTR(use_environment);
459 COPY_ATTR(dev_mode);
460
461#undef COPY_ATTR
462}
463
464
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100465static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200466preconfig_get_global_vars(PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100467{
Victor Stinner022be022019-05-22 23:58:50 +0200468 if (config->_config_init != _PyConfig_INIT_COMPAT) {
469 /* Python and Isolated configuration ignore global variables */
470 return;
471 }
472
Victor Stinnercad1f742019-03-05 02:01:27 +0100473#define COPY_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200474 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100475 config->ATTR = VALUE; \
476 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100477#define COPY_NOT_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200478 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100479 config->ATTR = !(VALUE); \
480 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100481
482 COPY_FLAG(isolated, Py_IsolatedFlag);
483 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner20e1e252019-05-23 04:12:27 +0200484 if (Py_UTF8Mode > 0) {
485 config->utf8_mode = Py_UTF8Mode;
486 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100487#ifdef MS_WINDOWS
488 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
489#endif
Victor Stinnercad1f742019-03-05 02:01:27 +0100490
491#undef COPY_FLAG
492#undef COPY_NOT_FLAG
493}
494
495
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100496static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200497preconfig_set_global_vars(const PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100498{
499#define COPY_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200500 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100501 VAR = config->ATTR; \
502 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100503#define COPY_NOT_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200504 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100505 VAR = !config->ATTR; \
506 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100507
508 COPY_FLAG(isolated, Py_IsolatedFlag);
509 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100510#ifdef MS_WINDOWS
511 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
512#endif
513 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100514
515#undef COPY_FLAG
516#undef COPY_NOT_FLAG
517}
518
519
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100520const char*
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100521_Py_GetEnv(int use_environment, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100522{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100523 assert(use_environment >= 0);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100524
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100525 if (!use_environment) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100526 return NULL;
527 }
528
529 const char *var = getenv(name);
530 if (var && var[0] != '\0') {
531 return var;
532 }
533 else {
534 return NULL;
535 }
536}
537
538
539int
540_Py_str_to_int(const char *str, int *result)
541{
542 const char *endptr = str;
543 errno = 0;
544 long value = strtol(str, (char **)&endptr, 10);
545 if (*endptr != '\0' || errno == ERANGE) {
546 return -1;
547 }
548 if (value < INT_MIN || value > INT_MAX) {
549 return -1;
550 }
551
552 *result = (int)value;
553 return 0;
554}
555
556
557void
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100558_Py_get_env_flag(int use_environment, int *flag, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100559{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100560 const char *var = _Py_GetEnv(use_environment, name);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100561 if (!var) {
562 return;
563 }
564 int value;
565 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
566 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
567 value = 1;
568 }
569 if (*flag < value) {
570 *flag = value;
571 }
572}
573
574
575const wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200576_Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100577{
Victor Stinner74f65682019-03-15 15:08:05 +0100578 for (Py_ssize_t i=0; i < xoptions->length; i++) {
579 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100580 size_t len;
581 wchar_t *sep = wcschr(option, L'=');
582 if (sep != NULL) {
583 len = (sep - option);
584 }
585 else {
586 len = wcslen(option);
587 }
588 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
589 return option;
590 }
591 }
592 return NULL;
593}
594
595
Victor Stinner331a6a52019-05-27 16:39:22 +0200596static PyStatus
597preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100598{
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100599#ifdef MS_WINDOWS
600 if (config->legacy_windows_fs_encoding) {
601 config->utf8_mode = 0;
602 }
603#endif
604
605 if (config->utf8_mode >= 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200606 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100607 }
608
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100609 const wchar_t *xopt;
Victor Stinner022be022019-05-22 23:58:50 +0200610 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100611 if (xopt) {
612 wchar_t *sep = wcschr(xopt, L'=');
613 if (sep) {
614 xopt = sep + 1;
615 if (wcscmp(xopt, L"1") == 0) {
616 config->utf8_mode = 1;
617 }
618 else if (wcscmp(xopt, L"0") == 0) {
619 config->utf8_mode = 0;
620 }
621 else {
Victor Stinner331a6a52019-05-27 16:39:22 +0200622 return _PyStatus_ERR("invalid -X utf8 option value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100623 }
624 }
625 else {
626 config->utf8_mode = 1;
627 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200628 return _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100629 }
630
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100631 const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100632 if (opt) {
633 if (strcmp(opt, "1") == 0) {
634 config->utf8_mode = 1;
635 }
636 else if (strcmp(opt, "0") == 0) {
637 config->utf8_mode = 0;
638 }
639 else {
Victor Stinner331a6a52019-05-27 16:39:22 +0200640 return _PyStatus_ERR("invalid PYTHONUTF8 environment "
Victor Stinnerdb719752019-05-01 05:35:33 +0200641 "variable value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100642 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200643 return _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100644 }
645
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100646
647#ifndef MS_WINDOWS
648 if (config->utf8_mode < 0) {
649 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
650 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
651 if (ctype_loc != NULL
652 && (strcmp(ctype_loc, "C") == 0
653 || strcmp(ctype_loc, "POSIX") == 0))
654 {
655 config->utf8_mode = 1;
656 }
657 }
658#endif
659
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100660 if (config->utf8_mode < 0) {
661 config->utf8_mode = 0;
662 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200663 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100664}
665
666
667static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200668preconfig_init_coerce_c_locale(PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100669{
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200670 if (!config->configure_locale) {
671 config->coerce_c_locale = 0;
672 config->coerce_c_locale_warn = 0;
673 return;
674 }
675
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100676 const char *env = _Py_GetEnv(config->use_environment, "PYTHONCOERCECLOCALE");
677 if (env) {
678 if (strcmp(env, "0") == 0) {
679 if (config->coerce_c_locale < 0) {
680 config->coerce_c_locale = 0;
681 }
682 }
683 else if (strcmp(env, "warn") == 0) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200684 if (config->coerce_c_locale_warn < 0) {
685 config->coerce_c_locale_warn = 1;
686 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100687 }
688 else {
689 if (config->coerce_c_locale < 0) {
690 config->coerce_c_locale = 1;
691 }
692 }
693 }
694
695 /* Test if coerce_c_locale equals to -1 or equals to 1:
696 PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.
697 It is only coerced if if the LC_CTYPE locale is "C". */
Victor Stinnercab5d072019-05-17 19:01:14 +0200698 if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) {
699 /* The C locale enables the C locale coercion (PEP 538) */
Victor Stinner0f721472019-05-20 17:16:38 +0200700 if (_Py_LegacyLocaleDetected(0)) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200701 config->coerce_c_locale = 2;
702 }
703 else {
704 config->coerce_c_locale = 0;
705 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100706 }
707
Victor Stinnercab5d072019-05-17 19:01:14 +0200708 if (config->coerce_c_locale_warn < 0) {
709 config->coerce_c_locale_warn = 0;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100710 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100711}
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100712
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100713
Victor Stinner331a6a52019-05-27 16:39:22 +0200714static PyStatus
715preconfig_init_allocator(PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100716{
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200717 if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100718 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
719 over PYTHONDEV env var and "-X dev" command line option.
720 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
721 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200722 const char *envvar = _Py_GetEnv(config->use_environment, "PYTHONMALLOC");
723 if (envvar) {
Victor Stinner6d1c4672019-05-20 11:02:00 +0200724 PyMemAllocatorName name;
725 if (_PyMem_GetAllocatorName(envvar, &name) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200726 return _PyStatus_ERR("PYTHONMALLOC: unknown allocator");
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100727 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200728 config->allocator = (int)name;
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100729 }
730 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100731
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200732 if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
733 config->allocator = PYMEM_ALLOCATOR_DEBUG;
Victor Stinner25d13f32019-03-06 12:51:53 +0100734 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200735 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100736}
737
738
Victor Stinner331a6a52019-05-27 16:39:22 +0200739static PyStatus
740preconfig_read(PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100741{
Victor Stinner331a6a52019-05-27 16:39:22 +0200742 PyStatus status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100743
Victor Stinner331a6a52019-05-27 16:39:22 +0200744 status = _PyPreCmdline_Read(cmdline, config);
745 if (_PyStatus_EXCEPTION(status)) {
746 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100747 }
748
Victor Stinner331a6a52019-05-27 16:39:22 +0200749 precmdline_set_preconfig(cmdline, config);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100750
751 /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
752#ifdef MS_WINDOWS
753 _Py_get_env_flag(config->use_environment,
754 &config->legacy_windows_fs_encoding,
755 "PYTHONLEGACYWINDOWSFSENCODING");
756#endif
757
758 preconfig_init_coerce_c_locale(config);
759
Victor Stinner331a6a52019-05-27 16:39:22 +0200760 status = preconfig_init_utf8_mode(config, cmdline);
761 if (_PyStatus_EXCEPTION(status)) {
762 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100763 }
764
765 /* allocator */
Victor Stinner331a6a52019-05-27 16:39:22 +0200766 status = preconfig_init_allocator(config);
767 if (_PyStatus_EXCEPTION(status)) {
768 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100769 }
Victor Stinner25d13f32019-03-06 12:51:53 +0100770
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100771 assert(config->coerce_c_locale >= 0);
Victor Stinnercab5d072019-05-17 19:01:14 +0200772 assert(config->coerce_c_locale_warn >= 0);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100773#ifdef MS_WINDOWS
774 assert(config->legacy_windows_fs_encoding >= 0);
775#endif
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100776 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100777 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100778 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100779 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100780
Victor Stinner331a6a52019-05-27 16:39:22 +0200781 return _PyStatus_OK();
Victor Stinnercad1f742019-03-05 02:01:27 +0100782}
783
784
Victor Stinner4fffd382019-03-06 01:44:31 +0100785/* Read the configuration from:
786
787 - command line arguments
788 - environment variables
789 - Py_xxx global configuration variables
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100790 - the LC_CTYPE locale */
Victor Stinner331a6a52019-05-27 16:39:22 +0200791PyStatus
792_PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100793{
Victor Stinner331a6a52019-05-27 16:39:22 +0200794 PyStatus status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100795
Victor Stinner331a6a52019-05-27 16:39:22 +0200796 status = _PyRuntime_Initialize();
797 if (_PyStatus_EXCEPTION(status)) {
798 return status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100799 }
800
Victor Stinner331a6a52019-05-27 16:39:22 +0200801 preconfig_get_global_vars(config);
Victor Stinnerf29084d2019-03-20 02:20:13 +0100802
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100803 /* Copy LC_CTYPE locale, since it's modified later */
804 const char *loc = setlocale(LC_CTYPE, NULL);
805 if (loc == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200806 return _PyStatus_ERR("failed to LC_CTYPE locale");
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100807 }
808 char *init_ctype_locale = _PyMem_RawStrdup(loc);
809 if (init_ctype_locale == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200810 return _PyStatus_NO_MEMORY();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100811 }
812
813 /* Save the config to be able to restore it if encodings change */
Victor Stinner331a6a52019-05-27 16:39:22 +0200814 PyPreConfig save_config;
Victor Stinner441b10c2019-09-28 04:28:35 +0200815
816 status = _PyPreConfig_InitFromPreConfig(&save_config, config);
817 if (_PyStatus_EXCEPTION(status)) {
818 return status;
819 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100820
821 /* Set LC_CTYPE to the user preferred locale */
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200822 if (config->configure_locale) {
823 _Py_SetLocaleFromEnv(LC_CTYPE);
824 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100825
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100826 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinner6a8c3132019-04-05 11:44:04 +0200827 int init_utf8_mode = Py_UTF8Mode;
828#ifdef MS_WINDOWS
829 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
830#endif
831
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100832 int locale_coerced = 0;
833 int loops = 0;
834
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100835 while (1) {
836 int utf8_mode = config->utf8_mode;
837
838 /* Watchdog to prevent an infinite loop */
839 loops++;
840 if (loops == 3) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200841 status = _PyStatus_ERR("Encoding changed twice while "
Victor Stinner8eb4aea2020-06-10 19:33:11 +0200842 "reading the configuration");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100843 goto done;
844 }
845
846 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
847 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
848 Py_UTF8Mode = config->utf8_mode;
849#ifdef MS_WINDOWS
850 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
851#endif
852
Victor Stinner8eb4aea2020-06-10 19:33:11 +0200853 if (args) {
854 // Set command line arguments at each iteration. If they are bytes
855 // strings, they are decoded from the new encoding.
856 status = _PyPreCmdline_SetArgv(&cmdline, args);
857 if (_PyStatus_EXCEPTION(status)) {
858 goto done;
859 }
860 }
861
Victor Stinner331a6a52019-05-27 16:39:22 +0200862 status = preconfig_read(config, &cmdline);
863 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100864 goto done;
865 }
866
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100867 /* The legacy C locale assumes ASCII as the default text encoding, which
868 * causes problems not only for the CPython runtime, but also other
869 * components like GNU readline.
870 *
871 * Accordingly, when the CLI detects it, it attempts to coerce it to a
872 * more capable UTF-8 based alternative.
873 *
874 * See the documentation of the PYTHONCOERCECLOCALE setting for more
875 * details.
876 */
877 int encoding_changed = 0;
878 if (config->coerce_c_locale && !locale_coerced) {
879 locale_coerced = 1;
880 _Py_CoerceLegacyLocale(0);
881 encoding_changed = 1;
882 }
883
884 if (utf8_mode == -1) {
885 if (config->utf8_mode == 1) {
886 /* UTF-8 Mode enabled */
887 encoding_changed = 1;
888 }
889 }
890 else {
891 if (config->utf8_mode != utf8_mode) {
892 encoding_changed = 1;
893 }
894 }
895
896 if (!encoding_changed) {
897 break;
898 }
899
900 /* Reset the configuration before reading again the configuration,
Victor Stinner8eb4aea2020-06-10 19:33:11 +0200901 just keep UTF-8 Mode and coerce C locale value. */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100902 int new_utf8_mode = config->utf8_mode;
903 int new_coerce_c_locale = config->coerce_c_locale;
Victor Stinner331a6a52019-05-27 16:39:22 +0200904 preconfig_copy(config, &save_config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100905 config->utf8_mode = new_utf8_mode;
906 config->coerce_c_locale = new_coerce_c_locale;
907
908 /* The encoding changed: read again the configuration
909 with the new encoding */
910 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200911 status = _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100912
913done:
914 if (init_ctype_locale != NULL) {
915 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100916 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100917 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100918 Py_UTF8Mode = init_utf8_mode ;
919#ifdef MS_WINDOWS
920 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
921#endif
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100922 _PyPreCmdline_Clear(&cmdline);
Victor Stinner331a6a52019-05-27 16:39:22 +0200923 return status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100924}
925
926
Victor Stinner4fffd382019-03-06 01:44:31 +0100927/* Write the pre-configuration:
928
929 - set the memory allocators
930 - set Py_xxx global configuration variables
931 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
932 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100933
Victor Stinner0f721472019-05-20 17:16:38 +0200934 The applied configuration is written into _PyRuntime.preconfig.
935 If the C locale cannot be coerced, set coerce_c_locale to 0.
Victor Stinner4fffd382019-03-06 01:44:31 +0100936
937 Do nothing if called after Py_Initialize(): ignore the new
938 pre-configuration. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200939PyStatus
940_PyPreConfig_Write(const PyPreConfig *src_config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100941{
Victor Stinner331a6a52019-05-27 16:39:22 +0200942 PyPreConfig config;
Victor Stinner441b10c2019-09-28 04:28:35 +0200943
944 PyStatus status = _PyPreConfig_InitFromPreConfig(&config, src_config);
945 if (_PyStatus_EXCEPTION(status)) {
946 return status;
947 }
Victor Stinner0f721472019-05-20 17:16:38 +0200948
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100949 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100950 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100951 the new configuration. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200952 return _PyStatus_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100953 }
954
Victor Stinner0f721472019-05-20 17:16:38 +0200955 PyMemAllocatorName name = (PyMemAllocatorName)config.allocator;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200956 if (name != PYMEM_ALLOCATOR_NOT_SET) {
957 if (_PyMem_SetupAllocators(name) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200958 return _PyStatus_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100959 }
960 }
961
Victor Stinner331a6a52019-05-27 16:39:22 +0200962 preconfig_set_global_vars(&config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100963
Victor Stinner0f721472019-05-20 17:16:38 +0200964 if (config.configure_locale) {
965 if (config.coerce_c_locale) {
966 if (!_Py_CoerceLegacyLocale(config.coerce_c_locale_warn)) {
967 /* C locale not coerced */
968 config.coerce_c_locale = 0;
969 }
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200970 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100971
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200972 /* Set LC_CTYPE to the user preferred locale */
973 _Py_SetLocaleFromEnv(LC_CTYPE);
974 }
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100975
Victor Stinner6d5ee972019-03-23 12:05:43 +0100976 /* Write the new pre-configuration into _PyRuntime */
Victor Stinner331a6a52019-05-27 16:39:22 +0200977 preconfig_copy(&_PyRuntime.preconfig, &config);
Victor Stinner6d5ee972019-03-23 12:05:43 +0100978
Victor Stinner331a6a52019-05-27 16:39:22 +0200979 return _PyStatus_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100980}