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