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.

736 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. wstrlist_join(wchar_t sep, int count, wchar_t **list)
  126. {
  127. size_t len = 1; /* NUL terminator */
  128. for (int i=0; i < count; i++) {
  129. if (i != 0) {
  130. len++;
  131. }
  132. len += wcslen(list[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 (int i=0; i < count; i++) {
  140. wchar_t *path = list[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 = wstrlist_join(DELIM,
  160. core_config->nmodule_search_path,
  161. core_config->module_search_paths);
  162. if (path_config.module_search_path == NULL) {
  163. goto no_memory;
  164. }
  165. if (copy_wstr(&path_config.program_full_path, core_config->executable) < 0) {
  166. goto no_memory;
  167. }
  168. if (copy_wstr(&path_config.prefix, core_config->prefix) < 0) {
  169. goto no_memory;
  170. }
  171. if (copy_wstr(&path_config.exec_prefix, core_config->exec_prefix) < 0) {
  172. goto no_memory;
  173. }
  174. #ifdef MS_WINDOWS
  175. if (copy_wstr(&path_config.dll_path, core_config->dll_path) < 0) {
  176. goto no_memory;
  177. }
  178. #endif
  179. if (copy_wstr(&path_config.program_name, core_config->program_name) < 0) {
  180. goto no_memory;
  181. }
  182. if (copy_wstr(&path_config.home, core_config->home) < 0) {
  183. goto no_memory;
  184. }
  185. err = _PyPathConfig_SetGlobal(&path_config);
  186. if (_Py_INIT_FAILED(err)) {
  187. goto done;
  188. }
  189. err = _Py_INIT_OK();
  190. goto done;
  191. no_memory:
  192. err = _Py_INIT_NO_MEMORY();
  193. done:
  194. _PyPathConfig_Clear(&path_config);
  195. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  196. return err;
  197. }
  198. static _PyInitError
  199. core_config_init_module_search_paths(_PyCoreConfig *config,
  200. _PyPathConfig *path_config)
  201. {
  202. assert(config->module_search_paths == NULL);
  203. assert(config->nmodule_search_path < 0);
  204. config->nmodule_search_path = 0;
  205. const wchar_t *sys_path = path_config->module_search_path;
  206. const wchar_t delim = DELIM;
  207. const wchar_t *p = sys_path;
  208. while (1) {
  209. p = wcschr(sys_path, delim);
  210. if (p == NULL) {
  211. p = sys_path + wcslen(sys_path); /* End of string */
  212. }
  213. size_t path_len = (p - sys_path);
  214. wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
  215. if (path == NULL) {
  216. return _Py_INIT_NO_MEMORY();
  217. }
  218. memcpy(path, sys_path, path_len * sizeof(wchar_t));
  219. path[path_len] = L'\0';
  220. _PyInitError err = _Py_wstrlist_append(&config->nmodule_search_path,
  221. &config->module_search_paths,
  222. path);
  223. PyMem_RawFree(path);
  224. if (_Py_INIT_FAILED(err)) {
  225. return err;
  226. }
  227. if (*p == '\0') {
  228. break;
  229. }
  230. sys_path = p + 1;
  231. }
  232. return _Py_INIT_OK();
  233. }
  234. static _PyInitError
  235. _PyCoreConfig_CalculatePathConfig(_PyCoreConfig *config)
  236. {
  237. _PyPathConfig path_config = _PyPathConfig_INIT;
  238. _PyInitError err;
  239. err = _PyPathConfig_Calculate(&path_config, config);
  240. if (_Py_INIT_FAILED(err)) {
  241. goto error;
  242. }
  243. if (config->nmodule_search_path < 0) {
  244. err = core_config_init_module_search_paths(config, &path_config);
  245. if (_Py_INIT_FAILED(err)) {
  246. goto error;
  247. }
  248. }
  249. if (config->executable == NULL) {
  250. if (copy_wstr(&config->executable,
  251. path_config.program_full_path) < 0) {
  252. goto no_memory;
  253. }
  254. }
  255. if (config->prefix == NULL) {
  256. if (copy_wstr(&config->prefix, path_config.prefix) < 0) {
  257. goto no_memory;
  258. }
  259. }
  260. if (config->exec_prefix == NULL) {
  261. if (copy_wstr(&config->exec_prefix,
  262. path_config.exec_prefix) < 0) {
  263. goto no_memory;
  264. }
  265. }
  266. #ifdef MS_WINDOWS
  267. if (config->dll_path == NULL) {
  268. if (copy_wstr(&config->dll_path, path_config.dll_path) < 0) {
  269. goto no_memory;
  270. }
  271. }
  272. #endif
  273. if (path_config.isolated != -1) {
  274. config->preconfig.isolated = path_config.isolated;
  275. }
  276. if (path_config.site_import != -1) {
  277. config->site_import = path_config.site_import;
  278. }
  279. _PyPathConfig_Clear(&path_config);
  280. return _Py_INIT_OK();
  281. no_memory:
  282. err = _Py_INIT_NO_MEMORY();
  283. error:
  284. _PyPathConfig_Clear(&path_config);
  285. return err;
  286. }
  287. _PyInitError
  288. _PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
  289. {
  290. /* Do we need to calculate the path? */
  291. if ((config->nmodule_search_path < 0)
  292. || (config->executable == NULL)
  293. || (config->prefix == NULL)
  294. #ifdef MS_WINDOWS
  295. || (config->dll_path == NULL)
  296. #endif
  297. || (config->exec_prefix == NULL))
  298. {
  299. _PyInitError err = _PyCoreConfig_CalculatePathConfig(config);
  300. if (_Py_INIT_FAILED(err)) {
  301. return err;
  302. }
  303. }
  304. if (config->base_prefix == NULL) {
  305. if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
  306. return _Py_INIT_NO_MEMORY();
  307. }
  308. }
  309. if (config->base_exec_prefix == NULL) {
  310. if (copy_wstr(&config->base_exec_prefix,
  311. config->exec_prefix) < 0) {
  312. return _Py_INIT_NO_MEMORY();
  313. }
  314. }
  315. return _Py_INIT_OK();
  316. }
  317. static void
  318. pathconfig_global_init(void)
  319. {
  320. if (_Py_path_config.module_search_path != NULL) {
  321. /* Already initialized */
  322. return;
  323. }
  324. _PyInitError err;
  325. _PyCoreConfig config = _PyCoreConfig_INIT;
  326. err = _PyCoreConfig_Read(&config, NULL);
  327. if (_Py_INIT_FAILED(err)) {
  328. goto error;
  329. }
  330. err = _PyCoreConfig_SetPathConfig(&config);
  331. if (_Py_INIT_FAILED(err)) {
  332. goto error;
  333. }
  334. _PyCoreConfig_Clear(&config);
  335. return;
  336. error:
  337. _PyCoreConfig_Clear(&config);
  338. _Py_ExitInitError(err);
  339. }
  340. /* External interface */
  341. void
  342. Py_SetPath(const wchar_t *path)
  343. {
  344. if (path == NULL) {
  345. _PyPathConfig_Clear(&_Py_path_config);
  346. return;
  347. }
  348. PyMemAllocatorEx old_alloc;
  349. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  350. _PyPathConfig new_config;
  351. new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
  352. int alloc_error = (new_config.program_full_path == NULL);
  353. new_config.prefix = _PyMem_RawWcsdup(L"");
  354. alloc_error |= (new_config.prefix == NULL);
  355. new_config.exec_prefix = _PyMem_RawWcsdup(L"");
  356. alloc_error |= (new_config.exec_prefix == NULL);
  357. #ifdef MS_WINDOWS
  358. new_config.dll_path = _PyMem_RawWcsdup(L"");
  359. alloc_error |= (new_config.dll_path == NULL);
  360. #endif
  361. new_config.module_search_path = _PyMem_RawWcsdup(path);
  362. alloc_error |= (new_config.module_search_path == NULL);
  363. /* steal the home and program_name values (to leave them unchanged) */
  364. new_config.home = _Py_path_config.home;
  365. _Py_path_config.home = NULL;
  366. new_config.program_name = _Py_path_config.program_name;
  367. _Py_path_config.program_name = NULL;
  368. _PyPathConfig_Clear(&_Py_path_config);
  369. _Py_path_config = new_config;
  370. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  371. if (alloc_error) {
  372. Py_FatalError("Py_SetPath() failed: out of memory");
  373. }
  374. }
  375. void
  376. Py_SetPythonHome(const wchar_t *home)
  377. {
  378. if (home == NULL) {
  379. return;
  380. }
  381. PyMemAllocatorEx old_alloc;
  382. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  383. PyMem_RawFree(_Py_path_config.home);
  384. _Py_path_config.home = _PyMem_RawWcsdup(home);
  385. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  386. if (_Py_path_config.home == NULL) {
  387. Py_FatalError("Py_SetPythonHome() failed: out of memory");
  388. }
  389. }
  390. void
  391. Py_SetProgramName(const wchar_t *program_name)
  392. {
  393. if (program_name == NULL || program_name[0] == L'\0') {
  394. return;
  395. }
  396. PyMemAllocatorEx old_alloc;
  397. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  398. PyMem_RawFree(_Py_path_config.program_name);
  399. _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
  400. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  401. if (_Py_path_config.program_name == NULL) {
  402. Py_FatalError("Py_SetProgramName() failed: out of memory");
  403. }
  404. }
  405. void
  406. _Py_SetProgramFullPath(const wchar_t *program_full_path)
  407. {
  408. if (program_full_path == NULL || program_full_path[0] == L'\0') {
  409. return;
  410. }
  411. PyMemAllocatorEx old_alloc;
  412. _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  413. PyMem_RawFree(_Py_path_config.program_full_path);
  414. _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
  415. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
  416. if (_Py_path_config.program_full_path == NULL) {
  417. Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
  418. }
  419. }
  420. wchar_t *
  421. Py_GetPath(void)
  422. {
  423. pathconfig_global_init();
  424. return _Py_path_config.module_search_path;
  425. }
  426. wchar_t *
  427. Py_GetPrefix(void)
  428. {
  429. pathconfig_global_init();
  430. return _Py_path_config.prefix;
  431. }
  432. wchar_t *
  433. Py_GetExecPrefix(void)
  434. {
  435. pathconfig_global_init();
  436. return _Py_path_config.exec_prefix;
  437. }
  438. wchar_t *
  439. Py_GetProgramFullPath(void)
  440. {
  441. pathconfig_global_init();
  442. return _Py_path_config.program_full_path;
  443. }
  444. wchar_t*
  445. Py_GetPythonHome(void)
  446. {
  447. pathconfig_global_init();
  448. return _Py_path_config.home;
  449. }
  450. wchar_t *
  451. Py_GetProgramName(void)
  452. {
  453. pathconfig_global_init();
  454. return _Py_path_config.program_name;
  455. }
  456. /* Compute argv[0] which will be prepended to sys.argv */
  457. PyObject*
  458. _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv)
  459. {
  460. wchar_t *argv0;
  461. wchar_t *p = NULL;
  462. Py_ssize_t n = 0;
  463. int have_script_arg = 0;
  464. int have_module_arg = 0;
  465. #ifdef HAVE_READLINK
  466. wchar_t link[MAXPATHLEN+1];
  467. wchar_t argv0copy[2*MAXPATHLEN+1];
  468. int nr = 0;
  469. #endif
  470. #if defined(HAVE_REALPATH)
  471. wchar_t fullpath[MAXPATHLEN];
  472. #elif defined(MS_WINDOWS)
  473. wchar_t fullpath[MAX_PATH];
  474. #endif
  475. argv0 = argv[0];
  476. if (argc > 0 && argv0 != NULL) {
  477. have_module_arg = (wcscmp(argv0, L"-m") == 0);
  478. have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
  479. }
  480. if (have_module_arg) {
  481. #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
  482. _Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath));
  483. argv0 = fullpath;
  484. n = wcslen(argv0);
  485. #else
  486. argv0 = L".";
  487. n = 1;
  488. #endif
  489. }
  490. #ifdef HAVE_READLINK
  491. if (have_script_arg)
  492. nr = _Py_wreadlink(argv0, link, MAXPATHLEN);
  493. if (nr > 0) {
  494. /* It's a symlink */
  495. link[nr] = '\0';
  496. if (link[0] == SEP)
  497. argv0 = link; /* Link to absolute path */
  498. else if (wcschr(link, SEP) == NULL)
  499. ; /* Link without path */
  500. else {
  501. /* Must join(dirname(argv0), link) */
  502. wchar_t *q = wcsrchr(argv0, SEP);
  503. if (q == NULL)
  504. argv0 = link; /* argv0 without path */
  505. else {
  506. /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */
  507. wcsncpy(argv0copy, argv0, MAXPATHLEN);
  508. q = wcsrchr(argv0copy, SEP);
  509. wcsncpy(q+1, link, MAXPATHLEN);
  510. q[MAXPATHLEN + 1] = L'\0';
  511. argv0 = argv0copy;
  512. }
  513. }
  514. }
  515. #endif /* HAVE_READLINK */
  516. #if SEP == '\\'
  517. /* Special case for Microsoft filename syntax */
  518. if (have_script_arg) {
  519. wchar_t *q;
  520. #if defined(MS_WINDOWS)
  521. /* Replace the first element in argv with the full path. */
  522. wchar_t *ptemp;
  523. if (GetFullPathNameW(argv0,
  524. Py_ARRAY_LENGTH(fullpath),
  525. fullpath,
  526. &ptemp)) {
  527. argv0 = fullpath;
  528. }
  529. #endif
  530. p = wcsrchr(argv0, SEP);
  531. /* Test for alternate separator */
  532. q = wcsrchr(p ? p : argv0, '/');
  533. if (q != NULL)
  534. p = q;
  535. if (p != NULL) {
  536. n = p + 1 - argv0;
  537. if (n > 1 && p[-1] != ':')
  538. n--; /* Drop trailing separator */
  539. }
  540. }
  541. #else /* All other filename syntaxes */
  542. if (have_script_arg) {
  543. #if defined(HAVE_REALPATH)
  544. if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
  545. argv0 = fullpath;
  546. }
  547. #endif
  548. p = wcsrchr(argv0, SEP);
  549. }
  550. if (p != NULL) {
  551. n = p + 1 - argv0;
  552. #if SEP == '/' /* Special case for Unix filename syntax */
  553. if (n > 1)
  554. n--; /* Drop trailing separator */
  555. #endif /* Unix */
  556. }
  557. #endif /* All others */
  558. return PyUnicode_FromWideChar(argv0, n);
  559. }
  560. #ifdef MS_WINDOWS
  561. #define WCSTOK wcstok_s
  562. #else
  563. #define WCSTOK wcstok
  564. #endif
  565. /* Search for a prefix value in an environment file (pyvenv.cfg).
  566. If found, copy it into the provided buffer. */
  567. int
  568. _Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
  569. wchar_t *value, size_t value_size)
  570. {
  571. int result = 0; /* meaning not found */
  572. char buffer[MAXPATHLEN*2+1]; /* allow extra for key, '=', etc. */
  573. fseek(env_file, 0, SEEK_SET);
  574. while (!feof(env_file)) {
  575. char * p = fgets(buffer, MAXPATHLEN*2, env_file);
  576. if (p == NULL) {
  577. break;
  578. }
  579. size_t n = strlen(p);
  580. if (p[n - 1] != '\n') {
  581. /* line has overflowed - bail */
  582. break;
  583. }
  584. if (p[0] == '#') {
  585. /* Comment - skip */
  586. continue;
  587. }
  588. wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n);
  589. if (tmpbuffer) {
  590. wchar_t * state;
  591. wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
  592. if ((tok != NULL) && !wcscmp(tok, key)) {
  593. tok = WCSTOK(NULL, L" \t", &state);
  594. if ((tok != NULL) && !wcscmp(tok, L"=")) {
  595. tok = WCSTOK(NULL, L"\r\n", &state);
  596. if (tok != NULL) {
  597. wcsncpy(value, tok, MAXPATHLEN);
  598. result = 1;
  599. PyMem_RawFree(tmpbuffer);
  600. break;
  601. }
  602. }
  603. }
  604. PyMem_RawFree(tmpbuffer);
  605. }
  606. }
  607. return result;
  608. }
  609. #ifdef __cplusplus
  610. }
  611. #endif