Coverage Report

Created: 2025-07-04 06:49

/src/cpython/Python/initconfig.c
Line
Count
Source (jump to first uncovered line)
1
#include "Python.h"
2
#include "pycore_fileutils.h"     // _Py_HasFileSystemDefaultEncodeErrors
3
#include "pycore_getopt.h"        // _PyOS_GetOpt()
4
#include "pycore_initconfig.h"    // _PyStatus_OK()
5
#include "pycore_interp.h"        // _PyInterpreterState.runtime
6
#include "pycore_long.h"          // _PY_LONG_MAX_STR_DIGITS_THRESHOLD
7
#include "pycore_pathconfig.h"    // _Py_path_config
8
#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
9
#include "pycore_pylifecycle.h"   // _Py_PreInitializeFromConfig()
10
#include "pycore_pymem.h"         // _PyMem_DefaultRawMalloc()
11
#include "pycore_pyhash.h"        // _Py_HashSecret
12
#include "pycore_pystate.h"       // _PyThreadState_GET()
13
#include "pycore_pystats.h"       // _Py_StatsOn()
14
#include "pycore_sysmodule.h"     // _PySys_SetIntMaxStrDigits()
15
16
#include "osdefs.h"               // DELIM
17
18
#include <locale.h>               // setlocale()
19
#include <stdlib.h>               // getenv()
20
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
21
#  ifdef HAVE_IO_H
22
#    include <io.h>
23
#  endif
24
#  ifdef HAVE_FCNTL_H
25
#    include <fcntl.h>            // O_BINARY
26
#  endif
27
#endif
28
29
#ifdef __APPLE__
30
/* Enable system log by default on non-macOS Apple platforms */
31
#  if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
32
#define USE_SYSTEM_LOGGER_DEFAULT 1;
33
#  else
34
#define USE_SYSTEM_LOGGER_DEFAULT 0;
35
#  endif
36
#endif
37
38
#include "config_common.h"
39
40
/* --- PyConfig setters ------------------------------------------- */
41
42
typedef PyObject* (*config_sys_flag_setter) (int value);
43
44
static PyObject*
45
config_sys_flag_long(int value)
46
0
{
47
0
    return PyLong_FromLong(value);
48
0
}
49
50
static PyObject*
51
config_sys_flag_not(int value)
52
0
{
53
0
    value = (!value);
54
0
    return config_sys_flag_long(value);
55
0
}
56
57
/* --- PyConfig spec ---------------------------------------------- */
58
59
typedef enum {
60
    PyConfig_MEMBER_INT = 0,
61
    PyConfig_MEMBER_UINT = 1,
62
    PyConfig_MEMBER_ULONG = 2,
63
    PyConfig_MEMBER_BOOL = 3,
64
65
    PyConfig_MEMBER_WSTR = 10,
66
    PyConfig_MEMBER_WSTR_OPT = 11,
67
    PyConfig_MEMBER_WSTR_LIST = 12,
68
} PyConfigMemberType;
69
70
typedef enum {
71
    // Option which cannot be get or set by PyConfig_Get() and PyConfig_Set()
72
    PyConfig_MEMBER_INIT_ONLY = 0,
73
74
    // Option which cannot be set by PyConfig_Set()
75
    PyConfig_MEMBER_READ_ONLY = 1,
76
77
    // Public option: can be get and set by PyConfig_Get() and PyConfig_Set()
78
    PyConfig_MEMBER_PUBLIC = 2,
79
} PyConfigMemberVisibility;
80
81
typedef struct {
82
    const char *attr;
83
    int flag_index;
84
    config_sys_flag_setter flag_setter;
85
} PyConfigSysSpec;
86
87
typedef struct {
88
    const char *name;
89
    size_t offset;
90
    PyConfigMemberType type;
91
    PyConfigMemberVisibility visibility;
92
    PyConfigSysSpec sys;
93
} PyConfigSpec;
94
95
#define SPEC(MEMBER, TYPE, VISIBILITY, sys) \
96
    {#MEMBER, offsetof(PyConfig, MEMBER), \
97
     PyConfig_MEMBER_##TYPE, PyConfig_MEMBER_##VISIBILITY, sys}
98
99
#define SYS_ATTR(name) {name, -1, NULL}
100
#define SYS_FLAG_SETTER(index, setter) {NULL, index, setter}
101
#define SYS_FLAG(index) SYS_FLAG_SETTER(index, NULL)
102
#define NO_SYS SYS_ATTR(NULL)
103
104
// Update _test_embed_set_config when adding new members
105
static const PyConfigSpec PYCONFIG_SPEC[] = {
106
    // --- Public options -----------
107
108
    SPEC(argv, WSTR_LIST, PUBLIC, SYS_ATTR("argv")),
109
    SPEC(base_exec_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("base_exec_prefix")),
110
    SPEC(base_executable, WSTR_OPT, PUBLIC, SYS_ATTR("_base_executable")),
111
    SPEC(base_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("base_prefix")),
112
    SPEC(bytes_warning, UINT, PUBLIC, SYS_FLAG(9)),
113
    SPEC(cpu_count, INT, PUBLIC, NO_SYS),
114
    SPEC(exec_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("exec_prefix")),
115
    SPEC(executable, WSTR_OPT, PUBLIC, SYS_ATTR("executable")),
116
    SPEC(inspect, BOOL, PUBLIC, SYS_FLAG(1)),
117
    SPEC(int_max_str_digits, UINT, PUBLIC, NO_SYS),
118
    SPEC(interactive, BOOL, PUBLIC, SYS_FLAG(2)),
119
    SPEC(module_search_paths, WSTR_LIST, PUBLIC, SYS_ATTR("path")),
120
    SPEC(optimization_level, UINT, PUBLIC, SYS_FLAG(3)),
121
    SPEC(parser_debug, BOOL, PUBLIC, SYS_FLAG(0)),
122
    SPEC(platlibdir, WSTR, PUBLIC, SYS_ATTR("platlibdir")),
123
    SPEC(prefix, WSTR_OPT, PUBLIC, SYS_ATTR("prefix")),
124
    SPEC(pycache_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("pycache_prefix")),
125
    SPEC(quiet, BOOL, PUBLIC, SYS_FLAG(10)),
126
    SPEC(stdlib_dir, WSTR_OPT, PUBLIC, SYS_ATTR("_stdlib_dir")),
127
    SPEC(use_environment, BOOL, PUBLIC, SYS_FLAG_SETTER(7, config_sys_flag_not)),
128
    SPEC(verbose, UINT, PUBLIC, SYS_FLAG(8)),
129
    SPEC(warnoptions, WSTR_LIST, PUBLIC, SYS_ATTR("warnoptions")),
130
    SPEC(write_bytecode, BOOL, PUBLIC, SYS_FLAG_SETTER(4, config_sys_flag_not)),
131
    SPEC(xoptions, WSTR_LIST, PUBLIC, SYS_ATTR("_xoptions")),
132
133
    // --- Read-only options -----------
134
135
#ifdef Py_STATS
136
    SPEC(_pystats, BOOL, READ_ONLY, NO_SYS),
137
#endif
138
    SPEC(buffered_stdio, BOOL, READ_ONLY, NO_SYS),
139
    SPEC(check_hash_pycs_mode, WSTR, READ_ONLY, NO_SYS),
140
    SPEC(code_debug_ranges, BOOL, READ_ONLY, NO_SYS),
141
    SPEC(configure_c_stdio, BOOL, READ_ONLY, NO_SYS),
142
    SPEC(dev_mode, BOOL, READ_ONLY, NO_SYS),  // sys.flags.dev_mode
143
    SPEC(dump_refs, BOOL, READ_ONLY, NO_SYS),
144
    SPEC(dump_refs_file, WSTR_OPT, READ_ONLY, NO_SYS),
145
#ifdef Py_GIL_DISABLED
146
    SPEC(enable_gil, INT, READ_ONLY, NO_SYS),
147
    SPEC(tlbc_enabled, INT, READ_ONLY, NO_SYS),
148
#endif
149
    SPEC(faulthandler, BOOL, READ_ONLY, NO_SYS),
150
    SPEC(filesystem_encoding, WSTR, READ_ONLY, NO_SYS),
151
    SPEC(filesystem_errors, WSTR, READ_ONLY, NO_SYS),
152
    SPEC(hash_seed, ULONG, READ_ONLY, NO_SYS),
153
    SPEC(home, WSTR_OPT, READ_ONLY, NO_SYS),
154
    SPEC(thread_inherit_context, INT, READ_ONLY, NO_SYS),
155
    SPEC(context_aware_warnings, INT, READ_ONLY, NO_SYS),
156
    SPEC(import_time, UINT, READ_ONLY, NO_SYS),
157
    SPEC(install_signal_handlers, BOOL, READ_ONLY, NO_SYS),
158
    SPEC(isolated, BOOL, READ_ONLY, NO_SYS),  // sys.flags.isolated
159
#ifdef MS_WINDOWS
160
    SPEC(legacy_windows_stdio, BOOL, READ_ONLY, NO_SYS),
161
#endif
162
    SPEC(malloc_stats, BOOL, READ_ONLY, NO_SYS),
163
    SPEC(orig_argv, WSTR_LIST, READ_ONLY, SYS_ATTR("orig_argv")),
164
    SPEC(parse_argv, BOOL, READ_ONLY, NO_SYS),
165
    SPEC(pathconfig_warnings, BOOL, READ_ONLY, NO_SYS),
166
    SPEC(perf_profiling, UINT, READ_ONLY, NO_SYS),
167
    SPEC(remote_debug, BOOL, READ_ONLY, NO_SYS),
168
    SPEC(program_name, WSTR, READ_ONLY, NO_SYS),
169
    SPEC(run_command, WSTR_OPT, READ_ONLY, NO_SYS),
170
    SPEC(run_filename, WSTR_OPT, READ_ONLY, NO_SYS),
171
    SPEC(run_module, WSTR_OPT, READ_ONLY, NO_SYS),
172
#ifdef Py_DEBUG
173
    SPEC(run_presite, WSTR_OPT, READ_ONLY, NO_SYS),
174
#endif
175
    SPEC(safe_path, BOOL, READ_ONLY, NO_SYS),
176
    SPEC(show_ref_count, BOOL, READ_ONLY, NO_SYS),
177
    SPEC(site_import, BOOL, READ_ONLY, NO_SYS),  // sys.flags.no_site
178
    SPEC(skip_source_first_line, BOOL, READ_ONLY, NO_SYS),
179
    SPEC(stdio_encoding, WSTR, READ_ONLY, NO_SYS),
180
    SPEC(stdio_errors, WSTR, READ_ONLY, NO_SYS),
181
    SPEC(tracemalloc, UINT, READ_ONLY, NO_SYS),
182
    SPEC(use_frozen_modules, BOOL, READ_ONLY, NO_SYS),
183
    SPEC(use_hash_seed, BOOL, READ_ONLY, NO_SYS),
184
#ifdef __APPLE__
185
    SPEC(use_system_logger, BOOL, READ_ONLY, NO_SYS),
186
#endif
187
    SPEC(user_site_directory, BOOL, READ_ONLY, NO_SYS),  // sys.flags.no_user_site
188
    SPEC(warn_default_encoding, BOOL, READ_ONLY, NO_SYS),
189
190
    // --- Init-only options -----------
191
192
    SPEC(_config_init, UINT, INIT_ONLY, NO_SYS),
193
    SPEC(_init_main, BOOL, INIT_ONLY, NO_SYS),
194
    SPEC(_install_importlib, BOOL, INIT_ONLY, NO_SYS),
195
    SPEC(_is_python_build, BOOL, INIT_ONLY, NO_SYS),
196
    SPEC(module_search_paths_set, BOOL, INIT_ONLY, NO_SYS),
197
    SPEC(pythonpath_env, WSTR_OPT, INIT_ONLY, NO_SYS),
198
    SPEC(sys_path_0, WSTR_OPT, INIT_ONLY, NO_SYS),
199
200
    // Array terminator
201
    {NULL, 0, 0, 0, NO_SYS},
202
};
203
204
#undef SPEC
205
#define SPEC(MEMBER, TYPE, VISIBILITY) \
206
    {#MEMBER, offsetof(PyPreConfig, MEMBER), PyConfig_MEMBER_##TYPE, \
207
     PyConfig_MEMBER_##VISIBILITY, NO_SYS}
208
209
static const PyConfigSpec PYPRECONFIG_SPEC[] = {
210
    // --- Read-only options -----------
211
212
    SPEC(allocator, INT, READ_ONLY),
213
    SPEC(coerce_c_locale, BOOL, READ_ONLY),
214
    SPEC(coerce_c_locale_warn, BOOL, READ_ONLY),
215
    SPEC(configure_locale, BOOL, READ_ONLY),
216
#ifdef MS_WINDOWS
217
    SPEC(legacy_windows_fs_encoding, BOOL, READ_ONLY),
218
#endif
219
    SPEC(utf8_mode, BOOL, READ_ONLY),
220
221
    // --- Init-only options -----------
222
    // Members already present in PYCONFIG_SPEC
223
224
    SPEC(_config_init, INT, INIT_ONLY),
225
    SPEC(dev_mode, BOOL, INIT_ONLY),
226
    SPEC(isolated, BOOL, INIT_ONLY),
227
    SPEC(parse_argv, BOOL, INIT_ONLY),
228
    SPEC(use_environment, BOOL, INIT_ONLY),
229
230
    // Array terminator
231
    {NULL, 0, 0, 0, NO_SYS},
232
};
233
234
#undef SPEC
235
#undef SYS_ATTR
236
#undef SYS_FLAG_SETTER
237
#undef SYS_FLAG
238
#undef NO_SYS
239
240
241
// Forward declarations
242
static PyObject*
243
config_get(const PyConfig *config, const PyConfigSpec *spec,
244
           int use_sys);
245
246
247
/* --- Command line options --------------------------------------- */
248
249
/* Short usage message (with %s for argv0) */
250
static const char usage_line[] =
251
"usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
252
253
/* Long help message */
254
/* Lines sorted by option name; keep in sync with usage_envvars* below */
255
static const char usage_help[] = "\
256
Options (and corresponding environment variables):\n\
257
-b     : issue warnings about converting bytes/bytearray to str and comparing\n\
258
         bytes/bytearray with str or bytes with int. (-bb: issue errors)\n\
259
-B     : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x\n\
260
-c cmd : program passed in as string (terminates option list)\n\
261
-d     : turn on parser debugging output (for experts only, only works on\n\
262
         debug builds); also PYTHONDEBUG=x\n\
263
-E     : ignore PYTHON* environment variables (such as PYTHONPATH)\n\
264
-h     : print this help message and exit (also -? or --help)\n\
265
-i     : inspect interactively after running script; forces a prompt even\n\
266
         if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\
267
-I     : isolate Python from the user's environment (implies -E, -P and -s)\n\
268
-m mod : run library module as a script (terminates option list)\n\
269
-O     : remove assert and __debug__-dependent statements; add .opt-1 before\n\
270
         .pyc extension; also PYTHONOPTIMIZE=x\n\
271
-OO    : do -O changes and also discard docstrings; add .opt-2 before\n\
272
         .pyc extension\n\
273
-P     : don't prepend a potentially unsafe path to sys.path; also\n\
274
         PYTHONSAFEPATH\n\
275
-q     : don't print version and copyright messages on interactive startup\n\
276
-s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE=x\n\
277
-S     : don't imply 'import site' on initialization\n\
278
-u     : force the stdout and stderr streams to be unbuffered;\n\
279
         this option has no effect on stdin; also PYTHONUNBUFFERED=x\n\
280
-v     : verbose (trace import statements); also PYTHONVERBOSE=x\n\
281
         can be supplied multiple times to increase verbosity\n\
282
-V     : print the Python version number and exit (also --version)\n\
283
         when given twice, print more information about the build\n\
284
-W arg : warning control; arg is action:message:category:module:lineno\n\
285
         also PYTHONWARNINGS=arg\n\
286
-x     : skip first line of source, allowing use of non-Unix forms of #!cmd\n\
287
-X opt : set implementation-specific option\n\
288
--check-hash-based-pycs always|default|never:\n\
289
         control how Python invalidates hash-based .pyc files\n\
290
--help-env: print help about Python environment variables and exit\n\
291
--help-xoptions: print help about implementation-specific -X options and exit\n\
292
--help-all: print complete help information and exit\n\
293
\n\
294
Arguments:\n\
295
file   : program read from script file\n\
296
-      : program read from stdin (default; interactive mode if a tty)\n\
297
arg ...: arguments passed to program in sys.argv[1:]\n\
298
";
299
300
static const char usage_xoptions[] = "\
301
The following implementation-specific options are available:\n\
302
-X cpu_count=N: override the return value of os.cpu_count();\n\
303
         -X cpu_count=default cancels overriding; also PYTHON_CPU_COUNT\n\
304
-X dev : enable Python Development Mode; also PYTHONDEVMODE\n\
305
-X faulthandler: dump the Python traceback on fatal errors;\n\
306
         also PYTHONFAULTHANDLER\n\
307
-X frozen_modules=[on|off]: whether to use frozen modules; the default is \"on\"\n\
308
         for installed Python and \"off\" for a local build;\n\
309
         also PYTHON_FROZEN_MODULES\n\
310
"
311
#ifdef Py_GIL_DISABLED
312
"-X gil=[0|1]: enable (1) or disable (0) the GIL; also PYTHON_GIL\n"
313
#endif
314
"\
315
-X importtime[=2]: show how long each import takes; use -X importtime=2 to\
316
         log imports of already-loaded modules; also PYTHONPROFILEIMPORTTIME\n\
317
-X int_max_str_digits=N: limit the size of int<->str conversions;\n\
318
         0 disables the limit; also PYTHONINTMAXSTRDIGITS\n\
319
-X no_debug_ranges: don't include extra location information in code objects;\n\
320
         also PYTHONNODEBUGRANGES\n\
321
-X perf: support the Linux \"perf\" profiler; also PYTHONPERFSUPPORT=1\n\
322
-X perf_jit: support the Linux \"perf\" profiler with DWARF support;\n\
323
         also PYTHON_PERF_JIT_SUPPORT=1\n\
324
-X disable-remote-debug: disable remote debugging; also PYTHON_DISABLE_REMOTE_DEBUG\n\
325
"
326
#ifdef Py_DEBUG
327
"-X presite=MOD: import this module before site; also PYTHON_PRESITE\n"
328
#endif
329
"\
330
-X pycache_prefix=PATH: write .pyc files to a parallel tree instead of to the\n\
331
         code tree; also PYTHONPYCACHEPREFIX\n\
332
"
333
#ifdef Py_STATS
334
"-X pystats: enable pystats collection at startup; also PYTHONSTATS\n"
335
#endif
336
"\
337
-X showrefcount: output the total reference count and number of used\n\
338
         memory blocks when the program finishes or after each statement in\n\
339
         the interactive interpreter; only works on debug builds\n"
340
#ifdef Py_GIL_DISABLED
341
"-X tlbc=[0|1]: enable (1) or disable (0) thread-local bytecode. Also\n\
342
         PYTHON_TLBC\n"
343
#endif
344
"\
345
-X thread_inherit_context=[0|1]: enable (1) or disable (0) threads inheriting\n\
346
         context vars by default; enabled by default in the free-threaded\n\
347
         build and disabled otherwise; also PYTHON_THREAD_INHERIT_CONTEXT\n\
348
-X context_aware_warnings=[0|1]: if true (1) then the warnings module will\n\
349
         use a context variables; if false (0) then the warnings module will\n\
350
         use module globals, which is not concurrent-safe; set to true for\n\
351
         free-threaded builds and false otherwise; also\n\
352
         PYTHON_CONTEXT_AWARE_WARNINGS\n\
353
-X tracemalloc[=N]: trace Python memory allocations; N sets a traceback limit\n \
354
         of N frames (default: 1); also PYTHONTRACEMALLOC=N\n\
355
-X utf8[=0|1]: enable (1) or disable (0) UTF-8 mode; also PYTHONUTF8\n\
356
-X warn_default_encoding: enable opt-in EncodingWarning for 'encoding=None';\n\
357
         also PYTHONWARNDEFAULTENCODING\
358
";
359
360
/* Envvars that don't have equivalent command-line options are listed first */
361
static const char usage_envvars[] =
362
"Environment variables that change behavior:\n"
363
"PYTHONSTARTUP   : file executed on interactive startup (no default)\n"
364
"PYTHONPATH      : '%lc'-separated list of directories prefixed to the\n"
365
"                  default module search path.  The result is sys.path.\n"
366
"PYTHONHOME      : alternate <prefix> directory (or <prefix>%lc<exec_prefix>).\n"
367
"                  The default module search path uses %s.\n"
368
"PYTHONPLATLIBDIR: override sys.platlibdir\n"
369
"PYTHONCASEOK    : ignore case in 'import' statements (Windows)\n"
370
"PYTHONIOENCODING: encoding[:errors] used for stdin/stdout/stderr\n"
371
"PYTHONHASHSEED  : if this variable is set to 'random', a random value is used\n"
372
"                  to seed the hashes of str and bytes objects.  It can also be\n"
373
"                  set to an integer in the range [0,4294967295] to get hash\n"
374
"                  values with a predictable seed.\n"
375
"PYTHONMALLOC    : set the Python memory allocators and/or install debug hooks\n"
376
"                  on Python memory allocators.  Use PYTHONMALLOC=debug to\n"
377
"                  install debug hooks.\n"
378
"PYTHONMALLOCSTATS: print memory allocator statistics\n"
379
"PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale\n"
380
"                  coercion behavior.  Use PYTHONCOERCECLOCALE=warn to request\n"
381
"                  display of locale coercion and locale compatibility warnings\n"
382
"                  on stderr.\n"
383
"PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\n"
384
"                  debugger.  It can be set to the callable of your debugger of\n"
385
"                  choice.\n"
386
"PYTHON_COLORS   : if this variable is set to 1, the interpreter will colorize\n"
387
"                  various kinds of output.  Setting it to 0 deactivates\n"
388
"                  this behavior.\n"
389
"PYTHON_HISTORY  : the location of a .python_history file.\n"
390
"PYTHONASYNCIODEBUG: enable asyncio debug mode\n"
391
#ifdef Py_TRACE_REFS
392
"PYTHONDUMPREFS  : dump objects and reference counts still alive after shutdown\n"
393
"PYTHONDUMPREFSFILE: dump objects and reference counts to the specified file\n"
394
#endif
395
#ifdef __APPLE__
396
"PYTHONEXECUTABLE: set sys.argv[0] to this value (macOS only)\n"
397
#endif
398
#ifdef MS_WINDOWS
399
"PYTHONLEGACYWINDOWSFSENCODING: use legacy \"mbcs\" encoding for file system\n"
400
"PYTHONLEGACYWINDOWSSTDIO: use legacy Windows stdio\n"
401
#endif
402
"PYTHONUSERBASE  : defines the user base directory (site.USER_BASE)\n"
403
"PYTHON_BASIC_REPL: use the traditional parser-based REPL\n"
404
"\n"
405
"These variables have equivalent command-line options (see --help for details):\n"
406
"PYTHON_CPU_COUNT: override the return value of os.cpu_count() (-X cpu_count)\n"
407
"PYTHONDEBUG     : enable parser debug mode (-d)\n"
408
"PYTHONDEVMODE   : enable Python Development Mode (-X dev)\n"
409
"PYTHONDONTWRITEBYTECODE: don't write .pyc files (-B)\n"
410
"PYTHONFAULTHANDLER: dump the Python traceback on fatal errors (-X faulthandler)\n"
411
"PYTHON_FROZEN_MODULES: whether to use frozen modules; the default is \"on\"\n"
412
"                  for installed Python and \"off\" for a local build\n"
413
"                  (-X frozen_modules)\n"
414
#ifdef Py_GIL_DISABLED
415
"PYTHON_GIL      : when set to 0, disables the GIL (-X gil)\n"
416
#endif
417
"PYTHONINSPECT   : inspect interactively after running script (-i)\n"
418
"PYTHONINTMAXSTRDIGITS: limit the size of int<->str conversions;\n"
419
"                  0 disables the limit (-X int_max_str_digits=N)\n"
420
"PYTHONNODEBUGRANGES: don't include extra location information in code objects\n"
421
"                  (-X no_debug_ranges)\n"
422
"PYTHONNOUSERSITE: disable user site directory (-s)\n"
423
"PYTHONOPTIMIZE  : enable level 1 optimizations (-O)\n"
424
"PYTHONPERFSUPPORT: support the Linux \"perf\" profiler (-X perf)\n"
425
"PYTHON_PERF_JIT_SUPPORT: enable Linux \"perf\" profiler support with JIT\n"
426
"                  (-X perf_jit)\n"
427
#ifdef Py_DEBUG
428
"PYTHON_PRESITE: import this module before site (-X presite)\n"
429
#endif
430
"PYTHONPROFILEIMPORTTIME: show how long each import takes (-X importtime)\n"
431
"PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files\n"
432
"                  (-X pycache_prefix)\n"
433
"PYTHONSAFEPATH  : don't prepend a potentially unsafe path to sys.path.\n"
434
#ifdef Py_STATS
435
"PYTHONSTATS     : turns on statistics gathering (-X pystats)\n"
436
#endif
437
#ifdef Py_GIL_DISABLED
438
"PYTHON_TLBC     : when set to 0, disables thread-local bytecode (-X tlbc)\n"
439
#endif
440
"PYTHON_THREAD_INHERIT_CONTEXT: if true (1), threads inherit context vars\n"
441
"                   (-X thread_inherit_context)\n"
442
"PYTHON_CONTEXT_AWARE_WARNINGS: if true (1), enable thread-safe warnings module\n"
443
"                   behaviour (-X context_aware_warnings)\n"
444
"PYTHONTRACEMALLOC: trace Python memory allocations (-X tracemalloc)\n"
445
"PYTHONUNBUFFERED: disable stdout/stderr buffering (-u)\n"
446
"PYTHONUTF8      : control the UTF-8 mode (-X utf8)\n"
447
"PYTHONVERBOSE   : trace import statements (-v)\n"
448
"PYTHONWARNDEFAULTENCODING: enable opt-in EncodingWarning for 'encoding=None'\n"
449
"                  (-X warn_default_encoding)\n"
450
"PYTHONWARNINGS  : warning control (-W)\n"
451
;
452
453
#if defined(MS_WINDOWS)
454
#  define PYTHONHOMEHELP "<prefix>\\python{major}{minor}"
455
#else
456
0
#  define PYTHONHOMEHELP "<prefix>/lib/pythonX.X"
457
#endif
458
459
460
/* --- Global configuration variables ----------------------------- */
461
462
/* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change
463
   stdin and stdout error handler to "surrogateescape". */
464
int Py_UTF8Mode = 0;
465
int Py_DebugFlag = 0; /* Needed by parser.c */
466
int Py_VerboseFlag = 0; /* Needed by import.c */
467
int Py_QuietFlag = 0; /* Needed by sysmodule.c */
468
int Py_InteractiveFlag = 0; /* Previously, was used by Py_FdIsInteractive() */
469
int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */
470
int Py_OptimizeFlag = 0; /* Needed by compile.c */
471
int Py_NoSiteFlag = 0; /* Suppress 'import site' */
472
int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */
473
int Py_FrozenFlag = 0; /* Needed by getpath.c */
474
int Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */
475
int Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */
476
int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
477
int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
478
int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
479
int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
480
#ifdef MS_WINDOWS
481
int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */
482
int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */
483
#endif
484
485
486
static PyObject *
487
_Py_GetGlobalVariablesAsDict(void)
488
0
{
489
0
_Py_COMP_DIAG_PUSH
490
0
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
491
0
    PyObject *dict, *obj;
492
493
0
    dict = PyDict_New();
494
0
    if (dict == NULL) {
495
0
        return NULL;
496
0
    }
497
498
0
#define SET_ITEM(KEY, EXPR) \
499
0
        do { \
500
0
            obj = (EXPR); \
501
0
            if (obj == NULL) { \
502
0
                return NULL; \
503
0
            } \
504
0
            int res = PyDict_SetItemString(dict, (KEY), obj); \
505
0
            Py_DECREF(obj); \
506
0
            if (res < 0) { \
507
0
                goto fail; \
508
0
            } \
509
0
        } while (0)
510
0
#define SET_ITEM_INT(VAR) \
511
0
    SET_ITEM(#VAR, PyLong_FromLong(VAR))
512
0
#define FROM_STRING(STR) \
513
0
    ((STR != NULL) ? \
514
0
        PyUnicode_FromString(STR) \
515
0
        : Py_NewRef(Py_None))
516
0
#define SET_ITEM_STR(VAR) \
517
0
    SET_ITEM(#VAR, FROM_STRING(VAR))
518
519
0
    SET_ITEM_STR(Py_FileSystemDefaultEncoding);
520
0
    SET_ITEM_INT(Py_HasFileSystemDefaultEncoding);
521
0
    SET_ITEM_STR(Py_FileSystemDefaultEncodeErrors);
522
0
    SET_ITEM_INT(_Py_HasFileSystemDefaultEncodeErrors);
523
524
0
    SET_ITEM_INT(Py_UTF8Mode);
525
0
    SET_ITEM_INT(Py_DebugFlag);
526
0
    SET_ITEM_INT(Py_VerboseFlag);
527
0
    SET_ITEM_INT(Py_QuietFlag);
528
0
    SET_ITEM_INT(Py_InteractiveFlag);
529
0
    SET_ITEM_INT(Py_InspectFlag);
530
531
0
    SET_ITEM_INT(Py_OptimizeFlag);
532
0
    SET_ITEM_INT(Py_NoSiteFlag);
533
0
    SET_ITEM_INT(Py_BytesWarningFlag);
534
0
    SET_ITEM_INT(Py_FrozenFlag);
535
0
    SET_ITEM_INT(Py_IgnoreEnvironmentFlag);
536
0
    SET_ITEM_INT(Py_DontWriteBytecodeFlag);
537
0
    SET_ITEM_INT(Py_NoUserSiteDirectory);
538
0
    SET_ITEM_INT(Py_UnbufferedStdioFlag);
539
0
    SET_ITEM_INT(Py_HashRandomizationFlag);
540
0
    SET_ITEM_INT(Py_IsolatedFlag);
541
542
#ifdef MS_WINDOWS
543
    SET_ITEM_INT(Py_LegacyWindowsFSEncodingFlag);
544
    SET_ITEM_INT(Py_LegacyWindowsStdioFlag);
545
#endif
546
547
0
    return dict;
548
549
0
fail:
550
0
    Py_DECREF(dict);
551
0
    return NULL;
552
553
0
#undef FROM_STRING
554
0
#undef SET_ITEM
555
0
#undef SET_ITEM_INT
556
0
#undef SET_ITEM_STR
557
0
_Py_COMP_DIAG_POP
558
0
}
559
560
char*
561
Py_GETENV(const char *name)
562
32
{
563
32
_Py_COMP_DIAG_PUSH
564
32
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
565
32
    if (Py_IgnoreEnvironmentFlag) {
566
0
        return NULL;
567
0
    }
568
32
    return getenv(name);
569
32
_Py_COMP_DIAG_POP
570
32
}
571
572
/* --- PyStatus ----------------------------------------------- */
573
574
PyStatus PyStatus_Ok(void)
575
48
{ return _PyStatus_OK(); }
576
577
PyStatus PyStatus_Error(const char *err_msg)
578
0
{
579
0
    assert(err_msg != NULL);
580
0
    return (PyStatus){._type = _PyStatus_TYPE_ERROR,
581
0
                      .err_msg = err_msg};
582
0
}
583
584
PyStatus PyStatus_NoMemory(void)
585
0
{ return PyStatus_Error("memory allocation failed"); }
586
587
PyStatus PyStatus_Exit(int exitcode)
588
0
{ return _PyStatus_EXIT(exitcode); }
589
590
591
int PyStatus_IsError(PyStatus status)
592
0
{ return _PyStatus_IS_ERROR(status); }
593
594
int PyStatus_IsExit(PyStatus status)
595
0
{ return _PyStatus_IS_EXIT(status); }
596
597
int PyStatus_Exception(PyStatus status)
598
0
{ return _PyStatus_EXCEPTION(status); }
599
600
void
601
_PyErr_SetFromPyStatus(PyStatus status)
602
0
{
603
0
    if (!_PyStatus_IS_ERROR(status)) {
604
0
        PyErr_Format(PyExc_SystemError,
605
0
                     "_PyErr_SetFromPyStatus() status is not an error");
606
0
        return;
607
0
    }
608
609
0
    const char *err_msg = status.err_msg;
610
0
    if (err_msg == NULL || strlen(err_msg) == 0) {
611
0
        PyErr_Format(PyExc_SystemError,
612
0
                     "_PyErr_SetFromPyStatus() status has no error message");
613
0
        return;
614
0
    }
615
616
0
    if (strcmp(err_msg, _PyStatus_NO_MEMORY_ERRMSG) == 0) {
617
0
        PyErr_NoMemory();
618
0
        return;
619
0
    }
620
621
0
    const char *func = status.func;
622
0
    if (func) {
623
0
        PyErr_Format(PyExc_RuntimeError, "%s: %s", func, err_msg);
624
0
    }
625
0
    else {
626
0
        PyErr_Format(PyExc_RuntimeError, "%s", err_msg);
627
0
    }
628
0
}
629
630
631
/* --- PyWideStringList ------------------------------------------------ */
632
633
#ifndef NDEBUG
634
int
635
_PyWideStringList_CheckConsistency(const PyWideStringList *list)
636
{
637
    assert(list->length >= 0);
638
    if (list->length != 0) {
639
        assert(list->items != NULL);
640
    }
641
    for (Py_ssize_t i = 0; i < list->length; i++) {
642
        assert(list->items[i] != NULL);
643
    }
644
    return 1;
645
}
646
#endif   /* Py_DEBUG */
647
648
649
static void
650
_PyWideStringList_ClearEx(PyWideStringList *list,
651
                          bool use_default_allocator)
652
800
{
653
800
    assert(_PyWideStringList_CheckConsistency(list));
654
896
    for (Py_ssize_t i=0; i < list->length; i++) {
655
96
        if (use_default_allocator) {
656
0
            _PyMem_DefaultRawFree(list->items[i]);
657
0
        }
658
96
        else {
659
96
            PyMem_RawFree(list->items[i]);
660
96
        }
661
96
    }
662
800
    if (use_default_allocator) {
663
16
        _PyMem_DefaultRawFree(list->items);
664
16
    }
665
784
    else {
666
784
        PyMem_RawFree(list->items);
667
784
    }
668
800
    list->length = 0;
669
800
    list->items = NULL;
670
800
}
671
672
void
673
_PyWideStringList_Clear(PyWideStringList *list)
674
528
{
675
528
    _PyWideStringList_ClearEx(list, false);
676
528
}
677
678
static int
679
_PyWideStringList_CopyEx(PyWideStringList *list,
680
                         const PyWideStringList *list2,
681
                         bool use_default_allocator)
682
272
{
683
272
    assert(_PyWideStringList_CheckConsistency(list));
684
272
    assert(_PyWideStringList_CheckConsistency(list2));
685
686
272
    if (list2->length == 0) {
687
224
        _PyWideStringList_ClearEx(list, use_default_allocator);
688
224
        return 0;
689
224
    }
690
691
48
    PyWideStringList copy = _PyWideStringList_INIT;
692
693
48
    size_t size = list2->length * sizeof(list2->items[0]);
694
48
    if (use_default_allocator) {
695
0
        copy.items = _PyMem_DefaultRawMalloc(size);
696
0
    }
697
48
    else {
698
48
        copy.items = PyMem_RawMalloc(size);
699
48
    }
700
48
    if (copy.items == NULL) {
701
0
        return -1;
702
0
    }
703
704
128
    for (Py_ssize_t i=0; i < list2->length; i++) {
705
80
        wchar_t *item;
706
80
        if (use_default_allocator) {
707
0
            item = _PyMem_DefaultRawWcsdup(list2->items[i]);
708
0
        }
709
80
        else {
710
80
            item = _PyMem_RawWcsdup(list2->items[i]);
711
80
        }
712
80
        if (item == NULL) {
713
0
            _PyWideStringList_ClearEx(&copy, use_default_allocator);
714
0
            return -1;
715
0
        }
716
80
        copy.items[i] = item;
717
80
        copy.length = i + 1;
718
80
    }
719
720
48
    _PyWideStringList_ClearEx(list, use_default_allocator);
721
48
    *list = copy;
722
48
    return 0;
723
48
}
724
725
int
726
_PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2)
727
256
{
728
256
    return _PyWideStringList_CopyEx(list, list2, false);
729
256
}
730
731
PyStatus
732
PyWideStringList_Insert(PyWideStringList *list,
733
                        Py_ssize_t index, const wchar_t *item)
734
80
{
735
80
    Py_ssize_t len = list->length;
736
80
    if (len == PY_SSIZE_T_MAX) {
737
        /* length+1 would overflow */
738
0
        return _PyStatus_NO_MEMORY();
739
0
    }
740
80
    if (index < 0) {
741
0
        return _PyStatus_ERR("PyWideStringList_Insert index must be >= 0");
742
0
    }
743
80
    if (index > len) {
744
0
        index = len;
745
0
    }
746
747
80
    wchar_t *item2 = _PyMem_RawWcsdup(item);
748
80
    if (item2 == NULL) {
749
0
        return _PyStatus_NO_MEMORY();
750
0
    }
751
752
80
    size_t size = (len + 1) * sizeof(list->items[0]);
753
80
    wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size);
754
80
    if (items2 == NULL) {
755
0
        PyMem_RawFree(item2);
756
0
        return _PyStatus_NO_MEMORY();
757
0
    }
758
759
80
    if (index < len) {
760
0
        memmove(&items2[index + 1],
761
0
                &items2[index],
762
0
                (len - index) * sizeof(items2[0]));
763
0
    }
764
765
80
    items2[index] = item2;
766
80
    list->items = items2;
767
80
    list->length++;
768
80
    return _PyStatus_OK();
769
80
}
770
771
772
PyStatus
773
PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
774
80
{
775
80
    return PyWideStringList_Insert(list, list->length, item);
776
80
}
777
778
779
PyStatus
780
_PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2)
781
32
{
782
32
    for (Py_ssize_t i = 0; i < list2->length; i++) {
783
0
        PyStatus status = PyWideStringList_Append(list, list2->items[i]);
784
0
        if (_PyStatus_EXCEPTION(status)) {
785
0
            return status;
786
0
        }
787
0
    }
788
32
    return _PyStatus_OK();
789
32
}
790
791
792
static int
793
_PyWideStringList_Find(PyWideStringList *list, const wchar_t *item)
794
0
{
795
0
    for (Py_ssize_t i = 0; i < list->length; i++) {
796
0
        if (wcscmp(list->items[i], item) == 0) {
797
0
            return 1;
798
0
        }
799
0
    }
800
0
    return 0;
801
0
}
802
803
804
PyObject*
805
_PyWideStringList_AsList(const PyWideStringList *list)
806
64
{
807
64
    assert(_PyWideStringList_CheckConsistency(list));
808
809
64
    PyObject *pylist = PyList_New(list->length);
810
64
    if (pylist == NULL) {
811
0
        return NULL;
812
0
    }
813
814
128
    for (Py_ssize_t i = 0; i < list->length; i++) {
815
64
        PyObject *item = PyUnicode_FromWideChar(list->items[i], -1);
816
64
        if (item == NULL) {
817
0
            Py_DECREF(pylist);
818
0
            return NULL;
819
0
        }
820
64
        PyList_SET_ITEM(pylist, i, item);
821
64
    }
822
64
    return pylist;
823
64
}
824
825
826
static PyObject*
827
_PyWideStringList_AsTuple(const PyWideStringList *list)
828
64
{
829
64
    assert(_PyWideStringList_CheckConsistency(list));
830
831
64
    PyObject *tuple = PyTuple_New(list->length);
832
64
    if (tuple == NULL) {
833
0
        return NULL;
834
0
    }
835
836
80
    for (Py_ssize_t i = 0; i < list->length; i++) {
837
16
        PyObject *item = PyUnicode_FromWideChar(list->items[i], -1);
838
16
        if (item == NULL) {
839
0
            Py_DECREF(tuple);
840
0
            return NULL;
841
0
        }
842
16
        PyTuple_SET_ITEM(tuple, i, item);
843
16
    }
844
64
    return tuple;
845
64
}
846
847
848
/* --- Py_GetArgcArgv() ------------------------------------------- */
849
850
void
851
_Py_ClearArgcArgv(void)
852
0
{
853
0
    _PyWideStringList_ClearEx(&_PyRuntime.orig_argv, true);
854
0
}
855
856
857
static int
858
_Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv)
859
16
{
860
16
    const PyWideStringList argv_list = {.length = argc, .items = (wchar_t **)argv};
861
862
    // XXX _PyRuntime.orig_argv only gets cleared by Py_Main(),
863
    // so it currently leaks for embedders.
864
16
    return _PyWideStringList_CopyEx(&_PyRuntime.orig_argv, &argv_list, true);
865
16
}
866
867
868
// _PyConfig_Write() calls _Py_SetArgcArgv() with PyConfig.orig_argv.
869
void
870
Py_GetArgcArgv(int *argc, wchar_t ***argv)
871
0
{
872
0
    *argc = (int)_PyRuntime.orig_argv.length;
873
0
    *argv = _PyRuntime.orig_argv.items;
874
0
}
875
876
877
/* --- PyConfig ---------------------------------------------- */
878
879
16
#define MAX_HASH_SEED 4294967295UL
880
881
882
#ifndef NDEBUG
883
static int
884
config_check_consistency(const PyConfig *config)
885
{
886
    /* Check config consistency */
887
    assert(config->isolated >= 0);
888
    assert(config->use_environment >= 0);
889
    assert(config->dev_mode >= 0);
890
    assert(config->install_signal_handlers >= 0);
891
    assert(config->use_hash_seed >= 0);
892
    assert(config->hash_seed <= MAX_HASH_SEED);
893
    assert(config->faulthandler >= 0);
894
    assert(config->tracemalloc >= 0);
895
    assert(config->import_time >= 0);
896
    assert(config->code_debug_ranges >= 0);
897
    assert(config->show_ref_count >= 0);
898
    assert(config->dump_refs >= 0);
899
    assert(config->malloc_stats >= 0);
900
    assert(config->site_import >= 0);
901
    assert(config->bytes_warning >= 0);
902
    assert(config->warn_default_encoding >= 0);
903
    assert(config->inspect >= 0);
904
    assert(config->interactive >= 0);
905
    assert(config->optimization_level >= 0);
906
    assert(config->parser_debug >= 0);
907
    assert(config->write_bytecode >= 0);
908
    assert(config->verbose >= 0);
909
    assert(config->quiet >= 0);
910
    assert(config->user_site_directory >= 0);
911
    assert(config->parse_argv >= 0);
912
    assert(config->configure_c_stdio >= 0);
913
    assert(config->buffered_stdio >= 0);
914
    assert(_PyWideStringList_CheckConsistency(&config->orig_argv));
915
    assert(_PyWideStringList_CheckConsistency(&config->argv));
916
    /* sys.argv must be non-empty: empty argv is replaced with [''] */
917
    assert(config->argv.length >= 1);
918
    assert(_PyWideStringList_CheckConsistency(&config->xoptions));
919
    assert(_PyWideStringList_CheckConsistency(&config->warnoptions));
920
    assert(_PyWideStringList_CheckConsistency(&config->module_search_paths));
921
    assert(config->module_search_paths_set >= 0);
922
    assert(config->filesystem_encoding != NULL);
923
    assert(config->filesystem_errors != NULL);
924
    assert(config->stdio_encoding != NULL);
925
    assert(config->stdio_errors != NULL);
926
#ifdef MS_WINDOWS
927
    assert(config->legacy_windows_stdio >= 0);
928
#endif
929
    /* -c and -m options are exclusive */
930
    assert(!(config->run_command != NULL && config->run_module != NULL));
931
    assert(config->check_hash_pycs_mode != NULL);
932
    assert(config->_install_importlib >= 0);
933
    assert(config->pathconfig_warnings >= 0);
934
    assert(config->_is_python_build >= 0);
935
    assert(config->safe_path >= 0);
936
    assert(config->int_max_str_digits >= 0);
937
    // cpu_count can be -1 if the user doesn't override it.
938
    assert(config->cpu_count != 0);
939
    // config->use_frozen_modules is initialized later
940
    // by _PyConfig_InitImportConfig().
941
    assert(config->thread_inherit_context >= 0);
942
    assert(config->context_aware_warnings >= 0);
943
#ifdef __APPLE__
944
    assert(config->use_system_logger >= 0);
945
#endif
946
#ifdef Py_STATS
947
    assert(config->_pystats >= 0);
948
#endif
949
    return 1;
950
}
951
#endif
952
953
954
/* Free memory allocated in config, but don't clear all attributes */
955
void
956
PyConfig_Clear(PyConfig *config)
957
64
{
958
64
#define CLEAR(ATTR) \
959
1.34k
    do { \
960
1.34k
        PyMem_RawFree(ATTR); \
961
1.34k
        ATTR = NULL; \
962
1.34k
    } while (0)
963
964
64
    CLEAR(config->pycache_prefix);
965
64
    CLEAR(config->pythonpath_env);
966
64
    CLEAR(config->home);
967
64
    CLEAR(config->program_name);
968
969
64
    _PyWideStringList_Clear(&config->argv);
970
64
    _PyWideStringList_Clear(&config->warnoptions);
971
64
    _PyWideStringList_Clear(&config->xoptions);
972
64
    _PyWideStringList_Clear(&config->module_search_paths);
973
64
    config->module_search_paths_set = 0;
974
64
    CLEAR(config->stdlib_dir);
975
976
64
    CLEAR(config->executable);
977
64
    CLEAR(config->base_executable);
978
64
    CLEAR(config->prefix);
979
64
    CLEAR(config->base_prefix);
980
64
    CLEAR(config->exec_prefix);
981
64
    CLEAR(config->base_exec_prefix);
982
64
    CLEAR(config->platlibdir);
983
64
    CLEAR(config->sys_path_0);
984
985
64
    CLEAR(config->filesystem_encoding);
986
64
    CLEAR(config->filesystem_errors);
987
64
    CLEAR(config->stdio_encoding);
988
64
    CLEAR(config->stdio_errors);
989
64
    CLEAR(config->run_command);
990
64
    CLEAR(config->run_module);
991
64
    CLEAR(config->run_filename);
992
64
    CLEAR(config->check_hash_pycs_mode);
993
#ifdef Py_DEBUG
994
    CLEAR(config->run_presite);
995
#endif
996
997
64
    _PyWideStringList_Clear(&config->orig_argv);
998
64
#undef CLEAR
999
64
}
1000
1001
1002
void
1003
_PyConfig_InitCompatConfig(PyConfig *config)
1004
48
{
1005
48
    memset(config, 0, sizeof(*config));
1006
1007
48
    config->_config_init = (int)_PyConfig_INIT_COMPAT;
1008
48
    config->import_time = -1;
1009
48
    config->isolated = -1;
1010
48
    config->use_environment = -1;
1011
48
    config->dev_mode = -1;
1012
48
    config->install_signal_handlers = 1;
1013
48
    config->use_hash_seed = -1;
1014
48
    config->faulthandler = -1;
1015
48
    config->tracemalloc = -1;
1016
48
    config->perf_profiling = -1;
1017
48
    config->remote_debug = -1;
1018
48
    config->module_search_paths_set = 0;
1019
48
    config->parse_argv = 0;
1020
48
    config->site_import = -1;
1021
48
    config->bytes_warning = -1;
1022
48
    config->warn_default_encoding = 0;
1023
48
    config->inspect = -1;
1024
48
    config->interactive = -1;
1025
48
    config->optimization_level = -1;
1026
48
    config->parser_debug= -1;
1027
48
    config->write_bytecode = -1;
1028
48
    config->verbose = -1;
1029
48
    config->quiet = -1;
1030
48
    config->user_site_directory = -1;
1031
48
    config->configure_c_stdio = 0;
1032
48
    config->buffered_stdio = -1;
1033
48
    config->_install_importlib = 1;
1034
48
    config->check_hash_pycs_mode = NULL;
1035
48
    config->pathconfig_warnings = -1;
1036
48
    config->_init_main = 1;
1037
#ifdef MS_WINDOWS
1038
    config->legacy_windows_stdio = -1;
1039
#endif
1040
#ifdef Py_DEBUG
1041
    config->use_frozen_modules = 0;
1042
#else
1043
48
    config->use_frozen_modules = 1;
1044
48
#endif
1045
48
    config->safe_path = 0;
1046
48
    config->int_max_str_digits = -1;
1047
48
    config->_is_python_build = 0;
1048
48
    config->code_debug_ranges = 1;
1049
48
    config->cpu_count = -1;
1050
#ifdef Py_GIL_DISABLED
1051
    config->thread_inherit_context = 1;
1052
    config->context_aware_warnings = 1;
1053
#else
1054
48
    config->thread_inherit_context = 0;
1055
48
    config->context_aware_warnings = 0;
1056
48
#endif
1057
#ifdef __APPLE__
1058
    config->use_system_logger = USE_SYSTEM_LOGGER_DEFAULT;
1059
#endif
1060
#ifdef Py_GIL_DISABLED
1061
    config->enable_gil = _PyConfig_GIL_DEFAULT;
1062
    config->tlbc_enabled = 1;
1063
#endif
1064
48
}
1065
1066
1067
static void
1068
config_init_defaults(PyConfig *config)
1069
32
{
1070
32
    _PyConfig_InitCompatConfig(config);
1071
1072
32
    config->isolated = 0;
1073
32
    config->use_environment = 1;
1074
32
    config->site_import = 1;
1075
32
    config->bytes_warning = 0;
1076
32
    config->inspect = 0;
1077
32
    config->interactive = 0;
1078
32
    config->optimization_level = 0;
1079
32
    config->parser_debug= 0;
1080
32
    config->write_bytecode = 1;
1081
32
    config->verbose = 0;
1082
32
    config->quiet = 0;
1083
32
    config->user_site_directory = 1;
1084
32
    config->buffered_stdio = 1;
1085
32
    config->pathconfig_warnings = 1;
1086
#ifdef MS_WINDOWS
1087
    config->legacy_windows_stdio = 0;
1088
#endif
1089
#ifdef Py_GIL_DISABLED
1090
    config->thread_inherit_context = 1;
1091
    config->context_aware_warnings = 1;
1092
#else
1093
32
    config->thread_inherit_context = 0;
1094
32
    config->context_aware_warnings = 0;
1095
32
#endif
1096
#ifdef __APPLE__
1097
    config->use_system_logger = USE_SYSTEM_LOGGER_DEFAULT;
1098
#endif
1099
32
}
1100
1101
1102
void
1103
PyConfig_InitPythonConfig(PyConfig *config)
1104
32
{
1105
32
    config_init_defaults(config);
1106
1107
32
    config->_config_init = (int)_PyConfig_INIT_PYTHON;
1108
32
    config->configure_c_stdio = 1;
1109
32
    config->parse_argv = 1;
1110
32
}
1111
1112
1113
void
1114
PyConfig_InitIsolatedConfig(PyConfig *config)
1115
0
{
1116
0
    config_init_defaults(config);
1117
1118
0
    config->_config_init = (int)_PyConfig_INIT_ISOLATED;
1119
0
    config->isolated = 1;
1120
0
    config->use_environment = 0;
1121
0
    config->user_site_directory = 0;
1122
0
    config->dev_mode = 0;
1123
0
    config->install_signal_handlers = 0;
1124
0
    config->use_hash_seed = 0;
1125
0
    config->tracemalloc = 0;
1126
0
    config->perf_profiling = 0;
1127
0
    config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
1128
0
    config->safe_path = 1;
1129
0
    config->pathconfig_warnings = 0;
1130
#ifdef Py_GIL_DISABLED
1131
    config->thread_inherit_context = 1;
1132
#else
1133
0
    config->thread_inherit_context = 0;
1134
0
#endif
1135
#ifdef MS_WINDOWS
1136
    config->legacy_windows_stdio = 0;
1137
#endif
1138
#ifdef __APPLE__
1139
    config->use_system_logger = USE_SYSTEM_LOGGER_DEFAULT;
1140
#endif
1141
0
}
1142
1143
1144
/* Copy str into *config_str (duplicate the string) */
1145
PyStatus
1146
PyConfig_SetString(PyConfig *config, wchar_t **config_str, const wchar_t *str)
1147
1.13k
{
1148
1.13k
    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
1149
1.13k
    if (_PyStatus_EXCEPTION(status)) {
1150
0
        return status;
1151
0
    }
1152
1153
1.13k
    wchar_t *str2;
1154
1.13k
    if (str != NULL) {
1155
400
        str2 = _PyMem_RawWcsdup(str);
1156
400
        if (str2 == NULL) {
1157
0
            return _PyStatus_NO_MEMORY();
1158
0
        }
1159
400
    }
1160
736
    else {
1161
736
        str2 = NULL;
1162
736
    }
1163
1.13k
    PyMem_RawFree(*config_str);
1164
1.13k
    *config_str = str2;
1165
1.13k
    return _PyStatus_OK();
1166
1.13k
}
1167
1168
1169
static PyStatus
1170
config_set_bytes_string(PyConfig *config, wchar_t **config_str,
1171
                        const char *str, const char *decode_err_msg)
