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