blob: 53ddfc997da8ac7f526d558f579fb13cc20bf4d1 [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"
5#include "internal/pystate.h"
6
7#ifdef __cplusplus
8extern "C" {
9#endif
10
11
12_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
13
14
15void
16_PyPathConfig_Clear(_PyPathConfig *config)
17{
18 /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
19 since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
20 called before Py_Initialize() which can changes the memory allocator. */
21 PyMemAllocatorEx old_alloc;
22 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
23
24#define CLEAR(ATTR) \
25 do { \
26 PyMem_RawFree(ATTR); \
27 ATTR = NULL; \
28 } while (0)
29
30 CLEAR(config->prefix);
31 CLEAR(config->program_full_path);
32#ifdef MS_WINDOWS
33 CLEAR(config->dll_path);
34#else
35 CLEAR(config->exec_prefix);
36#endif
37 CLEAR(config->module_search_path);
38 CLEAR(config->home);
39 CLEAR(config->program_name);
40#undef CLEAR
41
42 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
43}
44
45
46/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
47 and Py_GetProgramFullPath() */
48_PyInitError
49_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
50{
51 if (_Py_path_config.module_search_path) {
52 /* Already initialized */
53 return _Py_INIT_OK();
54 }
55
56 _PyInitError err;
57 _PyPathConfig new_config = _PyPathConfig_INIT;
58
59 PyMemAllocatorEx old_alloc;
60 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
61
62 /* Calculate program_full_path, prefix, exec_prefix (Unix)
63 or dll_path (Windows), and module_search_path */
64 err = _PyPathConfig_Calculate(&new_config, main_config);
65 if (_Py_INIT_FAILED(err)) {
66 _PyPathConfig_Clear(&new_config);
67 goto done;
68 }
69
70 /* Copy home and program_name from main_config */
71 if (main_config->home != NULL) {
72 new_config.home = _PyMem_RawWcsdup(main_config->home);
73 if (new_config.home == NULL) {
74 err = _Py_INIT_NO_MEMORY();
75 goto done;
76 }
77 }
78 else {
79 new_config.home = NULL;
80 }
81
82 new_config.program_name = _PyMem_RawWcsdup(main_config->program_name);
83 if (new_config.program_name == NULL) {
84 err = _Py_INIT_NO_MEMORY();
85 goto done;
86 }
87
88 _PyPathConfig_Clear(&_Py_path_config);
89 _Py_path_config = new_config;
90
91 err = _Py_INIT_OK();
92
93done:
94 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
95 return err;
96}
97
98
99static void
100pathconfig_global_init(void)
101{
102 if (_Py_path_config.module_search_path) {
103 /* Already initialized */
104 return;
105 }
106
107 _PyInitError err;
108 _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT;
109
110 err = _PyMainInterpreterConfig_ReadEnv(&config);
111 if (_Py_INIT_FAILED(err)) {
112 goto error;
113 }
114
115 err = _PyMainInterpreterConfig_Read(&config);
116 if (_Py_INIT_FAILED(err)) {
117 goto error;
118 }
119
120 err = _PyPathConfig_Init(&config);
121 if (_Py_INIT_FAILED(err)) {
122 goto error;
123 }
124
125 _PyMainInterpreterConfig_Clear(&config);
126 return;
127
128error:
129 _PyMainInterpreterConfig_Clear(&config);
130 _Py_FatalInitError(err);
131}
132
133
134/* External interface */
135
136void
137Py_SetPath(const wchar_t *path)
138{
139 if (path == NULL) {
140 _PyPathConfig_Clear(&_Py_path_config);
141 return;
142 }
143
144 PyMemAllocatorEx old_alloc;
145 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
146
147 _PyPathConfig new_config;
148 new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
149 new_config.prefix = _PyMem_RawWcsdup(L"");
150#ifdef MS_WINDOWS
151 new_config.dll_path = _PyMem_RawWcsdup(L"");
152#else
153 new_config.exec_prefix = _PyMem_RawWcsdup(L"");
154#endif
155 new_config.module_search_path = _PyMem_RawWcsdup(path);
156
157 /* steal the home and program_name values (to leave them unchanged) */
158 new_config.home = _Py_path_config.home;
159 _Py_path_config.home = NULL;
160 new_config.program_name = _Py_path_config.program_name;
161 _Py_path_config.program_name = NULL;
162
163 _PyPathConfig_Clear(&_Py_path_config);
164 _Py_path_config = new_config;
165
166 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
167}
168
169
170void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200171Py_SetPythonHome(const wchar_t *home)
Victor Stinner31a83932017-12-04 13:39:15 +0100172{
173 if (home == NULL) {
174 return;
175 }
176
177 PyMemAllocatorEx old_alloc;
178 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
179
180 PyMem_RawFree(_Py_path_config.home);
181 _Py_path_config.home = _PyMem_RawWcsdup(home);
182
183 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
184
185 if (_Py_path_config.home == NULL) {
186 Py_FatalError("Py_SetPythonHome() failed: out of memory");
187 }
188}
189
190
191void
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200192Py_SetProgramName(const wchar_t *program_name)
Victor Stinner31a83932017-12-04 13:39:15 +0100193{
194 if (program_name == NULL || program_name[0] == L'\0') {
195 return;
196 }
197
198 PyMemAllocatorEx old_alloc;
199 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
200
201 PyMem_RawFree(_Py_path_config.program_name);
202 _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
203
204 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
205
206 if (_Py_path_config.program_name == NULL) {
207 Py_FatalError("Py_SetProgramName() failed: out of memory");
208 }
209}
210
211
212wchar_t *
213Py_GetPath(void)
214{
215 pathconfig_global_init();
216 return _Py_path_config.module_search_path;
217}
218
219
220wchar_t *
221Py_GetPrefix(void)
222{
223 pathconfig_global_init();
224 return _Py_path_config.prefix;
225}
226
227
228wchar_t *
229Py_GetExecPrefix(void)
230{
231#ifdef MS_WINDOWS
232 return Py_GetPrefix();
233#else
234 pathconfig_global_init();
235 return _Py_path_config.exec_prefix;
236#endif
237}
238
239
240wchar_t *
241Py_GetProgramFullPath(void)
242{
243 pathconfig_global_init();
244 return _Py_path_config.program_full_path;
245}
246
247
248wchar_t*
249Py_GetPythonHome(void)
250{
251 pathconfig_global_init();
252 return _Py_path_config.home;
253}
254
255
256wchar_t *
257Py_GetProgramName(void)
258{
259 pathconfig_global_init();
260 return _Py_path_config.program_name;
261}
262
263
264#ifdef __cplusplus
265}
266#endif