Coverage Report

Created: 2025-07-11 06:59

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