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