1 /* Python interpreter main program */
2 
3 #include "Python.h"
4 #include "pycore_initconfig.h"
5 #include "pycore_pylifecycle.h"
6 #include "pycore_pymem.h"
7 #include "pycore_pystate.h"
8 
9 #ifdef __FreeBSD__
10 #  include <fenv.h>     /* fedisableexcept() */
11 #endif
12 
13 /* Includes for exit_sigint() */
14 #include <stdio.h>      /* perror() */
15 #ifdef HAVE_SIGNAL_H
16 #  include <signal.h>   /* SIGINT */
17 #endif
18 #if defined(HAVE_GETPID) && defined(HAVE_UNISTD_H)
19 #  include <unistd.h>   /* getpid() */
20 #endif
21 #ifdef MS_WINDOWS
22 #  include <windows.h>  /* STATUS_CONTROL_C_EXIT */
23 #endif
24 /* End of includes for exit_sigint() */
25 
26 #define COPYRIGHT \
27     "Type \"help\", \"copyright\", \"credits\" or \"license\" " \
28     "for more information."
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /* --- pymain_init() ---------------------------------------------- */
35 
36 static PyStatus
pymain_init(const _PyArgv * args)37 pymain_init(const _PyArgv *args)
38 {
39     PyStatus status;
40 
41     status = _PyRuntime_Initialize();
42     if (_PyStatus_EXCEPTION(status)) {
43         return status;
44     }
45 
46     /* 754 requires that FP exceptions run in "no stop" mode by default,
47      * and until C vendors implement C99's ways to control FP exceptions,
48      * Python requires non-stop mode.  Alas, some platforms enable FP
49      * exceptions by default.  Here we disable them.
50      */
51 #ifdef __FreeBSD__
52     fedisableexcept(FE_OVERFLOW);
53 #endif
54 
55     PyPreConfig preconfig;
56     PyPreConfig_InitPythonConfig(&preconfig);
57 
58     status = _Py_PreInitializeFromPyArgv(&preconfig, args);
59     if (_PyStatus_EXCEPTION(status)) {
60         return status;
61     }
62 
63     PyConfig config;
64     PyConfig_InitPythonConfig(&config);
65 
66     /* pass NULL as the config: config is read from command line arguments,
67        environment variables, configuration files */
68     if (args->use_bytes_argv) {
69         status = PyConfig_SetBytesArgv(&config, args->argc, args->bytes_argv);
70     }
71     else {
72         status = PyConfig_SetArgv(&config, args->argc, args->wchar_argv);
73     }
74     if (_PyStatus_EXCEPTION(status)) {
75         goto done;
76     }
77 
78     status = Py_InitializeFromConfig(&config);
79     if (_PyStatus_EXCEPTION(status)) {
80         goto done;
81     }
82     status = _PyStatus_OK();
83 
84 done:
85     PyConfig_Clear(&config);
86     return status;
87 }
88 
89 
90 /* --- pymain_run_python() ---------------------------------------- */
91 
92 /* Non-zero if filename, command (-c) or module (-m) is set
93    on the command line */
config_run_code(const PyConfig * config)94 static inline int config_run_code(const PyConfig *config)
95 {
96     return (config->run_command != NULL
97             || config->run_filename != NULL
98             || config->run_module != NULL);
99 }
100 
101 
102 /* Return non-zero is stdin is a TTY or if -i command line option is used */
103 static int
stdin_is_interactive(const PyConfig * config)104 stdin_is_interactive(const PyConfig *config)
105 {
106     return (isatty(fileno(stdin)) || config->interactive);
107 }
108 
109 
110 /* Display the current Python exception and return an exitcode */
111 static int
pymain_err_print(int * exitcode_p)112 pymain_err_print(int *exitcode_p)
113 {
114     int exitcode;
115     if (_Py_HandleSystemExit(&exitcode)) {
116         *exitcode_p = exitcode;
117         return 1;
118     }
119 
120     PyErr_Print();
121     return 0;
122 }
123 
124 
125 static int
pymain_exit_err_print(void)126 pymain_exit_err_print(void)
127 {
128     int exitcode = 1;
129     pymain_err_print(&exitcode);
130     return exitcode;
131 }
132 
133 
134 /* Write an exitcode into *exitcode and return 1 if we have to exit Python.
135    Return 0 otherwise. */
136 static int
pymain_get_importer(const wchar_t * filename,PyObject ** importer_p,int * exitcode)137 pymain_get_importer(const wchar_t *filename, PyObject **importer_p, int *exitcode)
138 {
139     PyObject *sys_path0 = NULL, *importer;
140 
141     sys_path0 = PyUnicode_FromWideChar(filename, wcslen(filename));
142     if (sys_path0 == NULL) {
143         goto error;
144     }
145 
146     importer = PyImport_GetImporter(sys_path0);
147     if (importer == NULL) {
148         goto error;
149     }
150 
151     if (importer == Py_None) {
152         Py_DECREF(sys_path0);
153         Py_DECREF(importer);
154         return 0;
155     }
156 
157     Py_DECREF(importer);
158     *importer_p = sys_path0;
159     return 0;
160 
161 error:
162     Py_XDECREF(sys_path0);
163 
164     PySys_WriteStderr("Failed checking if argv[0] is an import path entry\n");
165     return pymain_err_print(exitcode);
166 }
167 
168 
169 static int
pymain_sys_path_add_path0(PyInterpreterState * interp,PyObject * path0)170 pymain_sys_path_add_path0(PyInterpreterState *interp, PyObject *path0)
171 {
172     _Py_IDENTIFIER(path);
173     PyObject *sys_path;
174     PyObject *sysdict = interp->sysdict;
175     if (sysdict != NULL) {
176         sys_path = _PyDict_GetItemIdWithError(sysdict, &PyId_path);
177         if (sys_path == NULL && PyErr_Occurred()) {
178             return -1;
179         }
180     }
181     else {
182         sys_path = NULL;
183     }
184     if (sys_path == NULL) {
185         PyErr_SetString(PyExc_RuntimeError, "unable to get sys.path");
186         return -1;
187     }
188 
189     if (PyList_Insert(sys_path, 0, path0)) {
190         return -1;
191     }
192     return 0;
193 }
194 
195 
196 static void
pymain_header(const PyConfig * config)197 pymain_header(const PyConfig *config)
198 {
199     if (config->quiet) {
200         return;
201     }
202 
203     if (!config->verbose && (config_run_code(config) || !stdin_is_interactive(config))) {
204         return;
205     }
206 
207     fprintf(stderr, "Python %s on %s\n", Py_GetVersion(), Py_GetPlatform());
208     if (config->site_import) {
209         fprintf(stderr, "%s\n", COPYRIGHT);
210     }
211 }
212 
213 
214 static void
pymain_import_readline(const PyConfig * config)215 pymain_import_readline(const PyConfig *config)
216 {
217     if (config->isolated) {
218         return;
219     }
220     if (!config->inspect && config_run_code(config)) {
221         return;
222     }
223     if (!isatty(fileno(stdin))) {
224         return;
225     }
226 
227     PyObject *mod = PyImport_ImportModule("readline");
228     if (mod == NULL) {
229         PyErr_Clear();
230     }
231     else {
232         Py_DECREF(mod);
233     }
234 }
235 
236 
237 static int
pymain_run_command(wchar_t * command,PyCompilerFlags * cf)238 pymain_run_command(wchar_t *command, PyCompilerFlags *cf)
239 {
240     PyObject *unicode, *bytes;
241     int ret;
242 
243     unicode = PyUnicode_FromWideChar(command, -1);
244     if (unicode == NULL) {
245         goto error;
246     }
247 
248     if (PySys_Audit("cpython.run_command", "O", unicode) < 0) {
249         return pymain_exit_err_print();
250     }
251 
252     bytes = PyUnicode_AsUTF8String(unicode);
253     Py_DECREF(unicode);
254     if (bytes == NULL) {
255         goto error;
256     }
257 
258     ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), cf);
259     Py_DECREF(bytes);
260     return (ret != 0);
261 
262 error:
263     PySys_WriteStderr("Unable to decode the command from the command line:\n");
264     return pymain_exit_err_print();
265 }
266 
267 
268 static int
pymain_run_module(const wchar_t * modname,int set_argv0)269 pymain_run_module(const wchar_t *modname, int set_argv0)
270 {
271     PyObject *module, *runpy, *runmodule, *runargs, *result;
272     if (PySys_Audit("cpython.run_module", "u", modname) < 0) {
273         return pymain_exit_err_print();
274     }
275     runpy = PyImport_ImportModule("runpy");
276     if (runpy == NULL) {
277         fprintf(stderr, "Could not import runpy module\n");
278         return pymain_exit_err_print();
279     }
280     runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main");
281     if (runmodule == NULL) {
282         fprintf(stderr, "Could not access runpy._run_module_as_main\n");
283         Py_DECREF(runpy);
284         return pymain_exit_err_print();
285     }
286     module = PyUnicode_FromWideChar(modname, wcslen(modname));
287     if (module == NULL) {
288         fprintf(stderr, "Could not convert module name to unicode\n");
289         Py_DECREF(runpy);
290         Py_DECREF(runmodule);
291         return pymain_exit_err_print();
292     }
293     runargs = Py_BuildValue("(Oi)", module, set_argv0);
294     if (runargs == NULL) {
295         fprintf(stderr,
296             "Could not create arguments for runpy._run_module_as_main\n");
297         Py_DECREF(runpy);
298         Py_DECREF(runmodule);
299         Py_DECREF(module);
300         return pymain_exit_err_print();
301     }
302     _Py_UnhandledKeyboardInterrupt = 0;
303     result = PyObject_Call(runmodule, runargs, NULL);
304     if (!result && PyErr_Occurred() == PyExc_KeyboardInterrupt) {
305         _Py_UnhandledKeyboardInterrupt = 1;
306     }
307     Py_DECREF(runpy);
308     Py_DECREF(runmodule);
309     Py_DECREF(module);
310     Py_DECREF(runargs);
311     if (result == NULL) {
312         return pymain_exit_err_print();
313     }
314     Py_DECREF(result);
315     return 0;
316 }
317 
318 
319 static int
pymain_run_file(PyConfig * config,PyCompilerFlags * cf)320 pymain_run_file(PyConfig *config, PyCompilerFlags *cf)
321 {
322     const wchar_t *filename = config->run_filename;
323     if (PySys_Audit("cpython.run_file", "u", filename) < 0) {
324         return pymain_exit_err_print();
325     }
326     FILE *fp = _Py_wfopen(filename, L"rb");
327     if (fp == NULL) {
328         char *cfilename_buffer;
329         const char *cfilename;
330         int err = errno;
331         cfilename_buffer = _Py_EncodeLocaleRaw(filename, NULL);
332         if (cfilename_buffer != NULL)
333             cfilename = cfilename_buffer;
334         else
335             cfilename = "<unprintable file name>";
336         fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n",
337                 config->program_name, cfilename, err, strerror(err));
338         PyMem_RawFree(cfilename_buffer);
339         return 2;
340     }
341 
342     if (config->skip_source_first_line) {
343         int ch;
344         /* Push back first newline so line numbers remain the same */
345         while ((ch = getc(fp)) != EOF) {
346             if (ch == '\n') {
347                 (void)ungetc(ch, fp);
348                 break;
349             }
350         }
351     }
352 
353     struct _Py_stat_struct sb;
354     if (_Py_fstat_noraise(fileno(fp), &sb) == 0 && S_ISDIR(sb.st_mode)) {
355         fprintf(stderr,
356                 "%ls: '%ls' is a directory, cannot continue\n",
357                 config->program_name, filename);
358         fclose(fp);
359         return 1;
360     }
361 
362     /* call pending calls like signal handlers (SIGINT) */
363     if (Py_MakePendingCalls() == -1) {
364         fclose(fp);
365         return pymain_exit_err_print();
366     }
367 
368     PyObject *unicode, *bytes = NULL;
369     const char *filename_str;
370 
371     unicode = PyUnicode_FromWideChar(filename, wcslen(filename));
372     if (unicode != NULL) {
373         bytes = PyUnicode_EncodeFSDefault(unicode);
374         Py_DECREF(unicode);
375     }
376     if (bytes != NULL) {
377         filename_str = PyBytes_AsString(bytes);
378     }
379     else {
380         PyErr_Clear();
381         filename_str = "<filename encoding error>";
382     }
383 
384     /* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */
385     int run = PyRun_AnyFileExFlags(fp, filename_str, 1, cf);
386     Py_XDECREF(bytes);
387     return (run != 0);
388 }
389 
390 
391 static int
pymain_run_startup(PyConfig * config,PyCompilerFlags * cf,int * exitcode)392 pymain_run_startup(PyConfig *config, PyCompilerFlags *cf, int *exitcode)
393 {
394     int ret;
395     PyObject *startup_obj = NULL;
396     if (!config->use_environment) {
397         return 0;
398     }
399 #ifdef MS_WINDOWS
400     const wchar_t *wstartup = _wgetenv(L"PYTHONSTARTUP");
401     if (wstartup == NULL || wstartup[0] == L'\0') {
402         return 0;
403     }
404     PyObject *startup_bytes = NULL;
405     startup_obj = PyUnicode_FromWideChar(wstartup, wcslen(wstartup));
406     if (startup_obj == NULL) {
407         goto error;
408     }
409     startup_bytes = PyUnicode_EncodeFSDefault(startup_obj);
410     if (startup_bytes == NULL) {
411         goto error;
412     }
413     const char *startup = PyBytes_AS_STRING(startup_bytes);
414 #else
415     const char *startup = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP");
416     if (startup == NULL) {
417         return 0;
418     }
419     startup_obj = PyUnicode_DecodeFSDefault(startup);
420     if (startup_obj == NULL) {
421         goto error;
422     }
423 #endif
424     if (PySys_Audit("cpython.run_startup", "O", startup_obj) < 0) {
425         goto error;
426     }
427 
428 #ifdef MS_WINDOWS
429     FILE *fp = _Py_wfopen(wstartup, L"r");
430 #else
431     FILE *fp = _Py_fopen(startup, "r");
432 #endif
433     if (fp == NULL) {
434         int save_errno = errno;
435         PyErr_Clear();
436         PySys_WriteStderr("Could not open PYTHONSTARTUP\n");
437 
438         errno = save_errno;
439         PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, startup_obj, NULL);
440         goto error;
441     }
442 
443     (void) PyRun_SimpleFileExFlags(fp, startup, 0, cf);
444     PyErr_Clear();
445     fclose(fp);
446     ret = 0;
447 
448 done:
449 #ifdef MS_WINDOWS
450     Py_XDECREF(startup_bytes);
451 #endif
452     Py_XDECREF(startup_obj);
453     return ret;
454 
455 error:
456     ret = pymain_err_print(exitcode);
457     goto done;
458 }
459 
460 
461 /* Write an exitcode into *exitcode and return 1 if we have to exit Python.
462    Return 0 otherwise. */
463 static int
pymain_run_interactive_hook(int * exitcode)464 pymain_run_interactive_hook(int *exitcode)
465 {
466     PyObject *sys, *hook, *result;
467     sys = PyImport_ImportModule("sys");
468     if (sys == NULL) {
469         goto error;
470     }
471 
472     hook = PyObject_GetAttrString(sys, "__interactivehook__");
473     Py_DECREF(sys);
474     if (hook == NULL) {
475         PyErr_Clear();
476         return 0;
477     }
478 
479     if (PySys_Audit("cpython.run_interactivehook", "O", hook) < 0) {
480         goto error;
481     }
482 
483     result = _PyObject_CallNoArg(hook);
484     Py_DECREF(hook);
485     if (result == NULL) {
486         goto error;
487     }
488     Py_DECREF(result);
489 
490     return 0;
491 
492 error:
493     PySys_WriteStderr("Failed calling sys.__interactivehook__\n");
494     return pymain_err_print(exitcode);
495 }
496 
497 
498 static int
pymain_run_stdin(PyConfig * config,PyCompilerFlags * cf)499 pymain_run_stdin(PyConfig *config, PyCompilerFlags *cf)
500 {
501     if (stdin_is_interactive(config)) {
502         config->inspect = 0;
503         Py_InspectFlag = 0; /* do exit on SystemExit */
504 
505         int exitcode;
506         if (pymain_run_startup(config, cf, &exitcode)) {
507             return exitcode;
508         }
509 
510         if (pymain_run_interactive_hook(&exitcode)) {
511             return exitcode;
512         }
513     }
514 
515     /* call pending calls like signal handlers (SIGINT) */
516     if (Py_MakePendingCalls() == -1) {
517         return pymain_exit_err_print();
518     }
519 
520     if (PySys_Audit("cpython.run_stdin", NULL) < 0) {
521         return pymain_exit_err_print();
522     }
523 
524     int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, cf);
525     return (run != 0);
526 }
527 
528 
529 static void
pymain_repl(PyConfig * config,PyCompilerFlags * cf,int * exitcode)530 pymain_repl(PyConfig *config, PyCompilerFlags *cf, int *exitcode)
531 {
532     /* Check this environment variable at the end, to give programs the
533        opportunity to set it from Python. */
534     if (!config->inspect && _Py_GetEnv(config->use_environment, "PYTHONINSPECT")) {
535         config->inspect = 1;
536         Py_InspectFlag = 1;
537     }
538 
539     if (!(config->inspect && stdin_is_interactive(config) && config_run_code(config))) {
540         return;
541     }
542 
543     config->inspect = 0;
544     Py_InspectFlag = 0;
545     if (pymain_run_interactive_hook(exitcode)) {
546         return;
547     }
548 
549     int res = PyRun_AnyFileFlags(stdin, "<stdin>", cf);
550     *exitcode = (res != 0);
551 }
552 
553 
554 static void
pymain_run_python(int * exitcode)555 pymain_run_python(int *exitcode)
556 {
557     PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
558     /* pymain_run_stdin() modify the config */
559     PyConfig *config = &interp->config;
560 
561     PyObject *main_importer_path = NULL;
562     if (config->run_filename != NULL) {
563         /* If filename is a package (ex: directory or ZIP file) which contains
564            __main__.py, main_importer_path is set to filename and will be
565            prepended to sys.path.
566 
567            Otherwise, main_importer_path is left unchanged. */
568         if (pymain_get_importer(config->run_filename, &main_importer_path,
569                                 exitcode)) {
570             return;
571         }
572     }
573 
574     if (main_importer_path != NULL) {
575         if (pymain_sys_path_add_path0(interp, main_importer_path) < 0) {
576             goto error;
577         }
578     }
579     else if (!config->isolated) {
580         PyObject *path0 = NULL;
581         int res = _PyPathConfig_ComputeSysPath0(&config->argv, &path0);
582         if (res < 0) {
583             goto error;
584         }
585 
586         if (res > 0) {
587             if (pymain_sys_path_add_path0(interp, path0) < 0) {
588                 Py_DECREF(path0);
589                 goto error;
590             }
591             Py_DECREF(path0);
592         }
593     }
594 
595     PyCompilerFlags cf = _PyCompilerFlags_INIT;
596 
597     pymain_header(config);
598     pymain_import_readline(config);
599 
600     if (config->run_command) {
601         *exitcode = pymain_run_command(config->run_command, &cf);
602     }
603     else if (config->run_module) {
604         *exitcode = pymain_run_module(config->run_module, 1);
605     }
606     else if (main_importer_path != NULL) {
607         *exitcode = pymain_run_module(L"__main__", 0);
608     }
609     else if (config->run_filename != NULL) {
610         *exitcode = pymain_run_file(config, &cf);
611     }
612     else {
613         *exitcode = pymain_run_stdin(config, &cf);
614     }
615 
616     pymain_repl(config, &cf, exitcode);
617     goto done;
618 
619 error:
620     *exitcode = pymain_exit_err_print();
621 
622 done:
623     Py_XDECREF(main_importer_path);
624 }
625 
626 
627 /* --- pymain_main() ---------------------------------------------- */
628 
629 static void
pymain_free(void)630 pymain_free(void)
631 {
632     _PyImport_Fini2();
633 
634     /* Free global variables which cannot be freed in Py_Finalize():
635        configuration options set before Py_Initialize() which should
636        remain valid after Py_Finalize(), since
637        Py_Initialize()-Py_Finalize() can be called multiple times. */
638     _PyPathConfig_ClearGlobal();
639     _Py_ClearStandardStreamEncoding();
640     _Py_ClearArgcArgv();
641     _PyRuntime_Finalize();
642 }
643 
644 
645 static int
exit_sigint(void)646 exit_sigint(void)
647 {
648     /* bpo-1054041: We need to exit via the
649      * SIG_DFL handler for SIGINT if KeyboardInterrupt went unhandled.
650      * If we don't, a calling process such as a shell may not know
651      * about the user's ^C.  https://www.cons.org/cracauer/sigint.html */
652 #if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
653     if (PyOS_setsig(SIGINT, SIG_DFL) == SIG_ERR) {
654         perror("signal");  /* Impossible in normal environments. */
655     } else {
656         kill(getpid(), SIGINT);
657     }
658     /* If setting SIG_DFL failed, or kill failed to terminate us,
659      * there isn't much else we can do aside from an error code. */
660 #endif  /* HAVE_GETPID && !MS_WINDOWS */
661 #ifdef MS_WINDOWS
662     /* cmd.exe detects this, prints ^C, and offers to terminate. */
663     /* https://msdn.microsoft.com/en-us/library/cc704588.aspx */
664     return STATUS_CONTROL_C_EXIT;
665 #else
666     return SIGINT + 128;
667 #endif  /* !MS_WINDOWS */
668 }
669 
670 
671 static void _Py_NO_RETURN
pymain_exit_error(PyStatus status)672 pymain_exit_error(PyStatus status)
673 {
674     if (_PyStatus_IS_EXIT(status)) {
675         /* If it's an error rather than a regular exit, leave Python runtime
676            alive: Py_ExitStatusException() uses the current exception and use
677            sys.stdout in this case. */
678         pymain_free();
679     }
680     Py_ExitStatusException(status);
681 }
682 
683 
684 int
Py_RunMain(void)685 Py_RunMain(void)
686 {
687     int exitcode = 0;
688 
689     pymain_run_python(&exitcode);
690 
691     if (Py_FinalizeEx() < 0) {
692         /* Value unlikely to be confused with a non-error exit status or
693            other special meaning */
694         exitcode = 120;
695     }
696 
697     pymain_free();
698 
699     if (_Py_UnhandledKeyboardInterrupt) {
700         exitcode = exit_sigint();
701     }
702 
703     return exitcode;
704 }
705 
706 
707 static int
pymain_main(_PyArgv * args)708 pymain_main(_PyArgv *args)
709 {
710     PyStatus status = pymain_init(args);
711     if (_PyStatus_IS_EXIT(status)) {
712         pymain_free();
713         return status.exitcode;
714     }
715     if (_PyStatus_EXCEPTION(status)) {
716         pymain_exit_error(status);
717     }
718 
719     return Py_RunMain();
720 }
721 
722 
723 int
Py_Main(int argc,wchar_t ** argv)724 Py_Main(int argc, wchar_t **argv)
725 {
726     _PyArgv args = {
727         .argc = argc,
728         .use_bytes_argv = 0,
729         .bytes_argv = NULL,
730         .wchar_argv = argv};
731     return pymain_main(&args);
732 }
733 
734 
735 int
Py_BytesMain(int argc,char ** argv)736 Py_BytesMain(int argc, char **argv)
737 {
738     _PyArgv args = {
739         .argc = argc,
740         .use_bytes_argv = 1,
741         .bytes_argv = argv,
742         .wchar_argv = NULL};
743     return pymain_main(&args);
744 }
745 
746 #ifdef __cplusplus
747 }
748 #endif
749