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