blob: 24e16b41b406c98477400eb455d758b3c8e13b1c [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 Stinner331a6a52019-05-27 16:39:22 +0200373 PyStatus status;
Fred Drakeedabdc12000-07-08 06:16:37 +0000374 size_t n;
Martin v. Löwis790465f2008-04-05 20:41:37 +0000375 wchar_t *vpath;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000376
Fred Drakeedabdc12000-07-08 06:16:37 +0000377 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200378 if (pathconfig->home) {
379 if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100380 return PATHLEN_ERR();
381 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100382 wchar_t *delim = wcschr(prefix, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100383 if (delim) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000384 *delim = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100385 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200386 status = joinpath(prefix, calculate->lib_python, prefix_len);
387 if (_PyStatus_EXCEPTION(status)) {
388 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100389 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200390 status = joinpath(prefix, LANDMARK, prefix_len);
391 if (_PyStatus_EXCEPTION(status)) {
392 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100393 }
394 *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 Stinner85ce0a72019-09-24 00:55:48 +0200399 if (safe_wcscpy(prefix, argv0_path, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100400 return PATHLEN_ERR();
401 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200402 status = joinpath(prefix, L"Modules/Setup.local", prefix_len);
403 if (_PyStatus_EXCEPTION(status)) {
404 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100405 }
406
Victor Stinner9316ee42017-11-25 03:17:57 +0100407 if (isfile(prefix)) {
Neil Schemenauer6cf07022001-01-24 17:13:11 +0000408 /* Check VPATH to see if argv0_path is in the build directory. */
Victor Stinnerf6a271a2014-08-01 12:28:48 +0200409 vpath = Py_DecodeLocale(VPATH, NULL);
Victor Stinner21582312010-10-23 00:13:28 +0000410 if (vpath != NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200411 if (safe_wcscpy(prefix, argv0_path, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100412 return PATHLEN_ERR();
413 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200414 status = joinpath(prefix, vpath, prefix_len);
Victor Stinner1a7425f2013-07-07 16:25:15 +0200415 PyMem_RawFree(vpath);
Victor Stinner331a6a52019-05-27 16:39:22 +0200416 if (_PyStatus_EXCEPTION(status)) {
417 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100418 }
419
Victor Stinner331a6a52019-05-27 16:39:22 +0200420 status = joinpath(prefix, L"Lib", prefix_len);
421 if (_PyStatus_EXCEPTION(status)) {
422 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100423 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200424 status = joinpath(prefix, LANDMARK, prefix_len);
425 if (_PyStatus_EXCEPTION(status)) {
426 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100427 }
428
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100429 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100430 *found = -1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200431 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100432 }
Victor Stinner21582312010-10-23 00:13:28 +0000433 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000434 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000435
Fred Drakeedabdc12000-07-08 06:16:37 +0000436 /* Search from argv0_path, until root is found */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200437 status = copy_absolute(prefix, argv0_path, prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200438 if (_PyStatus_EXCEPTION(status)) {
439 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100440 }
441
Fred Drakeedabdc12000-07-08 06:16:37 +0000442 do {
Victor Stinner9316ee42017-11-25 03:17:57 +0100443 n = wcslen(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200444 status = joinpath(prefix, calculate->lib_python, prefix_len);
445 if (_PyStatus_EXCEPTION(status)) {
446 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100447 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200448 status = joinpath(prefix, LANDMARK, prefix_len);
449 if (_PyStatus_EXCEPTION(status)) {
450 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100451 }
452
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100453 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100454 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200455 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100456 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100457 prefix[n] = L'\0';
458 reduce(prefix);
459 } while (prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000460
Fred Drakeedabdc12000-07-08 06:16:37 +0000461 /* Look at configure's PREFIX */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100462 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
463 return PATHLEN_ERR();
464 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200465 status = joinpath(prefix, calculate->lib_python, prefix_len);
466 if (_PyStatus_EXCEPTION(status)) {
467 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100468 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200469 status = joinpath(prefix, LANDMARK, prefix_len);
470 if (_PyStatus_EXCEPTION(status)) {
471 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100472 }
473
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100474 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100475 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200476 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100477 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000478
Fred Drakeedabdc12000-07-08 06:16:37 +0000479 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100480 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200481 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000482}
483
484
Victor Stinner331a6a52019-05-27 16:39:22 +0200485static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200486calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200487 const wchar_t *argv0_path,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200488 wchar_t *prefix, size_t prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100489{
Victor Stinner331a6a52019-05-27 16:39:22 +0200490 PyStatus status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100491
Victor Stinner85ce0a72019-09-24 00:55:48 +0200492 status = search_for_prefix(calculate, pathconfig, argv0_path,
493 prefix, prefix_len,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200494 &calculate->prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200495 if (_PyStatus_EXCEPTION(status)) {
496 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100497 }
498
Victor Stinner0327bde2017-11-23 17:03:20 +0100499 if (!calculate->prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200500 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100501 fprintf(stderr,
502 "Could not find platform independent libraries <prefix>\n");
503 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100504 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
505 return PATHLEN_ERR();
506 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200507 status = joinpath(prefix, calculate->lib_python, prefix_len);
508 if (_PyStatus_EXCEPTION(status)) {
509 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100510 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100511 }
512 else {
Victor Stinner9316ee42017-11-25 03:17:57 +0100513 reduce(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100514 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200515 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100516}
517
518
Victor Stinner331a6a52019-05-27 16:39:22 +0200519static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200520calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
521 wchar_t *prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +0100522{
523 /* Reduce prefix and exec_prefix to their essence,
524 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
525 * If we're loading relative to the build directory,
526 * return the compiled-in defaults instead.
527 */
528 if (calculate->prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100529 reduce(prefix);
530 reduce(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100531 /* The prefix is the root directory, but reduce() chopped
532 * off the "/". */
Victor Stinner9316ee42017-11-25 03:17:57 +0100533 if (!prefix[0]) {
534 wcscpy(prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100535 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200536 pathconfig->prefix = _PyMem_RawWcsdup(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100537 }
538 else {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200539 pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix);
540 }
541
542 if (pathconfig->prefix == NULL) {
543 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100544 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200545 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100546}
547
548
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000549/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000550 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000551*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200552static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200553search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200554 const wchar_t *argv0_path,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100555 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100556 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000557{
Victor Stinner331a6a52019-05-27 16:39:22 +0200558 PyStatus status;
Fred Drakeedabdc12000-07-08 06:16:37 +0000559 size_t n;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000560
Fred Drakeedabdc12000-07-08 06:16:37 +0000561 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200562 if (pathconfig->home) {
563 wchar_t *delim = wcschr(pathconfig->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100564 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100565 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
566 return PATHLEN_ERR();
567 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100568 }
569 else {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200570 if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100571 return PATHLEN_ERR();
572 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100573 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200574 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
575 if (_PyStatus_EXCEPTION(status)) {
576 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100577 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200578 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
579 if (_PyStatus_EXCEPTION(status)) {
580 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100581 }
582 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200583 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000584 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000585
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000586 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
587 is written by setup.py and contains the relative path to the location
588 of shared library modules. */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200589 if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100590 return PATHLEN_ERR();
591 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200592 status = joinpath(exec_prefix, L"pybuilddir.txt", exec_prefix_len);
593 if (_PyStatus_EXCEPTION(status)) {
594 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100595 }
596
Victor Stinner9316ee42017-11-25 03:17:57 +0100597 if (isfile(exec_prefix)) {
598 FILE *f = _Py_wfopen(exec_prefix, L"rb");
Victor Stinner0327bde2017-11-23 17:03:20 +0100599 if (f == NULL) {
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000600 errno = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100601 }
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000602 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100603 char buf[MAXPATHLEN + 1];
604 n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, f);
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000605 buf[n] = '\0';
606 fclose(f);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100607
Victor Stinner5f9cf232019-03-19 01:46:25 +0100608 wchar_t *pybuilddir;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100609 size_t dec_len;
Victor Stinner5f9cf232019-03-19 01:46:25 +0100610 pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
611 if (!pybuilddir) {
612 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000613 }
Victor Stinner5f9cf232019-03-19 01:46:25 +0100614
Victor Stinner85ce0a72019-09-24 00:55:48 +0200615 if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100616 return PATHLEN_ERR();
617 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200618 status = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
Victor Stinner5f9cf232019-03-19 01:46:25 +0100619 PyMem_RawFree(pybuilddir );
Victor Stinner331a6a52019-05-27 16:39:22 +0200620 if (_PyStatus_EXCEPTION(status)) {
621 return status;
Victor Stinner5f9cf232019-03-19 01:46:25 +0100622 }
623
624 *found = -1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200625 return _PyStatus_OK();
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000626 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000627 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000628
Fred Drakeedabdc12000-07-08 06:16:37 +0000629 /* Search from argv0_path, until root is found */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200630 status = copy_absolute(exec_prefix, argv0_path, exec_prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200631 if (_PyStatus_EXCEPTION(status)) {
632 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100633 }
634
Fred Drakeedabdc12000-07-08 06:16:37 +0000635 do {
Victor Stinner9316ee42017-11-25 03:17:57 +0100636 n = wcslen(exec_prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200637 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
638 if (_PyStatus_EXCEPTION(status)) {
639 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100640 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200641 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
642 if (_PyStatus_EXCEPTION(status)) {
643 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100644 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100645 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100646 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200647 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100648 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100649 exec_prefix[n] = L'\0';
650 reduce(exec_prefix);
651 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000652
Fred Drakeedabdc12000-07-08 06:16:37 +0000653 /* Look at configure's EXEC_PREFIX */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100654 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
655 return PATHLEN_ERR();
656 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200657 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
658 if (_PyStatus_EXCEPTION(status)) {
659 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100660 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200661 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
662 if (_PyStatus_EXCEPTION(status)) {
663 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100664 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100665 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100666 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200667 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100668 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000669
Fred Drakeedabdc12000-07-08 06:16:37 +0000670 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100671 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200672 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000673}
674
Guido van Rossum305e5d01997-04-11 17:18:45 +0000675
Victor Stinner331a6a52019-05-27 16:39:22 +0200676static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200677calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200678 const wchar_t *argv0_path,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100679 wchar_t *exec_prefix, size_t exec_prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100680{
Victor Stinner331a6a52019-05-27 16:39:22 +0200681 PyStatus status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100682
Victor Stinner85ce0a72019-09-24 00:55:48 +0200683 status = search_for_exec_prefix(calculate, pathconfig, argv0_path,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200684 exec_prefix, exec_prefix_len,
685 &calculate->exec_prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200686 if (_PyStatus_EXCEPTION(status)) {
687 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100688 }
689
Victor Stinner0327bde2017-11-23 17:03:20 +0100690 if (!calculate->exec_prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200691 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100692 fprintf(stderr,
693 "Could not find platform dependent libraries <exec_prefix>\n");
694 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100695 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
696 return PATHLEN_ERR();
697 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200698 status = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len);
699 if (_PyStatus_EXCEPTION(status)) {
700 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100701 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100702 }
703 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
Victor Stinner331a6a52019-05-27 16:39:22 +0200704 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100705}
706
707
Victor Stinner331a6a52019-05-27 16:39:22 +0200708static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200709calculate_set_exec_prefix(PyCalculatePath *calculate,
710 _PyPathConfig *pathconfig,
711 wchar_t *exec_prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +0100712{
713 if (calculate->exec_prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100714 reduce(exec_prefix);
715 reduce(exec_prefix);
716 reduce(exec_prefix);
717 if (!exec_prefix[0]) {
718 wcscpy(exec_prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100719 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200720
721 pathconfig->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100722 }
723 else {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200724 pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100725 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200726
727 if (pathconfig->exec_prefix == NULL) {
728 return _PyStatus_NO_MEMORY();
729 }
730
Victor Stinner331a6a52019-05-27 16:39:22 +0200731 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100732}
733
734
Victor Stinner331a6a52019-05-27 16:39:22 +0200735static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200736calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100737{
Victor Stinner331a6a52019-05-27 16:39:22 +0200738 PyStatus status;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100739 wchar_t program_full_path[MAXPATHLEN + 1];
740 const size_t program_full_path_len = Py_ARRAY_LENGTH(program_full_path);
Victor Stinnerb64de462017-12-01 18:27:09 +0100741 memset(program_full_path, 0, sizeof(program_full_path));
Victor Stinner9316ee42017-11-25 03:17:57 +0100742
Victor Stinnerb9197952017-11-23 19:02:04 +0100743#ifdef __APPLE__
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100744 char execpath[MAXPATHLEN + 1];
Victor Stinnerb9197952017-11-23 19:02:04 +0100745#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100746 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100747#else
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100748 unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100749#endif
Victor Stinnerb9197952017-11-23 19:02:04 +0100750#endif
751
Victor Stinner0327bde2017-11-23 17:03:20 +0100752 /* If there is no slash in the argv0 path, then we have to
753 * assume python is on the user's $PATH, since there's no
754 * other way to find a directory to start the search from. If
755 * $PATH isn't exported, you lose.
756 */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200757 if (wcschr(pathconfig->program_name, SEP)) {
758 if (safe_wcscpy(program_full_path, pathconfig->program_name,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100759 program_full_path_len) < 0) {
760 return PATHLEN_ERR();
761 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100762 }
Jack Jansen1afd4802004-06-03 14:33:03 +0000763#ifdef __APPLE__
Jack Jansen1afd4802004-06-03 14:33:03 +0000764 /* On Mac OS X, if a script uses an interpreter of the form
765 * "#!/opt/python2.3/bin/python", the kernel only passes "python"
766 * as argv[0], which falls through to the $PATH search below.
767 * If /opt/python2.3/bin isn't in your path, or is near the end,
768 * this algorithm may incorrectly find /usr/bin/python. To work
769 * around this, we can use _NSGetExecutablePath to get a better
770 * hint of what the intended interpreter was, although this
771 * will fail if a relative path was used. but in that case,
772 * absolutize() should help us out below
773 */
Victor Stinnerf04ebe22017-11-25 00:01:23 +0100774 else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
Victor Stinner30290352019-06-28 16:49:38 +0200775 (wchar_t)execpath[0] == SEP)
Victor Stinnerf04ebe22017-11-25 00:01:23 +0100776 {
Victor Stinner31a83932017-12-04 13:39:15 +0100777 size_t len;
778 wchar_t *path = Py_DecodeLocale(execpath, &len);
779 if (path == NULL) {
780 return DECODE_LOCALE_ERR("executable path", len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000781 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100782 if (safe_wcscpy(program_full_path, path, program_full_path_len) < 0) {
783 PyMem_RawFree(path);
784 return PATHLEN_ERR();
785 }
Victor Stinner31a83932017-12-04 13:39:15 +0100786 PyMem_RawFree(path);
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000787 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000788#endif /* __APPLE__ */
Victor Stinner0327bde2017-11-23 17:03:20 +0100789 else if (calculate->path_env) {
790 wchar_t *path = calculate->path_env;
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000791 while (1) {
792 wchar_t *delim = wcschr(path, DELIM);
Jack Jansen55070f52001-12-02 23:56:28 +0000793
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000794 if (delim) {
795 size_t len = delim - path;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100796 if (len >= program_full_path_len) {
797 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100798 }
Victor Stinnerb64de462017-12-01 18:27:09 +0100799 wcsncpy(program_full_path, path, len);
800 program_full_path[len] = '\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000801 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100802 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100803 if (safe_wcscpy(program_full_path, path,
804 program_full_path_len) < 0) {
805 return PATHLEN_ERR();
806 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100807 }
Jack Jansen55070f52001-12-02 23:56:28 +0000808
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200809 status = joinpath(program_full_path, pathconfig->program_name,
810 program_full_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200811 if (_PyStatus_EXCEPTION(status)) {
812 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100813 }
814
Victor Stinnerb64de462017-12-01 18:27:09 +0100815 if (isxfile(program_full_path)) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000816 break;
Victor Stinner0327bde2017-11-23 17:03:20 +0100817 }
Jack Jansen55070f52001-12-02 23:56:28 +0000818
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000819 if (!delim) {
Victor Stinnerb64de462017-12-01 18:27:09 +0100820 program_full_path[0] = L'\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000821 break;
822 }
823 path = delim + 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000824 }
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000825 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100826 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100827 program_full_path[0] = '\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100828 }
Victor Stinner3939c322019-06-25 15:02:43 +0200829 if (!_Py_isabs(program_full_path) && program_full_path[0] != '\0') {
Victor Stinner331a6a52019-05-27 16:39:22 +0200830 status = absolutize(program_full_path, program_full_path_len);
831 if (_PyStatus_EXCEPTION(status)) {
832 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100833 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100834 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200835#if defined(__CYGWIN__) || defined(__MINGW32__)
836 /* For these platforms it is necessary to ensure that the .exe suffix
837 * is appended to the filename, otherwise there is potential for
838 * sys.executable to return the name of a directory under the same
839 * path (bpo-28441).
840 */
841 if (program_full_path[0] != '\0') {
Victor Stinner331a6a52019-05-27 16:39:22 +0200842 status = add_exe_suffix(program_full_path, program_full_path_len);
843 if (_PyStatus_EXCEPTION(status)) {
844 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100845 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200846 }
847#endif
Victor Stinner9316ee42017-11-25 03:17:57 +0100848
Victor Stinner331a6a52019-05-27 16:39:22 +0200849 pathconfig->program_full_path = _PyMem_RawWcsdup(program_full_path);
850 if (pathconfig->program_full_path == NULL) {
851 return _PyStatus_NO_MEMORY();
Victor Stinner9316ee42017-11-25 03:17:57 +0100852 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200853 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100854}
855
856
Victor Stinner331a6a52019-05-27 16:39:22 +0200857static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200858calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path,
859 wchar_t *argv0_path, size_t argv0_path_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100860{
Victor Stinner85ce0a72019-09-24 00:55:48 +0200861 if (safe_wcscpy(argv0_path, program_full_path, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100862 return PATHLEN_ERR();
863 }
Jack Jansen55070f52001-12-02 23:56:28 +0000864
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000865#ifdef WITH_NEXT_FRAMEWORK
Victor Stinner0327bde2017-11-23 17:03:20 +0100866 NSModule pythonModule;
867
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000868 /* On Mac OS X we have a special case if we're running from a framework.
869 ** This is because the python home should be set relative to the library,
870 ** which is in the framework, not relative to the executable, which may
871 ** be outside of the framework. Except when we're in the build directory...
872 */
Fred Drakeedabdc12000-07-08 06:16:37 +0000873 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
874 /* Use dylib functions to find out where the framework was loaded from */
Victor Stinner0327bde2017-11-23 17:03:20 +0100875 const char* modPath = NSLibraryNameForModule(pythonModule);
Vinay Sajip90db6612012-07-17 17:33:46 +0100876 if (modPath != NULL) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000877 /* We're in a framework. */
Jack Jansene925faf2001-08-15 01:14:40 +0000878 /* See if we might be in the build directory. The framework in the
879 ** build directory is incomplete, it only has the .dylib and a few
880 ** needed symlinks, it doesn't have the Lib directories and such.
881 ** If we're running with the framework from the build directory we must
882 ** be running the interpreter in the build directory, so we use the
883 ** build-directory-specific logic to find Lib and such.
884 */
Victor Stinner331a6a52019-05-27 16:39:22 +0200885 PyStatus status;
Victor Stinner9316ee42017-11-25 03:17:57 +0100886 size_t len;
887 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100888 if (wbuf == NULL) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100889 return DECODE_LOCALE_ERR("framework location", len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100890 }
891
Victor Stinner85ce0a72019-09-24 00:55:48 +0200892 if (safe_wcscpy(argv0_path, wbuf, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100893 return PATHLEN_ERR();
894 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200895 reduce(argv0_path);
896 status = joinpath(argv0_path, calculate->lib_python, argv0_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200897 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100898 PyMem_RawFree(wbuf);
Victor Stinner331a6a52019-05-27 16:39:22 +0200899 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100900 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200901 status = joinpath(argv0_path, LANDMARK, argv0_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200902 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100903 PyMem_RawFree(wbuf);
Victor Stinner331a6a52019-05-27 16:39:22 +0200904 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100905 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200906 if (!ismodule(argv0_path, Py_ARRAY_LENGTH(argv0_path))) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000907 /* We are in the build directory so use the name of the
908 executable - we know that the absolute path is passed */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200909 if (safe_wcscpy(argv0_path, program_full_path,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100910 argv0_path_len) < 0) {
911 return PATHLEN_ERR();
912 }
Jack Jansene925faf2001-08-15 01:14:40 +0000913 }
914 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100915 /* Use the location of the library as the program_full_path */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200916 if (safe_wcscpy(argv0_path, wbuf, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100917 return PATHLEN_ERR();
918 }
Jack Jansene925faf2001-08-15 01:14:40 +0000919 }
Victor Stinner1a7425f2013-07-07 16:25:15 +0200920 PyMem_RawFree(wbuf);
Fred Drakeedabdc12000-07-08 06:16:37 +0000921 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000922#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000923
Guido van Rossum305e5d01997-04-11 17:18:45 +0000924#if HAVE_READLINK
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100925 wchar_t tmpbuffer[MAXPATHLEN + 1];
926 const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
927 int linklen = _Py_wreadlink(program_full_path, tmpbuffer, buflen);
Victor Stinner0327bde2017-11-23 17:03:20 +0100928 while (linklen != -1) {
Victor Stinner3939c322019-06-25 15:02:43 +0200929 if (_Py_isabs(tmpbuffer)) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100930 /* tmpbuffer should never be longer than MAXPATHLEN,
931 but extra check does not hurt */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200932 if (safe_wcscpy(argv0_path, tmpbuffer, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100933 return PATHLEN_ERR();
934 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000935 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100936 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100937 /* Interpret relative to program_full_path */
Victor Stinner331a6a52019-05-27 16:39:22 +0200938 PyStatus status;
Victor Stinner85ce0a72019-09-24 00:55:48 +0200939 reduce(argv0_path);
940 status = joinpath(argv0_path, tmpbuffer, argv0_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200941 if (_PyStatus_EXCEPTION(status)) {
942 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100943 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100944 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200945 linklen = _Py_wreadlink(argv0_path, tmpbuffer, buflen);
Fred Drakeedabdc12000-07-08 06:16:37 +0000946 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000947#endif /* HAVE_READLINK */
948
Victor Stinner85ce0a72019-09-24 00:55:48 +0200949 reduce(argv0_path);
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000950 /* At this point, argv0_path is guaranteed to be less than
Victor Stinner0327bde2017-11-23 17:03:20 +0100951 MAXPATHLEN bytes long. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200952 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100953}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000954
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100955
Victor Stinner0327bde2017-11-23 17:03:20 +0100956/* Search for an "pyvenv.cfg" environment configuration file, first in the
957 executable's directory and then in the parent directory.
958 If found, open it for use when searching for prefixes.
959*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200960static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200961calculate_read_pyenv(PyCalculatePath *calculate,
962 wchar_t *argv0_path, size_t argv0_path_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100963{
Victor Stinner331a6a52019-05-27 16:39:22 +0200964 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +0100965 wchar_t tmpbuffer[MAXPATHLEN+1];
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100966 const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
Victor Stinner0327bde2017-11-23 17:03:20 +0100967 wchar_t *env_cfg = L"pyvenv.cfg";
968 FILE *env_file;
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100969
Victor Stinner85ce0a72019-09-24 00:55:48 +0200970 if (safe_wcscpy(tmpbuffer, argv0_path, buflen) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100971 return PATHLEN_ERR();
972 }
Vinay Sajip90db6612012-07-17 17:33:46 +0100973
Victor Stinner331a6a52019-05-27 16:39:22 +0200974 status = joinpath(tmpbuffer, env_cfg, buflen);
975 if (_PyStatus_EXCEPTION(status)) {
976 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100977 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100978 env_file = _Py_wfopen(tmpbuffer, L"r");
979 if (env_file == NULL) {
980 errno = 0;
981
982 reduce(tmpbuffer);
983 reduce(tmpbuffer);
Victor Stinner331a6a52019-05-27 16:39:22 +0200984 status = joinpath(tmpbuffer, env_cfg, buflen);
985 if (_PyStatus_EXCEPTION(status)) {
986 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100987 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100988
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100989 env_file = _Py_wfopen(tmpbuffer, L"r");
990 if (env_file == NULL) {
991 errno = 0;
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100992 }
993 }
994
Victor Stinner0327bde2017-11-23 17:03:20 +0100995 if (env_file == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200996 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000997 }
Guido van Rossume296ced2001-09-28 20:00:29 +0000998
Victor Stinner0327bde2017-11-23 17:03:20 +0100999 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001000 if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, buflen)) {
Victor Stinner85ce0a72019-09-24 00:55:48 +02001001 if (safe_wcscpy(argv0_path, tmpbuffer, argv0_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001002 return PATHLEN_ERR();
1003 }
Just van Rossum52e14d62002-12-30 22:08:05 +00001004 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001005 fclose(env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001006 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001007}
Just van Rossum52e14d62002-12-30 22:08:05 +00001008
Guido van Rossum305e5d01997-04-11 17:18:45 +00001009
Victor Stinner331a6a52019-05-27 16:39:22 +02001010static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +02001011calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix,
1012 wchar_t *zip_path, size_t zip_path_len)
Victor Stinner0327bde2017-11-23 17:03:20 +01001013{
Victor Stinner331a6a52019-05-27 16:39:22 +02001014 PyStatus status;
Victor Stinner85ce0a72019-09-24 00:55:48 +02001015 if (safe_wcscpy(zip_path, prefix, zip_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001016 return PATHLEN_ERR();
1017 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001018
Victor Stinner0327bde2017-11-23 17:03:20 +01001019 if (calculate->prefix_found > 0) {
1020 /* Use the reduced prefix returned by Py_GetPrefix() */
Victor Stinner85ce0a72019-09-24 00:55:48 +02001021 reduce(zip_path);
1022 reduce(zip_path);
Victor Stinnerd4341102017-11-23 00:12:09 +01001023 }
1024 else {
Victor Stinner85ce0a72019-09-24 00:55:48 +02001025 if (safe_wcscpy(zip_path, calculate->prefix, zip_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001026 return PATHLEN_ERR();
1027 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001028 }
Victor Stinner85ce0a72019-09-24 00:55:48 +02001029 status = joinpath(zip_path, L"lib/python00.zip", zip_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +02001030 if (_PyStatus_EXCEPTION(status)) {
1031 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001032 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001033
1034 /* Replace "00" with version */
Victor Stinner85ce0a72019-09-24 00:55:48 +02001035 size_t bufsz = wcslen(zip_path);
1036 zip_path[bufsz - 6] = VERSION[0];
1037 zip_path[bufsz - 5] = VERSION[2];
Victor Stinner331a6a52019-05-27 16:39:22 +02001038 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001039}
1040
1041
Victor Stinner331a6a52019-05-27 16:39:22 +02001042static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001043calculate_module_search_path(PyCalculatePath *calculate,
1044 _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +02001045 const wchar_t *prefix,
1046 const wchar_t *exec_prefix,
1047 const wchar_t *zip_path)
Victor Stinner0327bde2017-11-23 17:03:20 +01001048{
1049 /* Calculate size of return buffer */
1050 size_t bufsz = 0;
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001051 if (calculate->pythonpath_env != NULL) {
1052 bufsz += wcslen(calculate->pythonpath_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001053 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001054
Victor Stinner0327bde2017-11-23 17:03:20 +01001055 wchar_t *defpath = calculate->pythonpath;
Victor Stinner9316ee42017-11-25 03:17:57 +01001056 size_t prefixsz = wcslen(prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001057 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001058 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001059
Victor Stinner3939c322019-06-25 15:02:43 +02001060 if (!_Py_isabs(defpath)) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001061 /* Paths are relative to prefix */
1062 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001063 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001064
Victor Stinner0327bde2017-11-23 17:03:20 +01001065 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001066 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001067 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001068 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001069 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001070 break;
1071 }
1072 defpath = delim + 1;
1073 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001074
Victor Stinner85ce0a72019-09-24 00:55:48 +02001075 bufsz += wcslen(zip_path) + 1;
Victor Stinner9316ee42017-11-25 03:17:57 +01001076 bufsz += wcslen(exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001077
Victor Stinner0327bde2017-11-23 17:03:20 +01001078 /* Allocate the buffer */
1079 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001080 if (buf == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +02001081 return _PyStatus_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001082 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001083 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001084
Victor Stinner72967a42013-11-16 01:22:04 +01001085 /* Run-time value of $PYTHONPATH goes first */
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001086 if (calculate->pythonpath_env) {
1087 wcscpy(buf, calculate->pythonpath_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001088 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001089 }
Victor Stinner72967a42013-11-16 01:22:04 +01001090
1091 /* Next is the default zip path */
Victor Stinner85ce0a72019-09-24 00:55:48 +02001092 wcscat(buf, zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001093 wcscat(buf, delimiter);
1094
1095 /* Next goes merge of compile-time $PYTHONPATH with
1096 * dynamically located prefix.
1097 */
Victor Stinner0327bde2017-11-23 17:03:20 +01001098 defpath = calculate->pythonpath;
Victor Stinner72967a42013-11-16 01:22:04 +01001099 while (1) {
1100 wchar_t *delim = wcschr(defpath, DELIM);
1101
Victor Stinner3939c322019-06-25 15:02:43 +02001102 if (!_Py_isabs(defpath)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001103 wcscat(buf, prefix);
1104 if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001105 defpath[0] != (delim ? DELIM : L'\0'))
1106 {
1107 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001108 wcscat(buf, separator);
1109 }
Victor Stinner72967a42013-11-16 01:22:04 +01001110 }
1111
1112 if (delim) {
1113 size_t len = delim - defpath + 1;
1114 size_t end = wcslen(buf) + len;
1115 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001116 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001117 }
1118 else {
1119 wcscat(buf, defpath);
1120 break;
1121 }
1122 defpath = delim + 1;
1123 }
1124 wcscat(buf, delimiter);
1125
1126 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinner9316ee42017-11-25 03:17:57 +01001127 wcscat(buf, exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001128
Victor Stinner331a6a52019-05-27 16:39:22 +02001129 pathconfig->module_search_path = buf;
1130 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001131}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001132
Victor Stinner0327bde2017-11-23 17:03:20 +01001133
Victor Stinner331a6a52019-05-27 16:39:22 +02001134static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +02001135calculate_init(PyCalculatePath *calculate, const PyConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001136{
Victor Stinner0327bde2017-11-23 17:03:20 +01001137 size_t len;
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001138 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001139 if (path) {
1140 calculate->path_env = Py_DecodeLocale(path, &len);
1141 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001142 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001143 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001144 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001145
Victor Stinner0327bde2017-11-23 17:03:20 +01001146 calculate->pythonpath = Py_DecodeLocale(PYTHONPATH, &len);
1147 if (!calculate->pythonpath) {
Victor Stinner46972b72017-11-24 22:55:40 +01001148 return DECODE_LOCALE_ERR("PYTHONPATH define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001149 }
Victor Stinner85ce0a72019-09-24 00:55:48 +02001150
Victor Stinner0327bde2017-11-23 17:03:20 +01001151 calculate->prefix = Py_DecodeLocale(PREFIX, &len);
1152 if (!calculate->prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001153 return DECODE_LOCALE_ERR("PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001154 }
1155 calculate->exec_prefix = Py_DecodeLocale(EXEC_PREFIX, &len);
Orivej Desh09090d02019-09-09 16:05:21 +00001156 if (!calculate->exec_prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001157 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001158 }
1159 calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
1160 if (!calculate->lib_python) {
Victor Stinner46972b72017-11-24 22:55:40 +01001161 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001162 }
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001163
1164 calculate->warnings = config->pathconfig_warnings;
1165 calculate->pythonpath_env = config->pythonpath_env;
1166
Victor Stinner331a6a52019-05-27 16:39:22 +02001167 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001168}
1169
1170
1171static void
1172calculate_free(PyCalculatePath *calculate)
1173{
1174 PyMem_RawFree(calculate->pythonpath);
1175 PyMem_RawFree(calculate->prefix);
1176 PyMem_RawFree(calculate->exec_prefix);
1177 PyMem_RawFree(calculate->lib_python);
1178 PyMem_RawFree(calculate->path_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001179}
1180
1181
Victor Stinner331a6a52019-05-27 16:39:22 +02001182static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001183calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001184{
Victor Stinner331a6a52019-05-27 16:39:22 +02001185 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +01001186
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001187 if (pathconfig->program_full_path == NULL) {
1188 status = calculate_program_full_path(calculate, pathconfig);
1189 if (_PyStatus_EXCEPTION(status)) {
1190 return status;
1191 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001192 }
1193
Victor Stinner85ce0a72019-09-24 00:55:48 +02001194 wchar_t argv0_path[MAXPATHLEN+1];
1195 memset(argv0_path, 0, sizeof(argv0_path));
1196
1197 status = calculate_argv0_path(calculate, pathconfig->program_full_path,
1198 argv0_path, Py_ARRAY_LENGTH(argv0_path));
Victor Stinner331a6a52019-05-27 16:39:22 +02001199 if (_PyStatus_EXCEPTION(status)) {
1200 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001201 }
1202
Victor Stinner85ce0a72019-09-24 00:55:48 +02001203 status = calculate_read_pyenv(calculate,
1204 argv0_path, Py_ARRAY_LENGTH(argv0_path));
Victor Stinner331a6a52019-05-27 16:39:22 +02001205 if (_PyStatus_EXCEPTION(status)) {
1206 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001207 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001208
1209 wchar_t prefix[MAXPATHLEN+1];
1210 memset(prefix, 0, sizeof(prefix));
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001211 status = calculate_prefix(calculate, pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +02001212 argv0_path,
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001213 prefix, Py_ARRAY_LENGTH(prefix));
Victor Stinner331a6a52019-05-27 16:39:22 +02001214 if (_PyStatus_EXCEPTION(status)) {
1215 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001216 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001217
Victor Stinner85ce0a72019-09-24 00:55:48 +02001218 wchar_t zip_path[MAXPATHLEN+1]; /* ".../lib/pythonXY.zip" */
1219 memset(zip_path, 0, sizeof(zip_path));
1220
1221 status = calculate_zip_path(calculate, prefix,
1222 zip_path, Py_ARRAY_LENGTH(zip_path));
Victor Stinner331a6a52019-05-27 16:39:22 +02001223 if (_PyStatus_EXCEPTION(status)) {
1224 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001225 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001226
1227 wchar_t exec_prefix[MAXPATHLEN+1];
1228 memset(exec_prefix, 0, sizeof(exec_prefix));
Victor Stinner85ce0a72019-09-24 00:55:48 +02001229 status = calculate_exec_prefix(calculate, pathconfig, argv0_path,
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001230 exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
Victor Stinner331a6a52019-05-27 16:39:22 +02001231 if (_PyStatus_EXCEPTION(status)) {
1232 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001233 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001234
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001235 if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001236 calculate->warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001237 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001238 fprintf(stderr,
1239 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1240 }
1241
Victor Stinnere2677932019-09-21 01:50:16 +02001242 if (pathconfig->module_search_path == NULL) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001243 status = calculate_module_search_path(calculate, pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +02001244 prefix, exec_prefix, zip_path);
Victor Stinnere2677932019-09-21 01:50:16 +02001245 if (_PyStatus_EXCEPTION(status)) {
1246 return status;
1247 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001248 }
1249
Victor Stinner331a6a52019-05-27 16:39:22 +02001250 if (pathconfig->prefix == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +02001251 status = calculate_set_prefix(calculate, pathconfig, prefix);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001252 if (_PyStatus_EXCEPTION(status)) {
1253 return status;
1254 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001255 }
1256
Victor Stinner331a6a52019-05-27 16:39:22 +02001257 if (pathconfig->exec_prefix == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +02001258 status = calculate_set_exec_prefix(calculate, pathconfig, exec_prefix);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001259 if (_PyStatus_EXCEPTION(status)) {
1260 return status;
1261 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001262 }
1263
Victor Stinner331a6a52019-05-27 16:39:22 +02001264 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001265}
1266
1267
Victor Stinner85ce0a72019-09-24 00:55:48 +02001268/* Calculate the Python path configuration.
1269
1270 Inputs:
1271
1272 - PATH environment variable
1273 - Macros: PYTHONPATH, PREFIX, EXEC_PREFIX, VERSION (ex: "3.9").
1274 PREFIX and EXEC_PREFIX are generated by the configure script.
1275 PYTHONPATH macro is the default search path.
1276 - pybuilddir.txt file
1277 - pyvenv.cfg configuration file
1278 - PyConfig fields ('config' function argument):
1279
1280 - pathconfig_warnings
1281 - pythonpath_env (PYTHONPATH environment variable)
1282
1283 - _PyPathConfig fields ('pathconfig' function argument):
1284
1285 - program_name: see config_init_program_name()
1286 - home: Py_SetPythonHome() or PYTHONHOME environment variable
1287
1288 - current working directory: see copy_absolute()
1289
1290 Outputs, 'pathconfig' fields:
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001291
1292 - program_full_path
1293 - module_search_path
1294 - prefix
1295 - exec_prefix
1296
Victor Stinner85ce0a72019-09-24 00:55:48 +02001297 If a field is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001298PyStatus
1299_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001300{
Victor Stinner331a6a52019-05-27 16:39:22 +02001301 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001302 PyCalculatePath calculate;
1303 memset(&calculate, 0, sizeof(calculate));
1304
Victor Stinner331a6a52019-05-27 16:39:22 +02001305 status = calculate_init(&calculate, config);
1306 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001307 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001308 }
1309
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001310 status = calculate_path(&calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001311 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001312 goto done;
1313 }
1314
Victor Stinner331a6a52019-05-27 16:39:22 +02001315 status = _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001316
Victor Stinner9316ee42017-11-25 03:17:57 +01001317done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001318 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001319 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001320}
Victor Stinner46972b72017-11-24 22:55:40 +01001321
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001322#ifdef __cplusplus
1323}
1324#endif