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.

729 lines
18 KiB

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