blob: af70f3871ccdbbc4b556c57dde4c19858283b0c9 [file] [log] [blame]
Victor Stinner91b9ecf2019-03-01 17:52:56 +01001#include "Python.h"
2#include "pycore_coreconfig.h"
Victor Stinner6dcb5422019-03-05 02:44:12 +01003#include "pycore_getopt.h"
Victor Stinner91b9ecf2019-03-01 17:52:56 +01004
5
6#define DECODE_LOCALE_ERR(NAME, LEN) \
7 (((LEN) == -2) \
8 ? _Py_INIT_USER_ERR("cannot decode " NAME) \
9 : _Py_INIT_NO_MEMORY())
10
11
12/* --- File system encoding/errors -------------------------------- */
13
14/* The filesystem encoding is chosen by config_init_fs_encoding(),
15 see also initfsencoding(). */
16const char *Py_FileSystemDefaultEncoding = NULL;
17int Py_HasFileSystemDefaultEncoding = 0;
18const char *Py_FileSystemDefaultEncodeErrors = NULL;
19int _Py_HasFileSystemDefaultEncodeErrors = 0;
20
21void
22_Py_ClearFileSystemEncoding(void)
23{
24 if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
25 PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
26 Py_FileSystemDefaultEncoding = NULL;
27 }
28 if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
29 PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
30 Py_FileSystemDefaultEncodeErrors = NULL;
31 }
32}
33
34
35/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
36 global configuration variables. */
37int
38_Py_SetFileSystemEncoding(const char *encoding, const char *errors)
39{
40 char *encoding2 = _PyMem_RawStrdup(encoding);
41 if (encoding2 == NULL) {
42 return -1;
43 }
44
45 char *errors2 = _PyMem_RawStrdup(errors);
46 if (errors2 == NULL) {
47 PyMem_RawFree(encoding2);
48 return -1;
49 }
50
51 _Py_ClearFileSystemEncoding();
52
53 Py_FileSystemDefaultEncoding = encoding2;
54 Py_HasFileSystemDefaultEncoding = 0;
55
56 Py_FileSystemDefaultEncodeErrors = errors2;
57 _Py_HasFileSystemDefaultEncodeErrors = 0;
58 return 0;
59}
60
61
62/* --- _PyArgv ---------------------------------------------------- */
63
64_PyInitError
65_PyArgv_Decode(const _PyArgv *args, wchar_t*** argv_p)
66{
67 wchar_t** argv;
68 if (args->use_bytes_argv) {
69 /* +1 for a the NULL terminator */
70 size_t size = sizeof(wchar_t*) * (args->argc + 1);
71 argv = (wchar_t **)PyMem_RawMalloc(size);
72 if (argv == NULL) {
73 return _Py_INIT_NO_MEMORY();
74 }
75
76 for (int i = 0; i < args->argc; i++) {
77 size_t len;
78 wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
79 if (arg == NULL) {
80 _Py_wstrlist_clear(i, argv);
81 return DECODE_LOCALE_ERR("command line arguments",
82 (Py_ssize_t)len);
83 }
84 argv[i] = arg;
85 }
86 argv[args->argc] = NULL;
87 }
88 else {
89 argv = args->wchar_argv;
90 }
91 *argv_p = argv;
92 return _Py_INIT_OK();
93}
Victor Stinnercad1f742019-03-05 02:01:27 +010094
95
Victor Stinner6dcb5422019-03-05 02:44:12 +010096/* --- _PyPreCmdline ------------------------------------------------- */
97
98typedef struct {
99 const _PyArgv *args;
100 int argc;
101 wchar_t **argv;
102} _PyPreCmdline;
103
104
105static void
106precmdline_clear(_PyPreCmdline *cmdline)
107{
108 if (cmdline->args->use_bytes_argv && cmdline->argv != NULL) {
109 _Py_wstrlist_clear(cmdline->args->argc, cmdline->argv);
110 }
111 cmdline->argv = NULL;
112}
113
114
Victor Stinnercad1f742019-03-05 02:01:27 +0100115/* --- _PyPreConfig ----------------------------------------------- */
116
117void
118_PyPreConfig_Clear(_PyPreConfig *config)
119{
120}
121
122
123int
124_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
125{
126 _PyPreConfig_Clear(config);
127
128#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
129
130 COPY_ATTR(isolated);
131 COPY_ATTR(use_environment);
132
133#undef COPY_ATTR
134 return 0;
135}
136
137
138void
139_PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
140{
141#define COPY_FLAG(ATTR, VALUE) \
142 if (config->ATTR == -1) { \
143 config->ATTR = VALUE; \
144 }
145#define COPY_NOT_FLAG(ATTR, VALUE) \
146 if (config->ATTR == -1) { \
147 config->ATTR = !(VALUE); \
148 }
149
150 COPY_FLAG(isolated, Py_IsolatedFlag);
151 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
152
153#undef COPY_FLAG
154#undef COPY_NOT_FLAG
155}
156
157
158void
159_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
160{
161#define COPY_FLAG(ATTR, VAR) \
162 if (config->ATTR != -1) { \
163 VAR = config->ATTR; \
164 }
165#define COPY_NOT_FLAG(ATTR, VAR) \
166 if (config->ATTR != -1) { \
167 VAR = !config->ATTR; \
168 }
169
170 COPY_FLAG(isolated, Py_IsolatedFlag);
171 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
172
173#undef COPY_FLAG
174#undef COPY_NOT_FLAG
175}
176
177
178_PyInitError
179_PyPreConfig_Read(_PyPreConfig *config)
180{
181 _PyPreConfig_GetGlobalConfig(config);
182
183 if (config->isolated > 0) {
184 config->use_environment = 0;
185 }
186
187 /* Default values */
188 if (config->use_environment < 0) {
189 config->use_environment = 0;
190 }
191
Victor Stinner6dcb5422019-03-05 02:44:12 +0100192 assert(config->isolated >= 0);
Victor Stinnercad1f742019-03-05 02:01:27 +0100193 assert(config->use_environment >= 0);
194
195 return _Py_INIT_OK();
196}
197
198
199int
200_PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict)
201{
202#define SET_ITEM(KEY, EXPR) \
203 do { \
204 PyObject *obj = (EXPR); \
205 if (obj == NULL) { \
206 goto fail; \
207 } \
208 int res = PyDict_SetItemString(dict, (KEY), obj); \
209 Py_DECREF(obj); \
210 if (res < 0) { \
211 goto fail; \
212 } \
213 } while (0)
214#define SET_ITEM_INT(ATTR) \
215 SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
216
217 SET_ITEM_INT(isolated);
218 SET_ITEM_INT(use_environment);
219 return 0;
220
221fail:
222 return -1;
223
224#undef SET_ITEM
225#undef SET_ITEM_INT
226}
Victor Stinner6dcb5422019-03-05 02:44:12 +0100227
228
229/* Parse the command line arguments */
230static _PyInitError
231preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline)
232{
233 _PyOS_ResetGetOpt();
234 /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv()
235 is responsible for that */
236 _PyOS_opterr = 0;
237 do {
238 int longindex = -1;
239 int c = _PyOS_GetOpt(cmdline->args->argc, cmdline->argv, &longindex);
240
241 if (c == EOF || c == 'c' || c == 'm') {
242 break;
243 }
244
245 switch (c) {
246 case 'E':
247 config->use_environment = 0;
248 break;
249
250 case 'I':
251 config->isolated++;
252 break;
253
254 default:
255 /* ignore other argument:
256 handled by _PyCoreConfig_ReadFromArgv() */
257 break;
258 }
259 } while (1);
260
261 return _Py_INIT_OK();
262}
263
264
265_PyInitError
266_PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
267{
268 _PyInitError err;
269
270 _PyPreCmdline cmdline;
271 memset(&cmdline, 0, sizeof(cmdline));
272 cmdline.args = args;
273
274 err = _PyArgv_Decode(cmdline.args, &cmdline.argv);
275 if (_Py_INIT_FAILED(err)) {
276 goto done;
277 }
278
279 err = preconfig_parse_cmdline(config, &cmdline);
280 if (_Py_INIT_FAILED(err)) {
281 goto done;
282 }
283
284 err = _PyPreConfig_Read(config);
285 if (_Py_INIT_FAILED(err)) {
286 goto done;
287 }
288 err = _Py_INIT_OK();
289
290done:
291 precmdline_clear(&cmdline);
292 return err;
293}
294
295
296void
297_PyPreConfig_Write(const _PyPreConfig *config)
298{
299}