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