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