blob: ec67405a28d0544683f44774fc103cf848c016ed [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);
60#undef CLEAR
61
62 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
63}
64
65
Victor Stinner331a6a52019-05-27 16:39:22 +020066/* Calculate the path configuration: initialize pathconfig from config */
67static PyStatus
68pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Victor Stinner31a83932017-12-04 13:39:15 +010069{
Victor Stinner331a6a52019-05-27 16:39:22 +020070 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +010071 _PyPathConfig new_config = _PyPathConfig_INIT;
72
73 PyMemAllocatorEx old_alloc;
74 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
75
Steve Dower177a41a2018-11-17 20:41:48 -080076 /* Calculate program_full_path, prefix, exec_prefix,
77 dll_path (Windows), and module_search_path */
Victor Stinner331a6a52019-05-27 16:39:22 +020078 status = _PyPathConfig_Calculate(&new_config, config);
79 if (_PyStatus_EXCEPTION(status)) {
80 goto error;
Victor Stinner31a83932017-12-04 13:39:15 +010081 }
82
Victor Stinner331a6a52019-05-27 16:39:22 +020083 /* Copy home and program_name from config */
84 if (copy_wstr(&new_config.home, config->home) < 0) {
85 status = _PyStatus_NO_MEMORY();
86 goto error;
Victor Stinner31a83932017-12-04 13:39:15 +010087 }
Victor Stinner331a6a52019-05-27 16:39:22 +020088 if (copy_wstr(&new_config.program_name, config->program_name) < 0) {
89 status = _PyStatus_NO_MEMORY();
90 goto error;
Victor Stinner31a83932017-12-04 13:39:15 +010091 }
92
Victor Stinner331a6a52019-05-27 16:39:22 +020093 pathconfig_clear(pathconfig);
94 *pathconfig = new_config;
Victor Stinnerb1147e42018-07-21 02:06:16 +020095
Victor Stinner331a6a52019-05-27 16:39:22 +020096 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +020097 goto done;
98
Victor Stinner331a6a52019-05-27 16:39:22 +020099error:
100 pathconfig_clear(&new_config);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200101
102done:
103 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200104 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200105}
106
107
Victor Stinner331a6a52019-05-27 16:39:22 +0200108PyStatus
Victor Stinnerb1147e42018-07-21 02:06:16 +0200109_PyPathConfig_SetGlobal(const _PyPathConfig *config)
110{
Victor Stinner331a6a52019-05-27 16:39:22 +0200111 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200112 _PyPathConfig new_config = _PyPathConfig_INIT;
113
114 PyMemAllocatorEx old_alloc;
115 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
116
117#define COPY_ATTR(ATTR) \
118 do { \
119 if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \
Victor Stinner331a6a52019-05-27 16:39:22 +0200120 pathconfig_clear(&new_config); \
121 status = _PyStatus_NO_MEMORY(); \
Victor Stinnerb1147e42018-07-21 02:06:16 +0200122 goto done; \
123 } \
124 } while (0)
125
126 COPY_ATTR(program_full_path);
127 COPY_ATTR(prefix);
Steve Dower177a41a2018-11-17 20:41:48 -0800128 COPY_ATTR(exec_prefix);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200129#ifdef MS_WINDOWS
130 COPY_ATTR(dll_path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200131#endif
132 COPY_ATTR(module_search_path);
133 COPY_ATTR(program_name);
134 COPY_ATTR(home);
Victor Stinner31a83932017-12-04 13:39:15 +0100135
Victor Stinner331a6a52019-05-27 16:39:22 +0200136 pathconfig_clear(&_Py_path_config);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200137 /* Steal new_config strings; don't clear new_config */
Victor Stinner31a83932017-12-04 13:39:15 +0100138 _Py_path_config = new_config;
139
Victor Stinner331a6a52019-05-27 16:39:22 +0200140 status = _PyStatus_OK();
Victor Stinner31a83932017-12-04 13:39:15 +0100141
142done:
143 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200144 return status;
Victor Stinner31a83932017-12-04 13:39:15 +0100145}
146
147
Victor Stinnerb1147e42018-07-21 02:06:16 +0200148void
149_PyPathConfig_ClearGlobal(void)
150{
Victor Stinnerc1834442019-03-18 22:24:28 +0100151 PyMemAllocatorEx old_alloc;
152 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
153
Victor Stinner331a6a52019-05-27 16:39:22 +0200154 pathconfig_clear(&_Py_path_config);
Victor Stinnerc1834442019-03-18 22:24:28 +0100155
156 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200157}
158
159
160static wchar_t*
Victor Stinner331a6a52019-05-27 16:39:22 +0200161_PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200162{
163 size_t len = 1; /* NUL terminator */
Victor Stinner74f65682019-03-15 15:08:05 +0100164 for (Py_ssize_t i=0; i < list->length; i++) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200165 if (i != 0) {
166 len++;
167 }
Victor Stinner74f65682019-03-15 15:08:05 +0100168 len += wcslen(list->items[i]);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200169 }
170
171 wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
172 if (text == NULL) {
173 return NULL;
174 }
175 wchar_t *str = text;
Victor Stinner74f65682019-03-15 15:08:05 +0100176 for (Py_ssize_t i=0; i < list->length; i++) {
177 wchar_t *path = list->items[i];
Victor Stinnerb1147e42018-07-21 02:06:16 +0200178 if (i != 0) {
179 *str++ = SEP;
180 }
181 len = wcslen(path);
182 memcpy(str, path, len * sizeof(wchar_t));
183 str += len;
184 }
185 *str = L'\0';
186
187 return text;
188}
189
190
Victor Stinner331a6a52019-05-27 16:39:22 +0200191/* Set the global path configuration from config. */
192PyStatus
193_PyConfig_SetPathConfig(const PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200194{
195 PyMemAllocatorEx old_alloc;
196 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
197
Victor Stinner331a6a52019-05-27 16:39:22 +0200198 PyStatus status;
199 _PyPathConfig pathconfig = _PyPathConfig_INIT;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200200
Victor Stinner331a6a52019-05-27 16:39:22 +0200201 pathconfig.module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
202 if (pathconfig.module_search_path == NULL) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200203 goto no_memory;
204 }
205
Victor Stinner331a6a52019-05-27 16:39:22 +0200206 if (copy_wstr(&pathconfig.program_full_path, config->executable) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200207 goto no_memory;
208 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200209 if (copy_wstr(&pathconfig.prefix, config->prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200210 goto no_memory;
211 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200212 if (copy_wstr(&pathconfig.exec_prefix, config->exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200213 goto no_memory;
214 }
Steve Dower177a41a2018-11-17 20:41:48 -0800215#ifdef MS_WINDOWS
Victor Stinner331a6a52019-05-27 16:39:22 +0200216 pathconfig.dll_path = _Py_GetDLLPath();
217 if (pathconfig.dll_path == NULL) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200218 goto no_memory;
219 }
220#endif
Victor Stinner331a6a52019-05-27 16:39:22 +0200221 if (copy_wstr(&pathconfig.program_name, config->program_name) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200222 goto no_memory;
223 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200224 if (copy_wstr(&pathconfig.home, config->home) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200225 goto no_memory;
226 }
227
Victor Stinner331a6a52019-05-27 16:39:22 +0200228 status = _PyPathConfig_SetGlobal(&pathconfig);
229 if (_PyStatus_EXCEPTION(status)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200230 goto done;
231 }
232
Victor Stinner331a6a52019-05-27 16:39:22 +0200233 status = _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200234 goto done;
235
236no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200237 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200238
239done:
Victor Stinner331a6a52019-05-27 16:39:22 +0200240 pathconfig_clear(&pathconfig);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200241 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinner331a6a52019-05-27 16:39:22 +0200242 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200243}
244
245
Victor Stinner331a6a52019-05-27 16:39:22 +0200246static PyStatus
247config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200248{
Victor Stinner331a6a52019-05-27 16:39:22 +0200249 assert(!config->module_search_paths_set);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200250
Victor Stinner331a6a52019-05-27 16:39:22 +0200251 _PyWideStringList_Clear(&config->module_search_paths);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200252
Victor Stinner331a6a52019-05-27 16:39:22 +0200253 const wchar_t *sys_path = pathconfig->module_search_path;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200254 const wchar_t delim = DELIM;
255 const wchar_t *p = sys_path;
256 while (1) {
257 p = wcschr(sys_path, delim);
258 if (p == NULL) {
259 p = sys_path + wcslen(sys_path); /* End of string */
260 }
261
262 size_t path_len = (p - sys_path);
263 wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
264 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200265 return _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200266 }
267 memcpy(path, sys_path, path_len * sizeof(wchar_t));
268 path[path_len] = L'\0';
269
Victor Stinner331a6a52019-05-27 16:39:22 +0200270 PyStatus status = PyWideStringList_Append(&config->module_search_paths, path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200271 PyMem_RawFree(path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200272 if (_PyStatus_EXCEPTION(status)) {
273 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200274 }
275
276 if (*p == '\0') {
277 break;
278 }
279 sys_path = p + 1;
280 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200281 config->module_search_paths_set = 1;
282 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200283}
284
285
Victor Stinner331a6a52019-05-27 16:39:22 +0200286static PyStatus
287config_calculate_pathconfig(PyConfig *config)
Victor Stinnerb1147e42018-07-21 02:06:16 +0200288{
Victor Stinner331a6a52019-05-27 16:39:22 +0200289 _PyPathConfig pathconfig = _PyPathConfig_INIT;
290 PyStatus status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200291
Victor Stinner331a6a52019-05-27 16:39:22 +0200292 status = pathconfig_calculate(&pathconfig, config);
293 if (_PyStatus_EXCEPTION(status)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200294 goto error;
295 }
296
Victor Stinner331a6a52019-05-27 16:39:22 +0200297 if (!config->module_search_paths_set) {
298 status = config_init_module_search_paths(config, &pathconfig);
299 if (_PyStatus_EXCEPTION(status)) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200300 goto error;
301 }
302 }
303
304 if (config->executable == NULL) {
305 if (copy_wstr(&config->executable,
Victor Stinner331a6a52019-05-27 16:39:22 +0200306 pathconfig.program_full_path) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200307 goto no_memory;
308 }
309 }
310
311 if (config->prefix == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200312 if (copy_wstr(&config->prefix, pathconfig.prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200313 goto no_memory;
314 }
315 }
316
317 if (config->exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800318 if (copy_wstr(&config->exec_prefix,
Victor Stinner331a6a52019-05-27 16:39:22 +0200319 pathconfig.exec_prefix) < 0) {
Victor Stinnerb1147e42018-07-21 02:06:16 +0200320 goto no_memory;
321 }
322 }
323
Victor Stinner331a6a52019-05-27 16:39:22 +0200324 if (pathconfig.isolated != -1) {
325 config->isolated = pathconfig.isolated;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200326 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200327 if (pathconfig.site_import != -1) {
328 config->site_import = pathconfig.site_import;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200329 }
330
Victor Stinner331a6a52019-05-27 16:39:22 +0200331 pathconfig_clear(&pathconfig);
332 return _PyStatus_OK();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200333
334no_memory:
Victor Stinner331a6a52019-05-27 16:39:22 +0200335 status = _PyStatus_NO_MEMORY();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200336
337error:
Victor Stinner331a6a52019-05-27 16:39:22 +0200338 pathconfig_clear(&pathconfig);
339 return status;
Victor Stinnerb1147e42018-07-21 02:06:16 +0200340}
341
342
Victor Stinner331a6a52019-05-27 16:39:22 +0200343PyStatus
344_PyConfig_InitPathConfig(PyConfig *config)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200345{
346 /* Do we need to calculate the path? */
Victor Stinner331a6a52019-05-27 16:39:22 +0200347 if (!config->module_search_paths_set
Victor Stinner1dc6e392018-07-25 02:49:17 +0200348 || (config->executable == NULL)
349 || (config->prefix == NULL)
Victor Stinner1dc6e392018-07-25 02:49:17 +0200350 || (config->exec_prefix == NULL))
351 {
Victor Stinner331a6a52019-05-27 16:39:22 +0200352 PyStatus status = config_calculate_pathconfig(config);
353 if (_PyStatus_EXCEPTION(status)) {
354 return status;
Victor Stinner1dc6e392018-07-25 02:49:17 +0200355 }
356 }
357
358 if (config->base_prefix == NULL) {
359 if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200360 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200361 }
362 }
363
364 if (config->base_exec_prefix == NULL) {
Steve Dower177a41a2018-11-17 20:41:48 -0800365 if (copy_wstr(&config->base_exec_prefix,
366 config->exec_prefix) < 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200367 return _PyStatus_NO_MEMORY();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200368 }
369 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200370 return _PyStatus_OK();
Victor Stinner1dc6e392018-07-25 02:49:17 +0200371}
372
373
Victor Stinner31a83932017-12-04 13:39:15 +0100374static void
375pathconfig_global_init(void)
376{
Victor Stinnerb1147e42018-07-21 02:06:16 +0200377 if (_Py_path_config.module_search_path != NULL) {
Victor Stinner31a83932017-12-04 13:39:15 +0100378 /* Already initialized */
379 return;
380 }
381
Victor Stinner331a6a52019-05-27 16:39:22 +0200382 PyStatus status;
383 PyConfig config;
384 _PyConfig_InitCompatConfig(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100385
Victor Stinner331a6a52019-05-27 16:39:22 +0200386 status = PyConfig_Read(&config);
387 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner31a83932017-12-04 13:39:15 +0100388 goto error;
389 }
390
Victor Stinner331a6a52019-05-27 16:39:22 +0200391 status = _PyConfig_SetPathConfig(&config);
392 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner31a83932017-12-04 13:39:15 +0100393 goto error;
394 }
395
Victor Stinner331a6a52019-05-27 16:39:22 +0200396 PyConfig_Clear(&config);
Victor Stinner31a83932017-12-04 13:39:15 +0100397 return;
398
399error:
Victor Stinner331a6a52019-05-27 16:39:22 +0200400 PyConfig_Clear(&config);
401 Py_ExitStatusException(status);
Victor Stinner31a83932017-12-04 13:39:15 +0100402}
403
404
405/* External interface */
406
407void
408Py_SetPath(const wchar_t *path)
409{
410 if (path == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200411 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100412 return;
413 }
414
415 PyMemAllocatorEx old_alloc;
416 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
417
418 _PyPathConfig new_config;
419 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
Victor Stinnerb1147e42018-07-21 02:06:16 +0200420 int alloc_error = (new_config.program_full_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100421 new_config.prefix = _PyMem_RawWcsdup(L"");
Victor Stinnerb1147e42018-07-21 02:06:16 +0200422 alloc_error |= (new_config.prefix == NULL);
Steve Dower177a41a2018-11-17 20:41:48 -0800423 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
424 alloc_error |= (new_config.exec_prefix == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100425#ifdef MS_WINDOWS
Victor Stinner410759f2019-05-18 04:17:01 +0200426 new_config.dll_path = _Py_GetDLLPath();
Victor Stinnerb1147e42018-07-21 02:06:16 +0200427 alloc_error |= (new_config.dll_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100428#endif
429 new_config.module_search_path = _PyMem_RawWcsdup(path);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200430 alloc_error |= (new_config.module_search_path == NULL);
Victor Stinner31a83932017-12-04 13:39:15 +0100431
432 /* steal the home and program_name values (to leave them unchanged) */
433 new_config.home = _Py_path_config.home;
434 _Py_path_config.home = NULL;
435 new_config.program_name = _Py_path_config.program_name;
436 _Py_path_config.program_name = NULL;
437
Victor Stinner331a6a52019-05-27 16:39:22 +0200438 pathconfig_clear(&_Py_path_config);
Victor Stinner31a83932017-12-04 13:39:15 +0100439 _Py_path_config = new_config;
440
441 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Victor Stinnerb1147e42018-07-21 02:06:16 +0200442
443 if (alloc_error) {
444 Py_FatalError("Py_SetPath() failed: out of memory");
445 }
Victor Stinner31a83932017-12-04 13:39:15 +0100446}
447
448
449void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200450Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100451{
452 if (home == NULL) {
453 return;
454 }
455
456 PyMemAllocatorEx old_alloc;
457 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
458
459 PyMem_RawFree(_Py_path_config.home);
460 _Py_path_config.home = _PyMem_RawWcsdup(home);
461
462 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
463
464 if (_Py_path_config.home == NULL) {
465 Py_FatalError("Py_SetPythonHome() failed: out of memory");
466 }
467}
468
469
470void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200471Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100472{
473 if (program_name == NULL || program_name[0] == L'\0') {
474 return;
475 }
476
477 PyMemAllocatorEx old_alloc;
478 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
479
480 PyMem_RawFree(_Py_path_config.program_name);
481 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
482
483 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
484
485 if (_Py_path_config.program_name == NULL) {
486 Py_FatalError("Py_SetProgramName() failed: out of memory");
487 }
488}
489
Steve Dower177a41a2018-11-17 20:41:48 -0800490void
491_Py_SetProgramFullPath(const wchar_t *program_full_path)
492{
493 if (program_full_path == NULL || program_full_path[0] == L'\0') {
494 return;
495 }
496
497 PyMemAllocatorEx old_alloc;
498 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
499
500 PyMem_RawFree(_Py_path_config.program_full_path);
501 _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
502
503 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
504
505 if (_Py_path_config.program_full_path == NULL) {
506 Py_FatalError("_Py_SetProgramFullPath() failed: out of memory");
507 }
508}
509
Victor Stinner31a83932017-12-04 13:39:15 +0100510
511wchar_t *
512Py_GetPath(void)
513{
514 pathconfig_global_init();
515 return _Py_path_config.module_search_path;
516}
517
518
519wchar_t *
520Py_GetPrefix(void)
521{
522 pathconfig_global_init();
523 return _Py_path_config.prefix;
524}
525
526
527wchar_t *
528Py_GetExecPrefix(void)
529{
Victor Stinner31a83932017-12-04 13:39:15 +0100530 pathconfig_global_init();
531 return _Py_path_config.exec_prefix;
Victor Stinner31a83932017-12-04 13:39:15 +0100532}
533
534
535wchar_t *
536Py_GetProgramFullPath(void)
537{
538 pathconfig_global_init();
539 return _Py_path_config.program_full_path;
540}
541
542
543wchar_t*
544Py_GetPythonHome(void)
545{
546 pathconfig_global_init();
547 return _Py_path_config.home;
548}
549
550
551wchar_t *
552Py_GetProgramName(void)
553{
554 pathconfig_global_init();
555 return _Py_path_config.program_name;
556}
557
Victor Stinnerdcf61712019-03-19 16:09:27 +0100558/* Compute module search path from argv[0] or the current working
559 directory ("-m module" case) which will be prepended to sys.argv:
560 sys.path[0].
561
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200562 Return 1 if the path is correctly resolved and written into *path0_p.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100563
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200564 Return 0 if it fails to resolve the full path. For example, return 0 if the
565 current working directory has been removed (bpo-36236) or if argv is empty.
566
567 Raise an exception and return -1 on error.
Victor Stinnerdcf61712019-03-19 16:09:27 +0100568 */
569int
Victor Stinner331a6a52019-05-27 16:39:22 +0200570_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
Victor Stinner11a247d2017-12-13 21:05:57 +0100571{
Victor Stinner331a6a52019-05-27 16:39:22 +0200572 assert(_PyWideStringList_CheckConsistency(argv));
Victor Stinner74f65682019-03-15 15:08:05 +0100573
Victor Stinnerfc96e542019-03-19 18:22:55 +0100574 if (argv->length == 0) {
575 /* Leave sys.path unchanged if sys.argv is empty */
576 return 0;
577 }
578
579 wchar_t *argv0 = argv->items[0];
580 int have_module_arg = (wcscmp(argv0, L"-m") == 0);
581 int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
582
583 wchar_t *path0 = argv0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100584 Py_ssize_t n = 0;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100585
586#ifdef HAVE_REALPATH
Victor Stinner11a247d2017-12-13 21:05:57 +0100587 wchar_t fullpath[MAXPATHLEN];
588#elif defined(MS_WINDOWS)
589 wchar_t fullpath[MAX_PATH];
590#endif
591
Nick Coghland5d9e022018-03-25 23:03:10 +1000592 if (have_module_arg) {
Victor Stinnerdcf61712019-03-19 16:09:27 +0100593#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100594 if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
595 return 0;
596 }
597 path0 = fullpath;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100598#else
Victor Stinnerfc96e542019-03-19 18:22:55 +0100599 path0 = L".";
Victor Stinnerdcf61712019-03-19 16:09:27 +0100600#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100601 n = wcslen(path0);
Nick Coghland5d9e022018-03-25 23:03:10 +1000602 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100603
604#ifdef HAVE_READLINK
Victor Stinnerfc96e542019-03-19 18:22:55 +0100605 wchar_t link[MAXPATHLEN + 1];
606 int nr = 0;
607
608 if (have_script_arg) {
609 nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
610 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100611 if (nr > 0) {
612 /* It's a symlink */
613 link[nr] = '\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100614 if (link[0] == SEP) {
615 path0 = link; /* Link to absolute path */
616 }
617 else if (wcschr(link, SEP) == NULL) {
618 /* Link without path */
619 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100620 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100621 /* Must join(dirname(path0), link) */
622 wchar_t *q = wcsrchr(path0, SEP);
623 if (q == NULL) {
624 /* path0 without path */
625 path0 = link;
626 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100627 else {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100628 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
629 wchar_t path0copy[2 * MAXPATHLEN + 1];
630 wcsncpy(path0copy, path0, MAXPATHLEN);
631 q = wcsrchr(path0copy, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100632 wcsncpy(q+1, link, MAXPATHLEN);
633 q[MAXPATHLEN + 1] = L'\0';
Victor Stinnerfc96e542019-03-19 18:22:55 +0100634 path0 = path0copy;
Victor Stinner11a247d2017-12-13 21:05:57 +0100635 }
636 }
637 }
638#endif /* HAVE_READLINK */
639
Victor Stinnerfc96e542019-03-19 18:22:55 +0100640 wchar_t *p = NULL;
641
Victor Stinner11a247d2017-12-13 21:05:57 +0100642#if SEP == '\\'
643 /* Special case for Microsoft filename syntax */
Nick Coghland5d9e022018-03-25 23:03:10 +1000644 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100645 wchar_t *q;
646#if defined(MS_WINDOWS)
647 /* Replace the first element in argv with the full path. */
648 wchar_t *ptemp;
Victor Stinnerfc96e542019-03-19 18:22:55 +0100649 if (GetFullPathNameW(path0,
Victor Stinner11a247d2017-12-13 21:05:57 +0100650 Py_ARRAY_LENGTH(fullpath),
651 fullpath,
652 &ptemp)) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100653 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100654 }
655#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100656 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100657 /* Test for alternate separator */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100658 q = wcsrchr(p ? p : path0, '/');
Victor Stinner11a247d2017-12-13 21:05:57 +0100659 if (q != NULL)
660 p = q;
661 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100662 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100663 if (n > 1 && p[-1] != ':')
664 n--; /* Drop trailing separator */
665 }
666 }
Victor Stinnerfc96e542019-03-19 18:22:55 +0100667#else
668 /* All other filename syntaxes */
Nick Coghland5d9e022018-03-25 23:03:10 +1000669 if (have_script_arg) {
Victor Stinner11a247d2017-12-13 21:05:57 +0100670#if defined(HAVE_REALPATH)
Victor Stinnerfc96e542019-03-19 18:22:55 +0100671 if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
672 path0 = fullpath;
Victor Stinner11a247d2017-12-13 21:05:57 +0100673 }
674#endif
Victor Stinnerfc96e542019-03-19 18:22:55 +0100675 p = wcsrchr(path0, SEP);
Victor Stinner11a247d2017-12-13 21:05:57 +0100676 }
677 if (p != NULL) {
Victor Stinnerfc96e542019-03-19 18:22:55 +0100678 n = p + 1 - path0;
Victor Stinner11a247d2017-12-13 21:05:57 +0100679#if SEP == '/' /* Special case for Unix filename syntax */
Victor Stinnerfc96e542019-03-19 18:22:55 +0100680 if (n > 1) {
681 /* Drop trailing separator */
682 n--;
683 }
Victor Stinner11a247d2017-12-13 21:05:57 +0100684#endif /* Unix */
685 }
686#endif /* All others */
687
Victor Stinnerdbacfc22019-05-16 16:39:26 +0200688 PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
689 if (path0_obj == NULL) {
690 return -1;
691 }
692
693 *path0_p = path0_obj;
Victor Stinnerdcf61712019-03-19 16:09:27 +0100694 return 1;
Victor Stinner11a247d2017-12-13 21:05:57 +0100695}
696
Victor Stinner9bee3292017-12-21 16:49:13 +0100697
Minmin Gong8ebc6452019-02-02 20:26:55 -0800698#ifdef MS_WINDOWS
699#define WCSTOK wcstok_s
700#else
701#define WCSTOK wcstok
702#endif
703
Victor Stinner9bee3292017-12-21 16:49:13 +0100704/* Search for a prefix value in an environment file (pyvenv.cfg).
705 If found, copy it into the provided buffer. */
706int
707_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
708 wchar_t *value, size_t value_size)
709{
710 int result = 0; /* meaning not found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100711 char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
712 buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100713
714 fseek(env_file, 0, SEEK_SET);
715 while (!feof(env_file)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100716 char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
Victor Stinner9bee3292017-12-21 16:49:13 +0100717
718 if (p == NULL) {
719 break;
720 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100721
722 size_t n = strlen(p);
Victor Stinner9bee3292017-12-21 16:49:13 +0100723 if (p[n - 1] != '\n') {
724 /* line has overflowed - bail */
725 break;
726 }
727 if (p[0] == '#') {
728 /* Comment - skip */
729 continue;
730 }
Victor Stinner05d68a82018-01-18 11:15:25 +0100731
Victor Stinner5f9cf232019-03-19 01:46:25 +0100732 wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100733 if (tmpbuffer) {
Victor Stinner9bee3292017-12-21 16:49:13 +0100734 wchar_t * state;
Minmin Gong8ebc6452019-02-02 20:26:55 -0800735 wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100736 if ((tok != NULL) && !wcscmp(tok, key)) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800737 tok = WCSTOK(NULL, L" \t", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100738 if ((tok != NULL) && !wcscmp(tok, L"=")) {
Minmin Gong8ebc6452019-02-02 20:26:55 -0800739 tok = WCSTOK(NULL, L"\r\n", &state);
Victor Stinner9bee3292017-12-21 16:49:13 +0100740 if (tok != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100741 wcsncpy(value, tok, value_size - 1);
742 value[value_size - 1] = L'\0';
Victor Stinner9bee3292017-12-21 16:49:13 +0100743 result = 1;
744 PyMem_RawFree(tmpbuffer);
745 break;
746 }
747 }
748 }
749 PyMem_RawFree(tmpbuffer);
750 }
751 }
752 return result;
753}
754
Victor Stinner31a83932017-12-04 13:39:15 +0100755#ifdef __cplusplus
756}
757#endif