Coverage Report

Created: 2026-06-14 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Python-3.8.3/Python/initconfig.c
Line
Count
Source
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
416
{
287
416
    assert(_PyWideStringList_CheckConsistency(list));
288
481
    for (Py_ssize_t i=0; i < list->length; i++) {
289
65
        PyMem_RawFree(list->items[i]);
290
65
    }
291
416
    PyMem_RawFree(list->items);
292
416
    list->length = 0;
293
416
    list->items = NULL;
294
416
}
295
296
297
int
298
_PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2)
299
130
{
300
130
    assert(_PyWideStringList_CheckConsistency(list));
301
130
    assert(_PyWideStringList_CheckConsistency(list2));
302
303
130
    if (list2->length == 0) {
304
104
        _PyWideStringList_Clear(list);
305
104
        return 0;
306
104
    }
307
308
26
    PyWideStringList copy = _PyWideStringList_INIT;
309
310
26
    size_t size = list2->length * sizeof(list2->items[0]);
311
26
    copy.items = PyMem_RawMalloc(size);
312
26
    if (copy.items == NULL) {
313
0
        return -1;
314
0
    }
315
316
91
    for (Py_ssize_t i=0; i < list2->length; i++) {
317
65
        wchar_t *item = _PyMem_RawWcsdup(list2->items[i]);
318
65
        if (item == NULL) {
319
0
            _PyWideStringList_Clear(&copy);
320
0
            return -1;
321
0
        }
322
65
        copy.items[i] = item;
323
65
        copy.length = i + 1;
324
65
    }
325
326
26
    _PyWideStringList_Clear(list);
327
26
    *list = copy;
328
26
    return 0;
329
26
}
330
331
332
PyStatus
333
PyWideStringList_Insert(PyWideStringList *list,
334
                        Py_ssize_t index, const wchar_t *item)
335
65
{
336
65
    Py_ssize_t len = list->length;
337
65
    if (len == PY_SSIZE_T_MAX) {
338
        /* length+1 would overflow */
339
0
        return _PyStatus_NO_MEMORY();
340
0
    }
341
65
    if (index < 0) {
342
0
        return _PyStatus_ERR("PyWideStringList_Insert index must be >= 0");
343
0
    }
344
65
    if (index > len) {
345
0
        index = len;
346
0
    }
347
348
65
    wchar_t *item2 = _PyMem_RawWcsdup(item);
349
65
    if (item2 == NULL) {
350
0
        return _PyStatus_NO_MEMORY();
351
0
    }
352
353
65
    size_t size = (len + 1) * sizeof(list->items[0]);
354
65
    wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size);
355
65
    if (items2 == NULL) {
356
0
        PyMem_RawFree(item2);
357
0
        return _PyStatus_NO_MEMORY();
358
0
    }
359
360
65
    if (index < len) {
361
0
        memmove(&items2[index + 1],
362
0
                &items2[index],
363
0
                (len - index) * sizeof(items2[0]));
364
0
    }
365
366
65
    items2[index] = item2;
367
65
    list->items = items2;
368
65
    list->length++;
369
65
    return _PyStatus_OK();
