blob: 4246d4ca5ac0d52e46a63f7d18974a30495312e6 [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__
Victor Stinner0327bde2017-11-23 17:03:20 +010014# include <mach-o/dyld.h>
Guido van Rossum54ecc3d1999-01-27 17:53:11 +000015#endif
16
Guido van Rossum305e5d01997-04-11 17:18:45 +000017/* Search in some common locations for the associated Python libraries.
18 *
19 * Two directories must be found, the platform independent directory
Barry Warsaw90126031997-04-11 20:27:03 +000020 * (prefix), containing the common .py and .pyc files, and the platform
21 * dependent directory (exec_prefix), containing the shared library
22 * modules. Note that prefix and exec_prefix can be the same directory,
23 * but for some installations, they are different.
Guido van Rossum305e5d01997-04-11 17:18:45 +000024 *
Barry Warsaw90126031997-04-11 20:27:03 +000025 * Py_GetPath() carries out separate searches for prefix and exec_prefix.
26 * Each search tries a number of different locations until a ``landmark''
27 * file or directory is found. If no prefix or exec_prefix is found, a
28 * warning message is issued and the preprocessor defined PREFIX and
29 * EXEC_PREFIX are used (even though they will not work); python carries on
30 * as best as is possible, but most imports will fail.
Guido van Rossum305e5d01997-04-11 17:18:45 +000031 *
32 * Before any searches are done, the location of the executable is
Guido van Rossumd8faa362007-04-27 19:54:29 +000033 * determined. If argv[0] has one or more slashes in it, it is used
Barry Warsaw90126031997-04-11 20:27:03 +000034 * unchanged. Otherwise, it must have been invoked from the shell's path,
35 * so we search $PATH for the named executable and use that. If the
36 * executable was not found on $PATH (or there was no $PATH environment
37 * variable), the original argv[0] string is used.
Guido van Rossum305e5d01997-04-11 17:18:45 +000038 *
Barry Warsaw90126031997-04-11 20:27:03 +000039 * Next, the executable location is examined to see if it is a symbolic
40 * link. If so, the link is chased (correctly interpreting a relative
41 * pathname if one is found) and the directory of the link target is used.
Guido van Rossum305e5d01997-04-11 17:18:45 +000042 *
Barry Warsaw90126031997-04-11 20:27:03 +000043 * Finally, argv0_path is set to the directory containing the executable
44 * (i.e. the last component is stripped).
Guido van Rossum305e5d01997-04-11 17:18:45 +000045 *
Barry Warsaw90126031997-04-11 20:27:03 +000046 * With argv0_path in hand, we perform a number of steps. The same steps
47 * are performed for prefix and for exec_prefix, but with a different
48 * landmark.
Guido van Rossum305e5d01997-04-11 17:18:45 +000049 *
50 * Step 1. Are we running python out of the build directory? This is
51 * checked by looking for a different kind of landmark relative to
Barry Warsaw90126031997-04-11 20:27:03 +000052 * argv0_path. For prefix, the landmark's path is derived from the VPATH
53 * preprocessor variable (taking into account that its value is almost, but
54 * not quite, what we need). For exec_prefix, the landmark is
Antoine Pitroueba57b62010-08-14 12:33:18 +000055 * pybuilddir.txt. If the landmark is found, we're done.
Guido van Rossum305e5d01997-04-11 17:18:45 +000056 *
57 * For the remaining steps, the prefix landmark will always be
Jeremy Hylton847a9962000-05-26 21:49:07 +000058 * lib/python$VERSION/os.py and the exec_prefix will always be
Guido van Rossum266033e1997-10-20 23:20:32 +000059 * lib/python$VERSION/lib-dynload, where $VERSION is Python's version
Barry Warsaw90126031997-04-11 20:27:03 +000060 * number as supplied by the Makefile. Note that this means that no more
61 * build directory checking is performed; if the first step did not find
62 * the landmarks, the assumption is that python is running from an
63 * installed setup.
Guido van Rossum305e5d01997-04-11 17:18:45 +000064 *
65 * Step 2. See if the $PYTHONHOME environment variable points to the
Barry Warsaw90126031997-04-11 20:27:03 +000066 * installed location of the Python libraries. If $PYTHONHOME is set, then
67 * it points to prefix and exec_prefix. $PYTHONHOME can be a single
68 * directory, which is used for both, or the prefix and exec_prefix
69 * directories separated by a colon.
Guido van Rossum305e5d01997-04-11 17:18:45 +000070 *
71 * Step 3. Try to find prefix and exec_prefix relative to argv0_path,
Barry Warsaw90126031997-04-11 20:27:03 +000072 * backtracking up the path until it is exhausted. This is the most common
73 * step to succeed. Note that if prefix and exec_prefix are different,
74 * exec_prefix is more likely to be found; however if exec_prefix is a
75 * subdirectory of prefix, both will be found.
Guido van Rossum305e5d01997-04-11 17:18:45 +000076 *
Barry Warsaw90126031997-04-11 20:27:03 +000077 * Step 4. Search the directories pointed to by the preprocessor variables
78 * PREFIX and EXEC_PREFIX. These are supplied by the Makefile but can be
79 * passed in as options to the configure script.
Guido van Rossum305e5d01997-04-11 17:18:45 +000080 *
Barry Warsaw90126031997-04-11 20:27:03 +000081 * That's it!
82 *
83 * Well, almost. Once we have determined prefix and exec_prefix, the
Thomas Wouters7e474022000-07-16 12:04:32 +000084 * preprocessor variable PYTHONPATH is used to construct a path. Each
Barry Warsaw90126031997-04-11 20:27:03 +000085 * relative path on PYTHONPATH is prefixed with prefix. Then the directory
86 * containing the shared library modules is appended. The environment
87 * variable $PYTHONPATH is inserted in front of it all. Finally, the
88 * prefix and exec_prefix globals are tweaked so they reflect the values
89 * expected by other code, by stripping the "lib/python$VERSION/..." stuff
90 * off. If either points to the build directory, the globals are reset to
91 * the corresponding preprocessor variables (so sys.prefix will reflect the
92 * installation location, even though sys.path points into the build
93 * directory). This seems to make more sense given that currently the only
94 * known use of sys.prefix and sys.exec_prefix is for the ILU installation
95 * process to find the installed Python tree.
Antoine Pitroueba57b62010-08-14 12:33:18 +000096 *
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000097 * An embedding application can use Py_SetPath() to override all of
Min ho Kimc4cacc82019-07-31 08:16:13 +100098 * these automatic path computations.
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000099 *
Antoine Pitroueba57b62010-08-14 12:33:18 +0000100 * NOTE: Windows MSVC builds use PC/getpathp.c instead!
Barry Warsaw90126031997-04-11 20:27:03 +0000101 */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000102
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000103#ifdef __cplusplus
Victor Stinner0327bde2017-11-23 17:03:20 +0100104extern "C" {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000105#endif
106
107
Benjamin Petersonf5854142016-06-02 12:41:35 -0700108#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH)
109#error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000110#endif
Guido van Rossum667d7041995-08-04 04:20:48 +0000111
Guido van Rossum305e5d01997-04-11 17:18:45 +0000112#ifndef LANDMARK
Martin v. Löwis790465f2008-04-05 20:41:37 +0000113#define LANDMARK L"os.py"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000114#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000115
Victor Stinner9316ee42017-11-25 03:17:57 +0100116#define DECODE_LOCALE_ERR(NAME, LEN) \
117 ((LEN) == (size_t)-2) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200118 ? _PyStatus_ERR("cannot decode " NAME) \
119 : _PyStatus_NO_MEMORY()
Victor Stinner9316ee42017-11-25 03:17:57 +0100120
Victor Stinner331a6a52019-05-27 16:39:22 +0200121#define PATHLEN_ERR() _PyStatus_ERR("path configuration: path too long")
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100122
Victor Stinner0327bde2017-11-23 17:03:20 +0100123typedef struct {
124 wchar_t *path_env; /* PATH environment variable */
Victor Stinner0327bde2017-11-23 17:03:20 +0100125
Victor Stinner85ce0a72019-09-24 00:55:48 +0200126 wchar_t *pythonpath; /* PYTHONPATH macro */
127 wchar_t *prefix; /* PREFIX macro */
128 wchar_t *exec_prefix; /* EXEC_PREFIX macro */
Victor Stinner0327bde2017-11-23 17:03:20 +0100129
130 wchar_t *lib_python; /* "lib/pythonX.Y" */
Victor Stinner0327bde2017-11-23 17:03:20 +0100131
132 int prefix_found; /* found platform independent libraries? */
133 int exec_prefix_found; /* found the platform dependent libraries? */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200134
135 int warnings;
136 const wchar_t *pythonpath_env;
Victor Stinner0327bde2017-11-23 17:03:20 +0100137} PyCalculatePath;
138
139static const wchar_t delimiter[2] = {DELIM, '\0'};
140static const wchar_t separator[2] = {SEP, '\0'};
Victor Stinner0327bde2017-11-23 17:03:20 +0100141
Martin v. Löwis790465f2008-04-05 20:41:37 +0000142
Victor Stinner91afbb62015-03-24 12:16:28 +0100143/* Get file status. Encode the path to the locale encoding. */
Victor Stinner91afbb62015-03-24 12:16:28 +0100144static int
145_Py_wstat(const wchar_t* path, struct stat *buf)
146{
147 int err;
148 char *fname;
Victor Stinner9dd76202017-12-21 16:20:32 +0100149 fname = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner91afbb62015-03-24 12:16:28 +0100150 if (fname == NULL) {
151 errno = EINVAL;
152 return -1;
153 }
154 err = stat(fname, buf);
Victor Stinner9dd76202017-12-21 16:20:32 +0100155 PyMem_RawFree(fname);
Victor Stinner91afbb62015-03-24 12:16:28 +0100156 return err;
157}
158
Victor Stinner0327bde2017-11-23 17:03:20 +0100159
Guido van Rossum305e5d01997-04-11 17:18:45 +0000160static void
Martin v. Löwis790465f2008-04-05 20:41:37 +0000161reduce(wchar_t *dir)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000162{
Martin v. Löwis790465f2008-04-05 20:41:37 +0000163 size_t i = wcslen(dir);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100164 while (i > 0 && dir[i] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000165 --i;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100166 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000167 dir[i] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +0000168}
Guido van Rossumd29806c1998-01-19 22:06:22 +0000169
Victor Stinner0327bde2017-11-23 17:03:20 +0100170
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100171/* Is file, not directory */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000172static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100173isfile(const wchar_t *filename)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000174{
Fred Drakeedabdc12000-07-08 06:16:37 +0000175 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100176 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000177 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100178 }
179 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000180 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100181 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000182 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000183}
184
185
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100186/* Is module -- check for .pyc too */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000187static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100188ismodule(wchar_t *filename, size_t filename_len)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000189{
Victor Stinner0327bde2017-11-23 17:03:20 +0100190 if (isfile(filename)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000191 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100192 }
Guido van Rossumd29806c1998-01-19 22:06:22 +0000193
Fred Drakeedabdc12000-07-08 06:16:37 +0000194 /* Check for the compiled version of prefix. */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100195 if (wcslen(filename) + 2 <= filename_len) {
Brett Cannonf299abd2015-04-13 14:21:02 -0400196 wcscat(filename, L"c");
Victor Stinner0327bde2017-11-23 17:03:20 +0100197 if (isfile(filename)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000198 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100199 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000200 }
201 return 0;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000202}
203
204
Victor Stinner0327bde2017-11-23 17:03:20 +0100205/* Is executable file */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000206static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100207isxfile(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000208{
Fred Drakeedabdc12000-07-08 06:16:37 +0000209 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100210 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000211 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100212 }
213 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000214 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100215 }
216 if ((buf.st_mode & 0111) == 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000217 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100218 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000219 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000220}
221
222
Victor Stinner0327bde2017-11-23 17:03:20 +0100223/* Is directory */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000224static int
Victor Stinner0327bde2017-11-23 17:03:20 +0100225isdir(wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000226{
Fred Drakeedabdc12000-07-08 06:16:37 +0000227 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100228 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000229 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100230 }
231 if (!S_ISDIR(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000232 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100233 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000234 return 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000235}
236
237
Tim Petersec8c5a92004-08-08 01:00:47 +0000238/* Add a path component, by appending stuff to buffer.
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100239 buflen: 'buffer' length in characters including trailing NUL. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200240static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100241joinpath(wchar_t *buffer, const wchar_t *stuff, size_t buflen)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000242{
Fred Drakeedabdc12000-07-08 06:16:37 +0000243 size_t n, k;
Victor Stinner3939c322019-06-25 15:02:43 +0200244 if (!_Py_isabs(stuff)) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000245 n = wcslen(buffer);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100246 if (n >= buflen) {
247 return PATHLEN_ERR();
248 }
249
250 if (n > 0 && buffer[n-1] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000251 buffer[n++] = SEP;
Victor Stinner0327bde2017-11-23 17:03:20 +0100252 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000253 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100254 else {
255 n = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100256 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100257
Martin v. Löwis790465f2008-04-05 20:41:37 +0000258 k = wcslen(stuff);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100259 if (n + k >= buflen) {
260 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100261 }
Martin v. Löwis790465f2008-04-05 20:41:37 +0000262 wcsncpy(buffer+n, stuff, k);
Fred Drakeedabdc12000-07-08 06:16:37 +0000263 buffer[n+k] = '\0';
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100264
Victor Stinner331a6a52019-05-27 16:39:22 +0200265 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000266}
267
Victor Stinner0327bde2017-11-23 17:03:20 +0100268
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100269static inline int
270safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
271{
272 size_t srclen = wcslen(src);
273 if (n <= srclen) {
274 dst[0] = L'\0';
275 return -1;
276 }
277 memcpy(dst, src, (srclen + 1) * sizeof(wchar_t));
278 return 0;
279}
280
281
Guido van Rossume296ced2001-09-28 20:00:29 +0000282/* copy_absolute requires that path be allocated at least
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100283 'pathlen' characters (including trailing NUL). */
Victor Stinner331a6a52019-05-27 16:39:22 +0200284static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100285copy_absolute(wchar_t *path, const wchar_t *p, size_t pathlen)
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000286{
Victor Stinner3939c322019-06-25 15:02:43 +0200287 if (_Py_isabs(p)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100288 if (safe_wcscpy(path, p, pathlen) < 0) {
289 return PATHLEN_ERR();
290 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100291 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000292 else {
Victor Stinnerf4061da2010-10-14 12:37:19 +0000293 if (!_Py_wgetcwd(path, pathlen)) {
Victor Stinner4f3abb02010-10-07 23:29:18 +0000294 /* unable to get the current directory */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100295 if (safe_wcscpy(path, p, pathlen) < 0) {
296 return PATHLEN_ERR();
297 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200298 return _PyStatus_OK();
Victor Stinner4f3abb02010-10-07 23:29:18 +0000299 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100300 if (p[0] == '.' && p[1] == SEP) {
Guido van Rossume296ced2001-09-28 20:00:29 +0000301 p += 2;
Victor Stinner0327bde2017-11-23 17:03:20 +0100302 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200303 PyStatus status = joinpath(path, p, pathlen);
304 if (_PyStatus_EXCEPTION(status)) {
305 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100306 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000307 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200308 return _PyStatus_OK();
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000309}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000310
Victor Stinner0327bde2017-11-23 17:03:20 +0100311
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100312/* path_len: path length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200313static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100314absolutize(wchar_t *path, size_t path_len)
Guido van Rossume296ced2001-09-28 20:00:29 +0000315{
Victor Stinner3939c322019-06-25 15:02:43 +0200316 if (_Py_isabs(path)) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200317 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100318 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100319
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100320 wchar_t abs_path[MAXPATHLEN+1];
Victor Stinner331a6a52019-05-27 16:39:22 +0200321 PyStatus status = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path));
322 if (_PyStatus_EXCEPTION(status)) {
323 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100324 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100325
326 if (safe_wcscpy(path, abs_path, path_len) < 0) {
327 return PATHLEN_ERR();
328 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200329 return _PyStatus_OK();
Guido van Rossume296ced2001-09-28 20:00:29 +0000330}
331
Victor Stinner0327bde2017-11-23 17:03:20 +0100332
E. M. Bray7a7693e2018-10-05 13:38:50 +0200333#if defined(__CYGWIN__) || defined(__MINGW32__)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200334#ifndef EXE_SUFFIX
335#define EXE_SUFFIX L".exe"
336#endif
337
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100338/* pathlen: 'path' length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200339static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100340add_exe_suffix(wchar_t *progpath, size_t progpathlen)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200341{
342 /* Check for already have an executable suffix */
343 size_t n = wcslen(progpath);
344 size_t s = wcslen(EXE_SUFFIX);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100345 if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200346 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200347 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100348
349 if (n + s >= progpathlen) {
350 return PATHLEN_ERR();
351 }
352 wcsncpy(progpath + n, EXE_SUFFIX, s);
353 progpath[n+s] = '\0';
354
355 if (!isxfile(progpath)) {
356 /* Path that added suffix is invalid: truncate (remove suffix) */
357 progpath[n] = '\0';
358 }
359
Victor Stinner331a6a52019-05-27 16:39:22 +0200360 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200361}
362#endif
363
364
Guido van Rossume296ced2001-09-28 20:00:29 +0000365/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000366 bytes long.
367*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200368static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200369search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200370 const wchar_t *argv0_path,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200371 wchar_t *prefix, size_t prefix_len, int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000372{
Victor Stinner221fd842019-09-25 02:54:25 +0200373 wchar_t path[MAXPATHLEN+1];
374 memset(path, 0, sizeof(path));
375 size_t path_len = Py_ARRAY_LENGTH(path);
376
Victor Stinner331a6a52019-05-27 16:39:22 +0200377 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000378
Fred Drakeedabdc12000-07-08 06:16:37 +0000379 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200380 if (pathconfig->home) {
Victor Stinner221fd842019-09-25 02:54:25 +0200381 /* Path: <home> / <lib_python> */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200382 if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100383 return PATHLEN_ERR();
384 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100385 wchar_t *delim = wcschr(prefix, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100386 if (delim) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000387 *delim = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100388 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200389 status = joinpath(prefix, calculate->lib_python, prefix_len);
390 if (_PyStatus_EXCEPTION(status)) {
391 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100392 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100393 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200394 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000395 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000396
Fred Drakeedabdc12000-07-08 06:16:37 +0000397 /* Check to see if argv[0] is in the build directory */
Victor Stinner221fd842019-09-25 02:54:25 +0200398 if (safe_wcscpy(path, argv0_path, path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100399 return PATHLEN_ERR();
400 }
Victor Stinner221fd842019-09-25 02:54:25 +0200401 status = joinpath(path, L"Modules/Setup.local", path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200402 if (_PyStatus_EXCEPTION(status)) {
403 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100404 }
405
Victor Stinner221fd842019-09-25 02:54:25 +0200406 if (isfile(path)) {
407 /* Check VPATH to see if argv0_path is in the build directory.
408 VPATH can be empty. */
409 wchar_t *vpath = Py_DecodeLocale(VPATH, NULL);
Victor Stinner21582312010-10-23 00:13:28 +0000410 if (vpath != NULL) {
Victor Stinner221fd842019-09-25 02:54:25 +0200411 /* Path: <argv0_path> / <vpath> / Lib / LANDMARK */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200412 if (safe_wcscpy(prefix, argv0_path, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100413 return PATHLEN_ERR();
414 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200415 status = joinpath(prefix, vpath, prefix_len);
Victor Stinner1a7425f2013-07-07 16:25:15 +0200416 PyMem_RawFree(vpath);
Victor Stinner331a6a52019-05-27 16:39:22 +0200417 if (_PyStatus_EXCEPTION(status)) {
418 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100419 }
420
Victor Stinner331a6a52019-05-27 16:39:22 +0200421 status = joinpath(prefix, L"Lib", prefix_len);
422 if (_PyStatus_EXCEPTION(status)) {
423 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100424 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200425 status = joinpath(prefix, LANDMARK, prefix_len);
426 if (_PyStatus_EXCEPTION(status)) {
427 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100428 }
429
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100430 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100431 *found = -1;
Victor Stinner221fd842019-09-25 02:54:25 +0200432 reduce(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200433 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100434 }
Victor Stinner21582312010-10-23 00:13:28 +0000435 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000436 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000437
Fred Drakeedabdc12000-07-08 06:16:37 +0000438 /* Search from argv0_path, until root is found */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200439 status = copy_absolute(prefix, argv0_path, prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200440 if (_PyStatus_EXCEPTION(status)) {
441 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100442 }
443
Fred Drakeedabdc12000-07-08 06:16:37 +0000444 do {
Victor Stinner221fd842019-09-25 02:54:25 +0200445 /* Path: <argv0_path or substring> / <lib_python> / LANDMARK */
446 size_t n = wcslen(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200447 status = joinpath(prefix, calculate->lib_python, prefix_len);
448 if (_PyStatus_EXCEPTION(status)) {
449 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100450 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200451 status = joinpath(prefix, LANDMARK, prefix_len);
452 if (_PyStatus_EXCEPTION(status)) {
453 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100454 }
455
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100456 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100457 *found = 1;
Victor Stinner221fd842019-09-25 02:54:25 +0200458 reduce(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200459 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100460 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100461 prefix[n] = L'\0';
462 reduce(prefix);
463 } while (prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000464
Victor Stinner221fd842019-09-25 02:54:25 +0200465 /* Look at configure's PREFIX.
466 Path: <PREFIX macro> / <lib_python> / LANDMARK */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100467 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
468 return PATHLEN_ERR();
469 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200470 status = joinpath(prefix, calculate->lib_python, prefix_len);
471 if (_PyStatus_EXCEPTION(status)) {
472 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100473 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200474 status = joinpath(prefix, LANDMARK, prefix_len);
475 if (_PyStatus_EXCEPTION(status)) {
476 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100477 }
478
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100479 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100480 *found = 1;
Victor Stinner221fd842019-09-25 02:54:25 +0200481 reduce(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200482 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100483 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000484
Fred Drakeedabdc12000-07-08 06:16:37 +0000485 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100486 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200487 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000488}
489
490
Victor Stinner331a6a52019-05-27 16:39:22 +0200491static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200492calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200493 const wchar_t *argv0_path,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200494 wchar_t *prefix, size_t prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100495{
Victor Stinner331a6a52019-05-27 16:39:22 +0200496 PyStatus status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100497
Victor Stinner85ce0a72019-09-24 00:55:48 +0200498 status = search_for_prefix(calculate, pathconfig, argv0_path,
499 prefix, prefix_len,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200500 &calculate->prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200501 if (_PyStatus_EXCEPTION(status)) {
502 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100503 }
504
Victor Stinner0327bde2017-11-23 17:03:20 +0100505 if (!calculate->prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200506 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100507 fprintf(stderr,
508 "Could not find platform independent libraries <prefix>\n");
509 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100510 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
511 return PATHLEN_ERR();
512 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200513 status = joinpath(prefix, calculate->lib_python, prefix_len);
514 if (_PyStatus_EXCEPTION(status)) {
515 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100516 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100517 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200518 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100519}
520
521
Victor Stinner331a6a52019-05-27 16:39:22 +0200522static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200523calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
524 wchar_t *prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +0100525{
526 /* Reduce prefix and exec_prefix to their essence,
527 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
528 * If we're loading relative to the build directory,
529 * return the compiled-in defaults instead.
530 */
531 if (calculate->prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100532 reduce(prefix);
533 reduce(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100534 /* The prefix is the root directory, but reduce() chopped
535 * off the "/". */
Victor Stinner9316ee42017-11-25 03:17:57 +0100536 if (!prefix[0]) {
537 wcscpy(prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100538 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200539 pathconfig->prefix = _PyMem_RawWcsdup(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100540 }
541 else {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200542 pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix);
543 }
544
545 if (pathconfig->prefix == NULL) {
546 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100547 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200548 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100549}
550
551
Victor Stinner221fd842019-09-25 02:54:25 +0200552static PyStatus
553calculate_pybuilddir(const wchar_t *argv0_path,
554 wchar_t *exec_prefix, size_t exec_prefix_len,
555 int *found)
556{
557 PyStatus status;
558
559 wchar_t filename[MAXPATHLEN+1];
560 memset(filename, 0, sizeof(filename));
561 size_t filename_len = Py_ARRAY_LENGTH(filename);
562
563 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
564 is written by setup.py and contains the relative path to the location
565 of shared library modules.
566
567 Filename: <argv0_path> / "pybuilddir.txt" */
568 if (safe_wcscpy(filename, argv0_path, filename_len) < 0) {
569 return PATHLEN_ERR();
570 }
571 status = joinpath(filename, L"pybuilddir.txt", filename_len);
572 if (_PyStatus_EXCEPTION(status)) {
573 return status;
574 }
575
576 if (!isfile(filename)) {
577 return _PyStatus_OK();
578 }
579
580 FILE *fp = _Py_wfopen(filename, L"rb");
581 if (fp == NULL) {
582 errno = 0;
583 return _PyStatus_OK();
584 }
585
586 char buf[MAXPATHLEN + 1];
587 size_t n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, fp);
588 buf[n] = '\0';
589 fclose(fp);
590
591 size_t dec_len;
592 wchar_t *pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
593 if (!pybuilddir) {
594 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
595 }
596
597 /* Path: <argv0_path> / <pybuilddir content> */
598 if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) {
599 PyMem_RawFree(pybuilddir);
600 return PATHLEN_ERR();
601 }
602 status = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
603 PyMem_RawFree(pybuilddir);
604 if (_PyStatus_EXCEPTION(status)) {
605 return status;
606 }
607
608 *found = -1;
609 return _PyStatus_OK();
610}
611
612
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000613/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000614 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000615*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200616static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200617search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200618 const wchar_t *argv0_path,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100619 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100620 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000621{
Victor Stinner331a6a52019-05-27 16:39:22 +0200622 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000623
Fred Drakeedabdc12000-07-08 06:16:37 +0000624 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200625 if (pathconfig->home) {
Victor Stinner221fd842019-09-25 02:54:25 +0200626 /* Path: <home> / <lib_python> / "lib-dynload" */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200627 wchar_t *delim = wcschr(pathconfig->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100628 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100629 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
630 return PATHLEN_ERR();
631 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100632 }
633 else {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200634 if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100635 return PATHLEN_ERR();
636 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100637 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200638 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
639 if (_PyStatus_EXCEPTION(status)) {
640 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100641 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200642 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
643 if (_PyStatus_EXCEPTION(status)) {
644 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100645 }
646 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200647 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000648 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000649
Victor Stinner221fd842019-09-25 02:54:25 +0200650 /* Check for pybuilddir.txt */
651 assert(*found == 0);
652 status = calculate_pybuilddir(argv0_path, exec_prefix, exec_prefix_len,
653 found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200654 if (_PyStatus_EXCEPTION(status)) {
655 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100656 }
Victor Stinner221fd842019-09-25 02:54:25 +0200657 if (*found) {
658 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000659 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000660
Fred Drakeedabdc12000-07-08 06:16:37 +0000661 /* Search from argv0_path, until root is found */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200662 status = copy_absolute(exec_prefix, argv0_path, exec_prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200663 if (_PyStatus_EXCEPTION(status)) {
664 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100665 }
666
Fred Drakeedabdc12000-07-08 06:16:37 +0000667 do {
Victor Stinner221fd842019-09-25 02:54:25 +0200668 /* Path: <argv0_path or substring> / <lib_python> / "lib-dynload" */
669 size_t n = wcslen(exec_prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200670 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
671 if (_PyStatus_EXCEPTION(status)) {
672 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100673 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200674 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
675 if (_PyStatus_EXCEPTION(status)) {
676 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100677 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100678 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100679 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200680 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100681 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100682 exec_prefix[n] = L'\0';
683 reduce(exec_prefix);
684 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000685
Victor Stinner221fd842019-09-25 02:54:25 +0200686 /* Look at configure's EXEC_PREFIX.
687
688 Path: <EXEC_PREFIX macro> / <lib_python> / "lib-dynload" */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100689 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
690 return PATHLEN_ERR();
691 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200692 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
693 if (_PyStatus_EXCEPTION(status)) {
694 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100695 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200696 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
697 if (_PyStatus_EXCEPTION(status)) {
698 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100699 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100700 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100701 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200702 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100703 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000704
Fred Drakeedabdc12000-07-08 06:16:37 +0000705 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100706 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200707 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000708}
709
Guido van Rossum305e5d01997-04-11 17:18:45 +0000710
Victor Stinner331a6a52019-05-27 16:39:22 +0200711static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200712calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200713 const wchar_t *argv0_path,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100714 wchar_t *exec_prefix, size_t exec_prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100715{
Victor Stinner331a6a52019-05-27 16:39:22 +0200716 PyStatus status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100717
Victor Stinner85ce0a72019-09-24 00:55:48 +0200718 status = search_for_exec_prefix(calculate, pathconfig, argv0_path,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200719 exec_prefix, exec_prefix_len,
720 &calculate->exec_prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200721 if (_PyStatus_EXCEPTION(status)) {
722 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100723 }
724
Victor Stinner0327bde2017-11-23 17:03:20 +0100725 if (!calculate->exec_prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200726 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100727 fprintf(stderr,
728 "Could not find platform dependent libraries <exec_prefix>\n");
729 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100730 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
731 return PATHLEN_ERR();
732 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200733 status = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len);
734 if (_PyStatus_EXCEPTION(status)) {
735 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100736 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100737 }
738 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
Victor Stinner331a6a52019-05-27 16:39:22 +0200739 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100740}
741
742
Victor Stinner331a6a52019-05-27 16:39:22 +0200743static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200744calculate_set_exec_prefix(PyCalculatePath *calculate,
745 _PyPathConfig *pathconfig,
746 wchar_t *exec_prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +0100747{
748 if (calculate->exec_prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100749 reduce(exec_prefix);
750 reduce(exec_prefix);
751 reduce(exec_prefix);
752 if (!exec_prefix[0]) {
753 wcscpy(exec_prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100754 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200755
756 pathconfig->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100757 }
758 else {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200759 pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100760 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200761
762 if (pathconfig->exec_prefix == NULL) {
763 return _PyStatus_NO_MEMORY();
764 }
765
Victor Stinner331a6a52019-05-27 16:39:22 +0200766 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100767}
768
769
Victor Stinner331a6a52019-05-27 16:39:22 +0200770static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200771calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100772{
Victor Stinner331a6a52019-05-27 16:39:22 +0200773 PyStatus status;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100774 wchar_t program_full_path[MAXPATHLEN + 1];
775 const size_t program_full_path_len = Py_ARRAY_LENGTH(program_full_path);
Victor Stinnerb64de462017-12-01 18:27:09 +0100776 memset(program_full_path, 0, sizeof(program_full_path));
Victor Stinner9316ee42017-11-25 03:17:57 +0100777
Victor Stinnerb9197952017-11-23 19:02:04 +0100778#ifdef __APPLE__
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100779 char execpath[MAXPATHLEN + 1];
Victor Stinnerb9197952017-11-23 19:02:04 +0100780#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100781 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100782#else
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100783 unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100784#endif
Victor Stinnerb9197952017-11-23 19:02:04 +0100785#endif
786
Victor Stinner0327bde2017-11-23 17:03:20 +0100787 /* If there is no slash in the argv0 path, then we have to
788 * assume python is on the user's $PATH, since there's no
789 * other way to find a directory to start the search from. If
790 * $PATH isn't exported, you lose.
791 */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200792 if (wcschr(pathconfig->program_name, SEP)) {
793 if (safe_wcscpy(program_full_path, pathconfig->program_name,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100794 program_full_path_len) < 0) {
795 return PATHLEN_ERR();
796 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100797 }
Jack Jansen1afd4802004-06-03 14:33:03 +0000798#ifdef __APPLE__
Jack Jansen1afd4802004-06-03 14:33:03 +0000799 /* On Mac OS X, if a script uses an interpreter of the form
800 * "#!/opt/python2.3/bin/python", the kernel only passes "python"
801 * as argv[0], which falls through to the $PATH search below.
802 * If /opt/python2.3/bin isn't in your path, or is near the end,
803 * this algorithm may incorrectly find /usr/bin/python. To work
804 * around this, we can use _NSGetExecutablePath to get a better
805 * hint of what the intended interpreter was, although this
806 * will fail if a relative path was used. but in that case,
807 * absolutize() should help us out below
808 */
Victor Stinnerf04ebe22017-11-25 00:01:23 +0100809 else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
Victor Stinner30290352019-06-28 16:49:38 +0200810 (wchar_t)execpath[0] == SEP)
Victor Stinnerf04ebe22017-11-25 00:01:23 +0100811 {
Victor Stinner31a83932017-12-04 13:39:15 +0100812 size_t len;
813 wchar_t *path = Py_DecodeLocale(execpath, &len);
814 if (path == NULL) {
815 return DECODE_LOCALE_ERR("executable path", len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000816 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100817 if (safe_wcscpy(program_full_path, path, program_full_path_len) < 0) {
818 PyMem_RawFree(path);
819 return PATHLEN_ERR();
820 }
Victor Stinner31a83932017-12-04 13:39:15 +0100821 PyMem_RawFree(path);
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000822 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000823#endif /* __APPLE__ */
Victor Stinner0327bde2017-11-23 17:03:20 +0100824 else if (calculate->path_env) {
825 wchar_t *path = calculate->path_env;
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000826 while (1) {
827 wchar_t *delim = wcschr(path, DELIM);
Jack Jansen55070f52001-12-02 23:56:28 +0000828
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000829 if (delim) {
830 size_t len = delim - path;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100831 if (len >= program_full_path_len) {
832 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100833 }
Victor Stinnerb64de462017-12-01 18:27:09 +0100834 wcsncpy(program_full_path, path, len);
835 program_full_path[len] = '\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000836 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100837 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100838 if (safe_wcscpy(program_full_path, path,
839 program_full_path_len) < 0) {
840 return PATHLEN_ERR();
841 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100842 }
Jack Jansen55070f52001-12-02 23:56:28 +0000843
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200844 status = joinpath(program_full_path, pathconfig->program_name,
845 program_full_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200846 if (_PyStatus_EXCEPTION(status)) {
847 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100848 }
849
Victor Stinnerb64de462017-12-01 18:27:09 +0100850 if (isxfile(program_full_path)) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000851 break;
Victor Stinner0327bde2017-11-23 17:03:20 +0100852 }
Jack Jansen55070f52001-12-02 23:56:28 +0000853
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000854 if (!delim) {
Victor Stinnerb64de462017-12-01 18:27:09 +0100855 program_full_path[0] = L'\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000856 break;
857 }
858 path = delim + 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000859 }
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000860 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100861 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100862 program_full_path[0] = '\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100863 }
Victor Stinner3939c322019-06-25 15:02:43 +0200864 if (!_Py_isabs(program_full_path) && program_full_path[0] != '\0') {
Victor Stinner331a6a52019-05-27 16:39:22 +0200865 status = absolutize(program_full_path, program_full_path_len);
866 if (_PyStatus_EXCEPTION(status)) {
867 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100868 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100869 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200870#if defined(__CYGWIN__) || defined(__MINGW32__)
871 /* For these platforms it is necessary to ensure that the .exe suffix
872 * is appended to the filename, otherwise there is potential for
873 * sys.executable to return the name of a directory under the same
874 * path (bpo-28441).
875 */
876 if (program_full_path[0] != '\0') {
Victor Stinner331a6a52019-05-27 16:39:22 +0200877 status = add_exe_suffix(program_full_path, program_full_path_len);
878 if (_PyStatus_EXCEPTION(status)) {
879 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100880 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200881 }
882#endif
Victor Stinner9316ee42017-11-25 03:17:57 +0100883
Victor Stinner331a6a52019-05-27 16:39:22 +0200884 pathconfig->program_full_path = _PyMem_RawWcsdup(program_full_path);
885 if (pathconfig->program_full_path == NULL) {
886 return _PyStatus_NO_MEMORY();
Victor Stinner9316ee42017-11-25 03:17:57 +0100887 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200888 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100889}
890
891
Victor Stinner331a6a52019-05-27 16:39:22 +0200892static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200893calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path,
894 wchar_t *argv0_path, size_t argv0_path_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100895{
Victor Stinner85ce0a72019-09-24 00:55:48 +0200896 if (safe_wcscpy(argv0_path, program_full_path, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100897 return PATHLEN_ERR();
898 }
Jack Jansen55070f52001-12-02 23:56:28 +0000899
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000900#ifdef WITH_NEXT_FRAMEWORK
Victor Stinner0327bde2017-11-23 17:03:20 +0100901 NSModule pythonModule;
902
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000903 /* On Mac OS X we have a special case if we're running from a framework.
904 ** This is because the python home should be set relative to the library,
905 ** which is in the framework, not relative to the executable, which may
906 ** be outside of the framework. Except when we're in the build directory...
907 */
Fred Drakeedabdc12000-07-08 06:16:37 +0000908 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
909 /* Use dylib functions to find out where the framework was loaded from */
Victor Stinner0327bde2017-11-23 17:03:20 +0100910 const char* modPath = NSLibraryNameForModule(pythonModule);
Vinay Sajip90db6612012-07-17 17:33:46 +0100911 if (modPath != NULL) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000912 /* We're in a framework. */
Jack Jansene925faf2001-08-15 01:14:40 +0000913 /* See if we might be in the build directory. The framework in the
914 ** build directory is incomplete, it only has the .dylib and a few
915 ** needed symlinks, it doesn't have the Lib directories and such.
916 ** If we're running with the framework from the build directory we must
917 ** be running the interpreter in the build directory, so we use the
918 ** build-directory-specific logic to find Lib and such.
919 */
Victor Stinner331a6a52019-05-27 16:39:22 +0200920 PyStatus status;
Victor Stinner9316ee42017-11-25 03:17:57 +0100921 size_t len;
922 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100923 if (wbuf == NULL) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100924 return DECODE_LOCALE_ERR("framework location", len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100925 }
926
Victor Stinner85ce0a72019-09-24 00:55:48 +0200927 if (safe_wcscpy(argv0_path, wbuf, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100928 return PATHLEN_ERR();
929 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200930 reduce(argv0_path);
931 status = joinpath(argv0_path, calculate->lib_python, argv0_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200932 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100933 PyMem_RawFree(wbuf);
Victor Stinner331a6a52019-05-27 16:39:22 +0200934 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100935 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200936 status = joinpath(argv0_path, LANDMARK, argv0_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200937 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100938 PyMem_RawFree(wbuf);
Victor Stinner331a6a52019-05-27 16:39:22 +0200939 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100940 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200941 if (!ismodule(argv0_path, Py_ARRAY_LENGTH(argv0_path))) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000942 /* We are in the build directory so use the name of the
943 executable - we know that the absolute path is passed */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200944 if (safe_wcscpy(argv0_path, program_full_path,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100945 argv0_path_len) < 0) {
946 return PATHLEN_ERR();
947 }
Jack Jansene925faf2001-08-15 01:14:40 +0000948 }
949 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100950 /* Use the location of the library as the program_full_path */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200951 if (safe_wcscpy(argv0_path, wbuf, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100952 return PATHLEN_ERR();
953 }
Jack Jansene925faf2001-08-15 01:14:40 +0000954 }
Victor Stinner1a7425f2013-07-07 16:25:15 +0200955 PyMem_RawFree(wbuf);
Fred Drakeedabdc12000-07-08 06:16:37 +0000956 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000957#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000958
Guido van Rossum305e5d01997-04-11 17:18:45 +0000959#if HAVE_READLINK
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100960 wchar_t tmpbuffer[MAXPATHLEN + 1];
961 const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
962 int linklen = _Py_wreadlink(program_full_path, tmpbuffer, buflen);
Victor Stinner0327bde2017-11-23 17:03:20 +0100963 while (linklen != -1) {
Victor Stinner3939c322019-06-25 15:02:43 +0200964 if (_Py_isabs(tmpbuffer)) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100965 /* tmpbuffer should never be longer than MAXPATHLEN,
966 but extra check does not hurt */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200967 if (safe_wcscpy(argv0_path, tmpbuffer, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100968 return PATHLEN_ERR();
969 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000970 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100971 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100972 /* Interpret relative to program_full_path */
Victor Stinner331a6a52019-05-27 16:39:22 +0200973 PyStatus status;
Victor Stinner85ce0a72019-09-24 00:55:48 +0200974 reduce(argv0_path);
975 status = joinpath(argv0_path, tmpbuffer, argv0_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200976 if (_PyStatus_EXCEPTION(status)) {
977 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100978 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100979 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200980 linklen = _Py_wreadlink(argv0_path, tmpbuffer, buflen);
Fred Drakeedabdc12000-07-08 06:16:37 +0000981 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000982#endif /* HAVE_READLINK */
983
Victor Stinner85ce0a72019-09-24 00:55:48 +0200984 reduce(argv0_path);
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000985 /* At this point, argv0_path is guaranteed to be less than
Victor Stinner0327bde2017-11-23 17:03:20 +0100986 MAXPATHLEN bytes long. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200987 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100988}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000989
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100990
Victor Stinner0327bde2017-11-23 17:03:20 +0100991/* Search for an "pyvenv.cfg" environment configuration file, first in the
992 executable's directory and then in the parent directory.
993 If found, open it for use when searching for prefixes.
994*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200995static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200996calculate_read_pyenv(PyCalculatePath *calculate,
997 wchar_t *argv0_path, size_t argv0_path_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100998{
Victor Stinner331a6a52019-05-27 16:39:22 +0200999 PyStatus status;
Victor Stinner221fd842019-09-25 02:54:25 +02001000 const wchar_t *env_cfg = L"pyvenv.cfg";
Victor Stinner0327bde2017-11-23 17:03:20 +01001001 FILE *env_file;
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001002
Victor Stinner221fd842019-09-25 02:54:25 +02001003 wchar_t filename[MAXPATHLEN+1];
1004 const size_t filename_len = Py_ARRAY_LENGTH(filename);
1005 memset(filename, 0, sizeof(filename));
1006
1007 /* Filename: <argv0_path_len> / "pyvenv.cfg" */
1008 if (safe_wcscpy(filename, argv0_path, filename_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001009 return PATHLEN_ERR();
1010 }
Vinay Sajip90db6612012-07-17 17:33:46 +01001011
Victor Stinner221fd842019-09-25 02:54:25 +02001012 status = joinpath(filename, env_cfg, filename_len);
Victor Stinner331a6a52019-05-27 16:39:22 +02001013 if (_PyStatus_EXCEPTION(status)) {
1014 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001015 }
Victor Stinner221fd842019-09-25 02:54:25 +02001016 env_file = _Py_wfopen(filename, L"r");
Victor Stinner0327bde2017-11-23 17:03:20 +01001017 if (env_file == NULL) {
1018 errno = 0;
1019
Victor Stinner221fd842019-09-25 02:54:25 +02001020 /* Filename: <basename(basename(argv0_path_len))> / "pyvenv.cfg" */
1021 reduce(filename);
1022 reduce(filename);
1023 status = joinpath(filename, env_cfg, filename_len);
Victor Stinner331a6a52019-05-27 16:39:22 +02001024 if (_PyStatus_EXCEPTION(status)) {
1025 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001026 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001027
Victor Stinner221fd842019-09-25 02:54:25 +02001028 env_file = _Py_wfopen(filename, L"r");
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001029 if (env_file == NULL) {
1030 errno = 0;
Victor Stinner221fd842019-09-25 02:54:25 +02001031 return _PyStatus_OK();
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001032 }
1033 }
1034
Victor Stinner0327bde2017-11-23 17:03:20 +01001035 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinner221fd842019-09-25 02:54:25 +02001036 wchar_t home[MAXPATHLEN+1];
1037 memset(home, 0, sizeof(home));
1038
1039 if (_Py_FindEnvConfigValue(env_file, L"home",
1040 home, Py_ARRAY_LENGTH(home))) {
1041 if (safe_wcscpy(argv0_path, home, argv0_path_len) < 0) {
1042 fclose(env_file);
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001043 return PATHLEN_ERR();
1044 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001045 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001046 fclose(env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001047 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001048}
Just van Rossum52e14d62002-12-30 22:08:05 +00001049
Guido van Rossum305e5d01997-04-11 17:18:45 +00001050
Victor Stinner331a6a52019-05-27 16:39:22 +02001051static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +02001052calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix,
1053 wchar_t *zip_path, size_t zip_path_len)
Victor Stinner0327bde2017-11-23 17:03:20 +01001054{
Victor Stinner331a6a52019-05-27 16:39:22 +02001055 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001056
Victor Stinner0327bde2017-11-23 17:03:20 +01001057 if (calculate->prefix_found > 0) {
1058 /* Use the reduced prefix returned by Py_GetPrefix() */
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001059 if (safe_wcscpy(zip_path, prefix, zip_path_len) < 0) {
1060 return PATHLEN_ERR();
1061 }
Victor Stinner85ce0a72019-09-24 00:55:48 +02001062 reduce(zip_path);
1063 reduce(zip_path);
Victor Stinnerd4341102017-11-23 00:12:09 +01001064 }
1065 else {
Victor Stinner85ce0a72019-09-24 00:55:48 +02001066 if (safe_wcscpy(zip_path, calculate->prefix, zip_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001067 return PATHLEN_ERR();
1068 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001069 }
Victor Stinner85ce0a72019-09-24 00:55:48 +02001070 status = joinpath(zip_path, L"lib/python00.zip", zip_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +02001071 if (_PyStatus_EXCEPTION(status)) {
1072 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001073 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001074
1075 /* Replace "00" with version */
Victor Stinner85ce0a72019-09-24 00:55:48 +02001076 size_t bufsz = wcslen(zip_path);
1077 zip_path[bufsz - 6] = VERSION[0];
1078 zip_path[bufsz - 5] = VERSION[2];
Victor Stinner331a6a52019-05-27 16:39:22 +02001079 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001080}
1081
1082
Victor Stinner331a6a52019-05-27 16:39:22 +02001083static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001084calculate_module_search_path(PyCalculatePath *calculate,
1085 _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +02001086 const wchar_t *prefix,
1087 const wchar_t *exec_prefix,
1088 const wchar_t *zip_path)
Victor Stinner0327bde2017-11-23 17:03:20 +01001089{
1090 /* Calculate size of return buffer */
1091 size_t bufsz = 0;
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001092 if (calculate->pythonpath_env != NULL) {
1093 bufsz += wcslen(calculate->pythonpath_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001094 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001095
Victor Stinner0327bde2017-11-23 17:03:20 +01001096 wchar_t *defpath = calculate->pythonpath;
Victor Stinner9316ee42017-11-25 03:17:57 +01001097 size_t prefixsz = wcslen(prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001098 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001099 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001100
Victor Stinner3939c322019-06-25 15:02:43 +02001101 if (!_Py_isabs(defpath)) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001102 /* Paths are relative to prefix */
1103 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001104 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001105
Victor Stinner0327bde2017-11-23 17:03:20 +01001106 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001107 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001108 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001109 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001110 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001111 break;
1112 }
1113 defpath = delim + 1;
1114 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001115
Victor Stinner85ce0a72019-09-24 00:55:48 +02001116 bufsz += wcslen(zip_path) + 1;
Victor Stinner9316ee42017-11-25 03:17:57 +01001117 bufsz += wcslen(exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001118
Victor Stinner0327bde2017-11-23 17:03:20 +01001119 /* Allocate the buffer */
1120 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001121 if (buf == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +02001122 return _PyStatus_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001123 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001124 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001125
Victor Stinner72967a42013-11-16 01:22:04 +01001126 /* Run-time value of $PYTHONPATH goes first */
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001127 if (calculate->pythonpath_env) {
1128 wcscpy(buf, calculate->pythonpath_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001129 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001130 }
Victor Stinner72967a42013-11-16 01:22:04 +01001131
1132 /* Next is the default zip path */
Victor Stinner85ce0a72019-09-24 00:55:48 +02001133 wcscat(buf, zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001134 wcscat(buf, delimiter);
1135
1136 /* Next goes merge of compile-time $PYTHONPATH with
1137 * dynamically located prefix.
1138 */
Victor Stinner0327bde2017-11-23 17:03:20 +01001139 defpath = calculate->pythonpath;
Victor Stinner72967a42013-11-16 01:22:04 +01001140 while (1) {
1141 wchar_t *delim = wcschr(defpath, DELIM);
1142
Victor Stinner3939c322019-06-25 15:02:43 +02001143 if (!_Py_isabs(defpath)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001144 wcscat(buf, prefix);
1145 if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001146 defpath[0] != (delim ? DELIM : L'\0'))
1147 {
1148 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001149 wcscat(buf, separator);
1150 }
Victor Stinner72967a42013-11-16 01:22:04 +01001151 }
1152
1153 if (delim) {
1154 size_t len = delim - defpath + 1;
1155 size_t end = wcslen(buf) + len;
1156 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001157 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001158 }
1159 else {
1160 wcscat(buf, defpath);
1161 break;
1162 }
1163 defpath = delim + 1;
1164 }
1165 wcscat(buf, delimiter);
1166
1167 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinner9316ee42017-11-25 03:17:57 +01001168 wcscat(buf, exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001169
Victor Stinner331a6a52019-05-27 16:39:22 +02001170 pathconfig->module_search_path = buf;
1171 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001172}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001173
Victor Stinner0327bde2017-11-23 17:03:20 +01001174
Victor Stinner331a6a52019-05-27 16:39:22 +02001175static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +02001176calculate_init(PyCalculatePath *calculate, const PyConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001177{
Victor Stinner0327bde2017-11-23 17:03:20 +01001178 size_t len;
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001179 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001180 if (path) {
1181 calculate->path_env = Py_DecodeLocale(path, &len);
1182 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001183 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001184 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001185 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001186
Victor Stinner0327bde2017-11-23 17:03:20 +01001187 calculate->pythonpath = Py_DecodeLocale(PYTHONPATH, &len);
1188 if (!calculate->pythonpath) {
Victor Stinner46972b72017-11-24 22:55:40 +01001189 return DECODE_LOCALE_ERR("PYTHONPATH define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001190 }
Victor Stinner85ce0a72019-09-24 00:55:48 +02001191
Victor Stinner0327bde2017-11-23 17:03:20 +01001192 calculate->prefix = Py_DecodeLocale(PREFIX, &len);
1193 if (!calculate->prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001194 return DECODE_LOCALE_ERR("PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001195 }
1196 calculate->exec_prefix = Py_DecodeLocale(EXEC_PREFIX, &len);
Orivej Desh09090d02019-09-09 16:05:21 +00001197 if (!calculate->exec_prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001198 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001199 }
1200 calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
1201 if (!calculate->lib_python) {
Victor Stinner46972b72017-11-24 22:55:40 +01001202 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001203 }
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001204
1205 calculate->warnings = config->pathconfig_warnings;
1206 calculate->pythonpath_env = config->pythonpath_env;
1207
Victor Stinner331a6a52019-05-27 16:39:22 +02001208 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001209}
1210
1211
1212static void
1213calculate_free(PyCalculatePath *calculate)
1214{
1215 PyMem_RawFree(calculate->pythonpath);
1216 PyMem_RawFree(calculate->prefix);
1217 PyMem_RawFree(calculate->exec_prefix);
1218 PyMem_RawFree(calculate->lib_python);
1219 PyMem_RawFree(calculate->path_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001220}
1221
1222
Victor Stinner331a6a52019-05-27 16:39:22 +02001223static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001224calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001225{
Victor Stinner331a6a52019-05-27 16:39:22 +02001226 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +01001227
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001228 if (pathconfig->program_full_path == NULL) {
1229 status = calculate_program_full_path(calculate, pathconfig);
1230 if (_PyStatus_EXCEPTION(status)) {
1231 return status;
1232 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001233 }
1234
Victor Stinner85ce0a72019-09-24 00:55:48 +02001235 wchar_t argv0_path[MAXPATHLEN+1];
1236 memset(argv0_path, 0, sizeof(argv0_path));
1237
1238 status = calculate_argv0_path(calculate, pathconfig->program_full_path,
1239 argv0_path, Py_ARRAY_LENGTH(argv0_path));
Victor Stinner331a6a52019-05-27 16:39:22 +02001240 if (_PyStatus_EXCEPTION(status)) {
1241 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001242 }
1243
Victor Stinner221fd842019-09-25 02:54:25 +02001244 /* If a pyvenv.cfg configure file is found,
1245 argv0_path is overriden with its 'home' variable. */
Victor Stinner85ce0a72019-09-24 00:55:48 +02001246 status = calculate_read_pyenv(calculate,
1247 argv0_path, Py_ARRAY_LENGTH(argv0_path));
Victor Stinner331a6a52019-05-27 16:39:22 +02001248 if (_PyStatus_EXCEPTION(status)) {
1249 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001250 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001251
1252 wchar_t prefix[MAXPATHLEN+1];
1253 memset(prefix, 0, sizeof(prefix));
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001254 status = calculate_prefix(calculate, pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +02001255 argv0_path,
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001256 prefix, Py_ARRAY_LENGTH(prefix));
Victor Stinner331a6a52019-05-27 16:39:22 +02001257 if (_PyStatus_EXCEPTION(status)) {
1258 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001259 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001260
Victor Stinner85ce0a72019-09-24 00:55:48 +02001261 wchar_t zip_path[MAXPATHLEN+1]; /* ".../lib/pythonXY.zip" */
1262 memset(zip_path, 0, sizeof(zip_path));
1263
1264 status = calculate_zip_path(calculate, prefix,
1265 zip_path, Py_ARRAY_LENGTH(zip_path));
Victor Stinner331a6a52019-05-27 16:39:22 +02001266 if (_PyStatus_EXCEPTION(status)) {
1267 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001268 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001269
1270 wchar_t exec_prefix[MAXPATHLEN+1];
1271 memset(exec_prefix, 0, sizeof(exec_prefix));
Victor Stinner85ce0a72019-09-24 00:55:48 +02001272 status = calculate_exec_prefix(calculate, pathconfig, argv0_path,
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001273 exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
Victor Stinner331a6a52019-05-27 16:39:22 +02001274 if (_PyStatus_EXCEPTION(status)) {
1275 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001276 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001277
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001278 if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001279 calculate->warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001280 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001281 fprintf(stderr,
1282 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1283 }
1284
Victor Stinnere2677932019-09-21 01:50:16 +02001285 if (pathconfig->module_search_path == NULL) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001286 status = calculate_module_search_path(calculate, pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +02001287 prefix, exec_prefix, zip_path);
Victor Stinnere2677932019-09-21 01:50:16 +02001288 if (_PyStatus_EXCEPTION(status)) {
1289 return status;
1290 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001291 }
1292
Victor Stinner331a6a52019-05-27 16:39:22 +02001293 if (pathconfig->prefix == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +02001294 status = calculate_set_prefix(calculate, pathconfig, prefix);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001295 if (_PyStatus_EXCEPTION(status)) {
1296 return status;
1297 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001298 }
1299
Victor Stinner331a6a52019-05-27 16:39:22 +02001300 if (pathconfig->exec_prefix == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +02001301 status = calculate_set_exec_prefix(calculate, pathconfig, exec_prefix);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001302 if (_PyStatus_EXCEPTION(status)) {
1303 return status;
1304 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001305 }
1306
Victor Stinner331a6a52019-05-27 16:39:22 +02001307 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001308}
1309
1310
Victor Stinner85ce0a72019-09-24 00:55:48 +02001311/* Calculate the Python path configuration.
1312
1313 Inputs:
1314
1315 - PATH environment variable
1316 - Macros: PYTHONPATH, PREFIX, EXEC_PREFIX, VERSION (ex: "3.9").
1317 PREFIX and EXEC_PREFIX are generated by the configure script.
1318 PYTHONPATH macro is the default search path.
1319 - pybuilddir.txt file
1320 - pyvenv.cfg configuration file
1321 - PyConfig fields ('config' function argument):
1322
1323 - pathconfig_warnings
1324 - pythonpath_env (PYTHONPATH environment variable)
1325
1326 - _PyPathConfig fields ('pathconfig' function argument):
1327
1328 - program_name: see config_init_program_name()
1329 - home: Py_SetPythonHome() or PYTHONHOME environment variable
1330
1331 - current working directory: see copy_absolute()
1332
1333 Outputs, 'pathconfig' fields:
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001334
1335 - program_full_path
1336 - module_search_path
1337 - prefix
1338 - exec_prefix
1339
Victor Stinner85ce0a72019-09-24 00:55:48 +02001340 If a field is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001341PyStatus
1342_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001343{
Victor Stinner331a6a52019-05-27 16:39:22 +02001344 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001345 PyCalculatePath calculate;
1346 memset(&calculate, 0, sizeof(calculate));
1347
Victor Stinner331a6a52019-05-27 16:39:22 +02001348 status = calculate_init(&calculate, config);
1349 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001350 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001351 }
1352
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001353 status = calculate_path(&calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001354 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001355 goto done;
1356 }
1357
Victor Stinner331a6a52019-05-27 16:39:22 +02001358 status = _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001359
Victor Stinner9316ee42017-11-25 03:17:57 +01001360done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001361 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001362 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001363}
Victor Stinner46972b72017-11-24 22:55:40 +01001364
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001365#ifdef __cplusplus
1366}
1367#endif