1172
0
{
1173
0
    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
1174
0
    if (_PyStatus_EXCEPTION(status)) {
1175
0
        return status;
1176
0
    }
1177
1178
0
    wchar_t *str2;
1179
0
    if (str != NULL) {
1180
0
        size_t len;
1181
0
        str2 = Py_DecodeLocale(str, &len);
1182
0
        if (str2 == NULL) {
1183
0
            if (len == (size_t)-2) {
1184
0
                return _PyStatus_ERR(decode_err_msg);
1185
0
            }
1186
0
            else {
1187
0
                return  _PyStatus_NO_MEMORY();
1188
0
            }
1189
0
        }
1190
0
    }
1191
0
    else {
1192
0
        str2 = NULL;
1193
0
    }
1194
0
    PyMem_RawFree(*config_str);
1195
0
    *config_str = str2;
1196
0
    return _PyStatus_OK();
1197
0
}
1198
1199
1200
#define CONFIG_SET_BYTES_STR(config, config_str, str, NAME) \
1201
0
    config_set_bytes_string(config, config_str, str, "cannot decode " NAME)
1202
1203
1204
/* Decode str using Py_DecodeLocale() and set the result into *config_str.
1205
   Pre-initialize Python if needed to ensure that encodings are properly
1206
   configured. */