370
65
}
371
372
373
PyStatus
374
PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
375
65
{
376
65
    return PyWideStringList_Insert(list, list->length, item);
377
65
}
378
379
380
PyStatus
381
_PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2)
382
26
{
383
26
    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
26
    return _PyStatus_OK();
390
26
}
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
39
{
408
39
    assert(_PyWideStringList_CheckConsistency(list));
409
410
39
    PyObject *pylist = PyList_New(list->length);
411
39
    if (pylist == NULL) {
412
0
        return NULL;
413
0
    }
414
415
104
    for (Py_ssize_t i = 0; i < list->length; i++) {
416
65
        PyObject *item = PyUnicode_FromWideChar(list->items[i], -1);
417
65
        if (item == NULL) {
418
0
            Py_DECREF(pylist);
419
0
            return NULL;
420
0
        }
421
65
        PyList_SET_ITEM(pylist, i, item);
422
65
    }
423
39
    return pylist;
424
39
}
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
13
{
494
    /* Use the same allocator than Py_SetStandardStreamEncoding() */
495
13
    PyMemAllocatorEx old_alloc;
496
13
    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
497
498
    /* We won't need them anymore. */
499
13
    if (_Py_StandardStreamEncoding) {
500
0
        PyMem_RawFree(_Py_StandardStreamEncoding);
501
0
        _Py_StandardStreamEncoding = NULL;
502
0
    }
503
13
    if (_Py_StandardStreamErrors) {
504
0
        PyMem_RawFree(_Py_StandardStreamErrors);
505
0
        _Py_StandardStreamErrors = NULL;
506
0
    }
507
508
13
    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
509
13
}
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
13
{
533
13
    const PyWideStringList argv_list = {.length = argc, .items = (wchar_t **)argv};
534
13
    int res;
535
536
13
    PyMemAllocatorEx old_alloc;
537
13
    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
538
539
13
    res = _PyWideStringList_Copy(&orig_argv, &argv_list);
540
541
13
    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
542
13
    return res;
543
13
}
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
39
{
568
39
#define CLEAR(ATTR) \
569
702
    do { \
570
702
        PyMem_RawFree(ATTR); \
571
702
        ATTR = NULL; \
572
702
    } while (0)
573
574
39
    CLEAR(config->pycache_prefix);
575
39
    CLEAR(config->pythonpath_env);
576
39
    CLEAR(config->home);
577
39
    CLEAR(config->program_name);
578
579
39
    _PyWideStringList_Clear(&config->argv);
580
39
    _PyWideStringList_Clear(&config->warnoptions);
581
39
    _PyWideStringList_Clear(&config->xoptions);
582
39
    _PyWideStringList_Clear(&config->module_search_paths);
583
39
    config->module_search_paths_set = 0;
584
585
39
    CLEAR(config->executable);
586
39
    CLEAR(config->base_executable);
587
39
    CLEAR(config->prefix);
588
39
    CLEAR(config->base_prefix);
589
39
    CLEAR(config->exec_prefix);
590
39
    CLEAR(config->base_exec_prefix);
591
592
39
    CLEAR(config->filesystem_encoding);
593
39
    CLEAR(config->filesystem_errors);
594
39
    CLEAR(config->stdio_encoding);
595
39
    CLEAR(config->stdio_errors);
596
39
    CLEAR(config->run_command);
597
39
    CLEAR(config->run_module);
598
39
    CLEAR(config->run_filename);
599
39
    CLEAR(config->check_hash_pycs_mode);
600
39
#undef CLEAR
601
39
}
602
603
604
void
605
_PyConfig_InitCompatConfig(PyConfig *config)
606
39
{
607
39
    memset(config, 0, sizeof(*config));
608
609
39
    config->_config_init = (int)_PyConfig_INIT_COMPAT;
610
39
    config->isolated = -1;
611
39
    config->use_environment = -1;
612
39
    config->dev_mode = -1;
613
39
    config->install_signal_handlers = 1;
614
39
    config->use_hash_seed = -1;
615
39
    config->faulthandler = -1;
616
39
    config->tracemalloc = -1;
617
39
    config->module_search_paths_set = 0;
618
39
    config->parse_argv = 0;
619
39
    config->site_import = -1;
620
39
    config->bytes_warning = -1;
621
39
    config->inspect = -1;
622
39
    config->interactive = -1;
623
39
    config->optimization_level = -1;
624
39
    config->parser_debug= -1;
625
39
    config->write_bytecode = -1;
626
39
    config->verbose = -1;
627
39
    config->quiet = -1;
628
39
    config->user_site_directory = -1;
629
39
    config->configure_c_stdio = 0;
630
39
    config->buffered_stdio = -1;
631
39
    config->_install_importlib = 1;
632
39
    config->check_hash_pycs_mode = NULL;
633
39
    config->pathconfig_warnings = -1;
634
39
    config->_init_main = 1;
635
#ifdef MS_WINDOWS
636
    config->legacy_windows_stdio = -1;
637
#endif
638
39
}
639
640
641
static void
642
config_init_defaults(PyConfig *config)
643
13
{
644
13
    _PyConfig_InitCompatConfig(config);
645
646
13
    config->isolated = 0;
647
13
    config->use_environment = 1;
648
13
    config->site_import = 1;
649
13
    config->bytes_warning = 0;
650
13
    config->inspect = 0;
651
13
    config->interactive = 0;
652
13
    config->optimization_level = 0;
653
13
    config->parser_debug= 0;
654
13
    config->write_bytecode = 1;
655
13
    config->verbose = 0;
656
13
    config->quiet = 0;
657
13
    config->user_site_directory = 1;
658
13
    config->buffered_stdio = 1;
659
13
    config->pathconfig_warnings = 1;
660
#ifdef MS_WINDOWS
661
    config->legacy_windows_stdio = 0;
662
#endif
663
13
}
664
665
666
void
667
PyConfig_InitPythonConfig(PyConfig *config)
668
13
{
669
13
    config_init_defaults(config);
670
671
13
    config->_config_init = (int)_PyConfig_INIT_PYTHON;
672
13
    config->configure_c_stdio = 1;
673
13
    config->parse_argv = 1;
674
13
}
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
533
{
702
533
    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
703
533
    if (_PyStatus_EXCEPTION(status)) {
704
0
        return status;
705
0
    }
706
707
533
    wchar_t *str2;
708
533
    if (str != NULL) {
709
247
        str2 = _PyMem_RawWcsdup(str);
710
247
        if (str2 == NULL) {
711
0
            return _PyStatus_NO_MEMORY();
712
0
        }
713
247
    }
714
286
    else {
715
286
        str2 = NULL;
716
286
    }
717
533
    PyMem_RawFree(*config_str);
718
533
    *config_str = str2;
719
533
    return _PyStatus_OK();
720
533
}
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
39
{
727
39
    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
728
39
    if (_PyStatus_EXCEPTION(status)) {
729
0
        return status;
730
0
    }
731
732
39
    wchar_t *str2;
733
39
    if (str != NULL) {
734
39
        size_t len;
735
39
        str2 = Py_DecodeLocale(str, &len);
736
39
        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
39
    }
745
0
    else {
746
0
        str2 = NULL;
747
0
    }
748
39
    PyMem_RawFree(*config_str);
749
39
    *config_str = str2;
750
39
    return _PyStatus_OK();
751
39
}
752
753
754
#define CONFIG_SET_BYTES_STR(config, config_str, str, NAME) \
755
26
    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
