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.

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