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