1 /* Return the initial module search path. */
2
3 #include "Python.h"
4 #include "internal/pystate.h"
5 #include "osdefs.h"
6
7 #include <sys/types.h>
8 #include <string.h>
9
10 #ifdef __APPLE__
11 # include <mach-o/dyld.h>
12 #endif
13
14 /* Search in some common locations for the associated Python libraries.
15 *
16 * Two directories must be found, the platform independent directory
17 * (prefix), containing the common .py and .pyc files, and the platform
18 * dependent directory (exec_prefix), containing the shared library
19 * modules. Note that prefix and exec_prefix can be the same directory,
20 * but for some installations, they are different.
21 *
22 * Py_GetPath() carries out separate searches for prefix and exec_prefix.
23 * Each search tries a number of different locations until a ``landmark''
24 * file or directory is found. If no prefix or exec_prefix is found, a
25 * warning message is issued and the preprocessor defined PREFIX and
26 * EXEC_PREFIX are used (even though they will not work); python carries on
27 * as best as is possible, but most imports will fail.
28 *
29 * Before any searches are done, the location of the executable is
30 * determined. If argv[0] has one or more slashes in it, it is used
31 * unchanged. Otherwise, it must have been invoked from the shell's path,
32 * so we search $PATH for the named executable and use that. If the
33 * executable was not found on $PATH (or there was no $PATH environment
34 * variable), the original argv[0] string is used.
35 *
36 * Next, the executable location is examined to see if it is a symbolic
37 * link. If so, the link is chased (correctly interpreting a relative
38 * pathname if one is found) and the directory of the link target is used.
39 *
40 * Finally, argv0_path is set to the directory containing the executable
41 * (i.e. the last component is stripped).
42 *
43 * With argv0_path in hand, we perform a number of steps. The same steps
44 * are performed for prefix and for exec_prefix, but with a different
45 * landmark.
46 *
47 * Step 1. Are we running python out of the build directory? This is
48 * checked by looking for a different kind of landmark relative to
49 * argv0_path. For prefix, the landmark's path is derived from the VPATH
50 * preprocessor variable (taking into account that its value is almost, but
51 * not quite, what we need). For exec_prefix, the landmark is
52 * pybuilddir.txt. If the landmark is found, we're done.
53 *
54 * For the remaining steps, the prefix landmark will always be
55 * lib/python$VERSION/os.py and the exec_prefix will always be
56 * lib/python$VERSION/lib-dynload, where $VERSION is Python's version
57 * number as supplied by the Makefile. Note that this means that no more
58 * build directory checking is performed; if the first step did not find
59 * the landmarks, the assumption is that python is running from an
60 * installed setup.
61 *
62 * Step 2. See if the $PYTHONHOME environment variable points to the
63 * installed location of the Python libraries. If $PYTHONHOME is set, then
64 * it points to prefix and exec_prefix. $PYTHONHOME can be a single
65 * directory, which is used for both, or the prefix and exec_prefix
66 * directories separated by a colon.
67 *
68 * Step 3. Try to find prefix and exec_prefix relative to argv0_path,
69 * backtracking up the path until it is exhausted. This is the most common
70 * step to succeed. Note that if prefix and exec_prefix are different,
71 * exec_prefix is more likely to be found; however if exec_prefix is a
72 * subdirectory of prefix, both will be found.
73 *
74 * Step 4. Search the directories pointed to by the preprocessor variables
75 * PREFIX and EXEC_PREFIX. These are supplied by the Makefile but can be
76 * passed in as options to the configure script.
77 *
78 * That's it!
79 *
80 * Well, almost. Once we have determined prefix and exec_prefix, the
81 * preprocessor variable PYTHONPATH is used to construct a path. Each
82 * relative path on PYTHONPATH is prefixed with prefix. Then the directory
83 * containing the shared library modules is appended. The environment
84 * variable $PYTHONPATH is inserted in front of it all. Finally, the
85 * prefix and exec_prefix globals are tweaked so they reflect the values
86 * expected by other code, by stripping the "lib/python$VERSION/..." stuff
87 * off. If either points to the build directory, the globals are reset to
88 * the corresponding preprocessor variables (so sys.prefix will reflect the
89 * installation location, even though sys.path points into the build
90 * directory). This seems to make more sense given that currently the only
91 * known use of sys.prefix and sys.exec_prefix is for the ILU installation
92 * process to find the installed Python tree.
93 *
94 * An embedding application can use Py_SetPath() to override all of
95 * these authomatic path computations.
96 *
97 * NOTE: Windows MSVC builds use PC/getpathp.c instead!
98 */
99
100 #ifdef __cplusplus
101 extern "C" {
102 #endif
103
104
105 #if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH)
106 #error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined"
107 #endif
108
109 #ifndef LANDMARK
110 #define LANDMARK L"os.py"
111 #endif
112
113 #define DECODE_LOCALE_ERR(NAME, LEN) \
114 ((LEN) == (size_t)-2) \
115 ? _Py_INIT_USER_ERR("cannot decode " NAME) \
116 : _Py_INIT_NO_MEMORY()
117
118 typedef struct {
119 wchar_t *path_env; /* PATH environment variable */
120
121 wchar_t *pythonpath; /* PYTHONPATH define */
122 wchar_t *prefix; /* PREFIX define */
123 wchar_t *exec_prefix; /* EXEC_PREFIX define */
124
125 wchar_t *lib_python; /* "lib/pythonX.Y" */
126 wchar_t argv0_path[MAXPATHLEN+1];
127 wchar_t zip_path[MAXPATHLEN+1]; /* ".../lib/pythonXY.zip" */
128
129 int prefix_found; /* found platform independent libraries? */
130 int exec_prefix_found; /* found the platform dependent libraries? */
131 } PyCalculatePath;
132
133 static const wchar_t delimiter[2] = {DELIM, '\0'};
134 static const wchar_t separator[2] = {SEP, '\0'};
135
136
137 /* Get file status. Encode the path to the locale encoding. */
138 static int
_Py_wstat(const wchar_t * path,struct stat * buf)139 _Py_wstat(const wchar_t* path, struct stat *buf)
140 {
141 int err;
142 char *fname;
143 fname = _Py_EncodeLocaleRaw(path, NULL);
144 if (fname == NULL) {
145 errno = EINVAL;
146 return -1;
147 }
148 err = stat(fname, buf);
149 PyMem_RawFree(fname);
150 return err;
151 }
152
153
154 static void
reduce(wchar_t * dir)155 reduce(wchar_t *dir)
156 {
157 size_t i = wcslen(dir);
158 while (i > 0 && dir[i] != SEP)
159 --i;
160 dir[i] = '\0';
161 }
162
163
164 static int
isfile(wchar_t * filename)165 isfile(wchar_t *filename) /* Is file, not directory */
166 {
167 struct stat buf;
168 if (_Py_wstat(filename, &buf) != 0) {
169 return 0;
170 }
171 if (!S_ISREG(buf.st_mode)) {
172 return 0;
173 }
174 return 1;
175 }
176
177
178 static int
ismodule(wchar_t * filename)179 ismodule(wchar_t *filename) /* Is module -- check for .pyc too */
180 {
181 if (isfile(filename)) {
182 return 1;
183 }
184
185 /* Check for the compiled version of prefix. */
186 if (wcslen(filename) < MAXPATHLEN) {
187 wcscat(filename, L"c");
188 if (isfile(filename)) {
189 return 1;
190 }
191 }
192 return 0;
193 }
194
195
196 /* Is executable file */
197 static int
isxfile(wchar_t * filename)198 isxfile(wchar_t *filename)
199 {
200 struct stat buf;
201 if (_Py_wstat(filename, &buf) != 0) {
202 return 0;
203 }
204 if (!S_ISREG(buf.st_mode)) {
205 return 0;
206 }
207 if ((buf.st_mode & 0111) == 0) {
208 return 0;
209 }
210 return 1;
211 }
212
213
214 /* Is directory */
215 static int
isdir(wchar_t * filename)216 isdir(wchar_t *filename)
217 {
218 struct stat buf;
219 if (_Py_wstat(filename, &buf) != 0) {
220 return 0;
221 }
222 if (!S_ISDIR(buf.st_mode)) {
223 return 0;
224 }
225 return 1;
226 }
227
228
229 /* Add a path component, by appending stuff to buffer.
230 buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
231 NUL-terminated string with no more than MAXPATHLEN characters (not counting
232 the trailing NUL). It's a fatal error if it contains a string longer than
233 that (callers must be careful!). If these requirements are met, it's
234 guaranteed that buffer will still be a NUL-terminated string with no more
235 than MAXPATHLEN characters at exit. If stuff is too long, only as much of
236 stuff as fits will be appended.
237 */
238 static void
joinpath(wchar_t * buffer,wchar_t * stuff)239 joinpath(wchar_t *buffer, wchar_t *stuff)
240 {
241 size_t n, k;
242 if (stuff[0] == SEP) {
243 n = 0;
244 }
245 else {
246 n = wcslen(buffer);
247 if (n > 0 && buffer[n-1] != SEP && n < MAXPATHLEN) {
248 buffer[n++] = SEP;
249 }
250 }
251 if (n > MAXPATHLEN) {
252 Py_FatalError("buffer overflow in getpath.c's joinpath()");
253 }
254 k = wcslen(stuff);
255 if (n + k > MAXPATHLEN) {
256 k = MAXPATHLEN - n;
257 }
258 wcsncpy(buffer+n, stuff, k);
259 buffer[n+k] = '\0';
260 }
261
262
263 /* copy_absolute requires that path be allocated at least
264 MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes. */
265 static void
copy_absolute(wchar_t * path,wchar_t * p,size_t pathlen)266 copy_absolute(wchar_t *path, wchar_t *p, size_t pathlen)
267 {
268 if (p[0] == SEP) {
269 wcscpy(path, p);
270 }
271 else {
272 if (!_Py_wgetcwd(path, pathlen)) {
273 /* unable to get the current directory */
274 wcscpy(path, p);
275 return;
276 }
277 if (p[0] == '.' && p[1] == SEP) {
278 p += 2;
279 }
280 joinpath(path, p);
281 }
282 }
283
284
285 /* absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes. */
286 static void
absolutize(wchar_t * path)287 absolutize(wchar_t *path)
288 {
289 wchar_t buffer[MAXPATHLEN+1];
290
291 if (path[0] == SEP) {
292 return;
293 }
294 copy_absolute(buffer, path, MAXPATHLEN+1);
295 wcscpy(path, buffer);
296 }
297
298
299 #if defined(__CYGWIN__) || defined(__MINGW32__)
300 /* add_exe_suffix requires that progpath be allocated at least
301 MAXPATHLEN + 1 bytes.
302 */
303
304 #ifndef EXE_SUFFIX
305 #define EXE_SUFFIX L".exe"
306 #endif
307
308 static void
add_exe_suffix(wchar_t * progpath)309 add_exe_suffix(wchar_t *progpath)
310 {
311 /* Check for already have an executable suffix */
312 size_t n = wcslen(progpath);
313 size_t s = wcslen(EXE_SUFFIX);
314 if (wcsncasecmp(EXE_SUFFIX, progpath+n-s, s) != 0) {
315 if (n + s > MAXPATHLEN) {
316 Py_FatalError("progpath overflow in getpath.c's add_exe_suffix()");
317 }
318 /* Save original path for revert */
319 wchar_t orig[MAXPATHLEN+1];
320 wcsncpy(orig, progpath, MAXPATHLEN);
321
322 wcsncpy(progpath+n, EXE_SUFFIX, s);
323 progpath[n+s] = '\0';
324
325 if (!isxfile(progpath)) {
326 /* Path that added suffix is invalid */
327 wcsncpy(progpath, orig, MAXPATHLEN);
328 }
329 }
330 }
331 #endif
332
333
334 /* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
335 bytes long.
336 */
337 static int
search_for_prefix(const _PyCoreConfig * core_config,PyCalculatePath * calculate,wchar_t * prefix)338 search_for_prefix(const _PyCoreConfig *core_config,
339 PyCalculatePath *calculate, wchar_t *prefix)
340 {
341 size_t n;
342 wchar_t *vpath;
343
344 /* If PYTHONHOME is set, we believe it unconditionally */
345 if (core_config->home) {
346 wcsncpy(prefix, core_config->home, MAXPATHLEN);
347 prefix[MAXPATHLEN] = L'\0';
348 wchar_t *delim = wcschr(prefix, DELIM);
349 if (delim) {
350 *delim = L'\0';
351 }
352 joinpath(prefix, calculate->lib_python);
353 joinpath(prefix, LANDMARK);
354 return 1;
355 }
356
357 /* Check to see if argv[0] is in the build directory */
358 wcsncpy(prefix, calculate->argv0_path, MAXPATHLEN);
359 prefix[MAXPATHLEN] = L'\0';
360 joinpath(prefix, L"Modules/Setup");
361 if (isfile(prefix)) {
362 /* Check VPATH to see if argv0_path is in the build directory. */
363 vpath = Py_DecodeLocale(VPATH, NULL);
364 if (vpath != NULL) {
365 wcsncpy(prefix, calculate->argv0_path, MAXPATHLEN);
366 prefix[MAXPATHLEN] = L'\0';
367 joinpath(prefix, vpath);
368 PyMem_RawFree(vpath);
369 joinpath(prefix, L"Lib");
370 joinpath(prefix, LANDMARK);
371 if (ismodule(prefix)) {
372 return -1;
373 }
374 }
375 }
376
377 /* Search from argv0_path, until root is found */
378 copy_absolute(prefix, calculate->argv0_path, MAXPATHLEN+1);
379 do {
380 n = wcslen(prefix);
381 joinpath(prefix, calculate->lib_python);
382 joinpath(prefix, LANDMARK);
383 if (ismodule(prefix)) {
384 return 1;
385 }
386 prefix[n] = L'\0';
387 reduce(prefix);
388 } while (prefix[0]);
389
390 /* Look at configure's PREFIX */
391 wcsncpy(prefix, calculate->prefix, MAXPATHLEN);
392 prefix[MAXPATHLEN] = L'\0';
393 joinpath(prefix, calculate->lib_python);
394 joinpath(prefix, LANDMARK);
395 if (ismodule(prefix)) {
396 return 1;
397 }
398
399 /* Fail */
400 return 0;
401 }
402
403
404 static void
calculate_prefix(const _PyCoreConfig * core_config,PyCalculatePath * calculate,wchar_t * prefix)405 calculate_prefix(const _PyCoreConfig *core_config,
406 PyCalculatePath *calculate, wchar_t *prefix)
407 {
408 calculate->prefix_found = search_for_prefix(core_config, calculate, prefix);
409 if (!calculate->prefix_found) {
410 if (!Py_FrozenFlag) {
411 fprintf(stderr,
412 "Could not find platform independent libraries <prefix>\n");
413 }
414 wcsncpy(prefix, calculate->prefix, MAXPATHLEN);
415 joinpath(prefix, calculate->lib_python);
416 }
417 else {
418 reduce(prefix);
419 }
420 }
421
422
423 static void
calculate_reduce_prefix(PyCalculatePath * calculate,wchar_t * prefix)424 calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix)
425 {
426 /* Reduce prefix and exec_prefix to their essence,
427 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
428 * If we're loading relative to the build directory,
429 * return the compiled-in defaults instead.
430 */
431 if (calculate->prefix_found > 0) {
432 reduce(prefix);
433 reduce(prefix);
434 /* The prefix is the root directory, but reduce() chopped
435 * off the "/". */
436 if (!prefix[0]) {
437 wcscpy(prefix, separator);
438 }
439 }
440 else {
441 wcsncpy(prefix, calculate->prefix, MAXPATHLEN);
442 }
443 }
444
445
446 /* search_for_exec_prefix requires that argv0_path be no more than
447 MAXPATHLEN bytes long.
448 */
449 static int
search_for_exec_prefix(const _PyCoreConfig * core_config,PyCalculatePath * calculate,wchar_t * exec_prefix)450 search_for_exec_prefix(const _PyCoreConfig *core_config,
451 PyCalculatePath *calculate, wchar_t *exec_prefix)
452 {
453 size_t n;
454
455 /* If PYTHONHOME is set, we believe it unconditionally */
456 if (core_config->home) {
457 wchar_t *delim = wcschr(core_config->home, DELIM);
458 if (delim) {
459 wcsncpy(exec_prefix, delim+1, MAXPATHLEN);
460 }
461 else {
462 wcsncpy(exec_prefix, core_config->home, MAXPATHLEN);
463 }
464 exec_prefix[MAXPATHLEN] = L'\0';
465 joinpath(exec_prefix, calculate->lib_python);
466 joinpath(exec_prefix, L"lib-dynload");
467 return 1;
468 }
469
470 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
471 is written by setup.py and contains the relative path to the location
472 of shared library modules. */
473 wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN);
474 exec_prefix[MAXPATHLEN] = L'\0';
475 joinpath(exec_prefix, L"pybuilddir.txt");
476 if (isfile(exec_prefix)) {
477 FILE *f = _Py_wfopen(exec_prefix, L"rb");
478 if (f == NULL) {
479 errno = 0;
480 }
481 else {
482 char buf[MAXPATHLEN+1];
483 wchar_t *rel_builddir_path;
484 n = fread(buf, 1, MAXPATHLEN, f);
485 buf[n] = '\0';
486 fclose(f);
487 rel_builddir_path = _Py_DecodeUTF8_surrogateescape(buf, n);
488 if (rel_builddir_path) {
489 wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN);
490 exec_prefix[MAXPATHLEN] = L'\0';
491 joinpath(exec_prefix, rel_builddir_path);
492 PyMem_RawFree(rel_builddir_path );
493 return -1;
494 }
495 }
496 }
497
498 /* Search from argv0_path, until root is found */
499 copy_absolute(exec_prefix, calculate->argv0_path, MAXPATHLEN+1);
500 do {
501 n = wcslen(exec_prefix);
502 joinpath(exec_prefix, calculate->lib_python);
503 joinpath(exec_prefix, L"lib-dynload");
504 if (isdir(exec_prefix)) {
505 return 1;
506 }
507 exec_prefix[n] = L'\0';
508 reduce(exec_prefix);
509 } while (exec_prefix[0]);
510
511 /* Look at configure's EXEC_PREFIX */
512 wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN);
513 exec_prefix[MAXPATHLEN] = L'\0';
514 joinpath(exec_prefix, calculate->lib_python);
515 joinpath(exec_prefix, L"lib-dynload");
516 if (isdir(exec_prefix)) {
517 return 1;
518 }
519
520 /* Fail */
521 return 0;
522 }
523
524
525 static void
calculate_exec_prefix(const _PyCoreConfig * core_config,PyCalculatePath * calculate,wchar_t * exec_prefix)526 calculate_exec_prefix(const _PyCoreConfig *core_config,
527 PyCalculatePath *calculate, wchar_t *exec_prefix)
528 {
529 calculate->exec_prefix_found = search_for_exec_prefix(core_config,
530 calculate,
531 exec_prefix);
532 if (!calculate->exec_prefix_found) {
533 if (!Py_FrozenFlag) {
534 fprintf(stderr,
535 "Could not find platform dependent libraries <exec_prefix>\n");
536 }
537 wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN);
538 joinpath(exec_prefix, L"lib/lib-dynload");
539 }
540 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
541 }
542
543
544 static void
calculate_reduce_exec_prefix(PyCalculatePath * calculate,wchar_t * exec_prefix)545 calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
546 {
547 if (calculate->exec_prefix_found > 0) {
548 reduce(exec_prefix);
549 reduce(exec_prefix);
550 reduce(exec_prefix);
551 if (!exec_prefix[0]) {
552 wcscpy(exec_prefix, separator);
553 }
554 }
555 else {
556 wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN);
557 }
558 }
559
560
561 static _PyInitError
calculate_program_full_path(const _PyCoreConfig * core_config,PyCalculatePath * calculate,_PyPathConfig * config)562 calculate_program_full_path(const _PyCoreConfig *core_config,
563 PyCalculatePath *calculate, _PyPathConfig *config)
564 {
565 wchar_t program_full_path[MAXPATHLEN+1];
566 memset(program_full_path, 0, sizeof(program_full_path));
567
568 #ifdef __APPLE__
569 uint32_t nsexeclength = MAXPATHLEN;
570 char execpath[MAXPATHLEN+1];
571 #endif
572
573 /* If there is no slash in the argv0 path, then we have to
574 * assume python is on the user's $PATH, since there's no
575 * other way to find a directory to start the search from. If
576 * $PATH isn't exported, you lose.
577 */
578 if (wcschr(core_config->program_name, SEP)) {
579 wcsncpy(program_full_path, core_config->program_name, MAXPATHLEN);
580 }
581 #ifdef __APPLE__
582 /* On Mac OS X, if a script uses an interpreter of the form
583 * "#!/opt/python2.3/bin/python", the kernel only passes "python"
584 * as argv[0], which falls through to the $PATH search below.
585 * If /opt/python2.3/bin isn't in your path, or is near the end,
586 * this algorithm may incorrectly find /usr/bin/python. To work
587 * around this, we can use _NSGetExecutablePath to get a better
588 * hint of what the intended interpreter was, although this
589 * will fail if a relative path was used. but in that case,
590 * absolutize() should help us out below
591 */
592 else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
593 execpath[0] == SEP)
594 {
595 size_t len;
596 wchar_t *path = Py_DecodeLocale(execpath, &len);
597 if (path == NULL) {
598 return DECODE_LOCALE_ERR("executable path", len);
599 }
600 wcsncpy(program_full_path, path, MAXPATHLEN);
601 PyMem_RawFree(path);
602 }
603 #endif /* __APPLE__ */
604 else if (calculate->path_env) {
605 wchar_t *path = calculate->path_env;
606 while (1) {
607 wchar_t *delim = wcschr(path, DELIM);
608
609 if (delim) {
610 size_t len = delim - path;
611 if (len > MAXPATHLEN) {
612 len = MAXPATHLEN;
613 }
614 wcsncpy(program_full_path, path, len);
615 program_full_path[len] = '\0';
616 }
617 else {
618 wcsncpy(program_full_path, path, MAXPATHLEN);
619 }
620
621 joinpath(program_full_path, core_config->program_name);
622 if (isxfile(program_full_path)) {
623 break;
624 }
625
626 if (!delim) {
627 program_full_path[0] = L'\0';
628 break;
629 }
630 path = delim + 1;
631 }
632 }
633 else {
634 program_full_path[0] = '\0';
635 }
636 if (program_full_path[0] != SEP && program_full_path[0] != '\0') {
637 absolutize(program_full_path);
638 }
639 #if defined(__CYGWIN__) || defined(__MINGW32__)
640 /* For these platforms it is necessary to ensure that the .exe suffix
641 * is appended to the filename, otherwise there is potential for
642 * sys.executable to return the name of a directory under the same
643 * path (bpo-28441).
644 */
645 if (program_full_path[0] != '\0') {
646 add_exe_suffix(program_full_path);
647 }
648 #endif
649
650 config->program_full_path = _PyMem_RawWcsdup(program_full_path);
651 if (config->program_full_path == NULL) {
652 return _Py_INIT_NO_MEMORY();
653 }
654 return _Py_INIT_OK();
655 }
656
657
658 static _PyInitError
calculate_argv0_path(PyCalculatePath * calculate,const wchar_t * program_full_path)659 calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path)
660 {
661 wcsncpy(calculate->argv0_path, program_full_path, MAXPATHLEN);
662 calculate->argv0_path[MAXPATHLEN] = '\0';
663
664 #ifdef WITH_NEXT_FRAMEWORK
665 NSModule pythonModule;
666
667 /* On Mac OS X we have a special case if we're running from a framework.
668 ** This is because the python home should be set relative to the library,
669 ** which is in the framework, not relative to the executable, which may
670 ** be outside of the framework. Except when we're in the build directory...
671 */
672 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
673 /* Use dylib functions to find out where the framework was loaded from */
674 const char* modPath = NSLibraryNameForModule(pythonModule);
675 if (modPath != NULL) {
676 /* We're in a framework. */
677 /* See if we might be in the build directory. The framework in the
678 ** build directory is incomplete, it only has the .dylib and a few
679 ** needed symlinks, it doesn't have the Lib directories and such.
680 ** If we're running with the framework from the build directory we must
681 ** be running the interpreter in the build directory, so we use the
682 ** build-directory-specific logic to find Lib and such.
683 */
684 size_t len;
685 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
686 if (wbuf == NULL) {
687 return DECODE_LOCALE_ERR("framework location", len);
688 }
689
690 wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN);
691 reduce(calculate->argv0_path);
692 joinpath(calculate->argv0_path, calculate->lib_python);
693 joinpath(calculate->argv0_path, LANDMARK);
694 if (!ismodule(calculate->argv0_path)) {
695 /* We are in the build directory so use the name of the
696 executable - we know that the absolute path is passed */
697 wcsncpy(calculate->argv0_path, program_full_path, MAXPATHLEN);
698 }
699 else {
700 /* Use the location of the library as the program_full_path */
701 wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN);
702 }
703 PyMem_RawFree(wbuf);
704 }
705 #endif
706
707 #if HAVE_READLINK
708 wchar_t tmpbuffer[MAXPATHLEN+1];
709 int linklen = _Py_wreadlink(program_full_path, tmpbuffer, MAXPATHLEN);
710 while (linklen != -1) {
711 if (tmpbuffer[0] == SEP) {
712 /* tmpbuffer should never be longer than MAXPATHLEN,
713 but extra check does not hurt */
714 wcsncpy(calculate->argv0_path, tmpbuffer, MAXPATHLEN);
715 }
716 else {
717 /* Interpret relative to program_full_path */
718 reduce(calculate->argv0_path);
719 joinpath(calculate->argv0_path, tmpbuffer);
720 }
721 linklen = _Py_wreadlink(calculate->argv0_path, tmpbuffer, MAXPATHLEN);
722 }
723 #endif /* HAVE_READLINK */
724
725 reduce(calculate->argv0_path);
726 /* At this point, argv0_path is guaranteed to be less than
727 MAXPATHLEN bytes long. */
728 return _Py_INIT_OK();
729 }
730
731
732 /* Search for an "pyvenv.cfg" environment configuration file, first in the
733 executable's directory and then in the parent directory.
734 If found, open it for use when searching for prefixes.
735 */
736 static void
calculate_read_pyenv(PyCalculatePath * calculate)737 calculate_read_pyenv(PyCalculatePath *calculate)
738 {
739 wchar_t tmpbuffer[MAXPATHLEN+1];
740 wchar_t *env_cfg = L"pyvenv.cfg";
741 FILE *env_file;
742
743 wcscpy(tmpbuffer, calculate->argv0_path);
744
745 joinpath(tmpbuffer, env_cfg);
746 env_file = _Py_wfopen(tmpbuffer, L"r");
747 if (env_file == NULL) {
748 errno = 0;
749
750 reduce(tmpbuffer);
751 reduce(tmpbuffer);
752 joinpath(tmpbuffer, env_cfg);
753
754 env_file = _Py_wfopen(tmpbuffer, L"r");
755 if (env_file == NULL) {
756 errno = 0;
757 }
758 }
759
760 if (env_file == NULL) {
761 return;
762 }
763
764 /* Look for a 'home' variable and set argv0_path to it, if found */
765 if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, MAXPATHLEN)) {
766 wcscpy(calculate->argv0_path, tmpbuffer);
767 }
768 fclose(env_file);
769 }
770
771
772 static void
calculate_zip_path(PyCalculatePath * calculate,const wchar_t * prefix)773 calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix)
774 {
775 wcsncpy(calculate->zip_path, prefix, MAXPATHLEN);
776 calculate->zip_path[MAXPATHLEN] = L'\0';
777
778 if (calculate->prefix_found > 0) {
779 /* Use the reduced prefix returned by Py_GetPrefix() */
780 reduce(calculate->zip_path);
781 reduce(calculate->zip_path);
782 }
783 else {
784 wcsncpy(calculate->zip_path, calculate->prefix, MAXPATHLEN);
785 }
786 joinpath(calculate->zip_path, L"lib/python00.zip");
787
788 /* Replace "00" with version */
789 size_t bufsz = wcslen(calculate->zip_path);
790 calculate->zip_path[bufsz - 6] = VERSION[0];
791 calculate->zip_path[bufsz - 5] = VERSION[2];
792 }
793
794
795 static _PyInitError
calculate_module_search_path(const _PyCoreConfig * core_config,PyCalculatePath * calculate,const wchar_t * prefix,const wchar_t * exec_prefix,_PyPathConfig * config)796 calculate_module_search_path(const _PyCoreConfig *core_config,
797 PyCalculatePath *calculate,
798 const wchar_t *prefix, const wchar_t *exec_prefix,
799 _PyPathConfig *config)
800 {
801 /* Calculate size of return buffer */
802 size_t bufsz = 0;
803 if (core_config->module_search_path_env != NULL) {
804 bufsz += wcslen(core_config->module_search_path_env) + 1;
805 }
806
807 wchar_t *defpath = calculate->pythonpath;
808 size_t prefixsz = wcslen(prefix) + 1;
809 while (1) {
810 wchar_t *delim = wcschr(defpath, DELIM);
811
812 if (defpath[0] != SEP) {
813 /* Paths are relative to prefix */
814 bufsz += prefixsz;
815 }
816
817 if (delim) {
818 bufsz += delim - defpath + 1;
819 }
820 else {
821 bufsz += wcslen(defpath) + 1;
822 break;
823 }
824 defpath = delim + 1;
825 }
826
827 bufsz += wcslen(calculate->zip_path) + 1;
828 bufsz += wcslen(exec_prefix) + 1;
829
830 /* Allocate the buffer */
831 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
832 if (buf == NULL) {
833 return _Py_INIT_NO_MEMORY();
834 }
835 buf[0] = '\0';
836
837 /* Run-time value of $PYTHONPATH goes first */
838 if (core_config->module_search_path_env) {
839 wcscpy(buf, core_config->module_search_path_env);
840 wcscat(buf, delimiter);
841 }
842
843 /* Next is the default zip path */
844 wcscat(buf, calculate->zip_path);
845 wcscat(buf, delimiter);
846
847 /* Next goes merge of compile-time $PYTHONPATH with
848 * dynamically located prefix.
849 */
850 defpath = calculate->pythonpath;
851 while (1) {
852 wchar_t *delim = wcschr(defpath, DELIM);
853
854 if (defpath[0] != SEP) {
855 wcscat(buf, prefix);
856 if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP &&
857 defpath[0] != (delim ? DELIM : L'\0'))
858 {
859 /* not empty */
860 wcscat(buf, separator);
861 }
862 }
863
864 if (delim) {
865 size_t len = delim - defpath + 1;
866 size_t end = wcslen(buf) + len;
867 wcsncat(buf, defpath, len);
868 buf[end] = '\0';
869 }
870 else {
871 wcscat(buf, defpath);
872 break;
873 }
874 defpath = delim + 1;
875 }
876 wcscat(buf, delimiter);
877
878 /* Finally, on goes the directory for dynamic-load modules */
879 wcscat(buf, exec_prefix);
880
881 config->module_search_path = buf;
882 return _Py_INIT_OK();
883 }
884
885
886 static _PyInitError
calculate_init(PyCalculatePath * calculate,const _PyCoreConfig * core_config)887 calculate_init(PyCalculatePath *calculate,
888 const _PyCoreConfig *core_config)
889 {
890 size_t len;
891 const char *path = getenv("PATH");
892 if (path) {
893 calculate->path_env = Py_DecodeLocale(path, &len);
894 if (!calculate->path_env) {
895 return DECODE_LOCALE_ERR("PATH environment variable", len);
896 }
897 }
898
899 calculate->pythonpath = Py_DecodeLocale(PYTHONPATH, &len);
900 if (!calculate->pythonpath) {
901 return DECODE_LOCALE_ERR("PYTHONPATH define", len);
902 }
903 calculate->prefix = Py_DecodeLocale(PREFIX, &len);
904 if (!calculate->prefix) {
905 return DECODE_LOCALE_ERR("PREFIX define", len);
906 }
907 calculate->exec_prefix = Py_DecodeLocale(EXEC_PREFIX, &len);
908 if (!calculate->exec_prefix) {
909 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
910 }
911 calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
912 if (!calculate->lib_python) {
913 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
914 }
915 return _Py_INIT_OK();
916 }
917
918
919 static void
calculate_free(PyCalculatePath * calculate)920 calculate_free(PyCalculatePath *calculate)
921 {
922 PyMem_RawFree(calculate->pythonpath);
923 PyMem_RawFree(calculate->prefix);
924 PyMem_RawFree(calculate->exec_prefix);
925 PyMem_RawFree(calculate->lib_python);
926 PyMem_RawFree(calculate->path_env);
927 }
928
929
930 static _PyInitError
calculate_path_impl(const _PyCoreConfig * core_config,PyCalculatePath * calculate,_PyPathConfig * config)931 calculate_path_impl(const _PyCoreConfig *core_config,
932 PyCalculatePath *calculate, _PyPathConfig *config)
933 {
934 _PyInitError err;
935
936 err = calculate_program_full_path(core_config, calculate, config);
937 if (_Py_INIT_FAILED(err)) {
938 return err;
939 }
940
941 err = calculate_argv0_path(calculate, config->program_full_path);
942 if (_Py_INIT_FAILED(err)) {
943 return err;
944 }
945
946 calculate_read_pyenv(calculate);
947
948 wchar_t prefix[MAXPATHLEN+1];
949 memset(prefix, 0, sizeof(prefix));
950 calculate_prefix(core_config, calculate, prefix);
951
952 calculate_zip_path(calculate, prefix);
953
954 wchar_t exec_prefix[MAXPATHLEN+1];
955 memset(exec_prefix, 0, sizeof(exec_prefix));
956 calculate_exec_prefix(core_config, calculate, exec_prefix);
957
958 if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
959 !Py_FrozenFlag)
960 {
961 fprintf(stderr,
962 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
963 }
964
965 err = calculate_module_search_path(core_config, calculate,
966 prefix, exec_prefix, config);
967 if (_Py_INIT_FAILED(err)) {
968 return err;
969 }
970
971 calculate_reduce_prefix(calculate, prefix);
972
973 config->prefix = _PyMem_RawWcsdup(prefix);
974 if (config->prefix == NULL) {
975 return _Py_INIT_NO_MEMORY();
976 }
977
978 calculate_reduce_exec_prefix(calculate, exec_prefix);
979
980 config->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
981 if (config->exec_prefix == NULL) {
982 return _Py_INIT_NO_MEMORY();
983 }
984
985 return _Py_INIT_OK();
986 }
987
988
989 _PyInitError
_PyPathConfig_Calculate(_PyPathConfig * config,const _PyCoreConfig * core_config)990 _PyPathConfig_Calculate(_PyPathConfig *config, const _PyCoreConfig *core_config)
991 {
992 PyCalculatePath calculate;
993 memset(&calculate, 0, sizeof(calculate));
994
995 _PyInitError err = calculate_init(&calculate, core_config);
996 if (_Py_INIT_FAILED(err)) {
997 goto done;
998 }
999
1000 err = calculate_path_impl(core_config, &calculate, config);
1001 if (_Py_INIT_FAILED(err)) {
1002 goto done;
1003 }
1004
1005 err = _Py_INIT_OK();
1006
1007 done:
1008 calculate_free(&calculate);
1009 return err;
1010 }
1011
1012 #ifdef __cplusplus
1013 }
1014 #endif
1015