blob: 09533100b46385ff48d907f91e8bf366bd32456f [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
Victor Stinner31a83932017-12-04 13:39:15 +010054 CLEAR(config->program_full_path);
Victor Stinner3f5409a2019-09-23 19:50:27 +020055 CLEAR(config->prefix);
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);
Victor Stinner31a83932017-12-04 13:39:15 +010058 CLEAR(config->program_name);
Victor Stinner3f5409a2019-09-23 19:50:27 +020059 CLEAR(config->home);
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 +020067static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +020068pathconfig_copy(_PyPathConfig *config, const _PyPathConfig *config2)
Victor Stinner31a83932017-12-04 13:39:15 +010069{
Victor Stinner3f5409a2019-09-23 19:50:27 +020070 pathconfig_clear(config);
Victor Stinner31a83932017-12-04 13:39:15 +010071
Victor Stinner3f5409a2019-09-23 19:50:27 +020072#define COPY_ATTR(ATTR) \
73 do { \
74 if (copy_wstr(&config->ATTR, config2->ATTR) < 0) { \
75 return _PyStatus_NO_MEMORY(); \
76 } \
77 } while (0)
Victor Stinner31a83932017-12-04 13:39:15 +010078
Victor Stinner3f5409a2019-09-23 19:50:27 +020079 COPY_ATTR(program_full_path);
80 COPY_ATTR(prefix);
81 COPY_ATTR(exec_prefix);
82 COPY_ATTR(module_search_path);
83 COPY_ATTR(program_name);
84 COPY_ATTR(home);
85 config->isolated = config2->isolated;
86 config->site_import = config2->site_import;
87 COPY_ATTR(base_executable);
Victor Stinner9f3dcf82019-09-21 02:13:14 +020088
Victor Stinner3f5409a2019-09-23 19:50:27 +020089#undef COPY_ATTR
Victor Stinner31a83932017-12-04 13:39:15 +010090
Victor Stinner3f5409a2019-09-23 19:50:27 +020091 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +020092}
93
94
Victor Stinnerb1147e42018-07-21 02:06:16 +020095void
96_PyPathConfig_ClearGlobal(void)
97{
Victor Stinnerc1834442019-03-18 22:24:28 +010098 PyMemAllocatorEx old_alloc;
99 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
100
Victor Stinner331a6a52019-05-27 16:39:22 +0200101 pathconfig_clear(&_Py_path_config);
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200102#ifdef MS_WINDOWS
103 PyMem_RawFree(_Py_dll_path);
104 _Py_dll_path = NULL;
105#endif
Victor Stinnerc1834442019-03-18 22:24:28 +0100106
107 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200108}
109
110
111static wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200112_PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200113{
114 size_t len = 1; /* NUL terminator */
Victor Stinner74f65682019-03-15 15:08:05 +0100115 for (Py_ssize_t i=0; i < list->length; i++) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200116 if (i != 0) {
117 len++;
118 }
Victor Stinner74f65682019-03-15 15:08:05 +0100119 len += wcslen(list->items[i]);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200120 }
121
122 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
123 if (text == NULL) {
124 return NULL;
125 }
126 wchar_t *str = text;
Victor Stinner74f65682019-03-15 15:08:05 +0100127 for (Py_ssize_t i=0; i < list->length; i++) {
128 wchar_t *path = list->items[i];
Victor Stinnerb1147e42018-07-21 02:06:16 +0200129 if (i != 0) {
130 *str++ = SEP;
131 }
132 len = wcslen(path);
133 memcpy(str, path, len * sizeof(wchar_t));
134 str += len;
135 }
136 *str = L'\0';
137
138 return text;
139}
140
141
Victor Stinner3f5409a2019-09-23 19:50:27 +0200142/* Initialize _Py_dll_path on Windows. Do nothing on other platforms. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200143PyStatus
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200144_PyPathConfig_Init(void)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200145{
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200146#ifdef MS_WINDOWS
147 if (_Py_dll_path == NULL) {
148 /* Already set: nothing to do */
149 return _PyStatus_OK();
150 }
151
Victor Stinnerb1147e42018-07-21 02:06:16 +0200152 PyMemAllocatorEx old_alloc;
153 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
154
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200155 _Py_dll_path = _Py_GetDLLPath();
156
157 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
158
159 if (_Py_dll_path == NULL) {
160 return _PyStatus_NO_MEMORY();
161 }
162#endif
163 return _PyStatus_OK();
164}
165
166
167static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200168pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config)
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200169{
Victor Stinner331a6a52019-05-27 16:39:22 +0200170 PyStatus status;
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200171 PyMemAllocatorEx old_alloc;
172 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
173
Victor Stinner3f5409a2019-09-23 19:50:27 +0200174 if (config->module_search_paths_set) {
175 pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
176 if (pathconfig->module_search_path == NULL) {
177 goto no_memory;
178 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200179 }
180
Victor Stinner3f5409a2019-09-23 19:50:27 +0200181#define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \
182 if (config->CONFIG_ATTR) { \
183 if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \
184 goto no_memory; \
185 } \
186 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200187
Victor Stinner3f5409a2019-09-23 19:50:27 +0200188 COPY_CONFIG(base_executable, base_executable);
189 COPY_CONFIG(program_full_path, executable);
190 COPY_CONFIG(prefix, prefix);
191 COPY_CONFIG(exec_prefix, exec_prefix);
192 COPY_CONFIG(program_name, program_name);
193 COPY_CONFIG(home, home);
194
195#undef COPY_CONFIG
Victor Stinnerb1147e42018-07-21 02:06:16 +0200196
Victor Stinner331a6a52019-05-27 16:39:22 +0200197 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200198 goto done;
199
200no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200201 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200202
203done:
Victor Stinnerb1147e42018-07-21 02:06:16 +0200204 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200205 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200206}
207
208
Victor Stinner331a6a52019-05-27 16:39:22 +0200209static PyStatus
210config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200211{
Victor Stinner331a6a52019-05-27 16:39:22 +0200212 assert(!config->module_search_paths_set);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200213
Victor Stinner331a6a52019-05-27 16:39:22 +0200214 _PyWideStringList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200215
Victor Stinner331a6a52019-05-27 16:39:22 +0200216 const wchar_t *sys_path = pathconfig->module_search_path;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200217 const wchar_t delim = DELIM;
218 const wchar_t *p = sys_path;
219 while (1) {
220 p = wcschr(sys_path, delim);
221 if (p == NULL) {
222 p = sys_path + wcslen(sys_path); /* End of string */
223 }
224
225 size_t path_len = (p - sys_path);
226 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
227 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200228 return _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200229 }
230 memcpy(path, sys_path, path_len * sizeof(wchar_t));
231 path[path_len] = L'\0';
232
Victor Stinner331a6a52019-05-27 16:39:22 +0200233 PyStatus status = PyWideStringList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200234 PyMem_RawFree(path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200235 if (_PyStatus_EXCEPTION(status)) {
236 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200237 }
238
239 if (*p == '\0') {
240 break;
241 }
242 sys_path = p + 1;
243 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200244 config->module_search_paths_set = 1;
245 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200246}
247
248
Victor Stinner3f5409a2019-09-23 19:50:27 +0200249/* Calculate the path configuration:
250
251 - exec_prefix
252 - module_search_path
253 - prefix
254 - program_full_path
255
256 On Windows, more fields are calculated:
257
258 - base_executable
259 - isolated
260 - site_import
261
262 On other platforms, isolated and site_import are left unchanged, and
263 _PyConfig_InitPathConfig() copies executable to base_executable (if it's not
264 set).
265
266 Priority, highest to lowest:
267
268 - PyConfig
269 - _Py_path_config: set by Py_SetPath(), Py_SetPythonHome()
270 and Py_SetProgramName()
271 - _PyPathConfig_Calculate()
272*/
273static PyStatus
274pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
275{
276 PyStatus status;
277
278 PyMemAllocatorEx old_alloc;
279 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
280
281 status = pathconfig_copy(pathconfig, &_Py_path_config);
282 if (_PyStatus_EXCEPTION(status)) {
283 goto done;
284 }
285
286 status = pathconfig_set_from_config(pathconfig, config);
287 if (_PyStatus_EXCEPTION(status)) {
288 goto done;
289 }
290
291 if (_Py_path_config.module_search_path == NULL) {
292 status = _PyPathConfig_Calculate(pathconfig, config);
293 }
294 else {
295 /* Py_SetPath() has been called: avoid _PyPathConfig_Calculate() */
296 }
297
298done:
299 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
300 return status;
301}
302
303
Victor Stinner331a6a52019-05-27 16:39:22 +0200304static PyStatus
305config_calculate_pathconfig(PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200306{
Victor Stinner331a6a52019-05-27 16:39:22 +0200307 _PyPathConfig pathconfig = _PyPathConfig_INIT;
308 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200309
Victor Stinner331a6a52019-05-27 16:39:22 +0200310 status = pathconfig_calculate(&pathconfig, config);
311 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200312 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200313 }
314
Victor Stinner331a6a52019-05-27 16:39:22 +0200315 if (!config->module_search_paths_set) {
316 status = config_init_module_search_paths(config, &pathconfig);
317 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200318 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200319 }
320 }
321
Victor Stinner3f5409a2019-09-23 19:50:27 +0200322#define COPY_ATTR(PATH_ATTR, CONFIG_ATTR) \
323 if (config->CONFIG_ATTR == NULL) { \
324 if (copy_wstr(&config->CONFIG_ATTR, pathconfig.PATH_ATTR) < 0) { \
325 goto no_memory; \
326 } \
Victor Stinnerb1147e42018-07-21 02:06:16 +0200327 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200328
Victor Stinner3f5409a2019-09-23 19:50:27 +0200329 COPY_ATTR(program_full_path, executable);
330 COPY_ATTR(prefix, prefix);
331 COPY_ATTR(exec_prefix, exec_prefix);
332 COPY_ATTR(base_executable, base_executable);
333#undef COPY_ATTR
Steve Dower323e7432019-06-29 14:28:59 -0700334
Victor Stinner331a6a52019-05-27 16:39:22 +0200335 if (pathconfig.isolated != -1) {
336 config->isolated = pathconfig.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200337 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200338 if (pathconfig.site_import != -1) {
339 config->site_import = pathconfig.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200340 }
341
Victor Stinner3f5409a2019-09-23 19:50:27 +0200342 status = _PyStatus_OK();
343 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200344
345no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200346 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200347
Victor Stinner3f5409a2019-09-23 19:50:27 +0200348done:
Victor Stinner331a6a52019-05-27 16:39:22 +0200349 pathconfig_clear(&pathconfig);
350 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200351}
352
353
Victor Stinner331a6a52019-05-27 16:39:22 +0200354PyStatus
355_PyConfig_InitPathConfig(PyConfig *config)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200356{
357 /* Do we need to calculate the path? */
Victor Stinner331a6a52019-05-27 16:39:22 +0200358 if (!config->module_search_paths_set
Victor Stinner1dc6e392018-07-25 02:49:17 +0200359 || (config->executable == NULL)
360 || (config->prefix == NULL)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200361 || (config->exec_prefix == NULL))
362 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200363 PyStatus status = config_calculate_pathconfig(config);
364 if (_PyStatus_EXCEPTION(status)) {
365 return status;
Victor Stinner1dc6e392018-07-25 02:49:17 +0200366 }
367 }
368
369 if (config->base_prefix == NULL) {
370 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200371 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200372 }
373 }
374
375 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800376 if (copy_wstr(&config->base_exec_prefix,
377 config->exec_prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200378 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200379 }
380 }
Steve Dower323e7432019-06-29 14:28:59 -0700381
382 if (config->base_executable == NULL) {
383 if (copy_wstr(&config->base_executable,
384 config->executable) < 0) {
385 return _PyStatus_NO_MEMORY();
386 }
387 }
388
Victor Stinner331a6a52019-05-27 16:39:22 +0200389 return _PyStatus_OK();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200390}
391
392
Victor Stinner3f5409a2019-09-23 19:50:27 +0200393static PyStatus
394pathconfig_global_read(_PyPathConfig *pathconfig)
395{
396 PyStatus status;
397 PyConfig config;
398 _PyConfig_InitCompatConfig(&config);
399
400 /* Call _PyConfig_InitPathConfig() */
401 status = PyConfig_Read(&config);
402 if (_PyStatus_EXCEPTION(status)) {
403 goto done;
404 }
405
406 status = pathconfig_set_from_config(pathconfig, &config);
407
408done:
409 PyConfig_Clear(&config);
410 return status;
411}
412
413
Victor Stinner31a83932017-12-04 13:39:15 +0100414static void
415pathconfig_global_init(void)
416{
Victor Stinner3f5409a2019-09-23 19:50:27 +0200417 PyStatus status;
418
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200419 /* Initialize _Py_dll_path if needed */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200420 status = _PyPathConfig_Init();
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200421 if (_PyStatus_EXCEPTION(status)) {
422 Py_ExitStatusException(status);
423 }
424
Victor Stinner3f5409a2019-09-23 19:50:27 +0200425 if (_Py_path_config.module_search_path == NULL) {
426 status = pathconfig_global_read(&_Py_path_config);
427 if (_PyStatus_EXCEPTION(status)) {
428 Py_ExitStatusException(status);
429 }
430 }
431 else {
432 /* Global configuration already initialized */
Victor Stinner31a83932017-12-04 13:39:15 +0100433 }
434
Victor Stinner3f5409a2019-09-23 19:50:27 +0200435 assert(_Py_path_config.program_full_path != NULL);
436 assert(_Py_path_config.prefix != NULL);
437 assert(_Py_path_config.exec_prefix != NULL);
438 assert(_Py_path_config.module_search_path != NULL);
439 assert(_Py_path_config.program_name != NULL);
440 /* home can be NULL */
441 assert(_Py_path_config.base_executable != NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100442}
443
444
445/* External interface */
446
447void
448Py_SetPath(const wchar_t *path)
449{
450 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200451 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100452 return;
453 }
454
455 PyMemAllocatorEx old_alloc;
456 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
457
Victor Stinner3f5409a2019-09-23 19:50:27 +0200458 /* Getting the program name calls pathconfig_global_init() */
459 wchar_t *program_name = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinner31a83932017-12-04 13:39:15 +0100460
Victor Stinner3f5409a2019-09-23 19:50:27 +0200461 PyMem_RawFree(_Py_path_config.program_full_path);
462 PyMem_RawFree(_Py_path_config.prefix);
463 PyMem_RawFree(_Py_path_config.exec_prefix);
464 PyMem_RawFree(_Py_path_config.module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +0100465
Victor Stinner3f5409a2019-09-23 19:50:27 +0200466 /* Copy program_name to program_full_path */
467 _Py_path_config.program_full_path = program_name;
468 _Py_path_config.prefix = _PyMem_RawWcsdup(L"");
469 _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
470 _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinner31a83932017-12-04 13:39:15 +0100471
472 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200473
Victor Stinner3f5409a2019-09-23 19:50:27 +0200474 if (_Py_path_config.program_full_path == NULL
475 || _Py_path_config.prefix == NULL
476 || _Py_path_config.exec_prefix == NULL
477 || _Py_path_config.module_search_path == NULL)
478 {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200479 Py_FatalError("Py_SetPath() failed: out of memory");
480 }
Victor Stinner31a83932017-12-04 13:39:15 +0100481}
482
483
484void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200485Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100486{
487 if (home == NULL) {
488 return;
489 }
490
491 PyMemAllocatorEx old_alloc;
492 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
493
494 PyMem_RawFree(_Py_path_config.home);
495 _Py_path_config.home = _PyMem_RawWcsdup(home);
496
497 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
498
499 if (_Py_path_config.home == NULL) {
500 Py_FatalError("Py_SetPythonHome() failed: out of memory");
501 }
502}
503
504
505void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200506Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100507{
508 if (program_name == NULL || program_name[0] == L'\0') {
509 return;
510 }
511
512 PyMemAllocatorEx old_alloc;
513 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
514
515 PyMem_RawFree(_Py_path_config.program_name);
516 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
517
518 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
519
520 if (_Py_path_config.program_name == NULL) {
521 Py_FatalError("Py_SetProgramName() failed: out of memory");
522 }
523}
524
Steve Dower177a41a2018-11-17 20:41:48 -0800525void
526_Py_SetProgramFullPath(const wchar_t *program_full_path)
527{
528 if (program_full_path == NULL || program_full_path[0] == L'\0') {
529 return;
530 }
531
532 PyMemAllocatorEx old_alloc;
533 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
534
535 PyMem_RawFree(_Py_path_config.program_full_path);
536 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
537
538 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
539
540 if (_Py_path_config.program_full_path == NULL) {
541 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
542 }
543}
544
Victor Stinner31a83932017-12-04 13:39:15 +0100545
546wchar_t *
547Py_GetPath(void)
548{
549 pathconfig_global_init();
550 return _Py_path_config.module_search_path;
551}
552
553
554wchar_t *
555Py_GetPrefix(void)
556{
557 pathconfig_global_init();
558 return _Py_path_config.prefix;
559}
560
561
562wchar_t *
563Py_GetExecPrefix(void)
564{
Victor Stinner31a83932017-12-04 13:39:15 +0100565 pathconfig_global_init();
566 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100567}
568
569
570wchar_t *
571Py_GetProgramFullPath(void)
572{
573 pathconfig_global_init();
574 return _Py_path_config.program_full_path;
575}
576
577
578wchar_t*
579Py_GetPythonHome(void)
580{
581 pathconfig_global_init();
582 return _Py_path_config.home;
583}
584
585
586wchar_t *
587Py_GetProgramName(void)
588{
589 pathconfig_global_init();
590 return _Py_path_config.program_name;
591}
592
Victor Stinnerdcf61712019-03-19 16:09:27 +0100593/* Compute module search path from argv[0] or the current working
594 directory ("-m module" case) which will be prepended to sys.argv:
595 sys.path[0].
596
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200597 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100598
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200599 Return 0 if it fails to resolve the full path. For example, return 0 if the
600 current working directory has been removed (bpo-36236) or if argv is empty.
601
602 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100603 */
604int
Victor Stinner331a6a52019-05-27 16:39:22 +0200605_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100606{
Victor Stinner331a6a52019-05-27 16:39:22 +0200607 assert(_PyWideStringList_CheckConsistency(argv));
Victor Stinner74f65682019-03-15 15:08:05 +0100608
Victor Stinnerfc96e542019-03-19 18:22:55 +0100609 if (argv->length == 0) {
610 /* Leave sys.path unchanged if sys.argv is empty */
611 return 0;
612 }
613
614 wchar_t *argv0 = argv->items[0];
615 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
616 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
617
618 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100619 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100620
621#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100622 wchar_t fullpath[MAXPATHLEN];
623#elif defined(MS_WINDOWS)
624 wchar_t fullpath[MAX_PATH];
625#endif
626
Nick Coghland5d9e022018-03-25 23:03:10 +1000627 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100628#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100629 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
630 return 0;
631 }
632 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100633#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100634 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100635#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100636 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000637 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100638
639#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100640 wchar_t link[MAXPATHLEN + 1];
641 int nr = 0;
642
643 if (have_script_arg) {
644 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
645 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100646 if (nr > 0) {
647 /* It's a symlink */
648 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100649 if (link[0] == SEP) {
650 path0 = link; /* Link to absolute path */
651 }
652 else if (wcschr(link, SEP) == NULL) {
653 /* Link without path */
654 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100655 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100656 /* Must join(dirname(path0), link) */
657 wchar_t *q = wcsrchr(path0, SEP);
658 if (q == NULL) {
659 /* path0 without path */
660 path0 = link;
661 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100662 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100663 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
664 wchar_t path0copy[2 * MAXPATHLEN + 1];
665 wcsncpy(path0copy, path0, MAXPATHLEN);
666 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100667 wcsncpy(q+1, link, MAXPATHLEN);
668 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100669 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100670 }
671 }
672 }
673#endif /* HAVE_READLINK */
674
Victor Stinnerfc96e542019-03-19 18:22:55 +0100675 wchar_t *p = NULL;
676
Victor Stinner11a247d2017-12-13 21:05:57 +0100677#if SEP == '\\'
678 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000679 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100680 wchar_t *q;
681#if defined(MS_WINDOWS)
682 /* Replace the first element in argv with the full path. */
683 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100684 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100685 Py_ARRAY_LENGTH(fullpath),
686 fullpath,
687 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100688 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100689 }
690#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100691 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100692 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100693 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100694 if (q != NULL)
695 p = q;
696 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100697 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100698 if (n > 1 && p[-1] != ':')
699 n--; /* Drop trailing separator */
700 }
701 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100702#else
703 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000704 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100705#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100706 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
707 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100708 }
709#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100710 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100711 }
712 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100713 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100714#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100715 if (n > 1) {
716 /* Drop trailing separator */
717 n--;
718 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100719#endif /* Unix */
720 }
721#endif /* All others */
722
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200723 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
724 if (path0_obj == NULL) {
725 return -1;
726 }
727
728 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100729 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100730}
731
Victor Stinner9bee3292017-12-21 16:49:13 +0100732
Minmin Gong8ebc6452019-02-02 20:26:55 -0800733#ifdef MS_WINDOWS
734#define WCSTOK wcstok_s
735#else
736#define WCSTOK wcstok
737#endif
738
Victor Stinner9bee3292017-12-21 16:49:13 +0100739/* Search for a prefix value in an environment file (pyvenv.cfg).
740 If found, copy it into the provided buffer. */
741int
742_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
743 wchar_t *value, size_t value_size)
744{
745 int result = 0; /* meaning not found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100746 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
747 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100748
749 fseek(env_file, 0, SEEK_SET);
750 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100751 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100752
753 if (p == NULL) {
754 break;
755 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100756
757 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100758 if (p[n - 1] != '\n') {
759 /* line has overflowed - bail */
760 break;
761 }
762 if (p[0] == '#') {
763 /* Comment - skip */
764 continue;
765 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100766
Victor Stinner5f9cf232019-03-19 01:46:25 +0100767 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100768 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100769 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800770 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100771 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800772 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100773 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800774 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100775 if (tok != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100776 wcsncpy(value, tok, value_size - 1);
777 value[value_size - 1] = L'\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100778 result = 1;
779 PyMem_RawFree(tmpbuffer);
780 break;
781 }
782 }
783 }
784 PyMem_RawFree(tmpbuffer);
785 }
786 }
787 return result;
788}
789
Victor Stinner31a83932017-12-04 13:39:15 +0100790#ifdef __cplusplus
791}
792#endif