1 #include "Python.h"
2 #include "pycore_fileutils.h" // _Py_HasFileSystemDefaultEncodeErrors
3 #include "pycore_getopt.h" // _PyOS_GetOpt()
4 #include "pycore_initconfig.h" // _PyStatus_OK()
5 #include "pycore_interp.h" // _PyInterpreterState.runtime
6 #include "pycore_pathconfig.h" // _Py_path_config
7 #include "pycore_pyerrors.h" // _PyErr_Fetch()
8 #include "pycore_pylifecycle.h" // _Py_PreInitializeFromConfig()
9 #include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
10 #include "pycore_pystate.h" // _PyThreadState_GET()
11
12 #include "osdefs.h" // DELIM
13 #include <locale.h> // setlocale()
14 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
15 # ifdef HAVE_IO_H
16 # include <io.h>
17 # endif
18 # ifdef HAVE_FCNTL_H
19 # include <fcntl.h> // O_BINARY
20 # endif
21 #endif
22
23 #ifndef PLATLIBDIR
24 # error "PLATLIBDIR macro must be defined"
25 #endif
26
27
28 /* --- Command line options --------------------------------------- */
29
30 /* Short usage message (with %s for argv0) */
31 static const char usage_line[] =
32 "usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
33
34 /* Long usage message, split into parts < 512 bytes */
35 static const char usage_1[] = "\
36 Options and arguments (and corresponding environment variables):\n\
37 -b : issue warnings about str(bytes_instance), str(bytearray_instance)\n\
38 and comparing bytes/bytearray with str. (-bb: issue errors)\n\
39 -B : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x\n\
40 -c cmd : program passed in as string (terminates option list)\n\
41 -d : turn on parser debugging output (for experts only, only works on\n\
42 debug builds); also PYTHONDEBUG=x\n\
43 -E : ignore PYTHON* environment variables (such as PYTHONPATH)\n\
44 -h : print this help message and exit (also --help)\n\
45 ";
46 static const char usage_2[] = "\
47 -i : inspect interactively after running script; forces a prompt even\n\
48 if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\
49 -I : isolate Python from the user's environment (implies -E and -s)\n\
50 -m mod : run library module as a script (terminates option list)\n\
51 -O : remove assert and __debug__-dependent statements; add .opt-1 before\n\
52 .pyc extension; also PYTHONOPTIMIZE=x\n\
53 -OO : do -O changes and also discard docstrings; add .opt-2 before\n\
54 .pyc extension\n\
55 -q : don't print version and copyright messages on interactive startup\n\
56 -s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\
57 -S : don't imply 'import site' on initialization\n\
58 ";
59 static const char usage_3[] = "\
60 -u : force the stdout and stderr streams to be unbuffered;\n\
61 this option has no effect on stdin; also PYTHONUNBUFFERED=x\n\
62 -v : verbose (trace import statements); also PYTHONVERBOSE=x\n\
63 can be supplied multiple times to increase verbosity\n\
64 -V : print the Python version number and exit (also --version)\n\
65 when given twice, print more information about the build\n\
66 -W arg : warning control; arg is action:message:category:module:lineno\n\
67 also PYTHONWARNINGS=arg\n\
68 -x : skip first line of source, allowing use of non-Unix forms of #!cmd\n\
69 -X opt : set implementation-specific option. The following options are available:\n\
70 \n\
71 -X faulthandler: enable faulthandler\n\
72 -X showrefcount: output the total reference count and number of used\n\
73 memory blocks when the program finishes or after each statement in the\n\
74 interactive interpreter. This only works on debug builds\n\
75 -X tracemalloc: start tracing Python memory allocations using the\n\
76 tracemalloc module. By default, only the most recent frame is stored in a\n\
77 traceback of a trace. Use -X tracemalloc=NFRAME to start tracing with a\n\
78 traceback limit of NFRAME frames\n\
79 -X importtime: show how long each import takes. It shows module name,\n\
80 cumulative time (including nested imports) and self time (excluding\n\
81 nested imports). Note that its output may be broken in multi-threaded\n\
82 application. Typical usage is python3 -X importtime -c 'import asyncio'\n\
83 -X dev: enable CPython's \"development mode\", introducing additional runtime\n\
84 checks which are too expensive to be enabled by default. Effect of the\n\
85 developer mode:\n\
86 * Add default warning filter, as -W default\n\
87 * Install debug hooks on memory allocators: see the PyMem_SetupDebugHooks() C function\n\
88 * Enable the faulthandler module to dump the Python traceback on a crash\n\
89 * Enable asyncio debug mode\n\
90 * Set the dev_mode attribute of sys.flags to True\n\
91 * io.IOBase destructor logs close() exceptions\n\
92 -X utf8: enable UTF-8 mode for operating system interfaces, overriding the default\n\
93 locale-aware mode. -X utf8=0 explicitly disables UTF-8 mode (even when it would\n\
94 otherwise activate automatically)\n\
95 -X pycache_prefix=PATH: enable writing .pyc files to a parallel tree rooted at the\n\
96 given directory instead of to the code tree\n\
97 -X warn_default_encoding: enable opt-in EncodingWarning for 'encoding=None'\n\
98 \n\
99 --check-hash-based-pycs always|default|never:\n\
100 control how Python invalidates hash-based .pyc files\n\
101 ";
102 static const char usage_4[] = "\
103 file : program read from script file\n\
104 - : program read from stdin (default; interactive mode if a tty)\n\
105 arg ...: arguments passed to program in sys.argv[1:]\n\n\
106 Other environment variables:\n\
107 PYTHONSTARTUP: file executed on interactive startup (no default)\n\
108 PYTHONPATH : '%lc'-separated list of directories prefixed to the\n\
109 default module search path. The result is sys.path.\n\
110 ";
111 static const char usage_5[] =
112 "PYTHONHOME : alternate <prefix> directory (or <prefix>%lc<exec_prefix>).\n"
113 " The default module search path uses %s.\n"
114 "PYTHONPLATLIBDIR : override sys.platlibdir.\n"
115 "PYTHONCASEOK : ignore case in 'import' statements (Windows).\n"
116 "PYTHONUTF8: if set to 1, enable the UTF-8 mode.\n"
117 "PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n"
118 "PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.\n";
119 static const char usage_6[] =
120 "PYTHONHASHSEED: if this variable is set to 'random', a random value is used\n"
121 " to seed the hashes of str and bytes objects. It can also be set to an\n"
122 " integer in the range [0,4294967295] to get hash values with a\n"
123 " predictable seed.\n"
124 "PYTHONMALLOC: set the Python memory allocators and/or install debug hooks\n"
125 " on Python memory allocators. Use PYTHONMALLOC=debug to install debug\n"
126 " hooks.\n"
127 "PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale\n"
128 " coercion behavior. Use PYTHONCOERCECLOCALE=warn to request display of\n"
129 " locale coercion and locale compatibility warnings on stderr.\n"
130 "PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\n"
131 " debugger. It can be set to the callable of your debugger of choice.\n"
132 "PYTHONDEVMODE: enable the development mode.\n"
133 "PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.\n"
134 "PYTHONWARNDEFAULTENCODING: enable opt-in EncodingWarning for 'encoding=None'.\n";
135
136 #if defined(MS_WINDOWS)
137 # define PYTHONHOMEHELP "<prefix>\\python{major}{minor}"
138 #else
139 # define PYTHONHOMEHELP "<prefix>/lib/pythonX.X"
140 #endif
141
142
143 /* --- Global configuration variables ----------------------------- */
144
145 /* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change
146 stdin and stdout error handler to "surrogateescape". */
147 int Py_UTF8Mode = 0;
148 int Py_DebugFlag = 0; /* Needed by parser.c */
149 int Py_VerboseFlag = 0; /* Needed by import.c */
150 int Py_QuietFlag = 0; /* Needed by sysmodule.c */
151 int Py_InteractiveFlag = 0; /* Needed by Py_FdIsInteractive() below */
152 int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */
153 int Py_OptimizeFlag = 0; /* Needed by compile.c */
154 int Py_NoSiteFlag = 0; /* Suppress 'import site' */
155 int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */
156 int Py_FrozenFlag = 0; /* Needed by getpath.c */
157 int Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */
158 int Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */
159 int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
160 int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
161 int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
162 int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
163 #ifdef MS_WINDOWS
164 int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */
165 int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */
166 #endif
167
168
169 static PyObject *
_Py_GetGlobalVariablesAsDict(void)170 _Py_GetGlobalVariablesAsDict(void)
171 {
172 PyObject *dict, *obj;
173
174 dict = PyDict_New();
175 if (dict == NULL) {
176 return NULL;
177 }
178
179 #define SET_ITEM(KEY, EXPR) \
180 do { \
181 obj = (EXPR); \
182 if (obj == NULL) { \
183 return NULL; \
184 } \
185 int res = PyDict_SetItemString(dict, (KEY), obj); \
186 Py_DECREF(obj); \
187 if (res < 0) { \
188 goto fail; \
189 } \
190 } while (0)
191 #define SET_ITEM_INT(VAR) \
192 SET_ITEM(#VAR, PyLong_FromLong(VAR))
193 #define FROM_STRING(STR) \
194 ((STR != NULL) ? \
195 PyUnicode_FromString(STR) \
196 : (Py_INCREF(Py_None), Py_None))
197 #define SET_ITEM_STR(VAR) \
198 SET_ITEM(#VAR, FROM_STRING(VAR))
199
200 SET_ITEM_STR(Py_FileSystemDefaultEncoding);
201 SET_ITEM_INT(Py_HasFileSystemDefaultEncoding);
202 SET_ITEM_STR(Py_FileSystemDefaultEncodeErrors);
203 SET_ITEM_INT(_Py_HasFileSystemDefaultEncodeErrors);
204
205 SET_ITEM_INT(Py_UTF8Mode);
206 SET_ITEM_INT(Py_DebugFlag);
207 SET_ITEM_INT(Py_VerboseFlag);
208 SET_ITEM_INT(Py_QuietFlag);
209 SET_ITEM_INT(Py_InteractiveFlag);
210 SET_ITEM_INT(Py_InspectFlag);
211
212 SET_ITEM_INT(Py_OptimizeFlag);
213 SET_ITEM_INT(Py_NoSiteFlag);
214 SET_ITEM_INT(Py_BytesWarningFlag);
215 SET_ITEM_INT(Py_FrozenFlag);
216 SET_ITEM_INT(Py_IgnoreEnvironmentFlag);
217 SET_ITEM_INT(Py_DontWriteBytecodeFlag);
218 SET_ITEM_INT(Py_NoUserSiteDirectory);
219 SET_ITEM_INT(Py_UnbufferedStdioFlag);
220 SET_ITEM_INT(Py_HashRandomizationFlag);
221 SET_ITEM_INT(Py_IsolatedFlag);
222
223 #ifdef MS_WINDOWS
224 SET_ITEM_INT(Py_LegacyWindowsFSEncodingFlag);
225 SET_ITEM_INT(Py_LegacyWindowsStdioFlag);
226 #endif
227
228 return dict;
229
230 fail:
231 Py_DECREF(dict);
232 return NULL;
233
234 #undef FROM_STRING
235 #undef SET_ITEM
236 #undef SET_ITEM_INT
237 #undef SET_ITEM_STR
238 }
239
240
241 /* --- PyStatus ----------------------------------------------- */
242
PyStatus_Ok(void)243 PyStatus PyStatus_Ok(void)
244 { return _PyStatus_OK(); }
245
PyStatus_Error(const char * err_msg)246 PyStatus PyStatus_Error(const char *err_msg)
247 {
248 assert(err_msg != NULL);
249 return (PyStatus){._type = _PyStatus_TYPE_ERROR,
250 .err_msg = err_msg};
251 }
252
PyStatus_NoMemory(void)253 PyStatus PyStatus_NoMemory(void)
254 { return PyStatus_Error("memory allocation failed"); }
255
PyStatus_Exit(int exitcode)256 PyStatus PyStatus_Exit(int exitcode)
257 { return _PyStatus_EXIT(exitcode); }
258
259
PyStatus_IsError(PyStatus status)260 int PyStatus_IsError(PyStatus status)
261 { return _PyStatus_IS_ERROR(status); }
262
PyStatus_IsExit(PyStatus status)263 int PyStatus_IsExit(PyStatus status)
264 { return _PyStatus_IS_EXIT(status); }
265
PyStatus_Exception(PyStatus status)266 int PyStatus_Exception(PyStatus status)
267 { return _PyStatus_EXCEPTION(status); }
268
269 PyObject*
_PyErr_SetFromPyStatus(PyStatus status)270 _PyErr_SetFromPyStatus(PyStatus status)
271 {
272 if (!_PyStatus_IS_ERROR(status)) {
273 PyErr_Format(PyExc_SystemError,
274 "%s() expects an error PyStatus",
275 _PyStatus_GET_FUNC());
276 }
277 else if (status.func) {
278 PyErr_Format(PyExc_ValueError, "%s: %s", status.func, status.err_msg);
279 }
280 else {
281 PyErr_Format(PyExc_ValueError, "%s", status.err_msg);
282 }
283 return NULL;
284 }
285
286
287 /* --- PyWideStringList ------------------------------------------------ */
288
289 #ifndef NDEBUG
290 int
_PyWideStringList_CheckConsistency(const PyWideStringList * list)291 _PyWideStringList_CheckConsistency(const PyWideStringList *list)
292 {
293 assert(list->length >= 0);
294 if (list->length != 0) {
295 assert(list->items != NULL);
296 }
297 for (Py_ssize_t i = 0; i < list->length; i++) {
298 assert(list->items[i] != NULL);
299 }
300 return 1;
301 }
302 #endif /* Py_DEBUG */
303
304
305 void
_PyWideStringList_Clear(PyWideStringList * list)306 _PyWideStringList_Clear(PyWideStringList *list)
307 {
308 assert(_PyWideStringList_CheckConsistency(list));
309 for (Py_ssize_t i=0; i < list->length; i++) {
310 PyMem_RawFree(list->items[i]);
311 }
312 PyMem_RawFree(list->items);
313 list->length = 0;
314 list->items = NULL;
315 }
316
317
318 int
_PyWideStringList_Copy(PyWideStringList * list,const PyWideStringList * list2)319 _PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2)
320 {
321 assert(_PyWideStringList_CheckConsistency(list));
322 assert(_PyWideStringList_CheckConsistency(list2));
323
324 if (list2->length == 0) {
325 _PyWideStringList_Clear(list);
326 return 0;
327 }
328
329 PyWideStringList copy = _PyWideStringList_INIT;
330
331 size_t size = list2->length * sizeof(list2->items[0]);
332 copy.items = PyMem_RawMalloc(size);
333 if (copy.items == NULL) {
334 return -1;
335 }
336
337 for (Py_ssize_t i=0; i < list2->length; i++) {
338 wchar_t *item = _PyMem_RawWcsdup(list2->items[i]);
339 if (item == NULL) {
340 _PyWideStringList_Clear(©);
341 return -1;
342 }
343 copy.items[i] = item;
344 copy.length = i + 1;
345 }
346
347 _PyWideStringList_Clear(list);
348 *list = copy;
349 return 0;
350 }
351
352
353 PyStatus
PyWideStringList_Insert(PyWideStringList * list,Py_ssize_t index,const wchar_t * item)354 PyWideStringList_Insert(PyWideStringList *list,
355 Py_ssize_t index, const wchar_t *item)
356 {
357 Py_ssize_t len = list->length;
358 if (len == PY_SSIZE_T_MAX) {
359 /* length+1 would overflow */
360 return _PyStatus_NO_MEMORY();
361 }
362 if (index < 0) {
363 return _PyStatus_ERR("PyWideStringList_Insert index must be >= 0");
364 }
365 if (index > len) {
366 index = len;
367 }
368
369 wchar_t *item2 = _PyMem_RawWcsdup(item);
370 if (item2 == NULL) {
371 return _PyStatus_NO_MEMORY();
372 }
373
374 size_t size = (len + 1) * sizeof(list->items[0]);
375 wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size);
376 if (items2 == NULL) {
377 PyMem_RawFree(item2);
378 return _PyStatus_NO_MEMORY();
379 }
380
381 if (index < len) {
382 memmove(&items2[index + 1],
383 &items2[index],
384 (len - index) * sizeof(items2[0]));
385 }
386
387 items2[index] = item2;
388 list->items = items2;
389 list->length++;
390 return _PyStatus_OK();
391 }
392
393
394 PyStatus
PyWideStringList_Append(PyWideStringList * list,const wchar_t * item)395 PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
396 {
397 return PyWideStringList_Insert(list, list->length, item);
398 }
399
400
401 PyStatus
_PyWideStringList_Extend(PyWideStringList * list,const PyWideStringList * list2)402 _PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2)
403 {
404 for (Py_ssize_t i = 0; i < list2->length; i++) {
405 PyStatus status = PyWideStringList_Append(list, list2->items[i]);
406 if (_PyStatus_EXCEPTION(status)) {
407 return status;
408 }
409 }
410 return _PyStatus_OK();
411 }
412
413
414 static int
_PyWideStringList_Find(PyWideStringList * list,const wchar_t * item)415 _PyWideStringList_Find(PyWideStringList *list, const wchar_t *item)
416 {
417 for (Py_ssize_t i = 0; i < list->length; i++) {
418 if (wcscmp(list->items[i], item) == 0) {
419 return 1;
420 }
421 }
422 return 0;
423 }
424
425
426 PyObject*
_PyWideStringList_AsList(const PyWideStringList * list)427 _PyWideStringList_AsList(const PyWideStringList *list)
428 {
429 assert(_PyWideStringList_CheckConsistency(list));
430
431 PyObject *pylist = PyList_New(list->length);
432 if (pylist == NULL) {
433 return NULL;
434 }
435
436 for (Py_ssize_t i = 0; i < list->length; i++) {
437 PyObject *item = PyUnicode_FromWideChar(list->items[i], -1);
438 if (item == NULL) {
439 Py_DECREF(pylist);
440 return NULL;
441 }
442 PyList_SET_ITEM(pylist, i, item);
443 }
444 return pylist;
445 }
446
447
448 /* --- Py_SetStandardStreamEncoding() ----------------------------- */
449
450 /* Helper to allow an embedding application to override the normal
451 * mechanism that attempts to figure out an appropriate IO encoding
452 */
453
454 static char *_Py_StandardStreamEncoding = NULL;
455 static char *_Py_StandardStreamErrors = NULL;
456
457 int
Py_SetStandardStreamEncoding(const char * encoding,const char * errors)458 Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
459 {
460 if (Py_IsInitialized()) {
461 /* This is too late to have any effect */
462 return -1;
463 }
464
465 int res = 0;
466
467 /* Py_SetStandardStreamEncoding() can be called before Py_Initialize(),
468 but Py_Initialize() can change the allocator. Use a known allocator
469 to be able to release the memory later. */
470 PyMemAllocatorEx old_alloc;
471 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
472
473 /* Can't call PyErr_NoMemory() on errors, as Python hasn't been
474 * initialised yet.
475 *
476 * However, the raw memory allocators are initialised appropriately
477 * as C static variables, so _PyMem_RawStrdup is OK even though
478 * Py_Initialize hasn't been called yet.
479 */
480 if (encoding) {
481 PyMem_RawFree(_Py_StandardStreamEncoding);
482 _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
483 if (!_Py_StandardStreamEncoding) {
484 res = -2;
485 goto done;
486 }
487 }
488 if (errors) {
489 PyMem_RawFree(_Py_StandardStreamErrors);
490 _Py_StandardStreamErrors = _PyMem_RawStrdup(errors);
491 if (!_Py_StandardStreamErrors) {
492 PyMem_RawFree(_Py_StandardStreamEncoding);
493 _Py_StandardStreamEncoding = NULL;
494 res = -3;
495 goto done;
496 }
497 }
498 #ifdef MS_WINDOWS
499 if (_Py_StandardStreamEncoding) {
500 /* Overriding the stream encoding implies legacy streams */
501 Py_LegacyWindowsStdioFlag = 1;
502 }
503 #endif
504
505 done:
506 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
507
508 return res;
509 }
510
511
512 void
_Py_ClearStandardStreamEncoding(void)513 _Py_ClearStandardStreamEncoding(void)
514 {
515 /* Use the same allocator than Py_SetStandardStreamEncoding() */
516 PyMemAllocatorEx old_alloc;
517 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
518
519 /* We won't need them anymore. */
520 if (_Py_StandardStreamEncoding) {
521 PyMem_RawFree(_Py_StandardStreamEncoding);
522 _Py_StandardStreamEncoding = NULL;
523 }
524 if (_Py_StandardStreamErrors) {
525 PyMem_RawFree(_Py_StandardStreamErrors);
526 _Py_StandardStreamErrors = NULL;
527 }
528
529 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
530 }
531
532
533 /* --- Py_GetArgcArgv() ------------------------------------------- */
534
535 /* For Py_GetArgcArgv(); set by _Py_SetArgcArgv() */
536 static PyWideStringList orig_argv = {.length = 0, .items = NULL};
537
538
539 void
_Py_ClearArgcArgv(void)540 _Py_ClearArgcArgv(void)
541 {
542 PyMemAllocatorEx old_alloc;
543 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
544
545 _PyWideStringList_Clear(&orig_argv);
546
547 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
548 }
549
550
551 static int
_Py_SetArgcArgv(Py_ssize_t argc,wchar_t * const * argv)552 _Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv)
553 {
554 const PyWideStringList argv_list = {.length = argc, .items = (wchar_t **)argv};
555 int res;
556
557 PyMemAllocatorEx old_alloc;
558 _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
559
560 res = _PyWideStringList_Copy(&orig_argv, &argv_list);
561
562 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
563 return res;
564 }
565
566
567 // _PyConfig_Write() calls _Py_SetArgcArgv() with PyConfig.orig_argv.
568 void
Py_GetArgcArgv(int * argc,wchar_t *** argv)569 Py_GetArgcArgv(int *argc, wchar_t ***argv)
570 {
571 *argc = (int)orig_argv.length;
572 *argv = orig_argv.items;
573 }
574
575
576 /* --- PyConfig ---------------------------------------------- */
577
578 #define DECODE_LOCALE_ERR(NAME, LEN) \
579 (((LEN) == -2) \
580 ? _PyStatus_ERR("cannot decode " NAME) \
581 : _PyStatus_NO_MEMORY())
582
583 #define MAX_HASH_SEED 4294967295UL
584
585
586 #ifndef NDEBUG
587 static int
config_check_consistency(const PyConfig * config)588 config_check_consistency(const PyConfig *config)
589 {
590 /* Check config consistency */
591 assert(config->isolated >= 0);
592 assert(config->use_environment >= 0);
593 assert(config->dev_mode >= 0);
594 assert(config->install_signal_handlers >= 0);
595 assert(config->use_hash_seed >= 0);
596 assert(config->hash_seed <= MAX_HASH_SEED);
597 assert(config->faulthandler >= 0);
598 assert(config->tracemalloc >= 0);
599 assert(config->import_time >= 0);
600 assert(config->show_ref_count >= 0);
601 assert(config->dump_refs >= 0);
602 assert(config->malloc_stats >= 0);
603 assert(config->site_import >= 0);
604 assert(config->bytes_warning >= 0);
605 assert(config->warn_default_encoding >= 0);
606 assert(config->inspect >= 0);
607 assert(config->interactive >= 0);
608 assert(config->optimization_level >= 0);
609 assert(config->parser_debug >= 0);
610 assert(config->write_bytecode >= 0);
611 assert(config->verbose >= 0);
612 assert(config->quiet >= 0);
613 assert(config->user_site_directory >= 0);
614 assert(config->parse_argv >= 0);
615 assert(config->configure_c_stdio >= 0);
616 assert(config->buffered_stdio >= 0);
617 assert(config->program_name != NULL);
618 assert(_PyWideStringList_CheckConsistency(&config->orig_argv));
619 assert(_PyWideStringList_CheckConsistency(&config->argv));
620 /* sys.argv must be non-empty: empty argv is replaced with [''] */
621 assert(config->argv.length >= 1);
622 assert(_PyWideStringList_CheckConsistency(&config->xoptions));
623 assert(_PyWideStringList_CheckConsistency(&config->warnoptions));
624 assert(_PyWideStringList_CheckConsistency(&config->module_search_paths));
625 assert(config->module_search_paths_set >= 0);
626 assert(config->platlibdir != NULL);
627 assert(config->filesystem_encoding != NULL);
628 assert(config->filesystem_errors != NULL);
629 assert(config->stdio_encoding != NULL);
630 assert(config->stdio_errors != NULL);
631 #ifdef MS_WINDOWS
632 assert(config->legacy_windows_stdio >= 0);
633 #endif
634 /* -c and -m options are exclusive */
635 assert(!(config->run_command != NULL && config->run_module != NULL));
636 assert(config->check_hash_pycs_mode != NULL);
637 assert(config->_install_importlib >= 0);
638 assert(config->pathconfig_warnings >= 0);
639 return 1;
640 }
641 #endif
642
643
644 /* Free memory allocated in config, but don't clear all attributes */
645 void
PyConfig_Clear(PyConfig * config)646 PyConfig_Clear(PyConfig *config)
647 {
648 #define CLEAR(ATTR) \
649 do { \
650 PyMem_RawFree(ATTR); \
651 ATTR = NULL; \
652 } while (0)
653
654 CLEAR(config->pycache_prefix);
655 CLEAR(config->pythonpath_env);
656 CLEAR(config->home);
657 CLEAR(config->program_name);
658
659 _PyWideStringList_Clear(&config->argv);
660 _PyWideStringList_Clear(&config->warnoptions);
661 _PyWideStringList_Clear(&config->xoptions);
662 _PyWideStringList_Clear(&config->module_search_paths);
663 config->module_search_paths_set = 0;
664
665 CLEAR(config->executable);
666 CLEAR(config->base_executable);
667 CLEAR(config->prefix);
668 CLEAR(config->base_prefix);
669 CLEAR(config->exec_prefix);
670 CLEAR(config->base_exec_prefix);
671 CLEAR(config->platlibdir);
672
673 CLEAR(config->filesystem_encoding);
674 CLEAR(config->filesystem_errors);
675 CLEAR(config->stdio_encoding);
676 CLEAR(config->stdio_errors);
677 CLEAR(config->run_command);
678 CLEAR(config->run_module);
679 CLEAR(config->run_filename);
680 CLEAR(config->check_hash_pycs_mode);
681
682 _PyWideStringList_Clear(&config->orig_argv);
683 #undef CLEAR
684 }
685
686
687 void
_PyConfig_InitCompatConfig(PyConfig * config)688 _PyConfig_InitCompatConfig(PyConfig *config)
689 {
690 memset(config, 0, sizeof(*config));
691
692 config->_config_init = (int)_PyConfig_INIT_COMPAT;
693 config->isolated = -1;
694 config->use_environment = -1;
695 config->dev_mode = -1;
696 config->install_signal_handlers = 1;
697 config->use_hash_seed = -1;
698 config->faulthandler = -1;
699 config->tracemalloc = -1;
700 config->module_search_paths_set = 0;
701 config->parse_argv = 0;
702 config->site_import = -1;
703 config->bytes_warning = -1;
704 config->warn_default_encoding = 0;
705 config->inspect = -1;
706 config->interactive = -1;
707 config->optimization_level = -1;
708 config->parser_debug= -1;
709 config->write_bytecode = -1;
710 config->verbose = -1;
711 config->quiet = -1;
712 config->user_site_directory = -1;
713 config->configure_c_stdio = 0;
714 config->buffered_stdio = -1;
715 config->_install_importlib = 1;
716 config->check_hash_pycs_mode = NULL;
717 config->pathconfig_warnings = -1;
718 config->_init_main = 1;
719 config->_isolated_interpreter = 0;
720 #ifdef MS_WINDOWS
721 config->legacy_windows_stdio = -1;
722 #endif
723 }
724
725
726 static void
config_init_defaults(PyConfig * config)727 config_init_defaults(PyConfig *config)
728 {
729 _PyConfig_InitCompatConfig(config);
730
731 config->isolated = 0;
732 config->use_environment = 1;
733 config->site_import = 1;
734 config->bytes_warning = 0;
735 config->inspect = 0;
736 config->interactive = 0;
737 config->optimization_level = 0;
738 config->parser_debug= 0;
739 config->write_bytecode = 1;
740 config->verbose = 0;
741 config->quiet = 0;
742 config->user_site_directory = 1;
743 config->buffered_stdio = 1;
744 config->pathconfig_warnings = 1;
745 #ifdef MS_WINDOWS
746 config->legacy_windows_stdio = 0;
747 #endif
748 }
749
750
751 void
PyConfig_InitPythonConfig(PyConfig * config)752 PyConfig_InitPythonConfig(PyConfig *config)
753 {
754 config_init_defaults(config);
755
756 config->_config_init = (int)_PyConfig_INIT_PYTHON;
757 config->configure_c_stdio = 1;
758 config->parse_argv = 1;
759 }
760
761
762 void
PyConfig_InitIsolatedConfig(PyConfig * config)763 PyConfig_InitIsolatedConfig(PyConfig *config)
764 {
765 config_init_defaults(config);
766
767 config->_config_init = (int)_PyConfig_INIT_ISOLATED;
768 config->isolated = 1;
769 config->use_environment = 0;
770 config->user_site_directory = 0;
771 config->dev_mode = 0;
772 config->install_signal_handlers = 0;
773 config->use_hash_seed = 0;
774 config->faulthandler = 0;
775 config->tracemalloc = 0;
776 config->pathconfig_warnings = 0;
777 #ifdef MS_WINDOWS
778 config->legacy_windows_stdio = 0;
779 #endif
780 }
781
782
783 /* Copy str into *config_str (duplicate the string) */
784 PyStatus
PyConfig_SetString(PyConfig * config,wchar_t ** config_str,const wchar_t * str)785 PyConfig_SetString(PyConfig *config, wchar_t **config_str, const wchar_t *str)
786 {
787 PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
788 if (_PyStatus_EXCEPTION(status)) {
789 return status;
790 }
791
792 wchar_t *str2;
793 if (str != NULL) {
794 str2 = _PyMem_RawWcsdup(str);
795 if (str2 == NULL) {
796 return _PyStatus_NO_MEMORY();
797 }
798 }
799 else {
800 str2 = NULL;
801 }
802 PyMem_RawFree(*config_str);
803 *config_str = str2;
804 return _PyStatus_OK();
805 }
806
807
808 static PyStatus
config_set_bytes_string(PyConfig * config,wchar_t ** config_str,const char * str,const char * decode_err_msg)809 config_set_bytes_string(PyConfig *config, wchar_t **config_str,
810 const char *str, const char *decode_err_msg)
811 {
812 PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
813 if (_PyStatus_EXCEPTION(status)) {
814 return status;
815 }
816
817 wchar_t *str2;
818 if (str != NULL) {
819 size_t len;
820 str2 = Py_DecodeLocale(str, &len);
821 if (str2 == NULL) {
822 if (len == (size_t)-2) {
823 return _PyStatus_ERR(decode_err_msg);
824 }
825 else {
826 return _PyStatus_NO_MEMORY();
827 }
828 }
829 }
830 else {
831 str2 = NULL;
832 }
833 PyMem_RawFree(*config_str);
834 *config_str = str2;
835 return _PyStatus_OK();
836 }
837
838
839 #define CONFIG_SET_BYTES_STR(config, config_str, str, NAME) \
840 config_set_bytes_string(config, config_str, str, "cannot decode " NAME)
841
842
843 /* Decode str using Py_DecodeLocale() and set the result into *config_str.
844 Pre-initialize Python if needed to ensure that encodings are properly
845 configured. */
846 PyStatus
PyConfig_SetBytesString(PyConfig * config,wchar_t ** config_str,const char * str)847 PyConfig_SetBytesString(PyConfig *config, wchar_t **config_str,
848 const char *str)
849 {
850 return CONFIG_SET_BYTES_STR(config, config_str, str, "string");
851 }
852
853
854 PyStatus
_PyConfig_Copy(PyConfig * config,const PyConfig * config2)855 _PyConfig_Copy(PyConfig *config, const PyConfig *config2)
856 {
857 PyStatus status;
858
859 PyConfig_Clear(config);
860
861 #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
862 #define COPY_WSTR_ATTR(ATTR) \
863 do { \
864 status = PyConfig_SetString(config, &config->ATTR, config2->ATTR); \
865 if (_PyStatus_EXCEPTION(status)) { \
866 return status; \
867 } \
868 } while (0)
869 #define COPY_WSTRLIST(LIST) \
870 do { \
871 if (_PyWideStringList_Copy(&config->LIST, &config2->LIST) < 0) { \
872 return _PyStatus_NO_MEMORY(); \
873 } \
874 } while (0)
875
876 COPY_ATTR(_config_init);
877 COPY_ATTR(isolated);
878 COPY_ATTR(use_environment);
879 COPY_ATTR(dev_mode);
880 COPY_ATTR(install_signal_handlers);
881 COPY_ATTR(use_hash_seed);
882 COPY_ATTR(hash_seed);
883 COPY_ATTR(_install_importlib);
884 COPY_ATTR(faulthandler);
885 COPY_ATTR(tracemalloc);
886 COPY_ATTR(import_time);
887 COPY_ATTR(show_ref_count);
888 COPY_ATTR(dump_refs);
889 COPY_ATTR(malloc_stats);
890
891 COPY_WSTR_ATTR(pycache_prefix);
892 COPY_WSTR_ATTR(pythonpath_env);
893 COPY_WSTR_ATTR(home);
894 COPY_WSTR_ATTR(program_name);
895
896 COPY_ATTR(parse_argv);
897 COPY_WSTRLIST(argv);
898 COPY_WSTRLIST(warnoptions);
899 COPY_WSTRLIST(xoptions);
900 COPY_WSTRLIST(module_search_paths);
901 COPY_ATTR(module_search_paths_set);
902
903 COPY_WSTR_ATTR(executable);
904 COPY_WSTR_ATTR(base_executable);
905 COPY_WSTR_ATTR(prefix);
906 COPY_WSTR_ATTR(base_prefix);
907 COPY_WSTR_ATTR(exec_prefix);
908 COPY_WSTR_ATTR(base_exec_prefix);
909 COPY_WSTR_ATTR(platlibdir);
910
911 COPY_ATTR(site_import);
912 COPY_ATTR(bytes_warning);
913 COPY_ATTR(warn_default_encoding);
914 COPY_ATTR(inspect);
915 COPY_ATTR(interactive);
916 COPY_ATTR(optimization_level);
917 COPY_ATTR(parser_debug);
918 COPY_ATTR(write_bytecode);
919 COPY_ATTR(verbose);
920 COPY_ATTR(quiet);
921 COPY_ATTR(user_site_directory);
922 COPY_ATTR(configure_c_stdio);
923 COPY_ATTR(buffered_stdio);
924 COPY_WSTR_ATTR(filesystem_encoding);
925 COPY_WSTR_ATTR(filesystem_errors);
926 COPY_WSTR_ATTR(stdio_encoding);
927 COPY_WSTR_ATTR(stdio_errors);
928 #ifdef MS_WINDOWS
929 COPY_ATTR(legacy_windows_stdio);
930 #endif
931 COPY_ATTR(skip_source_first_line);
932 COPY_WSTR_ATTR(run_command);
933 COPY_WSTR_ATTR(run_module);
934 COPY_WSTR_ATTR(run_filename);
935 COPY_WSTR_ATTR(check_hash_pycs_mode);
936 COPY_ATTR(pathconfig_warnings);
937 COPY_ATTR(_init_main);
938 COPY_ATTR(_isolated_interpreter);
939 COPY_WSTRLIST(orig_argv);
940
941 #undef COPY_ATTR
942 #undef COPY_WSTR_ATTR
943 #undef COPY_WSTRLIST
944 return _PyStatus_OK();
945 }
946
947
948 PyObject *
_PyConfig_AsDict(const PyConfig * config)949 _PyConfig_AsDict(const PyConfig *config)
950 {
951 PyObject *dict = PyDict_New();
952 if (dict == NULL) {
953 return NULL;
954 }
955
956 #define SET_ITEM(KEY, EXPR) \
957 do { \
958 PyObject *obj = (EXPR); \
959 if (obj == NULL) { \
960 goto fail; \
961 } \
962 int res = PyDict_SetItemString(dict, (KEY), obj); \
963 Py_DECREF(obj); \
964 if (res < 0) { \
965 goto fail; \
966 } \
967 } while (0)
968 #define SET_ITEM_INT(ATTR) \
969 SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
970 #define SET_ITEM_UINT(ATTR) \
971 SET_ITEM(#ATTR, PyLong_FromUnsignedLong(config->ATTR))
972 #define FROM_WSTRING(STR) \
973 ((STR != NULL) ? \
974 PyUnicode_FromWideChar(STR, -1) \
975 : (Py_INCREF(Py_None), Py_None))
976 #define SET_ITEM_WSTR(ATTR) \
977 SET_ITEM(#ATTR, FROM_WSTRING(config->ATTR))
978 #define SET_ITEM_WSTRLIST(LIST) \
979 SET_ITEM(#LIST, _PyWideStringList_AsList(&config->LIST))
980
981 SET_ITEM_INT(_config_init);
982 SET_ITEM_INT(isolated);
983 SET_ITEM_INT(use_environment);
984 SET_ITEM_INT(dev_mode);
985 SET_ITEM_INT(install_signal_handlers);
986 SET_ITEM_INT(use_hash_seed);
987 SET_ITEM_UINT(hash_seed);
988 SET_ITEM_INT(faulthandler);
989 SET_ITEM_INT(tracemalloc);
990 SET_ITEM_INT(import_time);
991 SET_ITEM_INT(show_ref_count);
992 SET_ITEM_INT(dump_refs);
993 SET_ITEM_INT(malloc_stats);
994 SET_ITEM_WSTR(filesystem_encoding);
995 SET_ITEM_WSTR(filesystem_errors);
996 SET_ITEM_WSTR(pycache_prefix);
997 SET_ITEM_WSTR(program_name);
998 SET_ITEM_INT(parse_argv);
999 SET_ITEM_WSTRLIST(argv);
1000 SET_ITEM_WSTRLIST(xoptions);
1001 SET_ITEM_WSTRLIST(warnoptions);
1002 SET_ITEM_WSTR(pythonpath_env);
1003 SET_ITEM_WSTR(home);
1004 SET_ITEM_INT(module_search_paths_set);
1005 SET_ITEM_WSTRLIST(module_search_paths);
1006 SET_ITEM_WSTR(executable);
1007 SET_ITEM_WSTR(base_executable);
1008 SET_ITEM_WSTR(prefix);
1009 SET_ITEM_WSTR(base_prefix);
1010 SET_ITEM_WSTR(exec_prefix);
1011 SET_ITEM_WSTR(base_exec_prefix);
1012 SET_ITEM_WSTR(platlibdir);
1013 SET_ITEM_INT(site_import);
1014 SET_ITEM_INT(bytes_warning);
1015 SET_ITEM_INT(warn_default_encoding);
1016 SET_ITEM_INT(inspect);
1017 SET_ITEM_INT(interactive);
1018 SET_ITEM_INT(optimization_level);
1019 SET_ITEM_INT(parser_debug);
1020 SET_ITEM_INT(write_bytecode);
1021 SET_ITEM_INT(verbose);
1022 SET_ITEM_INT(quiet);
1023 SET_ITEM_INT(user_site_directory);
1024 SET_ITEM_INT(configure_c_stdio);
1025 SET_ITEM_INT(buffered_stdio);
1026 SET_ITEM_WSTR(stdio_encoding);
1027 SET_ITEM_WSTR(stdio_errors);
1028 #ifdef MS_WINDOWS
1029 SET_ITEM_INT(legacy_windows_stdio);
1030 #endif
1031 SET_ITEM_INT(skip_source_first_line);
1032 SET_ITEM_WSTR(run_command);
1033 SET_ITEM_WSTR(run_module);
1034 SET_ITEM_WSTR(run_filename);
1035 SET_ITEM_INT(_install_importlib);
1036 SET_ITEM_WSTR(check_hash_pycs_mode);
1037 SET_ITEM_INT(pathconfig_warnings);
1038 SET_ITEM_INT(_init_main);
1039 SET_ITEM_INT(_isolated_interpreter);
1040 SET_ITEM_WSTRLIST(orig_argv);
1041
1042 return dict;
1043
1044 fail:
1045 Py_DECREF(dict);
1046 return NULL;
1047
1048 #undef FROM_WSTRING
1049 #undef SET_ITEM
1050 #undef SET_ITEM_INT
1051 #undef SET_ITEM_UINT
1052 #undef SET_ITEM_WSTR
1053 #undef SET_ITEM_WSTRLIST
1054 }
1055
1056
1057 static PyObject*
config_dict_get(PyObject * dict,const char * name)1058 config_dict_get(PyObject *dict, const char *name)
1059 {
1060 PyObject *item = _PyDict_GetItemStringWithError(dict, name);
1061 if (item == NULL && !PyErr_Occurred()) {
1062 PyErr_Format(PyExc_ValueError, "missing config key: %s", name);
1063 return NULL;
1064 }
1065 return item;
1066 }
1067
1068
1069 static void
config_dict_invalid_value(const char * name)1070 config_dict_invalid_value(const char *name)
1071 {
1072 PyErr_Format(PyExc_ValueError, "invalid config value: %s", name);
1073 }
1074
1075
1076 static void
config_dict_invalid_type(const char * name)1077 config_dict_invalid_type(const char *name)
1078 {
1079 PyErr_Format(PyExc_TypeError, "invalid config type: %s", name);
1080 }
1081
1082
1083 static int
config_dict_get_int(PyObject * dict,const char * name,int * result)1084 config_dict_get_int(PyObject *dict, const char *name, int *result)
1085 {
1086 PyObject *item = config_dict_get(dict, name);
1087 if (item == NULL) {
1088 return -1;
1089 }
1090 int value = _PyLong_AsInt(item);
1091 if (value == -1 && PyErr_Occurred()) {
1092 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1093 config_dict_invalid_type(name);
1094 }
1095 else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
1096 config_dict_invalid_value(name);
1097 }
1098 return -1;
1099 }
1100 *result = value;
1101 return 0;
1102 }
1103
1104
1105 static int
config_dict_get_ulong(PyObject * dict,const char * name,unsigned long * result)1106 config_dict_get_ulong(PyObject *dict, const char *name, unsigned long *result)
1107 {
1108 PyObject *item = config_dict_get(dict, name);
1109 if (item == NULL) {
1110 return -1;
1111 }
1112 unsigned long value = PyLong_AsUnsignedLong(item);
1113 if (value == (unsigned long)-1 && PyErr_Occurred()) {
1114 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1115 config_dict_invalid_type(name);
1116 }
1117 else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
1118 config_dict_invalid_value(name);
1119 }
1120 return -1;
1121 }
1122 *result = value;
1123 return 0;
1124 }
1125
1126
1127 static int
config_dict_get_wstr(PyObject * dict,const char * name,PyConfig * config,wchar_t ** result)1128 config_dict_get_wstr(PyObject *dict, const char *name, PyConfig *config,
1129 wchar_t **result)
1130 {
1131 PyObject *item = config_dict_get(dict, name);
1132 if (item == NULL) {
1133 return -1;
1134 }
1135 PyStatus status;
1136 if (item == Py_None) {
1137 status = PyConfig_SetString(config, result, NULL);
1138 }
1139 else if (!PyUnicode_Check(item)) {
1140 config_dict_invalid_type(name);
1141 return -1;
1142 }
1143 else {
1144 wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
1145 if (wstr == NULL) {
1146 return -1;
1147 }
1148 status = PyConfig_SetString(config, result, wstr);
1149 PyMem_Free(wstr);
1150 }
1151 if (_PyStatus_EXCEPTION(status)) {
1152 PyErr_NoMemory();
1153 return -1;
1154 }
1155 return 0;
1156 }
1157
1158
1159 static int
config_dict_get_wstrlist(PyObject * dict,const char * name,PyConfig * config,PyWideStringList * result)1160 config_dict_get_wstrlist(PyObject *dict, const char *name, PyConfig *config,
1161 PyWideStringList *result)
1162 {
1163 PyObject *list = config_dict_get(dict, name);
1164 if (list == NULL) {
1165 return -1;
1166 }
1167
1168 if (!PyList_CheckExact(list)) {
1169 config_dict_invalid_type(name);
1170 return -1;
1171 }
1172
1173 PyWideStringList wstrlist = _PyWideStringList_INIT;
1174 for (Py_ssize_t i=0; i < PyList_GET_SIZE(list); i++) {
1175 PyObject *item = PyList_GET_ITEM(list, i);
1176
1177 if (item == Py_None) {
1178 config_dict_invalid_value(name);
1179 goto error;
1180 }
1181 else if (!PyUnicode_Check(item)) {
1182 config_dict_invalid_type(name);
1183 goto error;
1184 }
1185 wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
1186 if (wstr == NULL) {
1187 goto error;
1188 }
1189 PyStatus status = PyWideStringList_Append(&wstrlist, wstr);
1190 PyMem_Free(wstr);
1191 if (_PyStatus_EXCEPTION(status)) {
1192 PyErr_NoMemory();
1193 goto error;
1194 }
1195 }
1196
1197 if (_PyWideStringList_Copy(result, &wstrlist) < 0) {
1198 PyErr_NoMemory();
1199 goto error;
1200 }
1201 _PyWideStringList_Clear(&wstrlist);
1202 return 0;
1203
1204 error:
1205 _PyWideStringList_Clear(&wstrlist);
1206 return -1;
1207 }
1208
1209
1210 int
_PyConfig_FromDict(PyConfig * config,PyObject * dict)1211 _PyConfig_FromDict(PyConfig *config, PyObject *dict)
1212 {
1213 if (!PyDict_Check(dict)) {
1214 PyErr_SetString(PyExc_TypeError, "dict expected");
1215 return -1;
1216 }
1217
1218 #define CHECK_VALUE(NAME, TEST) \
1219 if (!(TEST)) { \
1220 config_dict_invalid_value(NAME); \
1221 return -1; \
1222 }
1223 #define GET_UINT(KEY) \
1224 do { \
1225 if (config_dict_get_int(dict, #KEY, &config->KEY) < 0) { \
1226 return -1; \
1227 } \
1228 CHECK_VALUE(#KEY, config->KEY >= 0); \
1229 } while (0)
1230 #define GET_WSTR(KEY) \
1231 do { \
1232 if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \
1233 return -1; \
1234 } \
1235 CHECK_VALUE(#KEY, config->KEY != NULL); \
1236 } while (0)
1237 #define GET_WSTR_OPT(KEY) \
1238 do { \
1239 if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \
1240 return -1; \
1241 } \
1242 } while (0)
1243 #define GET_WSTRLIST(KEY) \
1244 do { \
1245 if (config_dict_get_wstrlist(dict, #KEY, config, &config->KEY) < 0) { \
1246 return -1; \
1247 } \
1248 } while (0)
1249
1250 GET_UINT(_config_init);
1251 CHECK_VALUE("_config_init",
1252 config->_config_init == _PyConfig_INIT_COMPAT
1253 || config->_config_init == _PyConfig_INIT_PYTHON
1254 || config->_config_init == _PyConfig_INIT_ISOLATED);
1255 GET_UINT(isolated);
1256 GET_UINT(use_environment);
1257 GET_UINT(dev_mode);
1258 GET_UINT(install_signal_handlers);
1259 GET_UINT(use_hash_seed);
1260 if (config_dict_get_ulong(dict, "hash_seed", &config->hash_seed) < 0) {
1261 return -1;
1262 }
1263 CHECK_VALUE("hash_seed", config->hash_seed <= MAX_HASH_SEED);
1264 GET_UINT(faulthandler);
1265 GET_UINT(tracemalloc);
1266 GET_UINT(import_time);
1267 GET_UINT(show_ref_count);
1268 GET_UINT(dump_refs);
1269 GET_UINT(malloc_stats);
1270 GET_WSTR(filesystem_encoding);
1271 GET_WSTR(filesystem_errors);
1272 GET_WSTR_OPT(pycache_prefix);
1273 GET_UINT(parse_argv);
1274 GET_WSTRLIST(orig_argv);
1275 GET_WSTRLIST(argv);
1276 GET_WSTRLIST(xoptions);
1277 GET_WSTRLIST(warnoptions);
1278 GET_UINT(site_import);
1279 GET_UINT(bytes_warning);
1280 GET_UINT(warn_default_encoding);
1281 GET_UINT(inspect);
1282 GET_UINT(interactive);
1283 GET_UINT(optimization_level);
1284 GET_UINT(parser_debug);
1285 GET_UINT(write_bytecode);
1286 GET_UINT(verbose);
1287 GET_UINT(quiet);
1288 GET_UINT(user_site_directory);
1289 GET_UINT(configure_c_stdio);
1290 GET_UINT(buffered_stdio);
1291 GET_WSTR(stdio_encoding);
1292 GET_WSTR(stdio_errors);
1293 #ifdef MS_WINDOWS
1294 GET_UINT(legacy_windows_stdio);
1295 #endif
1296 GET_WSTR(check_hash_pycs_mode);
1297
1298 GET_UINT(pathconfig_warnings);
1299 GET_WSTR(program_name);
1300 GET_WSTR_OPT(pythonpath_env);
1301 GET_WSTR_OPT(home);
1302 GET_WSTR(platlibdir);
1303
1304 // Path configuration output
1305 GET_UINT(module_search_paths_set);
1306 GET_WSTRLIST(module_search_paths);
1307 GET_WSTR_OPT(executable);
1308 GET_WSTR_OPT(base_executable);
1309 GET_WSTR_OPT(prefix);
1310 GET_WSTR_OPT(base_prefix);
1311 GET_WSTR_OPT(exec_prefix);
1312 GET_WSTR_OPT(base_exec_prefix);
1313
1314 GET_UINT(skip_source_first_line);
1315 GET_WSTR_OPT(run_command);
1316 GET_WSTR_OPT(run_module);
1317 GET_WSTR_OPT(run_filename);
1318
1319 GET_UINT(_install_importlib);
1320 GET_UINT(_init_main);
1321 GET_UINT(_isolated_interpreter);
1322
1323 #undef CHECK_VALUE
1324 #undef GET_UINT
1325 #undef GET_WSTR
1326 #undef GET_WSTR_OPT
1327 return 0;
1328 }
1329
1330
1331 static const char*
config_get_env(const PyConfig * config,const char * name)1332 config_get_env(const PyConfig *config, const char *name)
1333 {
1334 return _Py_GetEnv(config->use_environment, name);
1335 }
1336
1337
1338 /* Get a copy of the environment variable as wchar_t*.
1339 Return 0 on success, but *dest can be NULL.
1340 Return -1 on memory allocation failure. Return -2 on decoding error. */
1341 static PyStatus
config_get_env_dup(PyConfig * config,wchar_t ** dest,wchar_t * wname,char * name,const char * decode_err_msg)1342 config_get_env_dup(PyConfig *config,
1343 wchar_t **dest,
1344 wchar_t *wname, char *name,
1345 const char *decode_err_msg)
1346 {
1347 assert(*dest == NULL);
1348 assert(config->use_environment >= 0);
1349
1350 if (!config->use_environment) {
1351 *dest = NULL;
1352 return _PyStatus_OK();
1353 }
1354
1355 #ifdef MS_WINDOWS
1356 const wchar_t *var = _wgetenv(wname);
1357 if (!var || var[0] == '\0') {
1358 *dest = NULL;
1359 return _PyStatus_OK();
1360 }
1361
1362 return PyConfig_SetString(config, dest, var);
1363 #else
1364 const char *var = getenv(name);
1365 if (!var || var[0] == '\0') {
1366 *dest = NULL;
1367 return _PyStatus_OK();
1368 }
1369
1370 return config_set_bytes_string(config, dest, var, decode_err_msg);
1371 #endif
1372 }
1373
1374
1375 #define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \
1376 config_get_env_dup(CONFIG, DEST, WNAME, NAME, "cannot decode " NAME)
1377
1378
1379 static void
config_get_global_vars(PyConfig * config)1380 config_get_global_vars(PyConfig *config)
1381 {
1382 if (config->_config_init != _PyConfig_INIT_COMPAT) {
1383 /* Python and Isolated configuration ignore global variables */
1384 return;
1385 }
1386
1387 #define COPY_FLAG(ATTR, VALUE) \
1388 if (config->ATTR == -1) { \
1389 config->ATTR = VALUE; \
1390 }
1391 #define COPY_NOT_FLAG(ATTR, VALUE) \
1392 if (config->ATTR == -1) { \
1393 config->ATTR = !(VALUE); \
1394 }
1395
1396 COPY_FLAG(isolated, Py_IsolatedFlag);
1397 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
1398 COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
1399 COPY_FLAG(inspect, Py_InspectFlag);
1400 COPY_FLAG(interactive, Py_InteractiveFlag);
1401 COPY_FLAG(optimization_level, Py_OptimizeFlag);
1402 COPY_FLAG(parser_debug, Py_DebugFlag);
1403 COPY_FLAG(verbose, Py_VerboseFlag);
1404 COPY_FLAG(quiet, Py_QuietFlag);
1405 #ifdef MS_WINDOWS
1406 COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
1407 #endif
1408 COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);
1409
1410 COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
1411 COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
1412 COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
1413 COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
1414
1415 #undef COPY_FLAG
1416 #undef COPY_NOT_FLAG
1417 }
1418
1419
1420 /* Set Py_xxx global configuration variables from 'config' configuration. */
1421 static void
config_set_global_vars(const PyConfig * config)1422 config_set_global_vars(const PyConfig *config)
1423 {
1424 #define COPY_FLAG(ATTR, VAR) \
1425 if (config->ATTR != -1) { \
1426 VAR = config->ATTR; \
1427 }
1428 #define COPY_NOT_FLAG(ATTR, VAR) \
1429 if (config->ATTR != -1) { \
1430 VAR = !config->ATTR; \
1431 }
1432
1433 COPY_FLAG(isolated, Py_IsolatedFlag);
1434 COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
1435 COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
1436 COPY_FLAG(inspect, Py_InspectFlag);
1437 COPY_FLAG(interactive, Py_InteractiveFlag);
1438 COPY_FLAG(optimization_level, Py_OptimizeFlag);
1439 COPY_FLAG(parser_debug, Py_DebugFlag);
1440 COPY_FLAG(verbose, Py_VerboseFlag);
1441 COPY_FLAG(quiet, Py_QuietFlag);
1442 #ifdef MS_WINDOWS
1443 COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
1444 #endif
1445 COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);
1446
1447 COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
1448 COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
1449 COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
1450 COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
1451
1452 /* Random or non-zero hash seed */
1453 Py_HashRandomizationFlag = (config->use_hash_seed == 0 ||
1454 config->hash_seed != 0);
1455
1456 #undef COPY_FLAG
1457 #undef COPY_NOT_FLAG
1458 }
1459
1460
1461 /* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__
1462 environment variables on macOS if available. */
1463 static PyStatus
config_init_program_name(PyConfig * config)1464 config_init_program_name(PyConfig *config)
1465 {
1466 PyStatus status;
1467
1468 /* If Py_SetProgramName() was called, use its value */
1469 const wchar_t *program_name = _Py_path_config.program_name;
1470 if (program_name != NULL) {
1471 config->program_name = _PyMem_RawWcsdup(program_name);
1472 if (config->program_name == NULL) {
1473 return _PyStatus_NO_MEMORY();
1474 }
1475 return _PyStatus_OK();
1476 }
1477
1478 #ifdef __APPLE__
1479 /* On MacOS X, when the Python interpreter is embedded in an
1480 application bundle, it gets executed by a bootstrapping script
1481 that does os.execve() with an argv[0] that's different from the
1482 actual Python executable. This is needed to keep the Finder happy,
1483 or rather, to work around Apple's overly strict requirements of
1484 the process name. However, we still need a usable sys.executable,
1485 so the actual executable path is passed in an environment variable.
1486 See Lib/plat-mac/bundlebuilder.py for details about the bootstrap
1487 script. */
1488 const char *p = config_get_env(config, "PYTHONEXECUTABLE");
1489 if (p != NULL) {
1490 status = CONFIG_SET_BYTES_STR(config, &config->program_name, p,
1491 "PYTHONEXECUTABLE environment variable");
1492 if (_PyStatus_EXCEPTION(status)) {
1493 return status;
1494 }
1495 return _PyStatus_OK();
1496 }
1497 #ifdef WITH_NEXT_FRAMEWORK
1498 else {
1499 const char* pyvenv_launcher = getenv("__PYVENV_LAUNCHER__");
1500 if (pyvenv_launcher && *pyvenv_launcher) {
1501 /* Used by Mac/Tools/pythonw.c to forward
1502 * the argv0 of the stub executable
1503 */
1504 status = CONFIG_SET_BYTES_STR(config,
1505 &config->program_name,
1506 pyvenv_launcher,
1507 "__PYVENV_LAUNCHER__ environment variable");
1508 if (_PyStatus_EXCEPTION(status)) {
1509 return status;
1510 }
1511
1512 /*
1513 * This environment variable is used to communicate between
1514 * the stub launcher and the real interpreter and isn't needed
1515 * beyond this point.
1516 *
1517 * Clean up to avoid problems when launching other programs
1518 * later on.
1519 */
1520 (void)unsetenv("__PYVENV_LAUNCHER__");
1521
1522 return _PyStatus_OK();
1523 }
1524 }
1525 #endif /* WITH_NEXT_FRAMEWORK */
1526 #endif /* __APPLE__ */
1527
1528 /* Use argv[0] if available and non-empty */
1529 const PyWideStringList *argv = &config->argv;
1530 if (argv->length >= 1 && argv->items[0][0] != L'\0') {
1531 config->program_name = _PyMem_RawWcsdup(argv->items[0]);
1532 if (config->program_name == NULL) {
1533 return _PyStatus_NO_MEMORY();
1534 }
1535 return _PyStatus_OK();
1536 }
1537
1538 /* Last fall back: hardcoded name */
1539 #ifdef MS_WINDOWS
1540 const wchar_t *default_program_name = L"python";
1541 #else
1542 const wchar_t *default_program_name = L"python3";
1543 #endif
1544 status = PyConfig_SetString(config, &config->program_name,
1545 default_program_name);
1546 if (_PyStatus_EXCEPTION(status)) {
1547 return status;
1548 }
1549 return _PyStatus_OK();
1550 }
1551
1552 static PyStatus
config_init_executable(PyConfig * config)1553 config_init_executable(PyConfig *config)
1554 {
1555 assert(config->executable == NULL);
1556
1557 /* If Py_SetProgramFullPath() was called, use its value */
1558 const wchar_t *program_full_path = _Py_path_config.program_full_path;
1559 if (program_full_path != NULL) {
1560 PyStatus status = PyConfig_SetString(config,
1561 &config->executable,
1562 program_full_path);
1563 if (_PyStatus_EXCEPTION(status)) {
1564 return status;
1565 }
1566 return _PyStatus_OK();
1567 }
1568 return _PyStatus_OK();
1569 }
1570
1571
1572 static const wchar_t*
config_get_xoption(const PyConfig * config,wchar_t * name)1573 config_get_xoption(const PyConfig *config, wchar_t *name)
1574 {
1575 return _Py_get_xoption(&config->xoptions, name);
1576 }
1577
1578
1579 static PyStatus
config_init_home(PyConfig * config)1580 config_init_home(PyConfig *config)
1581 {
1582 assert(config->home == NULL);
1583
1584 /* If Py_SetPythonHome() was called, use its value */
1585 wchar_t *home = _Py_path_config.home;
1586 if (home) {
1587 PyStatus status = PyConfig_SetString(config, &config->home, home);
1588 if (_PyStatus_EXCEPTION(status)) {
1589 return status;
1590 }
1591 return _PyStatus_OK();
1592 }
1593
1594 return CONFIG_GET_ENV_DUP(config, &config->home,
1595 L"PYTHONHOME", "PYTHONHOME");
1596 }
1597
1598 static PyStatus
config_init_hash_seed(PyConfig * config)1599 config_init_hash_seed(PyConfig *config)
1600 {
1601 const char *seed_text = config_get_env(config, "PYTHONHASHSEED");
1602
1603 Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc));
1604 /* Convert a text seed to a numeric one */
1605 if (seed_text && strcmp(seed_text, "random") != 0) {
1606 const char *endptr = seed_text;
1607 unsigned long seed;
1608 errno = 0;
1609 seed = strtoul(seed_text, (char **)&endptr, 10);
1610 if (*endptr != '\0'
1611 || seed > MAX_HASH_SEED
1612 || (errno == ERANGE && seed == ULONG_MAX))
1613 {
1614 return _PyStatus_ERR("PYTHONHASHSEED must be \"random\" "
1615 "or an integer in range [0; 4294967295]");
1616 }
1617 /* Use a specific hash */
1618 config->use_hash_seed = 1;
1619 config->hash_seed = seed;
1620 }
1621 else {
1622 /* Use a random hash */
1623 config->use_hash_seed = 0;
1624 config->hash_seed = 0;
1625 }
1626 return _PyStatus_OK();
1627 }
1628
1629
1630 static int
config_wstr_to_int(const wchar_t * wstr,int * result)1631 config_wstr_to_int(const wchar_t *wstr, int *result)
1632 {
1633 const wchar_t *endptr = wstr;
1634 errno = 0;
1635 long value = wcstol(wstr, (wchar_t **)&endptr, 10);
1636 if (*endptr != '\0' || errno == ERANGE) {
1637 return -1;
1638 }
1639 if (value < INT_MIN || value > INT_MAX) {
1640 return -1;
1641 }
1642
1643 *result = (int)value;
1644 return 0;
1645 }
1646
1647
1648 static PyStatus
config_read_env_vars(PyConfig * config)1649 config_read_env_vars(PyConfig *config)
1650 {
1651 PyStatus status;
1652 int use_env = config->use_environment;
1653
1654 /* Get environment variables */
1655 _Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG");
1656 _Py_get_env_flag(use_env, &config->verbose, "PYTHONVERBOSE");
1657 _Py_get_env_flag(use_env, &config->optimization_level, "PYTHONOPTIMIZE");
1658 _Py_get_env_flag(use_env, &config->inspect, "PYTHONINSPECT");
1659
1660 int dont_write_bytecode = 0;
1661 _Py_get_env_flag(use_env, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
1662 if (dont_write_bytecode) {
1663 config->write_bytecode = 0;
1664 }
1665
1666 int no_user_site_directory = 0;
1667 _Py_get_env_flag(use_env, &no_user_site_directory, "PYTHONNOUSERSITE");
1668 if (no_user_site_directory) {
1669 config->user_site_directory = 0;
1670 }
1671
1672 int unbuffered_stdio = 0;
1673 _Py_get_env_flag(use_env, &unbuffered_stdio, "PYTHONUNBUFFERED");
1674 if (unbuffered_stdio) {
1675 config->buffered_stdio = 0;
1676 }
1677
1678 #ifdef MS_WINDOWS
1679 _Py_get_env_flag(use_env, &config->legacy_windows_stdio,
1680 "PYTHONLEGACYWINDOWSSTDIO");
1681 #endif
1682
1683 if (config_get_env(config, "PYTHONDUMPREFS")) {
1684 config->dump_refs = 1;
1685 }
1686 if (config_get_env(config, "PYTHONMALLOCSTATS")) {
1687 config->malloc_stats = 1;
1688 }
1689
1690 if (config->pythonpath_env == NULL) {
1691 status = CONFIG_GET_ENV_DUP(config, &config->pythonpath_env,
1692 L"PYTHONPATH", "PYTHONPATH");
1693 if (_PyStatus_EXCEPTION(status)) {
1694 return status;
1695 }
1696 }
1697
1698 if(config->platlibdir == NULL) {
1699 status = CONFIG_GET_ENV_DUP(config, &config->platlibdir,
1700 L"PYTHONPLATLIBDIR", "PYTHONPLATLIBDIR");
1701 if (_PyStatus_EXCEPTION(status)) {
1702 return status;
1703 }
1704 }
1705
1706 if (config->use_hash_seed < 0) {
1707 status = config_init_hash_seed(config);
1708 if (_PyStatus_EXCEPTION(status)) {
1709 return status;
1710 }
1711 }
1712
1713 return _PyStatus_OK();
1714 }
1715
1716
1717 static PyStatus
config_init_tracemalloc(PyConfig * config)1718 config_init_tracemalloc(PyConfig *config)
1719 {
1720 int nframe;
1721 int valid;
1722
1723 const char *env = config_get_env(config, "PYTHONTRACEMALLOC");
1724 if (env) {
1725 if (!_Py_str_to_int(env, &nframe)) {
1726 valid = (nframe >= 0);
1727 }
1728 else {
1729 valid = 0;
1730 }
1731 if (!valid) {
1732 return _PyStatus_ERR("PYTHONTRACEMALLOC: invalid number of frames");
1733 }
1734 config->tracemalloc = nframe;
1735 }
1736
1737 const wchar_t *xoption = config_get_xoption(config, L"tracemalloc");
1738 if (xoption) {
1739 const wchar_t *sep = wcschr(xoption, L'=');
1740 if (sep) {
1741 if (!config_wstr_to_int(sep + 1, &nframe)) {
1742 valid = (nframe >= 0);
1743 }
1744 else {
1745 valid = 0;
1746 }
1747 if (!valid) {
1748 return _PyStatus_ERR("-X tracemalloc=NFRAME: "
1749 "invalid number of frames");
1750 }
1751 }
1752 else {
1753 /* -X tracemalloc behaves as -X tracemalloc=1 */
1754 nframe = 1;
1755 }
1756 config->tracemalloc = nframe;
1757 }
1758 return _PyStatus_OK();
1759 }
1760
1761
1762 static PyStatus
config_init_pycache_prefix(PyConfig * config)1763 config_init_pycache_prefix(PyConfig *config)
1764 {
1765 assert(config->pycache_prefix == NULL);
1766
1767 const wchar_t *xoption = config_get_xoption(config, L"pycache_prefix");
1768 if (xoption) {
1769 const wchar_t *sep = wcschr(xoption, L'=');
1770 if (sep && wcslen(sep) > 1) {
1771 config->pycache_prefix = _PyMem_RawWcsdup(sep + 1);
1772 if (config->pycache_prefix == NULL) {
1773 return _PyStatus_NO_MEMORY();
1774 }
1775 }
1776 else {
1777 // PYTHONPYCACHEPREFIX env var ignored
1778 // if "-X pycache_prefix=" option is used
1779 config->pycache_prefix = NULL;
1780 }
1781 return _PyStatus_OK();
1782 }
1783
1784 return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix,
1785 L"PYTHONPYCACHEPREFIX",
1786 "PYTHONPYCACHEPREFIX");
1787 }
1788
1789
1790 static PyStatus
config_read_complex_options(PyConfig * config)1791 config_read_complex_options(PyConfig *config)
1792 {
1793 /* More complex options configured by env var and -X option */
1794 if (config->faulthandler < 0) {
1795 if (config_get_env(config, "PYTHONFAULTHANDLER")
1796 || config_get_xoption(config, L"faulthandler")) {
1797 config->faulthandler = 1;
1798 }
1799 }
1800 if (config_get_env(config, "PYTHONPROFILEIMPORTTIME")
1801 || config_get_xoption(config, L"importtime")) {
1802 config->import_time = 1;
1803 }
1804
1805 PyStatus status;
1806 if (config->tracemalloc < 0) {
1807 status = config_init_tracemalloc(config);
1808 if (_PyStatus_EXCEPTION(status)) {
1809 return status;
1810 }
1811 }
1812
1813 if (config->pycache_prefix == NULL) {
1814 status = config_init_pycache_prefix(config);
1815 if (_PyStatus_EXCEPTION(status)) {
1816 return status;
1817 }
1818 }
1819 return _PyStatus_OK();
1820 }
1821
1822
1823 static const wchar_t *
config_get_stdio_errors(const PyPreConfig * preconfig)1824 config_get_stdio_errors(const PyPreConfig *preconfig)
1825 {
1826 if (preconfig->utf8_mode) {
1827 /* UTF-8 Mode uses UTF-8/surrogateescape */
1828 return L"surrogateescape";
1829 }
1830
1831 #ifndef MS_WINDOWS
1832 const char *loc = setlocale(LC_CTYPE, NULL);
1833 if (loc != NULL) {
1834 /* surrogateescape is the default in the legacy C and POSIX locales */
1835 if (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0) {
1836 return L"surrogateescape";
1837 }
1838
1839 #ifdef PY_COERCE_C_LOCALE
1840 /* surrogateescape is the default in locale coercion target locales */
1841 if (_Py_IsLocaleCoercionTarget(loc)) {
1842 return L"surrogateescape";
1843 }
1844 #endif
1845 }
1846
1847 return L"strict";
1848 #else
1849 /* On Windows, always use surrogateescape by default */
1850 return L"surrogateescape";
1851 #endif
1852 }
1853
1854
1855 // See also config_get_fs_encoding()
1856 static PyStatus
config_get_locale_encoding(PyConfig * config,const PyPreConfig * preconfig,wchar_t ** locale_encoding)1857 config_get_locale_encoding(PyConfig *config, const PyPreConfig *preconfig,
1858 wchar_t **locale_encoding)
1859 {
1860 wchar_t *encoding = _Py_GetLocaleEncoding();
1861 if (encoding == NULL) {
1862 return _PyStatus_NO_MEMORY();
1863 }
1864 PyStatus status = PyConfig_SetString(config, locale_encoding, encoding);
1865 PyMem_RawFree(encoding);
1866 return status;
1867 }
1868
1869
1870 static PyStatus
config_init_stdio_encoding(PyConfig * config,const PyPreConfig * preconfig)1871 config_init_stdio_encoding(PyConfig *config,
1872 const PyPreConfig *preconfig)
1873 {
1874 PyStatus status;
1875
1876 /* If Py_SetStandardStreamEncoding() has been called, use its
1877 arguments if they are not NULL. */
1878 if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) {
1879 status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding,
1880 _Py_StandardStreamEncoding,
1881 "_Py_StandardStreamEncoding");
1882 if (_PyStatus_EXCEPTION(status)) {
1883 return status;
1884 }
1885 }
1886
1887 if (config->stdio_errors == NULL && _Py_StandardStreamErrors != NULL) {
1888 status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors,
1889 _Py_StandardStreamErrors,
1890 "_Py_StandardStreamErrors");
1891 if (_PyStatus_EXCEPTION(status)) {
1892 return status;
1893 }
1894 }
1895
1896 // Exit if encoding and errors are defined
1897 if (config->stdio_encoding != NULL && config->stdio_errors != NULL) {
1898 return _PyStatus_OK();
1899 }
1900
1901 /* PYTHONIOENCODING environment variable */
1902 const char *opt = config_get_env(config, "PYTHONIOENCODING");
1903 if (opt) {
1904 char *pythonioencoding = _PyMem_RawStrdup(opt);
1905 if (pythonioencoding == NULL) {
1906 return _PyStatus_NO_MEMORY();
1907 }
1908
1909 char *errors = strchr(pythonioencoding, ':');
1910 if (errors) {
1911 *errors = '\0';
1912 errors++;
1913 if (!errors[0]) {
1914 errors = NULL;
1915 }
1916 }
1917
1918 /* Does PYTHONIOENCODING contain an encoding? */
1919 if (pythonioencoding[0]) {
1920 if (config->stdio_encoding == NULL) {
1921 status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding,
1922 pythonioencoding,
1923 "PYTHONIOENCODING environment variable");
1924 if (_PyStatus_EXCEPTION(status)) {
1925 PyMem_RawFree(pythonioencoding);
1926 return status;
1927 }
1928 }
1929
1930 /* If the encoding is set but not the error handler,
1931 use "strict" error handler by default.
1932 PYTHONIOENCODING=latin1 behaves as
1933 PYTHONIOENCODING=latin1:strict. */
1934 if (!errors) {
1935 errors = "strict";
1936 }
1937 }
1938
1939 if (config->stdio_errors == NULL && errors != NULL) {
1940 status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors,
1941 errors,
1942 "PYTHONIOENCODING environment variable");
1943 if (_PyStatus_EXCEPTION(status)) {
1944 PyMem_RawFree(pythonioencoding);
1945 return status;
1946 }
1947 }
1948
1949 PyMem_RawFree(pythonioencoding);
1950 }
1951
1952 /* Choose the default error handler based on the current locale. */
1953 if (config->stdio_encoding == NULL) {
1954 status = config_get_locale_encoding(config, preconfig,
1955 &config->stdio_encoding);
1956 if (_PyStatus_EXCEPTION(status)) {
1957 return status;
1958 }
1959 }
1960 if (config->stdio_errors == NULL) {
1961 const wchar_t *errors = config_get_stdio_errors(preconfig);
1962 assert(errors != NULL);
1963
1964 status = PyConfig_SetString(config, &config->stdio_errors, errors);
1965 if (_PyStatus_EXCEPTION(status)) {
1966 return status;
1967 }
1968 }
1969
1970 return _PyStatus_OK();
1971 }
1972
1973
1974 // See also config_get_locale_encoding()
1975 static PyStatus
config_get_fs_encoding(PyConfig * config,const PyPreConfig * preconfig,wchar_t ** fs_encoding)1976 config_get_fs_encoding(PyConfig *config, const PyPreConfig *preconfig,
1977 wchar_t **fs_encoding)
1978 {
1979 #ifdef _Py_FORCE_UTF8_FS_ENCODING
1980 return PyConfig_SetString(config, fs_encoding, L"utf-8");
1981 #elif defined(MS_WINDOWS)
1982 const wchar_t *encoding;
1983 if (preconfig->legacy_windows_fs_encoding) {
1984 // Legacy Windows filesystem encoding: mbcs/replace
1985 encoding = L"mbcs";
1986 }
1987 else {
1988 // Windows defaults to utf-8/surrogatepass (PEP 529)
1989 encoding = L"utf-8";
1990 }
1991 return PyConfig_SetString(config, fs_encoding, encoding);
1992 #else // !MS_WINDOWS
1993 if (preconfig->utf8_mode) {
1994 return PyConfig_SetString(config, fs_encoding, L"utf-8");
1995 }
1996
1997 if (_Py_GetForceASCII()) {
1998 return PyConfig_SetString(config, fs_encoding, L"ascii");
1999 }
2000
2001 return config_get_locale_encoding(config, preconfig, fs_encoding);
2002 #endif // !MS_WINDOWS
2003 }
2004
2005
2006 static PyStatus
config_init_fs_encoding(PyConfig * config,const PyPreConfig * preconfig)2007 config_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig)
2008 {
2009 PyStatus status;
2010
2011 if (config->filesystem_encoding == NULL) {
2012 status = config_get_fs_encoding(config, preconfig,
2013 &config->filesystem_encoding);
2014 if (_PyStatus_EXCEPTION(status)) {
2015 return status;
2016 }
2017 }
2018
2019 if (config->filesystem_errors == NULL) {
2020 const wchar_t *errors;
2021 #ifdef MS_WINDOWS
2022 if (preconfig->legacy_windows_fs_encoding) {
2023 errors = L"replace";
2024 }
2025 else {
2026 errors = L"surrogatepass";
2027 }
2028 #else
2029 errors = L"surrogateescape";
2030 #endif
2031 status = PyConfig_SetString(config, &config->filesystem_errors, errors);
2032 if (_PyStatus_EXCEPTION(status)) {
2033 return status;
2034 }
2035 }
2036 return _PyStatus_OK();
2037 }
2038
2039
2040 static PyStatus
config_read(PyConfig * config,int compute_path_config)2041 config_read(PyConfig *config, int compute_path_config)
2042 {
2043 PyStatus status;
2044 const PyPreConfig *preconfig = &_PyRuntime.preconfig;
2045
2046 if (config->use_environment) {
2047 status = config_read_env_vars(config);
2048 if (_PyStatus_EXCEPTION(status)) {
2049 return status;
2050 }
2051 }
2052
2053 /* -X options */
2054 if (config_get_xoption(config, L"showrefcount")) {
2055 config->show_ref_count = 1;
2056 }
2057
2058 status = config_read_complex_options(config);
2059 if (_PyStatus_EXCEPTION(status)) {
2060 return status;
2061 }
2062
2063 if (config->home == NULL) {
2064 status = config_init_home(config);
2065 if (_PyStatus_EXCEPTION(status)) {
2066 return status;
2067 }
2068 }
2069
2070 if (config->executable == NULL) {
2071 status = config_init_executable(config);
2072 if (_PyStatus_EXCEPTION(status)) {
2073 return status;
2074 }
2075 }
2076
2077 if(config->platlibdir == NULL) {
2078 status = CONFIG_SET_BYTES_STR(config, &config->platlibdir, PLATLIBDIR,
2079 "PLATLIBDIR macro");
2080 if (_PyStatus_EXCEPTION(status)) {
2081 return status;
2082 }
2083 }
2084
2085 if (config->_install_importlib) {
2086 status = _PyConfig_InitPathConfig(config, compute_path_config);
2087 if (_PyStatus_EXCEPTION(status)) {
2088 return status;
2089 }
2090 }
2091
2092 /* default values */
2093 if (config->dev_mode) {
2094 if (config->faulthandler < 0) {
2095 config->faulthandler = 1;
2096 }
2097 }
2098 if (config->faulthandler < 0) {
2099 config->faulthandler = 0;
2100 }
2101 if (config->tracemalloc < 0) {
2102 config->tracemalloc = 0;
2103 }
2104 if (config->use_hash_seed < 0) {
2105 config->use_hash_seed = 0;
2106 config->hash_seed = 0;
2107 }
2108
2109 if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) {
2110 status = config_init_fs_encoding(config, preconfig);
2111 if (_PyStatus_EXCEPTION(status)) {
2112 return status;
2113 }
2114 }
2115
2116 status = config_init_stdio_encoding(config, preconfig);
2117 if (_PyStatus_EXCEPTION(status)) {
2118 return status;
2119 }
2120
2121 if (config->argv.length < 1) {
2122 /* Ensure at least one (empty) argument is seen */
2123 status = PyWideStringList_Append(&config->argv, L"");
2124 if (_PyStatus_EXCEPTION(status)) {
2125 return status;
2126 }
2127 }
2128
2129 if (config->check_hash_pycs_mode == NULL) {
2130 status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
2131 L"default");
2132 if (_PyStatus_EXCEPTION(status)) {
2133 return status;
2134 }
2135 }
2136
2137 if (config->configure_c_stdio < 0) {
2138 config->configure_c_stdio = 1;
2139 }
2140
2141 // Only parse arguments once.
2142 if (config->parse_argv == 1) {
2143 config->parse_argv = 2;
2144 }
2145
2146 return _PyStatus_OK();
2147 }
2148
2149
2150 static void
config_init_stdio(const PyConfig * config)2151 config_init_stdio(const PyConfig *config)
2152 {
2153 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
2154 /* don't translate newlines (\r\n <=> \n) */
2155 _setmode(fileno(stdin), O_BINARY);
2156 _setmode(fileno(stdout), O_BINARY);
2157 _setmode(fileno(stderr), O_BINARY);
2158 #endif
2159
2160 if (!config->buffered_stdio) {
2161 #ifdef HAVE_SETVBUF
2162 setvbuf(stdin, (char *)NULL, _IONBF, BUFSIZ);
2163 setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
2164 setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
2165 #else /* !HAVE_SETVBUF */
2166 setbuf(stdin, (char *)NULL);
2167 setbuf(stdout, (char *)NULL);
2168 setbuf(stderr, (char *)NULL);
2169 #endif /* !HAVE_SETVBUF */
2170 }
2171 else if (config->interactive) {
2172 #ifdef MS_WINDOWS
2173 /* Doesn't have to have line-buffered -- use unbuffered */
2174 /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
2175 setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
2176 #else /* !MS_WINDOWS */
2177 #ifdef HAVE_SETVBUF
2178 setvbuf(stdin, (char *)NULL, _IOLBF, BUFSIZ);
2179 setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
2180 #endif /* HAVE_SETVBUF */
2181 #endif /* !MS_WINDOWS */
2182 /* Leave stderr alone - it should be unbuffered anyway. */
2183 }
2184 }
2185
2186
2187 /* Write the configuration:
2188
2189 - set Py_xxx global configuration variables
2190 - initialize C standard streams (stdin, stdout, stderr) */
2191 PyStatus
_PyConfig_Write(const PyConfig * config,_PyRuntimeState * runtime)2192 _PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime)
2193 {
2194 config_set_global_vars(config);
2195
2196 if (config->configure_c_stdio) {
2197 config_init_stdio(config);
2198 }
2199
2200 /* Write the new pre-configuration into _PyRuntime */
2201 PyPreConfig *preconfig = &runtime->preconfig;
2202 preconfig->isolated = config->isolated;
2203 preconfig->use_environment = config->use_environment;
2204 preconfig->dev_mode = config->dev_mode;
2205
2206 if (_Py_SetArgcArgv(config->orig_argv.length,
2207 config->orig_argv.items) < 0)
2208 {
2209 return _PyStatus_NO_MEMORY();
2210 }
2211 return _PyStatus_OK();
2212 }
2213
2214
2215 /* --- PyConfig command line parser -------------------------- */
2216
2217 static void
config_usage(int error,const wchar_t * program)2218 config_usage(int error, const wchar_t* program)
2219 {
2220 FILE *f = error ? stderr : stdout;
2221
2222 fprintf(f, usage_line, program);
2223 if (error)
2224 fprintf(f, "Try `python -h' for more information.\n");
2225 else {
2226 fputs(usage_1, f);
2227 fputs(usage_2, f);
2228 fputs(usage_3, f);
2229 fprintf(f, usage_4, (wint_t)DELIM);
2230 fprintf(f, usage_5, (wint_t)DELIM, PYTHONHOMEHELP);
2231 fputs(usage_6, f);
2232 }
2233 }
2234
2235
2236 /* Parse the command line arguments */
2237 static PyStatus
config_parse_cmdline(PyConfig * config,PyWideStringList * warnoptions,Py_ssize_t * opt_index)2238 config_parse_cmdline(PyConfig *config, PyWideStringList *warnoptions,
2239 Py_ssize_t *opt_index)
2240 {
2241 PyStatus status;
2242 const PyWideStringList *argv = &config->argv;
2243 int print_version = 0;
2244 const wchar_t* program = config->program_name;
2245
2246 _PyOS_ResetGetOpt();
2247 do {
2248 int longindex = -1;
2249 int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
2250 if (c == EOF) {
2251 break;
2252 }
2253
2254 if (c == 'c') {
2255 if (config->run_command == NULL) {
2256 /* -c is the last option; following arguments
2257 that look like options are left for the
2258 command to interpret. */
2259 size_t len = wcslen(_PyOS_optarg) + 1 + 1;
2260 wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len);
2261 if (command == NULL) {
2262 return _PyStatus_NO_MEMORY();
2263 }
2264 memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t));
2265 command[len - 2] = '\n';
2266 command[len - 1] = 0;
2267 config->run_command = command;
2268 }
2269 break;
2270 }
2271
2272 if (c == 'm') {
2273 /* -m is the last option; following arguments
2274 that look like options are left for the
2275 module to interpret. */
2276 if (config->run_module == NULL) {
2277 config->run_module = _PyMem_RawWcsdup(_PyOS_optarg);
2278 if (config->run_module == NULL) {
2279 return _PyStatus_NO_MEMORY();
2280 }
2281 }
2282 break;
2283 }
2284
2285 switch (c) {
2286 case 0:
2287 // Handle long option.
2288 assert(longindex == 0); // Only one long option now.
2289 if (wcscmp(_PyOS_optarg, L"always") == 0
2290 || wcscmp(_PyOS_optarg, L"never") == 0
2291 || wcscmp(_PyOS_optarg, L"default") == 0)
2292 {
2293 status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
2294 _PyOS_optarg);
2295 if (_PyStatus_EXCEPTION(status)) {
2296 return status;
2297 }
2298 } else {
2299 fprintf(stderr, "--check-hash-based-pycs must be one of "
2300 "'default', 'always', or 'never'\n");
2301 config_usage(1, program);
2302 return _PyStatus_EXIT(2);
2303 }
2304 break;
2305
2306 case 'b':
2307 config->bytes_warning++;
2308 break;
2309
2310 case 'd':
2311 config->parser_debug++;
2312 break;
2313
2314 case 'i':
2315 config->inspect++;
2316 config->interactive++;
2317 break;
2318
2319 case 'E':
2320 case 'I':
2321 case 'X':
2322 /* option handled by _PyPreCmdline_Read() */
2323 break;
2324
2325 /* case 'J': reserved for Jython */
2326
2327 case 'O':
2328 config->optimization_level++;
2329 break;
2330
2331 case 'B':
2332 config->write_bytecode = 0;
2333 break;
2334
2335 case 's':
2336 config->user_site_directory = 0;
2337 break;
2338
2339 case 'S':
2340 config->site_import = 0;
2341 break;
2342
2343 case 't':
2344 /* ignored for backwards compatibility */
2345 break;
2346
2347 case 'u':
2348 config->buffered_stdio = 0;
2349 break;
2350
2351 case 'v':
2352 config->verbose++;
2353 break;
2354
2355 case 'x':
2356 config->skip_source_first_line = 1;
2357 break;
2358
2359 case 'h':
2360 case '?':
2361 config_usage(0, program);
2362 return _PyStatus_EXIT(0);
2363
2364 case 'V':
2365 print_version++;
2366 break;
2367
2368 case 'W':
2369 status = PyWideStringList_Append(warnoptions, _PyOS_optarg);
2370 if (_PyStatus_EXCEPTION(status)) {
2371 return status;
2372 }
2373 break;
2374
2375 case 'q':
2376 config->quiet++;
2377 break;
2378
2379 case 'R':
2380 config->use_hash_seed = 0;
2381 break;
2382
2383 /* This space reserved for other options */
2384
2385 default:
2386 /* unknown argument: parsing failed */
2387 config_usage(1, program);
2388 return _PyStatus_EXIT(2);
2389 }
2390 } while (1);
2391
2392 if (print_version) {
2393 printf("Python %s\n",
2394 (print_version >= 2) ? Py_GetVersion() : PY_VERSION);
2395 return _PyStatus_EXIT(0);
2396 }
2397
2398 if (config->run_command == NULL && config->run_module == NULL
2399 && _PyOS_optind < argv->length
2400 && wcscmp(argv->items[_PyOS_optind], L"-") != 0
2401 && config->run_filename == NULL)
2402 {
2403 config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]);
2404 if (config->run_filename == NULL) {
2405 return _PyStatus_NO_MEMORY();
2406 }
2407 }
2408
2409 if (config->run_command != NULL || config->run_module != NULL) {
2410 /* Backup _PyOS_optind */
2411 _PyOS_optind--;
2412 }
2413
2414 *opt_index = _PyOS_optind;
2415
2416 return _PyStatus_OK();
2417 }
2418
2419
2420 #ifdef MS_WINDOWS
2421 # define WCSTOK wcstok_s
2422 #else
2423 # define WCSTOK wcstok
2424 #endif
2425
2426 /* Get warning options from PYTHONWARNINGS environment variable. */
2427 static PyStatus
config_init_env_warnoptions(PyConfig * config,PyWideStringList * warnoptions)2428 config_init_env_warnoptions(PyConfig *config, PyWideStringList *warnoptions)
2429 {
2430 PyStatus status;
2431 /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */
2432 wchar_t *env = NULL;
2433 status = CONFIG_GET_ENV_DUP(config, &env,
2434 L"PYTHONWARNINGS", "PYTHONWARNINGS");
2435 if (_PyStatus_EXCEPTION(status)) {
2436 return status;
2437 }
2438
2439 /* env var is not set or is empty */
2440 if (env == NULL) {
2441 return _PyStatus_OK();
2442 }
2443
2444
2445 wchar_t *warning, *context = NULL;
2446 for (warning = WCSTOK(env, L",", &context);
2447 warning != NULL;
2448 warning = WCSTOK(NULL, L",", &context))
2449 {
2450 status = PyWideStringList_Append(warnoptions, warning);
2451 if (_PyStatus_EXCEPTION(status)) {
2452 PyMem_RawFree(env);
2453 return status;
2454 }
2455 }
2456 PyMem_RawFree(env);
2457 return _PyStatus_OK();
2458 }
2459
2460
2461 static PyStatus
warnoptions_append(PyConfig * config,PyWideStringList * options,const wchar_t * option)2462 warnoptions_append(PyConfig *config, PyWideStringList *options,
2463 const wchar_t *option)
2464 {
2465 /* config_init_warnoptions() add existing config warnoptions at the end:
2466 ensure that the new option is not already present in this list to
2467 prevent change the options order when config_init_warnoptions() is
2468 called twice. */
2469 if (_PyWideStringList_Find(&config->warnoptions, option)) {
2470 /* Already present: do nothing */
2471 return _PyStatus_OK();
2472 }
2473 if (_PyWideStringList_Find(options, option)) {
2474 /* Already present: do nothing */
2475 return _PyStatus_OK();
2476 }
2477 return PyWideStringList_Append(options, option);
2478 }
2479
2480
2481 static PyStatus
warnoptions_extend(PyConfig * config,PyWideStringList * options,const PyWideStringList * options2)2482 warnoptions_extend(PyConfig *config, PyWideStringList *options,
2483 const PyWideStringList *options2)
2484 {
2485 const Py_ssize_t len = options2->length;
2486 wchar_t *const *items = options2->items;
2487
2488 for (Py_ssize_t i = 0; i < len; i++) {
2489 PyStatus status = warnoptions_append(config, options, items[i]);
2490 if (_PyStatus_EXCEPTION(status)) {
2491 return status;
2492 }
2493 }
2494 return _PyStatus_OK();
2495 }
2496
2497
2498 static PyStatus
config_init_warnoptions(PyConfig * config,const PyWideStringList * cmdline_warnoptions,const PyWideStringList * env_warnoptions,const PyWideStringList * sys_warnoptions)2499 config_init_warnoptions(PyConfig *config,
2500 const PyWideStringList *cmdline_warnoptions,
2501 const PyWideStringList *env_warnoptions,
2502 const PyWideStringList *sys_warnoptions)
2503 {
2504 PyStatus status;
2505 PyWideStringList options = _PyWideStringList_INIT;
2506
2507 /* Priority of warnings options, lowest to highest:
2508 *
2509 * - any implicit filters added by _warnings.c/warnings.py
2510 * - PyConfig.dev_mode: "default" filter
2511 * - PYTHONWARNINGS environment variable
2512 * - '-W' command line options
2513 * - PyConfig.bytes_warning ('-b' and '-bb' command line options):
2514 * "default::BytesWarning" or "error::BytesWarning" filter
2515 * - early PySys_AddWarnOption() calls
2516 * - PyConfig.warnoptions
2517 *
2518 * PyConfig.warnoptions is copied to sys.warnoptions. Since the warnings
2519 * module works on the basis of "the most recently added filter will be
2520 * checked first", we add the lowest precedence entries first so that later
2521 * entries override them.
2522 */
2523
2524 if (config->dev_mode) {
2525 status = warnoptions_append(config, &options, L"default");
2526 if (_PyStatus_EXCEPTION(status)) {
2527 goto error;
2528 }
2529 }
2530
2531 status = warnoptions_extend(config, &options, env_warnoptions);
2532 if (_PyStatus_EXCEPTION(status)) {
2533 goto error;
2534 }
2535
2536 status = warnoptions_extend(config, &options, cmdline_warnoptions);
2537 if (_PyStatus_EXCEPTION(status)) {
2538 goto error;
2539 }
2540
2541 /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c
2542 * don't even try to emit a warning, so we skip setting the filter in that
2543 * case.
2544 */
2545 if (config->bytes_warning) {
2546 const wchar_t *filter;
2547 if (config->bytes_warning> 1) {
2548 filter = L"error::BytesWarning";
2549 }
2550 else {
2551 filter = L"default::BytesWarning";
2552 }
2553 status = warnoptions_append(config, &options, filter);
2554 if (_PyStatus_EXCEPTION(status)) {
2555 goto error;
2556 }
2557 }
2558
2559 status = warnoptions_extend(config, &options, sys_warnoptions);
2560 if (_PyStatus_EXCEPTION(status)) {
2561 goto error;
2562 }
2563
2564 /* Always add all PyConfig.warnoptions options */
2565 status = _PyWideStringList_Extend(&options, &config->warnoptions);
2566 if (_PyStatus_EXCEPTION(status)) {
2567 goto error;
2568 }
2569
2570 _PyWideStringList_Clear(&config->warnoptions);
2571 config->warnoptions = options;
2572 return _PyStatus_OK();
2573
2574 error:
2575 _PyWideStringList_Clear(&options);
2576 return status;
2577 }
2578
2579
2580 static PyStatus
config_update_argv(PyConfig * config,Py_ssize_t opt_index)2581 config_update_argv(PyConfig *config, Py_ssize_t opt_index)
2582 {
2583 const PyWideStringList *cmdline_argv = &config->argv;
2584 PyWideStringList config_argv = _PyWideStringList_INIT;
2585
2586 /* Copy argv to be able to modify it (to force -c/-m) */
2587 if (cmdline_argv->length <= opt_index) {
2588 /* Ensure at least one (empty) argument is seen */
2589 PyStatus status = PyWideStringList_Append(&config_argv, L"");
2590 if (_PyStatus_EXCEPTION(status)) {
2591 return status;
2592 }
2593 }
2594 else {
2595 PyWideStringList slice;
2596 slice.length = cmdline_argv->length - opt_index;
2597 slice.items = &cmdline_argv->items[opt_index];
2598 if (_PyWideStringList_Copy(&config_argv, &slice) < 0) {
2599 return _PyStatus_NO_MEMORY();
2600 }
2601 }
2602 assert(config_argv.length >= 1);
2603
2604 wchar_t *arg0 = NULL;
2605 if (config->run_command != NULL) {
2606 /* Force sys.argv[0] = '-c' */
2607 arg0 = L"-c";
2608 }
2609 else if (config->run_module != NULL) {
2610 /* Force sys.argv[0] = '-m'*/
2611 arg0 = L"-m";
2612 }
2613
2614 if (arg0 != NULL) {
2615 arg0 = _PyMem_RawWcsdup(arg0);
2616 if (arg0 == NULL) {
2617 _PyWideStringList_Clear(&config_argv);
2618 return _PyStatus_NO_MEMORY();
2619 }
2620
2621 PyMem_RawFree(config_argv.items[0]);
2622 config_argv.items[0] = arg0;
2623 }
2624
2625 _PyWideStringList_Clear(&config->argv);
2626 config->argv = config_argv;
2627 return _PyStatus_OK();
2628 }
2629
2630
2631 static PyStatus
core_read_precmdline(PyConfig * config,_PyPreCmdline * precmdline)2632 core_read_precmdline(PyConfig *config, _PyPreCmdline *precmdline)
2633 {
2634 PyStatus status;
2635
2636 if (config->parse_argv == 1) {
2637 if (_PyWideStringList_Copy(&precmdline->argv, &config->argv) < 0) {
2638 return _PyStatus_NO_MEMORY();
2639 }
2640 }
2641
2642 PyPreConfig preconfig;
2643
2644 status = _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig);
2645 if (_PyStatus_EXCEPTION(status)) {
2646 return status;
2647 }
2648
2649 _PyPreConfig_GetConfig(&preconfig, config);
2650
2651 status = _PyPreCmdline_Read(precmdline, &preconfig);
2652 if (_PyStatus_EXCEPTION(status)) {
2653 return status;
2654 }
2655
2656 status = _PyPreCmdline_SetConfig(precmdline, config);
2657 if (_PyStatus_EXCEPTION(status)) {
2658 return status;
2659 }
2660 return _PyStatus_OK();
2661 }
2662
2663
2664 /* Get run_filename absolute path */
2665 static PyStatus
config_run_filename_abspath(PyConfig * config)2666 config_run_filename_abspath(PyConfig *config)
2667 {
2668 if (!config->run_filename) {
2669 return _PyStatus_OK();
2670 }
2671
2672 #ifndef MS_WINDOWS
2673 if (_Py_isabs(config->run_filename)) {
2674 /* path is already absolute */
2675 return _PyStatus_OK();
2676 }
2677 #endif
2678
2679 wchar_t *abs_filename;
2680 if (_Py_abspath(config->run_filename, &abs_filename) < 0) {
2681 /* failed to get the absolute path of the command line filename:
2682 ignore the error, keep the relative path */
2683 return _PyStatus_OK();
2684 }
2685 if (abs_filename == NULL) {
2686 return _PyStatus_NO_MEMORY();
2687 }
2688
2689 PyMem_RawFree(config->run_filename);
2690 config->run_filename = abs_filename;
2691 return _PyStatus_OK();
2692 }
2693
2694
2695 static PyStatus
config_read_cmdline(PyConfig * config)2696 config_read_cmdline(PyConfig *config)
2697 {
2698 PyStatus status;
2699 PyWideStringList cmdline_warnoptions = _PyWideStringList_INIT;
2700 PyWideStringList env_warnoptions = _PyWideStringList_INIT;
2701 PyWideStringList sys_warnoptions = _PyWideStringList_INIT;
2702
2703 if (config->parse_argv < 0) {
2704 config->parse_argv = 1;
2705 }
2706
2707 if (config->program_name == NULL) {
2708 status = config_init_program_name(config);
2709 if (_PyStatus_EXCEPTION(status)) {
2710 return status;
2711 }
2712 }
2713
2714 if (config->parse_argv == 1) {
2715 Py_ssize_t opt_index;
2716 status = config_parse_cmdline(config, &cmdline_warnoptions, &opt_index);
2717 if (_PyStatus_EXCEPTION(status)) {
2718 goto done;
2719 }
2720
2721 status = config_run_filename_abspath(config);
2722 if (_PyStatus_EXCEPTION(status)) {
2723 goto done;
2724 }
2725
2726 status = config_update_argv(config, opt_index);
2727 if (_PyStatus_EXCEPTION(status)) {
2728 goto done;
2729 }
2730 }
2731 else {
2732 status = config_run_filename_abspath(config);
2733 if (_PyStatus_EXCEPTION(status)) {
2734 goto done;
2735 }
2736 }
2737
2738 if (config->use_environment) {
2739 status = config_init_env_warnoptions(config, &env_warnoptions);
2740 if (_PyStatus_EXCEPTION(status)) {
2741 goto done;
2742 }
2743 }
2744
2745 /* Handle early PySys_AddWarnOption() calls */
2746 status = _PySys_ReadPreinitWarnOptions(&sys_warnoptions);
2747 if (_PyStatus_EXCEPTION(status)) {
2748 goto done;
2749 }
2750
2751 status = config_init_warnoptions(config,
2752 &cmdline_warnoptions,
2753 &env_warnoptions,
2754 &sys_warnoptions);
2755 if (_PyStatus_EXCEPTION(status)) {
2756 goto done;
2757 }
2758
2759 status = _PyStatus_OK();
2760
2761 done:
2762 _PyWideStringList_Clear(&cmdline_warnoptions);
2763 _PyWideStringList_Clear(&env_warnoptions);
2764 _PyWideStringList_Clear(&sys_warnoptions);
2765 return status;
2766 }
2767
2768
2769 PyStatus
_PyConfig_SetPyArgv(PyConfig * config,const _PyArgv * args)2770 _PyConfig_SetPyArgv(PyConfig *config, const _PyArgv *args)
2771 {
2772 PyStatus status = _Py_PreInitializeFromConfig(config, args);
2773 if (_PyStatus_EXCEPTION(status)) {
2774 return status;
2775 }
2776
2777 return _PyArgv_AsWstrList(args, &config->argv);
2778 }
2779
2780
2781 /* Set config.argv: decode argv using Py_DecodeLocale(). Pre-initialize Python
2782 if needed to ensure that encodings are properly configured. */
2783 PyStatus
PyConfig_SetBytesArgv(PyConfig * config,Py_ssize_t argc,char * const * argv)2784 PyConfig_SetBytesArgv(PyConfig *config, Py_ssize_t argc, char * const *argv)
2785 {
2786 _PyArgv args = {
2787 .argc = argc,
2788 .use_bytes_argv = 1,
2789 .bytes_argv = argv,
2790 .wchar_argv = NULL};
2791 return _PyConfig_SetPyArgv(config, &args);
2792 }
2793
2794
2795 PyStatus
PyConfig_SetArgv(PyConfig * config,Py_ssize_t argc,wchar_t * const * argv)2796 PyConfig_SetArgv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv)
2797 {
2798 _PyArgv args = {
2799 .argc = argc,
2800 .use_bytes_argv = 0,
2801 .bytes_argv = NULL,
2802 .wchar_argv = argv};
2803 return _PyConfig_SetPyArgv(config, &args);
2804 }
2805
2806
2807 PyStatus
PyConfig_SetWideStringList(PyConfig * config,PyWideStringList * list,Py_ssize_t length,wchar_t ** items)2808 PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list,
2809 Py_ssize_t length, wchar_t **items)
2810 {
2811 PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
2812 if (_PyStatus_EXCEPTION(status)) {
2813 return status;
2814 }
2815
2816 PyWideStringList list2 = {.length = length, .items = items};
2817 if (_PyWideStringList_Copy(list, &list2) < 0) {
2818 return _PyStatus_NO_MEMORY();
2819 }
2820 return _PyStatus_OK();
2821 }
2822
2823
2824 /* Read the configuration into PyConfig from:
2825
2826 * Command line arguments
2827 * Environment variables
2828 * Py_xxx global configuration variables
2829
2830 The only side effects are to modify config and to call _Py_SetArgcArgv(). */
2831 PyStatus
_PyConfig_Read(PyConfig * config,int compute_path_config)2832 _PyConfig_Read(PyConfig *config, int compute_path_config)
2833 {
2834 PyStatus status;
2835
2836 status = _Py_PreInitializeFromConfig(config, NULL);
2837 if (_PyStatus_EXCEPTION(status)) {
2838 return status;
2839 }
2840
2841 config_get_global_vars(config);
2842
2843 if (config->orig_argv.length == 0
2844 && !(config->argv.length == 1
2845 && wcscmp(config->argv.items[0], L"") == 0))
2846 {
2847 if (_PyWideStringList_Copy(&config->orig_argv, &config->argv) < 0) {
2848 return _PyStatus_NO_MEMORY();
2849 }
2850 }
2851
2852 _PyPreCmdline precmdline = _PyPreCmdline_INIT;
2853 status = core_read_precmdline(config, &precmdline);
2854 if (_PyStatus_EXCEPTION(status)) {
2855 goto done;
2856 }
2857
2858 assert(config->isolated >= 0);
2859 if (config->isolated) {
2860 config->use_environment = 0;
2861 config->user_site_directory = 0;
2862 }
2863
2864 status = config_read_cmdline(config);
2865 if (_PyStatus_EXCEPTION(status)) {
2866 goto done;
2867 }
2868
2869 /* Handle early PySys_AddXOption() calls */
2870 status = _PySys_ReadPreinitXOptions(config);
2871 if (_PyStatus_EXCEPTION(status)) {
2872 goto done;
2873 }
2874
2875 status = config_read(config, compute_path_config);
2876 if (_PyStatus_EXCEPTION(status)) {
2877 goto done;
2878 }
2879
2880 assert(config_check_consistency(config));
2881
2882 status = _PyStatus_OK();
2883
2884 done:
2885 _PyPreCmdline_Clear(&precmdline);
2886 return status;
2887 }
2888
2889
2890 PyStatus
PyConfig_Read(PyConfig * config)2891 PyConfig_Read(PyConfig *config)
2892 {
2893 return _PyConfig_Read(config, 1);
2894 }
2895
2896
2897 PyObject*
_Py_GetConfigsAsDict(void)2898 _Py_GetConfigsAsDict(void)
2899 {
2900 PyObject *result = NULL;
2901 PyObject *dict = NULL;
2902
2903 result = PyDict_New();
2904 if (result == NULL) {
2905 goto error;
2906 }
2907
2908 /* global result */
2909 dict = _Py_GetGlobalVariablesAsDict();
2910 if (dict == NULL) {
2911 goto error;
2912 }
2913 if (PyDict_SetItemString(result, "global_config", dict) < 0) {
2914 goto error;
2915 }
2916 Py_CLEAR(dict);
2917
2918 /* pre config */
2919 PyInterpreterState *interp = _PyInterpreterState_GET();
2920 const PyPreConfig *pre_config = &interp->runtime->preconfig;
2921 dict = _PyPreConfig_AsDict(pre_config);
2922 if (dict == NULL) {
2923 goto error;
2924 }
2925 if (PyDict_SetItemString(result, "pre_config", dict) < 0) {
2926 goto error;
2927 }
2928 Py_CLEAR(dict);
2929
2930 /* core config */
2931 const PyConfig *config = _PyInterpreterState_GetConfig(interp);
2932 dict = _PyConfig_AsDict(config);
2933 if (dict == NULL) {
2934 goto error;
2935 }
2936 if (PyDict_SetItemString(result, "config", dict) < 0) {
2937 goto error;
2938 }
2939 Py_CLEAR(dict);
2940
2941 /* path config */
2942 dict = _PyPathConfig_AsDict();
2943 if (dict == NULL) {
2944 goto error;
2945 }
2946 if (PyDict_SetItemString(result, "path_config", dict) < 0) {
2947 goto error;
2948 }
2949 Py_CLEAR(dict);
2950
2951 return result;
2952
2953 error:
2954 Py_XDECREF(result);
2955 Py_XDECREF(dict);
2956 return NULL;
2957 }
2958
2959
2960 static void
init_dump_ascii_wstr(const wchar_t * str)2961 init_dump_ascii_wstr(const wchar_t *str)
2962 {
2963 if (str == NULL) {
2964 PySys_WriteStderr("(not set)");
2965 return;
2966 }
2967
2968 PySys_WriteStderr("'");
2969 for (; *str != L'\0'; str++) {
2970 unsigned int ch = (unsigned int)*str;
2971 if (ch == L'\'') {
2972 PySys_WriteStderr("\\'");
2973 } else if (0x20 <= ch && ch < 0x7f) {
2974 PySys_WriteStderr("%c", ch);
2975 }
2976 else if (ch <= 0xff) {
2977 PySys_WriteStderr("\\x%02x", ch);
2978 }
2979 #if SIZEOF_WCHAR_T > 2
2980 else if (ch > 0xffff) {
2981 PySys_WriteStderr("\\U%08x", ch);
2982 }
2983 #endif
2984 else {
2985 PySys_WriteStderr("\\u%04x", ch);
2986 }
2987 }
2988 PySys_WriteStderr("'");
2989 }
2990
2991
2992 /* Dump the Python path configuration into sys.stderr */
2993 void
_Py_DumpPathConfig(PyThreadState * tstate)2994 _Py_DumpPathConfig(PyThreadState *tstate)
2995 {
2996 PyObject *exc_type, *exc_value, *exc_tb;
2997 _PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
2998
2999 PySys_WriteStderr("Python path configuration:\n");
3000
3001 #define DUMP_CONFIG(NAME, FIELD) \
3002 do { \
3003 PySys_WriteStderr(" " NAME " = "); \
3004 init_dump_ascii_wstr(config->FIELD); \
3005 PySys_WriteStderr("\n"); \
3006 } while (0)
3007
3008 const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
3009 DUMP_CONFIG("PYTHONHOME", home);
3010 DUMP_CONFIG("PYTHONPATH", pythonpath_env);
3011 DUMP_CONFIG("program name", program_name);
3012 PySys_WriteStderr(" isolated = %i\n", config->isolated);
3013 PySys_WriteStderr(" environment = %i\n", config->use_environment);
3014 PySys_WriteStderr(" user site = %i\n", config->user_site_directory);
3015 PySys_WriteStderr(" import site = %i\n", config->site_import);
3016 #undef DUMP_CONFIG
3017
3018 #define DUMP_SYS(NAME) \
3019 do { \
3020 obj = PySys_GetObject(#NAME); \
3021 PySys_FormatStderr(" sys.%s = ", #NAME); \
3022 if (obj != NULL) { \
3023 PySys_FormatStderr("%A", obj); \
3024 } \
3025 else { \
3026 PySys_WriteStderr("(not set)"); \
3027 } \
3028 PySys_FormatStderr("\n"); \
3029 } while (0)
3030
3031 PyObject *obj;
3032 DUMP_SYS(_base_executable);
3033 DUMP_SYS(base_prefix);
3034 DUMP_SYS(base_exec_prefix);
3035 DUMP_SYS(platlibdir);
3036 DUMP_SYS(executable);
3037 DUMP_SYS(prefix);
3038 DUMP_SYS(exec_prefix);
3039 #undef DUMP_SYS
3040
3041 PyObject *sys_path = PySys_GetObject("path"); /* borrowed reference */
3042 if (sys_path != NULL && PyList_Check(sys_path)) {
3043 PySys_WriteStderr(" sys.path = [\n");
3044 Py_ssize_t len = PyList_GET_SIZE(sys_path);
3045 for (Py_ssize_t i=0; i < len; i++) {
3046 PyObject *path = PyList_GET_ITEM(sys_path, i);
3047 PySys_FormatStderr(" %A,\n", path);
3048 }
3049 PySys_WriteStderr(" ]\n");
3050 }
3051
3052 _PyErr_Restore(tstate, exc_type, exc_value, exc_tb);
3053 }
3054