/home/mdboom/Work/builds/cpython/Modules/main.c
Line | Count | Source (jump to first uncovered line) |
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 |
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) { Branch (57:9): [True: 11, False: 3]
|
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 */ |
83 | static inline int config_run_code(const PyConfig *config) |
84 | { |
85 | return (config->run_command != NULL Branch (85:13): [True: 44, False: 7]
|
86 | || config->run_filename != NULL7 Branch (86:16): [True: 2, False: 5]
|
87 | || config->run_module != NULL5 ); Branch (87:16): [True: 2, False: 3]
|
88 | } |
89 | |
90 | |
91 | /* Return non-zero if stdin is a TTY or if -i command line option is used */ |
92 | static int |
93 | stdin_is_interactive(const PyConfig *config) |
94 | { |
95 | return (isatty(fileno(stdin)) || config->interactive0 ); Branch (95:13): [True: 3, False: 0]
Branch (95:38): [True: 0, False: 0]
|
96 | } |
97 | |
98 | |
99 | /* Display the current Python exception and return an exitcode */ |
100 | static int |
101 | pymain_err_print(int *exitcode_p) |
102 | { |
103 | int exitcode; |
104 | if (_Py_HandleSystemExit(&exitcode)) { Branch (104:9): [True: 1, False: 3]
|
105 | *exitcode_p = exitcode; |
106 | return 1; |
107 | } |
108 | |
109 | PyErr_Print(); |
110 | return 0; |
111 | } |
112 | |
113 | |
114 | static int |
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 |
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) { Branch (131:9): [True: 0, False: 1]
|
132 | goto error; |
133 | } |
134 | |
135 | importer = PyImport_GetImporter(sys_path0); |
136 | if (importer == NULL) { Branch (136:9): [True: 0, False: 1]
|
137 | goto error; |
138 | } |
139 | |
140 | if (importer == Py_None) { Branch (140:9): [True: 1, False: 0]
|
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 |
159 | pymain_sys_path_add_path0(PyInterpreterState *interp, PyObject *path0) |
160 | { |
161 | PyObject *sys_path; |
162 | PyObject *sysdict = interp->sysdict; |
163 | if (sysdict != NULL) { Branch (163:9): [True: 25, False: 0]
|
164 | sys_path = PyDict_GetItemWithError(sysdict, &_Py_ID(path)); |
165 | if (sys_path == NULL && PyErr_Occurred()0 ) { Branch (165:13): [True: 0, False: 25]
Branch (165:33): [True: 0, False: 0]
|
166 | return -1; |
167 | } |
168 | } |
169 | else { |
170 | sys_path = NULL; |
171 | } |
172 | if (sys_path == NULL) { Branch (172:9): [True: 0, False: 25]
|
173 | PyErr_SetString(PyExc_RuntimeError, "unable to get sys.path"); |
174 | return -1; |
175 | } |
176 | |
177 | if (PyList_Insert(sys_path, 0, path0)) { Branch (177:9): [True: 0, False: 25]
|
178 | return -1; |
179 | } |
180 | return 0; |
181 | } |
182 | |
183 | |
184 | static void |
185 | pymain_header(const PyConfig *config) |
186 | { |
187 | if (config->quiet) { Branch (187:9): [True: 3, False: 26]
|
188 | return; |
189 | } |
190 | |
191 | if (!config->verbose && (config_run_code(config) || !stdin_is_interactive(config)0 )) { Branch (191:9): [True: 26, False: 0]
Branch (191:30): [True: 26, False: 0]
Branch (191:57): [True: 0, False: 0]
|
192 | return; |
193 | } |
194 | |
195 | fprintf(stderr, "Python %s on %s\n", Py_GetVersion(), Py_GetPlatform()); |
196 | if (config->site_import) { Branch (196:9): [True: 0, False: 0]
|
197 | fprintf(stderr, "%s\n", COPYRIGHT); |
198 | } |
199 | } |
200 | |
201 | |
202 | static void |
203 | pymain_import_readline(const PyConfig *config) |
204 | { |
205 | if (config->isolated) { Branch (205:9): [True: 4, False: 25]
|
206 | return; |
207 | } |
208 | if (!config->inspect && config_run_code(config)) { Branch (208:9): [True: 25, False: 0]
Branch (208:29): [True: 22, False: 3]
|
209 | return; |
210 | } |
211 | if (!isatty(fileno(stdin))) { Branch (211:9): [True: 0, False: 3]
|
212 | return; |
213 | } |
214 | |
215 | PyObject *mod = PyImport_ImportModule("readline"); |
216 | if (mod == NULL) { Branch (216:9): [True: 0, False: 3]
|
217 | PyErr_Clear(); |
218 | } |
219 | else { |
220 | Py_DECREF(mod); |
221 | } |
222 | mod = PyImport_ImportModule("rlcompleter"); |
223 | if (mod == NULL) { Branch (223:9): [True: 0, False: 3]
|
224 | PyErr_Clear(); |
225 | } |
226 | else { |
227 | Py_DECREF(mod); |
228 | } |
229 | } |
230 | |
231 | |
232 | static int |
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) { Branch (239:9): [True: 0, False: 24]
|
240 | goto error; |
241 | } |
242 | |
243 | if (PySys_Audit("cpython.run_command", "O", unicode) < 0) { Branch (243:9): [True: 1, False: 23]
|
244 | return pymain_exit_err_print(); |
245 | } |
246 | |
247 | bytes = PyUnicode_AsUTF8String(unicode); |
248 | Py_DECREF(unicode); |
249 | if (bytes == NULL) { Branch (249:9): [True: 0, False: 23]
|
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 |
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) { Branch (269:9): [True: 0, False: 1]
|
270 | return pymain_exit_err_print(); |
271 | } |
272 | runpy = PyImport_ImportModule("runpy"); |
273 | if (runpy == NULL) { Branch (273:9): [True: 0, False: 1]
|
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) { Branch (278:9): [True: 0, False: 1]
|
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) { Branch (284:9): [True: 0, False: 1]
|
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); Branch (290:39): [True: 1, False: 0]
|
291 | if (runargs == NULL) { Branch (291:9): [True: 0, False: 1]
|
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) { Branch (301:9): [True: 1, False: 0]
Branch (301:20): [True: 0, False: 1]
|
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) { Branch (308:9): [True: 1, False: 0]
|
309 | return pymain_exit_err_print(); |
310 | } |
311 | Py_DECREF(result); |
312 | return 0; |
313 | } |
314 | |
315 | |
316 | static int |
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) { Branch (320:9): [True: 1, False: 0]
|
321 | return pymain_exit_err_print(); |
322 | } |
323 | |
324 | FILE *fp = _Py_fopen_obj(filename, "rb"); |
325 | if (fp == NULL) { Branch (325:9): [True: 0, False: 0]
|
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) { Branch (333:9): [True: 0, False: 0]
|
334 | int ch; |
335 | /* Push back first newline so line numbers remain the same */ |
336 | while ((ch = getc(fp)) != EOF) { Branch (336:16): [True: 0, False: 0]
|
337 | if (ch == '\n') { Branch (337:17): [True: 0, False: 0]
|
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)) { Branch (345:9): [True: 0, False: 0]
|
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) { Branch (353:9): [True: 0, False: 0]
|
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 |
365 | pymain_run_file(const PyConfig *config) |
366 | { |
367 | PyObject *filename = PyUnicode_FromWideChar(config->run_filename, -1); |
368 | if (filename == NULL) { Branch (368:9): [True: 0, False: 1]
|
369 | PyErr_Print(); |
370 | return -1; |
371 | } |
372 | PyObject *program_name = PyUnicode_FromWideChar(config->program_name, -1); |
373 | if (program_name == NULL) { Branch (373:9): [True: 0, False: 1]
|
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 |
388 | pymain_run_startup(PyConfig *config, int *exitcode) |
389 | { |
390 | int ret; |
391 | if (!config->use_environment) { Branch (391:9): [True: 0, False: 3]
|
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) { Branch (406:9): [True: 1, False: 2]
|
407 | return 0; |
408 | } |
409 | startup = PyUnicode_DecodeFSDefault(env); |
410 | if (startup == NULL) { Branch (410:9): [True: 0, False: 2]
|
411 | goto error; |
412 | } |
413 | #endif |
414 | if (PySys_Audit("cpython.run_startup", "O", startup) < 0) { Branch (414:9): [True: 0, False: 2]
|
415 | goto error; |
416 | } |
417 | |
418 | FILE *fp = _Py_fopen_obj(startup, "r"); |
419 | if (fp == NULL) { Branch (419:9): [True: 0, False: 2]
|
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 |
448 | pymain_run_interactive_hook(int *exitcode) |
449 | { |
450 | PyObject *sys, *hook, *result; |
451 | sys = PyImport_ImportModule("sys"); |
452 | if (sys == NULL) { Branch (452:9): [True: 0, False: 2]
|
453 | goto error; |
454 | } |
455 | |
456 | hook = PyObject_GetAttrString(sys, "__interactivehook__"); |
457 | Py_DECREF(sys); |
458 | if (hook == NULL) { Branch (458:9): [True: 0, False: 2]
|
459 | PyErr_Clear(); |
460 | return 0; |
461 | } |
462 | |
463 | if (PySys_Audit("cpython.run_interactivehook", "O", hook) < 0) { Branch (463:9): [True: 0, False: 2]
|
464 | goto error; |
465 | } |
466 | |
467 | result = _PyObject_CallNoArgs(hook); |
468 | Py_DECREF(hook); |
469 | if (result == NULL) { Branch (469:9): [True: 0, False: 2]
|
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 void |
483 | pymain_set_inspect(PyConfig *config, int inspect) |
484 | { |
485 | config->inspect = inspect; |
486 | _Py_COMP_DIAG_PUSH |
487 | _Py_COMP_DIAG_IGNORE_DEPR_DECLS |
488 | Py_InspectFlag = inspect; |
489 | _Py_COMP_DIAG_POP |
490 | } |
491 | |
492 | |
493 | static int |
494 | pymain_run_stdin(PyConfig *config) |
495 | { |
496 | if (stdin_is_interactive(config)) { Branch (496:9): [True: 3, False: 0]
|
497 | // do exit on SystemExit |
498 | pymain_set_inspect(config, 0); |
499 | |
500 | int exitcode; |
501 | if (pymain_run_startup(config, &exitcode)) { Branch (501:13): [True: 0, False: 3]
|
502 | return exitcode; |
503 | } |
504 | |
505 | if (pymain_run_interactive_hook(&exitcode)) { Branch (505:13): [True: 0, False: 3]
|
506 | return exitcode; |
507 | } |
508 | } |
509 | |
510 | /* call pending calls like signal handlers (SIGINT) */ |
511 | if (Py_MakePendingCalls() == -1) { Branch (511:9): [True: 0, False: 3]
|
512 | return pymain_exit_err_print(); |
513 | } |
514 | |
515 | if (PySys_Audit("cpython.run_stdin", NULL) < 0) { Branch (515:9): [True: 1, False: 2]
|
516 | return pymain_exit_err_print(); |
517 | } |
518 | |
519 | PyCompilerFlags cf = _PyCompilerFlags_INIT; |
520 | int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf); |
521 | return (run != 0); |
522 | } |
523 | |
524 | |
525 | static void |
526 | pymain_repl(PyConfig *config, int *exitcode) |
527 | { |
528 | /* Check this environment variable at the end, to give programs the |
529 | opportunity to set it from Python. */ |
530 | if (!config->inspect && _Py_GetEnv(config->use_environment, "PYTHONINSPECT")) { Branch (530:9): [True: 21, False: 0]
Branch (530:29): [True: 0, False: 21]
|
531 | pymain_set_inspect(config, 1); |
532 | } |
533 | |
534 | if (!(config->inspect && stdin_is_interactive(config)0 && config_run_code(config)0 )) { Branch (534:11): [True: 0, False: 21]
Branch (534:30): [True: 0, False: 0]
Branch (534:62): [True: 0, False: 0]
|
535 | return; |
536 | } |
537 | |
538 | pymain_set_inspect(config, 0); |
539 | if (pymain_run_interactive_hook(exitcode)) { Branch (539:9): [True: 0, False: 0]
|
540 | return; |
541 | } |
542 | |
543 | PyCompilerFlags cf = _PyCompilerFlags_INIT; |
544 | int res = PyRun_AnyFileFlags(stdin, "<stdin>", &cf); |
545 | *exitcode = (res != 0); |
546 | } |
547 | |
548 | |
549 | static void |
550 | pymain_run_python(int *exitcode) |
551 | { |
552 | PyObject *main_importer_path = NULL; |
553 | PyInterpreterState *interp = _PyInterpreterState_GET(); |
554 | /* pymain_run_stdin() modify the config */ |
555 | PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp); |
556 | |
557 | /* ensure path config is written into global variables */ |
558 | if (_PyStatus_EXCEPTION(_PyPathConfig_UpdateGlobal(config))) { |
559 | goto error; |
560 | } |
561 | |
562 | if (config->run_filename != NULL) { Branch (562:9): [True: 1, False: 28]
|
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, Branch (568:13): [True: 0, False: 1]
|
569 | exitcode)) { |
570 | return; |
571 | } |
572 | } |
573 | |
574 | // import readline and rlcompleter before script dir is added to sys.path |
575 | pymain_import_readline(config); |
576 | |
577 | if (main_importer_path != NULL) { Branch (577:9): [True: 0, False: 29]
|
578 | if (pymain_sys_path_add_path0(interp, main_importer_path) < 0) { Branch (578:13): [True: 0, False: 0]
|
579 | goto error; |
580 | } |
581 | } |
582 | else if (!config->safe_path) { Branch (582:14): [True: 25, False: 4]
|
583 | PyObject *path0 = NULL; |
584 | int res = _PyPathConfig_ComputeSysPath0(&config->argv, &path0); |
585 | if (res < 0) { Branch (585:13): [True: 0, False: 25]
|
586 | goto error; |
587 | } |
588 | |
589 | if (res > 0) { Branch (589:13): [True: 25, False: 0]
|
590 | if (pymain_sys_path_add_path0(interp, path0) < 0) { Branch (590:17): [True: 0, False: 25]
|
591 | Py_DECREF(path0); |
592 | goto error; |
593 | } |
594 | Py_DECREF(path0); |
595 | } |
596 | } |
597 | |
598 | pymain_header(config); |
599 | |
600 | if (config->run_command) { Branch (600:9): [True: 24, False: 5]
|
601 | *exitcode = pymain_run_command(config->run_command); |
602 | } |
603 | else if (config->run_module) { Branch (603:14): [True: 1, False: 4]
|
604 | *exitcode = pymain_run_module(config->run_module, 1); |
605 | } |
606 | else if (main_importer_path != NULL) { Branch (606:14): [True: 0, False: 4]
|
607 | *exitcode = pymain_run_module(L"__main__", 0); |
608 | } |
609 | else if (config->run_filename != NULL) { Branch (609:14): [True: 1, False: 3]
|
610 | *exitcode = pymain_run_file(config); |
611 | } |
612 | else { |
613 | *exitcode = pymain_run_stdin(config); |
614 | } |
615 | |
616 | pymain_repl(config, 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 |
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 |
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) { Branch (653:9): [True: 0, False: 0]
|
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 |
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 |
685 | Py_RunMain(void) |
686 | { |
687 | int exitcode = 0; |
688 | |
689 | pymain_run_python(&exitcode); |
690 | |
691 | if (Py_FinalizeEx() < 0) { Branch (691:9): [True: 0, False: 29]
|
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) { Branch (699:9): [True: 0, False: 29]
|
700 | exitcode = exit_sigint(); |
701 | } |
702 | |
703 | return exitcode; |
704 | } |
705 | |
706 | |
707 | static int |
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 |
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 |
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 |