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