1207
PyStatus
1208
PyConfig_SetBytesString(PyConfig *config, wchar_t **config_str,
1209
                        const char *str)
1210
0
{
1211
0
    return CONFIG_SET_BYTES_STR(config, config_str, str, "string");
1212
0
}
1213
1214
1215
static inline void*
1216
config_get_spec_member(const PyConfig *config, const PyConfigSpec *spec)
1217
5.52k
{
1218
5.52k
    return (char *)config + spec->offset;
1219
5.52k
}
1220
1221
1222
static inline void*
1223
preconfig_get_spec_member(const PyPreConfig *preconfig, const PyConfigSpec *spec)
1224
0
{
1225
0
    return (char *)preconfig + spec->offset;
1226
0
}
1227
1228
1229
PyStatus
1230
_PyConfig_Copy(PyConfig *config, const PyConfig *config2)
1231
32
{
1232
32
    PyConfig_Clear(config);
1233
1234
32
    PyStatus status;
1235
32
    const PyConfigSpec *spec = PYCONFIG_SPEC;
1236
2.24k
    for (; spec->name != NULL; spec++) {
1237
2.20k
        void *member = config_get_spec_member(config, spec);
1238
2.20k
        const void *member2 = config_get_spec_member((PyConfig*)config2, spec);
1239
2.20k
        switch (spec->type) {
1240
96
        case PyConfig_MEMBER_INT:
1241
352
        case PyConfig_MEMBER_UINT:
1242
1.31k
        case PyConfig_MEMBER_BOOL:
1243
1.31k
        {
1244
1.31k
            *(int*)member = *(int*)member2;
1245
1.31k
            break;
1246
352
        }
1247
32
        case PyConfig_MEMBER_ULONG:
1248
32
        {
1249
32
            *(unsigned long*)member = *(unsigned long*)member2;
1250
32
            break;
1251
352
        }
1252
224
        case PyConfig_MEMBER_WSTR:
1253
704
        case PyConfig_MEMBER_WSTR_OPT:
1254
704
        {
1255
704
            const wchar_t *str = *(const wchar_t**)member2;
1256
704
            status = PyConfig_SetString(config, (wchar_t**)member, str);
1257
704
            if (_PyStatus_EXCEPTION(status)) {
1258
0
                return status;
1259
0
            }
1260
704
            break;
1261
704
        }
1262
704
        case PyConfig_MEMBER_WSTR_LIST:
1263
160
        {
1264
160
            if (_PyWideStringList_Copy((PyWideStringList*)member,
1265
160
                                       (const PyWideStringList*)member2) < 0) {
1266
0
                return _PyStatus_NO_MEMORY();
1267
0
            }
1268
160
            break;
1269
160
        }
1270
160
        default:
1271
0
            Py_UNREACHABLE();
1272
2.20k
        }
1273
2.20k
    }
1274
32
    return _PyStatus_OK();
1275
32
}
1276
1277
1278
PyObject *
1279
_PyConfig_AsDict(const PyConfig *config)
1280
16
{
1281
16
    PyObject *dict = PyDict_New();
1282
16
    if (dict == NULL) {
1283
0
        return NULL;
1284
0
    }
1285
1286
16
    const PyConfigSpec *spec = PYCONFIG_SPEC;
1287
1.12k
    for (; spec->name != NULL; spec++) {
1288
1.10k
        PyObject *obj = config_get(config, spec, 0);
1289
1.10k
        if (obj == NULL) {
1290
0
            Py_DECREF(dict);
1291
0
            return NULL;
1292
0
        }
1293
1294
1.10k
        int res = PyDict_SetItemString(dict, spec->name, obj);
1295
1.10k
        Py_DECREF(obj);
1296
1.10k
        if (res < 0) {
1297
0
            Py_DECREF(dict);
1298
0
            return NULL;
1299
0
        }
1300
1.10k
    }
1301
16
    return dict;
1302
16
}
1303
1304
1305
static void
1306
config_dict_invalid_value(const char *name)
1307
0
{
1308
0
    PyErr_Format(PyExc_ValueError, "invalid config value: %s", name);
1309
0
}
1310
1311
1312
static int
1313
config_dict_get_int(PyObject *dict, const char *name, int *result)
1314
656
{
1315
656
    PyObject *item = config_dict_get(dict, name);
1316
656
    if (item == NULL) {
1317
0
        return -1;
1318
0
    }
1319
656
    int value = PyLong_AsInt(item);
1320
656
    Py_DECREF(item);
1321
656
    if (value == -1 && PyErr_Occurred()) {
1322
0
        if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1323
0
            config_dict_invalid_type(name);
1324
0
        }
1325
0
        else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
1326
0
            config_dict_invalid_value(name);
1327
0
        }
1328
0
        return -1;
1329
0
    }
1330
656
    *result = value;
1331
656
    return 0;
1332
656
}
1333
1334
1335
static int
1336
config_dict_get_ulong(PyObject *dict, const char *name, unsigned long *result)
1337
16
{
1338
16
    PyObject *item = config_dict_get(dict, name);
1339
16
    if (item == NULL) {
1340
0
        return -1;
1341
0
    }
1342
16
    unsigned long value = PyLong_AsUnsignedLong(item);
1343
16
    Py_DECREF(item);
1344
16
    if (value == (unsigned long)-1 && PyErr_Occurred()) {
1345
0
        if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1346
0
            config_dict_invalid_type(name);
1347
0
        }
1348
0
        else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
1349
0
            config_dict_invalid_value(name);
1350
0
        }
1351
0
        return -1;
1352
0
    }
1353
16
    *result = value;
1354
16
    return 0;
1355
16
}
1356
1357
1358
static int
1359
config_dict_get_wstr(PyObject *dict, const char *name, PyConfig *config,
1360
                     wchar_t **result)
1361
352
{
1362
352
    PyObject *item = config_dict_get(dict, name);
1363
352
    if (item == NULL) {
1364
0
        return -1;
1365
0
    }
1366
1367
352
    PyStatus status;
1368
352
    if (item == Py_None) {
1369
112
        status = PyConfig_SetString(config, result, NULL);
1370
112
    }
1371
240
    else if (!PyUnicode_Check(item)) {
1372
0
        config_dict_invalid_type(name);
1373
0
        goto error;
1374
0
    }
1375
240
    else {
1376
240
        wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
1377
240
        if (wstr == NULL) {
1378
0
            goto error;
1379
0
        }
1380
240
        status = PyConfig_SetString(config, result, wstr);
1381
240
        PyMem_Free(wstr);
1382
240
    }
1383
352
    if (_PyStatus_EXCEPTION(status)) {
1384
0
        PyErr_NoMemory();
1385
0
        goto error;
1386
0
    }
1387
352
    Py_DECREF(item);
1388
352
    return 0;
1389
1390
0
error:
1391
0
    Py_DECREF(item);
1392
0
    return -1;
1393
352
}
1394
1395
1396
static int
1397
config_dict_get_wstrlist(PyObject *dict, const char *name, PyConfig *config,
1398
                         PyWideStringList *result)
1399
64
{
1400
64
    PyObject *list = config_dict_get(dict, name);
1401
64
    if (list == NULL) {
1402
0
        return -1;
1403
0
    }
1404
1405
64
    int is_list = PyList_CheckExact(list);
1406
64
    if (!is_list && !PyTuple_CheckExact(list)) {
1407
0
        Py_DECREF(list);
1408
0
        config_dict_invalid_type(name);
1409
0
        return -1;
1410
0
    }
1411
1412
64
    PyWideStringList wstrlist = _PyWideStringList_INIT;
1413
64
    Py_ssize_t len = is_list ? PyList_GET_SIZE(list) : PyTuple_GET_SIZE(list);
1414
128
    for (Py_ssize_t i=0; i < len; i++) {
1415
64
        PyObject *item = is_list ? PyList_GET_ITEM(list, i) : PyTuple_GET_ITEM(list, i);
1416
1417
64
        if (item == Py_None) {
1418
0
            config_dict_invalid_value(name);
1419
0
            goto error;
1420
0
        }
1421
64
        else if (!PyUnicode_Check(item)) {
1422
0
            config_dict_invalid_type(name);
1423
0
            goto error;
1424
0
        }
1425
64
        wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
1426
64
        if (wstr == NULL) {
1427
0
            goto error;
1428
0
        }
1429
64
        PyStatus status = PyWideStringList_Append(&wstrlist, wstr);
1430
64
        PyMem_Free(wstr);
1431
64
        if (_PyStatus_EXCEPTION(status)) {
1432
0
            PyErr_NoMemory();
1433
0
            goto error;
1434
0
        }
1435
64
    }
1436
1437
64
    if (_PyWideStringList_Copy(result, &wstrlist) < 0) {
1438
0
        PyErr_NoMemory();
1439
0
        goto error;
1440
0
    }
1441
64
    _PyWideStringList_Clear(&wstrlist);
1442
64
    Py_DECREF(list);
1443
64
    return 0;
1444
1445
0
error:
1446
0
    _PyWideStringList_Clear(&wstrlist);
1447
0
    Py_DECREF(list);
1448
0
    return -1;
1449
64
}
1450
1451
1452
static int
1453
config_dict_get_xoptions(PyObject *dict, const char *name, PyConfig *config,
1454
                         PyWideStringList *result)
1455
16
{
1456
16
    PyObject *xoptions = config_dict_get(dict, name);
1457
16
    if (xoptions == NULL) {
1458
0
        return -1;
1459
0
    }
1460
1461
16
    if (!PyDict_CheckExact(xoptions)) {
1462
0
        Py_DECREF(xoptions);
1463
0
        config_dict_invalid_type(name);
1464
0
        return -1;
1465
0
    }
1466
1467
16
    Py_ssize_t pos = 0;
1468
16
    PyObject *key, *value;
1469
16
    PyWideStringList wstrlist = _PyWideStringList_INIT;
1470
16
    while (PyDict_Next(xoptions, &pos, &key, &value)) {
1471
0
        PyObject *item;
1472
1473
0
        if (value != Py_True) {
1474
0
            item = PyUnicode_FromFormat("%S=%S", key, value);
1475
0
            if (item == NULL) {
1476
0
                goto error;
1477
0
            }
1478
0
        }
1479
0
        else {
1480
0
            item = Py_NewRef(key);
1481
0
        }
1482
1483
0
        wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
1484
0
        Py_DECREF(item);
1485
0
        if (wstr == NULL) {
1486
0
            goto error;
1487
0
        }
1488
1489
0
        PyStatus status = PyWideStringList_Append(&wstrlist, wstr);
1490
0
        PyMem_Free(wstr);
1491
0
        if (_PyStatus_EXCEPTION(status)) {
1492
0
            PyErr_NoMemory();
1493
0
            goto error;
1494
0
        }
1495
0
    }
1496
1497
16
    if (_PyWideStringList_Copy(result, &wstrlist) < 0) {
1498
0
        PyErr_NoMemory();
1499
0
        goto error;
1500
0
    }
1501
16
    _PyWideStringList_Clear(&wstrlist);
1502
16
    Py_DECREF(xoptions);
1503
16
    return 0;
1504
1505
0
error:
1506
0
    _PyWideStringList_Clear(&wstrlist);
1507
0
    Py_DECREF(xoptions);
1508
0
    return -1;
1509
16
}
1510
1511
1512
int
1513
_PyConfig_FromDict(PyConfig *config, PyObject *dict)
1514
16
{
1515
16
    if (!PyDict_Check(dict)) {
1516
0
        PyErr_SetString(PyExc_TypeError, "dict expected");
1517
0
        return -1;
1518
0
    }
1519
1520
16
    const PyConfigSpec *spec = PYCONFIG_SPEC;
1521
1.12k
    for (; spec->name != NULL; spec++) {
1522
1.10k
        char *member = (char *)config + spec->offset;
1523
1.10k
        switch (spec->type) {
1524
48
        case PyConfig_MEMBER_INT:
1525
176
        case PyConfig_MEMBER_UINT:
1526
656
        case PyConfig_MEMBER_BOOL:
1527
656
        {
1528
656
            int value;
1529
656
            if (config_dict_get_int(dict, spec->name, &value) < 0) {
1530
0
                return -1;
1531
0
            }
1532
656
            if (spec->type == PyConfig_MEMBER_BOOL
1533
656
                || spec->type == PyConfig_MEMBER_UINT)
1534
608
            {
1535
608
                if (value < 0) {
1536
0
                    config_dict_invalid_value(spec->name);
1537
0
                    return -1;
1538
0
                }
1539
608
            }
1540
656
            *(int*)member = value;
1541
656
            break;
1542
656
        }
1543
16
        case PyConfig_MEMBER_ULONG:
1544
16
        {
1545
16
            if (config_dict_get_ulong(dict, spec->name,
1546
16
                                      (unsigned long*)member) < 0) {
1547
0
                return -1;
1548
0
            }
1549
16
            break;
1550
16
        }
1551
112
        case PyConfig_MEMBER_WSTR:
1552
112
        {
1553
112
            wchar_t **wstr = (wchar_t**)member;
1554
112
            if (config_dict_get_wstr(dict, spec->name, config, wstr) < 0) {
1555
0
                return -1;
1556
0
            }
1557
112
            if (*wstr == NULL) {
1558
0
                config_dict_invalid_value(spec->name);
1559
0
                return -1;
1560
0
            }
1561
112
            break;
1562
112
        }
1563
240
        case PyConfig_MEMBER_WSTR_OPT:
1564
240
        {
1565
240
            wchar_t **wstr = (wchar_t**)member;
1566
240
            if (config_dict_get_wstr(dict, spec->name, config, wstr) < 0) {
1567
0
                return -1;
1568
0
            }
1569
240
            break;
1570
240
        }
1571
240
        case PyConfig_MEMBER_WSTR_LIST:
1572
80
        {
1573
80
            if (strcmp(spec->name, "xoptions") == 0) {
1574
16
                if (config_dict_get_xoptions(dict, spec->name, config,
1575
16
                                             (PyWideStringList*)member) < 0) {
1576
0
                    return -1;
1577
0
                }
1578
16
            }
1579
64
            else {
1580
64
                if (config_dict_get_wstrlist(dict, spec->name, config,
1581
64
                                             (PyWideStringList*)member) < 0) {
1582
0
                    return -1;
1583
0
                }
1584
64
            }
1585
80
            break;
1586
80
        }
1587
80
        default:
1588
0
            Py_UNREACHABLE();
1589
1.10k
        }
1590
1.10k
    }
1591
1592
16
    if (!(config->_config_init == _PyConfig_INIT_COMPAT
1593
16
          || config->_config_init == _PyConfig_INIT_PYTHON
1594
16
          || config->_config_init == _PyConfig_INIT_ISOLATED))
1595
0
    {
1596
0
        config_dict_invalid_value("_config_init");
1597
0
        return -1;
1598
0
    }
1599
1600
16
    if (config->hash_seed > MAX_HASH_SEED) {
1601
0
        config_dict_invalid_value("hash_seed");
1602
0
        return -1;
1603
0
    }
1604
16
    return 0;
1605
16
}
1606
1607
1608
static const char*
1609
config_get_env(const PyConfig *config, const char *name)
1610
288
{
1611
288
    return _Py_GetEnv(config->use_environment, name);
1612
288
}
1613
1614
1615
/* Get a copy of the environment variable as wchar_t*.
1616
   Return 0 on success, but *dest can be NULL.
1617
   Return -1 on memory allocation failure. Return -2 on decoding error. */
