/* * This wrapper program executes a python executable hidden inside an * application bundle inside the Python framework. This is needed to run * GUI code: some GUI API's don't work unless the program is inside an * application bundle. * * This program uses posix_spawn rather than plain execv because we need * slightly more control over how the "real" interpreter is executed. */ #include #include #include #include #include #include extern char** environ; /* * FIXME: dynamicly determine PYTHONWEXECUTABLE path by linking to * Python.framework and looking for Py_Initialize. This would make * it a lot easier to have pythonw functinality in virtualenv */ static char Python[] = "/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python"; /*PYTHONWEXECUTABLE;*/ int main(int argc, char **argv) { posix_spawnattr_t spawnattr = NULL; size_t ocount; size_t count; cpu_type_t cpu_types[1]; short flags = 0; if ((errno = posix_spawnattr_init(&spawnattr)) != 0) { err(2, "posix_spawnattr_int"); /* NOTREACHTED */ } count = 1; /* Run the real python executable using the same architure as this executable, * this allows users to controle the architecture using "arch -ppc python" */ #if defined(__ppc64__) cpu_types[0] = CPU_TYPE_POWERPC64; #elif defined(__x86_64__) cpu_types[0] = CPU_TYPE_X86_64; #elif defined(__ppc__) cpu_types[0] = CPU_TYPE_POWERPC; #elif defined(__i386__) cpu_types[0] = CPU_TYPE_X86; #else # error "Unknown CPU" #endif #ifdef __LP64__ /* We're running in 64-bit mode. * * There are some APIs, both in the system and in 3th-party python * extensions, that don't work in 64-bit mode. Therefore allow the * user to select 32-bit mode using a -X flag as well. */ { int c; /* FIXME: the string of options needs to be synchronized with Py_Main, * and preferably without copying the getopt string as I've done below. */ while ((c = getopt(argc, argv, "3bBc:dEhiJm:OQ:sStuUvVW:xX:?")) != EOF) { switch (c) { case 'X': if (strcmp(optarg, "32bit") == 0) { printf("force 32bit mode\n"); #ifdef __ppc64__ cpu_types[0] = CPU_TYPE_POWERPC; #else /* !__ppc64__ */ cpu_types[0] = CPU_TYPE_X86; #endif /* !__ppc64__ */ } break; } } } #endif /* __LP64__ */ if (posix_spawnattr_setbinpref_np(&spawnattr, count, cpu_types, &ocount) == -1) { err(1, "posix_spawnattr_setbinpref"); /* NOTREACHTED */ } if (count != ocount) { fprintf(stderr, "posix_spawnattr_setbinpref failed to copy %ld != %ld\n", (long)count, (long)ocount); return 1; /* NOTREACHTED */ } /* * Set flag that causes posix_spawn to behave like execv */ flags |= POSIX_SPAWN_SETEXEC; if ((errno = posix_spawnattr_setflags(&spawnattr, flags)) != 0) { err(1, "posix_spawnattr_setflags"); /* NOTREACHTED */ } argv[0] = Python; posix_spawn(NULL, argv[0], NULL, &spawnattr, argv, environ); err(1, "posix_spawn: %s", Python); /* NOTREACHED */ }