2 * This wrapper program executes a python executable hidden inside an
3 * application bundle inside the Python framework. This is needed to run
4 * GUI code: some GUI API's don't work unless the program is inside an
7 * This program uses posix_spawn rather than plain execv because we need
8 * slightly more control over how the "real" interpreter is executed.
21 extern char** environ
;
24 * Locate the python framework by looking for the
25 * library that contains Py_Initialize.
27 * In a regular framework the structure is:
29 * Python.framework/Versions/2.7
31 * /Resources/Python.app/Contents/MacOS/Python
33 * In a virtualenv style structure the expected
38 * /.Python <- the dylib
39 * /.Resources/Python.app/Contents/MacOS/Python
41 * NOTE: virtualenv's are not an officially supported
42 * feature, support for that structure is provided as
45 static char* get_python_path(void)
52 if (dladdr(Py_Initialize
, &info
) == 0) {
56 len
= strlen(info
.dli_fname
);
58 g_path
= malloc(len
+60);
63 strcpy(g_path
, info
.dli_fname
);
64 end
= g_path
+ len
- 1;
65 while (end
!= g_path
&& *end
!= '/') {
72 strcpy(end
, "Resources/Python.app/Contents/MacOS/Python");
78 setup_spawnattr(posix_spawnattr_t
* spawnattr
)
82 cpu_type_t cpu_types
[1];
88 if ((errno
= posix_spawnattr_init(spawnattr
)) != 0) {
89 err(2, "posix_spawnattr_int");
95 /* Run the real python executable using the same architure as this
96 * executable, this allows users to controle the architecture using
100 #if defined(__ppc64__)
101 cpu_types
[0] = CPU_TYPE_POWERPC64
;
103 #elif defined(__x86_64__)
104 cpu_types
[0] = CPU_TYPE_X86_64
;
106 #elif defined(__ppc__)
107 cpu_types
[0] = CPU_TYPE_POWERPC
;
108 #elif defined(__i386__)
109 cpu_types
[0] = CPU_TYPE_X86
;
111 # error "Unknown CPU"
114 if (posix_spawnattr_setbinpref_np(spawnattr
, count
,
115 cpu_types
, &ocount
) == -1) {
116 err(1, "posix_spawnattr_setbinpref");
119 if (count
!= ocount
) {
120 fprintf(stderr
, "posix_spawnattr_setbinpref failed to copy\n");
127 * Set flag that causes posix_spawn to behave like execv
129 flags
|= POSIX_SPAWN_SETEXEC
;
130 if ((errno
= posix_spawnattr_setflags(spawnattr
, flags
)) != 0) {
131 err(1, "posix_spawnattr_setflags");
137 main(int argc
, char **argv
) {
138 posix_spawnattr_t spawnattr
= NULL
;
139 char* exec_path
= get_python_path();
142 setup_spawnattr(&spawnattr
);
143 posix_spawn(NULL
, exec_path
, NULL
,
144 &spawnattr
, argv
, environ
);
145 err(1, "posix_spawn: %s", argv
[0]);