1618
static PyStatus
1619
config_get_env_dup(PyConfig *config,
1620
                   wchar_t **dest,
1621
                   wchar_t *wname, char *name,
1622
                   const char *decode_err_msg)
1623
80
{
1624
80
    assert(*dest == NULL);
1625
80
    assert(config->use_environment >= 0);
1626
1627
80
    if (!config->use_environment) {
1628
0
        *dest = NULL;
1629
0
        return _PyStatus_OK();
1630
0
    }
1631
1632
#ifdef MS_WINDOWS
1633
    const wchar_t *var = _wgetenv(wname);
1634
    if (!var || var[0] == '\0') {
1635
        *dest = NULL;
1636
        return _PyStatus_OK();
1637
    }
1638
1639
    return PyConfig_SetString(config, dest, var);
1640
#else
1641
80
    const char *var = getenv(name);
1642
80
    if (!var || var[0] == '\0') {
1643
80
        *dest = NULL;
1644
80
        return _PyStatus_OK();
1645
80
    }
1646
1647
0
    return config_set_bytes_string(config, dest, var, decode_err_msg);
1648
80
#endif
1649
80
}
1650
1651
1652
#define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \
1653
80
    config_get_env_dup(CONFIG, DEST, WNAME, NAME, "cannot decode " NAME)
1654
1655
1656
static void
1657
config_get_global_vars(PyConfig *config)
1658
16
{
1659
16
_Py_COMP_DIAG_PUSH
1660
16
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
1661
16
    if (config->_config_init != _PyConfig_INIT_COMPAT) {
1662
        /* Python and Isolated configuration ignore global variables */
1663
0
        return;
1664
0
    }
1665
1666
16
#define COPY_FLAG(ATTR, VALUE) \
1667
128
        if (config->ATTR == -1) { \
1668
128
            config->ATTR = VALUE; \
1669
128
        }
1670
16
#define COPY_NOT_FLAG(ATTR, VALUE) \
1671
96
        if (config->ATTR == -1) { \
1672
96
            config->ATTR = !(VALUE); \
1673
96
        }
1674
1675
16
    COPY_FLAG(isolated, Py_IsolatedFlag);
1676
16
    COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
1677
16
    COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
1678
16
    COPY_FLAG(inspect, Py_InspectFlag);
1679
16
    COPY_FLAG(interactive, Py_InteractiveFlag);
1680
16
    COPY_FLAG(optimization_level, Py_OptimizeFlag);
1681
16
    COPY_FLAG(parser_debug, Py_DebugFlag);
1682
16
    COPY_FLAG(verbose, Py_VerboseFlag);
1683
16
    COPY_FLAG(quiet, Py_QuietFlag);
1684
#ifdef MS_WINDOWS
1685
    COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
1686
#endif
1687
16
    COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);
1688
1689
16
    COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
1690
16
    COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
1691
16
    COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
1692
16
    COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
1693
1694
16
#undef COPY_FLAG
1695
16
#undef COPY_NOT_FLAG
1696
16
_Py_COMP_DIAG_POP
1697
16
}
1698
1699
1700
/* Set Py_xxx global configuration variables from 'config' configuration. */
1701
static void
1702
config_set_global_vars(const PyConfig *config)
1703
16
{
1704
16
_Py_COMP_DIAG_PUSH
1705
16
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
1706
16
#define COPY_FLAG(ATTR, VAR) \
1707
128
        if (config->ATTR != -1) { \
1708
128
            VAR = config->ATTR; \
1709
128
        }
1710
16
#define COPY_NOT_FLAG(ATTR, VAR) \
1711
96
        if (config->ATTR != -1) { \
1712
96
            VAR = !config->ATTR; \
1713
96
        }
1714
1715
16
    COPY_FLAG(isolated, Py_IsolatedFlag);
1716
16
    COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
1717
16
    COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
1718
16
    COPY_FLAG(inspect, Py_InspectFlag);
1719
16
    COPY_FLAG(interactive, Py_InteractiveFlag);
1720
16
    COPY_FLAG(optimization_level, Py_OptimizeFlag);
1721
16
    COPY_FLAG(parser_debug, Py_DebugFlag);
1722
16
    COPY_FLAG(verbose, Py_VerboseFlag);
1723
16
    COPY_FLAG(quiet, Py_QuietFlag);
1724
#ifdef MS_WINDOWS
1725
    COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
1726
#endif
1727
16
    COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);
1728
1729
16
    COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
1730
16
    COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
1731
16
    COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
1732
16
    COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
1733
1734
    /* Random or non-zero hash seed */
1735
16
    Py_HashRandomizationFlag = (config->use_hash_seed == 0 ||
1736
16
                                config->hash_seed != 0);
1737
1738
16
#undef COPY_FLAG
1739
16
#undef COPY_NOT_FLAG
1740
16
_Py_COMP_DIAG_POP
1741
16
}
1742
1743
1744
static const wchar_t*
1745
config_get_xoption(const PyConfig *config, wchar_t *name)
1746
256
{
1747
256
    return _Py_get_xoption(&config->xoptions, name);
1748
256
}
1749
1750
static const wchar_t*
1751
config_get_xoption_value(const PyConfig *config, wchar_t *name)
1752
64
{
1753
64
    const wchar_t *xoption = config_get_xoption(config, name);
1754
64
    if (xoption == NULL) {
1755
64
        return NULL;
1756
64
    }
1757
0
    const wchar_t *sep = wcschr(xoption, L'=');
1758
0
    return sep ? sep + 1 : L"";
1759
64
}
1760
1761
1762
static PyStatus
1763
config_init_hash_seed(PyConfig *config)
1764
16
{
1765
16
    static_assert(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc),
1766
16
                  "_Py_HashSecret_t has wrong size");
1767
1768
16
    const char *seed_text = config_get_env(config, "PYTHONHASHSEED");
1769
1770
    /* Convert a text seed to a numeric one */
1771
16
    if (seed_text && strcmp(seed_text, "random") != 0) {
1772
0
        const char *endptr = seed_text;
1773
0
        unsigned long seed;
1774
0
        errno = 0;
1775
0
        seed = strtoul(seed_text, (char **)&endptr, 10);
1776
0
        if (*endptr != '\0'
1777
0
            || seed > MAX_HASH_SEED
1778
0
            || (errno == ERANGE && seed == ULONG_MAX))
1779
0
        {
1780
0
            return _PyStatus_ERR("PYTHONHASHSEED must be \"random\" "
1781
0
                                "or an integer in range [0; 4294967295]");
1782
0
        }
1783
        /* Use a specific hash */
1784
0
        config->use_hash_seed = 1;
1785
0
        config->hash_seed = seed;
1786
0
    }
1787
16
    else {
1788
        /* Use a random hash */
1789
16
        config->use_hash_seed = 0;
1790
16
        config->hash_seed = 0;
1791
16
    }
1792
16
    return _PyStatus_OK();
1793
16
}
1794
1795
1796
static int
1797
config_wstr_to_int(const wchar_t *wstr, int *result)
1798
0
{
1799
0
    const wchar_t *endptr = wstr;
1800
0
    errno = 0;
1801
0
    long value = wcstol(wstr, (wchar_t **)&endptr, 10);
1802
0
    if (*endptr != '\0' || errno == ERANGE) {
1803
0
        return -1;
1804
0
    }
1805
0
    if (value < INT_MIN || value > INT_MAX) {
1806
0
        return -1;
1807
0
    }
1808
1809
0
    *result = (int)value;
1810
0
    return 0;
1811
0
}
1812
1813
static PyStatus
1814
config_read_gil(PyConfig *config, size_t len, wchar_t first_char)
1815
0
{
1816
0
    if (len == 1 && first_char == L'0') {
1817
#ifdef Py_GIL_DISABLED
1818
        config->enable_gil = _PyConfig_GIL_DISABLE;
1819
#else
1820
0
        return _PyStatus_ERR("Disabling the GIL is not supported by this build");
1821
0
#endif
1822
0
    }
1823
0
    else if (len == 1 && first_char == L'1') {
1824
#ifdef Py_GIL_DISABLED
1825
        config->enable_gil = _PyConfig_GIL_ENABLE;
1826
#else
1827
0
        return _PyStatus_OK();
1828
0
#endif
1829
0
    }
1830
0
    else {
1831
0
        return _PyStatus_ERR("PYTHON_GIL / -X gil must be \"0\" or \"1\"");
1832
0
    }
1833
0
    return _PyStatus_OK();
1834
0
}
1835
1836
static PyStatus
1837
config_read_env_vars(PyConfig *config)
1838
16
{
1839
16
    PyStatus status;
1840
16
    int use_env = config->use_environment;
1841
1842
    /* Get environment variables */
1843
16
    _Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG");
1844
16
    _Py_get_env_flag(use_env, &config->verbose, "PYTHONVERBOSE");
1845
16
    _Py_get_env_flag(use_env, &config->optimization_level, "PYTHONOPTIMIZE");
1846
16
    _Py_get_env_flag(use_env, &config->inspect, "PYTHONINSPECT");
1847
1848
16
    int dont_write_bytecode = 0;
1849
16
    _Py_get_env_flag(use_env, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
1850
16
    if (dont_write_bytecode) {
1851
0
        config->write_bytecode = 0;
1852
0
    }
1853
1854
16
    int no_user_site_directory = 0;
1855
16
    _Py_get_env_flag(use_env, &no_user_site_directory, "PYTHONNOUSERSITE");
1856
16
    if (no_user_site_directory) {
1857
0
        config->user_site_directory = 0;
1858
0
    }
1859
1860
16
    int unbuffered_stdio = 0;
1861
16
    _Py_get_env_flag(use_env, &unbuffered_stdio, "PYTHONUNBUFFERED");
1862
16
    if (unbuffered_stdio) {
1863
0
        config->buffered_stdio = 0;
1864
0
    }
1865
1866
#ifdef MS_WINDOWS
1867
    _Py_get_env_flag(use_env, &config->legacy_windows_stdio,
1868
                     "PYTHONLEGACYWINDOWSSTDIO");
1869
#endif
1870
1871
16
    if (config_get_env(config, "PYTHONDUMPREFS")) {
1872
0
        config->dump_refs = 1;
1873
0
    }
1874
16
    if (config_get_env(config, "PYTHONMALLOCSTATS")) {
1875
0
        config->malloc_stats = 1;
1876
0
    }
1877
1878
16
    if (config->dump_refs_file == NULL) {
1879
16
        status = CONFIG_GET_ENV_DUP(config, &config->dump_refs_file,
1880
16
                                    L"PYTHONDUMPREFSFILE", "PYTHONDUMPREFSFILE");
1881
16
        if (_PyStatus_EXCEPTION(status)) {
1882
0
            return status;
1883
0
        }
1884
16
    }
1885
1886
16
    if (config->pythonpath_env == NULL) {
1887
16
        status = CONFIG_GET_ENV_DUP(config, &config->pythonpath_env,
1888
16
                                    L"PYTHONPATH", "PYTHONPATH");
1889
16
        if (_PyStatus_EXCEPTION(status)) {
1890
0
            return status;
1891
0
        }
1892
16
    }
1893
1894
16
    if(config->platlibdir == NULL) {
1895
16
        status = CONFIG_GET_ENV_DUP(config, &config->platlibdir,
1896
16
                                    L"PYTHONPLATLIBDIR", "PYTHONPLATLIBDIR");
1897
16
        if (_PyStatus_EXCEPTION(status)) {
1898
0
            return status;
1899
0
        }
1900
16
    }
1901
1902
16
    if (config->use_hash_seed < 0) {
1903
16
        status = config_init_hash_seed(config);
1904
16
        if (_PyStatus_EXCEPTION(status)) {
1905
0
            return status;
1906
0
        }
1907
16
    }
1908
1909
16
    if (config_get_env(config, "PYTHONSAFEPATH")) {
1910
0
        config->safe_path = 1;
1911
0
    }
1912
1913
16
    const char *gil = config_get_env(config, "PYTHON_GIL");
1914
16
    if (gil != NULL) {
1915
0
        size_t len = strlen(gil);
1916
0
        status = config_read_gil(config, len, gil[0]);
1917
0
        if (_PyStatus_EXCEPTION(status)) {
1918
0
            return status;
1919
0
        }
1920
0
    }
1921
1922
16
    return _PyStatus_OK();
1923
16
}
1924
1925
static PyStatus
1926
config_init_cpu_count(PyConfig *config)
1927
16
{
1928
16
    const char *env = config_get_env(config, "PYTHON_CPU_COUNT");
1929
16
    if (env) {
1930
0
        int cpu_count = -1;
1931
0
        if (strcmp(env, "default") == 0) {
1932
0
            cpu_count = -1;
1933
0
        }
1934
0
        else if (_Py_str_to_int(env, &cpu_count) < 0 || cpu_count < 1) {
1935
0
            goto error;
1936
0
        }
1937
0
        config->cpu_count = cpu_count;
1938
0
    }
1939
1940
16
    const wchar_t *xoption = config_get_xoption(config, L"cpu_count");
1941
16
    if (xoption) {
1942
0
        int cpu_count = -1;
1943
0
        const wchar_t *sep = wcschr(xoption, L'=');
1944
0
        if (sep) {
1945
0
            if (wcscmp(sep + 1, L"default") == 0) {
1946
0
                cpu_count = -1;
1947
0
            }
1948
0
            else if (config_wstr_to_int(sep + 1, &cpu_count) < 0 || cpu_count < 1) {
1949
0
                goto error;
1950
0
            }
1951
0
        }
1952
0
        else {
1953
0
            goto error;
1954
0
        }
1955
0
        config->cpu_count = cpu_count;
1956
0
    }
1957
16
    return _PyStatus_OK();
1958
1959
0
error:
1960
0
    return _PyStatus_ERR("-X cpu_count=n option: n is missing or an invalid number, "
1961
16
                         "n must be greater than 0");
1962
16
}
1963
1964
static PyStatus
1965
config_init_thread_inherit_context(PyConfig *config)
1966
16
{
1967
16
    const char *env = config_get_env(config, "PYTHON_THREAD_INHERIT_CONTEXT");
1968
16
    if (env) {
1969
0
        int enabled;
1970
0
        if (_Py_str_to_int(env, &enabled) < 0 || (enabled < 0) || (enabled > 1)) {
1971
0
            return _PyStatus_ERR(
1972
0
                "PYTHON_THREAD_INHERIT_CONTEXT=N: N is missing or invalid");
1973
0
        }
1974
0
        config->thread_inherit_context = enabled;
1975
0
    }
1976
1977
16
    const wchar_t *xoption = config_get_xoption(config, L"thread_inherit_context");
1978
16
    if (xoption) {
1979
0
        int enabled;
1980
0
        const wchar_t *sep = wcschr(xoption, L'=');
1981
0
        if (!sep || (config_wstr_to_int(sep + 1, &enabled) < 0) || (enabled < 0) || (enabled > 1)) {
1982
0
            return _PyStatus_ERR(
1983
0
                "-X thread_inherit_context=n: n is missing or invalid");
1984
0
        }
1985
0
        config->thread_inherit_context = enabled;
1986
0
    }
1987
16
    return _PyStatus_OK();
1988
16
}
1989
1990
static PyStatus
1991
config_init_context_aware_warnings(PyConfig *config)
1992
16
{
1993
16
    const char *env = config_get_env(config, "PYTHON_CONTEXT_AWARE_WARNINGS");
1994
16
    if (env) {
1995
0
        int enabled;
1996
0
        if (_Py_str_to_int(env, &enabled) < 0 || (enabled < 0) || (enabled > 1)) {
1997
0
            return _PyStatus_ERR(
1998
0
                "PYTHON_CONTEXT_AWARE_WARNINGS=N: N is missing or invalid");
1999
0
        }
2000
0
        config->context_aware_warnings = enabled;
2001
0
    }
2002
2003
16
    const wchar_t *xoption = config_get_xoption(config, L"context_aware_warnings");
2004
16
    if (xoption) {
2005
0
        int enabled;
2006
0
        const wchar_t *sep = wcschr(xoption, L'=');
2007
0
        if (!sep || (config_wstr_to_int(sep + 1, &enabled) < 0) || (enabled < 0) || (enabled > 1)) {
2008
0
            return _PyStatus_ERR(
2009
0
                "-X context_aware_warnings=n: n is missing or invalid");
2010
0
        }
2011
0
        config->context_aware_warnings = enabled;
2012
0
    }
2013
16
    return _PyStatus_OK();
2014
16
}
2015
2016
static PyStatus
2017
config_init_tlbc(PyConfig *config)
2018
16
{
2019
#ifdef Py_GIL_DISABLED
2020
    const char *env = config_get_env(config, "PYTHON_TLBC");
2021
    if (env) {
2022
        int enabled;
2023
        if (_Py_str_to_int(env, &enabled) < 0 || (enabled < 0) || (enabled > 1)) {
2024
            return _PyStatus_ERR(
2025
                "PYTHON_TLBC=N: N is missing or invalid");
2026
        }
2027
        config->tlbc_enabled = enabled;
2028
    }
2029
2030
    const wchar_t *xoption = config_get_xoption(config, L"tlbc");
2031
    if (xoption) {
2032
        int enabled;
2033
        const wchar_t *sep = wcschr(xoption, L'=');
2034
        if (!sep || (config_wstr_to_int(sep + 1, &enabled) < 0) || (enabled < 0) || (enabled > 1)) {
2035
            return _PyStatus_ERR(
2036
                "-X tlbc=n: n is missing or invalid");
2037
        }
2038
        config->tlbc_enabled = enabled;
2039
    }
2040
    return _PyStatus_OK();
2041
#else
2042
16
    return _PyStatus_OK();
2043
16
#endif
2044
16
}
2045
2046
static PyStatus
2047
config_init_perf_profiling(PyConfig *config)
2048
16
{
2049
16
    int active = 0;
2050
16
    const char *env = config_get_env(config, "PYTHONPERFSUPPORT");
2051
16
    if (env) {
2052
0
        if (_Py_str_to_int(env, &active) != 0) {
2053
0
            active = 0;
2054
0
        }
2055
0
        if (active) {
2056
0
            config->perf_profiling = 1;
2057
0
        }
2058
0
    }
2059
16
    const wchar_t *xoption = config_get_xoption(config, L"perf");
2060
16
    if (xoption) {
2061
0
        config->perf_profiling = 1;
2062
0
    }
2063
16
    env = config_get_env(config, "PYTHON_PERF_JIT_SUPPORT");
2064
16
    if (env) {
2065
0
        if (_Py_str_to_int(env, &active) != 0) {
2066
0
            active = 0;
2067
0
        }
2068
0
        if (active) {
2069
0
            config->perf_profiling = 2;
2070
0
        }
2071
0
    }
2072
16
    xoption = config_get_xoption(config, L"perf_jit");
2073
16
    if (xoption) {
2074
0
        config->perf_profiling = 2;
2075
0
    }
2076
2077
16
    return _PyStatus_OK();
2078
2079
16
}
2080
2081
static PyStatus
2082
config_init_remote_debug(PyConfig *config)
2083
16
{
2084
#ifndef Py_REMOTE_DEBUG
2085
    config->remote_debug = 0;
2086
#else
2087
16
    int active = 1;
2088
16
    const char *env = Py_GETENV("PYTHON_DISABLE_REMOTE_DEBUG");
2089
16
    if (env) {
2090
0
        active = 0;
2091
0
    }
2092
16
    const wchar_t *xoption = config_get_xoption(config, L"disable-remote-debug");
2093
16
    if (xoption) {
2094
0
        active = 0;
2095
0
    }
2096
2097
16
    config->remote_debug = active;
2098
16
#endif
2099
16
    return _PyStatus_OK();
2100
2101
16
}
2102
2103
static PyStatus
2104
config_init_tracemalloc(PyConfig *config)
2105
16
{
2106
16
    int nframe;
2107
16
    int valid;
2108
2109
16
    const char *env = config_get_env(config, "PYTHONTRACEMALLOC");
2110
16
    if (env) {
2111
0
        if (!_Py_str_to_int(env, &nframe)) {
2112
0
            valid = (nframe >= 0);
2113
0
        }
2114
0
        else {
2115
0
            valid = 0;
2116
0
        }
2117
0
        if (!valid) {
2118
0
            return _PyStatus_ERR("PYTHONTRACEMALLOC: invalid number of frames");
2119
0
        }
2120
0
        config->tracemalloc = nframe;
2121
0
    }
2122
2123
16
    const wchar_t *xoption = config_get_xoption(config, L"tracemalloc");
2124
16
    if (xoption) {
2125
0
        const wchar_t *sep = wcschr(xoption, L'=');
2126
0
        if (sep) {
2127
0
            if (!config_wstr_to_int(sep + 1, &nframe)) {
2128
0
                valid = (nframe >= 0);
2129
0
            }
2130
0
            else {
2131
0
                valid = 0;
2132
0
            }
2133
0
            if (!valid) {
2134
0
                return _PyStatus_ERR("-X tracemalloc=NFRAME: "
2135
0
                                     "invalid number of frames");
2136
0
            }
2137
0
        }
2138
0
        else {
2139
            /* -X tracemalloc behaves as -X tracemalloc=1 */
2140
0
            nframe = 1;
2141
0
        }
2142
0
        config->tracemalloc = nframe;
2143
0
    }
2144
16
    return _PyStatus_OK();
2145
16
}
2146
2147
static PyStatus
2148
config_init_int_max_str_digits(PyConfig *config)
2149
16
{
2150
16
    int maxdigits;
2151
2152
16
    const char *env = config_get_env(config, "PYTHONINTMAXSTRDIGITS");
2153
16
    if (env) {
2154
0
        bool valid = 0;
2155
0
        if (!_Py_str_to_int(env, &maxdigits)) {
2156
0
            valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
2157
0
        }
2158
0
        if (!valid) {
2159
0
#define STRINGIFY(VAL) _STRINGIFY(VAL)
2160
0
#define _STRINGIFY(VAL) #VAL
2161
0
            return _PyStatus_ERR(
2162
0
                    "PYTHONINTMAXSTRDIGITS: invalid limit; must be >= "
2163
0
                    STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)
2164
0
                    " or 0 for unlimited.");
2165
0
        }
2166
0
        config->int_max_str_digits = maxdigits;
2167
0
    }
2168
2169
16
    const wchar_t *xoption = config_get_xoption(config, L"int_max_str_digits");
2170
16
    if (xoption) {
2171
0
        const wchar_t *sep = wcschr(xoption, L'=');
2172
0
        bool valid = 0;
2173
0
        if (sep) {
2174
0
            if (!config_wstr_to_int(sep + 1, &maxdigits)) {
2175
0
                valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
2176
0
            }
2177
0
        }
2178
0
        if (!valid) {
2179
0
            return _PyStatus_ERR(
2180
0
                    "-X int_max_str_digits: invalid limit; must be >= "
2181
0
                    STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)
2182
0
                    " or 0 for unlimited.");
2183
0
#undef _STRINGIFY
2184
0
#undef STRINGIFY
2185
0
        }
2186
0
        config->int_max_str_digits = maxdigits;
2187
0
    }