26
{
772
26
    PyStatus status;
773
774
26
    PyConfig_Clear(config);
775
776
832
#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
777
26
#define COPY_WSTR_ATTR(ATTR) \
778
468
    do { \
779
468
        status = PyConfig_SetString(config, &config->ATTR, config2->ATTR); \
780
468
        if (_PyStatus_EXCEPTION(status)) { \
781
0
            return status; \
782
0
        } \
783
468
    } while (0)
784
26
#define COPY_WSTRLIST(LIST) \
785
104
    do { \
786
104
        if (_PyWideStringList_Copy(&config->LIST, &config2->LIST) < 0) { \
787
0
            return _PyStatus_NO_MEMORY(); \
788
0
        } \
789
104
    } while (0)
790
791
26
    COPY_ATTR(_config_init);
792
26
    COPY_ATTR(isolated);
793
26
    COPY_ATTR(use_environment);
794
26
    COPY_ATTR(dev_mode);
795
26
    COPY_ATTR(install_signal_handlers);
796
26
    COPY_ATTR(use_hash_seed);
797
26
    COPY_ATTR(hash_seed);
798
26
    COPY_ATTR(_install_importlib);
799
26
    COPY_ATTR(faulthandler);
800
26
    COPY_ATTR(tracemalloc);
801
26
    COPY_ATTR(import_time);
802
26
    COPY_ATTR(show_ref_count);
803
26
    COPY_ATTR(show_alloc_count);
804
26
    COPY_ATTR(dump_refs);
805
26
    COPY_ATTR(malloc_stats);
806
807
26
    COPY_WSTR_ATTR(pycache_prefix);
808
26
    COPY_WSTR_ATTR(pythonpath_env);
809
26
    COPY_WSTR_ATTR(home);
810
26
    COPY_WSTR_ATTR(program_name);
811
812
26
    COPY_ATTR(parse_argv);
813
26
    COPY_WSTRLIST(argv);
814
26
    COPY_WSTRLIST(warnoptions);
815
26
    COPY_WSTRLIST(xoptions);
816
26
    COPY_WSTRLIST(module_search_paths);
817
26
    COPY_ATTR(module_search_paths_set);
818
819
26
    COPY_WSTR_ATTR(executable);
820
26
    COPY_WSTR_ATTR(base_executable);
821
26
    COPY_WSTR_ATTR(prefix);
822
26
    COPY_WSTR_ATTR(base_prefix);
823
26
    COPY_WSTR_ATTR(exec_prefix);
824
26
    COPY_WSTR_ATTR(base_exec_prefix);
825
826
26
    COPY_ATTR(site_import);
827
26
    COPY_ATTR(bytes_warning);
828
26
    COPY_ATTR(inspect);
829
26
    COPY_ATTR(interactive);
830
26
    COPY_ATTR(optimization_level);
831
26
    COPY_ATTR(parser_debug);
832
26
    COPY_ATTR(write_bytecode);
833
26
    COPY_ATTR(verbose);
834
26
    COPY_ATTR(quiet);
835
26
    COPY_ATTR(user_site_directory);
836
26
    COPY_ATTR(configure_c_stdio);
837
26
    COPY_ATTR(buffered_stdio);
838
26
    COPY_WSTR_ATTR(filesystem_encoding);
839
26
    COPY_WSTR_ATTR(filesystem_errors);
840
26
    COPY_WSTR_ATTR(stdio_encoding);
841
26
    COPY_WSTR_ATTR(stdio_errors);
842
#ifdef MS_WINDOWS
843
    COPY_ATTR(legacy_windows_stdio);
844
#endif
845
26
    COPY_ATTR(skip_source_first_line);
846
26
    COPY_WSTR_ATTR(run_command);
847
26
    COPY_WSTR_ATTR(run_module);
848
26
    COPY_WSTR_ATTR(run_filename);
849
26
    COPY_WSTR_ATTR(check_hash_pycs_mode);
850
26
    COPY_ATTR(pathconfig_warnings);
851
26
    COPY_ATTR(_init_main);
852
853
26
#undef COPY_ATTR
854
26
#undef COPY_WSTR_ATTR
855
26
#undef COPY_WSTRLIST
856
26
    return _PyStatus_OK();
857
26
}
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
91
{
970
91
    return _Py_GetEnv(config->use_environment, name);
971
91
}
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
39
{
983
39
    assert(*dest == NULL);
984
39
    assert(config->use_environment >= 0);
985
986
39
    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
39
    const char *var = getenv(name);
1001
39
    if (!var || var[0] == '\0') {
1002
26
        *dest = NULL;
1003
26
        return _PyStatus_OK();
1004
26
    }
1005
1006
13
    return config_set_bytes_string(config, dest, var, decode_err_msg);
1007
39
#endif
1008
39
}
1009
1010
1011
#define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \
1012
39
    config_get_env_dup(CONFIG, DEST, WNAME, NAME, "cannot decode " NAME)
