123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773 |
- /* Python interpreter main program */
- #include "Python.h"
- #include "pycore_call.h" // _PyObject_CallNoArgs()
- #include "pycore_initconfig.h" // _PyArgv
- #include "pycore_interp.h" // _PyInterpreterState.sysdict
- #include "pycore_pathconfig.h" // _PyPathConfig_ComputeSysPath0()
- #include "pycore_pylifecycle.h" // _Py_PreInitializeFromPyArgv()
- #include "pycore_pystate.h" // _PyInterpreterState_GET()
- /* Includes for exit_sigint() */
- #include <stdio.h> // perror()
- #ifdef HAVE_SIGNAL_H
- # include <signal.h> // SIGINT
- #endif
- #if defined(HAVE_GETPID) && defined(HAVE_UNISTD_H)
- # include <unistd.h> // getpid()
- #endif
- #ifdef MS_WINDOWS
- # include <windows.h> // STATUS_CONTROL_C_EXIT
- #endif
- /* End of includes for exit_sigint() */
- #define COPYRIGHT \
- "Type \"help\", \"copyright\", \"credits\" or \"license\" " \
- "for more information."
- #ifdef __cplusplus
- extern "C" {
- #endif
- /* --- pymain_init() ---------------------------------------------- */
- static PyStatus
- pymain_init(const _PyArgv *args)
- {
- PyStatus status;
- status = _PyRuntime_Initialize();
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
- PyPreConfig preconfig;
- PyPreConfig_InitPythonConfig(&preconfig);
- status = _Py_PreInitializeFromPyArgv(&preconfig, args);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
- config.pathconfig_warnings = 0; /* Suppress errors from getpath.c */
- /* pass NULL as the config: config is read from command line arguments,
- environment variables, configuration files */
- if (args->use_bytes_argv) {
- status = PyConfig_SetBytesArgv(&config, args->argc, args->bytes_argv);
- }
- else {
- status = PyConfig_SetArgv(&config, args->argc, args->wchar_argv);
- }
- if (_PyStatus_EXCEPTION(status)) {
- goto done;
- }
- status = Py_InitializeFromConfig(&config);
- if (_PyStatus_EXCEPTION(status)) {
- goto done;
- }
- status = _PyStatus_OK();
- done:
- PyConfig_Clear(&config);
- return status;
- }
- /* --- pymain_run_python() ---------------------------------------- */
- /* Non-zero if filename, command (-c) or module (-m) is set
- on the command line */
- static inline int config_run_code(const PyConfig *config)
- {
- return (config->run_command != NULL
- || config->run_filename != NULL
- || config->run_module != NULL);
- }
- /* Return non-zero if stdin is a TTY or if -i command line option is used */
- static int
- stdin_is_interactive(const PyConfig *config)
- {
- return (isatty(fileno(stdin)) || config->interactive);
- }
- /* Display the current Python exception and return an exitcode */
- static int
- pymain_err_print(int *exitcode_p)
- {
- int exitcode;
- if (_Py_HandleSystemExit(&exitcode)) {
- *exitcode_p = exitcode;
- return 1;
- }
- PyErr_Print();
- return 0;
- }
- static int
- pymain_exit_err_print(void)
- {
- int exitcode = 1;
- pymain_err_print(&exitcode);
- return exitcode;
- }
- /* Write an exitcode into *exitcode and return 1 if we have to exit Python.
- Return 0 otherwise. */
- static int
- pymain_get_importer(const wchar_t *filename, PyObject **importer_p, int *exitcode)
- {
- PyObject *sys_path0 = NULL, *importer;
- sys_path0 = PyUnicode_FromWideChar(filename, wcslen(filename));
- if (sys_path0 == NULL) {
- goto error;
- }
- importer = PyImport_GetImporter(sys_path0);
- if (importer == NULL) {
- goto error;
- }
- if (importer == Py_None) {
- Py_DECREF(sys_path0);
- Py_DECREF(importer);
- return 0;
- }
- Py_DECREF(importer);
- *importer_p = sys_path0;
- return 0;
- error:
- Py_XDECREF(sys_path0);
- PySys_WriteStderr("Failed checking if argv[0] is an import path entry\n");
- return pymain_err_print(exitcode);
- }
- static int
- pymain_sys_path_add_path0(PyInterpreterState *interp, PyObject *path0)
- {
- PyObject *sys_path;
- PyObject *sysdict = interp->sysdict;
- if (sysdict != NULL) {
- sys_path = PyDict_GetItemWithError(sysdict, &_Py_ID(path));
- if (sys_path == NULL && PyErr_Occurred()) {
- return -1;
- }
- }
- else {
- sys_path = NULL;
- }
- if (sys_path == NULL) {
- PyErr_SetString(PyExc_RuntimeError, "unable to get sys.path");
- return -1;
- }
- if (PyList_Insert(sys_path, 0, path0)) {
- return -1;
- }
- return 0;
- }
- static void
- pymain_header(const PyConfig *config)
- {
- if (config->quiet) {
- return;
- }
- if (!config->verbose && (config_run_code(config) || !stdin_is_interactive(config))) {
- return;
- }
- fprintf(stderr, "Python %s on %s\n", Py_GetVersion(), Py_GetPlatform());
- if (config->site_import) {
- fprintf(stderr, "%s\n", COPYRIGHT);
- }
- }
- static void
- pymain_import_readline(const PyConfig *config)
- {
- if (config->isolated) {
- return;
- }
- if (!config->inspect && config_run_code(config)) {
- return;
- }
- if (!isatty(fileno(stdin))) {
- return;
- }
- PyObject *mod = PyImport_ImportModule("readline");
- if (mod == NULL) {
- PyErr_Clear();
- }
- else {
- Py_DECREF(mod);
- }
- mod = PyImport_ImportModule("rlcompleter");
- if (mod == NULL) {
- PyErr_Clear();
- }
- else {
- Py_DECREF(mod);
- }
- }
- static int
- pymain_run_command(wchar_t *command)
- {
- PyObject *unicode, *bytes;
- int ret;
- unicode = PyUnicode_FromWideChar(command, -1);
- if (unicode == NULL) {
- goto error;
- }
- if (PySys_Audit("cpython.run_command", "O", unicode) < 0) {
- return pymain_exit_err_print();
- }
- bytes = PyUnicode_AsUTF8String(unicode);
- Py_DECREF(unicode);
- if (bytes == NULL) {
- goto error;
- }
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
- cf.cf_flags |= PyCF_IGNORE_COOKIE;
- ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), &cf);
- Py_DECREF(bytes);
- return (ret != 0);
- error:
- PySys_WriteStderr("Unable to decode the command from the command line:\n");
- return pymain_exit_err_print();
- }
- static int
- pymain_run_module(const wchar_t *modname, int set_argv0)
- {
- PyObject *module, *runpy, *runmodule, *runargs, *result;
- if (PySys_Audit("cpython.run_module", "u", modname) < 0) {
- return pymain_exit_err_print();
- }
- runpy = PyImport_ImportModule("runpy");
- if (runpy == NULL) {
- fprintf(stderr, "Could not import runpy module\n");
- return pymain_exit_err_print();
- }
- runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main");
- if (runmodule == NULL) {
- fprintf(stderr, "Could not access runpy._run_module_as_main\n");
- Py_DECREF(runpy);
- return pymain_exit_err_print();
- }
- module = PyUnicode_FromWideChar(modname, wcslen(modname));
- if (module == NULL) {
- fprintf(stderr, "Could not convert module name to unicode\n");
- Py_DECREF(runpy);
- Py_DECREF(runmodule);
- return pymain_exit_err_print();
- }
- runargs = PyTuple_Pack(2, module, set_argv0 ? Py_True : Py_False);
- if (runargs == NULL) {
- fprintf(stderr,
- "Could not create arguments for runpy._run_module_as_main\n");
- Py_DECREF(runpy);
- Py_DECREF(runmodule);
- Py_DECREF(module);
- return pymain_exit_err_print();
- }
- _PyRuntime.signals.unhandled_keyboard_interrupt = 0;
- result = PyObject_Call(runmodule, runargs, NULL);
- if (!result && PyErr_Occurred() == PyExc_KeyboardInterrupt) {
- _PyRuntime.signals.unhandled_keyboard_interrupt = 1;
- }
- Py_DECREF(runpy);
- Py_DECREF(runmodule);
- Py_DECREF(module);
- Py_DECREF(runargs);
- if (result == NULL) {
- return pymain_exit_err_print();
- }
- Py_DECREF(result);
- return 0;
- }
- static int
- pymain_run_file_obj(PyObject *program_name, PyObject *filename,
- int skip_source_first_line)
- {
- if (PySys_Audit("cpython.run_file", "O", filename) < 0) {
- return pymain_exit_err_print();
- }
- FILE *fp = _Py_fopen_obj(filename, "rb");
- if (fp == NULL) {
- // Ignore the OSError
- PyErr_Clear();
- PySys_FormatStderr("%S: can't open file %R: [Errno %d] %s\n",
- program_name, filename, errno, strerror(errno));
- return 2;
- }
- if (skip_source_first_line) {
- int ch;
- /* Push back first newline so line numbers remain the same */
- while ((ch = getc(fp)) != EOF) {
- if (ch == '\n') {
- (void)ungetc(ch, fp);
- break;
- }
- }
- }
- struct _Py_stat_struct sb;
- if (_Py_fstat_noraise(fileno(fp), &sb) == 0 && S_ISDIR(sb.st_mode)) {
- PySys_FormatStderr("%S: %R is a directory, cannot continue\n",
- program_name, filename);
- fclose(fp);
- return 1;
- }
- // Call pending calls like signal handlers (SIGINT)
- if (Py_MakePendingCalls() == -1) {
- fclose(fp);
- return pymain_exit_err_print();
- }
- /* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
- int run = _PyRun_AnyFileObject(fp, filename, 1, &cf);
- return (run != 0);
- }
- static int
- pymain_run_file(const PyConfig *config)
- {
- PyObject *filename = PyUnicode_FromWideChar(config->run_filename, -1);
- if (filename == NULL) {
- PyErr_Print();
- return -1;
- }
- PyObject *program_name = PyUnicode_FromWideChar(config->program_name, -1);
- if (program_name == NULL) {
- Py_DECREF(filename);
- PyErr_Print();
- return -1;
- }
- int res = pymain_run_file_obj(program_name, filename,
- config->skip_source_first_line);
- Py_DECREF(filename);
- Py_DECREF(program_name);
- return res;
- }
- static int
- pymain_run_startup(PyConfig *config, int *exitcode)
- {
- int ret;
- if (!config->use_environment) {
- return 0;
- }
- PyObject *startup = NULL;
- #ifdef MS_WINDOWS
- const wchar_t *env = _wgetenv(L"PYTHONSTARTUP");
- if (env == NULL || env[0] == L'\0') {
- return 0;
- }
- startup = PyUnicode_FromWideChar(env, wcslen(env));
- if (startup == NULL) {
- goto error;
- }
- #else
- const char *env = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP");
- if (env == NULL) {
- return 0;
- }
- startup = PyUnicode_DecodeFSDefault(env);
- if (startup == NULL) {
- goto error;
- }
- #endif
- if (PySys_Audit("cpython.run_startup", "O", startup) < 0) {
- goto error;
- }
- FILE *fp = _Py_fopen_obj(startup, "r");
- if (fp == NULL) {
- int save_errno = errno;
- PyErr_Clear();
- PySys_WriteStderr("Could not open PYTHONSTARTUP\n");
- errno = save_errno;
- PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, startup, NULL);
- goto error;
- }
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
- (void) _PyRun_SimpleFileObject(fp, startup, 0, &cf);
- PyErr_Clear();
- fclose(fp);
- ret = 0;
- done:
- Py_XDECREF(startup);
- return ret;
- error:
- ret = pymain_err_print(exitcode);
- goto done;
- }
- /* Write an exitcode into *exitcode and return 1 if we have to exit Python.
- Return 0 otherwise. */
- static int
- pymain_run_interactive_hook(int *exitcode)
- {
- PyObject *sys, *hook, *result;
- sys = PyImport_ImportModule("sys");
- if (sys == NULL) {
- goto error;
- }
- hook = PyObject_GetAttrString(sys, "__interactivehook__");
- Py_DECREF(sys);
- if (hook == NULL) {
- PyErr_Clear();
- return 0;
- }
- if (PySys_Audit("cpython.run_interactivehook", "O", hook) < 0) {
- goto error;
- }
- result = _PyObject_CallNoArgs(hook);
- Py_DECREF(hook);
- if (result == NULL) {
- goto error;
- }
- Py_DECREF(result);
- return 0;
- error:
- PySys_WriteStderr("Failed calling sys.__interactivehook__\n");
- return pymain_err_print(exitcode);
- }
- static void
- pymain_set_inspect(PyConfig *config, int inspect)
- {
- config->inspect = inspect;
- _Py_COMP_DIAG_PUSH
- _Py_COMP_DIAG_IGNORE_DEPR_DECLS
- Py_InspectFlag = inspect;
- _Py_COMP_DIAG_POP
- }
- static int
- pymain_run_stdin(PyConfig *config)
- {
- if (stdin_is_interactive(config)) {
- // do exit on SystemExit
- pymain_set_inspect(config, 0);
- int exitcode;
- if (pymain_run_startup(config, &exitcode)) {
- return exitcode;
- }
- if (pymain_run_interactive_hook(&exitcode)) {
- return exitcode;
- }
- }
- /* call pending calls like signal handlers (SIGINT) */
- if (Py_MakePendingCalls() == -1) {
- return pymain_exit_err_print();
- }
- if (PySys_Audit("cpython.run_stdin", NULL) < 0) {
- return pymain_exit_err_print();
- }
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
- int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf);
- return (run != 0);
- }
- static void
- pymain_repl(PyConfig *config, int *exitcode)
- {
- /* Check this environment variable at the end, to give programs the
- opportunity to set it from Python. */
- if (!config->inspect && _Py_GetEnv(config->use_environment, "PYTHONINSPECT")) {
- pymain_set_inspect(config, 1);
- }
- if (!(config->inspect && stdin_is_interactive(config) && config_run_code(config))) {
- return;
- }
- pymain_set_inspect(config, 0);
- if (pymain_run_interactive_hook(exitcode)) {
- return;
- }
- if (PySys_Audit("cpython.run_stdin", NULL) < 0) {
- return;
- }
- PyCompilerFlags cf = _PyCompilerFlags_INIT;
- int res = PyRun_AnyFileFlags(stdin, "<stdin>", &cf);
- *exitcode = (res != 0);
- }
- static void
- pymain_run_python(int *exitcode)
- {
- PyObject *main_importer_path = NULL;
- PyInterpreterState *interp = _PyInterpreterState_GET();
- /* pymain_run_stdin() modify the config */
- PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp);
- /* ensure path config is written into global variables */
- if (_PyStatus_EXCEPTION(_PyPathConfig_UpdateGlobal(config))) {
- goto error;
- }
- assert(interp->runtime->sys_path_0 == NULL);
- if (config->run_filename != NULL) {
- /* If filename is a package (ex: directory or ZIP file) which contains
- __main__.py, main_importer_path is set to filename and will be
- prepended to sys.path.
- Otherwise, main_importer_path is left unchanged. */
- if (pymain_get_importer(config->run_filename, &main_importer_path,
- exitcode)) {
- return;
- }
- }
- // import readline and rlcompleter before script dir is added to sys.path
- pymain_import_readline(config);
- PyObject *path0 = NULL;
- if (main_importer_path != NULL) {
- path0 = Py_NewRef(main_importer_path);
- }
- else if (!config->safe_path) {
- int res = _PyPathConfig_ComputeSysPath0(&config->argv, &path0);
- if (res < 0) {
- goto error;
- }
- else if (res == 0) {
- Py_CLEAR(path0);
- }
- }
- if (path0 != NULL) {
- wchar_t *wstr = PyUnicode_AsWideCharString(path0, NULL);
- if (wstr == NULL) {
- Py_DECREF(path0);
- goto error;
- }
- PyMemAllocatorEx old_alloc;
- _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
- interp->runtime->sys_path_0 = _PyMem_RawWcsdup(wstr);
- PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
- PyMem_Free(wstr);
- if (interp->runtime->sys_path_0 == NULL) {
- Py_DECREF(path0);
- goto error;
- }
- int res = pymain_sys_path_add_path0(interp, path0);
- Py_DECREF(path0);
- if (res < 0) {
- goto error;
- }
- }
- pymain_header(config);
- _PyInterpreterState_SetRunningMain(interp);
- assert(!PyErr_Occurred());
- if (config->run_command) {
- *exitcode = pymain_run_command(config->run_command);
- }
- else if (config->run_module) {
- *exitcode = pymain_run_module(config->run_module, 1);
- }
- else if (main_importer_path != NULL) {
- *exitcode = pymain_run_module(L"__main__", 0);
- }
- else if (config->run_filename != NULL) {
- *exitcode = pymain_run_file(config);
- }
- else {
- *exitcode = pymain_run_stdin(config);
- }
- pymain_repl(config, exitcode);
- goto done;
- error:
- *exitcode = pymain_exit_err_print();
- done:
- _PyInterpreterState_SetNotRunningMain(interp);
- Py_XDECREF(main_importer_path);
- }
- /* --- pymain_main() ---------------------------------------------- */
- static void
- pymain_free(void)
- {
- _PyImport_Fini2();
- /* Free global variables which cannot be freed in Py_Finalize():
- configuration options set before Py_Initialize() which should
- remain valid after Py_Finalize(), since
- Py_Initialize()-Py_Finalize() can be called multiple times. */
- _PyPathConfig_ClearGlobal();
- _Py_ClearStandardStreamEncoding();
- _Py_ClearArgcArgv();
- _PyRuntime_Finalize();
- }
- static int
- exit_sigint(void)
- {
- /* bpo-1054041: We need to exit via the
- * SIG_DFL handler for SIGINT if KeyboardInterrupt went unhandled.
- * If we don't, a calling process such as a shell may not know
- * about the user's ^C. https://www.cons.org/cracauer/sigint.html */
- #if defined(HAVE_GETPID) && defined(HAVE_KILL) && !defined(MS_WINDOWS)
- if (PyOS_setsig(SIGINT, SIG_DFL) == SIG_ERR) {
- perror("signal"); /* Impossible in normal environments. */
- } else {
- kill(getpid(), SIGINT);
- }
- /* If setting SIG_DFL failed, or kill failed to terminate us,
- * there isn't much else we can do aside from an error code. */
- #endif /* HAVE_GETPID && !MS_WINDOWS */
- #ifdef MS_WINDOWS
- /* cmd.exe detects this, prints ^C, and offers to terminate. */
- /* https://msdn.microsoft.com/en-us/library/cc704588.aspx */
- return STATUS_CONTROL_C_EXIT;
- #else
- return SIGINT + 128;
- #endif /* !MS_WINDOWS */
- }
- static void _Py_NO_RETURN
- pymain_exit_error(PyStatus status)
- {
- if (_PyStatus_IS_EXIT(status)) {
- /* If it's an error rather than a regular exit, leave Python runtime
- alive: Py_ExitStatusException() uses the current exception and use
- sys.stdout in this case. */
- pymain_free();
- }
- Py_ExitStatusException(status);
- }
- int
- Py_RunMain(void)
- {
- int exitcode = 0;
- pymain_run_python(&exitcode);
- if (Py_FinalizeEx() < 0) {
- /* Value unlikely to be confused with a non-error exit status or
- other special meaning */
- exitcode = 120;
- }
- pymain_free();
- if (_PyRuntime.signals.unhandled_keyboard_interrupt) {
- exitcode = exit_sigint();
- }
- return exitcode;
- }
- static int
- pymain_main(_PyArgv *args)
- {
- PyStatus status = pymain_init(args);
- if (_PyStatus_IS_EXIT(status)) {
- pymain_free();
- return status.exitcode;
- }
- if (_PyStatus_EXCEPTION(status)) {
- pymain_exit_error(status);
- }
- return Py_RunMain();
- }
- int
- Py_Main(int argc, wchar_t **argv)
- {
- _PyArgv args = {
- .argc = argc,
- .use_bytes_argv = 0,
- .bytes_argv = NULL,
- .wchar_argv = argv};
- return pymain_main(&args);
- }
- int
- Py_BytesMain(int argc, char **argv)
- {
- _PyArgv args = {
- .argc = argc,
- .use_bytes_argv = 1,
- .bytes_argv = argv,
- .wchar_argv = NULL};
- return pymain_main(&args);
- }
- #ifdef __cplusplus
- }
- #endif
|