blob: 1934f2e1c4b87738c4b1b25e30ef176ba502df66 [file] [log] [blame]
Victor Stinner31a83932017-12-04 13:39:15 +01001/* Path configuration like module_search_path (sys.path) */
2
3#include "Python.h"
4#include "osdefs.h"
Victor Stinner331a6a52019-05-27 16:39:22 +02005#include "pycore_initconfig.h"
Victor Stinner9fc57a32018-11-07 00:44:03 +01006#include "pycore_fileutils.h"
Victor Stinnera1c249c2018-11-01 03:15:58 +01007#include "pycore_pathconfig.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01008#include "pycore_pymem.h"
9#include "pycore_pystate.h"
Nick Coghland5d9e022018-03-25 23:03:10 +100010#include <wchar.h>
Victor Stinner31a83932017-12-04 13:39:15 +010011
12#ifdef __cplusplus
13extern "C" {
14#endif
15
16
17_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
Victor Stinner9f3dcf82019-09-21 02:13:14 +020018#ifdef MS_WINDOWS
19wchar_t *_Py_dll_path = NULL;
20#endif
Victor Stinner31a83932017-12-04 13:39:15 +010021
22
Victor Stinnerb1147e42018-07-21 02:06:16 +020023static int
24copy_wstr(wchar_t **dst, const wchar_t *src)
25{
26 if (src != NULL) {
27 *dst = _PyMem_RawWcsdup(src);
28 if (*dst == NULL) {
29 return -1;
30 }
31 }
32 else {
33 *dst = NULL;
34 }
35 return 0;
36}
37
38
39static void
Victor Stinner331a6a52019-05-27 16:39:22 +020040pathconfig_clear(_PyPathConfig *config)
Victor Stinner31a83932017-12-04 13:39:15 +010041{
42 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
43 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
44 called before Py_Initialize() which can changes the memory allocator. */
45 PyMemAllocatorEx old_alloc;
46 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
47
48#define CLEAR(ATTR) \
49 do { \
50 PyMem_RawFree(ATTR); \
51 ATTR = NULL; \
52 } while (0)
53
54 CLEAR(config->prefix);
55 CLEAR(config->program_full_path);
Steve Dower177a41a2018-11-17 20:41:48 -080056 CLEAR(config->exec_prefix);
Victor Stinner31a83932017-12-04 13:39:15 +010057 CLEAR(config->module_search_path);
58 CLEAR(config->home);
59 CLEAR(config->program_name);
Steve Dower323e7432019-06-29 14:28:59 -070060 CLEAR(config->base_executable);
Victor Stinner31a83932017-12-04 13:39:15 +010061#undef CLEAR
62
63 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
64}
65
66
Victor Stinner331a6a52019-05-27 16:39:22 +020067/* Calculate the path configuration: initialize pathconfig from config */
68static PyStatus
69pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Victor Stinner31a83932017-12-04 13:39:15 +010070{
Victor Stinner331a6a52019-05-27 16:39:22 +020071 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +010072 _PyPathConfig new_config = _PyPathConfig_INIT;
73
74 PyMemAllocatorEx old_alloc;
75 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
76
Victor Stinner9f3dcf82019-09-21 02:13:14 +020077 if (copy_wstr(&new_config.module_search_path,
78 _Py_path_config.module_search_path) < 0)
79 {
80 status = _PyStatus_NO_MEMORY();
81 goto error;
82 }
83
Steve Dower177a41a2018-11-17 20:41:48 -080084 /* Calculate program_full_path, prefix, exec_prefix,
85 dll_path (Windows), and module_search_path */
Victor Stinner331a6a52019-05-27 16:39:22 +020086 status = _PyPathConfig_Calculate(&new_config, config);
87 if (_PyStatus_EXCEPTION(status)) {
88 goto error;
Victor Stinner31a83932017-12-04 13:39:15 +010089 }
90
Victor Stinner331a6a52019-05-27 16:39:22 +020091 /* Copy home and program_name from config */
92 if (copy_wstr(&new_config.home, config->home) < 0) {
93 status = _PyStatus_NO_MEMORY();
94 goto error;
Victor Stinner31a83932017-12-04 13:39:15 +010095 }
Victor Stinner331a6a52019-05-27 16:39:22 +020096 if (copy_wstr(&new_config.program_name, config->program_name) < 0) {
97 status = _PyStatus_NO_MEMORY();
98 goto error;
Victor Stinner31a83932017-12-04 13:39:15 +010099 }
Steve Dower323e7432019-06-29 14:28:59 -0700100 if (config->base_executable) {
101 PyMem_RawFree(new_config.base_executable);
102 if (copy_wstr(&new_config.base_executable,
103 config->base_executable) < 0) {
104 status = _PyStatus_NO_MEMORY();
105 goto error;
106 }
107 }
Victor Stinner31a83932017-12-04 13:39:15 +0100108
Victor Stinner331a6a52019-05-27 16:39:22 +0200109 pathconfig_clear(pathconfig);
110 *pathconfig = new_config;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200111
Victor Stinner331a6a52019-05-27 16:39:22 +0200112 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200113 goto done;
114
Victor Stinner331a6a52019-05-27 16:39:22 +0200115error:
116 pathconfig_clear(&new_config);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200117
118done:
119 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200120 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200121}
122
123
Victor Stinnerb1147e42018-07-21 02:06:16 +0200124void
125_PyPathConfig_ClearGlobal(void)
126{
Victor Stinnerc1834442019-03-18 22:24:28 +0100127 PyMemAllocatorEx old_alloc;
128 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
129
Victor Stinner331a6a52019-05-27 16:39:22 +0200130 pathconfig_clear(&_Py_path_config);
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200131#ifdef MS_WINDOWS
132 PyMem_RawFree(_Py_dll_path);
133 _Py_dll_path = NULL;
134#endif
Victor Stinnerc1834442019-03-18 22:24:28 +0100135
136 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200137}
138
139
140static wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200141_PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200142{
143 size_t len = 1; /* NUL terminator */
Victor Stinner74f65682019-03-15 15:08:05 +0100144 for (Py_ssize_t i=0; i < list->length; i++) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200145 if (i != 0) {
146 len++;
147 }
Victor Stinner74f65682019-03-15 15:08:05 +0100148 len += wcslen(list->items[i]);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200149 }
150
151 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
152 if (text == NULL) {
153 return NULL;
154 }
155 wchar_t *str = text;
Victor Stinner74f65682019-03-15 15:08:05 +0100156 for (Py_ssize_t i=0; i < list->length; i++) {
157 wchar_t *path = list->items[i];
Victor Stinnerb1147e42018-07-21 02:06:16 +0200158 if (i != 0) {
159 *str++ = SEP;
160 }
161 len = wcslen(path);
162 memcpy(str, path, len * sizeof(wchar_t));
163 str += len;
164 }
165 *str = L'\0';
166
167 return text;
168}
169
170
Victor Stinner331a6a52019-05-27 16:39:22 +0200171/* Set the global path configuration from config. */
172PyStatus
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200173_PyPathConfig_Init(void)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200174{
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200175#ifdef MS_WINDOWS
176 if (_Py_dll_path == NULL) {
177 /* Already set: nothing to do */
178 return _PyStatus_OK();
179 }
180
Victor Stinnerb1147e42018-07-21 02:06:16 +0200181 PyMemAllocatorEx old_alloc;
182 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
183
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200184 _Py_dll_path = _Py_GetDLLPath();
185
186 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
187
188 if (_Py_dll_path == NULL) {
189 return _PyStatus_NO_MEMORY();
190 }
191#endif
192 return _PyStatus_OK();
193}
194
195
196static PyStatus
197pathconfig_global_init_from_config(const PyConfig *config)
198{
Victor Stinner331a6a52019-05-27 16:39:22 +0200199 PyStatus status;
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200200 PyMemAllocatorEx old_alloc;
201 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
202
Victor Stinner331a6a52019-05-27 16:39:22 +0200203 _PyPathConfig pathconfig = _PyPathConfig_INIT;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200204
Victor Stinner331a6a52019-05-27 16:39:22 +0200205 pathconfig.module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
206 if (pathconfig.module_search_path == NULL) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200207 goto no_memory;
208 }
209
Victor Stinner331a6a52019-05-27 16:39:22 +0200210 if (copy_wstr(&pathconfig.program_full_path, config->executable) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200211 goto no_memory;
212 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200213 if (copy_wstr(&pathconfig.prefix, config->prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200214 goto no_memory;
215 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200216 if (copy_wstr(&pathconfig.exec_prefix, config->exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200217 goto no_memory;
218 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200219 if (copy_wstr(&pathconfig.program_name, config->program_name) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200220 goto no_memory;
221 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200222 if (copy_wstr(&pathconfig.home, config->home) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200223 goto no_memory;
224 }
Steve Dower323e7432019-06-29 14:28:59 -0700225 if (copy_wstr(&pathconfig.base_executable, config->base_executable) < 0) {
226 goto no_memory;
227 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200228
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200229 pathconfig_clear(&_Py_path_config);
230 /* Steal new_config strings; don't clear new_config */
231 _Py_path_config = pathconfig;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200232
Victor Stinner331a6a52019-05-27 16:39:22 +0200233 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200234 goto done;
235
236no_memory:
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200237 pathconfig_clear(&pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +0200238 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200239
240done:
Victor Stinnerb1147e42018-07-21 02:06:16 +0200241 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200242 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200243}
244
245
Victor Stinner331a6a52019-05-27 16:39:22 +0200246static PyStatus
247config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200248{
Victor Stinner331a6a52019-05-27 16:39:22 +0200249 assert(!config->module_search_paths_set);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200250
Victor Stinner331a6a52019-05-27 16:39:22 +0200251 _PyWideStringList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200252
Victor Stinner331a6a52019-05-27 16:39:22 +0200253 const wchar_t *sys_path = pathconfig->module_search_path;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200254 const wchar_t delim = DELIM;
255 const wchar_t *p = sys_path;
256 while (1) {
257 p = wcschr(sys_path, delim);
258 if (p == NULL) {
259 p = sys_path + wcslen(sys_path); /* End of string */
260 }
261
262 size_t path_len = (p - sys_path);
263 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
264 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200265 return _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200266 }
267 memcpy(path, sys_path, path_len * sizeof(wchar_t));
268 path[path_len] = L'\0';
269
Victor Stinner331a6a52019-05-27 16:39:22 +0200270 PyStatus status = PyWideStringList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200271 PyMem_RawFree(path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200272 if (_PyStatus_EXCEPTION(status)) {
273 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200274 }
275
276 if (*p == '\0') {
277 break;
278 }
279 sys_path = p + 1;
280 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200281 config->module_search_paths_set = 1;
282 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200283}
284
285
Victor Stinner331a6a52019-05-27 16:39:22 +0200286static PyStatus
287config_calculate_pathconfig(PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200288{
Victor Stinner331a6a52019-05-27 16:39:22 +0200289 _PyPathConfig pathconfig = _PyPathConfig_INIT;
290 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200291
Victor Stinner331a6a52019-05-27 16:39:22 +0200292 status = pathconfig_calculate(&pathconfig, config);
293 if (_PyStatus_EXCEPTION(status)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200294 goto error;
295 }
296
Victor Stinner331a6a52019-05-27 16:39:22 +0200297 if (!config->module_search_paths_set) {
298 status = config_init_module_search_paths(config, &pathconfig);
299 if (_PyStatus_EXCEPTION(status)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200300 goto error;
301 }
302 }
303
304 if (config->executable == NULL) {
305 if (copy_wstr(&config->executable,
Victor Stinner331a6a52019-05-27 16:39:22 +0200306 pathconfig.program_full_path) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200307 goto no_memory;
308 }
309 }
310
311 if (config->prefix == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200312 if (copy_wstr(&config->prefix, pathconfig.prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200313 goto no_memory;
314 }
315 }
316
317 if (config->exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800318 if (copy_wstr(&config->exec_prefix,
Victor Stinner331a6a52019-05-27 16:39:22 +0200319 pathconfig.exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200320 goto no_memory;
321 }
322 }
323
Steve Dower323e7432019-06-29 14:28:59 -0700324 if (config->base_executable == NULL) {
325 if (copy_wstr(&config->base_executable,
326 pathconfig.base_executable) < 0) {
327 goto no_memory;
328 }
329 }
330
Victor Stinner331a6a52019-05-27 16:39:22 +0200331 if (pathconfig.isolated != -1) {
332 config->isolated = pathconfig.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200333 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200334 if (pathconfig.site_import != -1) {
335 config->site_import = pathconfig.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200336 }
337
Victor Stinner331a6a52019-05-27 16:39:22 +0200338 pathconfig_clear(&pathconfig);
339 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200340
341no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200342 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200343
344error:
Victor Stinner331a6a52019-05-27 16:39:22 +0200345 pathconfig_clear(&pathconfig);
346 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200347}
348
349
Victor Stinner331a6a52019-05-27 16:39:22 +0200350PyStatus
351_PyConfig_InitPathConfig(PyConfig *config)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200352{
353 /* Do we need to calculate the path? */
Victor Stinner331a6a52019-05-27 16:39:22 +0200354 if (!config->module_search_paths_set
Victor Stinner1dc6e392018-07-25 02:49:17 +0200355 || (config->executable == NULL)
356 || (config->prefix == NULL)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200357 || (config->exec_prefix == NULL))
358 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200359 PyStatus status = config_calculate_pathconfig(config);
360 if (_PyStatus_EXCEPTION(status)) {
361 return status;
Victor Stinner1dc6e392018-07-25 02:49:17 +0200362 }
363 }
364
365 if (config->base_prefix == NULL) {
366 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200367 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200368 }
369 }
370
371 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800372 if (copy_wstr(&config->base_exec_prefix,
373 config->exec_prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200374 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200375 }
376 }
Steve Dower323e7432019-06-29 14:28:59 -0700377
378 if (config->base_executable == NULL) {
379 if (copy_wstr(&config->base_executable,
380 config->executable) < 0) {
381 return _PyStatus_NO_MEMORY();
382 }
383 }
384
Victor Stinner331a6a52019-05-27 16:39:22 +0200385 return _PyStatus_OK();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200386}
387
388
Victor Stinner31a83932017-12-04 13:39:15 +0100389static void
390pathconfig_global_init(void)
391{
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200392 /* Initialize _Py_dll_path if needed */
393 PyStatus status = _PyPathConfig_Init();
394 if (_PyStatus_EXCEPTION(status)) {
395 Py_ExitStatusException(status);
396 }
397
Victor Stinnerb1147e42018-07-21 02:06:16 +0200398 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100399 /* Already initialized */
400 return;
401 }
402
Victor Stinner331a6a52019-05-27 16:39:22 +0200403 PyConfig config;
404 _PyConfig_InitCompatConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100405
Victor Stinner331a6a52019-05-27 16:39:22 +0200406 status = PyConfig_Read(&config);
407 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner31a83932017-12-04 13:39:15 +0100408 goto error;
409 }
410
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200411 status = pathconfig_global_init_from_config(&config);
Victor Stinner331a6a52019-05-27 16:39:22 +0200412 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner31a83932017-12-04 13:39:15 +0100413 goto error;
414 }
415
Victor Stinner331a6a52019-05-27 16:39:22 +0200416 PyConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100417 return;
418
419error:
Victor Stinner331a6a52019-05-27 16:39:22 +0200420 PyConfig_Clear(&config);
421 Py_ExitStatusException(status);
Victor Stinner31a83932017-12-04 13:39:15 +0100422}
423
424
425/* External interface */
426
427void
428Py_SetPath(const wchar_t *path)
429{
430 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200431 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100432 return;
433 }
434
435 PyMemAllocatorEx old_alloc;
436 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
437
438 _PyPathConfig new_config;
439 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200440 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100441 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200442 alloc_error |= (new_config.prefix == NULL);
Steve Dower177a41a2018-11-17 20:41:48 -0800443 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
444 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100445 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200446 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100447
448 /* steal the home and program_name values (to leave them unchanged) */
449 new_config.home = _Py_path_config.home;
450 _Py_path_config.home = NULL;
451 new_config.program_name = _Py_path_config.program_name;
452 _Py_path_config.program_name = NULL;
Steve Dower323e7432019-06-29 14:28:59 -0700453 new_config.base_executable = _Py_path_config.base_executable;
454 _Py_path_config.base_executable = NULL;
Victor Stinner31a83932017-12-04 13:39:15 +0100455
Victor Stinner331a6a52019-05-27 16:39:22 +0200456 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100457 _Py_path_config = new_config;
458
459 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200460
461 if (alloc_error) {
462 Py_FatalError("Py_SetPath() failed: out of memory");
463 }
Victor Stinner31a83932017-12-04 13:39:15 +0100464}
465
466
467void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200468Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100469{
470 if (home == NULL) {
471 return;
472 }
473
474 PyMemAllocatorEx old_alloc;
475 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
476
477 PyMem_RawFree(_Py_path_config.home);
478 _Py_path_config.home = _PyMem_RawWcsdup(home);
479
480 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
481
482 if (_Py_path_config.home == NULL) {
483 Py_FatalError("Py_SetPythonHome() failed: out of memory");
484 }
485}
486
487
488void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200489Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100490{
491 if (program_name == NULL || program_name[0] == L'\0') {
492 return;
493 }
494
495 PyMemAllocatorEx old_alloc;
496 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
497
498 PyMem_RawFree(_Py_path_config.program_name);
499 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
500
501 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
502
503 if (_Py_path_config.program_name == NULL) {
504 Py_FatalError("Py_SetProgramName() failed: out of memory");
505 }
506}
507
Steve Dower177a41a2018-11-17 20:41:48 -0800508void
509_Py_SetProgramFullPath(const wchar_t *program_full_path)
510{
511 if (program_full_path == NULL || program_full_path[0] == L'\0') {
512 return;
513 }
514
515 PyMemAllocatorEx old_alloc;
516 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
517
518 PyMem_RawFree(_Py_path_config.program_full_path);
519 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
520
521 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
522
523 if (_Py_path_config.program_full_path == NULL) {
524 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
525 }
526}
527
Victor Stinner31a83932017-12-04 13:39:15 +0100528
529wchar_t *
530Py_GetPath(void)
531{
532 pathconfig_global_init();
533 return _Py_path_config.module_search_path;
534}
535
536
537wchar_t *
538Py_GetPrefix(void)
539{
540 pathconfig_global_init();
541 return _Py_path_config.prefix;
542}
543
544
545wchar_t *
546Py_GetExecPrefix(void)
547{
Victor Stinner31a83932017-12-04 13:39:15 +0100548 pathconfig_global_init();
549 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100550}
551
552
553wchar_t *
554Py_GetProgramFullPath(void)
555{
556 pathconfig_global_init();
557 return _Py_path_config.program_full_path;
558}
559
560
561wchar_t*
562Py_GetPythonHome(void)
563{
564 pathconfig_global_init();
565 return _Py_path_config.home;
566}
567
568
569wchar_t *
570Py_GetProgramName(void)
571{
572 pathconfig_global_init();
573 return _Py_path_config.program_name;
574}
575
Victor Stinnerdcf61712019-03-19 16:09:27 +0100576/* Compute module search path from argv[0] or the current working
577 directory ("-m module" case) which will be prepended to sys.argv:
578 sys.path[0].
579
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200580 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100581
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200582 Return 0 if it fails to resolve the full path. For example, return 0 if the
583 current working directory has been removed (bpo-36236) or if argv is empty.
584
585 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100586 */
587int
Victor Stinner331a6a52019-05-27 16:39:22 +0200588_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100589{
Victor Stinner331a6a52019-05-27 16:39:22 +0200590 assert(_PyWideStringList_CheckConsistency(argv));
Victor Stinner74f65682019-03-15 15:08:05 +0100591
Victor Stinnerfc96e542019-03-19 18:22:55 +0100592 if (argv->length == 0) {
593 /* Leave sys.path unchanged if sys.argv is empty */
594 return 0;
595 }
596
597 wchar_t *argv0 = argv->items[0];
598 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
599 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
600
601 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100602 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100603
604#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100605 wchar_t fullpath[MAXPATHLEN];
606#elif defined(MS_WINDOWS)
607 wchar_t fullpath[MAX_PATH];
608#endif
609
Nick Coghland5d9e022018-03-25 23:03:10 +1000610 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100611#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100612 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
613 return 0;
614 }
615 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100616#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100617 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100618#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100619 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000620 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100621
622#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100623 wchar_t link[MAXPATHLEN + 1];
624 int nr = 0;
625
626 if (have_script_arg) {
627 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
628 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100629 if (nr > 0) {
630 /* It's a symlink */
631 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100632 if (link[0] == SEP) {
633 path0 = link; /* Link to absolute path */
634 }
635 else if (wcschr(link, SEP) == NULL) {
636 /* Link without path */
637 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100638 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100639 /* Must join(dirname(path0), link) */
640 wchar_t *q = wcsrchr(path0, SEP);
641 if (q == NULL) {
642 /* path0 without path */
643 path0 = link;
644 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100645 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100646 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
647 wchar_t path0copy[2 * MAXPATHLEN + 1];
648 wcsncpy(path0copy, path0, MAXPATHLEN);
649 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100650 wcsncpy(q+1, link, MAXPATHLEN);
651 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100652 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100653 }
654 }
655 }
656#endif /* HAVE_READLINK */
657
Victor Stinnerfc96e542019-03-19 18:22:55 +0100658 wchar_t *p = NULL;
659
Victor Stinner11a247d2017-12-13 21:05:57 +0100660#if SEP == '\\'
661 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000662 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100663 wchar_t *q;
664#if defined(MS_WINDOWS)
665 /* Replace the first element in argv with the full path. */
666 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100667 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100668 Py_ARRAY_LENGTH(fullpath),
669 fullpath,
670 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100671 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100672 }
673#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100674 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100675 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100676 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100677 if (q != NULL)
678 p = q;
679 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100680 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100681 if (n > 1 && p[-1] != ':')
682 n--; /* Drop trailing separator */
683 }
684 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100685#else
686 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000687 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100688#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100689 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
690 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100691 }
692#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100693 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100694 }
695 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100696 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100697#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100698 if (n > 1) {
699 /* Drop trailing separator */
700 n--;
701 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100702#endif /* Unix */
703 }
704#endif /* All others */
705
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200706 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
707 if (path0_obj == NULL) {
708 return -1;
709 }
710
711 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100712 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100713}
714
Victor Stinner9bee3292017-12-21 16:49:13 +0100715
Minmin Gong8ebc6452019-02-02 20:26:55 -0800716#ifdef MS_WINDOWS
717#define WCSTOK wcstok_s
718#else
719#define WCSTOK wcstok
720#endif
721
Victor Stinner9bee3292017-12-21 16:49:13 +0100722/* Search for a prefix value in an environment file (pyvenv.cfg).
723 If found, copy it into the provided buffer. */
724int
725_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
726 wchar_t *value, size_t value_size)
727{
728 int result = 0; /* meaning not found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100729 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
730 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100731
732 fseek(env_file, 0, SEEK_SET);
733 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100734 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100735
736 if (p == NULL) {
737 break;
738 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100739
740 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100741 if (p[n - 1] != '\n') {
742 /* line has overflowed - bail */
743 break;
744 }
745 if (p[0] == '#') {
746 /* Comment - skip */
747 continue;
748 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100749
Victor Stinner5f9cf232019-03-19 01:46:25 +0100750 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100751 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100752 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800753 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100754 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800755 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100756 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800757 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100758 if (tok != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100759 wcsncpy(value, tok, value_size - 1);
760 value[value_size - 1] = L'\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100761 result = 1;
762 PyMem_RawFree(tmpbuffer);
763 break;
764 }
765 }
766 }
767 PyMem_RawFree(tmpbuffer);
768 }
769 }
770 return result;
771}
772
Victor Stinner31a83932017-12-04 13:39:15 +0100773#ifdef __cplusplus
774}
775#endif