diff --git a/Lib/test/test_osx_env.py b/Lib/test/test_osx_env.py new file mode 100644 index 00000000000..5b3f3e19fd1 --- /dev/null +++ b/Lib/test/test_osx_env.py @@ -0,0 +1,34 @@ +""" +Test suite for OS X interpreter environment variables. +""" + +from test.support import EnvironmentVarGuard, run_unittest +import subprocess +import sys +import unittest + +class OSXEnvironmentVariableTestCase(unittest.TestCase): + def _check_sys(self, ev, cond, sv, val = '/some/path/to/python'): + with EnvironmentVarGuard() as evg: + subpc = [str(sys.executable), '-c', + 'import sys; sys.exit(2 if "%s" %s %s else 3)' % (val, cond, sv)] + # ensure environment variable does not exist + evg.unset(ev) + # test that test on sys.xxx normally fails + rc = subprocess.call(subpc) + self.assertEqual(rc, 3, "expected %s not %s %s" % (ev, cond, sv)) + # set environ variable + evg.set(ev, val) + # test that sys.xxx has been influenced by the environ value + rc = subprocess.call(subpc) + self.assertEqual(rc, 2, "expected %s %s %s" % (ev, cond, sv)) + + def test_pythonexecutable_sets_sys_executable(self): + self._check_sys('PYTHONEXECUTABLE', '==', 'sys.executable') + +def test_main(): + if sys.platform == 'darwin': + run_unittest(OSXEnvironmentVariableTestCase) + +if __name__ == "__main__": + test_main() diff --git a/Modules/getpath.c b/Modules/getpath.c index 064877c0fcc..b7f178eb7ab 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -457,6 +457,7 @@ calculate_path(void) #else unsigned long nsexeclength = MAXPATHLEN; #endif + char execpath[MAXPATHLEN+1]; #endif if (_path) { @@ -486,8 +487,13 @@ calculate_path(void) * will fail if a relative path was used. but in that case, * absolutize() should help us out below */ - else if(0 == _NSGetExecutablePath(progpath, &nsexeclength) && progpath[0] == SEP) - ; + else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && execpath[0] == SEP) { + size_t r = mbstowcs(progpath, execpath, MAXPATHLEN+1); + if (r == (size_t)-1 || r > MAXPATHLEN) { + /* Could not convert execpath, or it's too long. */ + progpath[0] = '\0'; + } + } #endif /* __APPLE__ */ else if (path) { while (1) { diff --git a/Modules/main.c b/Modules/main.c index 6de152315f9..8352e667222 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -487,10 +487,23 @@ Py_Main(int argc, wchar_t **argv) so the actual executable path is passed in an environment variable. See Lib/plat-mac/bundlebuiler.py for details about the bootstrap script. */ - if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') - Py_SetProgramName(p); - else + if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') { + wchar_t* buffer; + size_t len = strlen(p); + size_t r; + + buffer = malloc(len * sizeof(wchar_t)); + if (buffer == NULL) { + Py_FatalError( + "not enough memory to copy PYTHONEXECUTABLE"); + } + + r = mbstowcs(buffer, p, len); + Py_SetProgramName(buffer); + /* buffer is now handed off - do not free */ + } else { Py_SetProgramName(argv[0]); + } #else Py_SetProgramName(argv[0]); #endif