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