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