2188
16
    if (config->int_max_str_digits < 0) {
2189
16
        config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
2190
16
    }
2191
16
    return _PyStatus_OK();
2192
16
}
2193
2194
static PyStatus
2195
config_init_pycache_prefix(PyConfig *config)
2196
16
{
2197
16
    assert(config->pycache_prefix == NULL);
2198
2199
16
    const wchar_t *xoption = config_get_xoption(config, L"pycache_prefix");
2200
16
    if (xoption) {
2201
0
        const wchar_t *sep = wcschr(xoption, L'=');
2202
0
        if (sep && wcslen(sep) > 1) {
2203
0
            config->pycache_prefix = _PyMem_RawWcsdup(sep + 1);
2204
0
            if (config->pycache_prefix == NULL) {
2205
0
                return _PyStatus_NO_MEMORY();
2206
0
            }
2207
0
        }
2208
0
        else {
2209
            // PYTHONPYCACHEPREFIX env var ignored
2210
            // if "-X pycache_prefix=" option is used
2211
0
            config->pycache_prefix = NULL;
2212
0
        }
2213
0
        return _PyStatus_OK();
2214
0
    }
2215
2216
16
    return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix,
2217
16
                              L"PYTHONPYCACHEPREFIX",
2218
16
                              "PYTHONPYCACHEPREFIX");
2219
16
}
2220
2221
2222
#ifdef Py_DEBUG
2223
static PyStatus
2224
config_init_run_presite(PyConfig *config)
2225
{
2226
    assert(config->run_presite == NULL);
2227
2228
    const wchar_t *xoption = config_get_xoption(config, L"presite");
2229
    if (xoption) {
2230
        const wchar_t *sep = wcschr(xoption, L'=');
2231
        if (sep && wcslen(sep) > 1) {
2232
            config->run_presite = _PyMem_RawWcsdup(sep + 1);
2233
            if (config->run_presite == NULL) {
2234
                return _PyStatus_NO_MEMORY();
2235
            }
2236
        }
2237
        else {
2238
            // PYTHON_PRESITE env var ignored
2239
            // if "-X presite=" option is used
2240
            config->run_presite = NULL;
2241
        }
2242
        return _PyStatus_OK();
2243
    }
2244
2245
    return CONFIG_GET_ENV_DUP(config, &config->run_presite,
2246
                              L"PYTHON_PRESITE",
2247
                              "PYTHON_PRESITE");
2248
}
2249
#endif
2250
2251
static PyStatus
2252
config_init_import_time(PyConfig *config)
2253
16
{
2254
16
    int importtime = 0;
2255
2256
16
    const char *env = config_get_env(config, "PYTHONPROFILEIMPORTTIME");
2257
16
    if (env) {
2258
0
        if (_Py_str_to_int(env, &importtime) != 0) {
2259
0
            importtime = 1;
2260
0
        }
2261
0
        if (importtime < 0 || importtime > 2) {
2262
0
            return _PyStatus_ERR(
2263
0
                "PYTHONPROFILEIMPORTTIME: numeric values other than 1 and 2 "
2264
0
                "are reserved for future use.");
2265
0
        }
2266
0
    }
2267
2268
16
    const wchar_t *x_value = config_get_xoption_value(config, L"importtime");
2269
16
    if (x_value) {
2270
0
        if (*x_value == 0 || config_wstr_to_int(x_value, &importtime) != 0) {
2271
0
            importtime = 1;
2272
0
        }
2273
0
        if (importtime < 0 || importtime > 2) {
2274
0
            return _PyStatus_ERR(
2275
0
                "-X importtime: values other than 1 and 2 "
2276
0
                "are reserved for future use.");
2277
0
        }
2278
0
    }
2279
2280
16
    config->import_time = importtime;
2281
16
    return _PyStatus_OK();
2282
16
}
2283
2284
static PyStatus
2285
config_read_complex_options(PyConfig *config)
2286
16
{
2287
    /* More complex options configured by env var and -X option */
2288
16
    if (config->faulthandler < 0) {
2289
16
        if (config_get_env(config, "PYTHONFAULTHANDLER")
2290
16
           || config_get_xoption(config, L"faulthandler")) {
2291
0
            config->faulthandler = 1;
2292
0
        }
2293
16
    }
2294
16
    if (config_get_env(config, "PYTHONNODEBUGRANGES")
2295
16
       || config_get_xoption(config, L"no_debug_ranges")) {
2296
0
        config->code_debug_ranges = 0;
2297
0
    }
2298
2299
16
    PyStatus status;
2300
16
    if (config->import_time < 0) {
2301
16
        status = config_init_import_time(config);
2302
16
        if (_PyStatus_EXCEPTION(status)) {
2303
0
            return status;
2304
0
        }
2305
16
    }
2306
2307
16
    if (config->tracemalloc < 0) {
2308
16
        status = config_init_tracemalloc(config);
2309
16
        if (_PyStatus_EXCEPTION(status)) {
2310
0
            return status;
2311
0
        }
2312
16
    }
2313
2314
16
    if (config->perf_profiling < 0) {
2315
16
        status = config_init_perf_profiling(config);
2316
16
        if (_PyStatus_EXCEPTION(status)) {
2317
0
            return status;
2318
0
        }
2319
16
    }
2320
2321
16
    if (config->remote_debug < 0) {
2322
16
        status = config_init_remote_debug(config);
2323
16
        if (_PyStatus_EXCEPTION(status)) {
2324
0
            return status;
2325
0
        }
2326
16
    }
2327
2328
16
    if (config->int_max_str_digits < 0) {
2329
16
        status = config_init_int_max_str_digits(config);
2330
16
        if (_PyStatus_EXCEPTION(status)) {
2331
0
            return status;
2332
0
        }
2333
16
    }
2334
2335
16
    if (config->cpu_count < 0) {
2336
16
        status = config_init_cpu_count(config);
2337
16
        if (_PyStatus_EXCEPTION(status)) {
2338
0
            return status;
2339
0
        }
2340
16
    }
2341
2342
16
    if (config->pycache_prefix == NULL) {
2343
16
        status = config_init_pycache_prefix(config);
2344
16
        if (_PyStatus_EXCEPTION(status)) {
2345
0
            return status;
2346
0
        }
2347
16
    }
2348
2349
#ifdef Py_DEBUG
2350
    if (config->run_presite == NULL) {
2351
        status = config_init_run_presite(config);
2352
        if (_PyStatus_EXCEPTION(status)) {
2353
            return status;
2354
        }
2355
    }
2356
#endif
2357
2358
16
    status = config_init_thread_inherit_context(config);
2359
16
    if (_PyStatus_EXCEPTION(status)) {
2360
0
        return status;
2361
0
    }
2362
2363
16
    status = config_init_context_aware_warnings(config);
2364
16
    if (_PyStatus_EXCEPTION(status)) {
2365
0
        return status;
2366
0
    }
2367
2368
16
    status = config_init_tlbc(config);
2369
16
    if (_PyStatus_EXCEPTION(status)) {
2370
0
        return status;
2371
0
    }
2372
2373
16
    return _PyStatus_OK();
2374
16
}
2375
2376
2377
static const wchar_t *
2378
config_get_stdio_errors(const PyPreConfig *preconfig)
2379
16
{
2380
16
    if (preconfig->utf8_mode) {
2381
        /* UTF-8 Mode uses UTF-8/surrogateescape */
2382
0
        return L"surrogateescape";
2383
0
    }
2384
2385
16
#ifndef MS_WINDOWS
2386
16
    const char *loc = setlocale(LC_CTYPE, NULL);
2387
16
    if (loc != NULL) {
2388
        /* surrogateescape is the default in the legacy C and POSIX locales */
2389
16
        if (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0) {
2390
16
            return L"surrogateescape";
2391
16
        }
2392
2393
0
#ifdef PY_COERCE_C_LOCALE
2394
        /* surrogateescape is the default in locale coercion target locales */
2395
0
        if (_Py_IsLocaleCoercionTarget(loc)) {
2396
0
            return L"surrogateescape";
2397
0
        }
2398
0
#endif
2399
0
    }
2400
2401
0
    return L"strict";
2402
#else
2403
    /* On Windows, always use surrogateescape by default */
2404
    return L"surrogateescape";
2405
#endif
2406
16
}
2407
2408
2409
// See also config_get_fs_encoding()
2410
static PyStatus
2411
config_get_locale_encoding(PyConfig *config, const PyPreConfig *preconfig,
2412
                           wchar_t **locale_encoding)
2413
32
{
2414
32
    wchar_t *encoding;
2415
32
    if (preconfig->utf8_mode) {
2416
0
        encoding = _PyMem_RawWcsdup(L"utf-8");
2417
0
    }
2418
32
    else {
2419
32
        encoding = _Py_GetLocaleEncoding();
2420
32
    }
2421
32
    if (encoding == NULL) {
2422
0
        return _PyStatus_NO_MEMORY();
2423
0
    }
2424
32
    PyStatus status = PyConfig_SetString(config, locale_encoding, encoding);
2425
32
    PyMem_RawFree(encoding);
2426
32
    return status;
2427
32
}
2428
2429
2430
static PyStatus
2431
config_init_stdio_encoding(PyConfig *config,
2432
                           const PyPreConfig *preconfig)
2433
16
{
2434
16
    PyStatus status;
2435
2436
    // Exit if encoding and errors are defined
2437
16
    if (config->stdio_encoding != NULL && config->stdio_errors != NULL) {
2438
0
        return _PyStatus_OK();
2439
0
    }
2440
2441
    /* PYTHONIOENCODING environment variable */
2442
16
    const char *opt = config_get_env(config, "PYTHONIOENCODING");
2443
16
    if (opt) {
2444
0
        char *pythonioencoding = _PyMem_RawStrdup(opt);
2445
0
        if (pythonioencoding == NULL) {
2446
0
            return _PyStatus_NO_MEMORY();
2447
0
        }
2448
2449
0
        char *errors = strchr(pythonioencoding, ':');
2450
0
        if (errors) {
2451
0
            *errors = '\0';
2452
0
            errors++;
2453
0
            if (!errors[0]) {
2454
0
                errors = NULL;
2455
0
            }
2456
0
        }
2457
2458
        /* Does PYTHONIOENCODING contain an encoding? */
2459
0
        if (pythonioencoding[0]) {
2460
0
            if (config->stdio_encoding == NULL) {
2461
0
                status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding,
2462
0
                                              pythonioencoding,
2463
0
                                              "PYTHONIOENCODING environment variable");
2464
0
                if (_PyStatus_EXCEPTION(status)) {
2465
0
                    PyMem_RawFree(pythonioencoding);
2466
0
                    return status;
2467
0
                }
2468
0
            }
2469
2470
            /* If the encoding is set but not the error handler,
2471
               use "strict" error handler by default.
2472
               PYTHONIOENCODING=latin1 behaves as
2473
               PYTHONIOENCODING=latin1:strict. */
2474
0
            if (!errors) {
2475
0
                errors = "strict";
2476
0
            }
2477
0
        }
2478
2479
0
        if (config->stdio_errors == NULL && errors != NULL) {
2480
0
            status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors,
2481
0
                                          errors,
2482
0
                                          "PYTHONIOENCODING environment variable");
2483
0
            if (_PyStatus_EXCEPTION(status)) {
2484
0
                PyMem_RawFree(pythonioencoding);
2485
0
                return status;
2486
0
            }
2487
0
        }
2488
2489
0
        PyMem_RawFree(pythonioencoding);
2490
0
    }
2491
2492
    /* Choose the default error handler based on the current locale. */
2493
16
    if (config->stdio_encoding == NULL) {
2494
16
        status = config_get_locale_encoding(config, preconfig,
2495
16
                                            &config->stdio_encoding);
2496
16
        if (_PyStatus_EXCEPTION(status)) {
2497
0
            return status;
2498
0
        }
2499
16
    }
2500
16
    if (config->stdio_errors == NULL) {
2501
16
        const wchar_t *errors = config_get_stdio_errors(preconfig);
2502
16
        assert(errors != NULL);
2503
2504
16
        status = PyConfig_SetString(config, &config->stdio_errors, errors);
2505
16
        if (_PyStatus_EXCEPTION(status)) {
2506
0
            return status;
2507
0
        }
2508
16
    }
2509
2510
16
    return _PyStatus_OK();
2511
16
}
2512
2513
2514
// See also config_get_locale_encoding()
2515
static PyStatus
2516
config_get_fs_encoding(PyConfig *config, const PyPreConfig *preconfig,
2517
                       wchar_t **fs_encoding)
2518
16
{
2519
#ifdef _Py_FORCE_UTF8_FS_ENCODING
2520
    return PyConfig_SetString(config, fs_encoding, L"utf-8");
2521
#elif defined(MS_WINDOWS)
2522
    const wchar_t *encoding;
2523
    if (preconfig->legacy_windows_fs_encoding) {
2524
        // Legacy Windows filesystem encoding: mbcs/replace
2525
        encoding = L"mbcs";
2526
    }
2527
    else {
2528
        // Windows defaults to utf-8/surrogatepass (PEP 529)
2529
        encoding = L"utf-8";
2530
    }
2531
     return PyConfig_SetString(config, fs_encoding, encoding);
2532
#else  // !MS_WINDOWS
2533
16
    if (preconfig->utf8_mode) {
2534
0
        return PyConfig_SetString(config, fs_encoding, L"utf-8");
2535
0
    }
2536
2537
16
    if (_Py_GetForceASCII()) {
2538
0
        return PyConfig_SetString(config, fs_encoding, L"ascii");
2539
0
    }
2540
2541
16
    return config_get_locale_encoding(config, preconfig, fs_encoding);
2542
16
#endif  // !MS_WINDOWS
2543
16
}
2544
2545
2546
static PyStatus
2547
config_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig)
2548
16
{
2549
16
    PyStatus status;
2550
2551
16
    if (config->filesystem_encoding == NULL) {
2552
16
        status = config_get_fs_encoding(config, preconfig,
2553
16
                                        &config->filesystem_encoding);
2554
16
        if (_PyStatus_EXCEPTION(status)) {
2555
0
            return status;
2556
0
        }
2557
16
    }
2558
2559
16
    if (config->filesystem_errors == NULL) {
2560
16
        const wchar_t *errors;
2561
#ifdef MS_WINDOWS
2562
        if (preconfig->legacy_windows_fs_encoding) {
2563
            errors = L"replace";
2564
        }
2565
        else {
2566
            errors = L"surrogatepass";
2567
        }
2568
#else
2569
16
        errors = L"surrogateescape";
2570
16
#endif
2571
16
        status = PyConfig_SetString(config, &config->filesystem_errors, errors);
2572
16
        if (_PyStatus_EXCEPTION(status)) {
2573
0
            return status;
2574
0
        }
2575
16
    }
2576
16
    return _PyStatus_OK();
2577
16
}
2578
2579
2580
static PyStatus
2581
config_init_import(PyConfig *config, int compute_path_config)
2582
32
{
2583
32
    PyStatus status;
2584
2585
32
    status = _PyConfig_InitPathConfig(config, compute_path_config);
2586
32
    if (_PyStatus_EXCEPTION(status)) {
2587
0
        return status;
2588
0
    }
2589
2590
32
    const char *env = config_get_env(config, "PYTHON_FROZEN_MODULES");
2591
32
    if (env == NULL) {
2592
32
    }
2593
0
    else if (strcmp(env, "on") == 0) {
2594
0
        config->use_frozen_modules = 1;
2595
0
    }
2596
0
    else if (strcmp(env, "off") == 0) {
2597
0
        config->use_frozen_modules = 0;
2598
0
    } else {
2599
0
        return PyStatus_Error("bad value for PYTHON_FROZEN_MODULES "
2600
0
                              "(expected \"on\" or \"off\")");
2601
0
    }
2602
2603
    /* -X frozen_modules=[on|off] */
2604
32
    const wchar_t *value = config_get_xoption_value(config, L"frozen_modules");
2605
32
    if (value == NULL) {
2606
32
    }
2607
0
    else if (wcscmp(value, L"on") == 0) {
2608
0
        config->use_frozen_modules = 1;
2609
0
    }
2610
0
    else if (wcscmp(value, L"off") == 0) {
2611
0
        config->use_frozen_modules = 0;
2612
0
    }
2613
0
    else if (wcslen(value) == 0) {
2614
        // "-X frozen_modules" and "-X frozen_modules=" both imply "on".
2615
0
        config->use_frozen_modules = 1;
2616
0
    }
2617
0
    else {
2618
0
        return PyStatus_Error("bad value for option -X frozen_modules "
2619
0
                              "(expected \"on\" or \"off\")");
2620
0
    }
2621
2622
32
    assert(config->use_frozen_modules >= 0);
2623
32
    return _PyStatus_OK();
2624
32
}
2625
2626
PyStatus
2627
_PyConfig_InitImportConfig(PyConfig *config)
2628
16
{
2629
16
    return config_init_import(config, 1);
2630
16
}
2631
2632
2633
static PyStatus
2634
config_read(PyConfig *config, int compute_path_config)
2635
16
{
2636
16
    PyStatus status;
2637
16
    const PyPreConfig *preconfig = &_PyRuntime.preconfig;
2638
2639
16
    if (config->use_environment) {
2640
16
        status = config_read_env_vars(config);
2641
16
        if (_PyStatus_EXCEPTION(status)) {
2642
0
            return status;
2643
0
        }
2644
16
    }
2645
2646
    /* -X options */
2647
16
    if (config_get_xoption(config, L"showrefcount")) {
2648
0
        config->show_ref_count = 1;
2649
0
    }
2650
2651
16
    const wchar_t *x_gil = config_get_xoption_value(config, L"gil");
2652
16
    if (x_gil != NULL) {
2653
0
        size_t len = wcslen(x_gil);
2654
0
        status = config_read_gil(config, len, x_gil[0]);
2655
0
        if (_PyStatus_EXCEPTION(status)) {
2656
0
            return status;
2657
0
        }
2658
0
    }
2659
2660
#ifdef Py_STATS
2661
    if (config_get_xoption(config, L"pystats")) {
2662
        config->_pystats = 1;
2663
    }
2664
    else if (config_get_env(config, "PYTHONSTATS")) {
2665
        config->_pystats = 1;
2666
    }
2667
    if (config->_pystats < 0) {
2668
        config->_pystats = 0;
2669
    }
2670
#endif
2671
2672
16
    status = config_read_complex_options(config);
2673
16
    if (_PyStatus_EXCEPTION(status)) {
2674
0
        return status;
2675
0
    }
2676
2677
16
    if (config->_install_importlib) {
2678
16
        status = config_init_import(config, compute_path_config);
2679
16
        if (_PyStatus_EXCEPTION(status)) {
2680
0
            return status;
2681
0
        }
2682
16
    }
2683
2684
    /* default values */
2685
16
    if (config->dev_mode) {
2686
0
        if (config->faulthandler < 0) {
2687
0
            config->faulthandler = 1;
2688
0
        }
2689
0
    }
2690
16
    if (config->faulthandler < 0) {
2691
16
        config->faulthandler = 0;
2692
16
    }
2693
16
    if (config->tracemalloc < 0) {
2694
16
        config->tracemalloc = 0;
2695
16
    }
2696
16
    if (config->perf_profiling < 0) {
2697
16
        config->perf_profiling = 0;
2698
16
    }
2699
16
    if (config->remote_debug < 0) {
2700
0
        config->remote_debug = -1;
2701
0
    }
2702
16
    if (config->use_hash_seed < 0) {
2703
0
        config->use_hash_seed = 0;
2704
0
        config->hash_seed = 0;
2705
0
    }
2706
2707
16
    if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) {
2708
16
        status = config_init_fs_encoding(config, preconfig);
2709
16
        if (_PyStatus_EXCEPTION(status)) {
2710
0
            return status;
2711
0
        }
2712
16
    }
2713
2714
16
    status = config_init_stdio_encoding(config, preconfig);
2715
16
    if (_PyStatus_EXCEPTION(status)) {
2716
0
        return status;
2717
0
    }
2718
2719
16
    if (config->argv.length < 1) {
2720
        /* Ensure at least one (empty) argument is seen */
2721
16
        status = PyWideStringList_Append(&config->argv, L"");
2722
16
        if (_PyStatus_EXCEPTION(status)) {
2723
0
            return status;
2724
0
        }
2725
16
    }
2726
2727
16
    if (config->check_hash_pycs_mode == NULL) {
2728
16
        status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
2729
16
                                    L"default");
2730
16
        if (_PyStatus_EXCEPTION(status)) {
2731
0
            return status;
2732
0
        }
2733
16
    }
2734
2735
16
    if (config->configure_c_stdio < 0) {
2736
0
        config->configure_c_stdio = 1;
2737
0
    }
2738
2739
    // Only parse arguments once.
2740
16
    if (config->parse_argv == 1) {
2741
0
        config->parse_argv = 2;
2742
0
    }
2743
2744
16
    return _PyStatus_OK();
2745
16
}
2746
2747
2748
static void
2749
config_init_stdio(const PyConfig *config)
2750
0
{
2751
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
2752
    /* don't translate newlines (\r\n <=> \n) */
2753
    _setmode(fileno(stdin), O_BINARY);
2754
    _setmode(fileno(stdout), O_BINARY);
2755
    _setmode(fileno(stderr), O_BINARY);
2756
#endif
2757
2758
0
    if (!config->buffered_stdio) {
2759
0
#ifdef HAVE_SETVBUF
2760
0
        setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
2761
0
        setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
2762
0
        setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
2763
#else /* !HAVE_SETVBUF */
2764
        setbuf(stdin,  (char *)NULL);
2765
        setbuf(stdout, (char *)NULL);
2766
        setbuf(stderr, (char *)NULL);
2767
#endif /* !HAVE_SETVBUF */
2768
0
    }
2769
0
    else if (config->interactive) {
2770
#ifdef MS_WINDOWS
2771
        /* Doesn't have to have line-buffered -- use unbuffered */
2772
        /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
2773
        setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
2774
#else /* !MS_WINDOWS */
2775
0
#ifdef HAVE_SETVBUF
2776
0
        setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
2777
0
        setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
2778
0
#endif /* HAVE_SETVBUF */
2779
0
#endif /* !MS_WINDOWS */
2780
        /* Leave stderr alone - it should be unbuffered anyway. */
2781
0
    }
2782
0
}
2783
2784
2785
/* Write the configuration:
2786
2787
   - set Py_xxx global configuration variables
2788
   - initialize C standard streams (stdin, stdout, stderr) */
