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.

717 lines
17 KiB

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