1013
1014
1015
static void
1016
config_get_global_vars(PyConfig *config)
1017
13
{
1018
13
    if (config->_config_init != _PyConfig_INIT_COMPAT) {
1019
        /* Python and Isolated configuration ignore global variables */
1020
0
        return;
1021
0
    }
1022
1023
13
#define COPY_FLAG(ATTR, VALUE) \
1024
104
        if (config->ATTR == -1) { \
1025
104
            config->ATTR = VALUE; \
1026
104
        }
1027
13
#define COPY_NOT_FLAG(ATTR, VALUE) \
1028
78
        if (config->ATTR == -1) { \
1029
78
            config->ATTR = !(VALUE); \
1030
78
        }
1031
1032
13
    COPY_FLAG(isolated, Py_IsolatedFlag);
1033
13
    COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
1034
13
    COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
1035
13
    COPY_FLAG(inspect, Py_InspectFlag);
1036
13
    COPY_FLAG(interactive, Py_InteractiveFlag);
1037
13
    COPY_FLAG(optimization_level, Py_OptimizeFlag);
1038
13
    COPY_FLAG(parser_debug, Py_DebugFlag);
1039
13
    COPY_FLAG(verbose, Py_VerboseFlag);
1040
13
    COPY_FLAG(quiet, Py_QuietFlag);
1041
#ifdef MS_WINDOWS
1042
    COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
1043
#endif
1044
13
    COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);
1045
1046
13
    COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
1047
13
    COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
1048
13
    COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
1049
13
    COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
1050
1051
13
#undef COPY_FLAG
1052
13
#undef COPY_NOT_FLAG
1053
13
}
1054
1055
1056
/* Set Py_xxx global configuration variables from 'config' configuration. */
1057
static void
1058
config_set_global_vars(const PyConfig *config)
1059
26
{
1060
26
#define COPY_FLAG(ATTR, VAR) \
1061
208
        if (config->ATTR != -1) { \
1062
208
            VAR = config->ATTR; \
1063
208
        }
1064
26
#define COPY_NOT_FLAG(ATTR, VAR) \
1065
156
        if (config->ATTR != -1) { \
1066
156
            VAR = !config->ATTR; \
1067
156
        }
1068
1069
26
    COPY_FLAG(isolated, Py_IsolatedFlag);
1070
26
    COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
1071
26
    COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
1072
26
    COPY_FLAG(inspect, Py_InspectFlag);
1073
26
    COPY_FLAG(interactive, Py_InteractiveFlag);
1074
26
    COPY_FLAG(optimization_level, Py_OptimizeFlag);
1075
26
    COPY_FLAG(parser_debug, Py_DebugFlag);
1076
26
    COPY_FLAG(verbose, Py_VerboseFlag);
1077
26
    COPY_FLAG(quiet, Py_QuietFlag);
1078
#ifdef MS_WINDOWS
1079
    COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
1080
#endif
1081
26
    COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);
1082
1083
26
    COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
1084
26
    COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
1085
26
    COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
1086
26
    COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
1087
1088
    /* Random or non-zero hash seed */
1089
26
    Py_HashRandomizationFlag = (config->use_hash_seed == 0 ||
1090
0
                                config->hash_seed != 0);
1091
1092
26
#undef COPY_FLAG
1093
26
#undef COPY_NOT_FLAG
1094
26
}
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
13
{
1102
13
    PyStatus status;
1103
1104
    /* If Py_SetProgramName() was called, use its value */
1105
13
    const wchar_t *program_name = _Py_path_config.program_name;
1106
13
    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
13
    const PyWideStringList *argv = &config->argv;
1166
13
    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
13
    const wchar_t *default_program_name = L"python3";
1179
13
#endif
1180
13
    status = PyConfig_SetString(config, &config->program_name,
1181
13
                                default_program_name);
1182
13
    if (_PyStatus_EXCEPTION(status)) {
1183
0
        return status;
1184
0
    }
1185
13
    return _PyStatus_OK();
1186
13
}
1187
1188
static PyStatus
1189
config_init_executable(PyConfig *config)
1190
13
{
1191
13
    assert(config->executable == NULL);
1192
1193
    /* If Py_SetProgramFullPath() was called, use its value */
1194
13
    const wchar_t *program_full_path = _Py_path_config.program_full_path;
1195
13
    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
13
    return _PyStatus_OK();
1205
13
}
1206
1207
1208
static const wchar_t*
1209
config_get_xoption(const PyConfig *config, wchar_t *name)
1210
78
{
1211
78
    return _Py_get_xoption(&config->xoptions, name);
1212
78
}
1213
1214
1215
static PyStatus
1216
config_init_home(PyConfig *config)
1217
13
{
1218
13
    assert(config->home == NULL);
1219
1220
    /* If Py_SetPythonHome() was called, use its value */
1221
13
    wchar_t *home = _Py_path_config.home;
1222
13
    if (home) {
1223
13
        PyStatus status = PyConfig_SetString(config, &config->home, home);
1224
13
        if (_PyStatus_EXCEPTION(status)) {
1225
0
            return status;
1226
0
        }
1227
13
        return _PyStatus_OK();
1228
13
    }
1229
1230
0
    return CONFIG_GET_ENV_DUP(config, &config->home,
1231
13
                              L"PYTHONHOME", "PYTHONHOME");
1232
13
}
1233
1234
1235
static PyStatus
1236
config_init_hash_seed(PyConfig *config)
1237
13
{
1238
13
    const char *seed_text = config_get_env(config, "PYTHONHASHSEED");
1239
1240
13
    Py_BUILD_ASSERT(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc));
1241
    /* Convert a text seed to a numeric one */
1242
13
    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
13
    else {
1259
        /* Use a random hash */
1260
13
        config->use_hash_seed = 0;
1261
13
        config->hash_seed = 0;
1262
13
    }
1263
13
    return _PyStatus_OK();
