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