2789
PyStatus
2790
_PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime)
2791
16
{
2792
16
    config_set_global_vars(config);
2793
2794
16
    if (config->configure_c_stdio) {
2795
0
        config_init_stdio(config);
2796
0
    }
2797
2798
    /* Write the new pre-configuration into _PyRuntime */
2799
16
    PyPreConfig *preconfig = &runtime->preconfig;
2800
16
    preconfig->isolated = config->isolated;
2801
16
    preconfig->use_environment = config->use_environment;
2802
16
    preconfig->dev_mode = config->dev_mode;
2803
2804
16
    if (_Py_SetArgcArgv(config->orig_argv.length,
2805
16
                        config->orig_argv.items) < 0)
2806
0
    {
2807
0
        return _PyStatus_NO_MEMORY();
2808
0
    }
2809
2810
#ifdef Py_STATS
2811
    if (config->_pystats) {
2812
        _Py_StatsOn();
2813
    }
2814
#endif
2815
2816
16
    return _PyStatus_OK();
2817
16
}
2818
2819
2820
/* --- PyConfig command line parser -------------------------- */
2821
2822
static void
2823
config_usage(int error, const wchar_t* program)
2824
0
{
2825
0
    FILE *f = error ? stderr : stdout;
2826
2827
0
    fprintf(f, usage_line, program);
2828
0
    if (error)
2829
0
        fprintf(f, "Try `python -h' for more information.\n");
2830
0
    else {
2831
0
        fputs(usage_help, f);
2832
0
    }
2833
0
}
2834
2835
static void
2836
config_envvars_usage(void)
2837
0
{
2838
0
    printf(usage_envvars, (wint_t)DELIM, (wint_t)DELIM, PYTHONHOMEHELP);
2839
0
}
2840
2841
static void
2842
config_xoptions_usage(void)
2843
0
{
2844
0
    puts(usage_xoptions);
2845
0
}
2846
2847
static void
2848
config_complete_usage(const wchar_t* program)
2849
0
{
2850
0
   config_usage(0, program);
2851
0
   putchar('\n');
2852
0
   config_envvars_usage();
2853
0
   putchar('\n');
2854
0
   config_xoptions_usage();
2855
0
}
2856
2857
2858
/* Parse the command line arguments */
2859
static PyStatus
2860
config_parse_cmdline(PyConfig *config, PyWideStringList *warnoptions,
2861
                     Py_ssize_t *opt_index)
2862
0
{
2863
0
    PyStatus status;
2864
0
    const PyWideStringList *argv = &config->argv;
2865
0
    int print_version = 0;
2866
0
    const wchar_t* program = config->program_name;
2867
0
    if (!program && argv->length >= 1) {
2868
0
        program = argv->items[0];
2869
0
    }
2870
2871
0
    _PyOS_ResetGetOpt();
2872
0
    do {
2873
0
        int longindex = -1;
2874
0
        int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
2875
0
        if (c == EOF) {
2876
0
            break;
2877
0
        }
2878
2879
0
        if (c == 'c') {
2880
0
            if (config->run_command == NULL) {
2881
                /* -c is the last option; following arguments
2882
                   that look like options are left for the
2883
                   command to interpret. */
2884
0
                size_t len = wcslen(_PyOS_optarg) + 1 + 1;
2885
0
                wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len);
2886
0
                if (command == NULL) {
2887
0
                    return _PyStatus_NO_MEMORY();
2888
0
                }
2889
0
                memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t));
2890
0
                command[len - 2] = '\n';
2891
0
                command[len - 1] = 0;
2892
0
                config->run_command = command;
2893
0
            }
2894
0
            break;
2895
0
        }
2896
2897
0
        if (c == 'm') {
2898
            /* -m is the last option; following arguments
2899
               that look like options are left for the
2900
               module to interpret. */
2901
0
            if (config->run_module == NULL) {
2902
0
                config->run_module = _PyMem_RawWcsdup(_PyOS_optarg);
2903
0
                if (config->run_module == NULL) {
2904
0
                    return _PyStatus_NO_MEMORY();
2905
0
                }
2906
0
            }
2907
0
            break;
2908
0
        }
2909
2910
0
        switch (c) {
2911
        // Integers represent long options, see Python/getopt.c
2912
0
        case 0:
2913
            // check-hash-based-pycs
2914
0
            if (wcscmp(_PyOS_optarg, L"always") == 0
2915
0
                || wcscmp(_PyOS_optarg, L"never") == 0
2916
0
                || wcscmp(_PyOS_optarg, L"default") == 0)
2917
0
            {
2918
0
                status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
2919
0
                                            _PyOS_optarg);
2920
0
                if (_PyStatus_EXCEPTION(status)) {
2921
0
                    return status;
2922
0
                }
2923
0
            } else {
2924
0
                fprintf(stderr, "--check-hash-based-pycs must be one of "
2925
0
                        "'default', 'always', or 'never'\n");
2926
0
                config_usage(1, program);
2927
0
                return _PyStatus_EXIT(2);
2928
0
            }
2929
0
            break;
2930
2931
0
        case 1:
2932
            // help-all
2933
0
            config_complete_usage(program);
2934
0
            return _PyStatus_EXIT(0);
2935
2936
0
        case 2:
2937
            // help-env
2938
0
            config_envvars_usage();
2939
0
            return _PyStatus_EXIT(0);
2940
2941
0
        case 3:
2942
            // help-xoptions
2943
0
            config_xoptions_usage();
2944
0
            return _PyStatus_EXIT(0);
2945
2946
0
        case 'b':
2947
0
            config->bytes_warning++;
2948
0
            break;
2949
2950
0
        case 'd':
2951
0
            config->parser_debug++;
2952
0
            break;
2953
2954
0
        case 'i':
2955
0
            config->inspect++;
2956
0
            config->interactive++;
2957
0
            break;
2958
2959
0
        case 'E':
2960
0
        case 'I':
2961
0
        case 'X':
2962
            /* option handled by _PyPreCmdline_Read() */
2963
0
            break;
2964
2965
0
        case 'O':
2966
0
            config->optimization_level++;
2967
0
            break;
2968
2969
0
        case 'P':
2970
0
            config->safe_path = 1;
2971
0
            break;
2972
2973
0
        case 'B':
2974
0
            config->write_bytecode = 0;
2975
0
            break;
2976
2977
0
        case 's':
2978
0
            config->user_site_directory = 0;
2979
0
            break;
2980
2981
0
        case 'S':
2982
0
            config->site_import = 0;
2983
0
            break;
2984
2985
0
        case 't':
2986
            /* ignored for backwards compatibility */
2987
0
            break;
2988
2989
0
        case 'u':
2990
0
            config->buffered_stdio = 0;
2991
0
            break;
2992
2993
0
        case 'v':
2994
0
            config->verbose++;
2995
0
            break;
2996
2997
0
        case 'x':
2998
0
            config->skip_source_first_line = 1;
2999
0
            break;
3000
3001
0
        case 'h':
3002
0
        case '?':
3003
0
            config_usage(0, program);
3004
0
            return _PyStatus_EXIT(0);
3005
3006
0
        case 'V':
3007
0
            print_version++;
3008
0
            break;
3009
3010
0
        case 'W':
3011
0
            status = PyWideStringList_Append(warnoptions, _PyOS_optarg);
3012
0
            if (_PyStatus_EXCEPTION(status)) {
3013
0
                return status;
3014
0
            }
3015
0
            break;
3016
3017
0
        case 'q':
3018
0
            config->quiet++;
3019
0
            break;
3020
3021
0
        case 'R':
3022
0
            config->use_hash_seed = 0;
3023
0
            break;
3024
3025
        /* This space reserved for other options */
3026
3027
0
        default:
3028
            /* unknown argument: parsing failed */
3029
0
            config_usage(1, program);
3030
0
            return _PyStatus_EXIT(2);
3031
0
        }
3032
0
    } while (1);
3033
3034
0
    if (print_version) {
3035
0
        printf("Python %s\n",
3036
0
                (print_version >= 2) ? Py_GetVersion() : PY_VERSION);
3037
0
        return _PyStatus_EXIT(0);
3038
0
    }
3039
3040
0
    if (config->run_command == NULL && config->run_module == NULL
3041
0
        && _PyOS_optind < argv->length
3042
0
        && wcscmp(argv->items[_PyOS_optind], L"-") != 0
3043
0
        && config->run_filename == NULL)
3044
0
    {
3045
0
        config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]);
3046
0
        if (config->run_filename == NULL) {
3047
0
            return _PyStatus_NO_MEMORY();
3048
0
        }
3049
0
    }
3050
3051
0
    if (config->run_command != NULL || config->run_module != NULL) {
3052
        /* Backup _PyOS_optind */
3053
0
        _PyOS_optind--;
3054
0
    }
3055
3056
0
    *opt_index = _PyOS_optind;
3057
3058
0
    return _PyStatus_OK();
3059
0
}
3060
3061
3062
#ifdef MS_WINDOWS
3063
#  define WCSTOK wcstok_s
3064
#else
3065
0
#  define WCSTOK wcstok
3066
#endif
3067
3068
/* Get warning options from PYTHONWARNINGS environment variable. */
3069
static PyStatus
3070
config_init_env_warnoptions(PyConfig *config, PyWideStringList *warnoptions)
3071
16
{
3072
16
    PyStatus status;
3073
    /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */
3074
16
    wchar_t *env = NULL;
3075
16
    status = CONFIG_GET_ENV_DUP(config, &env,
3076
16
                             L"PYTHONWARNINGS", "PYTHONWARNINGS");
3077
16
    if (_PyStatus_EXCEPTION(status)) {
3078
0
        return status;
3079
0
    }
3080
3081
    /* env var is not set or is empty */
3082
16
    if (env == NULL) {
3083
16
        return _PyStatus_OK();
3084
16
    }
3085
3086
3087
0
    wchar_t *warning, *context = NULL;
3088
0
    for (warning = WCSTOK(env, L",", &context);
3089
0
         warning != NULL;
3090
0
         warning = WCSTOK(NULL, L",", &context))
3091
0
    {
3092
0
        status = PyWideStringList_Append(warnoptions, warning);
3093
0
        if (_PyStatus_EXCEPTION(status)) {
3094
0
            PyMem_RawFree(env);
3095
0
            return status;
3096
0
        }
3097
0
    }
3098
0
    PyMem_RawFree(env);
3099
0
    return _PyStatus_OK();
3100
0
}
3101
3102
3103
static PyStatus
3104
warnoptions_append(PyConfig *config, PyWideStringList *options,
3105
                   const wchar_t *option)
3106
0
{
3107
    /* config_init_warnoptions() add existing config warnoptions at the end:
3108
       ensure that the new option is not already present in this list to
3109
       prevent change the options order when config_init_warnoptions() is
3110
       called twice. */
3111
0
    if (_PyWideStringList_Find(&config->warnoptions, option)) {
3112
        /* Already present: do nothing */
3113
0
        return _PyStatus_OK();
3114
0
    }
3115
0
    if (_PyWideStringList_Find(options, option)) {
3116
        /* Already present: do nothing */
3117
0
        return _PyStatus_OK();
3118
0
    }
3119
0
    return PyWideStringList_Append(options, option);
3120
0
}
3121
3122
3123
static PyStatus
3124
warnoptions_extend(PyConfig *config, PyWideStringList *options,
3125
                   const PyWideStringList *options2)
3126
48
{
3127
48
    const Py_ssize_t len = options2->length;
3128
48
    wchar_t *const *items = options2->items;
3129
3130
48
    for (Py_ssize_t i = 0; i < len; i++) {
3131
0
        PyStatus status = warnoptions_append(config, options, items[i]);
3132
0
        if (_PyStatus_EXCEPTION(status)) {
3133
0
            return status;
3134
0
        }
3135
0
    }
3136
48
    return _PyStatus_OK();
3137
48
}
3138
3139
3140
static PyStatus
3141
config_init_warnoptions(PyConfig *config,
3142
                        const PyWideStringList *cmdline_warnoptions,
3143
                        const PyWideStringList *env_warnoptions,
3144
                        const PyWideStringList *sys_warnoptions)
3145
16
{
3146
16
    PyStatus status;
3147
16
    PyWideStringList options = _PyWideStringList_INIT;
3148
3149
    /* Priority of warnings options, lowest to highest:
3150
     *
3151
     * - any implicit filters added by _warnings.c/warnings.py
3152
     * - PyConfig.dev_mode: "default" filter
3153
     * - PYTHONWARNINGS environment variable
3154
     * - '-W' command line options
3155
     * - PyConfig.bytes_warning ('-b' and '-bb' command line options):
3156
     *   "default::BytesWarning" or "error::BytesWarning" filter
3157
     * - early PySys_AddWarnOption() calls
3158
     * - PyConfig.warnoptions
3159
     *
3160
     * PyConfig.warnoptions is copied to sys.warnoptions. Since the warnings
3161
     * module works on the basis of "the most recently added filter will be
3162
     * checked first", we add the lowest precedence entries first so that later
3163
     * entries override them.
3164
     */
3165
3166
16
    if (config->dev_mode) {
3167
0
        status = warnoptions_append(config, &options, L"default");
3168
0
        if (_PyStatus_EXCEPTION(status)) {
3169
0
            goto error;
3170
0
        }
3171
0
    }
3172
3173
16
    status = warnoptions_extend(config, &options, env_warnoptions);
3174
16
    if (_PyStatus_EXCEPTION(status)) {
3175
0
        goto error;
3176
0
    }
3177
3178
16
    status = warnoptions_extend(config, &options, cmdline_warnoptions);
3179
16
    if (_PyStatus_EXCEPTION(status)) {
3180
0
        goto error;
3181
0
    }
3182
3183
    /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c
3184
     * don't even try to emit a warning, so we skip setting the filter in that
3185
     * case.
3186
     */
3187
16
    if (config->bytes_warning) {
3188
0
        const wchar_t *filter;
3189
0
        if (config->bytes_warning> 1) {
3190
0
            filter = L"error::BytesWarning";
3191
0
        }
3192
0
        else {
3193
0
            filter = L"default::BytesWarning";
3194
0
        }
3195
0
        status = warnoptions_append(config, &options, filter);
3196
0
        if (_PyStatus_EXCEPTION(status)) {
3197
0
            goto error;
3198
0
        }
3199
0
    }
3200
3201
16
    status = warnoptions_extend(config, &options, sys_warnoptions);
3202
16
    if (_PyStatus_EXCEPTION(status)) {
3203
0
        goto error;
3204
0
    }
3205
3206
    /* Always add all PyConfig.warnoptions options */
3207
16
    status = _PyWideStringList_Extend(&options, &config->warnoptions);
3208
16
    if (_PyStatus_EXCEPTION(status)) {
3209
0
        goto error;
3210
0
    }
3211
3212
16
    _PyWideStringList_Clear(&config->warnoptions);
3213
16
    config->warnoptions = options;
3214
16
    return _PyStatus_OK();
3215
3216
0
error:
3217
0
    _PyWideStringList_Clear(&options);
3218
0
    return status;
3219
16
}
3220
3221
3222
static PyStatus
3223
config_update_argv(PyConfig *config, Py_ssize_t opt_index)
3224
0
{
3225
0
    const PyWideStringList *cmdline_argv = &config->argv;
3226
0
    PyWideStringList config_argv = _PyWideStringList_INIT;
3227
3228
    /* Copy argv to be able to modify it (to force -c/-m) */
3229
0
    if (cmdline_argv->length <= opt_index) {
3230
        /* Ensure at least one (empty) argument is seen */
3231
0
        PyStatus status = PyWideStringList_Append(&config_argv, L"");
3232
0
        if (_PyStatus_EXCEPTION(status)) {
3233
0
            return status;
3234
0
        }
3235
0
    }
3236
0
    else {
3237
0
        PyWideStringList slice;
3238
0
        slice.length = cmdline_argv->length - opt_index;
3239
0
        slice.items = &cmdline_argv->items[opt_index];
3240
0
        if (_PyWideStringList_Copy(&config_argv, &slice) < 0) {
3241
0
            return _PyStatus_NO_MEMORY();
3242
0
        }
3243
0
    }
3244
0
    assert(config_argv.length >= 1);
3245
3246
0
    wchar_t *arg0 = NULL;
3247
0
    if (config->run_command != NULL) {
3248
        /* Force sys.argv[0] = '-c' */
3249
0
        arg0 = L"-c";
3250
0
    }
3251
0
    else if (config->run_module != NULL) {
3252
        /* Force sys.argv[0] = '-m'*/
3253
0
        arg0 = L"-m";
3254
0
    }
3255
3256
0
    if (arg0 != NULL) {
3257
0
        arg0 = _PyMem_RawWcsdup(arg0);
3258
0
        if (arg0 == NULL) {
3259
0
            _PyWideStringList_Clear(&config_argv);
3260
0
            return _PyStatus_NO_MEMORY();
3261
0
        }
3262
3263
0
        PyMem_RawFree(config_argv.items[0]);
3264
0
        config_argv.items[0] = arg0;
3265
0
    }
3266
3267
0
    _PyWideStringList_Clear(&config->argv);
3268
0
    config->argv = config_argv;
3269
0
    return _PyStatus_OK();
3270
0
}
3271
3272
3273
static PyStatus
3274
core_read_precmdline(PyConfig *config, _PyPreCmdline *precmdline)
3275
16
{
3276
16
    PyStatus status;
3277
3278
16
    if (config->parse_argv == 1) {
3279
0
        if (_PyWideStringList_Copy(&precmdline->argv, &config->argv) < 0) {
3280
0
            return _PyStatus_NO_MEMORY();
3281
0
        }
3282
0
    }
3283
3284
16
    PyPreConfig preconfig;
3285
3286
16
    status = _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig);
3287
16
    if (_PyStatus_EXCEPTION(status)) {
3288
0
        return status;
3289
0
    }
3290
3291
16
    _PyPreConfig_GetConfig(&preconfig, config);
3292
3293
16
    status = _PyPreCmdline_Read(precmdline, &preconfig);
3294
16
    if (_PyStatus_EXCEPTION(status)) {
3295
0
        return status;
3296
0
    }
3297
3298
16
    status = _PyPreCmdline_SetConfig(precmdline, config);
3299
16
    if (_PyStatus_EXCEPTION(status)) {
3300
0
        return status;
3301
0
    }
3302
16
    return _PyStatus_OK();
3303
16
}
3304
3305
3306
/* Get run_filename absolute path */
3307
static PyStatus
3308
config_run_filename_abspath(PyConfig *config)
3309
16
{
3310
16
    if (!config->run_filename) {
3311
16
        return _PyStatus_OK();
3312
16
    }
3313
3314
0
#ifndef MS_WINDOWS
3315
0
    if (_Py_isabs(config->run_filename)) {
3316
        /* path is already absolute */
3317
0
        return _PyStatus_OK();
3318
0
    }
3319
0
#endif
3320
3321
0
    wchar_t *abs_filename;
3322
0
    if (_Py_abspath(config->run_filename, &abs_filename) < 0) {
3323
        /* failed to get the absolute path of the command line filename:
3324
           ignore the error, keep the relative path */
3325
0
        return _PyStatus_OK();
3326
0
    }
3327
0
    if (abs_filename == NULL) {
3328
0
        return _PyStatus_NO_MEMORY();
3329
0
    }
3330
3331
0
    PyMem_RawFree(config->run_filename);
3332
0
    config->run_filename = abs_filename;
3333
0
    return _PyStatus_OK();
3334
0
}
3335
3336
3337
static PyStatus
3338
config_read_cmdline(PyConfig *config)
3339
16
{
3340
16
    PyStatus status;
3341
16
    PyWideStringList cmdline_warnoptions = _PyWideStringList_INIT;
3342
16
    PyWideStringList env_warnoptions = _PyWideStringList_INIT;
3343
16
    PyWideStringList sys_warnoptions = _PyWideStringList_INIT;
3344
3345
16
    if (config->parse_argv < 0) {
3346
0
        config->parse_argv = 1;
3347
0
    }
3348
3349
16
    if (config->parse_argv == 1) {
3350
0
        Py_ssize_t opt_index;
3351
0
        status = config_parse_cmdline(config, &cmdline_warnoptions, &opt_index);
3352
0
        if (_PyStatus_EXCEPTION(status)) {
3353
0
            goto done;
3354
0
        }
3355
3356
0
        status = config_run_filename_abspath(config);
3357
0
        if (_PyStatus_EXCEPTION(status)) {
3358
0
            goto done;
3359
0
        }
3360
3361
0
        status = config_update_argv(config, opt_index);
3362
0
        if (_PyStatus_EXCEPTION(status)) {
3363
0
            goto done;
3364
0
        }
3365
0
    }
3366
16
    else {
3367
16
        status = config_run_filename_abspath(config);
3368
16
        if (_PyStatus_EXCEPTION(status)) {
3369
0
            goto done;
3370
0
        }
3371
16
    }
3372
3373
16
    if (config->use_environment) {
3374
16
        status = config_init_env_warnoptions(config, &env_warnoptions);
3375
16
        if (_PyStatus_EXCEPTION(status)) {
3376
0
            goto done;
3377
0
        }
3378
16
    }
3379
3380
    /* Handle early PySys_AddWarnOption() calls */
3381
16
    status = _PySys_ReadPreinitWarnOptions(&sys_warnoptions);
3382
16
    if (_PyStatus_EXCEPTION(status)) {
3383
0
        goto done;
3384
0
    }
3385
3386
16
    status = config_init_warnoptions(config,
3387
16
                                     &cmdline_warnoptions,
3388
16
                                     &env_warnoptions,
3389
16
                                     &sys_warnoptions);
3390
16
    if (_PyStatus_EXCEPTION(status)) {
3391
0
        goto done;
3392
0
    }
3393
3394
16
    status = _PyStatus_OK();
3395
3396
16
done:
3397
16
    _PyWideStringList_Clear(&cmdline_warnoptions);
3398
16
    _PyWideStringList_Clear(&env_warnoptions);
3399
16
    _PyWideStringList_Clear(&sys_warnoptions);
3400
16
    return status;
3401
16
}
3402
3403
3404
PyStatus
3405
_PyConfig_SetPyArgv(PyConfig *config, const _PyArgv *args)
3406
0
{
3407
0
    PyStatus status = _Py_PreInitializeFromConfig(config, args);
3408
0
    if (_PyStatus_EXCEPTION(status)) {
3409
0
        return status;
3410
0
    }
3411
3412
0
    return _PyArgv_AsWstrList(args, &config->argv);
3413
0
}
3414
3415
3416
/* Set config.argv: decode argv using Py_DecodeLocale(). Pre-initialize Python
3417
   if needed to ensure that encodings are properly configured. */
3418
PyStatus
3419
PyConfig_SetBytesArgv(PyConfig *config, Py_ssize_t argc, char * const *argv)
3420
0
{
3421
0
    _PyArgv args = {
3422
0
        .argc = argc,
3423
0
        .use_bytes_argv = 1,
3424
0
        .bytes_argv = argv,
3425
0
        .wchar_argv = NULL};
3426
0
    return _PyConfig_SetPyArgv(config, &args);
3427
0
}
3428
3429
3430
PyStatus
3431
PyConfig_SetArgv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv)
3432
0
{
3433
0
    _PyArgv args = {
3434
0
        .argc = argc,
3435
0
        .use_bytes_argv = 0,
3436
0
        .bytes_argv = NULL,
3437
0
        .wchar_argv = argv};
3438
0
    return _PyConfig_SetPyArgv(config, &args);
3439
0
}
3440
3441
3442
PyStatus
3443
PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list,
3444
                           Py_ssize_t length, wchar_t **items)