1264
13
}
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
13
{
1288
13
    PyStatus status;
1289
13
    int use_env = config->use_environment;
1290
1291
    /* Get environment variables */
1292
13
    _Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG");
1293
13
    _Py_get_env_flag(use_env, &config->verbose, "PYTHONVERBOSE");
1294
13
    _Py_get_env_flag(use_env, &config->optimization_level, "PYTHONOPTIMIZE");
1295
13
    _Py_get_env_flag(use_env, &config->inspect, "PYTHONINSPECT");
1296
1297
13
    int dont_write_bytecode = 0;
1298
13
    _Py_get_env_flag(use_env, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
1299
13
    if (dont_write_bytecode) {
1300
0
        config->write_bytecode = 0;
1301
0
    }
1302
1303
13
    int no_user_site_directory = 0;
1304
13
    _Py_get_env_flag(use_env, &no_user_site_directory, "PYTHONNOUSERSITE");
1305
13
    if (no_user_site_directory) {
1306
13
        config->user_site_directory = 0;
1307
13
    }
1308
1309
13
    int unbuffered_stdio = 0;
1310
13
    _Py_get_env_flag(use_env, &unbuffered_stdio, "PYTHONUNBUFFERED");
1311
13
    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
13
    if (config_get_env(config, "PYTHONDUMPREFS")) {
1321
0
        config->dump_refs = 1;
1322
0
    }
1323
13
    if (config_get_env(config, "PYTHONMALLOCSTATS")) {
1324
0
        config->malloc_stats = 1;
1325
0
    }
1326
1327
13
    if (config->pythonpath_env == NULL) {
1328
13
        status = CONFIG_GET_ENV_DUP(config, &config->pythonpath_env,
1329
13
                                    L"PYTHONPATH", "PYTHONPATH");
1330
13
        if (_PyStatus_EXCEPTION(status)) {
1331
0
            return status;
1332
0
        }
1333
13
    }
1334
1335
13
    if (config->use_hash_seed < 0) {
1336
13
        status = config_init_hash_seed(config);
1337
13
        if (_PyStatus_EXCEPTION(status)) {
1338
0
            return status;
1339
0
        }
1340
13
    }
1341
1342
13
    return _PyStatus_OK();
1343
13
}
1344
1345
1346
static PyStatus
1347
config_init_tracemalloc(PyConfig *config)
1348
13
{
1349
13
    int nframe;
1350
13
    int valid;
1351
1352
13
    const char *env = config_get_env(config, "PYTHONTRACEMALLOC");
1353
13
    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
13
    const wchar_t *xoption = config_get_xoption(config, L"tracemalloc");
1367
13
    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
13
    return _PyStatus_OK();
1388
13
}
1389
1390
1391
static PyStatus
1392
config_init_pycache_prefix(PyConfig *config)
1393
13
{
1394
13
    assert(config->pycache_prefix == NULL);
1395
1396
13
    const wchar_t *xoption = config_get_xoption(config, L"pycache_prefix");
1397
13
    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
13
    return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix,
1414
13
                              L"PYTHONPYCACHEPREFIX",
1415
13
                              "PYTHONPYCACHEPREFIX");
1416
13
}
1417
1418
1419
static PyStatus
1420
config_read_complex_options(PyConfig *config)
1421
13
{
1422
    /* More complex options configured by env var and -X option */
1423
13
    if (config->faulthandler < 0) {
1424
13
        if (config_get_env(config, "PYTHONFAULTHANDLER")
1425
13
           || config_get_xoption(config, L"faulthandler")) {
1426
0
            config->faulthandler = 1;
1427
0
        }
1428
13
    }
1429
13
    if (config_get_env(config, "PYTHONPROFILEIMPORTTIME")
1430
13
       || config_get_xoption(config, L"importtime")) {
1431
0
        config->import_time = 1;
1432
0
    }
1433
1434
13
    PyStatus status;
1435
13
    if (config->tracemalloc < 0) {
1436
13
        status = config_init_tracemalloc(config);
1437
13
        if (_PyStatus_EXCEPTION(status)) {
1438
0
            return status;
1439
0
        }
1440
13
    }
1441
1442
13
    if (config->pycache_prefix == NULL) {
1443
13
        status = config_init_pycache_prefix(config);
1444
13
        if (_PyStatus_EXCEPTION(status)) {
1445
0
            return status;
1446
0
        }
1447
13
    }
1448
13
    return _PyStatus_OK();
1449
13
}
1450
1451
1452
static const wchar_t *
1453
config_get_stdio_errors(const PyConfig *config)
1454
13
{
1455
13
#ifndef MS_WINDOWS
1456
13
    const char *loc = setlocale(LC_CTYPE, NULL);
1457
13
    if (loc != NULL) {
1458
        /* surrogateescape is the default in the legacy C and POSIX locales */
1459
13
        if (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0) {
1460
13
            return L"surrogateescape";
1461
13
        }
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
13
}
1477
1478
1479
static PyStatus
1480
config_get_locale_encoding(PyConfig *config, wchar_t **locale_encoding)
1481
26
{
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
26
    const char *encoding = nl_langinfo(CODESET);
1490
26
    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
26
    return CONFIG_SET_BYTES_STR(config,
1496
26
                                locale_encoding, encoding,
1497
26
                                "nl_langinfo(CODESET)");
1498
26
#endif
1499
26
}
1500
1501
1502
static PyStatus
1503
config_init_stdio_encoding(PyConfig *config,
1504
                           const PyPreConfig *preconfig)
1505
13
{
1506
13
    PyStatus status;
1507
1508
    /* If Py_SetStandardStreamEncoding() have been called, use these
1509
        parameters. */
1510
13
    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
13
    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
13
    if (config->stdio_encoding != NULL && config->stdio_errors != NULL) {
1529
0
        return _PyStatus_OK();
1530
0
    }
1531
1532
    /* PYTHONIOENCODING environment variable */
1533
13
    const char *opt = config_get_env(config, "PYTHONIOENCODING");
1534
13
    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
13
    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
13
    if (config->stdio_encoding == NULL) {
1603
13
        status = config_get_locale_encoding(config, &config->stdio_encoding);
1604
13
        if (_PyStatus_EXCEPTION(status)) {
1605
0
            return status;
1606
0
        }
1607
13
    }
1608
13
    if (config->stdio_errors == NULL) {
1609
13
        const wchar_t *errors = config_get_stdio_errors(config);
1610
13
        assert(errors != NULL);
1611
1612
13
        status = PyConfig_SetString(config, &config->stdio_errors, errors);
1613
13
        if (_PyStatus_EXCEPTION(status)) {
1614
0
            return status;
1615
0
        }
1616
13
    }
1617
1618
13
    return _PyStatus_OK();
1619
13
}
1620
1621
1622
static PyStatus
1623
config_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig)
1624
13
{
1625
13
    PyStatus status;
1626
1627
13
    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
13
        if (preconfig->utf8_mode) {
1641
0
            status = PyConfig_SetString(config, &config->filesystem_encoding,
1642
0
                                        L"utf-8");
1643
0
        }
1644
13
#ifndef MS_WINDOWS
1645
13
        else if (_Py_GetForceASCII()) {
1646
0
            status = PyConfig_SetString(config, &config->filesystem_encoding,
1647
0
                                        L"ascii");
1648
0
        }
1649
13
#endif
1650
13
        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
13
            status = config_get_locale_encoding(config,
1657
13
                                                &config->filesystem_encoding);
1658
13
#endif
1659
13
        }
