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