blob: 60c104492d6468da7721c0487bc6b48e49235174 [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{
Victor Stinner96c84752019-09-26 16:17:34 +020023 assert(*dst == NULL);
Victor Stinnerb1147e42018-07-21 02:06:16 +020024 if (src != NULL) {
25 *dst = _PyMem_RawWcsdup(src);
26 if (*dst == NULL) {
27 return -1;
28 }
29 }
30 else {
31 *dst = NULL;
32 }
33 return 0;
34}
35
36
37static void
Victor Stinner331a6a52019-05-27 16:39:22 +020038pathconfig_clear(_PyPathConfig *config)
Victor Stinner31a83932017-12-04 13:39:15 +010039{
40 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
41 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
42 called before Py_Initialize() which can changes the memory allocator. */
43 PyMemAllocatorEx old_alloc;
44 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
45
46#define CLEAR(ATTR) \
47 do { \
48 PyMem_RawFree(ATTR); \
49 ATTR = NULL; \
50 } while (0)
51
Victor Stinner31a83932017-12-04 13:39:15 +010052 CLEAR(config->program_full_path);
Victor Stinner3f5409a2019-09-23 19:50:27 +020053 CLEAR(config->prefix);
Steve Dower177a41a2018-11-17 20:41:48 -080054 CLEAR(config->exec_prefix);
Victor Stinner31a83932017-12-04 13:39:15 +010055 CLEAR(config->module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +010056 CLEAR(config->program_name);
Victor Stinner3f5409a2019-09-23 19:50:27 +020057 CLEAR(config->home);
Victor Stinner96c84752019-09-26 16:17:34 +020058#ifdef MS_WINDOWS
Steve Dower323e7432019-06-29 14:28:59 -070059 CLEAR(config->base_executable);
Victor Stinner96c84752019-09-26 16:17:34 +020060#endif
61
Victor Stinner31a83932017-12-04 13:39:15 +010062#undef CLEAR
63
64 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
65}
66
67
Victor Stinner331a6a52019-05-27 16:39:22 +020068static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +020069pathconfig_copy(_PyPathConfig *config, const _PyPathConfig *config2)
Victor Stinner31a83932017-12-04 13:39:15 +010070{
Victor Stinner3f5409a2019-09-23 19:50:27 +020071 pathconfig_clear(config);
Victor Stinner31a83932017-12-04 13:39:15 +010072
Victor Stinner3f5409a2019-09-23 19:50:27 +020073#define COPY_ATTR(ATTR) \
74 do { \
75 if (copy_wstr(&config->ATTR, config2->ATTR) < 0) { \
76 return _PyStatus_NO_MEMORY(); \
77 } \
78 } while (0)
Victor Stinner31a83932017-12-04 13:39:15 +010079
Victor Stinner3f5409a2019-09-23 19:50:27 +020080 COPY_ATTR(program_full_path);
81 COPY_ATTR(prefix);
82 COPY_ATTR(exec_prefix);
83 COPY_ATTR(module_search_path);
84 COPY_ATTR(program_name);
85 COPY_ATTR(home);
Victor Stinner96c84752019-09-26 16:17:34 +020086#ifdef MS_WINDOWS
Victor Stinner3f5409a2019-09-23 19:50:27 +020087 config->isolated = config2->isolated;
88 config->site_import = config2->site_import;
89 COPY_ATTR(base_executable);
Victor Stinner96c84752019-09-26 16:17:34 +020090#endif
Victor Stinner9f3dcf82019-09-21 02:13:14 +020091
Victor Stinner3f5409a2019-09-23 19:50:27 +020092#undef COPY_ATTR
Victor Stinner31a83932017-12-04 13:39:15 +010093
Victor Stinner3f5409a2019-09-23 19:50:27 +020094 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +020095}
96
97
Victor Stinnerb1147e42018-07-21 02:06:16 +020098void
99_PyPathConfig_ClearGlobal(void)
100{
Victor Stinnerc1834442019-03-18 22:24:28 +0100101 PyMemAllocatorEx old_alloc;
102 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
103
Victor Stinner331a6a52019-05-27 16:39:22 +0200104 pathconfig_clear(&_Py_path_config);
Victor Stinnerc1834442019-03-18 22:24:28 +0100105
106 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200107}
108
109
110static wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200111_PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200112{
113 size_t len = 1; /* NUL terminator */
Victor Stinner74f65682019-03-15 15:08:05 +0100114 for (Py_ssize_t i=0; i < list->length; i++) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200115 if (i != 0) {
116 len++;
117 }
Victor Stinner74f65682019-03-15 15:08:05 +0100118 len += wcslen(list->items[i]);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200119 }
120
121 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
122 if (text == NULL) {
123 return NULL;
124 }
125 wchar_t *str = text;
Victor Stinner74f65682019-03-15 15:08:05 +0100126 for (Py_ssize_t i=0; i < list->length; i++) {
127 wchar_t *path = list->items[i];
Victor Stinnerb1147e42018-07-21 02:06:16 +0200128 if (i != 0) {
Victor Stinner96c84752019-09-26 16:17:34 +0200129 *str++ = sep;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200130 }
131 len = wcslen(path);
132 memcpy(str, path, len * sizeof(wchar_t));
133 str += len;
134 }
135 *str = L'\0';
136
137 return text;
138}
139
140
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200141static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200142pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config)
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200143{
Victor Stinner331a6a52019-05-27 16:39:22 +0200144 PyStatus status;
Victor Stinner9f3dcf82019-09-21 02:13:14 +0200145 PyMemAllocatorEx old_alloc;
146 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
147
Victor Stinner3f5409a2019-09-23 19:50:27 +0200148 if (config->module_search_paths_set) {
Victor Stinner96c84752019-09-26 16:17:34 +0200149 PyMem_RawFree(pathconfig->module_search_path);
Victor Stinner3f5409a2019-09-23 19:50:27 +0200150 pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
151 if (pathconfig->module_search_path == NULL) {
152 goto no_memory;
153 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200154 }
155
Victor Stinner3f5409a2019-09-23 19:50:27 +0200156#define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \
157 if (config->CONFIG_ATTR) { \
Victor Stinner96c84752019-09-26 16:17:34 +0200158 PyMem_RawFree(pathconfig->PATH_ATTR); \
159 pathconfig->PATH_ATTR = NULL; \
Victor Stinner3f5409a2019-09-23 19:50:27 +0200160 if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \
161 goto no_memory; \
162 } \
163 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200164
Victor Stinner3f5409a2019-09-23 19:50:27 +0200165 COPY_CONFIG(program_full_path, executable);
166 COPY_CONFIG(prefix, prefix);
167 COPY_CONFIG(exec_prefix, exec_prefix);
168 COPY_CONFIG(program_name, program_name);
169 COPY_CONFIG(home, home);
Victor Stinner96c84752019-09-26 16:17:34 +0200170#ifdef MS_WINDOWS
171 COPY_CONFIG(base_executable, base_executable);
172#endif
Victor Stinner3f5409a2019-09-23 19:50:27 +0200173
174#undef COPY_CONFIG
Victor Stinnerb1147e42018-07-21 02:06:16 +0200175
Victor Stinner331a6a52019-05-27 16:39:22 +0200176 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200177 goto done;
178
179no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200180 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200181
182done:
Victor Stinnerb1147e42018-07-21 02:06:16 +0200183 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200184 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200185}
186
187
Victor Stinner96c84752019-09-26 16:17:34 +0200188PyStatus
189_PyConfig_WritePathConfig(const PyConfig *config)
190{
Victor Stinner96c84752019-09-26 16:17:34 +0200191 return pathconfig_set_from_config(&_Py_path_config, config);
192}
193
194
Victor Stinner331a6a52019-05-27 16:39:22 +0200195static PyStatus
196config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200197{
Victor Stinner331a6a52019-05-27 16:39:22 +0200198 assert(!config->module_search_paths_set);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200199
Victor Stinner331a6a52019-05-27 16:39:22 +0200200 _PyWideStringList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200201
Victor Stinner331a6a52019-05-27 16:39:22 +0200202 const wchar_t *sys_path = pathconfig->module_search_path;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200203 const wchar_t delim = DELIM;
204 const wchar_t *p = sys_path;
205 while (1) {
206 p = wcschr(sys_path, delim);
207 if (p == NULL) {
208 p = sys_path + wcslen(sys_path); /* End of string */
209 }
210
211 size_t path_len = (p - sys_path);
212 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
213 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200214 return _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200215 }
216 memcpy(path, sys_path, path_len * sizeof(wchar_t));
217 path[path_len] = L'\0';
218
Victor Stinner331a6a52019-05-27 16:39:22 +0200219 PyStatus status = PyWideStringList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200220 PyMem_RawFree(path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200221 if (_PyStatus_EXCEPTION(status)) {
222 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200223 }
224
225 if (*p == '\0') {
226 break;
227 }
228 sys_path = p + 1;
229 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200230 config->module_search_paths_set = 1;
231 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200232}
233
234
Victor Stinner3f5409a2019-09-23 19:50:27 +0200235/* Calculate the path configuration:
236
237 - exec_prefix
238 - module_search_path
239 - prefix
240 - program_full_path
241
242 On Windows, more fields are calculated:
243
244 - base_executable
245 - isolated
246 - site_import
247
248 On other platforms, isolated and site_import are left unchanged, and
249 _PyConfig_InitPathConfig() copies executable to base_executable (if it's not
250 set).
251
252 Priority, highest to lowest:
253
254 - PyConfig
255 - _Py_path_config: set by Py_SetPath(), Py_SetPythonHome()
256 and Py_SetProgramName()
257 - _PyPathConfig_Calculate()
258*/
259static PyStatus
260pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
261{
262 PyStatus status;
263
264 PyMemAllocatorEx old_alloc;
265 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
266
267 status = pathconfig_copy(pathconfig, &_Py_path_config);
268 if (_PyStatus_EXCEPTION(status)) {
269 goto done;
270 }
271
272 status = pathconfig_set_from_config(pathconfig, config);
273 if (_PyStatus_EXCEPTION(status)) {
274 goto done;
275 }
276
277 if (_Py_path_config.module_search_path == NULL) {
278 status = _PyPathConfig_Calculate(pathconfig, config);
279 }
280 else {
281 /* Py_SetPath() has been called: avoid _PyPathConfig_Calculate() */
282 }
283
284done:
285 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
286 return status;
287}
288
289
Victor Stinner331a6a52019-05-27 16:39:22 +0200290static PyStatus
291config_calculate_pathconfig(PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200292{
Victor Stinner331a6a52019-05-27 16:39:22 +0200293 _PyPathConfig pathconfig = _PyPathConfig_INIT;
294 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200295
Victor Stinner331a6a52019-05-27 16:39:22 +0200296 status = pathconfig_calculate(&pathconfig, config);
297 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200298 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200299 }
300
Victor Stinner331a6a52019-05-27 16:39:22 +0200301 if (!config->module_search_paths_set) {
302 status = config_init_module_search_paths(config, &pathconfig);
303 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200304 goto done;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200305 }
306 }
307
Victor Stinner3f5409a2019-09-23 19:50:27 +0200308#define COPY_ATTR(PATH_ATTR, CONFIG_ATTR) \
309 if (config->CONFIG_ATTR == NULL) { \
310 if (copy_wstr(&config->CONFIG_ATTR, pathconfig.PATH_ATTR) < 0) { \
311 goto no_memory; \
312 } \
Victor Stinnerb1147e42018-07-21 02:06:16 +0200313 }
Victor Stinnerb1147e42018-07-21 02:06:16 +0200314
Victor Stinner96c84752019-09-26 16:17:34 +0200315#ifdef MS_WINDOWS
316 if (config->executable != NULL && config->base_executable == NULL) {
317 /* If executable is set explicitly in the configuration,
318 ignore calculated base_executable: _PyConfig_InitPathConfig()
319 will copy executable to base_executable */
320 }
321 else {
322 COPY_ATTR(base_executable, base_executable);
323 }
324#endif
325
Victor Stinner3f5409a2019-09-23 19:50:27 +0200326 COPY_ATTR(program_full_path, executable);
327 COPY_ATTR(prefix, prefix);
328 COPY_ATTR(exec_prefix, exec_prefix);
Victor Stinner96c84752019-09-26 16:17:34 +0200329
Victor Stinner3f5409a2019-09-23 19:50:27 +0200330#undef COPY_ATTR
Steve Dower323e7432019-06-29 14:28:59 -0700331
Victor Stinner96c84752019-09-26 16:17:34 +0200332#ifdef MS_WINDOWS
333 /* If a ._pth file is found: isolated and site_import are overriden */
Victor Stinner331a6a52019-05-27 16:39:22 +0200334 if (pathconfig.isolated != -1) {
335 config->isolated = pathconfig.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200336 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200337 if (pathconfig.site_import != -1) {
338 config->site_import = pathconfig.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200339 }
Victor Stinner96c84752019-09-26 16:17:34 +0200340#endif
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200341
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 Stinner96c84752019-09-26 16:17:34 +0200359 || config->executable == NULL
360 || config->prefix == NULL
361 || config->exec_prefix == NULL)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200362 {
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{
Victor Stinner3f5409a2019-09-23 19:50:27 +0200396 PyConfig config;
Miss Islington (bot)d49f0962019-10-01 03:26:04 -0700397 _PyConfig_InitCompatConfig(&config);
Victor Stinner3f5409a2019-09-23 19:50:27 +0200398
399 /* Call _PyConfig_InitPathConfig() */
Miss Islington (bot)d49f0962019-10-01 03:26:04 -0700400 PyStatus status = PyConfig_Read(&config);
Victor Stinner3f5409a2019-09-23 19:50:27 +0200401 if (_PyStatus_EXCEPTION(status)) {
402 goto done;
403 }
404
405 status = pathconfig_set_from_config(pathconfig, &config);
406
407done:
408 PyConfig_Clear(&config);
409 return status;
410}
411
412
Victor Stinner31a83932017-12-04 13:39:15 +0100413static void
414pathconfig_global_init(void)
415{
Victor Stinner3f5409a2019-09-23 19:50:27 +0200416 PyStatus status;
417
Victor Stinner3f5409a2019-09-23 19:50:27 +0200418 if (_Py_path_config.module_search_path == NULL) {
419 status = pathconfig_global_read(&_Py_path_config);
420 if (_PyStatus_EXCEPTION(status)) {
421 Py_ExitStatusException(status);
422 }
423 }
424 else {
425 /* Global configuration already initialized */
Victor Stinner31a83932017-12-04 13:39:15 +0100426 }
427
Victor Stinner3f5409a2019-09-23 19:50:27 +0200428 assert(_Py_path_config.program_full_path != NULL);
429 assert(_Py_path_config.prefix != NULL);
430 assert(_Py_path_config.exec_prefix != NULL);
431 assert(_Py_path_config.module_search_path != NULL);
432 assert(_Py_path_config.program_name != NULL);
433 /* home can be NULL */
Victor Stinner96c84752019-09-26 16:17:34 +0200434#ifdef MS_WINDOWS
Victor Stinner3f5409a2019-09-23 19:50:27 +0200435 assert(_Py_path_config.base_executable != NULL);
Victor Stinner96c84752019-09-26 16:17:34 +0200436#endif
Victor Stinner31a83932017-12-04 13:39:15 +0100437}
438
439
440/* External interface */
441
442void
443Py_SetPath(const wchar_t *path)
444{
445 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200446 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100447 return;
448 }
449
450 PyMemAllocatorEx old_alloc;
451 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
452
Victor Stinner96c84752019-09-26 16:17:34 +0200453 /* Getting the program full path calls pathconfig_global_init() */
454 wchar_t *program_full_path = _PyMem_RawWcsdup(Py_GetProgramFullPath());
Victor Stinner31a83932017-12-04 13:39:15 +0100455
Victor Stinner3f5409a2019-09-23 19:50:27 +0200456 PyMem_RawFree(_Py_path_config.program_full_path);
457 PyMem_RawFree(_Py_path_config.prefix);
458 PyMem_RawFree(_Py_path_config.exec_prefix);
459 PyMem_RawFree(_Py_path_config.module_search_path);
Victor Stinner31a83932017-12-04 13:39:15 +0100460
Victor Stinner96c84752019-09-26 16:17:34 +0200461 _Py_path_config.program_full_path = program_full_path;
Victor Stinner3f5409a2019-09-23 19:50:27 +0200462 _Py_path_config.prefix = _PyMem_RawWcsdup(L"");
463 _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
464 _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinner31a83932017-12-04 13:39:15 +0100465
466 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200467
Victor Stinner3f5409a2019-09-23 19:50:27 +0200468 if (_Py_path_config.program_full_path == NULL
469 || _Py_path_config.prefix == NULL
470 || _Py_path_config.exec_prefix == NULL
471 || _Py_path_config.module_search_path == NULL)
472 {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200473 Py_FatalError("Py_SetPath() failed: out of memory");
474 }
Victor Stinner31a83932017-12-04 13:39:15 +0100475}
476
477
478void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200479Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100480{
481 if (home == NULL) {
482 return;
483 }
484
485 PyMemAllocatorEx old_alloc;
486 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
487
488 PyMem_RawFree(_Py_path_config.home);
489 _Py_path_config.home = _PyMem_RawWcsdup(home);
490
491 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
492
493 if (_Py_path_config.home == NULL) {
494 Py_FatalError("Py_SetPythonHome() failed: out of memory");
495 }
496}
497
498
499void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200500Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100501{
502 if (program_name == NULL || program_name[0] == L'\0') {
503 return;
504 }
505
506 PyMemAllocatorEx old_alloc;
507 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
508
509 PyMem_RawFree(_Py_path_config.program_name);
510 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
511
512 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
513
514 if (_Py_path_config.program_name == NULL) {
515 Py_FatalError("Py_SetProgramName() failed: out of memory");
516 }
517}
518
Steve Dower177a41a2018-11-17 20:41:48 -0800519void
520_Py_SetProgramFullPath(const wchar_t *program_full_path)
521{
522 if (program_full_path == NULL || program_full_path[0] == L'\0') {
523 return;
524 }
525
526 PyMemAllocatorEx old_alloc;
527 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
528
529 PyMem_RawFree(_Py_path_config.program_full_path);
530 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
531
532 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
533
534 if (_Py_path_config.program_full_path == NULL) {
535 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
536 }
537}
538
Victor Stinner31a83932017-12-04 13:39:15 +0100539
540wchar_t *
541Py_GetPath(void)
542{
543 pathconfig_global_init();
544 return _Py_path_config.module_search_path;
545}
546
547
548wchar_t *
549Py_GetPrefix(void)
550{
551 pathconfig_global_init();
552 return _Py_path_config.prefix;
553}
554
555
556wchar_t *
557Py_GetExecPrefix(void)
558{
Victor Stinner31a83932017-12-04 13:39:15 +0100559 pathconfig_global_init();
560 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100561}
562
563
564wchar_t *
565Py_GetProgramFullPath(void)
566{
567 pathconfig_global_init();
568 return _Py_path_config.program_full_path;
569}
570
571
572wchar_t*
573Py_GetPythonHome(void)
574{
575 pathconfig_global_init();
576 return _Py_path_config.home;
577}
578
579
580wchar_t *
581Py_GetProgramName(void)
582{
583 pathconfig_global_init();
584 return _Py_path_config.program_name;
585}
586
Victor Stinnerdcf61712019-03-19 16:09:27 +0100587/* Compute module search path from argv[0] or the current working
588 directory ("-m module" case) which will be prepended to sys.argv:
589 sys.path[0].
590
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200591 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100592
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200593 Return 0 if it fails to resolve the full path. For example, return 0 if the
594 current working directory has been removed (bpo-36236) or if argv is empty.
595
596 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100597 */
598int
Victor Stinner331a6a52019-05-27 16:39:22 +0200599_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100600{
Victor Stinner331a6a52019-05-27 16:39:22 +0200601 assert(_PyWideStringList_CheckConsistency(argv));
Victor Stinner74f65682019-03-15 15:08:05 +0100602
Victor Stinnerfc96e542019-03-19 18:22:55 +0100603 if (argv->length == 0) {
604 /* Leave sys.path unchanged if sys.argv is empty */
605 return 0;
606 }
607
608 wchar_t *argv0 = argv->items[0];
609 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
610 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
611
612 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100613 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100614
615#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100616 wchar_t fullpath[MAXPATHLEN];
617#elif defined(MS_WINDOWS)
618 wchar_t fullpath[MAX_PATH];
619#endif
620
Nick Coghland5d9e022018-03-25 23:03:10 +1000621 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100622#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100623 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
624 return 0;
625 }
626 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100627#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100628 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100629#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100630 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000631 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100632
633#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100634 wchar_t link[MAXPATHLEN + 1];
635 int nr = 0;
Miss Islington (bot)d5ee9b92020-06-22 00:43:41 -0700636 wchar_t path0copy[2 * MAXPATHLEN + 1];
Victor Stinnerfc96e542019-03-19 18:22:55 +0100637
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 */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100659 wcsncpy(path0copy, path0, MAXPATHLEN);
660 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100661 wcsncpy(q+1, link, MAXPATHLEN);
662 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100663 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100664 }
665 }
666 }
667#endif /* HAVE_READLINK */
668
Victor Stinnerfc96e542019-03-19 18:22:55 +0100669 wchar_t *p = NULL;
670
Victor Stinner11a247d2017-12-13 21:05:57 +0100671#if SEP == '\\'
672 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000673 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100674 wchar_t *q;
675#if defined(MS_WINDOWS)
676 /* Replace the first element in argv with the full path. */
677 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100678 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100679 Py_ARRAY_LENGTH(fullpath),
680 fullpath,
681 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100682 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100683 }
684#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100685 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100686 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100687 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100688 if (q != NULL)
689 p = q;
690 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100691 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100692 if (n > 1 && p[-1] != ':')
693 n--; /* Drop trailing separator */
694 }
695 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100696#else
697 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000698 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100699#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100700 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
701 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100702 }
703#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100704 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100705 }
706 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100707 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100708#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100709 if (n > 1) {
710 /* Drop trailing separator */
711 n--;
712 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100713#endif /* Unix */
714 }
715#endif /* All others */
716
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200717 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
718 if (path0_obj == NULL) {
719 return -1;
720 }
721
722 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100723 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100724}
725
Victor Stinner9bee3292017-12-21 16:49:13 +0100726
Minmin Gong8ebc6452019-02-02 20:26:55 -0800727#ifdef MS_WINDOWS
728#define WCSTOK wcstok_s
729#else
730#define WCSTOK wcstok
731#endif
732
Victor Stinner9bee3292017-12-21 16:49:13 +0100733/* Search for a prefix value in an environment file (pyvenv.cfg).
734 If found, copy it into the provided buffer. */
735int
736_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
737 wchar_t *value, size_t value_size)
738{
739 int result = 0; /* meaning not found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100740 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
741 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100742
743 fseek(env_file, 0, SEEK_SET);
744 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100745 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100746
747 if (p == NULL) {
748 break;
749 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100750
751 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100752 if (p[n - 1] != '\n') {
753 /* line has overflowed - bail */
754 break;
755 }
756 if (p[0] == '#') {
757 /* Comment - skip */
758 continue;
759 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100760
Victor Stinner5f9cf232019-03-19 01:46:25 +0100761 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100762 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100763 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800764 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100765 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800766 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100767 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800768 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100769 if (tok != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100770 wcsncpy(value, tok, value_size - 1);
771 value[value_size - 1] = L'\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100772 result = 1;
773 PyMem_RawFree(tmpbuffer);
774 break;
775 }
776 }
777 }
778 PyMem_RawFree(tmpbuffer);
779 }
780 }
781 return result;
782}
783
Victor Stinner31a83932017-12-04 13:39:15 +0100784#ifdef __cplusplus
785}
786#endif