1660
13
#endif   /* !_Py_FORCE_UTF8_FS_ENCODING */
1661
1662
13
        if (_PyStatus_EXCEPTION(status)) {
1663
0
            return status;
1664
0
        }
1665
13
    }
1666
1667
13
    if (config->filesystem_errors == NULL) {
1668
13
        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
13
        errors = L"surrogateescape";
1678
13
#endif
1679
13
        status = PyConfig_SetString(config, &config->filesystem_errors, errors);
1680
13
        if (_PyStatus_EXCEPTION(status)) {
1681
0
            return status;
1682
0
        }
1683
13
    }
1684
13
    return _PyStatus_OK();
1685
13
}
1686
1687
1688
static PyStatus
1689
config_read(PyConfig *config)
1690
13
{
1691
13
    PyStatus status;
1692
13
    const PyPreConfig *preconfig = &_PyRuntime.preconfig;
1693
1694
13
    if (config->use_environment) {
1695
13
        status = config_read_env_vars(config);
1696
13
        if (_PyStatus_EXCEPTION(status)) {
1697
0
            return status;
1698
0
        }
1699
13
    }
1700
1701
    /* -X options */
1702
13
    if (config_get_xoption(config, L"showrefcount")) {
1703
0
        config->show_ref_count = 1;
1704
0
    }
1705
13
    if (config_get_xoption(config, L"showalloccount")) {
1706
0
        config->show_alloc_count = 1;
1707
0
    }
1708
1709
13
    status = config_read_complex_options(config);
1710
13
    if (_PyStatus_EXCEPTION(status)) {
1711
0
        return status;
1712
0
    }
1713
1714
13
    if (config->home == NULL) {
1715
13
        status = config_init_home(config);
1716
13
        if (_PyStatus_EXCEPTION(status)) {
1717
0
            return status;
1718
0
        }
1719
13
    }
1720
1721
13
    if (config->executable == NULL) {
1722
13
        status = config_init_executable(config);
1723
13
        if (_PyStatus_EXCEPTION(status)) {
1724
0
            return status;
1725
0
        }
1726
13
    }
1727
1728
13
    if (config->_install_importlib) {
1729
13
        status = _PyConfig_InitPathConfig(config);
1730
13
        if (_PyStatus_EXCEPTION(status)) {
1731
0
            return status;
1732
0
        }
1733
13
    }
1734
1735
    /* default values */
1736
13
    if (config->dev_mode) {
1737
0
        if (config->faulthandler < 0) {
1738
0
            config->faulthandler = 1;
1739
0
        }
1740
0
    }
1741
13
    if (config->faulthandler < 0) {
1742
13
        config->faulthandler = 0;
1743
13
    }
1744
13
    if (config->tracemalloc < 0) {
1745
13
        config->tracemalloc = 0;
1746
13
    }
1747
13
    if (config->use_hash_seed < 0) {
1748
0
        config->use_hash_seed = 0;
1749
0
        config->hash_seed = 0;
1750
0
    }
1751
1752
13
    if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) {
1753
13
        status = config_init_fs_encoding(config, preconfig);
1754
13
        if (_PyStatus_EXCEPTION(status)) {
1755
0
            return status;
1756
0
        }
1757
13
    }
1758
1759
13
    status = config_init_stdio_encoding(config, preconfig);
