blob: 5ce751a3e9eac297fb743e18481d21655a040d9d [file] [log] [blame]
Guido van Rossum582646a1996-05-28 22:30:17 +00001/* Return the initial module search path. */
2
Guido van Rossum667d7041995-08-04 04:20:48 +00003#include "Python.h"
Victor Stinner331a6a52019-05-27 16:39:22 +02004#include "pycore_initconfig.h"
Guido van Rossum667d7041995-08-04 04:20:48 +00005#include "osdefs.h"
Victor Stinner9fc57a32018-11-07 00:44:03 +01006#include "pycore_fileutils.h"
Victor Stinnera1c249c2018-11-01 03:15:58 +01007#include "pycore_pathconfig.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01008#include "pycore_pystate.h"
Guido van Rossum667d7041995-08-04 04:20:48 +00009
Guido van Rossum305e5d01997-04-11 17:18:45 +000010#include <sys/types.h>
Guido van Rossum21f84971997-06-02 22:18:31 +000011#include <string.h>
Guido van Rossum667d7041995-08-04 04:20:48 +000012
Brett Cannonf6af76d2004-06-26 04:03:06 +000013#ifdef __APPLE__
Dan Willemsen7af58832020-07-14 16:41:59 -070014# include <AvailabilityMacros.h>
Victor Stinner0327bde2017-11-23 17:03:20 +010015# include <mach-o/dyld.h>
Guido van Rossum54ecc3d1999-01-27 17:53:11 +000016#endif
17
Guido van Rossum305e5d01997-04-11 17:18:45 +000018/* Search in some common locations for the associated Python libraries.
19 *
20 * Two directories must be found, the platform independent directory
Barry Warsaw90126031997-04-11 20:27:03 +000021 * (prefix), containing the common .py and .pyc files, and the platform
22 * dependent directory (exec_prefix), containing the shared library
23 * modules. Note that prefix and exec_prefix can be the same directory,
24 * but for some installations, they are different.
Guido van Rossum305e5d01997-04-11 17:18:45 +000025 *
Barry Warsaw90126031997-04-11 20:27:03 +000026 * Py_GetPath() carries out separate searches for prefix and exec_prefix.
27 * Each search tries a number of different locations until a ``landmark''
28 * file or directory is found. If no prefix or exec_prefix is found, a
29 * warning message is issued and the preprocessor defined PREFIX and
30 * EXEC_PREFIX are used (even though they will not work); python carries on
31 * as best as is possible, but most imports will fail.
Guido van Rossum305e5d01997-04-11 17:18:45 +000032 *
33 * Before any searches are done, the location of the executable is
Guido van Rossumd8faa362007-04-27 19:54:29 +000034 * determined. If argv[0] has one or more slashes in it, it is used
Barry Warsaw90126031997-04-11 20:27:03 +000035 * unchanged. Otherwise, it must have been invoked from the shell's path,
36 * so we search $PATH for the named executable and use that. If the
37 * executable was not found on $PATH (or there was no $PATH environment
38 * variable), the original argv[0] string is used.
Guido van Rossum305e5d01997-04-11 17:18:45 +000039 *
Barry Warsaw90126031997-04-11 20:27:03 +000040 * Next, the executable location is examined to see if it is a symbolic
41 * link. If so, the link is chased (correctly interpreting a relative
42 * pathname if one is found) and the directory of the link target is used.
Guido van Rossum305e5d01997-04-11 17:18:45 +000043 *
Barry Warsaw90126031997-04-11 20:27:03 +000044 * Finally, argv0_path is set to the directory containing the executable
45 * (i.e. the last component is stripped).
Guido van Rossum305e5d01997-04-11 17:18:45 +000046 *
Barry Warsaw90126031997-04-11 20:27:03 +000047 * With argv0_path in hand, we perform a number of steps. The same steps
48 * are performed for prefix and for exec_prefix, but with a different
49 * landmark.
Guido van Rossum305e5d01997-04-11 17:18:45 +000050 *
51 * Step 1. Are we running python out of the build directory? This is
52 * checked by looking for a different kind of landmark relative to
Barry Warsaw90126031997-04-11 20:27:03 +000053 * argv0_path. For prefix, the landmark's path is derived from the VPATH
54 * preprocessor variable (taking into account that its value is almost, but
55 * not quite, what we need). For exec_prefix, the landmark is
Antoine Pitroueba57b62010-08-14 12:33:18 +000056 * pybuilddir.txt. If the landmark is found, we're done.
Guido van Rossum305e5d01997-04-11 17:18:45 +000057 *
58 * For the remaining steps, the prefix landmark will always be
Jeremy Hylton847a9962000-05-26 21:49:07 +000059 * lib/python$VERSION/os.py and the exec_prefix will always be
Guido van Rossum266033e1997-10-20 23:20:32 +000060 * lib/python$VERSION/lib-dynload, where $VERSION is Python's version
Barry Warsaw90126031997-04-11 20:27:03 +000061 * number as supplied by the Makefile. Note that this means that no more
62 * build directory checking is performed; if the first step did not find
63 * the landmarks, the assumption is that python is running from an
64 * installed setup.
Guido van Rossum305e5d01997-04-11 17:18:45 +000065 *
66 * Step 2. See if the $PYTHONHOME environment variable points to the
Barry Warsaw90126031997-04-11 20:27:03 +000067 * installed location of the Python libraries. If $PYTHONHOME is set, then
68 * it points to prefix and exec_prefix. $PYTHONHOME can be a single
69 * directory, which is used for both, or the prefix and exec_prefix
70 * directories separated by a colon.
Guido van Rossum305e5d01997-04-11 17:18:45 +000071 *
72 * Step 3. Try to find prefix and exec_prefix relative to argv0_path,
Barry Warsaw90126031997-04-11 20:27:03 +000073 * backtracking up the path until it is exhausted. This is the most common
74 * step to succeed. Note that if prefix and exec_prefix are different,
75 * exec_prefix is more likely to be found; however if exec_prefix is a
76 * subdirectory of prefix, both will be found.
Guido van Rossum305e5d01997-04-11 17:18:45 +000077 *
Barry Warsaw90126031997-04-11 20:27:03 +000078 * Step 4. Search the directories pointed to by the preprocessor variables
79 * PREFIX and EXEC_PREFIX. These are supplied by the Makefile but can be
80 * passed in as options to the configure script.
Guido van Rossum305e5d01997-04-11 17:18:45 +000081 *
Barry Warsaw90126031997-04-11 20:27:03 +000082 * That's it!
83 *
84 * Well, almost. Once we have determined prefix and exec_prefix, the
Thomas Wouters7e474022000-07-16 12:04:32 +000085 * preprocessor variable PYTHONPATH is used to construct a path. Each
Barry Warsaw90126031997-04-11 20:27:03 +000086 * relative path on PYTHONPATH is prefixed with prefix. Then the directory
87 * containing the shared library modules is appended. The environment
88 * variable $PYTHONPATH is inserted in front of it all. Finally, the
89 * prefix and exec_prefix globals are tweaked so they reflect the values
90 * expected by other code, by stripping the "lib/python$VERSION/..." stuff
91 * off. If either points to the build directory, the globals are reset to
92 * the corresponding preprocessor variables (so sys.prefix will reflect the
93 * installation location, even though sys.path points into the build
94 * directory). This seems to make more sense given that currently the only
95 * known use of sys.prefix and sys.exec_prefix is for the ILU installation
96 * process to find the installed Python tree.
Antoine Pitroueba57b62010-08-14 12:33:18 +000097 *
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000098 * An embedding application can use Py_SetPath() to override all of
99 * these authomatic path computations.
100 *
Antoine Pitroueba57b62010-08-14 12:33:18 +0000101 * NOTE: Windows MSVC builds use PC/getpathp.c instead!
Barry Warsaw90126031997-04-11 20:27:03 +0000102 */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000103
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000104#ifdef __cplusplus
Victor Stinner0327bde2017-11-23 17:03:20 +0100105extern "C" {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000106#endif
107
108
Benjamin Petersonf5854142016-06-02 12:41:35 -0700109#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH)
110#error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000111#endif
Guido van Rossum667d7041995-08-04 04:20:48 +0000112
Guido van Rossum305e5d01997-04-11 17:18:45 +0000113#ifndef LANDMARK
Martin v. Löwis790465f2008-04-05 20:41:37 +0000114#define LANDMARK L"os.py"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000115#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000116
Victor Stinner9316ee42017-11-25 03:17:57 +0100117#define DECODE_LOCALE_ERR(NAME, LEN) \
118 ((LEN) == (size_t)-2) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200119 ? _PyStatus_ERR("cannot decode " NAME) \
120 : _PyStatus_NO_MEMORY()
Victor Stinner9316ee42017-11-25 03:17:57 +0100121
Victor Stinner331a6a52019-05-27 16:39:22 +0200122#define PATHLEN_ERR() _PyStatus_ERR("path configuration: path too long")
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100123
Victor Stinner0327bde2017-11-23 17:03:20 +0100124typedef struct {
125 wchar_t *path_env; /* PATH environment variable */
Victor Stinner0327bde2017-11-23 17:03:20 +0100126
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700127 wchar_t *pythonpath; /* PYTHONPATH macro */
128 wchar_t *prefix; /* PREFIX macro */
129 wchar_t *exec_prefix; /* EXEC_PREFIX macro */
Victor Stinner0327bde2017-11-23 17:03:20 +0100130
131 wchar_t *lib_python; /* "lib/pythonX.Y" */
Victor Stinner0327bde2017-11-23 17:03:20 +0100132
133 int prefix_found; /* found platform independent libraries? */
134 int exec_prefix_found; /* found the platform dependent libraries? */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200135
136 int warnings;
137 const wchar_t *pythonpath_env;
Victor Stinner0327bde2017-11-23 17:03:20 +0100138} PyCalculatePath;
139
140static const wchar_t delimiter[2] = {DELIM, '\0'};
141static const wchar_t separator[2] = {SEP, '\0'};
Victor Stinner0327bde2017-11-23 17:03:20 +0100142
Martin v. Löwis790465f2008-04-05 20:41:37 +0000143
Victor Stinner91afbb62015-03-24 12:16:28 +0100144/* Get file status. Encode the path to the locale encoding. */
Victor Stinner91afbb62015-03-24 12:16:28 +0100145static int
146_Py_wstat(const wchar_t* path, struct stat *buf)
147{
148 int err;
149 char *fname;
Victor Stinner9dd76202017-12-21 16:20:32 +0100150 fname = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner91afbb62015-03-24 12:16:28 +0100151 if (fname == NULL) {
152 errno = EINVAL;
153 return -1;
154 }
155 err = stat(fname, buf);
Victor Stinner9dd76202017-12-21 16:20:32 +0100156 PyMem_RawFree(fname);
Victor Stinner91afbb62015-03-24 12:16:28 +0100157 return err;
158}
159
Victor Stinner0327bde2017-11-23 17:03:20 +0100160
Guido van Rossum305e5d01997-04-11 17:18:45 +0000161static void
Martin v. Löwis790465f2008-04-05 20:41:37 +0000162reduce(wchar_t *dir)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000163{
Martin v. Löwis790465f2008-04-05 20:41:37 +0000164 size_t i = wcslen(dir);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100165 while (i > 0 && dir[i] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000166 --i;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100167 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000168 dir[i] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +0000169}
Guido van Rossumd29806c1998-01-19 22:06:22 +0000170
Victor Stinner0327bde2017-11-23 17:03:20 +0100171
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100172/* Is file, not directory */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000173static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100174isfile(const wchar_t *filename)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000175{
Fred Drakeedabdc12000-07-08 06:16:37 +0000176 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100177 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000178 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100179 }
180 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000181 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100182 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000183 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000184}
185
186
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100187/* Is module -- check for .pyc too */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000188static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100189ismodule(wchar_t *filename, size_t filename_len)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000190{
Victor Stinner0327bde2017-11-23 17:03:20 +0100191 if (isfile(filename)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000192 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100193 }
Guido van Rossumd29806c1998-01-19 22:06:22 +0000194
Fred Drakeedabdc12000-07-08 06:16:37 +0000195 /* Check for the compiled version of prefix. */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100196 if (wcslen(filename) + 2 <= filename_len) {
Brett Cannonf299abd2015-04-13 14:21:02 -0400197 wcscat(filename, L"c");
Victor Stinner0327bde2017-11-23 17:03:20 +0100198 if (isfile(filename)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000199 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100200 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000201 }
202 return 0;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000203}
204
205
Victor Stinner0327bde2017-11-23 17:03:20 +0100206/* Is executable file */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000207static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100208isxfile(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000209{
Fred Drakeedabdc12000-07-08 06:16:37 +0000210 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100211 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000212 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100213 }
214 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000215 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100216 }
217 if ((buf.st_mode & 0111) == 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000218 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100219 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000220 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000221}
222
223
Victor Stinner0327bde2017-11-23 17:03:20 +0100224/* Is directory */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000225static int
Victor Stinner0327bde2017-11-23 17:03:20 +0100226isdir(wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000227{
Fred Drakeedabdc12000-07-08 06:16:37 +0000228 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100229 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000230 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100231 }
232 if (!S_ISDIR(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000233 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100234 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000235 return 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000236}
237
238
Tim Petersec8c5a92004-08-08 01:00:47 +0000239/* Add a path component, by appending stuff to buffer.
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100240 buflen: 'buffer' length in characters including trailing NUL. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200241static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100242joinpath(wchar_t *buffer, const wchar_t *stuff, size_t buflen)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000243{
Fred Drakeedabdc12000-07-08 06:16:37 +0000244 size_t n, k;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100245 if (stuff[0] != SEP) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000246 n = wcslen(buffer);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100247 if (n >= buflen) {
248 return PATHLEN_ERR();
249 }
250
251 if (n > 0 && buffer[n-1] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000252 buffer[n++] = SEP;
Victor Stinner0327bde2017-11-23 17:03:20 +0100253 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000254 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100255 else {
256 n = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100257 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100258
Martin v. Löwis790465f2008-04-05 20:41:37 +0000259 k = wcslen(stuff);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100260 if (n + k >= buflen) {
261 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100262 }
Martin v. Löwis790465f2008-04-05 20:41:37 +0000263 wcsncpy(buffer+n, stuff, k);
Fred Drakeedabdc12000-07-08 06:16:37 +0000264 buffer[n+k] = '\0';
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100265
Victor Stinner331a6a52019-05-27 16:39:22 +0200266 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000267}
268
Victor Stinner0327bde2017-11-23 17:03:20 +0100269
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100270static inline int
271safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
272{
273 size_t srclen = wcslen(src);
274 if (n <= srclen) {
275 dst[0] = L'\0';
276 return -1;
277 }
278 memcpy(dst, src, (srclen + 1) * sizeof(wchar_t));
279 return 0;
280}
281
282
Guido van Rossume296ced2001-09-28 20:00:29 +0000283/* copy_absolute requires that path be allocated at least
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100284 'pathlen' characters (including trailing NUL). */
Victor Stinner331a6a52019-05-27 16:39:22 +0200285static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100286copy_absolute(wchar_t *path, const wchar_t *p, size_t pathlen)
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000287{
Victor Stinner0327bde2017-11-23 17:03:20 +0100288 if (p[0] == SEP) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100289 if (safe_wcscpy(path, p, pathlen) < 0) {
290 return PATHLEN_ERR();
291 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100292 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000293 else {
Victor Stinnerf4061da2010-10-14 12:37:19 +0000294 if (!_Py_wgetcwd(path, pathlen)) {
Victor Stinner4f3abb02010-10-07 23:29:18 +0000295 /* unable to get the current directory */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100296 if (safe_wcscpy(path, p, pathlen) < 0) {
297 return PATHLEN_ERR();
298 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200299 return _PyStatus_OK();
Victor Stinner4f3abb02010-10-07 23:29:18 +0000300 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100301 if (p[0] == '.' && p[1] == SEP) {
Guido van Rossume296ced2001-09-28 20:00:29 +0000302 p += 2;
Victor Stinner0327bde2017-11-23 17:03:20 +0100303 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200304 PyStatus status = joinpath(path, p, pathlen);
305 if (_PyStatus_EXCEPTION(status)) {
306 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100307 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000308 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200309 return _PyStatus_OK();
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000310}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000311
Victor Stinner0327bde2017-11-23 17:03:20 +0100312
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100313/* path_len: path length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200314static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100315absolutize(wchar_t *path, size_t path_len)
Guido van Rossume296ced2001-09-28 20:00:29 +0000316{
Victor Stinner0327bde2017-11-23 17:03:20 +0100317 if (path[0] == SEP) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200318 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100319 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100320
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100321 wchar_t abs_path[MAXPATHLEN+1];
Victor Stinner331a6a52019-05-27 16:39:22 +0200322 PyStatus status = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path));
323 if (_PyStatus_EXCEPTION(status)) {
324 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100325 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100326
327 if (safe_wcscpy(path, abs_path, path_len) < 0) {
328 return PATHLEN_ERR();
329 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200330 return _PyStatus_OK();
Guido van Rossume296ced2001-09-28 20:00:29 +0000331}
332
Victor Stinner0327bde2017-11-23 17:03:20 +0100333
E. M. Bray7a7693e2018-10-05 13:38:50 +0200334#if defined(__CYGWIN__) || defined(__MINGW32__)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200335#ifndef EXE_SUFFIX
336#define EXE_SUFFIX L".exe"
337#endif
338
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100339/* pathlen: 'path' length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200340static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100341add_exe_suffix(wchar_t *progpath, size_t progpathlen)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200342{
343 /* Check for already have an executable suffix */
344 size_t n = wcslen(progpath);
345 size_t s = wcslen(EXE_SUFFIX);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100346 if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200347 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200348 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100349
350 if (n + s >= progpathlen) {
351 return PATHLEN_ERR();
352 }
353 wcsncpy(progpath + n, EXE_SUFFIX, s);
354 progpath[n+s] = '\0';
355
356 if (!isxfile(progpath)) {
357 /* Path that added suffix is invalid: truncate (remove suffix) */
358 progpath[n] = '\0';
359 }
360
Victor Stinner331a6a52019-05-27 16:39:22 +0200361 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200362}
363#endif
364
365
Guido van Rossume296ced2001-09-28 20:00:29 +0000366/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000367 bytes long.
368*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200369static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200370search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700371 const wchar_t *argv0_path,
Victor Stinner3f5409a2019-09-23 19:50:27 +0200372 wchar_t *prefix, size_t prefix_len, int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000373{
Victor Stinner96c84752019-09-26 16:17:34 +0200374 wchar_t path[MAXPATHLEN+1];
375 memset(path, 0, sizeof(path));
376 size_t path_len = Py_ARRAY_LENGTH(path);
377
Victor Stinner331a6a52019-05-27 16:39:22 +0200378 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000379
Fred Drakeedabdc12000-07-08 06:16:37 +0000380 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200381 if (pathconfig->home) {
Victor Stinner96c84752019-09-26 16:17:34 +0200382 /* Path: <home> / <lib_python> */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200383 if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100384 return PATHLEN_ERR();
385 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100386 wchar_t *delim = wcschr(prefix, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100387 if (delim) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000388 *delim = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100389 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200390 status = joinpath(prefix, calculate->lib_python, prefix_len);
391 if (_PyStatus_EXCEPTION(status)) {
392 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100393 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100394 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200395 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000396 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000397
Fred Drakeedabdc12000-07-08 06:16:37 +0000398 /* Check to see if argv[0] is in the build directory */
Victor Stinner96c84752019-09-26 16:17:34 +0200399 if (safe_wcscpy(path, argv0_path, path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100400 return PATHLEN_ERR();
401 }
Victor Stinner96c84752019-09-26 16:17:34 +0200402 status = joinpath(path, L"Modules/Setup.local", path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200403 if (_PyStatus_EXCEPTION(status)) {
404 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100405 }
406
Victor Stinner96c84752019-09-26 16:17:34 +0200407 if (isfile(path)) {
408 /* Check VPATH to see if argv0_path is in the build directory.
409 VPATH can be empty. */
410 wchar_t *vpath = Py_DecodeLocale(VPATH, NULL);
Victor Stinner21582312010-10-23 00:13:28 +0000411 if (vpath != NULL) {
Victor Stinner96c84752019-09-26 16:17:34 +0200412 /* Path: <argv0_path> / <vpath> / Lib / LANDMARK */
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700413 if (safe_wcscpy(prefix, argv0_path, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100414 return PATHLEN_ERR();
415 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200416 status = joinpath(prefix, vpath, prefix_len);
Victor Stinner1a7425f2013-07-07 16:25:15 +0200417 PyMem_RawFree(vpath);
Victor Stinner331a6a52019-05-27 16:39:22 +0200418 if (_PyStatus_EXCEPTION(status)) {
419 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100420 }
421
Victor Stinner331a6a52019-05-27 16:39:22 +0200422 status = joinpath(prefix, L"Lib", prefix_len);
423 if (_PyStatus_EXCEPTION(status)) {
424 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100425 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200426 status = joinpath(prefix, LANDMARK, prefix_len);
427 if (_PyStatus_EXCEPTION(status)) {
428 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100429 }
430
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100431 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100432 *found = -1;
Victor Stinner96c84752019-09-26 16:17:34 +0200433 reduce(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200434 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100435 }
Victor Stinner21582312010-10-23 00:13:28 +0000436 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000437 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000438
Fred Drakeedabdc12000-07-08 06:16:37 +0000439 /* Search from argv0_path, until root is found */
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700440 status = copy_absolute(prefix, argv0_path, prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200441 if (_PyStatus_EXCEPTION(status)) {
442 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100443 }
444
Fred Drakeedabdc12000-07-08 06:16:37 +0000445 do {
Victor Stinner96c84752019-09-26 16:17:34 +0200446 /* Path: <argv0_path or substring> / <lib_python> / LANDMARK */
447 size_t n = wcslen(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200448 status = joinpath(prefix, calculate->lib_python, prefix_len);
449 if (_PyStatus_EXCEPTION(status)) {
450 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100451 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200452 status = joinpath(prefix, LANDMARK, prefix_len);
453 if (_PyStatus_EXCEPTION(status)) {
454 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100455 }
456
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100457 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100458 *found = 1;
Victor Stinner96c84752019-09-26 16:17:34 +0200459 reduce(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200460 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100461 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100462 prefix[n] = L'\0';
463 reduce(prefix);
464 } while (prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000465
Victor Stinner96c84752019-09-26 16:17:34 +0200466 /* Look at configure's PREFIX.
467 Path: <PREFIX macro> / <lib_python> / LANDMARK */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100468 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
469 return PATHLEN_ERR();
470 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200471 status = joinpath(prefix, calculate->lib_python, prefix_len);
472 if (_PyStatus_EXCEPTION(status)) {
473 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100474 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200475 status = joinpath(prefix, LANDMARK, prefix_len);
476 if (_PyStatus_EXCEPTION(status)) {
477 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100478 }
479
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100480 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100481 *found = 1;
Victor Stinner96c84752019-09-26 16:17:34 +0200482 reduce(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200483 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100484 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000485
Fred Drakeedabdc12000-07-08 06:16:37 +0000486 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100487 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200488 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000489}
490
491
Victor Stinner331a6a52019-05-27 16:39:22 +0200492static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200493calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700494 const wchar_t *argv0_path,
Victor Stinner3f5409a2019-09-23 19:50:27 +0200495 wchar_t *prefix, size_t prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100496{
Victor Stinner331a6a52019-05-27 16:39:22 +0200497 PyStatus status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100498
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700499 status = search_for_prefix(calculate, pathconfig, argv0_path,
500 prefix, prefix_len,
Victor Stinner3f5409a2019-09-23 19:50:27 +0200501 &calculate->prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200502 if (_PyStatus_EXCEPTION(status)) {
503 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100504 }
505
Victor Stinner0327bde2017-11-23 17:03:20 +0100506 if (!calculate->prefix_found) {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200507 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100508 fprintf(stderr,
509 "Could not find platform independent libraries <prefix>\n");
510 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100511 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
512 return PATHLEN_ERR();
513 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200514 status = joinpath(prefix, calculate->lib_python, prefix_len);
515 if (_PyStatus_EXCEPTION(status)) {
516 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100517 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100518 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200519 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100520}
521
522
Victor Stinner331a6a52019-05-27 16:39:22 +0200523static PyStatus
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700524calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
525 wchar_t *prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +0100526{
527 /* Reduce prefix and exec_prefix to their essence,
528 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
529 * If we're loading relative to the build directory,
530 * return the compiled-in defaults instead.
531 */
532 if (calculate->prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100533 reduce(prefix);
534 reduce(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100535 /* The prefix is the root directory, but reduce() chopped
536 * off the "/". */
Victor Stinner9316ee42017-11-25 03:17:57 +0100537 if (!prefix[0]) {
538 wcscpy(prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100539 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700540 pathconfig->prefix = _PyMem_RawWcsdup(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100541 }
542 else {
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700543 pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix);
544 }
545
546 if (pathconfig->prefix == NULL) {
547 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100548 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200549 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100550}
551
552
Victor Stinner96c84752019-09-26 16:17:34 +0200553static PyStatus
554calculate_pybuilddir(const wchar_t *argv0_path,
555 wchar_t *exec_prefix, size_t exec_prefix_len,
556 int *found)
557{
558 PyStatus status;
559
560 wchar_t filename[MAXPATHLEN+1];
561 memset(filename, 0, sizeof(filename));
562 size_t filename_len = Py_ARRAY_LENGTH(filename);
563
564 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
565 is written by setup.py and contains the relative path to the location
566 of shared library modules.
567
568 Filename: <argv0_path> / "pybuilddir.txt" */
569 if (safe_wcscpy(filename, argv0_path, filename_len) < 0) {
570 return PATHLEN_ERR();
571 }
572 status = joinpath(filename, L"pybuilddir.txt", filename_len);
573 if (_PyStatus_EXCEPTION(status)) {
574 return status;
575 }
576
577 if (!isfile(filename)) {
578 return _PyStatus_OK();
579 }
580
581 FILE *fp = _Py_wfopen(filename, L"rb");
582 if (fp == NULL) {
583 errno = 0;
584 return _PyStatus_OK();
585 }
586
587 char buf[MAXPATHLEN + 1];
588 size_t n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, fp);
589 buf[n] = '\0';
590 fclose(fp);
591
592 size_t dec_len;
593 wchar_t *pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
594 if (!pybuilddir) {
595 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
596 }
597
598 /* Path: <argv0_path> / <pybuilddir content> */
599 if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) {
600 PyMem_RawFree(pybuilddir);
601 return PATHLEN_ERR();
602 }
603 status = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
604 PyMem_RawFree(pybuilddir);
605 if (_PyStatus_EXCEPTION(status)) {
606 return status;
607 }
608
609 *found = -1;
610 return _PyStatus_OK();
611}
612
613
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000614/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000615 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000616*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200617static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200618search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700619 const wchar_t *argv0_path,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100620 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100621 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000622{
Victor Stinner331a6a52019-05-27 16:39:22 +0200623 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000624
Fred Drakeedabdc12000-07-08 06:16:37 +0000625 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200626 if (pathconfig->home) {
Victor Stinner96c84752019-09-26 16:17:34 +0200627 /* Path: <home> / <lib_python> / "lib-dynload" */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200628 wchar_t *delim = wcschr(pathconfig->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100629 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100630 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
631 return PATHLEN_ERR();
632 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100633 }
634 else {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200635 if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100636 return PATHLEN_ERR();
637 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100638 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200639 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
640 if (_PyStatus_EXCEPTION(status)) {
641 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100642 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200643 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
644 if (_PyStatus_EXCEPTION(status)) {
645 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100646 }
647 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200648 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000649 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000650
Victor Stinner96c84752019-09-26 16:17:34 +0200651 /* Check for pybuilddir.txt */
652 assert(*found == 0);
653 status = calculate_pybuilddir(argv0_path, exec_prefix, exec_prefix_len,
654 found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200655 if (_PyStatus_EXCEPTION(status)) {
656 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100657 }
Victor Stinner96c84752019-09-26 16:17:34 +0200658 if (*found) {
659 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000660 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000661
Fred Drakeedabdc12000-07-08 06:16:37 +0000662 /* Search from argv0_path, until root is found */
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700663 status = copy_absolute(exec_prefix, argv0_path, exec_prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200664 if (_PyStatus_EXCEPTION(status)) {
665 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100666 }
667
Fred Drakeedabdc12000-07-08 06:16:37 +0000668 do {
Victor Stinner96c84752019-09-26 16:17:34 +0200669 /* Path: <argv0_path or substring> / <lib_python> / "lib-dynload" */
670 size_t n = wcslen(exec_prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200671 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
672 if (_PyStatus_EXCEPTION(status)) {
673 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100674 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200675 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
676 if (_PyStatus_EXCEPTION(status)) {
677 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100678 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100679 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100680 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200681 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100682 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100683 exec_prefix[n] = L'\0';
684 reduce(exec_prefix);
685 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000686
Victor Stinner96c84752019-09-26 16:17:34 +0200687 /* Look at configure's EXEC_PREFIX.
688
689 Path: <EXEC_PREFIX macro> / <lib_python> / "lib-dynload" */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100690 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
691 return PATHLEN_ERR();
692 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200693 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
694 if (_PyStatus_EXCEPTION(status)) {
695 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100696 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200697 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
698 if (_PyStatus_EXCEPTION(status)) {
699 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100700 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100701 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100702 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200703 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100704 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000705
Fred Drakeedabdc12000-07-08 06:16:37 +0000706 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100707 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200708 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000709}
710
Guido van Rossum305e5d01997-04-11 17:18:45 +0000711
Victor Stinner331a6a52019-05-27 16:39:22 +0200712static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200713calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700714 const wchar_t *argv0_path,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100715 wchar_t *exec_prefix, size_t exec_prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100716{
Victor Stinner331a6a52019-05-27 16:39:22 +0200717 PyStatus status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100718
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700719 status = search_for_exec_prefix(calculate, pathconfig, argv0_path,
Victor Stinner3f5409a2019-09-23 19:50:27 +0200720 exec_prefix, exec_prefix_len,
721 &calculate->exec_prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200722 if (_PyStatus_EXCEPTION(status)) {
723 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100724 }
725
Victor Stinner0327bde2017-11-23 17:03:20 +0100726 if (!calculate->exec_prefix_found) {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200727 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100728 fprintf(stderr,
729 "Could not find platform dependent libraries <exec_prefix>\n");
730 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100731 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
732 return PATHLEN_ERR();
733 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200734 status = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len);
735 if (_PyStatus_EXCEPTION(status)) {
736 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100737 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100738 }
739 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
Victor Stinner331a6a52019-05-27 16:39:22 +0200740 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100741}
742
743
Victor Stinner331a6a52019-05-27 16:39:22 +0200744static PyStatus
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700745calculate_set_exec_prefix(PyCalculatePath *calculate,
746 _PyPathConfig *pathconfig,
747 wchar_t *exec_prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +0100748{
749 if (calculate->exec_prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100750 reduce(exec_prefix);
751 reduce(exec_prefix);
752 reduce(exec_prefix);
753 if (!exec_prefix[0]) {
754 wcscpy(exec_prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100755 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700756
757 pathconfig->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100758 }
759 else {
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700760 pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100761 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700762
763 if (pathconfig->exec_prefix == NULL) {
764 return _PyStatus_NO_MEMORY();
765 }
766
Victor Stinner331a6a52019-05-27 16:39:22 +0200767 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100768}
769
770
Victor Stinner331a6a52019-05-27 16:39:22 +0200771static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200772calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100773{
Victor Stinner331a6a52019-05-27 16:39:22 +0200774 PyStatus status;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100775 wchar_t program_full_path[MAXPATHLEN + 1];
776 const size_t program_full_path_len = Py_ARRAY_LENGTH(program_full_path);
Victor Stinnerb64de462017-12-01 18:27:09 +0100777 memset(program_full_path, 0, sizeof(program_full_path));
Victor Stinner9316ee42017-11-25 03:17:57 +0100778
Victor Stinnerb9197952017-11-23 19:02:04 +0100779#ifdef __APPLE__
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100780 char execpath[MAXPATHLEN + 1];
Victor Stinnerb9197952017-11-23 19:02:04 +0100781#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100782 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100783#else
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100784 unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100785#endif
Victor Stinnerb9197952017-11-23 19:02:04 +0100786#endif
787
Victor Stinner0327bde2017-11-23 17:03:20 +0100788 /* If there is no slash in the argv0 path, then we have to
789 * assume python is on the user's $PATH, since there's no
790 * other way to find a directory to start the search from. If
791 * $PATH isn't exported, you lose.
792 */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200793 if (wcschr(pathconfig->program_name, SEP)) {
794 if (safe_wcscpy(program_full_path, pathconfig->program_name,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100795 program_full_path_len) < 0) {
796 return PATHLEN_ERR();
797 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100798 }
Jack Jansen1afd4802004-06-03 14:33:03 +0000799#ifdef __APPLE__
Jack Jansen1afd4802004-06-03 14:33:03 +0000800 /* On Mac OS X, if a script uses an interpreter of the form
801 * "#!/opt/python2.3/bin/python", the kernel only passes "python"
802 * as argv[0], which falls through to the $PATH search below.
803 * If /opt/python2.3/bin isn't in your path, or is near the end,
804 * this algorithm may incorrectly find /usr/bin/python. To work
805 * around this, we can use _NSGetExecutablePath to get a better
806 * hint of what the intended interpreter was, although this
807 * will fail if a relative path was used. but in that case,
808 * absolutize() should help us out below
809 */
Victor Stinnerf04ebe22017-11-25 00:01:23 +0100810 else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
811 execpath[0] == SEP)
812 {
Victor Stinner31a83932017-12-04 13:39:15 +0100813 size_t len;
814 wchar_t *path = Py_DecodeLocale(execpath, &len);
815 if (path == NULL) {
816 return DECODE_LOCALE_ERR("executable path", len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000817 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100818 if (safe_wcscpy(program_full_path, path, program_full_path_len) < 0) {
819 PyMem_RawFree(path);
820 return PATHLEN_ERR();
821 }
Victor Stinner31a83932017-12-04 13:39:15 +0100822 PyMem_RawFree(path);
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000823 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000824#endif /* __APPLE__ */
Victor Stinner0327bde2017-11-23 17:03:20 +0100825 else if (calculate->path_env) {
826 wchar_t *path = calculate->path_env;
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000827 while (1) {
828 wchar_t *delim = wcschr(path, DELIM);
Jack Jansen55070f52001-12-02 23:56:28 +0000829
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000830 if (delim) {
831 size_t len = delim - path;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100832 if (len >= program_full_path_len) {
833 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100834 }
Victor Stinnerb64de462017-12-01 18:27:09 +0100835 wcsncpy(program_full_path, path, len);
836 program_full_path[len] = '\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000837 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100838 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100839 if (safe_wcscpy(program_full_path, path,
840 program_full_path_len) < 0) {
841 return PATHLEN_ERR();
842 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100843 }
Jack Jansen55070f52001-12-02 23:56:28 +0000844
Victor Stinner3f5409a2019-09-23 19:50:27 +0200845 status = joinpath(program_full_path, pathconfig->program_name,
846 program_full_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200847 if (_PyStatus_EXCEPTION(status)) {
848 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100849 }
850
Victor Stinnerb64de462017-12-01 18:27:09 +0100851 if (isxfile(program_full_path)) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000852 break;
Victor Stinner0327bde2017-11-23 17:03:20 +0100853 }
Jack Jansen55070f52001-12-02 23:56:28 +0000854
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000855 if (!delim) {
Victor Stinnerb64de462017-12-01 18:27:09 +0100856 program_full_path[0] = L'\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000857 break;
858 }
859 path = delim + 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000860 }
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000861 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100862 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100863 program_full_path[0] = '\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100864 }
Victor Stinnerb64de462017-12-01 18:27:09 +0100865 if (program_full_path[0] != SEP && program_full_path[0] != '\0') {
Victor Stinner331a6a52019-05-27 16:39:22 +0200866 status = absolutize(program_full_path, program_full_path_len);
867 if (_PyStatus_EXCEPTION(status)) {
868 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100869 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100870 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200871#if defined(__CYGWIN__) || defined(__MINGW32__)
872 /* For these platforms it is necessary to ensure that the .exe suffix
873 * is appended to the filename, otherwise there is potential for
874 * sys.executable to return the name of a directory under the same
875 * path (bpo-28441).
876 */
877 if (program_full_path[0] != '\0') {
Victor Stinner331a6a52019-05-27 16:39:22 +0200878 status = add_exe_suffix(program_full_path, program_full_path_len);
879 if (_PyStatus_EXCEPTION(status)) {
880 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100881 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200882 }
883#endif
Victor Stinner9316ee42017-11-25 03:17:57 +0100884
Victor Stinner331a6a52019-05-27 16:39:22 +0200885 pathconfig->program_full_path = _PyMem_RawWcsdup(program_full_path);
886 if (pathconfig->program_full_path == NULL) {
887 return _PyStatus_NO_MEMORY();
Victor Stinner9316ee42017-11-25 03:17:57 +0100888 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200889 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100890}
891
892
Victor Stinner331a6a52019-05-27 16:39:22 +0200893static PyStatus
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700894calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path,
895 wchar_t *argv0_path, size_t argv0_path_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100896{
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700897 if (safe_wcscpy(argv0_path, program_full_path, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100898 return PATHLEN_ERR();
899 }
Jack Jansen55070f52001-12-02 23:56:28 +0000900
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000901#ifdef WITH_NEXT_FRAMEWORK
Victor Stinner0327bde2017-11-23 17:03:20 +0100902 NSModule pythonModule;
903
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000904 /* On Mac OS X we have a special case if we're running from a framework.
905 ** This is because the python home should be set relative to the library,
906 ** which is in the framework, not relative to the executable, which may
907 ** be outside of the framework. Except when we're in the build directory...
908 */
Fred Drakeedabdc12000-07-08 06:16:37 +0000909 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
910 /* Use dylib functions to find out where the framework was loaded from */
Victor Stinner0327bde2017-11-23 17:03:20 +0100911 const char* modPath = NSLibraryNameForModule(pythonModule);
Vinay Sajip90db6612012-07-17 17:33:46 +0100912 if (modPath != NULL) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000913 /* We're in a framework. */
Jack Jansene925faf2001-08-15 01:14:40 +0000914 /* See if we might be in the build directory. The framework in the
915 ** build directory is incomplete, it only has the .dylib and a few
916 ** needed symlinks, it doesn't have the Lib directories and such.
917 ** If we're running with the framework from the build directory we must
918 ** be running the interpreter in the build directory, so we use the
919 ** build-directory-specific logic to find Lib and such.
920 */
Victor Stinner331a6a52019-05-27 16:39:22 +0200921 PyStatus status;
Victor Stinner9316ee42017-11-25 03:17:57 +0100922 size_t len;
923 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100924 if (wbuf == NULL) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100925 return DECODE_LOCALE_ERR("framework location", len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100926 }
927
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700928 if (safe_wcscpy(argv0_path, wbuf, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100929 return PATHLEN_ERR();
930 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700931 reduce(argv0_path);
932 status = joinpath(argv0_path, calculate->lib_python, argv0_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200933 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100934 PyMem_RawFree(wbuf);
Victor Stinner331a6a52019-05-27 16:39:22 +0200935 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100936 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700937 status = joinpath(argv0_path, LANDMARK, argv0_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200938 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100939 PyMem_RawFree(wbuf);
Victor Stinner331a6a52019-05-27 16:39:22 +0200940 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100941 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700942 if (!ismodule(argv0_path, Py_ARRAY_LENGTH(argv0_path))) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000943 /* We are in the build directory so use the name of the
944 executable - we know that the absolute path is passed */
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700945 if (safe_wcscpy(argv0_path, program_full_path,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100946 argv0_path_len) < 0) {
947 return PATHLEN_ERR();
948 }
Jack Jansene925faf2001-08-15 01:14:40 +0000949 }
950 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100951 /* Use the location of the library as the program_full_path */
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700952 if (safe_wcscpy(argv0_path, wbuf, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100953 return PATHLEN_ERR();
954 }
Jack Jansene925faf2001-08-15 01:14:40 +0000955 }
Victor Stinner1a7425f2013-07-07 16:25:15 +0200956 PyMem_RawFree(wbuf);
Fred Drakeedabdc12000-07-08 06:16:37 +0000957 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000958#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000959
Guido van Rossum305e5d01997-04-11 17:18:45 +0000960#if HAVE_READLINK
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100961 wchar_t tmpbuffer[MAXPATHLEN + 1];
962 const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
963 int linklen = _Py_wreadlink(program_full_path, tmpbuffer, buflen);
Victor Stinner0327bde2017-11-23 17:03:20 +0100964 while (linklen != -1) {
965 if (tmpbuffer[0] == SEP) {
966 /* tmpbuffer should never be longer than MAXPATHLEN,
967 but extra check does not hurt */
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700968 if (safe_wcscpy(argv0_path, tmpbuffer, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100969 return PATHLEN_ERR();
970 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000971 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100972 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100973 /* Interpret relative to program_full_path */
Victor Stinner331a6a52019-05-27 16:39:22 +0200974 PyStatus status;
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700975 reduce(argv0_path);
976 status = joinpath(argv0_path, tmpbuffer, argv0_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200977 if (_PyStatus_EXCEPTION(status)) {
978 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100979 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100980 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700981 linklen = _Py_wreadlink(argv0_path, tmpbuffer, buflen);
Fred Drakeedabdc12000-07-08 06:16:37 +0000982 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000983#endif /* HAVE_READLINK */
984
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700985 reduce(argv0_path);
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000986 /* At this point, argv0_path is guaranteed to be less than
Victor Stinner0327bde2017-11-23 17:03:20 +0100987 MAXPATHLEN bytes long. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200988 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100989}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000990
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100991
Victor Stinner0327bde2017-11-23 17:03:20 +0100992/* Search for an "pyvenv.cfg" environment configuration file, first in the
993 executable's directory and then in the parent directory.
994 If found, open it for use when searching for prefixes.
995*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200996static PyStatus
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700997calculate_read_pyenv(PyCalculatePath *calculate,
998 wchar_t *argv0_path, size_t argv0_path_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100999{
Victor Stinner331a6a52019-05-27 16:39:22 +02001000 PyStatus status;
Victor Stinner96c84752019-09-26 16:17:34 +02001001 const wchar_t *env_cfg = L"pyvenv.cfg";
Victor Stinner0327bde2017-11-23 17:03:20 +01001002 FILE *env_file;
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001003
Victor Stinner96c84752019-09-26 16:17:34 +02001004 wchar_t filename[MAXPATHLEN+1];
1005 const size_t filename_len = Py_ARRAY_LENGTH(filename);
1006 memset(filename, 0, sizeof(filename));
1007
1008 /* Filename: <argv0_path_len> / "pyvenv.cfg" */
1009 if (safe_wcscpy(filename, argv0_path, filename_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001010 return PATHLEN_ERR();
1011 }
Vinay Sajip90db6612012-07-17 17:33:46 +01001012
Victor Stinner96c84752019-09-26 16:17:34 +02001013 status = joinpath(filename, env_cfg, filename_len);
Victor Stinner331a6a52019-05-27 16:39:22 +02001014 if (_PyStatus_EXCEPTION(status)) {
1015 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001016 }
Victor Stinner96c84752019-09-26 16:17:34 +02001017 env_file = _Py_wfopen(filename, L"r");
Victor Stinner0327bde2017-11-23 17:03:20 +01001018 if (env_file == NULL) {
1019 errno = 0;
1020
Victor Stinner96c84752019-09-26 16:17:34 +02001021 /* Filename: <basename(basename(argv0_path_len))> / "pyvenv.cfg" */
1022 reduce(filename);
1023 reduce(filename);
1024 status = joinpath(filename, env_cfg, filename_len);
Victor Stinner331a6a52019-05-27 16:39:22 +02001025 if (_PyStatus_EXCEPTION(status)) {
1026 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001027 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001028
Victor Stinner96c84752019-09-26 16:17:34 +02001029 env_file = _Py_wfopen(filename, L"r");
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001030 if (env_file == NULL) {
1031 errno = 0;
Victor Stinner96c84752019-09-26 16:17:34 +02001032 return _PyStatus_OK();
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001033 }
1034 }
1035
Victor Stinner0327bde2017-11-23 17:03:20 +01001036 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinner96c84752019-09-26 16:17:34 +02001037 wchar_t home[MAXPATHLEN+1];
1038 memset(home, 0, sizeof(home));
1039
1040 if (_Py_FindEnvConfigValue(env_file, L"home",
1041 home, Py_ARRAY_LENGTH(home))) {
1042 if (safe_wcscpy(argv0_path, home, argv0_path_len) < 0) {
1043 fclose(env_file);
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001044 return PATHLEN_ERR();
1045 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001046 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001047 fclose(env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001048 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001049}
Just van Rossum52e14d62002-12-30 22:08:05 +00001050
Guido van Rossum305e5d01997-04-11 17:18:45 +00001051
Victor Stinner331a6a52019-05-27 16:39:22 +02001052static PyStatus
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001053calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix,
1054 wchar_t *zip_path, size_t zip_path_len)
Victor Stinner0327bde2017-11-23 17:03:20 +01001055{
Victor Stinner331a6a52019-05-27 16:39:22 +02001056 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001057
Victor Stinner0327bde2017-11-23 17:03:20 +01001058 if (calculate->prefix_found > 0) {
1059 /* Use the reduced prefix returned by Py_GetPrefix() */
Victor Stinner96c84752019-09-26 16:17:34 +02001060 if (safe_wcscpy(zip_path, prefix, zip_path_len) < 0) {
1061 return PATHLEN_ERR();
1062 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001063 reduce(zip_path);
1064 reduce(zip_path);
Victor Stinnerd4341102017-11-23 00:12:09 +01001065 }
1066 else {
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001067 if (safe_wcscpy(zip_path, calculate->prefix, zip_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001068 return PATHLEN_ERR();
1069 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001070 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001071 status = joinpath(zip_path, L"lib/python00.zip", zip_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +02001072 if (_PyStatus_EXCEPTION(status)) {
1073 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001074 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001075
1076 /* Replace "00" with version */
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001077 size_t bufsz = wcslen(zip_path);
1078 zip_path[bufsz - 6] = VERSION[0];
1079 zip_path[bufsz - 5] = VERSION[2];
Victor Stinner331a6a52019-05-27 16:39:22 +02001080 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001081}
1082
1083
Victor Stinner331a6a52019-05-27 16:39:22 +02001084static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +02001085calculate_module_search_path(PyCalculatePath *calculate,
1086 _PyPathConfig *pathconfig,
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001087 const wchar_t *prefix,
1088 const wchar_t *exec_prefix,
1089 const wchar_t *zip_path)
Victor Stinner0327bde2017-11-23 17:03:20 +01001090{
1091 /* Calculate size of return buffer */
1092 size_t bufsz = 0;
Victor Stinner3f5409a2019-09-23 19:50:27 +02001093 if (calculate->pythonpath_env != NULL) {
1094 bufsz += wcslen(calculate->pythonpath_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001095 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001096
Victor Stinner0327bde2017-11-23 17:03:20 +01001097 wchar_t *defpath = calculate->pythonpath;
Victor Stinner9316ee42017-11-25 03:17:57 +01001098 size_t prefixsz = wcslen(prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001099 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001100 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001101
Victor Stinner0327bde2017-11-23 17:03:20 +01001102 if (defpath[0] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001103 /* Paths are relative to prefix */
1104 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001105 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001106
Victor Stinner0327bde2017-11-23 17:03:20 +01001107 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001108 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001109 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001110 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001111 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001112 break;
1113 }
1114 defpath = delim + 1;
1115 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001116
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001117 bufsz += wcslen(zip_path) + 1;
Victor Stinner9316ee42017-11-25 03:17:57 +01001118 bufsz += wcslen(exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001119
Victor Stinner0327bde2017-11-23 17:03:20 +01001120 /* Allocate the buffer */
1121 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001122 if (buf == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +02001123 return _PyStatus_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001124 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001125 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001126
Victor Stinner72967a42013-11-16 01:22:04 +01001127 /* Run-time value of $PYTHONPATH goes first */
Victor Stinner3f5409a2019-09-23 19:50:27 +02001128 if (calculate->pythonpath_env) {
1129 wcscpy(buf, calculate->pythonpath_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001130 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001131 }
Victor Stinner72967a42013-11-16 01:22:04 +01001132
1133 /* Next is the default zip path */
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001134 wcscat(buf, zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001135 wcscat(buf, delimiter);
1136
1137 /* Next goes merge of compile-time $PYTHONPATH with
1138 * dynamically located prefix.
1139 */
Victor Stinner0327bde2017-11-23 17:03:20 +01001140 defpath = calculate->pythonpath;
Victor Stinner72967a42013-11-16 01:22:04 +01001141 while (1) {
1142 wchar_t *delim = wcschr(defpath, DELIM);
1143
1144 if (defpath[0] != SEP) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001145 wcscat(buf, prefix);
1146 if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001147 defpath[0] != (delim ? DELIM : L'\0'))
1148 {
1149 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001150 wcscat(buf, separator);
1151 }
Victor Stinner72967a42013-11-16 01:22:04 +01001152 }
1153
1154 if (delim) {
1155 size_t len = delim - defpath + 1;
1156 size_t end = wcslen(buf) + len;
1157 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001158 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001159 }
1160 else {
1161 wcscat(buf, defpath);
1162 break;
1163 }
1164 defpath = delim + 1;
1165 }
1166 wcscat(buf, delimiter);
1167
1168 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinner9316ee42017-11-25 03:17:57 +01001169 wcscat(buf, exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001170
Victor Stinner331a6a52019-05-27 16:39:22 +02001171 pathconfig->module_search_path = buf;
1172 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001173}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001174
Victor Stinner0327bde2017-11-23 17:03:20 +01001175
Victor Stinner331a6a52019-05-27 16:39:22 +02001176static PyStatus
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001177calculate_init(PyCalculatePath *calculate, const PyConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001178{
Victor Stinner0327bde2017-11-23 17:03:20 +01001179 size_t len;
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001180 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001181 if (path) {
1182 calculate->path_env = Py_DecodeLocale(path, &len);
1183 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001184 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001185 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001186 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001187
Victor Stinner0327bde2017-11-23 17:03:20 +01001188 calculate->pythonpath = Py_DecodeLocale(PYTHONPATH, &len);
1189 if (!calculate->pythonpath) {
Victor Stinner46972b72017-11-24 22:55:40 +01001190 return DECODE_LOCALE_ERR("PYTHONPATH define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001191 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001192
Victor Stinner0327bde2017-11-23 17:03:20 +01001193 calculate->prefix = Py_DecodeLocale(PREFIX, &len);
1194 if (!calculate->prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001195 return DECODE_LOCALE_ERR("PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001196 }
1197 calculate->exec_prefix = Py_DecodeLocale(EXEC_PREFIX, &len);
Miss Islington (bot)e8329632019-09-09 10:59:18 -07001198 if (!calculate->exec_prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001199 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001200 }
1201 calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
1202 if (!calculate->lib_python) {
Victor Stinner46972b72017-11-24 22:55:40 +01001203 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001204 }
Victor Stinner3f5409a2019-09-23 19:50:27 +02001205
1206 calculate->warnings = config->pathconfig_warnings;
1207 calculate->pythonpath_env = config->pythonpath_env;
1208
Victor Stinner331a6a52019-05-27 16:39:22 +02001209 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001210}
1211
1212
1213static void
1214calculate_free(PyCalculatePath *calculate)
1215{
1216 PyMem_RawFree(calculate->pythonpath);
1217 PyMem_RawFree(calculate->prefix);
1218 PyMem_RawFree(calculate->exec_prefix);
1219 PyMem_RawFree(calculate->lib_python);
1220 PyMem_RawFree(calculate->path_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001221}
1222
1223
Victor Stinner331a6a52019-05-27 16:39:22 +02001224static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +02001225calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001226{
Victor Stinner331a6a52019-05-27 16:39:22 +02001227 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +01001228
Victor Stinner3f5409a2019-09-23 19:50:27 +02001229 if (pathconfig->program_full_path == NULL) {
1230 status = calculate_program_full_path(calculate, pathconfig);
1231 if (_PyStatus_EXCEPTION(status)) {
1232 return status;
1233 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001234 }
1235
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001236 wchar_t argv0_path[MAXPATHLEN+1];
1237 memset(argv0_path, 0, sizeof(argv0_path));
1238
1239 status = calculate_argv0_path(calculate, pathconfig->program_full_path,
1240 argv0_path, Py_ARRAY_LENGTH(argv0_path));
Victor Stinner331a6a52019-05-27 16:39:22 +02001241 if (_PyStatus_EXCEPTION(status)) {
1242 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001243 }
1244
Victor Stinner96c84752019-09-26 16:17:34 +02001245 /* If a pyvenv.cfg configure file is found,
1246 argv0_path is overriden with its 'home' variable. */
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001247 status = calculate_read_pyenv(calculate,
1248 argv0_path, Py_ARRAY_LENGTH(argv0_path));
Victor Stinner331a6a52019-05-27 16:39:22 +02001249 if (_PyStatus_EXCEPTION(status)) {
1250 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001251 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001252
1253 wchar_t prefix[MAXPATHLEN+1];
1254 memset(prefix, 0, sizeof(prefix));
Victor Stinner3f5409a2019-09-23 19:50:27 +02001255 status = calculate_prefix(calculate, pathconfig,
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001256 argv0_path,
Victor Stinner3f5409a2019-09-23 19:50:27 +02001257 prefix, Py_ARRAY_LENGTH(prefix));
Victor Stinner331a6a52019-05-27 16:39:22 +02001258 if (_PyStatus_EXCEPTION(status)) {
1259 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001260 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001261
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001262 wchar_t zip_path[MAXPATHLEN+1]; /* ".../lib/pythonXY.zip" */
1263 memset(zip_path, 0, sizeof(zip_path));
1264
1265 status = calculate_zip_path(calculate, prefix,
1266 zip_path, Py_ARRAY_LENGTH(zip_path));
Victor Stinner331a6a52019-05-27 16:39:22 +02001267 if (_PyStatus_EXCEPTION(status)) {
1268 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001269 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001270
1271 wchar_t exec_prefix[MAXPATHLEN+1];
1272 memset(exec_prefix, 0, sizeof(exec_prefix));
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001273 status = calculate_exec_prefix(calculate, pathconfig, argv0_path,
Victor Stinner3f5409a2019-09-23 19:50:27 +02001274 exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
Victor Stinner331a6a52019-05-27 16:39:22 +02001275 if (_PyStatus_EXCEPTION(status)) {
1276 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001277 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001278
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001279 if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
Victor Stinner3f5409a2019-09-23 19:50:27 +02001280 calculate->warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001281 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001282 fprintf(stderr,
1283 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1284 }
1285
Victor Stinner9f3dcf82019-09-21 02:13:14 +02001286 if (pathconfig->module_search_path == NULL) {
Victor Stinner3f5409a2019-09-23 19:50:27 +02001287 status = calculate_module_search_path(calculate, pathconfig,
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001288 prefix, exec_prefix, zip_path);
Victor Stinner9f3dcf82019-09-21 02:13:14 +02001289 if (_PyStatus_EXCEPTION(status)) {
1290 return status;
1291 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001292 }
1293
Victor Stinner331a6a52019-05-27 16:39:22 +02001294 if (pathconfig->prefix == NULL) {
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001295 status = calculate_set_prefix(calculate, pathconfig, prefix);
Victor Stinner3f5409a2019-09-23 19:50:27 +02001296 if (_PyStatus_EXCEPTION(status)) {
1297 return status;
1298 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001299 }
1300
Victor Stinner331a6a52019-05-27 16:39:22 +02001301 if (pathconfig->exec_prefix == NULL) {
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001302 status = calculate_set_exec_prefix(calculate, pathconfig, exec_prefix);
Victor Stinner3f5409a2019-09-23 19:50:27 +02001303 if (_PyStatus_EXCEPTION(status)) {
1304 return status;
1305 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001306 }
1307
Victor Stinner331a6a52019-05-27 16:39:22 +02001308 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001309}
1310
1311
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001312/* Calculate the Python path configuration.
1313
1314 Inputs:
1315
1316 - PATH environment variable
1317 - Macros: PYTHONPATH, PREFIX, EXEC_PREFIX, VERSION (ex: "3.9").
1318 PREFIX and EXEC_PREFIX are generated by the configure script.
1319 PYTHONPATH macro is the default search path.
1320 - pybuilddir.txt file
1321 - pyvenv.cfg configuration file
1322 - PyConfig fields ('config' function argument):
1323
1324 - pathconfig_warnings
1325 - pythonpath_env (PYTHONPATH environment variable)
1326
1327 - _PyPathConfig fields ('pathconfig' function argument):
1328
1329 - program_name: see config_init_program_name()
1330 - home: Py_SetPythonHome() or PYTHONHOME environment variable
1331
1332 - current working directory: see copy_absolute()
1333
1334 Outputs, 'pathconfig' fields:
Victor Stinner3f5409a2019-09-23 19:50:27 +02001335
1336 - program_full_path
1337 - module_search_path
1338 - prefix
1339 - exec_prefix
1340
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001341 If a field is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001342PyStatus
1343_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001344{
Victor Stinner331a6a52019-05-27 16:39:22 +02001345 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001346 PyCalculatePath calculate;
1347 memset(&calculate, 0, sizeof(calculate));
1348
Victor Stinner331a6a52019-05-27 16:39:22 +02001349 status = calculate_init(&calculate, config);
1350 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001351 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001352 }
1353
Victor Stinner3f5409a2019-09-23 19:50:27 +02001354 status = calculate_path(&calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001355 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001356 goto done;
1357 }
1358
Victor Stinner331a6a52019-05-27 16:39:22 +02001359 status = _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001360
Victor Stinner9316ee42017-11-25 03:17:57 +01001361done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001362 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001363 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001364}
Victor Stinner46972b72017-11-24 22:55:40 +01001365
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001366#ifdef __cplusplus
1367}
1368#endif