1 /** @file
2   Python interpreter main program.
3 
4   Copyright (c) 2015, Daryl McDaniel. All rights reserved.<BR>
5 **/
6 
7 #include "Python.h"
8 #include "osdefs.h"
9 #include "code.h" /* For CO_FUTURE_DIVISION */
10 #include "import.h"
11 
12 #ifdef __VMS
13 #include <unixlib.h>
14 #endif
15 
16 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
17 #ifdef HAVE_FCNTL_H
18 #include <fcntl.h>
19 #endif
20 #endif
21 
22 #if (defined(PYOS_OS2) && !defined(PYCC_GCC)) || defined(MS_WINDOWS)
23 #define PYTHONHOMEHELP "<prefix>\\lib"
24 #else
25 #if defined(PYOS_OS2) && defined(PYCC_GCC)
26 #define PYTHONHOMEHELP "<prefix>/Lib"
27 #else
28 #define PYTHONHOMEHELP "<prefix>/pythonX.X"
29 #endif
30 #endif
31 
32 #include "pygetopt.h"
33 
34 #define COPYRIGHT \
35     "Type \"help\", \"copyright\", \"credits\" or \"license\" " \
36     "for more information."
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 /* For Py_GetArgcArgv(); set by main() */
43 static char **orig_argv;
44 static int  orig_argc;
45 
46 /* command line options */
47 #define BASE_OPTS "#3bBc:dEhiJm:OQ:sStuUvVW:xX?"
48 
49 #ifndef RISCOS
50 #define PROGRAM_OPTS BASE_OPTS
51 #else /*RISCOS*/
52 /* extra option saying that we are running under a special task window
53    frontend; especially my_readline will behave different */
54 #define PROGRAM_OPTS BASE_OPTS "w"
55 /* corresponding flag */
56 extern int Py_RISCOSWimpFlag;
57 #endif /*RISCOS*/
58 
59 /* Short usage message (with %s for argv0) */
60 static char *usage_line =
61 "usage: %s [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
62 
63 /* Long usage message, split into parts < 512 bytes */
64 static char *usage_1 = "\
65 Options and arguments (and corresponding environment variables):\n\
66 -#     : alias stderr to stdout for platforms without STDERR output.\n\
67 -B     : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x\n\
68 -c cmd : program passed in as string (terminates option list)\n\
69 -d     : debug output from parser; also PYTHONDEBUG=x\n\
70 -E     : ignore PYTHON* environment variables (such as PYTHONPATH)\n\
71 -h     : print this help message and exit (also --help)\n\
72 -i     : inspect interactively after running script; forces a prompt even\n\
73 ";
74 static char *usage_2 = "\
75          if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\
76 -m mod : run library module as a script (terminates option list)\n\
77 -O     : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\
78 -OO    : remove doc-strings in addition to the -O optimizations\n\
79 -Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n\
80 -s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\
81 -S     : don't imply 'import site' on initialization\n\
82 -t     : issue warnings about inconsistent tab usage (-tt: issue errors)\n\
83 ";
84 static char *usage_3 = "\
85 -u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x\n\
86          see man page for details on internal buffering relating to '-u'\n\
87 -v     : verbose (trace import statements); also PYTHONVERBOSE=x\n\
88          can be supplied multiple times to increase verbosity\n\
89 -V     : print the Python version number and exit (also --version)\n\
90 -W arg : warning control; arg is action:message:category:module:lineno\n\
91          also PYTHONWARNINGS=arg\n\
92 -x     : skip first line of source, allowing use of non-Unix forms of #!cmd\n\
93 ";
94 static char *usage_4 = "\
95 -3     : warn about Python 3.x incompatibilities that 2to3 cannot trivially fix\n\
96 file   : program read from script file\n\
97 -      : program read from stdin (default; interactive mode if a tty)\n\
98 arg ...: arguments passed to program in sys.argv[1:]\n\n\
99 Other environment variables:\n\
100 PYTHONSTARTUP: file executed on interactive startup (no default)\n\
101 PYTHONPATH   : '%c'-separated list of directories prefixed to the\n\
102                default module search path.  The result is sys.path.\n\
103 ";
104 static char *usage_5 = "\
105 PYTHONHOME   : alternate <prefix> directory (or <prefix>%c<exec_prefix>).\n\
106                The default module search path uses %s.\n\
107 PYTHONCASEOK : ignore case in 'import' statements (UEFI default).\n\
108 PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n\
109 ";
110 
111 
112 static int
usage(int exitcode,char * program)113 usage(int exitcode, char* program)
114 {
115     FILE *f = exitcode ? stderr : stdout;
116 
117     fprintf(f, usage_line, program);
118     if (exitcode)
119         fprintf(f, "Try `python -h' for more information.\n");
120     else {
121         fputs(usage_1, f);
122         fputs(usage_2, f);
123         fputs(usage_3, f);
124         fprintf(f, usage_4, DELIM);
125         fprintf(f, usage_5, DELIM, PYTHONHOMEHELP);
126     }
127 #if defined(__VMS)
128     if (exitcode == 0) {
129         /* suppress 'error' message */
130         return 1;
131     }
132     else {
133         /* STS$M_INHIB_MSG + SS$_ABORT */
134         return 0x1000002c;
135     }
136 #else
137     return exitcode;
138 #endif
139     /*NOTREACHED*/
140 }
141 
RunStartupFile(PyCompilerFlags * cf)142 static void RunStartupFile(PyCompilerFlags *cf)
143 {
144     char *startup = Py_GETENV("PYTHONSTARTUP");
145     if (startup != NULL && startup[0] != '\0') {
146         FILE *fp = fopen(startup, "r");
147         if (fp != NULL) {
148             (void) PyRun_SimpleFileExFlags(fp, startup, 0, cf);
149             PyErr_Clear();
150             fclose(fp);
151            } else {
152                     int save_errno;
153                     save_errno = errno;
154                     PySys_WriteStderr("Could not open PYTHONSTARTUP\n");
155                     errno = save_errno;
156                     PyErr_SetFromErrnoWithFilename(PyExc_IOError,
157                                                    startup);
158                     PyErr_Print();
159                     PyErr_Clear();
160         }
161     }
162 }
163 
164 
RunModule(char * module,int set_argv0)165 static int RunModule(char *module, int set_argv0)
166 {
167     PyObject *runpy, *runmodule, *runargs, *result;
168     runpy = PyImport_ImportModule("runpy");
169     if (runpy == NULL) {
170         fprintf(stderr, "Could not import runpy module\n");
171         return -1;
172     }
173     runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main");
174     if (runmodule == NULL) {
175         fprintf(stderr, "Could not access runpy._run_module_as_main\n");
176         Py_DECREF(runpy);
177         return -1;
178     }
179     runargs = Py_BuildValue("(si)", module, set_argv0);
180     if (runargs == NULL) {
181         fprintf(stderr,
182             "Could not create arguments for runpy._run_module_as_main\n");
183         Py_DECREF(runpy);
184         Py_DECREF(runmodule);
185         return -1;
186     }
187     result = PyObject_Call(runmodule, runargs, NULL);
188     if (result == NULL) {
189         PyErr_Print();
190     }
191     Py_DECREF(runpy);
192     Py_DECREF(runmodule);
193     Py_DECREF(runargs);
194     if (result == NULL) {
195         return -1;
196     }
197     Py_DECREF(result);
198     return 0;
199 }
200 
RunMainFromImporter(char * filename)201 static int RunMainFromImporter(char *filename)
202 {
203     PyObject *argv0 = NULL, *importer = NULL;
204 
205     if ((argv0 = PyString_FromString(filename)) &&
206         (importer = PyImport_GetImporter(argv0)) &&
207         (importer->ob_type != &PyNullImporter_Type))
208     {
209              /* argv0 is usable as an import source, so
210                     put it in sys.path[0] and import __main__ */
211         PyObject *sys_path = NULL;
212         if ((sys_path = PySys_GetObject("path")) &&
213             !PyList_SetItem(sys_path, 0, argv0))
214         {
215             Py_INCREF(argv0);
216             Py_DECREF(importer);
217             sys_path = NULL;
218             return RunModule("__main__", 0) != 0;
219         }
220     }
221     Py_XDECREF(argv0);
222     Py_XDECREF(importer);
223     if (PyErr_Occurred()) {
224         PyErr_Print();
225         return 1;
226     }
227     return -1;
228 }
229 
230 
231 /* Main program */
232 
233 int
Py_Main(int argc,char ** argv)234 Py_Main(int argc, char **argv)
235 {
236     int c;
237     int sts;
238     char *command = NULL;
239     char *filename = NULL;
240     char *module = NULL;
241     FILE *fp = stdin;
242     char *p;
243     int unbuffered = 0;
244     int skipfirstline = 0;
245     int stdin_is_interactive = 0;
246     int help = 0;
247     int version = 0;
248     int saw_unbuffered_flag = 0;
249     int saw_pound_flag = 0;
250     PyCompilerFlags cf;
251 
252     cf.cf_flags = 0;
253 
254     orig_argc = argc;           /* For Py_GetArgcArgv() */
255     orig_argv = argv;
256 
257 #ifdef RISCOS
258     Py_RISCOSWimpFlag = 0;
259 #endif
260 
261     PySys_ResetWarnOptions();
262 
263     while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
264         if (c == 'c') {
265             /* -c is the last option; following arguments
266                that look like options are left for the
267                command to interpret. */
268             command = (char *)malloc(strlen(_PyOS_optarg) + 2);
269             if (command == NULL)
270                 Py_FatalError(
271                    "not enough memory to copy -c argument");
272             strcpy(command, _PyOS_optarg);
273             strcat(command, "\n");
274             break;
275         }
276 
277         if (c == 'm') {
278             /* -m is the last option; following arguments
279                that look like options are left for the
280                module to interpret. */
281             module = (char *)malloc(strlen(_PyOS_optarg) + 2);
282             if (module == NULL)
283                 Py_FatalError(
284                    "not enough memory to copy -m argument");
285             strcpy(module, _PyOS_optarg);
286             break;
287         }
288 
289         switch (c) {
290         case 'b':
291             Py_BytesWarningFlag++;
292             break;
293 
294         case 'd':
295             Py_DebugFlag++;
296             break;
297 
298         case '3':
299             Py_Py3kWarningFlag++;
300             if (!Py_DivisionWarningFlag)
301                 Py_DivisionWarningFlag = 1;
302             break;
303 
304         case 'Q':
305             if (strcmp(_PyOS_optarg, "old") == 0) {
306                 Py_DivisionWarningFlag = 0;
307                 break;
308             }
309             if (strcmp(_PyOS_optarg, "warn") == 0) {
310                 Py_DivisionWarningFlag = 1;
311                 break;
312             }
313             if (strcmp(_PyOS_optarg, "warnall") == 0) {
314                 Py_DivisionWarningFlag = 2;
315                 break;
316             }
317             if (strcmp(_PyOS_optarg, "new") == 0) {
318                 /* This only affects __main__ */
319                 cf.cf_flags |= CO_FUTURE_DIVISION;
320                 /* And this tells the eval loop to treat
321                    BINARY_DIVIDE as BINARY_TRUE_DIVIDE */
322                 _Py_QnewFlag = 1;
323                 break;
324             }
325             fprintf(stderr,
326                 "-Q option should be `-Qold', "
327                 "`-Qwarn', `-Qwarnall', or `-Qnew' only\n");
328             return usage(2, argv[0]);
329             /* NOTREACHED */
330 
331         case 'i':
332             Py_InspectFlag++;
333             Py_InteractiveFlag++;
334             break;
335 
336         /* case 'J': reserved for Jython */
337 
338         case 'O':
339             Py_OptimizeFlag++;
340             break;
341 
342         case 'B':
343             Py_DontWriteBytecodeFlag++;
344             break;
345 
346         case 's':
347             Py_NoUserSiteDirectory++;
348             break;
349 
350         case 'S':
351             Py_NoSiteFlag++;
352             break;
353 
354         case 'E':
355           Py_IgnoreEnvironmentFlag++;
356           break;
357 
358         case 't':
359             Py_TabcheckFlag++;
360             break;
361 
362         case 'u':
363             unbuffered++;
364             saw_unbuffered_flag = 1;
365             break;
366 
367         case 'v':
368             Py_VerboseFlag++;
369             break;
370 
371 #ifdef RISCOS
372         case 'w':
373             Py_RISCOSWimpFlag = 1;
374             break;
375 #endif
376 
377         case 'x':
378             skipfirstline = 1;
379             break;
380 
381         /* case 'X': reserved for implementation-specific arguments */
382 
383         case 'U':
384             Py_UnicodeFlag++;
385             break;
386         case 'h':
387         case '?':
388             help++;
389             break;
390         case 'V':
391             version++;
392             break;
393 
394         case 'W':
395             PySys_AddWarnOption(_PyOS_optarg);
396             break;
397 
398         case '#':
399           if (saw_pound_flag == 0) {
400             if(freopen("stdout:", "w", stderr) == NULL) {
401               puts("ERROR: Unable to reopen stderr as an alias to stdout!");
402             }
403             saw_pound_flag = 0xFF;
404           }
405           break;
406 
407         /* This space reserved for other options */
408 
409         default:
410             return usage(2, argv[0]);
411             /*NOTREACHED*/
412 
413         }
414     }
415 
416     if (help)
417         return usage(0, argv[0]);
418 
419     if (version) {
420         fprintf(stderr, "Python %s\n", PY_VERSION);
421         return 0;
422     }
423 
424     if (Py_Py3kWarningFlag && !Py_TabcheckFlag)
425         /* -3 implies -t (but not -tt) */
426         Py_TabcheckFlag = 1;
427 
428     if (!Py_InspectFlag &&
429         (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
430         Py_InspectFlag = 1;
431     if (!saw_unbuffered_flag &&
432         (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
433         unbuffered = 1;
434 
435     if (!Py_NoUserSiteDirectory &&
436         (p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0')
437         Py_NoUserSiteDirectory = 1;
438 
439     if ((p = Py_GETENV("PYTHONWARNINGS")) && *p != '\0') {
440         char *buf, *warning;
441 
442         buf = (char *)malloc(strlen(p) + 1);
443         if (buf == NULL)
444             Py_FatalError(
445                "not enough memory to copy PYTHONWARNINGS");
446         strcpy(buf, p);
447         for (warning = strtok(buf, ",");
448              warning != NULL;
449              warning = strtok(NULL, ","))
450             PySys_AddWarnOption(warning);
451         free(buf);
452     }
453 
454     if (command == NULL && module == NULL && _PyOS_optind < argc &&
455         strcmp(argv[_PyOS_optind], "-") != 0)
456     {
457 #ifdef __VMS
458         filename = decc$translate_vms(argv[_PyOS_optind]);
459         if (filename == (char *)0 || filename == (char *)-1)
460             filename = argv[_PyOS_optind];
461 
462 #else
463         filename = argv[_PyOS_optind];
464 #endif
465     }
466 
467     stdin_is_interactive = Py_FdIsInteractive(stdin, (char *)0);
468 
469     if (unbuffered) {
470 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
471         _setmode(fileno(stdin), O_BINARY);
472         _setmode(fileno(stdout), O_BINARY);
473 #endif
474 #ifdef HAVE_SETVBUF
475         setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
476         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
477         setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
478 #else /* !HAVE_SETVBUF */
479         setbuf(stdin,  (char *)NULL);
480         setbuf(stdout, (char *)NULL);
481         setbuf(stderr, (char *)NULL);
482 #endif /* !HAVE_SETVBUF */
483     }
484     else if (Py_InteractiveFlag) {
485 #ifdef MS_WINDOWS
486         /* Doesn't have to have line-buffered -- use unbuffered */
487         /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
488         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
489 #else /* !MS_WINDOWS */
490 #ifdef HAVE_SETVBUF
491         setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
492         setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
493 #endif /* HAVE_SETVBUF */
494 #endif /* !MS_WINDOWS */
495         /* Leave stderr alone - it should be unbuffered anyway. */
496     }
497 #ifdef __VMS
498     else {
499         setvbuf (stdout, (char *)NULL, _IOLBF, BUFSIZ);
500     }
501 #endif /* __VMS */
502 
503 #ifdef __APPLE__
504     /* On MacOS X, when the Python interpreter is embedded in an
505        application bundle, it gets executed by a bootstrapping script
506        that does os.execve() with an argv[0] that's different from the
507        actual Python executable. This is needed to keep the Finder happy,
508        or rather, to work around Apple's overly strict requirements of
509        the process name. However, we still need a usable sys.executable,
510        so the actual executable path is passed in an environment variable.
511        See Lib/plat-mac/bundlebuiler.py for details about the bootstrap
512        script. */
513     if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0')
514         Py_SetProgramName(p);
515     else
516         Py_SetProgramName(argv[0]);
517 #else
518     Py_SetProgramName(argv[0]);
519 #endif
520     Py_Initialize();
521 
522     if (Py_VerboseFlag ||
523         (command == NULL && filename == NULL && module == NULL && stdin_is_interactive)) {
524         fprintf(stderr, "Python %s on %s\n",
525             Py_GetVersion(), Py_GetPlatform());
526         if (!Py_NoSiteFlag)
527             fprintf(stderr, "%s\n", COPYRIGHT);
528     }
529 
530     if (command != NULL) {
531         /* Backup _PyOS_optind and force sys.argv[0] = '-c' */
532         _PyOS_optind--;
533         argv[_PyOS_optind] = "-c";
534     }
535 
536     if (module != NULL) {
537         /* Backup _PyOS_optind and force sys.argv[0] = '-c'
538            so that PySys_SetArgv correctly sets sys.path[0] to ''
539            rather than looking for a file called "-m". See
540            tracker issue #8202 for details. */
541         _PyOS_optind--;
542         argv[_PyOS_optind] = "-c";
543     }
544 
545     PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
546 
547     if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) &&
548         isatty(fileno(stdin))) {
549         PyObject *v;
550         v = PyImport_ImportModule("readline");
551         if (v == NULL)
552             PyErr_Clear();
553         else
554             Py_DECREF(v);
555     }
556 
557     if (command) {
558         sts = PyRun_SimpleStringFlags(command, &cf) != 0;
559         free(command);
560     } else if (module) {
561         sts = (RunModule(module, 1) != 0);
562         free(module);
563     }
564     else {
565 
566         if (filename == NULL && stdin_is_interactive) {
567             Py_InspectFlag = 0; /* do exit on SystemExit */
568             RunStartupFile(&cf);
569         }
570         /* XXX */
571 
572         sts = -1;               /* keep track of whether we've already run __main__ */
573 
574         if (filename != NULL) {
575             sts = RunMainFromImporter(filename);
576         }
577 
578         if (sts==-1 && filename!=NULL) {
579             if ((fp = fopen(filename, "r")) == NULL) {
580                 fprintf(stderr, "%s: can't open file '%s': [Errno %d] %s\n",
581                     argv[0], filename, errno, strerror(errno));
582 
583                 return 2;
584             }
585             else if (skipfirstline) {
586                 int ch;
587                 /* Push back first newline so line numbers
588                    remain the same */
589                 while ((ch = getc(fp)) != EOF) {
590                     if (ch == '\n') {
591                         (void)ungetc(ch, fp);
592                         break;
593                     }
594                 }
595             }
596             {
597                 /* XXX: does this work on Win/Win64? (see posix_fstat) */
598                 struct stat sb;
599                 if (fstat(fileno(fp), &sb) == 0 &&
600                     S_ISDIR(sb.st_mode)) {
601                     fprintf(stderr, "%s: '%s' is a directory, cannot continue\n", argv[0], filename);
602                     fclose(fp);
603                     return 1;
604                 }
605             }
606         }
607 
608         if (sts==-1) {
609             /* call pending calls like signal handlers (SIGINT) */
610             if (Py_MakePendingCalls() == -1) {
611                 PyErr_Print();
612                 sts = 1;
613             } else {
614                 sts = PyRun_AnyFileExFlags(
615                     fp,
616                     filename == NULL ? "<stdin>" : filename,
617                     filename != NULL, &cf) != 0;
618             }
619         }
620 
621     }
622 
623     /* Check this environment variable at the end, to give programs the
624      * opportunity to set it from Python.
625      */
626     if (!Py_InspectFlag &&
627         (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
628     {
629         Py_InspectFlag = 1;
630     }
631 
632     if (Py_InspectFlag && stdin_is_interactive &&
633         (filename != NULL || command != NULL || module != NULL)) {
634         Py_InspectFlag = 0;
635         /* XXX */
636         sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
637     }
638 
639     Py_Finalize();
640 #ifdef RISCOS
641     if (Py_RISCOSWimpFlag)
642         fprintf(stderr, "\x0cq\x0c"); /* make frontend quit */
643 #endif
644 
645 #ifdef __INSURE__
646     /* Insure++ is a memory analysis tool that aids in discovering
647      * memory leaks and other memory problems.  On Python exit, the
648      * interned string dictionary is flagged as being in use at exit
649      * (which it is).  Under normal circumstances, this is fine because
650      * the memory will be automatically reclaimed by the system.  Under
651      * memory debugging, it's a huge source of useless noise, so we
652      * trade off slower shutdown for less distraction in the memory
653      * reports.  -baw
654      */
655     _Py_ReleaseInternedStrings();
656 #endif /* __INSURE__ */
657 
658     return sts;
659 }
660 
661 /* this is gonna seem *real weird*, but if you put some other code between
662    Py_Main() and Py_GetArgcArgv() you will need to adjust the test in the
663    while statement in Misc/gdbinit:ppystack */
664 
665 /* Make the *original* argc/argv available to other modules.
666    This is rare, but it is needed by the secureware extension. */
667 
668 void
Py_GetArgcArgv(int * argc,char *** argv)669 Py_GetArgcArgv(int *argc, char ***argv)
670 {
671     *argc = orig_argc;
672     *argv = orig_argv;
673 }
674 
675 #ifdef __cplusplus
676 }
677 #endif
678 
679