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 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 //Pythons 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