3445
0
{
3446
0
    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
3447
0
    if (_PyStatus_EXCEPTION(status)) {
3448
0
        return status;
3449
0
    }
3450
3451
0
    PyWideStringList list2 = {.length = length, .items = items};
3452
0
    if (_PyWideStringList_Copy(list, &list2) < 0) {
3453
0
        return _PyStatus_NO_MEMORY();
3454
0
    }
3455
0
    return _PyStatus_OK();
3456
0
}
3457
3458
3459
/* Read the configuration into PyConfig from:
3460
3461
   * Command line arguments
3462
   * Environment variables
3463
   * Py_xxx global configuration variables
3464
3465
   The only side effects are to modify config and to call _Py_SetArgcArgv(). */
3466
PyStatus
3467
_PyConfig_Read(PyConfig *config, int compute_path_config)
3468
16
{
3469
16
    PyStatus status;
3470
3471
16
    status = _Py_PreInitializeFromConfig(config, NULL);
3472
16
    if (_PyStatus_EXCEPTION(status)) {
3473
0
        return status;
3474
0
    }
3475
3476
16
    config_get_global_vars(config);
3477
3478
16
    if (config->orig_argv.length == 0
3479
16
        && !(config->argv.length == 1
3480
16
             && wcscmp(config->argv.items[0], L"") == 0))
3481
16
    {
3482
16
        if (_PyWideStringList_Copy(&config->orig_argv, &config->argv) < 0) {
3483
0
            return _PyStatus_NO_MEMORY();
3484
0
        }
3485
16
    }
3486
3487
16
    _PyPreCmdline precmdline = _PyPreCmdline_INIT;
3488
16
    status = core_read_precmdline(config, &precmdline);
3489
16
    if (_PyStatus_EXCEPTION(status)) {
3490
0
        goto done;
3491
0
    }
3492
3493
16
    assert(config->isolated >= 0);
3494
16
    if (config->isolated) {
3495
0
        config->safe_path = 1;
3496
0
        config->use_environment = 0;
3497
0
        config->user_site_directory = 0;
3498
0
    }
3499
3500
16
    status = config_read_cmdline(config);
3501
16
    if (_PyStatus_EXCEPTION(status)) {
3502
0
        goto done;
3503
0
    }
3504
3505
    /* Handle early PySys_AddXOption() calls */
3506
16
    status = _PySys_ReadPreinitXOptions(config);
3507
16
    if (_PyStatus_EXCEPTION(status)) {
3508
0
        goto done;
3509
0
    }
3510
3511
16
    status = config_read(config, compute_path_config);
3512
16
    if (_PyStatus_EXCEPTION(status)) {
3513
0
        goto done;
3514
0
    }
3515
3516
16
    assert(config_check_consistency(config));
3517
3518
16
    status = _PyStatus_OK();
3519
3520
16
done:
3521
16
    _PyPreCmdline_Clear(&precmdline);
3522
16
    return status;
3523
16
}
3524
3525
3526
PyStatus
3527
PyConfig_Read(PyConfig *config)
3528
0
{
3529
0
    return _PyConfig_Read(config, 0);
3530
0
}
3531
3532
3533
PyObject*
3534
_Py_GetConfigsAsDict(void)
3535
0
{
3536
0
    PyObject *result = NULL;
3537
0
    PyObject *dict = NULL;
3538
3539
0
    result = PyDict_New();
3540
0
    if (result == NULL) {
3541
0
        goto error;
3542
0
    }
3543
3544
    /* global result */
3545
0
    dict = _Py_GetGlobalVariablesAsDict();
3546
0
    if (dict == NULL) {
3547
0
        goto error;
3548
0
    }
3549
0
    if (PyDict_SetItemString(result, "global_config", dict) < 0) {
3550
0
        goto error;
3551
0
    }
3552
0
    Py_CLEAR(dict);
3553
3554
    /* pre config */
3555
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
3556
0
    const PyPreConfig *pre_config = &interp->runtime->preconfig;
3557
0
    dict = _PyPreConfig_AsDict(pre_config);
3558
0
    if (dict == NULL) {
3559
0
        goto error;
3560
0
    }
3561
0
    if (PyDict_SetItemString(result, "pre_config", dict) < 0) {
3562
0
        goto error;
3563
0
    }
3564
0
    Py_CLEAR(dict);
3565
3566
    /* core config */
3567
0
    const PyConfig *config = _PyInterpreterState_GetConfig(interp);
3568
0
    dict = _PyConfig_AsDict(config);
3569
0
    if (dict == NULL) {
3570
0
        goto error;
3571
0
    }
3572
0
    if (PyDict_SetItemString(result, "config", dict) < 0) {
3573
0
        goto error;
3574
0
    }
3575
0
    Py_CLEAR(dict);
3576
3577
0
    return result;
3578
3579
0
error:
3580
0
    Py_XDECREF(result);
3581
0
    Py_XDECREF(dict);
3582
0
    return NULL;
3583
0
}
3584
3585
3586
static void
3587
init_dump_ascii_wstr(const wchar_t *str)
3588
0
{
3589
0
    if (str == NULL) {
3590
0
        PySys_WriteStderr("(not set)");
3591
0
        return;
3592
0
    }
3593
3594
0
    PySys_WriteStderr("'");
3595
0
    for (; *str != L'\0'; str++) {
3596
0
        unsigned int ch = (unsigned int)*str;
3597
0
        if (ch == L'\'') {
3598
0
            PySys_WriteStderr("\\'");
3599
0
        } else if (0x20 <= ch && ch < 0x7f) {
3600
0
            PySys_WriteStderr("%c", ch);
3601
0
        }
3602
0
        else if (ch <= 0xff) {
3603
0
            PySys_WriteStderr("\\x%02x", ch);
3604
0
        }
3605
0
#if SIZEOF_WCHAR_T > 2
3606
0
        else if (ch > 0xffff) {
3607
0
            PySys_WriteStderr("\\U%08x", ch);
3608
0
        }
3609
0
#endif
3610
0
        else {
3611
0
            PySys_WriteStderr("\\u%04x", ch);
3612
0
        }
3613
0
    }
3614
0
    PySys_WriteStderr("'");
3615
0
}
3616
3617
3618
/* Dump the Python path configuration into sys.stderr */
3619
void
3620
_Py_DumpPathConfig(PyThreadState *tstate)
3621
0
{
3622
0
    PyObject *exc = _PyErr_GetRaisedException(tstate);
3623
3624
0
    PySys_WriteStderr("Python path configuration:\n");
3625
3626
0
#define DUMP_CONFIG(NAME, FIELD) \
3627
0
        do { \
3628
0
            PySys_WriteStderr("  " NAME " = "); \
3629
0
            init_dump_ascii_wstr(config->FIELD); \
3630
0
            PySys_WriteStderr("\n"); \
3631
0
        } while (0)
3632
3633
0
    const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
3634
0
    DUMP_CONFIG("PYTHONHOME", home);
3635
0
    DUMP_CONFIG("PYTHONPATH", pythonpath_env);
3636
0
    DUMP_CONFIG("program name", program_name);
3637
0
    PySys_WriteStderr("  isolated = %i\n", config->isolated);
3638
0
    PySys_WriteStderr("  environment = %i\n", config->use_environment);
3639
0
    PySys_WriteStderr("  user site = %i\n", config->user_site_directory);
3640
0
    PySys_WriteStderr("  safe_path = %i\n", config->safe_path);
3641
0
    PySys_WriteStderr("  import site = %i\n", config->site_import);
3642
0
    PySys_WriteStderr("  is in build tree = %i\n", config->_is_python_build);
3643
0
    DUMP_CONFIG("stdlib dir", stdlib_dir);
3644
0
    DUMP_CONFIG("sys.path[0]", sys_path_0);
3645
0
#undef DUMP_CONFIG
3646
3647
0
#define DUMP_SYS(NAME) \
3648
0
        do { \
3649
0
            PySys_FormatStderr("  sys.%s = ", #NAME); \
3650
0
            if (PySys_GetOptionalAttrString(#NAME, &obj) < 0) { \
3651
0
                PyErr_Clear(); \
3652
0
            } \
3653
0
            if (obj != NULL) { \
3654
0
                PySys_FormatStderr("%A", obj); \
3655
0
                Py_DECREF(obj); \
3656
0
            } \
3657
0
            else { \
3658
0
                PySys_WriteStderr("(not set)"); \
3659
0
            } \
3660
0
            PySys_FormatStderr("\n"); \
3661
0
        } while (0)
3662
3663
0
    PyObject *obj;
3664
0
    DUMP_SYS(_base_executable);
3665
0
    DUMP_SYS(base_prefix);
3666
0
    DUMP_SYS(base_exec_prefix);
3667
0
    DUMP_SYS(platlibdir);
3668
0
    DUMP_SYS(executable);
3669
0
    DUMP_SYS(prefix);
3670
0
    DUMP_SYS(exec_prefix);
3671
0
#undef DUMP_SYS
3672
3673
0
    PyObject *sys_path;
3674
0
    (void) PySys_GetOptionalAttrString("path", &sys_path);
3675
0
    if (sys_path != NULL && PyList_Check(sys_path)) {
3676
0
        PySys_WriteStderr("  sys.path = [\n");
3677
0
        Py_ssize_t len = PyList_GET_SIZE(sys_path);
3678
0
        for (Py_ssize_t i=0; i < len; i++) {
3679
0
            PyObject *path = PyList_GET_ITEM(sys_path, i);
3680
0
            PySys_FormatStderr("    %A,\n", path);
3681
0
        }
3682
0
        PySys_WriteStderr("  ]\n");
3683
0
    }
3684
0
    Py_XDECREF(sys_path);
3685
3686
0
    _PyErr_SetRaisedException(tstate, exc);
3687
0
}
3688
3689
3690
// --- PyInitConfig API ---------------------------------------------------
3691
3692
struct PyInitConfig {
3693
    PyPreConfig preconfig;
3694
    PyConfig config;
3695
    struct _inittab *inittab;
3696
    Py_ssize_t inittab_size;
3697
    PyStatus status;
3698
    char *err_msg;
3699
};
3700
3701
static PyInitConfig*
3702
initconfig_alloc(void)
3703
0
{
3704
0
    return calloc(1, sizeof(PyInitConfig));
3705
0
}
3706
3707
3708
PyInitConfig*
3709
PyInitConfig_Create(void)
3710
0
{
3711
0
    PyInitConfig *config = initconfig_alloc();
3712
0
    if (config == NULL) {
3713
0
        return NULL;
3714
0
    }
3715
0
    PyPreConfig_InitIsolatedConfig(&config->preconfig);
3716
0
    PyConfig_InitIsolatedConfig(&config->config);
3717
0
    config->status = _PyStatus_OK();
3718
0
    return config;
3719
0
}
3720
3721
3722
void
3723
PyInitConfig_Free(PyInitConfig *config)
3724
0
{
3725
0
    if (config == NULL) {
3726
0
        return;
3727
0
    }
3728
0
    free(config->err_msg);
3729
0
    free(config);
3730
0
}
3731
3732
3733
int
3734
PyInitConfig_GetError(PyInitConfig* config, const char **perr_msg)
3735
0
{
3736
0
    if (_PyStatus_IS_EXIT(config->status)) {
3737
0
        char buffer[22];  // len("exit code -2147483648\0")
3738
0
        PyOS_snprintf(buffer, sizeof(buffer),
3739
0
                      "exit code %i",
3740
0
                      config->status.exitcode);
3741
3742
0
        if (config->err_msg != NULL) {
3743
0
            free(config->err_msg);
3744
0
        }
3745
0
        config->err_msg = strdup(buffer);
3746
0
        if (config->err_msg != NULL) {
3747
0
            *perr_msg = config->err_msg;
3748
0
            return 1;
3749
0
        }
3750
0
        config->status = _PyStatus_NO_MEMORY();
3751
0
    }
3752
3753
0
    if (_PyStatus_IS_ERROR(config->status) && config->status.err_msg != NULL) {
3754
0
        *perr_msg = config->status.err_msg;
3755
0
        return 1;
3756
0
    }
3757
0
    else {
3758
0
        *perr_msg = NULL;
3759
0
        return 0;
3760
0
    }
3761
0
}
3762
3763
3764
int
3765
PyInitConfig_GetExitCode(PyInitConfig* config, int *exitcode)
3766
0
{
3767
0
    if (_PyStatus_IS_EXIT(config->status)) {
3768
0
        *exitcode = config->status.exitcode;
3769
0
        return 1;
3770
0
    }
3771
0
    else {
3772
0
        return 0;
3773
0
    }
3774
0
}
3775
3776
3777
static void
3778
initconfig_set_error(PyInitConfig *config, const char *err_msg)
3779
0
{
3780
0
    config->status = _PyStatus_ERR(err_msg);
3781
0
}
3782
3783
3784
static const PyConfigSpec*
3785
initconfig_find_spec(const PyConfigSpec *spec, const char *name)
3786
0
{
3787
0
    for (; spec->name != NULL; spec++) {
3788
0
        if (strcmp(name, spec->name) == 0) {
3789
0
            return spec;
3790
0
        }
3791
0
    }
3792
0
    return NULL;
3793
0
}
3794
3795
3796
int
3797
PyInitConfig_HasOption(PyInitConfig *config, const char *name)
3798
0
{
3799
0
    const PyConfigSpec *spec = initconfig_find_spec(PYCONFIG_SPEC, name);
3800
0
    if (spec == NULL) {
3801
0
        spec = initconfig_find_spec(PYPRECONFIG_SPEC, name);
3802
0
    }
3803
0
    return (spec != NULL);
3804
0
}
3805
3806
3807
static const PyConfigSpec*
3808
initconfig_prepare(PyInitConfig *config, const char *name, void **raw_member)
3809
0
{
3810
0
    const PyConfigSpec *spec = initconfig_find_spec(PYCONFIG_SPEC, name);
3811
0
    if (spec != NULL) {
3812
0
        *raw_member = config_get_spec_member(&config->config, spec);
3813
0
        return spec;
3814
0
    }
3815
3816
0
    spec = initconfig_find_spec(PYPRECONFIG_SPEC, name);
3817
0
    if (spec != NULL) {
3818
0
        *raw_member = preconfig_get_spec_member(&config->preconfig, spec);
3819
0
        return spec;
3820
0
    }
3821
3822
0
    initconfig_set_error(config, "unknown config option name");
3823
0
    return NULL;
3824
0
}
3825
3826
3827
int
3828
PyInitConfig_GetInt(PyInitConfig *config, const char *name, int64_t *value)
3829
0
{
3830
0
    void *raw_member;
3831
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
3832
0
    if (spec == NULL) {
3833
0
        return -1;
3834
0
    }
3835
3836
0
    switch (spec->type) {
3837
0
    case PyConfig_MEMBER_INT:
3838
0
    case PyConfig_MEMBER_UINT:
3839
0
    case PyConfig_MEMBER_BOOL:
3840
0
    {
3841
0
        int *member = raw_member;
3842
0
        *value = *member;
3843
0
        break;
3844
0
    }
3845
3846
0
    case PyConfig_MEMBER_ULONG:
3847
0
    {
3848
0
        unsigned long *member = raw_member;
3849
0
#if SIZEOF_LONG >= 8
3850
0
        if ((unsigned long)INT64_MAX < *member) {
3851
0
            initconfig_set_error(config,
3852
0
                "config option value doesn't fit into int64_t");
3853
0
            return -1;
3854
0
        }
3855
0
#endif
3856
0
        *value = *member;
3857
0
        break;
3858
0
    }
3859
3860
0
    default:
3861
0
        initconfig_set_error(config, "config option type is not int");
3862
0
        return -1;
3863
0
    }
3864
0
    return 0;
3865
0
}
3866
3867
3868
static char*
3869
wstr_to_utf8(PyInitConfig *config, wchar_t *wstr)
3870
0
{
3871
0
    char *utf8;
3872
0
    int res = _Py_EncodeUTF8Ex(wstr, &utf8, NULL, NULL, 1, _Py_ERROR_STRICT);
3873
0
    if (res == -2) {
3874
0
        initconfig_set_error(config, "encoding error");
3875
0
        return NULL;
3876
0
    }
3877
0
    if (res < 0) {
3878
0
        config->status = _PyStatus_NO_MEMORY();
3879
0
        return NULL;
3880
0
    }
3881
3882
    // Copy to use the malloc() memory allocator
3883
0
    size_t size = strlen(utf8) + 1;
3884
0
    char *str = malloc(size);
3885
0
    if (str == NULL) {
3886
0
        PyMem_RawFree(utf8);
3887
0
        config->status = _PyStatus_NO_MEMORY();
3888
0
        return NULL;
3889
0
    }
3890
3891
0
    memcpy(str, utf8, size);
3892
0
    PyMem_RawFree(utf8);
3893
0
    return str;
3894
0
}
3895
3896
3897
int
3898
PyInitConfig_GetStr(PyInitConfig *config, const char *name, char **value)
3899
0
{
3900
0
    void *raw_member;
3901
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
3902
0
    if (spec == NULL) {
3903
0
        return -1;
3904
0
    }
3905
3906
0
    if (spec->type != PyConfig_MEMBER_WSTR
3907
0
        && spec->type != PyConfig_MEMBER_WSTR_OPT)
3908
0
    {
3909
0
        initconfig_set_error(config, "config option type is not string");
3910
0
        return -1;
3911
0
    }
3912
3913
0
    wchar_t **member = raw_member;
3914
0
    if (*member == NULL) {
3915
0
        *value = NULL;
3916
0
        return 0;
3917
0
    }
3918
3919
0
    *value = wstr_to_utf8(config, *member);
3920
0
    if (*value == NULL) {
3921
0
        return -1;
3922
0
    }
3923
0
    return 0;
3924
0
}
3925
3926
3927
int
3928
PyInitConfig_GetStrList(PyInitConfig *config, const char *name, size_t *length, char ***items)
3929
0
{
3930
0
    void *raw_member;
3931
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
3932
0
    if (spec == NULL) {
3933
0
        return -1;
3934
0
    }
3935
3936
0
    if (spec->type != PyConfig_MEMBER_WSTR_LIST) {
3937
0
        initconfig_set_error(config, "config option type is not string list");
3938
0
        return -1;
3939
0
    }
3940
3941
0
    PyWideStringList *list = raw_member;
3942
0
    *length = list->length;
3943
3944
0
    *items = malloc(list->length * sizeof(char*));
3945
0
    if (*items == NULL) {
3946
0
        config->status = _PyStatus_NO_MEMORY();
3947
0
        return -1;
3948
0
    }
3949
3950
0
    for (Py_ssize_t i=0; i < list->length; i++) {
3951
0
        (*items)[i] = wstr_to_utf8(config, list->items[i]);
3952
0
        if ((*items)[i] == NULL) {
3953
0
            PyInitConfig_FreeStrList(i, *items);
3954
0
            return -1;
3955
0
        }
3956
0
    }
3957
0
    return 0;
3958
0
}
3959
3960
3961
void
3962
PyInitConfig_FreeStrList(size_t length, char **items)
3963
0
{
3964
0
    for (size_t i=0; i < length; i++) {
3965
0
        free(items[i]);
3966
0
    }
3967
0
    free(items);
3968
0
}
3969
3970
3971
int
3972
PyInitConfig_SetInt(PyInitConfig *config, const char *name, int64_t value)
3973
0
{
3974
0
    void *raw_member;
3975
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
3976
0
    if (spec == NULL) {
3977
0
        return -1;
3978
0
    }
3979
3980
0
    switch (spec->type) {
3981
0
    case PyConfig_MEMBER_INT:
3982
0
    {
3983
0
        if (value < (int64_t)INT_MIN || (int64_t)INT_MAX < value) {
3984
0
            initconfig_set_error(config,
3985
0
                "config option value is out of int range");
3986
0
            return -1;
3987
0
        }
3988
0
        int int_value = (int)value;
3989
3990
0
        int *member = raw_member;
3991
0
        *member = int_value;
3992
0
        break;
3993
0
    }
3994
3995
0
    case PyConfig_MEMBER_UINT:
3996
0
    case PyConfig_MEMBER_BOOL:
3997
0
    {
3998
0
        if (value < 0 || (uint64_t)UINT_MAX < (uint64_t)value) {
3999
0
            initconfig_set_error(config,
4000
0
                "config option value is out of unsigned int range");
4001
0
            return -1;
4002
0
        }
4003
0
        int int_value = (int)value;
4004
4005
0
        int *member = raw_member;
4006
0
        *member = int_value;
4007
0
        break;
4008
0
    }
4009
4010
0
    case PyConfig_MEMBER_ULONG:
4011
0
    {
4012
0
        if (value < 0 || (uint64_t)ULONG_MAX < (uint64_t)value) {
4013
0
            initconfig_set_error(config,
4014
0
                "config option value is out of unsigned long range");
4015
0
            return -1;
4016
0
        }
4017
0
        unsigned long ulong_value = (unsigned long)value;
4018
4019
0
        unsigned long *member = raw_member;
4020
0
        *member = ulong_value;
4021
0
        break;
4022
0
    }
4023
4024
0
    default:
4025
0
        initconfig_set_error(config, "config option type is not int");
4026
0
        return -1;
4027
0
    }
4028
4029
0
    if (strcmp(name, "hash_seed") == 0) {
4030
0
        config->config.use_hash_seed = 1;
4031
0
    }
4032
4033
0
    return 0;
4034
0
}
4035
4036
4037
static wchar_t*
4038
utf8_to_wstr(PyInitConfig *config, const char *str)
4039
0
{
4040
0
    wchar_t *wstr;
4041
0
    size_t wlen;
4042
0
    int res = _Py_DecodeUTF8Ex(str, strlen(str), &wstr, &wlen, NULL, _Py_ERROR_STRICT);
4043
0
    if (res == -2) {
4044
0
        initconfig_set_error(config, "decoding error");
4045
0
        return NULL;
4046
0
    }
4047
0
    if (res < 0) {
4048
0
        config->status = _PyStatus_NO_MEMORY();
4049
0
        return NULL;
4050
0
    }
4051
4052
    // Copy to use the malloc() memory allocator
4053
0
    size_t size = (wlen + 1) * sizeof(wchar_t);
4054
0
    wchar_t *wstr2 = malloc(size);
4055
0
    if (wstr2 == NULL) {
4056
0
        PyMem_RawFree(wstr);
4057
0
        config->status = _PyStatus_NO_MEMORY();
4058
0
        return NULL;
4059
0
    }
4060
4061
0
    memcpy(wstr2, wstr, size);
4062
0
    PyMem_RawFree(wstr);
4063
0
    return wstr2;
4064
0
}
4065
4066
4067
int
4068
PyInitConfig_SetStr(PyInitConfig *config, const char *name, const char* value)
4069
0
{
4070
0
    void *raw_member;
4071
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
4072
0
    if (spec == NULL) {
4073
0
        return -1;
4074
0
    }
4075
4076
0
    if (spec->type != PyConfig_MEMBER_WSTR
4077
0
            && spec->type != PyConfig_MEMBER_WSTR_OPT) {
4078
0
        initconfig_set_error(config, "config option type is not string");
4079
0
        return -1;
4080
0
    }
4081
4082
0
    if (value == NULL && spec->type != PyConfig_MEMBER_WSTR_OPT) {
4083
0
        initconfig_set_error(config, "config option string cannot be NULL");
4084
0
    }
4085
4086
0
    wchar_t **member = raw_member;
4087
4088
0
    *member = utf8_to_wstr(config, value);
4089
0
    if (*member == NULL) {
4090
0
        return -1;
4091
0
    }
4092
0
    return 0;
4093
0
}
4094
4095
4096
static int
4097
_PyWideStringList_FromUTF8(PyInitConfig *config, PyWideStringList *list,
4098
                           Py_ssize_t length, char * const *items)
4099
0
{
4100
0
    PyWideStringList wlist = _PyWideStringList_INIT;
4101
0
    size_t size = sizeof(wchar_t*) * length;
4102
0
    wlist.items = (wchar_t **)PyMem_RawMalloc(size);
4103
0
    if (wlist.items == NULL) {
4104
0
        config->status = _PyStatus_NO_MEMORY();
4105
0
        return -1;
4106
0
    }
4107
4108
0
    for (Py_ssize_t i = 0; i < length; i++) {
4109
0
        wchar_t *arg = utf8_to_wstr(config, items[i]);
4110
0
        if (arg == NULL) {
4111
0
            _PyWideStringList_Clear(&wlist);
4112
0
            return -1;
4113
0
        }
4114
0
        wlist.items[i] = arg;
4115
0
        wlist.length++;
4116
0
    }
4117
4118
0
    _PyWideStringList_Clear(list);
4119
0
    *list = wlist;
4120
0
    return 0;
4121
0
}
4122
4123
4124
int
4125
PyInitConfig_SetStrList(PyInitConfig *config, const char *name,
4126
                        size_t length, char * const *items)
4127
0
{
4128
0
    void *raw_member;
4129
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
4130
0
    if (spec == NULL) {
4131
0
        return -1;
4132
0
    }
4133
4134
0
    if (spec->type != PyConfig_MEMBER_WSTR_LIST) {
4135
0
        initconfig_set_error(config, "config option type is not strings list");
4136
0
        return -1;
4137
0
    }
4138
0
    PyWideStringList *list = raw_member;
4139
0
    if (_PyWideStringList_FromUTF8(config, list, length, items) < 0) {
4140
0
        return -1;
4141
0
    }
4142
4143
0
    if (strcmp(name, "module_search_paths") == 0) {
4144
0
        config->config.module_search_paths_set = 1;
4145
0
    }
4146
0
    return 0;
4147
0
}
4148
4149
4150
int
4151
PyInitConfig_AddModule(PyInitConfig *config, const char *name,
4152
                       PyObject* (*initfunc)(void))
4153
0
{
4154
0
    size_t size = sizeof(struct _inittab) * (config->inittab_size + 2);
4155
0
    struct _inittab *new_inittab = PyMem_RawRealloc(config->inittab, size);
4156
0
    if (new_inittab == NULL) {
4157
0
        config->status = _PyStatus_NO_MEMORY();
4158
0
        return -1;
4159
0
    }
4160
0
    config->inittab = new_inittab;
4161
4162
0
    struct _inittab *entry = &config->inittab[config->inittab_size];
4163
0
    entry->name = name;
4164
0
    entry->initfunc = initfunc;
4165
4166
    // Terminator entry
4167
0
    entry = &config->inittab[config->inittab_size + 1];
4168
0
    entry->name = NULL;
4169
0
    entry->initfunc = NULL;
4170
4171
0
    config->inittab_size++;
4172
0
    return 0;
4173
0
}
4174
4175
4176
int
4177
Py_InitializeFromInitConfig(PyInitConfig *config)
4178
0
{
4179
0
    if (config->inittab_size >= 1) {
4180
0
        if (PyImport_ExtendInittab(config->inittab) < 0) {
4181
0
            config->status = _PyStatus_NO_MEMORY();
4182
0
            return -1;
4183
0
        }
4184
0
    }
4185
4186
0
    _PyPreConfig_GetConfig(&config->preconfig, &config->config);
4187
4188
0
    config->status = Py_PreInitializeFromArgs(
4189
0
        &config->preconfig,
4190
0
        config->config.argv.length,
4191
0
        config->config.argv.items);
4192
0
    if (_PyStatus_EXCEPTION(config->status)) {
4193
0
        return -1;
4194
0
    }
4195
4196
0
    config->status = Py_InitializeFromConfig(&config->config);
4197
0
    if (_PyStatus_EXCEPTION(config->status)) {
4198
0
        return -1;
4199
0
    }
4200
4201
0
    return 0;
4202
0
}
4203
4204
4205
// --- PyConfig_Get() -------------------------------------------------------
4206
4207
static const PyConfigSpec*
4208
config_generic_find_spec(const PyConfigSpec *spec, const char *name)
4209
0
{
4210
0
    for (; spec->name != NULL; spec++) {
4211
0
        if (spec->visibility == PyConfig_MEMBER_INIT_ONLY) {
4212
0
            continue;
4213
0
        }
4214
0
        if (strcmp(name, spec->name) == 0) {
4215
0
            return spec;
4216
0
        }
4217
0
    }
4218
0
    return NULL;
4219
0
}
4220
4221
4222
static const PyConfigSpec*
4223
config_find_spec(const char *name)
4224
0
{
4225
0
    return config_generic_find_spec(PYCONFIG_SPEC, name);
4226
0
}
4227
4228
4229
static const PyConfigSpec*
4230
preconfig_find_spec(const char *name)
4231
0
{
4232
0
    return config_generic_find_spec(PYPRECONFIG_SPEC, name);
4233
0
}
4234
4235
4236
static int
4237
config_add_xoption(PyObject *dict, const wchar_t *str)
4238
0
{
4239
0
    PyObject *name = NULL, *value = NULL;
4240
4241
0
    const wchar_t *name_end = wcschr(str, L'=');
4242
0
    if (!name_end) {
4243
0
        name = PyUnicode_FromWideChar(str, -1);
4244
0
        if (name == NULL) {
4245
0
            goto error;
4246
0
        }
4247
0
        value = Py_NewRef(Py_True);
4248
0
    }
4249
0
    else {
4250
0
        name = PyUnicode_FromWideChar(str, name_end - str);
4251
0
        if (name == NULL) {
4252
0
            goto error;
4253
0
        }
4254
0
        value = PyUnicode_FromWideChar(name_end + 1, -1);
4255
0
        if (value == NULL) {
4256
0
            goto error;
4257
0
        }
4258
0
    }
4259
0
    if (PyDict_SetItem(dict, name, value) < 0) {
4260
0
        goto error;
4261
0
    }
4262
0
    Py_DECREF(name);
4263
0
    Py_DECREF(value);
4264
0
    return 0;
4265
4266
0
error:
4267
0
    Py_XDECREF(name);
4268
0
    Py_XDECREF(value);
4269
0
    return -1;
4270
0
}
4271
4272
4273
PyObject*
4274
_PyConfig_CreateXOptionsDict(const PyConfig *config)
4275
32
{
4276
32
    PyObject *dict = PyDict_New();
4277
32
    if (dict == NULL) {
4278
0
        return NULL;
4279
0
    }
4280
4281
32
    Py_ssize_t nxoption = config->xoptions.length;
4282
32
    wchar_t **xoptions = config->xoptions.items;
4283
32
    for (Py_ssize_t i=0; i < nxoption; i++) {
4284
0
        const wchar_t *option = xoptions[i];
4285
0
        if (config_add_xoption(dict, option) < 0) {
4286
0
            Py_DECREF(dict);
4287
0
            return NULL;
4288
0
        }
4289
0
    }
4290
32
    return dict;
4291
32
}
4292
4293
4294
static int
4295
config_get_sys_write_bytecode(const PyConfig *config, int *value)
4296
0
{
4297
0
    PyObject *attr = PySys_GetAttrString("dont_write_bytecode");
4298
0
    if (attr == NULL) {
4299
0
        return -1;
4300
0
    }
4301
4302
0
    int is_true = PyObject_IsTrue(attr);
4303
0
    Py_DECREF(attr);
4304
0
    if (is_true < 0) {
4305
0
        return -1;
4306
0
    }
4307
0
    *value = (!is_true);
4308
0
    return 0;
4309
0
}
4310
4311
4312
static PyObject*
4313
config_get(const PyConfig *config, const PyConfigSpec *spec,
4314
           int use_sys)
4315
1.10k
{
4316
1.10k
    if (use_sys) {
4317
0
        if (spec->sys.attr != NULL) {
4318
0
            return PySys_GetAttrString(spec->sys.attr);
4319
0
        }
4320
4321
0
        if (strcmp(spec->name, "write_bytecode") == 0) {
4322
0
            int value;
4323
0
            if (config_get_sys_write_bytecode(config, &value) < 0) {
4324
0
                return NULL;
4325
0
            }
4326
0
            return PyBool_FromLong(value);
4327
0
        }
4328
4329
0
        if (strcmp(spec->name, "int_max_str_digits") == 0) {
4330
0
            PyInterpreterState *interp = _PyInterpreterState_GET();
4331
0
            return PyLong_FromLong(interp->long_state.max_str_digits);
4332
0
        }
4333
0
    }
4334
4335
1.10k
    void *member = config_get_spec_member(config, spec);
4336
1.10k
    switch (spec->type) {
4337
48
    case PyConfig_MEMBER_INT:
4338
176
    case PyConfig_MEMBER_UINT:
4339
176
    {
4340
176
        int value = *(int *)member;
4341
176
        return PyLong_FromLong(value);
4342
48
    }
4343
4344
480
    case PyConfig_MEMBER_BOOL:
4345
480
    {
4346
480
        int value = *(int *)member;
4347
480
        return PyBool_FromLong(value != 0);
4348
48
    }
4349
4350
16
    case PyConfig_MEMBER_ULONG:
4351
16
    {
4352
16
        unsigned long value = *(unsigned long *)member;
4353
16
        return PyLong_FromUnsignedLong(value);
4354
48
    }
4355
4356
112
    case PyConfig_MEMBER_WSTR:
4357
352
    case PyConfig_MEMBER_WSTR_OPT:
4358
352
    {
4359
352
        wchar_t *wstr = *(wchar_t **)member;
4360
352
        if (wstr != NULL) {
4361
80
            return PyUnicode_FromWideChar(wstr, -1);
4362
80
        }
4363
272
        else {
4364
272
            return Py_NewRef(Py_None);
4365
272
        }
4366
352
    }
4367
4368
80
    case PyConfig_MEMBER_WSTR_LIST:
4369
80
    {
4370
80
        if (strcmp(spec->name, "xoptions") == 0) {
4371
16
            return _PyConfig_CreateXOptionsDict(config);
4372
16
        }
4373
64
        else {
4374
64
            const PyWideStringList *list = (const PyWideStringList *)member;
4375
64
            return _PyWideStringList_AsTuple(list);
4376
64
        }
4377
80
    }
4378
4379
0
    default:
4380
0
        Py_UNREACHABLE();
4381
1.10k
    }
4382
1.10k
}
4383
4384
4385
static PyObject*
4386
preconfig_get(const PyPreConfig *preconfig, const PyConfigSpec *spec)
4387
0
{
4388
    // The type of all PYPRECONFIG_SPEC members is INT or BOOL.
4389
0
    assert(spec->type == PyConfig_MEMBER_INT
4390
0
           || spec->type == PyConfig_MEMBER_BOOL);
4391
4392
0
    char *member = (char *)preconfig + spec->offset;
4393
0
    int value = *(int *)member;
4394
4395
0
    if (spec->type == PyConfig_MEMBER_BOOL) {
4396
0
        return PyBool_FromLong(value != 0);
4397
0
    }
4398
0
    else {
4399
0
        return PyLong_FromLong(value);
4400
0
    }
4401
0
}
4402
4403
4404
static void
4405
config_unknown_name_error(const char *name)
4406
0
{
4407
0
    PyErr_Format(PyExc_ValueError, "unknown config option name: %s", name);
4408
0
}
4409
4410
4411
PyObject*
4412
PyConfig_Get(const char *name)
4413
0
{
4414
0
    const PyConfigSpec *spec = config_find_spec(name);
4415
0
    if (spec != NULL) {
4416
0
        const PyConfig *config = _Py_GetConfig();
4417
0
        return config_get(config, spec, 1);
4418
0
    }
4419
4420
0
    spec = preconfig_find_spec(name);
4421
0
    if (spec != NULL) {
4422
0
        const PyPreConfig *preconfig = &_PyRuntime.preconfig;
4423
0
        return preconfig_get(preconfig, spec);
4424
0
    }
4425
4426
0
    config_unknown_name_error(name);
4427
0
    return NULL;
4428
0
}
4429
4430
4431
int
4432
PyConfig_GetInt(const char *name, int *value)
4433
0
{
4434
0
    assert(!PyErr_Occurred());
4435
4436
0
    PyObject *obj = PyConfig_Get(name);
4437
0
    if (obj == NULL) {
4438
0
        return -1;
4439
0
    }
4440
4441
0
    if (!PyLong_Check(obj)) {
4442
0
        Py_DECREF(obj);
4443
0
        PyErr_Format(PyExc_TypeError, "config option %s is not an int", name);
4444
0
        return -1;
4445
0
    }
4446
4447
0
    int as_int = PyLong_AsInt(obj);
4448
0
    Py_DECREF(obj);
4449
0
    if (as_int == -1 && PyErr_Occurred()) {
4450
0
        PyErr_Format(PyExc_OverflowError,
4451
0
                     "config option %s value does not fit into a C int", name);
4452
0
        return -1;
4453
0
    }
4454
4455
0
    *value = as_int;
4456
0
    return 0;
4457
0
}
4458
4459
4460
static int
4461
config_names_add(PyObject *names, const PyConfigSpec *spec)
4462
0
{
4463
0
    for (; spec->name != NULL; spec++) {
4464
0
        if (spec->visibility == PyConfig_MEMBER_INIT_ONLY) {
4465
0
            continue;
4466
0
        }
4467
0
        PyObject *name = PyUnicode_FromString(spec->name);
4468
0
        if (name == NULL) {
4469
0
            return -1;
4470
0
        }
4471
0
        int res = PyList_Append(names, name);
4472
0
        Py_DECREF(name);
4473
0
        if (res < 0) {
4474
0
            return -1;
4475
0
        }
4476
0
    }
4477
0
    return 0;
4478
0
}
4479
4480
4481
PyObject*
4482
PyConfig_Names(void)
4483
0
{
4484
0
    PyObject *names = PyList_New(0);
4485
0
    if (names == NULL) {
4486
0
        goto error;
4487
0
    }
4488
4489
0
    if (config_names_add(names, PYCONFIG_SPEC) < 0) {
4490
0
        goto error;
4491
0
    }
4492
0
    if (config_names_add(names, PYPRECONFIG_SPEC) < 0) {
4493
0
        goto error;
4494
0
    }
4495
4496
0
    PyObject *frozen = PyFrozenSet_New(names);
4497
0
    Py_DECREF(names);
4498
0
    return frozen;
4499
4500
0
error:
4501
0
    Py_XDECREF(names);
4502
0
    return NULL;
4503
0
}
4504
4505
4506
// --- PyConfig_Set() -------------------------------------------------------
4507
4508
static int
4509
config_set_sys_flag(const PyConfigSpec *spec, int int_value)
4510
0
{
4511
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
4512
0
    PyConfig *config = &interp->config;
4513
4514
0
    if (spec->type == PyConfig_MEMBER_BOOL) {
4515
0
        if (int_value != 0) {
4516
            // convert values < 0 and values > 1 to 1
4517
0
            int_value = 1;
4518
0
        }
4519
0
    }
4520
4521
0
    PyObject *value;
4522
0
    if (spec->sys.flag_setter) {
4523
0
        value = spec->sys.flag_setter(int_value);
4524
0
    }
4525
0
    else {
4526
0
        value = config_sys_flag_long(int_value);
4527
0
    }
4528
0
    if (value == NULL) {
4529
0
        return -1;
4530
0
    }
4531
4532
    // Set sys.flags.FLAG
4533
0
    Py_ssize_t pos = spec->sys.flag_index;
4534
0
    if (_PySys_SetFlagObj(pos, value) < 0) {
4535
0
        goto error;
4536
0
    }
4537
4538
    // Set PyConfig.ATTR
4539
0
    assert(spec->type == PyConfig_MEMBER_INT
4540
0
           || spec->type == PyConfig_MEMBER_UINT
4541
0
           || spec->type == PyConfig_MEMBER_BOOL);
4542
0
    int *member = config_get_spec_member(config, spec);
4543
0
    *member = int_value;
4544
4545
    // Set sys.dont_write_bytecode attribute
4546
0
    if (strcmp(spec->name, "write_bytecode") == 0) {
4547
0
        if (PySys_SetObject("dont_write_bytecode", value) < 0) {
4548
0
            goto error;
4549
0
        }
4550
0
    }
4551
4552
0
    Py_DECREF(value);
4553
0
    return 0;
4554
4555
0
error:
4556
0
    Py_DECREF(value);
4557
0
    return -1;
4558
0
}
4559
4560
4561
// Set PyConfig.ATTR integer member
4562
static int
4563
config_set_int_attr(const PyConfigSpec *spec, int value)
4564
0
{
4565
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
4566
0
    PyConfig *config = &interp->config;
4567
0
    int *member = config_get_spec_member(config, spec);
4568
0
    *member = value;
4569
0
    return 0;
4570
0
}
4571
4572
4573
int
4574
PyConfig_Set(const char *name, PyObject *value)
4575
0
{
4576
0
    if (PySys_Audit("cpython.PyConfig_Set", "sO", name, value) < 0) {
4577
0
        return -1;
4578
0
    }
4579
4580
0
    const PyConfigSpec *spec = config_find_spec(name);
4581
0
    if (spec == NULL) {
4582
0
        spec = preconfig_find_spec(name);
4583
0
        if (spec == NULL) {
4584
0
            config_unknown_name_error(name);
4585
0
            return -1;
4586
0
        }
4587
0
        assert(spec->visibility != PyConfig_MEMBER_PUBLIC);
4588
0
    }
4589
4590
0
    if (spec->visibility != PyConfig_MEMBER_PUBLIC) {
4591
0
        PyErr_Format(PyExc_ValueError, "cannot set read-only option %s",
4592
0
                     name);
4593
0
        return -1;
4594
0
    }
4595
4596
0
    int int_value = 0;
4597
0
    int has_int_value = 0;
4598
4599
0
    switch (spec->type) {
4600
0
    case PyConfig_MEMBER_INT:
4601
0
    case PyConfig_MEMBER_UINT:
4602
0
    case PyConfig_MEMBER_BOOL:
4603
0
        if (!PyLong_Check(value)) {
4604
0
            PyErr_Format(PyExc_TypeError, "expected int or bool, got %T", value);
4605
0
            return -1;
4606
0
        }
4607
0
        int_value = PyLong_AsInt(value);
4608
0
        if (int_value == -1 && PyErr_Occurred()) {
4609
0
            return -1;
4610
0
        }
4611
0
        if (int_value < 0 && spec->type != PyConfig_MEMBER_INT) {
4612
0
            PyErr_Format(PyExc_ValueError, "value must be >= 0");
4613
0
            return -1;
4614
0
        }
4615
0
        has_int_value = 1;
4616
0
        break;
4617
4618
0
    case PyConfig_MEMBER_ULONG:
4619
        // not implemented: only hash_seed uses this type, and it's read-only
4620
0
        goto cannot_set;
4621
4622
0
    case PyConfig_MEMBER_WSTR:
4623
0
        if (!PyUnicode_CheckExact(value)) {
4624
0
            PyErr_Format(PyExc_TypeError, "expected str, got %T", value);
4625
0
            return -1;
4626
0
        }
4627
0
        break;
4628
4629
0
    case PyConfig_MEMBER_WSTR_OPT:
4630
0
        if (value != Py_None && !PyUnicode_CheckExact(value)) {
4631
0
            PyErr_Format(PyExc_TypeError, "expected str or None, got %T", value);
4632
0
            return -1;
4633
0
        }
4634
0
        break;
4635
4636
0
    case PyConfig_MEMBER_WSTR_LIST:
4637
0
        if (strcmp(spec->name, "xoptions") != 0) {
4638
0
            if (!PyList_Check(value)) {
4639
0
                PyErr_Format(PyExc_TypeError, "expected list[str], got %T",
4640
0
                             value);
4641
0
                return -1;
4642
0
            }
4643
0
            for (Py_ssize_t i=0; i < PyList_GET_SIZE(value); i++) {
4644
0
                PyObject *item = PyList_GET_ITEM(value, i);
4645
0
                if (!PyUnicode_Check(item)) {
4646
0
                    PyErr_Format(PyExc_TypeError,
4647
0
                                 "expected str, list item %zd has type %T",
4648
0
                                 i, item);
4649
0
                    return -1;
4650
0
                }
4651
0
            }
4652
0
        }
4653
0
        else {
4654
            // xoptions type is dict[str, str]
4655
0
            if (!PyDict_Check(value)) {
4656
0
                PyErr_Format(PyExc_TypeError,
4657
0
                             "expected dict[str, str | bool], got %T",
4658
0
                             value);
4659
0
                return -1;
4660
0
            }
4661
4662
0
            Py_ssize_t pos = 0;
4663
0
            PyObject *key, *item;
4664
0
            while (PyDict_Next(value, &pos, &key, &item)) {
4665
0
                if (!PyUnicode_Check(key)) {
4666
0
                    PyErr_Format(PyExc_TypeError,
4667
0
                                 "expected str, "
4668
0
                                 "got dict key type %T", key);
4669
0
                    return -1;
4670
0
                }
4671
0
                if (!PyUnicode_Check(item) && !PyBool_Check(item)) {
4672
0
                    PyErr_Format(PyExc_TypeError,
4673
0
                                 "expected str or bool, "
4674
0
                                 "got dict value type %T", key);
4675
0
                    return -1;
4676
0
                }
4677
0
            }
4678
0
        }
4679
0
        break;
4680
4681
0
    default:
4682
0
        Py_UNREACHABLE();
4683
0
    }
4684
4685
0
    if (spec->sys.attr != NULL) {
4686
        // Set the sys attribute, but don't set PyInterpreterState.config
4687
        // to keep the code simple.
4688
0
        return PySys_SetObject(spec->sys.attr, value);
4689
0
    }
4690
0
    else if (has_int_value) {
4691
0
        if (spec->sys.flag_index >= 0) {
4692
0
            return config_set_sys_flag(spec, int_value);
4693
0
        }
4694
0
        else if (strcmp(spec->name, "int_max_str_digits") == 0) {
4695
0
            return _PySys_SetIntMaxStrDigits(int_value);
4696
0
        }
4697
0
        else {
4698
0
            return config_set_int_attr(spec, int_value);
4699
0
        }
4700
0
    }
4701
4702
0
cannot_set:
4703
0
    PyErr_Format(PyExc_ValueError, "cannot set option %s", name);
4704
0
    return -1;
4705
0
}