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.

734 lines
18 KiB

  1. /* Path configuration like module_search_path (sys.path) */
  2. #include "Python.h"
  3. #include "osdefs.h"
  4. #include "pycore_coreconfig.h"
  5. #include "pycore_fileutils.h"
  6. #include "pycore_pathconfig.h"
  7. #include "pycore_pymem.h"
  8. #include "pycore_pystate.h"
  9. #include <wchar.h>
  10. #ifdef __cplusplus
  11. extern "C" {
  12. #endif
  13. _PyPathConfig _Py_path_config = _PyPathConfig_INIT;
  14. static int
  15. copy_wstr(wchar_t **dst, const wchar_t *src)
  16. {
  17. if (src != NULL) {
  18. *dst = _PyMem_RawWcsdup(src);
  19. if (*dst == NULL) {
  20. return -1;
  21. }
  22. }
  23. else {
  24. *dst = NULL;
  25. }
  26. return 0;
  27. }
  28. static void
  29. _PyPathConfig_Clear(_PyPathConfig *config)
  30. {
  31. /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
  32. since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
  33. called before Py_Initialize() which can changes the memory allocator. */
  34. PyMemAllocatorEx old_alloc;
  35. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  36. #define CLEAR(ATTR) \
  37. do { \
  38. PyMem_RawFree(ATTR); \
  39. ATTR = NULL; \
  40. } while (0)
  41. CLEAR(config->prefix);
  42. CLEAR(config->program_full_path);
  43. CLEAR(config->exec_prefix);
  44. #ifdef MS_WINDOWS
  45. CLEAR(config->dll_path);
  46. #endif
  47. CLEAR(config->module_search_path);
  48. CLEAR(config->home);
  49. CLEAR(config->program_name);
  50. #undef CLEAR
  51. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  52. }
  53. /* Calculate the path configuration: initialize path_config from core_config */
  54. static _PyInitError
  55. _PyPathConfig_Calculate(_PyPathConfig *path_config,
  56. const _PyCoreConfig *core_config)
  57. {
  58. _PyInitError err;
  59. _PyPathConfig new_config = _PyPathConfig_INIT;
  60. PyMemAllocatorEx old_alloc;
  61. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  62. /* Calculate program_full_path, prefix, exec_prefix,
  63. dll_path (Windows), and module_search_path */
  64. err = _PyPathConfig_Calculate_impl(&new_config, core_config);
  65. if (_Py_INIT_FAILED(err)) {
  66. goto err;
  67. }
  68. /* Copy home and program_name from core_config */
  69. if (copy_wstr(&new_config.home, core_config->home) < 0) {
  70. err = _Py_INIT_NO_MEMORY();
  71. goto err;
  72. }
  73. if (copy_wstr(&new_config.program_name, core_config->program_name) < 0) {
  74. err = _Py_INIT_NO_MEMORY();
  75. goto err;
  76. }
  77. _PyPathConfig_Clear(path_config);
  78. *path_config = new_config;
  79. err = _Py_INIT_OK();
  80. goto done;
  81. err:
  82. _PyPathConfig_Clear(&new_config);
  83. done:
  84. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  85. return err;
  86. }
  87. _PyInitError
  88. _PyPathConfig_SetGlobal(const _PyPathConfig *config)
  89. {
  90. _PyInitError err;
  91. _PyPathConfig new_config = _PyPathConfig_INIT;
  92. PyMemAllocatorEx old_alloc;
  93. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  94. #define COPY_ATTR(ATTR) \
  95. do { \
  96. if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \
  97. _PyPathConfig_Clear(&new_config); \
  98. err = _Py_INIT_NO_MEMORY(); \
  99. goto done; \
  100. } \
  101. } while (0)
  102. COPY_ATTR(program_full_path);
  103. COPY_ATTR(prefix);
  104. COPY_ATTR(exec_prefix);
  105. #ifdef MS_WINDOWS
  106. COPY_ATTR(dll_path);
  107. #endif
  108. COPY_ATTR(module_search_path);
  109. COPY_ATTR(program_name);
  110. COPY_ATTR(home);
  111. _PyPathConfig_Clear(&_Py_path_config);
  112. /* Steal new_config strings; don't clear new_config */
  113. _Py_path_config = new_config;
  114. err = _Py_INIT_OK();
  115. done:
  116. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  117. return err;
  118. }
  119. void
  120. _PyPathConfig_ClearGlobal(void)
  121. {
  122. _PyPathConfig_Clear(&_Py_path_config);
  123. }
  124. static wchar_t*
  125. _PyWstrList_Join(const _PyWstrList *list, wchar_t sep)
  126. {
  127. size_t len = 1; /* NUL terminator */
  128. for (Py_ssize_t i=0; i < list->length; i++) {
  129. if (i != 0) {
  130. len++;
  131. }
  132. len += wcslen(list->items[i]);
  133. }
  134. wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
  135. if (text == NULL) {
  136. return NULL;
  137. }
  138. wchar_t *str = text;
  139. for (Py_ssize_t i=0; i < list->length; i++) {
  140. wchar_t *path = list->items[i];
  141. if (i != 0) {
  142. *str++ = SEP;
  143. }
  144. len = wcslen(path);
  145. memcpy(str, path, len * sizeof(wchar_t));
  146. str += len;
  147. }
  148. *str = L'\0';
  149. return text;
  150. }
  151. /* Set the global path configuration from core_config. */
  152. _PyInitError
  153. _PyCoreConfig_SetPathConfig(const _PyCoreConfig *core_config)
  154. {
  155. PyMemAllocatorEx old_alloc;
  156. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  157. _PyInitError err;
  158. _PyPathConfig path_config = _PyPathConfig_INIT;
  159. path_config.module_search_path = _PyWstrList_Join(&core_config->module_search_paths, DELIM);
  160. if (path_config.module_search_path == NULL) {
  161. goto no_memory;
  162. }
  163. if (copy_wstr(&path_config.program_full_path, core_config->executable) < 0) {
  164. goto no_memory;
  165. }
  166. if (copy_wstr(&path_config.prefix, core_config->prefix) < 0) {
  167. goto no_memory;
  168. }
  169. if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
  170. goto no_memory;
  171. }
  172. #ifdef MS_WINDOWS
  173. if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
  174. goto no_memory;
  175. }
  176. #endif
  177. if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) {
  178. goto no_memory;
  179. }
  180. if (copy_wstr(&path_config.home, core_config->home) < 0) {
  181. goto no_memory;
  182. }
  183. err = _PyPathConfig_SetGlobal(&path_config);
  184. if (_Py_INIT_FAILED(err)) {
  185. goto done;
  186. }
  187. err = _Py_INIT_OK();
  188. goto done;
  189. no_memory:
  190. err = _Py_INIT_NO_MEMORY();
  191. done:
  192. _PyPathConfig_Clear(&path_config);
  193. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  194. return err;
  195. }
  196. static _PyInitError
  197. core_config_init_module_search_paths(_PyCoreConfig *config,
  198. _PyPathConfig *path_config)
  199. {
  200. assert(!config->use_module_search_paths);
  201. _PyWstrList_Clear(&config->module_search_paths);
  202. const wchar_t *sys_path = path_config->module_search_path;
  203. const wchar_t delim = DELIM;
  204. const wchar_t *p = sys_path;
  205. while (1) {
  206. p = wcschr(sys_path, delim);
  207. if (p == NULL) {
  208. p = sys_path + wcslen(sys_path); /* End of string */
  209. }
  210. size_t path_len = (p - sys_path);
  211. wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
  212. if (path == NULL) {
  213. return _Py_INIT_NO_MEMORY();
  214. }
  215. memcpy(path, sys_path, path_len * sizeof(wchar_t));
  216. path[path_len] = L'\0';
  217. int res = _PyWstrList_Append(&config->module_search_paths, path);
  218. PyMem_RawFree(path);
  219. if (res < 0) {
  220. return _Py_INIT_NO_MEMORY();
  221. }
  222. if (*p == '\0') {
  223. break;
  224. }
  225. sys_path = p + 1;
  226. }
  227. config->use_module_search_paths = 1;
  228. return _Py_INIT_OK();
  229. }
  230. static _PyInitError
  231. _PyCoreConfig_CalculatePathConfig(_PyCoreConfig *config)
  232. {
  233. _PyPathConfig path_config = _PyPathConfig_INIT;
  234. _PyInitError err;
  235. err = _PyPathConfig_Calculate(&path_config, config);
  236. if (_Py_INIT_FAILED(err)) {
  237. goto error;
  238. }
  239. if (!config->use_module_search_paths) {
  240. err = core_config_init_module_search_paths(config, &path_config);
  241. if (_Py_INIT_FAILED(err)) {
  242. goto error;
  243. }
  244. }
  245. if (config->executable == NULL) {
  246. if (copy_wstr(&config->executable,
  247. path_config.program_full_path) < 0) {
  248. goto no_memory;
  249. }
  250. }
  251. if (config->prefix == NULL) {
  252. if (copy_wstr(&config->prefix, path_config.prefix) < 0) {
  253. goto no_memory;
  254. }
  255. }
  256. if (config->exec_prefix == NULL) {
  257. if (copy_wstr(&config->exec_prefix,
  258. path_config.exec_prefix) < 0) {
  259. goto no_memory;
  260. }
  261. }
  262. #ifdef MS_WINDOWS
  263. if (config->dll_path == NULL) {
  264. if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
  265. goto no_memory;
  266. }
  267. }
  268. #endif
  269. if (path_config.isolated != -1) {
  270. config->preconfig.isolated = path_config.isolated;
  271. }
  272. if (path_config.site_import != -1) {
  273. config->site_import = path_config.site_import;
  274. }
  275. _PyPathConfig_Clear(&path_config);
  276. return _Py_INIT_OK();
  277. no_memory:
  278. err = _Py_INIT_NO_MEMORY();
  279. error:
  280. _PyPathConfig_Clear(&path_config);
  281. return err;
  282. }
  283. _PyInitError
  284. _PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
  285. {
  286. /* Do we need to calculate the path? */
  287. if (!config->use_module_search_paths
  288. || (config->executable == NULL)
  289. || (config->prefix == NULL)
  290. #ifdef MS_WINDOWS
  291. || (config->dll_path == NULL)
  292. #endif
  293. || (config->exec_prefix == NULL))
  294. {
  295. _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
  296. if (_Py_INIT_FAILED(err)) {
  297. return err;
  298. }
  299. }
  300. if (config->base_prefix == NULL) {
  301. if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
  302. return _Py_INIT_NO_MEMORY();
  303. }
  304. }
  305. if (config->base_exec_prefix == NULL) {
  306. if (copy_wstr(&config->base_exec_prefix,
  307. config->exec_prefix) < 0) {
  308. return _Py_INIT_NO_MEMORY();
  309. }
  310. }
  311. return _Py_INIT_OK();
  312. }
  313. static void
  314. pathconfig_global_init(void)
  315. {
  316. if (_Py_path_config.module_search_path != NULL) {
  317. /* Already initialized */
  318. return;
  319. }
  320. _PyInitError err;
  321. _PyCoreConfig config = _PyCoreConfig_INIT;
  322. err = _PyCoreConfig_Read(&config, NULL);
  323. if (_Py_INIT_FAILED(err)) {
  324. goto error;
  325. }
  326. err = _PyCoreConfig_SetPathConfig(&config);
  327. if (_Py_INIT_FAILED(err)) {
  328. goto error;
  329. }
  330. _PyCoreConfig_Clear(&config);
  331. return;
  332. error:
  333. _PyCoreConfig_Clear(&config);
  334. _Py_ExitInitError(err);
  335. }
  336. /* External interface */
  337. void
  338. Py_SetPath(const wchar_t *path)
  339. {
  340. if (path == NULL) {
  341. _PyPathConfig_Clear(&_Py_path_config);
  342. return;
  343. }
  344. PyMemAllocatorEx old_alloc;
  345. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  346. _PyPathConfig new_config;
  347. new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
  348. int alloc_error = (new_config.program_full_path == NULL);
  349. new_config.prefix = _PyMem_RawWcsdup(L"");
  350. alloc_error |= (new_config.prefix == NULL);
  351. new_config.exec_prefix = _PyMem_RawWcsdup(L"");
  352. alloc_error |= (new_config.exec_prefix == NULL);
  353. #ifdef MS_WINDOWS
  354. new_config.dll_path = _PyMem_RawWcsdup(L"");
  355. alloc_error |= (new_config.dll_path == NULL);
  356. #endif
  357. new_config.module_search_path = _PyMem_RawWcsdup(path);
  358. alloc_error |= (new_config.module_search_path == NULL);
  359. /* steal the home and program_name values (to leave them unchanged) */
  360. new_config.home = _Py_path_config.home;
  361. _Py_path_config.home = NULL;
  362. new_config.program_name = _Py_path_config.program_name;
  363. _Py_path_config.program_name = NULL;
  364. _PyPathConfig_Clear(&_Py_path_config);
  365. _Py_path_config = new_config;
  366. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  367. if (alloc_error) {
  368. Py_FatalError("Py_SetPath() failed: out of memory");
  369. }
  370. }
  371. void
  372. Py_SetPythonHome(const wchar_t *home)
  373. {
  374. if (home == NULL) {
  375. return;
  376. }
  377. PyMemAllocatorEx old_alloc;
  378. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  379. PyMem_RawFree(_Py_path_config.home);
  380. _Py_path_config.home = _PyMem_RawWcsdup(home);
  381. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  382. if (_Py_path_config.home == NULL) {
  383. Py_FatalError("Py_SetPythonHome() failed: out of memory");
  384. }
  385. }
  386. void
  387. Py_SetProgramName(const wchar_t *program_name)
  388. {
  389. if (program_name == NULL || program_name[0] == L'\0') {
  390. return;
  391. }
  392. PyMemAllocatorEx old_alloc;
  393. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  394. PyMem_RawFree(_Py_path_config.program_name);
  395. _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
  396. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  397. if (_Py_path_config.program_name == NULL) {
  398. Py_FatalError("Py_SetProgramName() failed: out of memory");
  399. }
  400. }
  401. void
  402. _Py_SetProgramFullPath(const wchar_t *program_full_path)
  403. {
  404. if (program_full_path == NULL || program_full_path[0] == L'\0') {
  405. return;
  406. }
  407. PyMemAllocatorEx old_alloc;
  408. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  409. PyMem_RawFree(_Py_path_config.program_full_path);
  410. _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
  411. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  412. if (_Py_path_config.program_full_path == NULL) {
  413. Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
  414. }
  415. }
  416. wchar_t *
  417. Py_GetPath(void)
  418. {
  419. pathconfig_global_init();
  420. return _Py_path_config.module_search_path;
  421. }
  422. wchar_t *
  423. Py_GetPrefix(void)
  424. {
  425. pathconfig_global_init();
  426. return _Py_path_config.prefix;
  427. }
  428. wchar_t *
  429. Py_GetExecPrefix(void)
  430. {
  431. pathconfig_global_init();
  432. return _Py_path_config.exec_prefix;
  433. }
  434. wchar_t *
  435. Py_GetProgramFullPath(void)
  436. {
  437. pathconfig_global_init();
  438. return _Py_path_config.program_full_path;
  439. }
  440. wchar_t*
  441. Py_GetPythonHome(void)
  442. {
  443. pathconfig_global_init();
  444. return _Py_path_config.home;
  445. }
  446. wchar_t *
  447. Py_GetProgramName(void)
  448. {
  449. pathconfig_global_init();
  450. return _Py_path_config.program_name;
  451. }
  452. /* Compute argv[0] which will be prepended to sys.argv */
  453. PyObject*
  454. _PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
  455. {
  456. assert(_PyWstrList_CheckConsistency(argv));
  457. wchar_t *argv0;
  458. wchar_t *p = NULL;
  459. Py_ssize_t n = 0;
  460. int have_script_arg = 0;
  461. int have_module_arg = 0;
  462. #ifdef HAVE_READLINK
  463. wchar_t link[MAXPATHLEN+1];
  464. wchar_t argv0copy[2*MAXPATHLEN+1];
  465. int nr = 0;
  466. #endif
  467. #if defined(HAVE_REALPATH)
  468. wchar_t fullpath[MAXPATHLEN];
  469. #elif defined(MS_WINDOWS)
  470. wchar_t fullpath[MAX_PATH];
  471. #endif
  472. if (argv->length > 0) {
  473. argv0 = argv->items[0];
  474. have_module_arg = (wcscmp(argv0, L"-m") == 0);
  475. have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
  476. }
  477. if (have_module_arg) {
  478. #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
  479. _Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath));
  480. argv0 = fullpath;
  481. n = wcslen(argv0);
  482. #else
  483. argv0 = L".";
  484. n = 1;
  485. #endif
  486. }
  487. #ifdef HAVE_READLINK
  488. if (have_script_arg)
  489. nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
  490. if (nr > 0) {
  491. /* It's a symlink */
  492. link[nr] = '\0';
  493. if (link[0] == SEP)
  494. argv0 = link; /* Link to absolute path */
  495. else if (wcschr(link, SEP) == NULL)
  496. ; /* Link without path */
  497. else {
  498. /* Must join(dirname(argv0), link) */
  499. wchar_t *q = wcsrchr(argv0, SEP);
  500. if (q == NULL)
  501. argv0 = link; /* argv0 without path */
  502. else {
  503. /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
  504. wcsncpy(argv0copy, argv0, MAXPATHLEN);
  505. q = wcsrchr(argv0copy, SEP);
  506. wcsncpy(q+1, link, MAXPATHLEN);
  507. q[MAXPATHLEN + 1] = L'\0';
  508. argv0 = argv0copy;
  509. }
  510. }
  511. }
  512. #endif /* HAVE_READLINK */
  513. #if SEP == '\\'
  514. /* Special case for Microsoft filename syntax */
  515. if (have_script_arg) {
  516. wchar_t *q;
  517. #if defined(MS_WINDOWS)
  518. /* Replace the first element in argv with the full path. */
  519. wchar_t *ptemp;
  520. if (GetFullPathNameW(argv0,
  521. Py_ARRAY_LENGTH(fullpath),
  522. fullpath,
  523. &ptemp)) {
  524. argv0 = fullpath;
  525. }
  526. #endif
  527. p = wcsrchr(argv0, SEP);
  528. /* Test for alternate separator */
  529. q = wcsrchr(p ? p : argv0, '/');
  530. if (q != NULL)
  531. p = q;
  532. if (p != NULL) {
  533. n = p + 1 - argv0;
  534. if (n > 1 && p[-1] != ':')
  535. n--; /* Drop trailing separator */
  536. }
  537. }
  538. #else /* All other filename syntaxes */
  539. if (have_script_arg) {
  540. #if defined(HAVE_REALPATH)
  541. if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
  542. argv0 = fullpath;
  543. }
  544. #endif
  545. p = wcsrchr(argv0, SEP);
  546. }
  547. if (p != NULL) {
  548. n = p + 1 - argv0;
  549. #if SEP == '/' /* Special case for Unix filename syntax */
  550. if (n > 1)
  551. n--; /* Drop trailing separator */
  552. #endif /* Unix */
  553. }
  554. #endif /* All others */
  555. return PyUnicode_FromWideChar(argv0, n);
  556. }
  557. #ifdef MS_WINDOWS
  558. #define WCSTOK wcstok_s
  559. #else
  560. #define WCSTOK wcstok
  561. #endif
  562. /* Search for a prefix value in an environment file (pyvenv.cfg).
  563. If found, copy it into the provided buffer. */
  564. int
  565. _Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
  566. wchar_t *value, size_t value_size)
  567. {
  568. int result = 0; /* meaning not found */
  569. char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */
  570. fseek(env_file, 0, SEEK_SET);
  571. while (!feof(env_file)) {
  572. char * p = fgets(buffer, MAXPATHLEN*2, env_file);
  573. if (p == NULL) {
  574. break;
  575. }
  576. size_t n = strlen(p);
  577. if (p[n - 1] != '\n') {
  578. /* line has overflowed - bail */
  579. break;
  580. }
  581. if (p[0] == '#') {
  582. /* Comment - skip */
  583. continue;
  584. }
  585. wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n);
  586. if (tmpbuffer) {
  587. wchar_t * state;
  588. wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
  589. if ((tok != NULL) && !wcscmp(tok, key)) {
  590. tok = WCSTOK(NULL, L" \t", &state);
  591. if ((tok != NULL) && !wcscmp(tok, L"=")) {
  592. tok = WCSTOK(NULL, L"\r\n", &state);
  593. if (tok != NULL) {
  594. wcsncpy(value, tok, MAXPATHLEN);
  595. result = 1;
  596. PyMem_RawFree(tmpbuffer);
  597. break;
  598. }
  599. }
  600. }
  601. PyMem_RawFree(tmpbuffer);
  602. }
  603. }
  604. return result;
  605. }
  606. #ifdef __cplusplus
  607. }
  608. #endif