You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

859 lines
21 KiB

  1. #include "Python.h"
  2. #include "pycore_coreconfig.h"
  3. #include "pycore_getopt.h"
  4. #include "pycore_pystate.h" /* _PyRuntime_Initialize() */
  5. #include <locale.h> /* setlocale() */
  6. #define DECODE_LOCALE_ERR(NAME, LEN) \
  7. (((LEN) == -2) \
  8. ? _Py_INIT_ERR("cannot decode " NAME) \
  9. : _Py_INIT_NO_MEMORY())
  10. /* --- File system encoding/errors -------------------------------- */
  11. /* The filesystem encoding is chosen by config_init_fs_encoding(),
  12. see also initfsencoding().
  13. Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
  14. are encoded to UTF-8. */
  15. const char *Py_FileSystemDefaultEncoding = NULL;
  16. int Py_HasFileSystemDefaultEncoding = 0;
  17. const char *Py_FileSystemDefaultEncodeErrors = NULL;
  18. int _Py_HasFileSystemDefaultEncodeErrors = 0;
  19. void
  20. _Py_ClearFileSystemEncoding(void)
  21. {
  22. if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
  23. PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
  24. Py_FileSystemDefaultEncoding = NULL;
  25. }
  26. if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
  27. PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
  28. Py_FileSystemDefaultEncodeErrors = NULL;
  29. }
  30. }
  31. /* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
  32. global configuration variables. */
  33. int
  34. _Py_SetFileSystemEncoding(const char *encoding, const char *errors)
  35. {
  36. char *encoding2 = _PyMem_RawStrdup(encoding);
  37. if (encoding2 == NULL) {
  38. return -1;
  39. }
  40. char *errors2 = _PyMem_RawStrdup(errors);
  41. if (errors2 == NULL) {
  42. PyMem_RawFree(encoding2);
  43. return -1;
  44. }
  45. _Py_ClearFileSystemEncoding();
  46. Py_FileSystemDefaultEncoding = encoding2;
  47. Py_HasFileSystemDefaultEncoding = 0;
  48. Py_FileSystemDefaultEncodeErrors = errors2;
  49. _Py_HasFileSystemDefaultEncodeErrors = 0;
  50. return 0;
  51. }
  52. /* --- _PyArgv ---------------------------------------------------- */
  53. /* Decode bytes_argv using Py_DecodeLocale() */
  54. _PyInitError
  55. _PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list)
  56. {
  57. _PyWstrList wargv = _PyWstrList_INIT;
  58. if (args->use_bytes_argv) {
  59. size_t size = sizeof(wchar_t*) * args->argc;
  60. wargv.items = (wchar_t **)PyMem_RawMalloc(size);
  61. if (wargv.items == NULL) {
  62. return _Py_INIT_NO_MEMORY();
  63. }
  64. for (Py_ssize_t i = 0; i < args->argc; i++) {
  65. size_t len;
  66. wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
  67. if (arg == NULL) {
  68. _PyWstrList_Clear(&wargv);
  69. return DECODE_LOCALE_ERR("command line arguments",
  70. (Py_ssize_t)len);
  71. }
  72. wargv.items[i] = arg;
  73. wargv.length++;
  74. }
  75. _PyWstrList_Clear(list);
  76. *list = wargv;
  77. }
  78. else {
  79. wargv.length = args->argc;
  80. wargv.items = args->wchar_argv;
  81. if (_PyWstrList_Copy(list, &wargv) < 0) {
  82. return _Py_INIT_NO_MEMORY();
  83. }
  84. }
  85. return _Py_INIT_OK();
  86. }
  87. /* --- _PyPreCmdline ------------------------------------------------- */
  88. void
  89. _PyPreCmdline_Clear(_PyPreCmdline *cmdline)
  90. {
  91. _PyWstrList_Clear(&cmdline->argv);
  92. _PyWstrList_Clear(&cmdline->xoptions);
  93. }
  94. _PyInitError
  95. _PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
  96. {
  97. return _PyArgv_AsWstrList(args, &cmdline->argv);
  98. }
  99. static void
  100. _PyPreCmdline_GetPreConfig(_PyPreCmdline *cmdline, const _PyPreConfig *config)
  101. {
  102. #define COPY_ATTR(ATTR) \
  103. if (config->ATTR != -1) { \
  104. cmdline->ATTR = config->ATTR; \
  105. }
  106. COPY_ATTR(isolated);
  107. COPY_ATTR(use_environment);
  108. COPY_ATTR(dev_mode);
  109. #undef COPY_ATTR
  110. }
  111. static void
  112. _PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
  113. {
  114. #define COPY_ATTR(ATTR) \
  115. config->ATTR = cmdline->ATTR
  116. COPY_ATTR(isolated);
  117. COPY_ATTR(use_environment);
  118. COPY_ATTR(dev_mode);
  119. #undef COPY_ATTR
  120. }
  121. int
  122. _PyPreCmdline_SetCoreConfig(const _PyPreCmdline *cmdline, _PyCoreConfig *config)
  123. {
  124. #define COPY_ATTR(ATTR) \
  125. config->ATTR = cmdline->ATTR
  126. if (_PyWstrList_Extend(&config->xoptions, &cmdline->xoptions) < 0) {
  127. return -1;
  128. }
  129. COPY_ATTR(isolated);
  130. COPY_ATTR(use_environment);
  131. COPY_ATTR(dev_mode);
  132. return 0;
  133. #undef COPY_ATTR
  134. }
  135. /* Parse the command line arguments */
  136. static _PyInitError
  137. precmdline_parse_cmdline(_PyPreCmdline *cmdline)
  138. {
  139. const _PyWstrList *argv = &cmdline->argv;
  140. _PyOS_ResetGetOpt();
  141. /* Don't log parsing errors into stderr here: _PyCoreConfig_Read()
  142. is responsible for that */
  143. _PyOS_opterr = 0;
  144. do {
  145. int longindex = -1;
  146. int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
  147. if (c == EOF || c == 'c' || c == 'm') {
  148. break;
  149. }
  150. switch (c) {
  151. case 'E':
  152. cmdline->use_environment = 0;
  153. break;
  154. case 'I':
  155. cmdline->isolated = 1;
  156. break;
  157. case 'X':
  158. {
  159. if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) {
  160. return _Py_INIT_NO_MEMORY();
  161. }
  162. break;
  163. }
  164. default:
  165. /* ignore other argument:
  166. handled by _PyCoreConfig_Read() */
  167. break;
  168. }
  169. } while (1);
  170. return _Py_INIT_OK();
  171. }
  172. _PyInitError
  173. _PyPreCmdline_Read(_PyPreCmdline *cmdline,
  174. const _PyPreConfig *preconfig)
  175. {
  176. if (preconfig) {
  177. _PyPreCmdline_GetPreConfig(cmdline, preconfig);
  178. }
  179. _PyInitError err = precmdline_parse_cmdline(cmdline);
  180. if (_Py_INIT_FAILED(err)) {
  181. return err;
  182. }
  183. /* isolated, use_environment */
  184. if (cmdline->isolated < 0) {
  185. cmdline->isolated = 0;
  186. }
  187. if (cmdline->isolated > 0) {
  188. cmdline->use_environment = 0;
  189. }
  190. if (cmdline->use_environment < 0) {
  191. cmdline->use_environment = 0;
  192. }
  193. /* dev_mode */
  194. if ((cmdline && _Py_get_xoption(&cmdline->xoptions, L"dev"))
  195. || _Py_GetEnv(cmdline->use_environment, "PYTHONDEVMODE"))
  196. {
  197. cmdline->dev_mode = 1;
  198. }
  199. if (cmdline->dev_mode < 0) {
  200. cmdline->dev_mode = 0;
  201. }
  202. assert(cmdline->use_environment >= 0);
  203. assert(cmdline->isolated >= 0);
  204. assert(cmdline->dev_mode >= 0);
  205. return _Py_INIT_OK();
  206. }
  207. /* --- _PyPreConfig ----------------------------------------------- */
  208. int
  209. _PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
  210. {
  211. #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
  212. #define COPY_STR_ATTR(ATTR) \
  213. do { \
  214. if (config2->ATTR != NULL) { \
  215. config->ATTR = _PyMem_RawStrdup(config2->ATTR); \
  216. if (config->ATTR == NULL) { \
  217. return -1; \
  218. } \
  219. } \
  220. } while (0)
  221. COPY_ATTR(isolated);
  222. COPY_ATTR(use_environment);
  223. COPY_ATTR(dev_mode);
  224. COPY_ATTR(coerce_c_locale);
  225. COPY_ATTR(coerce_c_locale_warn);
  226. #ifdef MS_WINDOWS
  227. COPY_ATTR(legacy_windows_fs_encoding);
  228. #endif
  229. COPY_ATTR(utf8_mode);
  230. COPY_ATTR(allocator);
  231. #undef COPY_ATTR
  232. #undef COPY_STR_ATTR
  233. return 0;
  234. }
  235. PyObject*
  236. _PyPreConfig_AsDict(const _PyPreConfig *config)
  237. {
  238. PyObject *dict;
  239. dict = PyDict_New();
  240. if (dict == NULL) {
  241. return NULL;
  242. }
  243. #define SET_ITEM(KEY, EXPR) \
  244. do { \
  245. PyObject *obj = (EXPR); \
  246. if (obj == NULL) { \
  247. goto fail; \
  248. } \
  249. int res = PyDict_SetItemString(dict, (KEY), obj); \
  250. Py_DECREF(obj); \
  251. if (res < 0) { \
  252. goto fail; \
  253. } \
  254. } while (0)
  255. #define SET_ITEM_INT(ATTR) \
  256. SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
  257. #define FROM_STRING(STR) \
  258. ((STR != NULL) ? \
  259. PyUnicode_FromString(STR) \
  260. : (Py_INCREF(Py_None), Py_None))
  261. #define SET_ITEM_STR(ATTR) \
  262. SET_ITEM(#ATTR, FROM_STRING(config->ATTR))
  263. SET_ITEM_INT(isolated);
  264. SET_ITEM_INT(use_environment);
  265. SET_ITEM_INT(coerce_c_locale);
  266. SET_ITEM_INT(coerce_c_locale_warn);
  267. SET_ITEM_INT(utf8_mode);
  268. #ifdef MS_WINDOWS
  269. SET_ITEM_INT(legacy_windows_fs_encoding);
  270. #endif
  271. SET_ITEM_INT(dev_mode);
  272. SET_ITEM_INT(allocator);
  273. return dict;
  274. fail:
  275. Py_DECREF(dict);
  276. return NULL;
  277. #undef FROM_STRING
  278. #undef SET_ITEM
  279. #undef SET_ITEM_INT
  280. #undef SET_ITEM_STR
  281. }
  282. void
  283. _PyCoreConfig_GetCoreConfig(_PyPreConfig *config,
  284. const _PyCoreConfig *core_config)
  285. {
  286. #define COPY_ATTR(ATTR) \
  287. if (core_config->ATTR != -1) { \
  288. config->ATTR = core_config->ATTR; \
  289. }
  290. COPY_ATTR(isolated);
  291. COPY_ATTR(use_environment);
  292. COPY_ATTR(dev_mode);
  293. #undef COPY_ATTR
  294. }
  295. static void
  296. _PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
  297. {
  298. #define COPY_FLAG(ATTR, VALUE) \
  299. if (config->ATTR == -1) { \
  300. config->ATTR = VALUE; \
  301. }
  302. #define COPY_NOT_FLAG(ATTR, VALUE) \
  303. if (config->ATTR == -1) { \
  304. config->ATTR = !(VALUE); \
  305. }
  306. COPY_FLAG(isolated, Py_IsolatedFlag);
  307. COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
  308. #ifdef MS_WINDOWS
  309. COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
  310. #endif
  311. if (Py_UTF8Mode > 0) {
  312. config->utf8_mode = 1;
  313. }
  314. #undef COPY_FLAG
  315. #undef COPY_NOT_FLAG
  316. }
  317. static void
  318. _PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
  319. {
  320. #define COPY_FLAG(ATTR, VAR) \
  321. if (config->ATTR != -1) { \
  322. VAR = config->ATTR; \
  323. }
  324. #define COPY_NOT_FLAG(ATTR, VAR) \
  325. if (config->ATTR != -1) { \
  326. VAR = !config->ATTR; \
  327. }
  328. COPY_FLAG(isolated, Py_IsolatedFlag);
  329. COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
  330. #ifdef MS_WINDOWS
  331. COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
  332. #endif
  333. COPY_FLAG(utf8_mode, Py_UTF8Mode);
  334. #undef COPY_FLAG
  335. #undef COPY_NOT_FLAG
  336. }
  337. const char*
  338. _Py_GetEnv(int use_environment, const char *name)
  339. {
  340. assert(use_environment >= 0);
  341. if (!use_environment) {
  342. return NULL;
  343. }
  344. const char *var = getenv(name);
  345. if (var && var[0] != '\0') {
  346. return var;
  347. }
  348. else {
  349. return NULL;
  350. }
  351. }
  352. int
  353. _Py_str_to_int(const char *str, int *result)
  354. {
  355. const char *endptr = str;
  356. errno = 0;
  357. long value = strtol(str, (char **)&endptr, 10);
  358. if (*endptr != '\0' || errno == ERANGE) {
  359. return -1;
  360. }
  361. if (value < INT_MIN || value > INT_MAX) {
  362. return -1;
  363. }
  364. *result = (int)value;
  365. return 0;
  366. }
  367. void
  368. _Py_get_env_flag(int use_environment, int *flag, const char *name)
  369. {
  370. const char *var = _Py_GetEnv(use_environment, name);
  371. if (!var) {
  372. return;
  373. }
  374. int value;
  375. if (_Py_str_to_int(var, &value) < 0 || value < 0) {
  376. /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
  377. value = 1;
  378. }
  379. if (*flag < value) {
  380. *flag = value;
  381. }
  382. }
  383. const wchar_t*
  384. _Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
  385. {
  386. for (Py_ssize_t i=0; i < xoptions->length; i++) {
  387. const wchar_t *option = xoptions->items[i];
  388. size_t len;
  389. wchar_t *sep = wcschr(option, L'=');
  390. if (sep != NULL) {
  391. len = (sep - option);
  392. }
  393. else {
  394. len = wcslen(option);
  395. }
  396. if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
  397. return option;
  398. }
  399. }
  400. return NULL;
  401. }
  402. static _PyInitError
  403. preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
  404. {
  405. #ifdef MS_WINDOWS
  406. if (config->legacy_windows_fs_encoding) {
  407. config->utf8_mode = 0;
  408. }
  409. #endif
  410. if (config->utf8_mode >= 0) {
  411. return _Py_INIT_OK();
  412. }
  413. const wchar_t *xopt;
  414. if (cmdline) {
  415. xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
  416. }
  417. else {
  418. xopt = NULL;
  419. }
  420. if (xopt) {
  421. wchar_t *sep = wcschr(xopt, L'=');
  422. if (sep) {
  423. xopt = sep + 1;
  424. if (wcscmp(xopt, L"1") == 0) {
  425. config->utf8_mode = 1;
  426. }
  427. else if (wcscmp(xopt, L"0") == 0) {
  428. config->utf8_mode = 0;
  429. }
  430. else {
  431. return _Py_INIT_ERR("invalid -X utf8 option value");
  432. }
  433. }
  434. else {
  435. config->utf8_mode = 1;
  436. }
  437. return _Py_INIT_OK();
  438. }
  439. const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
  440. if (opt) {
  441. if (strcmp(opt, "1") == 0) {
  442. config->utf8_mode = 1;
  443. }
  444. else if (strcmp(opt, "0") == 0) {
  445. config->utf8_mode = 0;
  446. }
  447. else {
  448. return _Py_INIT_ERR("invalid PYTHONUTF8 environment "
  449. "variable value");
  450. }
  451. return _Py_INIT_OK();
  452. }
  453. #ifndef MS_WINDOWS
  454. if (config->utf8_mode < 0) {
  455. /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
  456. const char *ctype_loc = setlocale(LC_CTYPE, NULL);
  457. if (ctype_loc != NULL
  458. && (strcmp(ctype_loc, "C") == 0
  459. || strcmp(ctype_loc, "POSIX") == 0))
  460. {
  461. config->utf8_mode = 1;
  462. }
  463. }
  464. #endif
  465. if (config->utf8_mode < 0) {
  466. config->utf8_mode = 0;
  467. }
  468. return _Py_INIT_OK();
  469. }
  470. static void
  471. preconfig_init_coerce_c_locale(_PyPreConfig *config)
  472. {
  473. const char *env = _Py_GetEnv(config->use_environment, "PYTHONCOERCECLOCALE");
  474. if (env) {
  475. if (strcmp(env, "0") == 0) {
  476. if (config->coerce_c_locale < 0) {
  477. config->coerce_c_locale = 0;
  478. }
  479. }
  480. else if (strcmp(env, "warn") == 0) {
  481. config->coerce_c_locale_warn = 1;
  482. }
  483. else {
  484. if (config->coerce_c_locale < 0) {
  485. config->coerce_c_locale = 1;
  486. }
  487. }
  488. }
  489. /* Test if coerce_c_locale equals to -1 or equals to 1:
  490. PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.
  491. It is only coerced if if the LC_CTYPE locale is "C". */
  492. if (config->coerce_c_locale == 0 || config->coerce_c_locale == 2) {
  493. return;
  494. }
  495. /* The C locale enables the C locale coercion (PEP 538) */
  496. if (_Py_LegacyLocaleDetected()) {
  497. config->coerce_c_locale = 2;
  498. }
  499. else {
  500. config->coerce_c_locale = 0;
  501. }
  502. assert(config->coerce_c_locale >= 0);
  503. }
  504. static _PyInitError
  505. preconfig_init_allocator(_PyPreConfig *config)
  506. {
  507. if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
  508. /* bpo-34247. The PYTHONMALLOC environment variable has the priority
  509. over PYTHONDEV env var and "-X dev" command line option.
  510. For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
  511. allocators to "malloc" (and not to "debug"). */
  512. const char *envvar = _Py_GetEnv(config->use_environment, "PYTHONMALLOC");
  513. if (envvar) {
  514. if (_PyMem_GetAllocatorName(envvar, &config->allocator) < 0) {
  515. return _Py_INIT_ERR("PYTHONMALLOC: unknown allocator");
  516. }
  517. }
  518. }
  519. if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
  520. config->allocator = PYMEM_ALLOCATOR_DEBUG;
  521. }
  522. return _Py_INIT_OK();
  523. }
  524. static _PyInitError
  525. preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
  526. {
  527. _PyInitError err;
  528. err = _PyPreCmdline_Read(cmdline, config);
  529. if (_Py_INIT_FAILED(err)) {
  530. return err;
  531. }
  532. _PyPreCmdline_SetPreConfig(cmdline, config);
  533. /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
  534. #ifdef MS_WINDOWS
  535. _Py_get_env_flag(config->use_environment,
  536. &config->legacy_windows_fs_encoding,
  537. "PYTHONLEGACYWINDOWSFSENCODING");
  538. #endif
  539. preconfig_init_coerce_c_locale(config);
  540. err = preconfig_init_utf8_mode(config, cmdline);
  541. if (_Py_INIT_FAILED(err)) {
  542. return err;
  543. }
  544. /* allocator */
  545. err = preconfig_init_allocator(config);
  546. if (_Py_INIT_FAILED(err)) {
  547. return err;
  548. }
  549. assert(config->coerce_c_locale >= 0);
  550. #ifdef MS_WINDOWS
  551. assert(config->legacy_windows_fs_encoding >= 0);
  552. #endif
  553. assert(config->utf8_mode >= 0);
  554. assert(config->isolated >= 0);
  555. assert(config->use_environment >= 0);
  556. assert(config->dev_mode >= 0);
  557. return _Py_INIT_OK();
  558. }
  559. /* Read the configuration from:
  560. - command line arguments
  561. - environment variables
  562. - Py_xxx global configuration variables
  563. - the LC_CTYPE locale */
  564. _PyInitError
  565. _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args)
  566. {
  567. _PyInitError err;
  568. err = _PyRuntime_Initialize();
  569. if (_Py_INIT_FAILED(err)) {
  570. return err;
  571. }
  572. _PyPreConfig_GetGlobalConfig(config);
  573. /* Copy LC_CTYPE locale, since it's modified later */
  574. const char *loc = setlocale(LC_CTYPE, NULL);
  575. if (loc == NULL) {
  576. return _Py_INIT_ERR("failed to LC_CTYPE locale");
  577. }
  578. char *init_ctype_locale = _PyMem_RawStrdup(loc);
  579. if (init_ctype_locale == NULL) {
  580. return _Py_INIT_NO_MEMORY();
  581. }
  582. /* Save the config to be able to restore it if encodings change */
  583. _PyPreConfig save_config = _PyPreConfig_INIT;
  584. if (_PyPreConfig_Copy(&save_config, config) < 0) {
  585. return _Py_INIT_NO_MEMORY();
  586. }
  587. /* Set LC_CTYPE to the user preferred locale */
  588. _Py_SetLocaleFromEnv(LC_CTYPE);
  589. _PyPreCmdline cmdline = _PyPreCmdline_INIT;
  590. int init_utf8_mode = Py_UTF8Mode;
  591. #ifdef MS_WINDOWS
  592. int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
  593. #endif
  594. if (args) {
  595. err = _PyPreCmdline_SetArgv(&cmdline, args);
  596. if (_Py_INIT_FAILED(err)) {
  597. goto done;
  598. }
  599. }
  600. int locale_coerced = 0;
  601. int loops = 0;
  602. while (1) {
  603. int utf8_mode = config->utf8_mode;
  604. /* Watchdog to prevent an infinite loop */
  605. loops++;
  606. if (loops == 3) {
  607. err = _Py_INIT_ERR("Encoding changed twice while "
  608. "reading the configuration");
  609. goto done;
  610. }
  611. /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
  612. on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
  613. Py_UTF8Mode = config->utf8_mode;
  614. #ifdef MS_WINDOWS
  615. Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
  616. #endif
  617. err = preconfig_read(config, &cmdline);
  618. if (_Py_INIT_FAILED(err)) {
  619. goto done;
  620. }
  621. /* The legacy C locale assumes ASCII as the default text encoding, which
  622. * causes problems not only for the CPython runtime, but also other
  623. * components like GNU readline.
  624. *
  625. * Accordingly, when the CLI detects it, it attempts to coerce it to a
  626. * more capable UTF-8 based alternative.
  627. *
  628. * See the documentation of the PYTHONCOERCECLOCALE setting for more
  629. * details.
  630. */
  631. int encoding_changed = 0;
  632. if (config->coerce_c_locale && !locale_coerced) {
  633. locale_coerced = 1;
  634. _Py_CoerceLegacyLocale(0);
  635. encoding_changed = 1;
  636. }
  637. if (utf8_mode == -1) {
  638. if (config->utf8_mode == 1) {
  639. /* UTF-8 Mode enabled */
  640. encoding_changed = 1;
  641. }
  642. }
  643. else {
  644. if (config->utf8_mode != utf8_mode) {
  645. encoding_changed = 1;
  646. }
  647. }
  648. if (!encoding_changed) {
  649. break;
  650. }
  651. /* Reset the configuration before reading again the configuration,
  652. just keep UTF-8 Mode value. */
  653. int new_utf8_mode = config->utf8_mode;
  654. int new_coerce_c_locale = config->coerce_c_locale;
  655. if (_PyPreConfig_Copy(config, &save_config) < 0) {
  656. err = _Py_INIT_NO_MEMORY();
  657. goto done;
  658. }
  659. config->utf8_mode = new_utf8_mode;
  660. config->coerce_c_locale = new_coerce_c_locale;
  661. /* The encoding changed: read again the configuration
  662. with the new encoding */
  663. }
  664. err = _Py_INIT_OK();
  665. done:
  666. if (init_ctype_locale != NULL) {
  667. setlocale(LC_CTYPE, init_ctype_locale);
  668. PyMem_RawFree(init_ctype_locale);
  669. }
  670. Py_UTF8Mode = init_utf8_mode ;
  671. #ifdef MS_WINDOWS
  672. Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
  673. #endif
  674. _PyPreCmdline_Clear(&cmdline);
  675. return err;
  676. }
  677. /* Write the pre-configuration:
  678. - set the memory allocators
  679. - set Py_xxx global configuration variables
  680. - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
  681. (PEP 540)
  682. If the memory allocator is changed, config is re-allocated with new
  683. allocator. So calling _PyPreConfig_Clear(config) is safe after this call.
  684. Do nothing if called after Py_Initialize(): ignore the new
  685. pre-configuration. */
  686. _PyInitError
  687. _PyPreConfig_Write(const _PyPreConfig *config)
  688. {
  689. if (_PyRuntime.core_initialized) {
  690. /* bpo-34008: Calling this functions after Py_Initialize() ignores
  691. the new configuration. */
  692. return _Py_INIT_OK();
  693. }
  694. if (config->allocator != PYMEM_ALLOCATOR_NOT_SET) {
  695. if (_PyMem_SetupAllocators(config->allocator) < 0) {
  696. return _Py_INIT_ERR("Unknown PYTHONMALLOC allocator");
  697. }
  698. }
  699. _PyPreConfig_SetGlobalConfig(config);
  700. if (config->coerce_c_locale) {
  701. _Py_CoerceLegacyLocale(config->coerce_c_locale_warn);
  702. }
  703. /* Set LC_CTYPE to the user preferred locale */
  704. _Py_SetLocaleFromEnv(LC_CTYPE);
  705. /* Write the new pre-configuration into _PyRuntime */
  706. PyMemAllocatorEx old_alloc;
  707. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  708. int res = _PyPreConfig_Copy(&_PyRuntime.preconfig, config);
  709. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  710. if (res < 0) {
  711. return _Py_INIT_NO_MEMORY();
  712. }
  713. return _Py_INIT_OK();
  714. }