blob: ae1cc3f90fca7f18eec1e582c4584b7ef33f71f0 [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);
Inada Naoki48274832021-03-29 12:28:14 +0900172 COPY_ATTR(warn_default_encoding);
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
Inada Naoki48274832021-03-29 12:28:14 +0900261 // warn_default_encoding
262 if (_Py_get_xoption(&cmdline->xoptions, L"warn_default_encoding")
263 || _Py_GetEnv(cmdline->use_environment, "PYTHONWARNDEFAULTENCODING"))
264 {
265 cmdline->warn_default_encoding = 1;
266 }
267
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100268 assert(cmdline->use_environment >= 0);
269 assert(cmdline->isolated >= 0);
270 assert(cmdline->dev_mode >= 0);
Inada Naoki48274832021-03-29 12:28:14 +0900271 assert(cmdline->warn_default_encoding >= 0);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100272
Victor Stinner331a6a52019-05-27 16:39:22 +0200273 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100274}
275
276
Victor Stinner331a6a52019-05-27 16:39:22 +0200277/* --- PyPreConfig ----------------------------------------------- */
Victor Stinnercad1f742019-03-05 02:01:27 +0100278
Victor Stinnerbab0db62019-05-18 03:21:27 +0200279
Victor Stinner3c30a762019-10-01 10:56:37 +0200280void
Victor Stinner331a6a52019-05-27 16:39:22 +0200281_PyPreConfig_InitCompatConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200282{
Victor Stinnerbab0db62019-05-18 03:21:27 +0200283 memset(config, 0, sizeof(*config));
Victor Stinner441b10c2019-09-28 04:28:35 +0200284
Victor Stinner022be022019-05-22 23:58:50 +0200285 config->_config_init = (int)_PyConfig_INIT_COMPAT;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200286 config->parse_argv = 0;
Victor Stinnerbab0db62019-05-18 03:21:27 +0200287 config->isolated = -1;
288 config->use_environment = -1;
289 config->configure_locale = 1;
Victor Stinner20e1e252019-05-23 04:12:27 +0200290
291 /* bpo-36443: C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
292 are disabled by default using the Compat configuration.
293
294 Py_UTF8Mode=1 enables the UTF-8 mode. PYTHONUTF8 environment variable
295 is ignored (even if use_environment=1). */
296 config->utf8_mode = 0;
297 config->coerce_c_locale = 0;
298 config->coerce_c_locale_warn = 0;
299
Victor Stinnerbab0db62019-05-18 03:21:27 +0200300 config->dev_mode = -1;
Victor Stinnerc5fa3642020-05-05 16:41:11 +0200301#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
302 /* bpo-40512: pymalloc is not compatible with subinterpreters,
303 force usage of libc malloc() which is thread-safe. */
304#ifdef Py_DEBUG
305 config->allocator = PYMEM_ALLOCATOR_MALLOC_DEBUG;
306#else
307 config->allocator = PYMEM_ALLOCATOR_MALLOC;
308#endif
309#else
Victor Stinnerbab0db62019-05-18 03:21:27 +0200310 config->allocator = PYMEM_ALLOCATOR_NOT_SET;
Victor Stinnerc5fa3642020-05-05 16:41:11 +0200311#endif
Victor Stinnerbab0db62019-05-18 03:21:27 +0200312#ifdef MS_WINDOWS
313 config->legacy_windows_fs_encoding = -1;
314#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200315}
316
317
Victor Stinner3c30a762019-10-01 10:56:37 +0200318void
Victor Stinner331a6a52019-05-27 16:39:22 +0200319PyPreConfig_InitPythonConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200320{
Victor Stinner3c30a762019-10-01 10:56:37 +0200321 _PyPreConfig_InitCompatConfig(config);
Victor Stinnercab5d072019-05-17 19:01:14 +0200322
Victor Stinner022be022019-05-22 23:58:50 +0200323 config->_config_init = (int)_PyConfig_INIT_PYTHON;
324 config->isolated = 0;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200325 config->parse_argv = 1;
Victor Stinner022be022019-05-22 23:58:50 +0200326 config->use_environment = 1;
Victor Stinnercab5d072019-05-17 19:01:14 +0200327 /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
328 depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE
329 environment variables. */
330 config->coerce_c_locale = -1;
331 config->coerce_c_locale_warn = -1;
332 config->utf8_mode = -1;
Victor Stinner022be022019-05-22 23:58:50 +0200333#ifdef MS_WINDOWS
334 config->legacy_windows_fs_encoding = 0;
335#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200336}
337
338
Victor Stinner3c30a762019-10-01 10:56:37 +0200339void
Victor Stinner331a6a52019-05-27 16:39:22 +0200340PyPreConfig_InitIsolatedConfig(PyPreConfig *config)
Victor Stinnercab5d072019-05-17 19:01:14 +0200341{
Victor Stinner3c30a762019-10-01 10:56:37 +0200342 _PyPreConfig_InitCompatConfig(config);
Victor Stinnercab5d072019-05-17 19:01:14 +0200343
Victor Stinner022be022019-05-22 23:58:50 +0200344 config->_config_init = (int)_PyConfig_INIT_ISOLATED;
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200345 config->configure_locale = 0;
Victor Stinnercab5d072019-05-17 19:01:14 +0200346 config->isolated = 1;
347 config->use_environment = 0;
Victor Stinnerbab0db62019-05-18 03:21:27 +0200348 config->utf8_mode = 0;
349 config->dev_mode = 0;
Victor Stinnercab5d072019-05-17 19:01:14 +0200350#ifdef MS_WINDOWS
351 config->legacy_windows_fs_encoding = 0;
352#endif
Victor Stinnercab5d072019-05-17 19:01:14 +0200353}
354
355
Victor Stinner441b10c2019-09-28 04:28:35 +0200356PyStatus
Victor Stinner331a6a52019-05-27 16:39:22 +0200357_PyPreConfig_InitFromPreConfig(PyPreConfig *config,
358 const PyPreConfig *config2)
Victor Stinner6d1c4672019-05-20 11:02:00 +0200359{
Victor Stinner3c30a762019-10-01 10:56:37 +0200360 PyPreConfig_InitPythonConfig(config);
Victor Stinner331a6a52019-05-27 16:39:22 +0200361 preconfig_copy(config, config2);
Victor Stinner441b10c2019-09-28 04:28:35 +0200362 return _PyStatus_OK();
Victor Stinner6d1c4672019-05-20 11:02:00 +0200363}
364
365
Victor Stinner3c30a762019-10-01 10:56:37 +0200366void
Victor Stinner331a6a52019-05-27 16:39:22 +0200367_PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config)
Victor Stinner6d1c4672019-05-20 11:02:00 +0200368{
Victor Stinner331a6a52019-05-27 16:39:22 +0200369 _PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200370 switch (config_init) {
Victor Stinner022be022019-05-22 23:58:50 +0200371 case _PyConfig_INIT_PYTHON:
Victor Stinner3c30a762019-10-01 10:56:37 +0200372 PyPreConfig_InitPythonConfig(preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200373 break;
Victor Stinner022be022019-05-22 23:58:50 +0200374 case _PyConfig_INIT_ISOLATED:
Victor Stinner3c30a762019-10-01 10:56:37 +0200375 PyPreConfig_InitIsolatedConfig(preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200376 break;
Victor Stinner022be022019-05-22 23:58:50 +0200377 case _PyConfig_INIT_COMPAT:
Victor Stinner6d1c4672019-05-20 11:02:00 +0200378 default:
Victor Stinner3c30a762019-10-01 10:56:37 +0200379 _PyPreConfig_InitCompatConfig(preconfig);
Victor Stinner441b10c2019-09-28 04:28:35 +0200380 }
381
Victor Stinner331a6a52019-05-27 16:39:22 +0200382 _PyPreConfig_GetConfig(preconfig, config);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200383}
384
385
Victor Stinner331a6a52019-05-27 16:39:22 +0200386static void
387preconfig_copy(PyPreConfig *config, const PyPreConfig *config2)
Victor Stinnercad1f742019-03-05 02:01:27 +0100388{
Victor Stinnercad1f742019-03-05 02:01:27 +0100389#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
390
Victor Stinner20e1e252019-05-23 04:12:27 +0200391 COPY_ATTR(_config_init);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200392 COPY_ATTR(parse_argv);
Victor Stinnercad1f742019-03-05 02:01:27 +0100393 COPY_ATTR(isolated);
394 COPY_ATTR(use_environment);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200395 COPY_ATTR(configure_locale);
Victor Stinner20004952019-03-26 02:31:11 +0100396 COPY_ATTR(dev_mode);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100397 COPY_ATTR(coerce_c_locale);
398 COPY_ATTR(coerce_c_locale_warn);
Victor Stinnerb5947842019-05-18 00:38:16 +0200399 COPY_ATTR(utf8_mode);
400 COPY_ATTR(allocator);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100401#ifdef MS_WINDOWS
402 COPY_ATTR(legacy_windows_fs_encoding);
403#endif
Victor Stinnercad1f742019-03-05 02:01:27 +0100404
405#undef COPY_ATTR
Victor Stinnercad1f742019-03-05 02:01:27 +0100406}
407
408
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100409PyObject*
Victor Stinner331a6a52019-05-27 16:39:22 +0200410_PyPreConfig_AsDict(const PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100411{
412 PyObject *dict;
413
414 dict = PyDict_New();
415 if (dict == NULL) {
416 return NULL;
417 }
418
Victor Stinner6d1c4672019-05-20 11:02:00 +0200419#define SET_ITEM_INT(ATTR) \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100420 do { \
Victor Stinner6d1c4672019-05-20 11:02:00 +0200421 PyObject *obj = PyLong_FromLong(config->ATTR); \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100422 if (obj == NULL) { \
423 goto fail; \
424 } \
Victor Stinner6d1c4672019-05-20 11:02:00 +0200425 int res = PyDict_SetItemString(dict, #ATTR, obj); \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100426 Py_DECREF(obj); \
427 if (res < 0) { \
428 goto fail; \
429 } \
430 } while (0)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100431
Victor Stinner20e1e252019-05-23 04:12:27 +0200432 SET_ITEM_INT(_config_init);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200433 SET_ITEM_INT(parse_argv);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100434 SET_ITEM_INT(isolated);
435 SET_ITEM_INT(use_environment);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200436 SET_ITEM_INT(configure_locale);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100437 SET_ITEM_INT(coerce_c_locale);
438 SET_ITEM_INT(coerce_c_locale_warn);
439 SET_ITEM_INT(utf8_mode);
440#ifdef MS_WINDOWS
441 SET_ITEM_INT(legacy_windows_fs_encoding);
442#endif
443 SET_ITEM_INT(dev_mode);
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200444 SET_ITEM_INT(allocator);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100445 return dict;
446
447fail:
448 Py_DECREF(dict);
449 return NULL;
450
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100451#undef SET_ITEM_INT
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100452}
453
454
Victor Stinner5ac27a52019-03-27 13:40:14 +0100455void
Victor Stinner331a6a52019-05-27 16:39:22 +0200456_PyPreConfig_GetConfig(PyPreConfig *preconfig, const PyConfig *config)
Victor Stinner5ac27a52019-03-27 13:40:14 +0100457{
458#define COPY_ATTR(ATTR) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200459 if (config->ATTR != -1) { \
460 preconfig->ATTR = config->ATTR; \
Victor Stinner5ac27a52019-03-27 13:40:14 +0100461 }
462
Victor Stinner6d1c4672019-05-20 11:02:00 +0200463 COPY_ATTR(parse_argv);
Victor Stinner5ac27a52019-03-27 13:40:14 +0100464 COPY_ATTR(isolated);
465 COPY_ATTR(use_environment);
466 COPY_ATTR(dev_mode);
467
468#undef COPY_ATTR
469}
470
471
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100472static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200473preconfig_get_global_vars(PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100474{
Victor Stinner022be022019-05-22 23:58:50 +0200475 if (config->_config_init != _PyConfig_INIT_COMPAT) {
476 /* Python and Isolated configuration ignore global variables */
477 return;
478 }
479
Victor Stinnercad1f742019-03-05 02:01:27 +0100480#define COPY_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200481 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100482 config->ATTR = VALUE; \
483 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100484#define COPY_NOT_FLAG(ATTR, VALUE) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200485 if (config->ATTR < 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100486 config->ATTR = !(VALUE); \
487 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100488
489 COPY_FLAG(isolated, Py_IsolatedFlag);
490 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner20e1e252019-05-23 04:12:27 +0200491 if (Py_UTF8Mode > 0) {
492 config->utf8_mode = Py_UTF8Mode;
493 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100494#ifdef MS_WINDOWS
495 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
496#endif
Victor Stinnercad1f742019-03-05 02:01:27 +0100497
498#undef COPY_FLAG
499#undef COPY_NOT_FLAG
500}
501
502
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100503static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200504preconfig_set_global_vars(const PyPreConfig *config)
Victor Stinnercad1f742019-03-05 02:01:27 +0100505{
506#define COPY_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200507 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100508 VAR = config->ATTR; \
509 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100510#define COPY_NOT_FLAG(ATTR, VAR) \
Victor Stinnercab5d072019-05-17 19:01:14 +0200511 if (config->ATTR >= 0) { \
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100512 VAR = !config->ATTR; \
513 }
Victor Stinnercad1f742019-03-05 02:01:27 +0100514
515 COPY_FLAG(isolated, Py_IsolatedFlag);
516 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100517#ifdef MS_WINDOWS
518 COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
519#endif
520 COPY_FLAG(utf8_mode, Py_UTF8Mode);
Victor Stinnercad1f742019-03-05 02:01:27 +0100521
522#undef COPY_FLAG
523#undef COPY_NOT_FLAG
524}
525
526
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100527const char*
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100528_Py_GetEnv(int use_environment, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100529{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100530 assert(use_environment >= 0);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100531
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100532 if (!use_environment) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100533 return NULL;
534 }
535
536 const char *var = getenv(name);
537 if (var && var[0] != '\0') {
538 return var;
539 }
540 else {
541 return NULL;
542 }
543}
544
545
546int
547_Py_str_to_int(const char *str, int *result)
548{
549 const char *endptr = str;
550 errno = 0;
551 long value = strtol(str, (char **)&endptr, 10);
552 if (*endptr != '\0' || errno == ERANGE) {
553 return -1;
554 }
555 if (value < INT_MIN || value > INT_MAX) {
556 return -1;
557 }
558
559 *result = (int)value;
560 return 0;
561}
562
563
564void
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100565_Py_get_env_flag(int use_environment, int *flag, const char *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100566{
Victor Stinnerf78a5e92019-03-26 00:03:15 +0100567 const char *var = _Py_GetEnv(use_environment, name);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100568 if (!var) {
569 return;
570 }
571 int value;
572 if (_Py_str_to_int(var, &value) < 0 || value < 0) {
573 /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
574 value = 1;
575 }
576 if (*flag < value) {
577 *flag = value;
578 }
579}
580
581
582const wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200583_Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100584{
Victor Stinner74f65682019-03-15 15:08:05 +0100585 for (Py_ssize_t i=0; i < xoptions->length; i++) {
586 const wchar_t *option = xoptions->items[i];
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100587 size_t len;
588 wchar_t *sep = wcschr(option, L'=');
589 if (sep != NULL) {
590 len = (sep - option);
591 }
592 else {
593 len = wcslen(option);
594 }
595 if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
596 return option;
597 }
598 }
599 return NULL;
600}
601
602
Victor Stinner331a6a52019-05-27 16:39:22 +0200603static PyStatus
604preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100605{
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100606#ifdef MS_WINDOWS
607 if (config->legacy_windows_fs_encoding) {
608 config->utf8_mode = 0;
609 }
610#endif
611
612 if (config->utf8_mode >= 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200613 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100614 }
615
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100616 const wchar_t *xopt;
Victor Stinner022be022019-05-22 23:58:50 +0200617 xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100618 if (xopt) {
619 wchar_t *sep = wcschr(xopt, L'=');
620 if (sep) {
621 xopt = sep + 1;
622 if (wcscmp(xopt, L"1") == 0) {
623 config->utf8_mode = 1;
624 }
625 else if (wcscmp(xopt, L"0") == 0) {
626 config->utf8_mode = 0;
627 }
628 else {
Victor Stinner331a6a52019-05-27 16:39:22 +0200629 return _PyStatus_ERR("invalid -X utf8 option value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100630 }
631 }
632 else {
633 config->utf8_mode = 1;
634 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200635 return _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100636 }
637
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100638 const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100639 if (opt) {
640 if (strcmp(opt, "1") == 0) {
641 config->utf8_mode = 1;
642 }
643 else if (strcmp(opt, "0") == 0) {
644 config->utf8_mode = 0;
645 }
646 else {
Victor Stinner331a6a52019-05-27 16:39:22 +0200647 return _PyStatus_ERR("invalid PYTHONUTF8 environment "
Victor Stinnerdb719752019-05-01 05:35:33 +0200648 "variable value");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100649 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200650 return _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100651 }
652
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100653
654#ifndef MS_WINDOWS
655 if (config->utf8_mode < 0) {
656 /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
657 const char *ctype_loc = setlocale(LC_CTYPE, NULL);
658 if (ctype_loc != NULL
659 && (strcmp(ctype_loc, "C") == 0
660 || strcmp(ctype_loc, "POSIX") == 0))
661 {
662 config->utf8_mode = 1;
663 }
664 }
665#endif
666
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100667 if (config->utf8_mode < 0) {
668 config->utf8_mode = 0;
669 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200670 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100671}
672
673
674static void
Victor Stinner331a6a52019-05-27 16:39:22 +0200675preconfig_init_coerce_c_locale(PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100676{
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200677 if (!config->configure_locale) {
678 config->coerce_c_locale = 0;
679 config->coerce_c_locale_warn = 0;
680 return;
681 }
682
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100683 const char *env = _Py_GetEnv(config->use_environment, "PYTHONCOERCECLOCALE");
684 if (env) {
685 if (strcmp(env, "0") == 0) {
686 if (config->coerce_c_locale < 0) {
687 config->coerce_c_locale = 0;
688 }
689 }
690 else if (strcmp(env, "warn") == 0) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200691 if (config->coerce_c_locale_warn < 0) {
692 config->coerce_c_locale_warn = 1;
693 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100694 }
695 else {
696 if (config->coerce_c_locale < 0) {
697 config->coerce_c_locale = 1;
698 }
699 }
700 }
701
702 /* Test if coerce_c_locale equals to -1 or equals to 1:
703 PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.
704 It is only coerced if if the LC_CTYPE locale is "C". */
Victor Stinnercab5d072019-05-17 19:01:14 +0200705 if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) {
706 /* The C locale enables the C locale coercion (PEP 538) */
Victor Stinner0f721472019-05-20 17:16:38 +0200707 if (_Py_LegacyLocaleDetected(0)) {
Victor Stinnercab5d072019-05-17 19:01:14 +0200708 config->coerce_c_locale = 2;
709 }
710 else {
711 config->coerce_c_locale = 0;
712 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100713 }
714
Victor Stinnercab5d072019-05-17 19:01:14 +0200715 if (config->coerce_c_locale_warn < 0) {
716 config->coerce_c_locale_warn = 0;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100717 }
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100718}
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100719
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100720
Victor Stinner331a6a52019-05-27 16:39:22 +0200721static PyStatus
722preconfig_init_allocator(PyPreConfig *config)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100723{
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200724 if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
Victor Stinner25d13f32019-03-06 12:51:53 +0100725 /* bpo-34247. The PYTHONMALLOC environment variable has the priority
726 over PYTHONDEV env var and "-X dev" command line option.
727 For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
728 allocators to "malloc" (and not to "debug"). */
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200729 const char *envvar = _Py_GetEnv(config->use_environment, "PYTHONMALLOC");
730 if (envvar) {
Victor Stinner6d1c4672019-05-20 11:02:00 +0200731 PyMemAllocatorName name;
732 if (_PyMem_GetAllocatorName(envvar, &name) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200733 return _PyStatus_ERR("PYTHONMALLOC: unknown allocator");
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100734 }
Victor Stinner6d1c4672019-05-20 11:02:00 +0200735 config->allocator = (int)name;
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100736 }
737 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100738
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200739 if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
740 config->allocator = PYMEM_ALLOCATOR_DEBUG;
Victor Stinner25d13f32019-03-06 12:51:53 +0100741 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200742 return _PyStatus_OK();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100743}
744
745
Victor Stinner331a6a52019-05-27 16:39:22 +0200746static PyStatus
747preconfig_read(PyPreConfig *config, _PyPreCmdline *cmdline)
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100748{
Victor Stinner331a6a52019-05-27 16:39:22 +0200749 PyStatus status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100750
Victor Stinner331a6a52019-05-27 16:39:22 +0200751 status = _PyPreCmdline_Read(cmdline, config);
752 if (_PyStatus_EXCEPTION(status)) {
753 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100754 }
755
Victor Stinner331a6a52019-05-27 16:39:22 +0200756 precmdline_set_preconfig(cmdline, config);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100757
758 /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
759#ifdef MS_WINDOWS
760 _Py_get_env_flag(config->use_environment,
761 &config->legacy_windows_fs_encoding,
762 "PYTHONLEGACYWINDOWSFSENCODING");
763#endif
764
765 preconfig_init_coerce_c_locale(config);
766
Victor Stinner331a6a52019-05-27 16:39:22 +0200767 status = preconfig_init_utf8_mode(config, cmdline);
768 if (_PyStatus_EXCEPTION(status)) {
769 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100770 }
771
772 /* allocator */
Victor Stinner331a6a52019-05-27 16:39:22 +0200773 status = preconfig_init_allocator(config);
774 if (_PyStatus_EXCEPTION(status)) {
775 return status;
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100776 }
Victor Stinner25d13f32019-03-06 12:51:53 +0100777
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100778 assert(config->coerce_c_locale >= 0);
Victor Stinnercab5d072019-05-17 19:01:14 +0200779 assert(config->coerce_c_locale_warn >= 0);
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100780#ifdef MS_WINDOWS
781 assert(config->legacy_windows_fs_encoding >= 0);
782#endif
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100783 assert(config->utf8_mode >= 0);
Victor Stinner6dcb5422019-03-05 02:44:12 +0100784 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100785 assert(config->use_environment >= 0);
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100786 assert(config->dev_mode >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100787
Victor Stinner331a6a52019-05-27 16:39:22 +0200788 return _PyStatus_OK();
Victor Stinnercad1f742019-03-05 02:01:27 +0100789}
790
791
Victor Stinner4fffd382019-03-06 01:44:31 +0100792/* Read the configuration from:
793
794 - command line arguments
795 - environment variables
796 - Py_xxx global configuration variables
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100797 - the LC_CTYPE locale */
Victor Stinner331a6a52019-05-27 16:39:22 +0200798PyStatus
799_PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args)
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100800{
Victor Stinner331a6a52019-05-27 16:39:22 +0200801 PyStatus status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100802
Victor Stinner331a6a52019-05-27 16:39:22 +0200803 status = _PyRuntime_Initialize();
804 if (_PyStatus_EXCEPTION(status)) {
805 return status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100806 }
807
Victor Stinner331a6a52019-05-27 16:39:22 +0200808 preconfig_get_global_vars(config);
Victor Stinnerf29084d2019-03-20 02:20:13 +0100809
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100810 /* Copy LC_CTYPE locale, since it's modified later */
811 const char *loc = setlocale(LC_CTYPE, NULL);
812 if (loc == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200813 return _PyStatus_ERR("failed to LC_CTYPE locale");
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100814 }
815 char *init_ctype_locale = _PyMem_RawStrdup(loc);
816 if (init_ctype_locale == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200817 return _PyStatus_NO_MEMORY();
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100818 }
819
820 /* Save the config to be able to restore it if encodings change */
Victor Stinner331a6a52019-05-27 16:39:22 +0200821 PyPreConfig save_config;
Victor Stinner441b10c2019-09-28 04:28:35 +0200822
823 status = _PyPreConfig_InitFromPreConfig(&save_config, config);
824 if (_PyStatus_EXCEPTION(status)) {
825 return status;
826 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100827
828 /* Set LC_CTYPE to the user preferred locale */
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200829 if (config->configure_locale) {
830 _Py_SetLocaleFromEnv(LC_CTYPE);
831 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100832
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100833 _PyPreCmdline cmdline = _PyPreCmdline_INIT;
Victor Stinner6a8c3132019-04-05 11:44:04 +0200834 int init_utf8_mode = Py_UTF8Mode;
835#ifdef MS_WINDOWS
836 int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
837#endif
838
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100839 int locale_coerced = 0;
840 int loops = 0;
841
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100842 while (1) {
843 int utf8_mode = config->utf8_mode;
844
845 /* Watchdog to prevent an infinite loop */
846 loops++;
847 if (loops == 3) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200848 status = _PyStatus_ERR("Encoding changed twice while "
Victor Stinner8eb4aea2020-06-10 19:33:11 +0200849 "reading the configuration");
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100850 goto done;
851 }
852
853 /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
854 on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
855 Py_UTF8Mode = config->utf8_mode;
856#ifdef MS_WINDOWS
857 Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
858#endif
859
Victor Stinner8eb4aea2020-06-10 19:33:11 +0200860 if (args) {
861 // Set command line arguments at each iteration. If they are bytes
862 // strings, they are decoded from the new encoding.
863 status = _PyPreCmdline_SetArgv(&cmdline, args);
864 if (_PyStatus_EXCEPTION(status)) {
865 goto done;
866 }
867 }
868
Victor Stinner331a6a52019-05-27 16:39:22 +0200869 status = preconfig_read(config, &cmdline);
870 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100871 goto done;
872 }
873
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100874 /* The legacy C locale assumes ASCII as the default text encoding, which
875 * causes problems not only for the CPython runtime, but also other
876 * components like GNU readline.
877 *
878 * Accordingly, when the CLI detects it, it attempts to coerce it to a
879 * more capable UTF-8 based alternative.
880 *
881 * See the documentation of the PYTHONCOERCECLOCALE setting for more
882 * details.
883 */
884 int encoding_changed = 0;
885 if (config->coerce_c_locale && !locale_coerced) {
886 locale_coerced = 1;
887 _Py_CoerceLegacyLocale(0);
888 encoding_changed = 1;
889 }
890
891 if (utf8_mode == -1) {
892 if (config->utf8_mode == 1) {
893 /* UTF-8 Mode enabled */
894 encoding_changed = 1;
895 }
896 }
897 else {
898 if (config->utf8_mode != utf8_mode) {
899 encoding_changed = 1;
900 }
901 }
902
903 if (!encoding_changed) {
904 break;
905 }
906
907 /* Reset the configuration before reading again the configuration,
Victor Stinner8eb4aea2020-06-10 19:33:11 +0200908 just keep UTF-8 Mode and coerce C locale value. */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100909 int new_utf8_mode = config->utf8_mode;
910 int new_coerce_c_locale = config->coerce_c_locale;
Victor Stinner331a6a52019-05-27 16:39:22 +0200911 preconfig_copy(config, &save_config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100912 config->utf8_mode = new_utf8_mode;
913 config->coerce_c_locale = new_coerce_c_locale;
914
915 /* The encoding changed: read again the configuration
916 with the new encoding */
917 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200918 status = _PyStatus_OK();
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100919
920done:
921 if (init_ctype_locale != NULL) {
922 setlocale(LC_CTYPE, init_ctype_locale);
Victor Stinnerc1834442019-03-18 22:24:28 +0100923 PyMem_RawFree(init_ctype_locale);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100924 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100925 Py_UTF8Mode = init_utf8_mode ;
926#ifdef MS_WINDOWS
927 Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
928#endif
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100929 _PyPreCmdline_Clear(&cmdline);
Victor Stinner331a6a52019-05-27 16:39:22 +0200930 return status;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100931}
932
933
Victor Stinner4fffd382019-03-06 01:44:31 +0100934/* Write the pre-configuration:
935
936 - set the memory allocators
937 - set Py_xxx global configuration variables
938 - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
939 (PEP 540)
Victor Stinnerc656e252019-03-06 01:13:43 +0100940
Victor Stinner0f721472019-05-20 17:16:38 +0200941 The applied configuration is written into _PyRuntime.preconfig.
942 If the C locale cannot be coerced, set coerce_c_locale to 0.
Victor Stinner4fffd382019-03-06 01:44:31 +0100943
944 Do nothing if called after Py_Initialize(): ignore the new
945 pre-configuration. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200946PyStatus
947_PyPreConfig_Write(const PyPreConfig *src_config)
Victor Stinner6dcb5422019-03-05 02:44:12 +0100948{
Victor Stinner331a6a52019-05-27 16:39:22 +0200949 PyPreConfig config;
Victor Stinner441b10c2019-09-28 04:28:35 +0200950
951 PyStatus status = _PyPreConfig_InitFromPreConfig(&config, src_config);
952 if (_PyStatus_EXCEPTION(status)) {
953 return status;
954 }
Victor Stinner0f721472019-05-20 17:16:38 +0200955
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100956 if (_PyRuntime.core_initialized) {
Victor Stinner4fffd382019-03-06 01:44:31 +0100957 /* bpo-34008: Calling this functions after Py_Initialize() ignores
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100958 the new configuration. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200959 return _PyStatus_OK();
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100960 }
961
Victor Stinner0f721472019-05-20 17:16:38 +0200962 PyMemAllocatorName name = (PyMemAllocatorName)config.allocator;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200963 if (name != PYMEM_ALLOCATOR_NOT_SET) {
964 if (_PyMem_SetupAllocators(name) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200965 return _PyStatus_ERR("Unknown PYTHONMALLOC allocator");
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100966 }
967 }
968
Victor Stinner331a6a52019-05-27 16:39:22 +0200969 preconfig_set_global_vars(&config);
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100970
Victor Stinner0f721472019-05-20 17:16:38 +0200971 if (config.configure_locale) {
972 if (config.coerce_c_locale) {
973 if (!_Py_CoerceLegacyLocale(config.coerce_c_locale_warn)) {
974 /* C locale not coerced */
975 config.coerce_c_locale = 0;
976 }
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200977 }
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100978
Victor Stinnerbcfbbd72019-05-17 22:44:16 +0200979 /* Set LC_CTYPE to the user preferred locale */
980 _Py_SetLocaleFromEnv(LC_CTYPE);
981 }
Victor Stinner7d2ef3e2019-03-06 00:36:56 +0100982
Victor Stinner6d5ee972019-03-23 12:05:43 +0100983 /* Write the new pre-configuration into _PyRuntime */
Victor Stinner331a6a52019-05-27 16:39:22 +0200984 preconfig_copy(&_PyRuntime.preconfig, &config);
Victor Stinner6d5ee972019-03-23 12:05:43 +0100985
Victor Stinner331a6a52019-05-27 16:39:22 +0200986 return _PyStatus_OK();
Victor Stinner6dcb5422019-03-05 02:44:12 +0100987}