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.

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