ยปCore Development>Code coverage>Mac/Tools/pythonw.c

Python code coverage for Mac/Tools/pythonw.c

#countcontent
1n/a/*
2n/a * This wrapper program executes a python executable hidden inside an
3n/a * application bundle inside the Python framework. This is needed to run
4n/a * GUI code: some GUI API's don't work unless the program is inside an
5n/a * application bundle.
6n/a *
7n/a * This program uses posix_spawn rather than plain execv because we need
8n/a * slightly more control over how the "real" interpreter is executed.
9n/a *
10n/a * On OSX 10.4 (and earlier) this falls back to using exec because the
11n/a * posix_spawnv functions aren't available there.
12n/a */
13n/a#pragma weak_import posix_spawnattr_init
14n/a#pragma weak_import posix_spawnattr_setbinpref_np
15n/a#pragma weak_import posix_spawnattr_setflags
16n/a#pragma weak_import posix_spawn
17n/a
18n/a#include <Python.h>
19n/a#include <unistd.h>
20n/a#ifdef HAVE_SPAWN_H
21n/a#include <spawn.h>
22n/a#endif
23n/a#include <stdio.h>
24n/a#include <string.h>
25n/a#include <errno.h>
26n/a#include <err.h>
27n/a#include <dlfcn.h>
28n/a#include <stdlib.h>
29n/a
30n/a
31n/aextern char** environ;
32n/a
33n/a/*
34n/a * Locate the python framework by looking for the
35n/a * library that contains Py_Initialize.
36n/a *
37n/a * In a regular framework the structure is:
38n/a *
39n/a * Python.framework/Versions/2.7
40n/a * /Python
41n/a * /Resources/Python.app/Contents/MacOS/Python
42n/a *
43n/a * In a virtualenv style structure the expected
44n/a * structure is:
45n/a *
46n/a * ROOT
47n/a * /bin/pythonw
48n/a * /.Python <- the dylib
49n/a * /.Resources/Python.app/Contents/MacOS/Python
50n/a *
51n/a * NOTE: virtualenv's are not an officially supported
52n/a * feature, support for that structure is provided as
53n/a * a convenience.
54n/a */
55n/astatic char* get_python_path(void)
56n/a{
57n/a size_t len;
58n/a Dl_info info;
59n/a char* end;
60n/a char* g_path;
61n/a
62n/a if (dladdr(Py_Initialize, &info) == 0) {
63n/a return NULL;
64n/a }
65n/a
66n/a len = strlen(info.dli_fname);
67n/a
68n/a g_path = malloc(len+60);
69n/a if (g_path == NULL) {
70n/a return NULL;
71n/a }
72n/a
73n/a strcpy(g_path, info.dli_fname);
74n/a end = g_path + len - 1;
75n/a while (end != g_path && *end != '/') {
76n/a end --;
77n/a }
78n/a end++;
79n/a if (end[1] == '.') {
80n/a end++;
81n/a }
82n/a strcpy(end, "Resources/Python.app/Contents/MacOS/" PYTHONFRAMEWORK);
83n/a
84n/a return g_path;
85n/a}
86n/a
87n/a#ifdef HAVE_SPAWN_H
88n/astatic void
89n/asetup_spawnattr(posix_spawnattr_t* spawnattr)
90n/a{
91n/a size_t ocount;
92n/a size_t count;
93n/a cpu_type_t cpu_types[1];
94n/a short flags = 0;
95n/a#ifdef __LP64__
96n/a int ch;
97n/a#endif
98n/a
99n/a if ((errno = posix_spawnattr_init(spawnattr)) != 0) {
100n/a err(2, "posix_spawnattr_int");
101n/a /* NOTREACHTED */
102n/a }
103n/a
104n/a count = 1;
105n/a
106n/a /* Run the real python executable using the same architure as this
107n/a * executable, this allows users to controle the architecture using
108n/a * "arch -ppc python"
109n/a */
110n/a
111n/a#if defined(__ppc64__)
112n/a cpu_types[0] = CPU_TYPE_POWERPC64;
113n/a
114n/a#elif defined(__x86_64__)
115n/a cpu_types[0] = CPU_TYPE_X86_64;
116n/a
117n/a#elif defined(__ppc__)
118n/a cpu_types[0] = CPU_TYPE_POWERPC;
119n/a#elif defined(__i386__)
120n/a cpu_types[0] = CPU_TYPE_X86;
121n/a#else
122n/a# error "Unknown CPU"
123n/a#endif
124n/a
125n/a if (posix_spawnattr_setbinpref_np(spawnattr, count,
126n/a cpu_types, &ocount) == -1) {
127n/a err(1, "posix_spawnattr_setbinpref");
128n/a /* NOTREACHTED */
129n/a }
130n/a if (count != ocount) {
131n/a fprintf(stderr, "posix_spawnattr_setbinpref failed to copy\n");
132n/a exit(1);
133n/a /* NOTREACHTED */
134n/a }
135n/a
136n/a
137n/a /*
138n/a * Set flag that causes posix_spawn to behave like execv
139n/a */
140n/a flags |= POSIX_SPAWN_SETEXEC;
141n/a if ((errno = posix_spawnattr_setflags(spawnattr, flags)) != 0) {
142n/a err(1, "posix_spawnattr_setflags");
143n/a /* NOTREACHTED */
144n/a }
145n/a}
146n/a#endif
147n/a
148n/aint
149n/amain(int argc, char **argv) {
150n/a char* exec_path = get_python_path();
151n/a
152n/a#ifdef HAVE_SPAWN_H
153n/a
154n/a /* We're weak-linking to posix-spawnv to ensure that
155n/a * an executable build on 10.5 can work on 10.4.
156n/a */
157n/a if (posix_spawn != NULL) {
158n/a posix_spawnattr_t spawnattr = NULL;
159n/a
160n/a
161n/a setup_spawnattr(&spawnattr);
162n/a posix_spawn(NULL, exec_path, NULL,
163n/a &spawnattr, argv, environ);
164n/a err(1, "posix_spawn: %s", argv[0]);
165n/a }
166n/a#endif
167n/a execve(exec_path, argv, environ);
168n/a err(1, "execve: %s", argv[0]);
169n/a /* NOTREACHED */
170n/a}