• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "launcher_internal.h"
16 
17 #include <Python.h>
18 #include <android-base/file.h>
19 #include <osdefs.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string>
23 
main(int argc,char * argv[])24 int main(int argc, char *argv[]) {
25   int result = 0 /* Used to mark if current program runs with success/failure. */;
26 
27   // Clear PYTHONPATH and PYTHONHOME so Python doesn't attempt to check the local
28   // disk for Python modules to load. The value of PYTHONHOME will replace "prefix"
29   // and "exe_prefix" based on the description in getpath.c.
30   // Please don't use PYTHONPATH and PYTHONHOME within user program.
31   // TODO(nanzhang): figure out if unsetenv("PYTHONPATH") is better.
32   unsetenv(const_cast<char *>("PYTHONPATH"));
33   // TODO(nanzhang): figure out if Py_SetPythonHome() is better.
34   unsetenv(const_cast<char *>("PYTHONHOME"));
35   // PYTHONEXECUTABLE is only used on MacOs X, when the Python interpreter
36   // embedded in an application bundle. It is not sure that we have this use case
37   // for Android hermetic Python. So override this environment variable to empty
38   // for now to make our self-contained environment more strict.
39   // For user (.py) program, it can access hermetic .par file path through
40   // sys.argv[0].
41   unsetenv(const_cast<char *>("PYTHONEXECUTABLE"));
42 
43   // Resolving absolute path based on argv[0] is not reliable since it may
44   // include something unusable, too bad.
45   // android::base::GetExecutablePath() also handles for Darwin/Windows.
46   std::string executable_path = android::base::GetExecutablePath();
47 
48   argv[0] = strdup(executable_path.c_str());
49   // argv[0] is used for setting internal path, and Python sys.argv[0]. It
50   // should not exceed MAXPATHLEN defined for CPython.
51   if (!argv[0] || strlen(argv[0]) > MAXPATHLEN) {
52     fprintf(stderr, "The executable path %s is NULL or of invalid length.\n", argv[0]);
53     return 1;
54   }
55 
56   // For debugging/logging purpose, set stdin/stdout/stderr unbuffered through
57   // environment variable.
58   // TODO(nanzhang): Set Py_VerboseFlag if more debugging requests needed.
59   const char *unbuffered_env = getenv("PYTHONUNBUFFERED");
60   if (unbuffered_env && unbuffered_env[0]) {
61     #if defined(MS_WINDOWS) || defined(__CYGWIN__)
62       _setmode(fileno(stdin), O_BINARY);
63       _setmode(fileno(stdout), O_BINARY);
64     #endif
65     #ifdef HAVE_SETVBUF
66       setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
67       setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
68       setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
69     #else /* !HAVE_SETVBUF */
70       setbuf(stdin,  (char *)NULL);
71       setbuf(stdout, (char *)NULL);
72       setbuf(stderr, (char *)NULL);
73     #endif /* !HAVE_SETVBUF */
74   }
75   //For debugging/logging purpose, Warning control.
76   //Python’s warning machinery by default prints warning messages to sys.stderr.
77   //The full form of argument is:action:message:category:module:line
78   char *warnings_env = getenv("PYTHONWARNINGS");
79   if (warnings_env && warnings_env[0]) {
80       char *warnings_buf, *warning;
81 
82       // Note: "new" operation; we need free this chuck of data after use.
83       warnings_buf = new char[strlen(warnings_env) + 1];
84       if (warnings_buf == NULL)
85           Py_FatalError(
86              "not enough memory to copy PYTHONWARNINGS");
87       strcpy(warnings_buf, warnings_env);
88       for (warning = strtok(warnings_buf, ",");
89            warning != NULL;
90            warning = strtok(NULL, ","))
91           PySys_AddWarnOption(warning);
92       delete[] warnings_buf;
93   }
94 
95   // Always enable Python "-s" option. We don't need user-site directories,
96   // everything's supposed to be hermetic.
97   Py_NoUserSiteDirectory = 1;
98 
99   Py_SetProgramName(argv[0]);
100   Py_Initialize();
101   PySys_SetArgvEx(argc, argv, 0);
102 
103   // Set sys.executable to None. The real executable is available as
104   // sys.argv[0], and too many things assume sys.executable is a regular Python
105   // binary, which isn't available. By setting it to None we get clear errors
106   // when people try to use it.
107   if (PySys_SetObject(const_cast<char *>("executable"), Py_None) < 0) {
108     PyErr_Print();
109     result = 1;
110     goto error;
111   }
112 
113   result = android::cpython2::python_launcher::RunEntryPointOrMainModule(argv[0]);
114   if (result < 0) {
115     PyErr_Print();
116     goto error;
117   }
118 
119 error:
120   Py_Finalize();
121 
122   free(argv[0]);
123   exit(abs(result));
124 }
125