blob: 79ec4af00d83baa5c1ab5212863a6088680ca0c9 [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;
18
19
Victor Stinnerb1147e42018-07-21 02:06:16 +020020static int
21copy_wstr(wchar_t **dst, const wchar_t *src)
22{
23 if (src != NULL) {
24 *dst = _PyMem_RawWcsdup(src);
25 if (*dst == NULL) {
26 return -1;
27 }
28 }
29 else {
30 *dst = NULL;
31 }
32 return 0;
33}
34
35
36static void
Victor Stinner331a6a52019-05-27 16:39:22 +020037pathconfig_clear(_PyPathConfig *config)
Victor Stinner31a83932017-12-04 13:39:15 +010038{
39 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
40 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
41 called before Py_Initialize() which can changes the memory allocator. */
42 PyMemAllocatorEx old_alloc;
43 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
44
45#define CLEAR(ATTR) \
46 do { \
47 PyMem_RawFree(ATTR); \
48 ATTR = NULL; \
49 } while (0)
50
51 CLEAR(config->prefix);
52 CLEAR(config->program_full_path);
Steve Dower177a41a2018-11-17 20:41:48 -080053 CLEAR(config->exec_prefix);
Victor Stinner31a83932017-12-04 13:39:15 +010054#ifdef MS_WINDOWS
55 CLEAR(config->dll_path);
Victor Stinner31a83932017-12-04 13:39:15 +010056#endif
57 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
Steve Dower177a41a2018-11-17 20:41:48 -080077 /* Calculate program_full_path, prefix, exec_prefix,
78 dll_path (Windows), and module_search_path */
Victor Stinner331a6a52019-05-27 16:39:22 +020079 status = _PyPathConfig_Calculate(&new_config, config);
80 if (_PyStatus_EXCEPTION(status)) {
81 goto error;
Victor Stinner31a83932017-12-04 13:39:15 +010082 }
83
Victor Stinner331a6a52019-05-27 16:39:22 +020084 /* Copy home and program_name from config */
85 if (copy_wstr(&new_config.home, config->home) < 0) {
86 status = _PyStatus_NO_MEMORY();
87 goto error;
Victor Stinner31a83932017-12-04 13:39:15 +010088 }
Victor Stinner331a6a52019-05-27 16:39:22 +020089 if (copy_wstr(&new_config.program_name, config->program_name) < 0) {
90 status = _PyStatus_NO_MEMORY();
91 goto error;
Victor Stinner31a83932017-12-04 13:39:15 +010092 }
Steve Dower323e7432019-06-29 14:28:59 -070093 if (config->base_executable) {
94 PyMem_RawFree(new_config.base_executable);
95 if (copy_wstr(&new_config.base_executable,
96 config->base_executable) < 0) {
97 status = _PyStatus_NO_MEMORY();
98 goto error;
99 }
100 }
Victor Stinner31a83932017-12-04 13:39:15 +0100101
Victor Stinner331a6a52019-05-27 16:39:22 +0200102 pathconfig_clear(pathconfig);
103 *pathconfig = new_config;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200104
Victor Stinner331a6a52019-05-27 16:39:22 +0200105 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200106 goto done;
107
Victor Stinner331a6a52019-05-27 16:39:22 +0200108error:
109 pathconfig_clear(&new_config);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200110
111done:
112 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200113 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200114}
115
116
Victor Stinner331a6a52019-05-27 16:39:22 +0200117PyStatus
Victor Stinnerb1147e42018-07-21 02:06:16 +0200118_PyPathConfig_SetGlobal(const _PyPathConfig *config)
119{
Victor Stinner331a6a52019-05-27 16:39:22 +0200120 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200121 _PyPathConfig new_config = _PyPathConfig_INIT;
122
123 PyMemAllocatorEx old_alloc;
124 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
125
126#define COPY_ATTR(ATTR) \
127 do { \
128 if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \
Victor Stinner331a6a52019-05-27 16:39:22 +0200129 pathconfig_clear(&new_config); \
130 status = _PyStatus_NO_MEMORY(); \
Victor Stinnerb1147e42018-07-21 02:06:16 +0200131 goto done; \
132 } \
133 } while (0)
134
135 COPY_ATTR(program_full_path);
136 COPY_ATTR(prefix);
Steve Dower177a41a2018-11-17 20:41:48 -0800137 COPY_ATTR(exec_prefix);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200138#ifdef MS_WINDOWS
139 COPY_ATTR(dll_path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200140#endif
141 COPY_ATTR(module_search_path);
142 COPY_ATTR(program_name);
143 COPY_ATTR(home);
Steve Dower323e7432019-06-29 14:28:59 -0700144 COPY_ATTR(base_executable);
Victor Stinner31a83932017-12-04 13:39:15 +0100145
Victor Stinner331a6a52019-05-27 16:39:22 +0200146 pathconfig_clear(&_Py_path_config);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200147 /* Steal new_config strings; don't clear new_config */
Victor Stinner31a83932017-12-04 13:39:15 +0100148 _Py_path_config = new_config;
149
Victor Stinner331a6a52019-05-27 16:39:22 +0200150 status = _PyStatus_OK();
Victor Stinner31a83932017-12-04 13:39:15 +0100151
152done:
153 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200154 return status;
Victor Stinner31a83932017-12-04 13:39:15 +0100155}
156
157
Victor Stinnerb1147e42018-07-21 02:06:16 +0200158void
159_PyPathConfig_ClearGlobal(void)
160{
Victor Stinnerc1834442019-03-18 22:24:28 +0100161 PyMemAllocatorEx old_alloc;
162 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
163
Victor Stinner331a6a52019-05-27 16:39:22 +0200164 pathconfig_clear(&_Py_path_config);
Victor Stinnerc1834442019-03-18 22:24:28 +0100165
166 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200167}
168
169
170static wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200171_PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200172{
173 size_t len = 1; /* NUL terminator */
Victor Stinner74f65682019-03-15 15:08:05 +0100174 for (Py_ssize_t i=0; i < list->length; i++) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200175 if (i != 0) {
176 len++;
177 }
Victor Stinner74f65682019-03-15 15:08:05 +0100178 len += wcslen(list->items[i]);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200179 }
180
181 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
182 if (text == NULL) {
183 return NULL;
184 }
185 wchar_t *str = text;
Victor Stinner74f65682019-03-15 15:08:05 +0100186 for (Py_ssize_t i=0; i < list->length; i++) {
187 wchar_t *path = list->items[i];
Victor Stinnerb1147e42018-07-21 02:06:16 +0200188 if (i != 0) {
189 *str++ = SEP;
190 }
191 len = wcslen(path);
192 memcpy(str, path, len * sizeof(wchar_t));
193 str += len;
194 }
195 *str = L'\0';
196
197 return text;
198}
199
200
Victor Stinner331a6a52019-05-27 16:39:22 +0200201/* Set the global path configuration from config. */
202PyStatus
203_PyConfig_SetPathConfig(const PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200204{
205 PyMemAllocatorEx old_alloc;
206 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
207
Victor Stinner331a6a52019-05-27 16:39:22 +0200208 PyStatus status;
209 _PyPathConfig pathconfig = _PyPathConfig_INIT;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200210
Victor Stinner331a6a52019-05-27 16:39:22 +0200211 pathconfig.module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
212 if (pathconfig.module_search_path == NULL) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200213 goto no_memory;
214 }
215
Victor Stinner331a6a52019-05-27 16:39:22 +0200216 if (copy_wstr(&pathconfig.program_full_path, config->executable) < 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.prefix, config->prefix) < 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.exec_prefix, config->exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200223 goto no_memory;
224 }
Steve Dower177a41a2018-11-17 20:41:48 -0800225#ifdef MS_WINDOWS
Victor Stinner331a6a52019-05-27 16:39:22 +0200226 pathconfig.dll_path = _Py_GetDLLPath();
227 if (pathconfig.dll_path == NULL) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200228 goto no_memory;
229 }
230#endif
Victor Stinner331a6a52019-05-27 16:39:22 +0200231 if (copy_wstr(&pathconfig.program_name, config->program_name) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200232 goto no_memory;
233 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200234 if (copy_wstr(&pathconfig.home, config->home) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200235 goto no_memory;
236 }
Steve Dower323e7432019-06-29 14:28:59 -0700237 if (copy_wstr(&pathconfig.base_executable, config->base_executable) < 0) {
238 goto no_memory;
239 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200240
Victor Stinner331a6a52019-05-27 16:39:22 +0200241 status = _PyPathConfig_SetGlobal(&pathconfig);
242 if (_PyStatus_EXCEPTION(status)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200243 goto done;
244 }
245
Victor Stinner331a6a52019-05-27 16:39:22 +0200246 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200247 goto done;
248
249no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200250 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200251
252done:
Victor Stinner331a6a52019-05-27 16:39:22 +0200253 pathconfig_clear(&pathconfig);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200254 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200255 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200256}
257
258
Victor Stinner331a6a52019-05-27 16:39:22 +0200259static PyStatus
260config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200261{
Victor Stinner331a6a52019-05-27 16:39:22 +0200262 assert(!config->module_search_paths_set);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200263
Victor Stinner331a6a52019-05-27 16:39:22 +0200264 _PyWideStringList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200265
Victor Stinner331a6a52019-05-27 16:39:22 +0200266 const wchar_t *sys_path = pathconfig->module_search_path;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200267 const wchar_t delim = DELIM;
268 const wchar_t *p = sys_path;
269 while (1) {
270 p = wcschr(sys_path, delim);
271 if (p == NULL) {
272 p = sys_path + wcslen(sys_path); /* End of string */
273 }
274
275 size_t path_len = (p - sys_path);
276 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
277 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200278 return _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200279 }
280 memcpy(path, sys_path, path_len * sizeof(wchar_t));
281 path[path_len] = L'\0';
282
Victor Stinner331a6a52019-05-27 16:39:22 +0200283 PyStatus status = PyWideStringList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200284 PyMem_RawFree(path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200285 if (_PyStatus_EXCEPTION(status)) {
286 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200287 }
288
289 if (*p == '\0') {
290 break;
291 }
292 sys_path = p + 1;
293 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200294 config->module_search_paths_set = 1;
295 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200296}
297
298
Victor Stinner331a6a52019-05-27 16:39:22 +0200299static PyStatus
300config_calculate_pathconfig(PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200301{
Victor Stinner331a6a52019-05-27 16:39:22 +0200302 _PyPathConfig pathconfig = _PyPathConfig_INIT;
303 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200304
Victor Stinner331a6a52019-05-27 16:39:22 +0200305 status = pathconfig_calculate(&pathconfig, config);
306 if (_PyStatus_EXCEPTION(status)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200307 goto error;
308 }
309
Victor Stinner331a6a52019-05-27 16:39:22 +0200310 if (!config->module_search_paths_set) {
311 status = config_init_module_search_paths(config, &pathconfig);
312 if (_PyStatus_EXCEPTION(status)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200313 goto error;
314 }
315 }
316
317 if (config->executable == NULL) {
318 if (copy_wstr(&config->executable,
Victor Stinner331a6a52019-05-27 16:39:22 +0200319 pathconfig.program_full_path) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200320 goto no_memory;
321 }
322 }
323
324 if (config->prefix == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200325 if (copy_wstr(&config->prefix, pathconfig.prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200326 goto no_memory;
327 }
328 }
329
330 if (config->exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800331 if (copy_wstr(&config->exec_prefix,
Victor Stinner331a6a52019-05-27 16:39:22 +0200332 pathconfig.exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200333 goto no_memory;
334 }
335 }
336
Steve Dower323e7432019-06-29 14:28:59 -0700337 if (config->base_executable == NULL) {
338 if (copy_wstr(&config->base_executable,
339 pathconfig.base_executable) < 0) {
340 goto no_memory;
341 }
342 }
343
Victor Stinner331a6a52019-05-27 16:39:22 +0200344 if (pathconfig.isolated != -1) {
345 config->isolated = pathconfig.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200346 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200347 if (pathconfig.site_import != -1) {
348 config->site_import = pathconfig.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200349 }
350
Victor Stinner331a6a52019-05-27 16:39:22 +0200351 pathconfig_clear(&pathconfig);
352 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200353
354no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200355 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200356
357error:
Victor Stinner331a6a52019-05-27 16:39:22 +0200358 pathconfig_clear(&pathconfig);
359 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200360}
361
362
Victor Stinner331a6a52019-05-27 16:39:22 +0200363PyStatus
364_PyConfig_InitPathConfig(PyConfig *config)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200365{
366 /* Do we need to calculate the path? */
Victor Stinner331a6a52019-05-27 16:39:22 +0200367 if (!config->module_search_paths_set
Victor Stinner1dc6e392018-07-25 02:49:17 +0200368 || (config->executable == NULL)
369 || (config->prefix == NULL)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200370 || (config->exec_prefix == NULL))
371 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200372 PyStatus status = config_calculate_pathconfig(config);
373 if (_PyStatus_EXCEPTION(status)) {
374 return status;
Victor Stinner1dc6e392018-07-25 02:49:17 +0200375 }
376 }
377
378 if (config->base_prefix == NULL) {
379 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200380 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200381 }
382 }
383
384 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800385 if (copy_wstr(&config->base_exec_prefix,
386 config->exec_prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200387 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200388 }
389 }
Steve Dower323e7432019-06-29 14:28:59 -0700390
391 if (config->base_executable == NULL) {
392 if (copy_wstr(&config->base_executable,
393 config->executable) < 0) {
394 return _PyStatus_NO_MEMORY();
395 }
396 }
397
Victor Stinner331a6a52019-05-27 16:39:22 +0200398 return _PyStatus_OK();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200399}
400
401
Victor Stinner31a83932017-12-04 13:39:15 +0100402static void
403pathconfig_global_init(void)
404{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200405 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100406 /* Already initialized */
407 return;
408 }
409
Victor Stinner331a6a52019-05-27 16:39:22 +0200410 PyStatus status;
411 PyConfig config;
412 _PyConfig_InitCompatConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100413
Victor Stinner331a6a52019-05-27 16:39:22 +0200414 status = PyConfig_Read(&config);
415 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner31a83932017-12-04 13:39:15 +0100416 goto error;
417 }
418
Victor Stinner331a6a52019-05-27 16:39:22 +0200419 status = _PyConfig_SetPathConfig(&config);
420 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner31a83932017-12-04 13:39:15 +0100421 goto error;
422 }
423
Victor Stinner331a6a52019-05-27 16:39:22 +0200424 PyConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100425 return;
426
427error:
Victor Stinner331a6a52019-05-27 16:39:22 +0200428 PyConfig_Clear(&config);
429 Py_ExitStatusException(status);
Victor Stinner31a83932017-12-04 13:39:15 +0100430}
431
432
433/* External interface */
434
435void
436Py_SetPath(const wchar_t *path)
437{
438 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200439 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100440 return;
441 }
442
443 PyMemAllocatorEx old_alloc;
444 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
445
446 _PyPathConfig new_config;
447 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200448 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100449 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200450 alloc_error |= (new_config.prefix == NULL);
Steve Dower177a41a2018-11-17 20:41:48 -0800451 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
452 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100453#ifdef MS_WINDOWS
Victor Stinner410759f2019-05-18 04:17:01 +0200454 new_config.dll_path = _Py_GetDLLPath();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200455 alloc_error |= (new_config.dll_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100456#endif
457 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200458 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100459
460 /* steal the home and program_name values (to leave them unchanged) */
461 new_config.home = _Py_path_config.home;
462 _Py_path_config.home = NULL;
463 new_config.program_name = _Py_path_config.program_name;
464 _Py_path_config.program_name = NULL;
Steve Dower323e7432019-06-29 14:28:59 -0700465 new_config.base_executable = _Py_path_config.base_executable;
466 _Py_path_config.base_executable = NULL;
Victor Stinner31a83932017-12-04 13:39:15 +0100467
Victor Stinner331a6a52019-05-27 16:39:22 +0200468 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100469 _Py_path_config = new_config;
470
471 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200472
473 if (alloc_error) {
474 Py_FatalError("Py_SetPath() failed: out of memory");
475 }
Victor Stinner31a83932017-12-04 13:39:15 +0100476}
477
478
479void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200480Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100481{
482 if (home == NULL) {
483 return;
484 }
485
486 PyMemAllocatorEx old_alloc;
487 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
488
489 PyMem_RawFree(_Py_path_config.home);
490 _Py_path_config.home = _PyMem_RawWcsdup(home);
491
492 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
493
494 if (_Py_path_config.home == NULL) {
495 Py_FatalError("Py_SetPythonHome() failed: out of memory");
496 }
497}
498
499
500void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200501Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100502{
503 if (program_name == NULL || program_name[0] == L'\0') {
504 return;
505 }
506
507 PyMemAllocatorEx old_alloc;
508 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
509
510 PyMem_RawFree(_Py_path_config.program_name);
511 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
512
513 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
514
515 if (_Py_path_config.program_name == NULL) {
516 Py_FatalError("Py_SetProgramName() failed: out of memory");
517 }
518}
519
Steve Dower177a41a2018-11-17 20:41:48 -0800520void
521_Py_SetProgramFullPath(const wchar_t *program_full_path)
522{
523 if (program_full_path == NULL || program_full_path[0] == L'\0') {
524 return;
525 }
526
527 PyMemAllocatorEx old_alloc;
528 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
529
530 PyMem_RawFree(_Py_path_config.program_full_path);
531 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
532
533 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
534
535 if (_Py_path_config.program_full_path == NULL) {
536 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
537 }
538}
539
Victor Stinner31a83932017-12-04 13:39:15 +0100540
541wchar_t *
542Py_GetPath(void)
543{
544 pathconfig_global_init();
545 return _Py_path_config.module_search_path;
546}
547
548
549wchar_t *
550Py_GetPrefix(void)
551{
552 pathconfig_global_init();
553 return _Py_path_config.prefix;
554}
555
556
557wchar_t *
558Py_GetExecPrefix(void)
559{
Victor Stinner31a83932017-12-04 13:39:15 +0100560 pathconfig_global_init();
561 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100562}
563
564
565wchar_t *
566Py_GetProgramFullPath(void)
567{
568 pathconfig_global_init();
569 return _Py_path_config.program_full_path;
570}
571
572
573wchar_t*
574Py_GetPythonHome(void)
575{
576 pathconfig_global_init();
577 return _Py_path_config.home;
578}
579
580
581wchar_t *
582Py_GetProgramName(void)
583{
584 pathconfig_global_init();
585 return _Py_path_config.program_name;
586}
587
Victor Stinnerdcf61712019-03-19 16:09:27 +0100588/* Compute module search path from argv[0] or the current working
589 directory ("-m module" case) which will be prepended to sys.argv:
590 sys.path[0].
591
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200592 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100593
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200594 Return 0 if it fails to resolve the full path. For example, return 0 if the
595 current working directory has been removed (bpo-36236) or if argv is empty.
596
597 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100598 */
599int
Victor Stinner331a6a52019-05-27 16:39:22 +0200600_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100601{
Victor Stinner331a6a52019-05-27 16:39:22 +0200602 assert(_PyWideStringList_CheckConsistency(argv));
Victor Stinner74f65682019-03-15 15:08:05 +0100603
Victor Stinnerfc96e542019-03-19 18:22:55 +0100604 if (argv->length == 0) {
605 /* Leave sys.path unchanged if sys.argv is empty */
606 return 0;
607 }
608
609 wchar_t *argv0 = argv->items[0];
610 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
611 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
612
613 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100614 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100615
616#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100617 wchar_t fullpath[MAXPATHLEN];
618#elif defined(MS_WINDOWS)
619 wchar_t fullpath[MAX_PATH];
620#endif
621
Nick Coghland5d9e022018-03-25 23:03:10 +1000622 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100623#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100624 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
625 return 0;
626 }
627 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100628#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100629 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100630#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100631 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000632 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100633
634#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100635 wchar_t link[MAXPATHLEN + 1];
636 int nr = 0;
637
638 if (have_script_arg) {
639 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
640 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100641 if (nr > 0) {
642 /* It's a symlink */
643 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100644 if (link[0] == SEP) {
645 path0 = link; /* Link to absolute path */
646 }
647 else if (wcschr(link, SEP) == NULL) {
648 /* Link without path */
649 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100650 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100651 /* Must join(dirname(path0), link) */
652 wchar_t *q = wcsrchr(path0, SEP);
653 if (q == NULL) {
654 /* path0 without path */
655 path0 = link;
656 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100657 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100658 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
659 wchar_t path0copy[2 * MAXPATHLEN + 1];
660 wcsncpy(path0copy, path0, MAXPATHLEN);
661 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100662 wcsncpy(q+1, link, MAXPATHLEN);
663 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100664 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100665 }
666 }
667 }
668#endif /* HAVE_READLINK */
669
Victor Stinnerfc96e542019-03-19 18:22:55 +0100670 wchar_t *p = NULL;
671
Victor Stinner11a247d2017-12-13 21:05:57 +0100672#if SEP == '\\'
673 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000674 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100675 wchar_t *q;
676#if defined(MS_WINDOWS)
677 /* Replace the first element in argv with the full path. */
678 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100679 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100680 Py_ARRAY_LENGTH(fullpath),
681 fullpath,
682 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100683 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100684 }
685#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100686 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100687 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100688 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100689 if (q != NULL)
690 p = q;
691 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100692 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100693 if (n > 1 && p[-1] != ':')
694 n--; /* Drop trailing separator */
695 }
696 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100697#else
698 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000699 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100700#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100701 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
702 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100703 }
704#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100705 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100706 }
707 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100708 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100709#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100710 if (n > 1) {
711 /* Drop trailing separator */
712 n--;
713 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100714#endif /* Unix */
715 }
716#endif /* All others */
717
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200718 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
719 if (path0_obj == NULL) {
720 return -1;
721 }
722
723 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100724 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100725}
726
Victor Stinner9bee3292017-12-21 16:49:13 +0100727
Minmin Gong8ebc6452019-02-02 20:26:55 -0800728#ifdef MS_WINDOWS
729#define WCSTOK wcstok_s
730#else
731#define WCSTOK wcstok
732#endif
733
Victor Stinner9bee3292017-12-21 16:49:13 +0100734/* Search for a prefix value in an environment file (pyvenv.cfg).
735 If found, copy it into the provided buffer. */
736int
737_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
738 wchar_t *value, size_t value_size)
739{
740 int result = 0; /* meaning not found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100741 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
742 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100743
744 fseek(env_file, 0, SEEK_SET);
745 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100746 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100747
748 if (p == NULL) {
749 break;
750 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100751
752 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100753 if (p[n - 1] != '\n') {
754 /* line has overflowed - bail */
755 break;
756 }
757 if (p[0] == '#') {
758 /* Comment - skip */
759 continue;
760 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100761
Victor Stinner5f9cf232019-03-19 01:46:25 +0100762 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100763 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100764 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800765 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100766 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800767 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100768 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800769 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100770 if (tok != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100771 wcsncpy(value, tok, value_size - 1);
772 value[value_size - 1] = L'\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100773 result = 1;
774 PyMem_RawFree(tmpbuffer);
775 break;
776 }
777 }
778 }
779 PyMem_RawFree(tmpbuffer);
780 }
781 }
782 return result;
783}
784
Victor Stinner31a83932017-12-04 13:39:15 +0100785#ifdef __cplusplus
786}
787#endif