1760
13
    if (_PyStatus_EXCEPTION(status)) {
1761
0
        return status;
1762
0
    }
1763
1764
13
    if (config->argv.length < 1) {
1765
        /* Ensure at least one (empty) argument is seen */
1766
13
        status = PyWideStringList_Append(&config->argv, L"");
1767
13
        if (_PyStatus_EXCEPTION(status)) {
1768
0
            return status;
1769
0
        }
1770
13
    }
1771
1772
13
    if (config->check_hash_pycs_mode == NULL) {
1773
13
        status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
1774
13
                                    L"default");
1775
13
        if (_PyStatus_EXCEPTION(status)) {
1776
0
            return status;
1777
0
        }
1778
13
    }
1779
1780
13
    if (config->configure_c_stdio < 0) {
1781
0
        config->configure_c_stdio = 1;
1782
0
    }
1783
1784
13
    return _PyStatus_OK();
1785
13
}
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
26
{
1832
26
    config_set_global_vars(config);
1833
1834
26
    if (config->configure_c_stdio) {
1835
0
        config_init_stdio(config);
1836
0
    }
1837
1838
    /* Write the new pre-configuration into _PyRuntime */
1839
26
    PyPreConfig *preconfig = &runtime->preconfig;
1840
26
    preconfig->isolated = config->isolated;
1841
26
    preconfig->use_environment = config->use_environment;
1842
26
    preconfig->dev_mode = config->dev_mode;
1843
26
}
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
13
{
2061
13
    PyStatus status;
2062
    /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */
2063
13
    wchar_t *env = NULL;
2064
13
    status = CONFIG_GET_ENV_DUP(config, &env,
2065
13
                             L"PYTHONWARNINGS", "PYTHONWARNINGS");
2066
13
    if (_PyStatus_EXCEPTION(status)) {
2067
0
        return status;
2068
0
    }
2069
2070
    /* env var is not set or is empty */
2071
13
    if (env == NULL) {
2072
13
        return _PyStatus_OK();
2073
13
    }
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
39
{
2116
39
    const Py_ssize_t len = options2->length;
2117
39
    wchar_t *const *items = options2->items;
2118
2119
39
    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
39
    return _PyStatus_OK();
2126
39
}
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
13
{
2135
13
    PyStatus status;
2136
13
    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
13
    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
13
    status = warnoptions_extend(config, &options, env_warnoptions);
2163
13
    if (_PyStatus_EXCEPTION(status)) {
2164
0
        goto error;
2165
0
    }
2166
2167
13
    status = warnoptions_extend(config, &options, cmdline_warnoptions);
2168
13
    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
13
    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
13
    status = warnoptions_extend(config, &options, sys_warnoptions);
2191
13
    if (_PyStatus_EXCEPTION(status)) {
2192
0
        goto error;
2193
0
    }
2194
2195
    /* Always add all PyConfig.warnoptions options */
2196
13
    status = _PyWideStringList_Extend(&options, &config->warnoptions);
2197
13
    if (_PyStatus_EXCEPTION(status)) {
2198
0
        goto error;
2199
0
    }
2200
2201
13
    _PyWideStringList_Clear(&config->warnoptions);
2202
13
    config->warnoptions = options;
2203
13
    return _PyStatus_OK();
2204
2205
0
error:
2206
0
    _PyWideStringList_Clear(&options);
2207
0
    return status;
2208
13
}
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
13
{
2264
13
    PyStatus status;
2265
2266
13
    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
13
    PyPreConfig preconfig;
2273
2274
13
    status = _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig);
2275
13
    if (_PyStatus_EXCEPTION(status)) {
2276
0
        return status;
2277
0
    }
2278
2279
13
    _PyPreConfig_GetConfig(&preconfig, config);
2280
2281
13
    status = _PyPreCmdline_Read(precmdline, &preconfig);
2282
13
    if (_PyStatus_EXCEPTION(status)) {
2283
0
        return status;
2284
0
    }
2285
2286
13
    status = _PyPreCmdline_SetConfig(precmdline, config);
2287
13
    if (_PyStatus_EXCEPTION(status)) {
2288
0
        return status;
2289
0
    }
2290
13
    return _PyStatus_OK();
2291
13
}
2292
2293
2294
static PyStatus
2295
config_read_cmdline(PyConfig *config)
2296
13
{
2297
13
    PyStatus status;
2298
13
    PyWideStringList cmdline_warnoptions = _PyWideStringList_INIT;
2299
13
    PyWideStringList env_warnoptions = _PyWideStringList_INIT;
2300
13
    PyWideStringList sys_warnoptions = _PyWideStringList_INIT;
2301
2302
13
    if (config->parse_argv < 0) {
2303
0
        config->parse_argv = 1;
2304
0
    }
2305
2306
13
    if (config->program_name == NULL) {
2307
13
        status = config_init_program_name(config);
2308
13
        if (_PyStatus_EXCEPTION(status)) {
2309
0
            return status;
2310
0
        }
2311
13
    }
2312
2313
13
    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
13
    if (config->use_environment) {
2327
13
        status = config_init_env_warnoptions(config, &env_warnoptions);
2328
13
        if (_PyStatus_EXCEPTION(status)) {
2329
0
            goto done;
2330
0
        }
2331
13
    }
2332
2333
    /* Handle early PySys_AddWarnOption() calls */
2334
13
    status = _PySys_ReadPreinitWarnOptions(&sys_warnoptions);
2335
13
    if (_PyStatus_EXCEPTION(status)) {
2336
0
        goto done;
2337
0
    }
2338
2339
13
    status = config_init_warnoptions(config,
2340
13
                                     &cmdline_warnoptions,
2341
13
                                     &env_warnoptions,
2342
13
                                     &sys_warnoptions);
2343
13
    if (_PyStatus_EXCEPTION(status)) {
2344
0
        goto done;
2345
0
    }
2346
2347
13
    status = _PyStatus_OK();
2348
2349
13
done:
2350
13
    _PyWideStringList_Clear(&cmdline_warnoptions);
2351
13
    _PyWideStringList_Clear(&env_warnoptions);
2352
13
    _PyWideStringList_Clear(&sys_warnoptions);
2353
13
    return status;
2354
13
}
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
13
{
2422
13
    PyStatus status;
2423
13
    PyWideStringList orig_argv = _PyWideStringList_INIT;
2424
2425
13
    status = _Py_PreInitializeFromConfig(config, NULL);
2426
13
    if (_PyStatus_EXCEPTION(status)) {
2427
0
        return status;
2428
0
    }
2429
2430
13
    config_get_global_vars(config);
2431
2432
13
    if (_PyWideStringList_Copy(&orig_argv, &config->argv) < 0) {
2433
0
        return _PyStatus_NO_MEMORY();
2434
0
    }
2435
2436
13
    _PyPreCmdline precmdline = _PyPreCmdline_INIT;
2437
13
    status = core_read_precmdline(config, &precmdline);
2438
13
    if (_PyStatus_EXCEPTION(status)) {
2439
0
        goto done;
2440
0
    }
2441
2442
13
    assert(config->isolated >= 0);
2443
13
    if (config->isolated) {
2444
0
        config->use_environment = 0;
2445
0
        config->user_site_directory = 0;
2446
0
    }
2447
2448
13
    status = config_read_cmdline(config);
2449
13
    if (_PyStatus_EXCEPTION(status)) {
2450
0
        goto done;
2451
0
    }
2452
2453
    /* Handle early PySys_AddXOption() calls */
2454
13
    status = _PySys_ReadPreinitXOptions(config);
2455
13
    if (_PyStatus_EXCEPTION(status)) {
2456
0
        goto done;
2457
0
    }
2458
2459
13
    status = config_read(config);
2460
13
    if (_PyStatus_EXCEPTION(status)) {
2461
0
        goto done;
2462
0
    }
2463
2464
13
    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
13
    assert(config->isolated >= 0);
2471
13
    assert(config->use_environment >= 0);
2472
13
    assert(config->dev_mode >= 0);
2473
13
    assert(config->install_signal_handlers >= 0);
2474
13
    assert(config->use_hash_seed >= 0);
2475
13
    assert(config->faulthandler >= 0);
2476
13
    assert(config->tracemalloc >= 0);
2477
13
    assert(config->site_import >= 0);
2478
13
    assert(config->bytes_warning >= 0);
2479
13
    assert(config->inspect >= 0);
2480
13
    assert(config->interactive >= 0);
2481
13
    assert(config->optimization_level >= 0);
2482
13
    assert(config->parser_debug >= 0);
2483
13
    assert(config->write_bytecode >= 0);
2484
13
    assert(config->verbose >= 0);
2485
13
    assert(config->quiet >= 0);
2486
13
    assert(config->user_site_directory >= 0);
2487
13
    assert(config->parse_argv >= 0);
2488
13
    assert(config->configure_c_stdio >= 0);
2489
13
    assert(config->buffered_stdio >= 0);
2490
13
    assert(config->program_name != NULL);
2491
13
    assert(_PyWideStringList_CheckConsistency(&config->argv));
2492
    /* sys.argv must be non-empty: empty argv is replaced with [''] */
2493
13
    assert(config->argv.length >= 1);
2494
13
    assert(_PyWideStringList_CheckConsistency(&config->xoptions));
2495
13
    assert(_PyWideStringList_CheckConsistency(&config->warnoptions));
2496
13
    assert(_PyWideStringList_CheckConsistency(&config->module_search_paths));
2497
13
    if (config->_install_importlib) {
2498
13
        assert(config->module_search_paths_set != 0);
2499
        /* don't check config->module_search_paths */
2500
13
        assert(config->executable != NULL);
2501
13
        assert(config->base_executable != NULL);
2502
13
        assert(config->prefix != NULL);
2503
13
        assert(config->base_prefix != NULL);
2504
13
        assert(config->exec_prefix != NULL);
2505
13
        assert(config->base_exec_prefix != NULL);
2506
13
    }
2507
13
    assert(config->filesystem_encoding != NULL);
2508
13
    assert(config->filesystem_errors != NULL);
2509
13
    assert(config->stdio_encoding != NULL);
2510
13
    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
13
    assert(!(config->run_command != NULL && config->run_module != NULL));
2516
13
    assert(config->check_hash_pycs_mode != NULL);
2517
13
    assert(config->_install_importlib >= 0);
2518
13
    assert(config->pathconfig_warnings >= 0);
2519
2520
13
    status = _PyStatus_OK();
2521
2522
13
done:
2523
13
    _PyWideStringList_Clear(&orig_argv);
2524
13
    _PyPreCmdline_Clear(&precmdline);
2525
13
    return status;
2526
13
}
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
}