<Hermetic> Implement CPython2 Launcher in C++.

The launcher is actually a wrapper which will statically link Python
interpreter within the .par file. It is used to bootstrap embedded
interpreter.

The next step is to change/integrate with Soong to make this hermetic .par
generation process more automatic.

Bug: b/62380596

Test: The launcher has been tested using real files:
zip -r hermetic.zip entry_point.txt Stdlib/ runfiles/
cat launcher | cat - hermetic.zip > executable && chmod u+x executable

Change-Id: I293cae2fe74d46766044f3e3c4b654a54d319b67
diff --git a/Launcher/launcher_main.cpp b/Launcher/launcher_main.cpp
new file mode 100644
index 0000000..a49998c
--- /dev/null
+++ b/Launcher/launcher_main.cpp
@@ -0,0 +1,124 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "launcher_internal.h"
+
+#include <Python.h>
+#include <android-base/file.h>
+#include <osdefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+
+int main(int argc, char *argv[]) {
+  int result = 0 /* Used to mark if current program runs with success/failure. */;
+
+  // Clear PYTHONPATH and PYTHONHOME so Python doesn't attempt to check the local
+  // disk for Python modules to load. The value of PYTHONHOME will replace "prefix"
+  // and "exe_prefix" based on the description in getpath.c.
+  // Please don't use PYTHONPATH and PYTHONHOME within user program.
+  // TODO(nanzhang): figure out if unsetenv("PYTHONPATH") is better.
+  unsetenv(const_cast<char *>("PYTHONPATH"));
+  // TODO(nanzhang): figure out if Py_SetPythonHome() is better.
+  unsetenv(const_cast<char *>("PYTHONHOME"));
+  // PYTHONEXECUTABLE is only used on MacOs X, when the Python interpreter
+  // embedded in an application bundle. It is not sure that we have this use case
+  // for Android hermetic Python. So override this environment variable to empty
+  // for now to make our self-contained environment more strict.
+  // For user (.py) program, it can access hermetic .par file path through
+  // sys.argv[0].
+  unsetenv(const_cast<char *>("PYTHONEXECUTABLE"));
+
+  // Resolving absolute path based on argv[0] is not reliable since it may
+  // include something unusable, too bad.
+  // android::base::GetExecutablePath() also handles for Darwin/Windows.
+  std::string executable_path = android::base::GetExecutablePath();
+
+  argv[0] = strdup(executable_path.c_str());
+  // argv[0] is used for setting internal path, and Python sys.argv[0]. It
+  // should not exceed MAXPATHLEN defined for CPython.
+  if (!argv[0] || strlen(argv[0]) > MAXPATHLEN) {
+    fprintf(stderr, "The executable path %s is NULL or of invalid length.\n", argv[0]);
+    return 1;
+  }
+
+  // For debugging/logging purpose, set stdin/stdout/stderr unbuffered through
+  // environment variable.
+  // TODO(nanzhang): Set Py_VerboseFlag if more debugging requests needed.
+  const char *unbuffered_env = getenv("PYTHONUNBUFFERED");
+  if (unbuffered_env && unbuffered_env[0]) {
+    #if defined(MS_WINDOWS) || defined(__CYGWIN__)
+      _setmode(fileno(stdin), O_BINARY);
+      _setmode(fileno(stdout), O_BINARY);
+    #endif
+    #ifdef HAVE_SETVBUF
+      setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
+      setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
+      setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
+    #else /* !HAVE_SETVBUF */
+      setbuf(stdin,  (char *)NULL);
+      setbuf(stdout, (char *)NULL);
+      setbuf(stderr, (char *)NULL);
+    #endif /* !HAVE_SETVBUF */
+  }
+  //For debugging/logging purpose, Warning control.
+  //Python’s warning machinery by default prints warning messages to sys.stderr.
+  //The full form of argument is:action:message:category:module:line
+  char *warnings_env = getenv("PYTHONWARNINGS");
+  if (warnings_env && warnings_env[0]) {
+      char *warnings_buf, *warning;
+
+      // Note: "new" operation; we need free this chuck of data after use.
+      warnings_buf = new char[strlen(warnings_env) + 1];
+      if (warnings_buf == NULL)
+          Py_FatalError(
+             "not enough memory to copy PYTHONWARNINGS");
+      strcpy(warnings_buf, warnings_env);
+      for (warning = strtok(warnings_buf, ",");
+           warning != NULL;
+           warning = strtok(NULL, ","))
+          PySys_AddWarnOption(warning);
+      delete[] warnings_buf;
+  }
+
+  // Always enable Python "-s" option. We don't need user-site directories,
+  // everything's supposed to be hermetic.
+  Py_NoUserSiteDirectory = 1;
+
+  Py_SetProgramName(argv[0]);
+  Py_Initialize();
+  PySys_SetArgvEx(argc, argv, 0);
+
+  // Set sys.executable to None. The real executable is available as
+  // sys.argv[0], and too many things assume sys.executable is a regular Python
+  // binary, which isn't available. By setting it to None we get clear errors
+  // when people try to use it.
+  if (PySys_SetObject(const_cast<char *>("executable"), Py_None) < 0) {
+    PyErr_Print();
+    result = 1;
+    goto error;
+  }
+
+  result = android::cpython2::python_launcher::RunEntryPointOrMainModule(argv[0]);
+  if (result < 0) {
+    PyErr_Print();
+    goto error;
+  }
+
+error:
+  Py_Finalize();
+
+  free(argv[0]);
+  exit(abs(result));
+}