Coverage Report

Created: 2026-02-09 07:07

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