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.

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