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