blob: 3dcfcef7bd78560bb8d0a6bd7e48256f953a58cf [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 Stinner871ff772019-05-17 23:54:00 +02004#include "pycore_coreconfig.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
98 * these authomatic path computations.
99 *
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 Stinnerdb719752019-05-01 05:35:33 +0200118 ? _Py_INIT_ERR("cannot decode " NAME) \
Victor Stinner9316ee42017-11-25 03:17:57 +0100119 : _Py_INIT_NO_MEMORY()
120
Victor Stinnerdb719752019-05-01 05:35:33 +0200121#define PATHLEN_ERR() _Py_INIT_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 Stinner0327bde2017-11-23 17:03:20 +0100126 wchar_t *pythonpath; /* PYTHONPATH define */
127 wchar_t *prefix; /* PREFIX define */
128 wchar_t *exec_prefix; /* EXEC_PREFIX define */
129
130 wchar_t *lib_python; /* "lib/pythonX.Y" */
131 wchar_t argv0_path[MAXPATHLEN+1];
132 wchar_t zip_path[MAXPATHLEN+1]; /* ".../lib/pythonXY.zip" */
133
134 int prefix_found; /* found platform independent libraries? */
135 int exec_prefix_found; /* found the platform dependent libraries? */
136} PyCalculatePath;
137
138static const wchar_t delimiter[2] = {DELIM, '\0'};
139static const wchar_t separator[2] = {SEP, '\0'};
Victor Stinner0327bde2017-11-23 17:03:20 +0100140
Martin v. Löwis790465f2008-04-05 20:41:37 +0000141
Victor Stinner91afbb62015-03-24 12:16:28 +0100142/* Get file status. Encode the path to the locale encoding. */
Victor Stinner91afbb62015-03-24 12:16:28 +0100143static int
144_Py_wstat(const wchar_t* path, struct stat *buf)
145{
146 int err;
147 char *fname;
Victor Stinner9dd76202017-12-21 16:20:32 +0100148 fname = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner91afbb62015-03-24 12:16:28 +0100149 if (fname == NULL) {
150 errno = EINVAL;
151 return -1;
152 }
153 err = stat(fname, buf);
Victor Stinner9dd76202017-12-21 16:20:32 +0100154 PyMem_RawFree(fname);
Victor Stinner91afbb62015-03-24 12:16:28 +0100155 return err;
156}
157
Victor Stinner0327bde2017-11-23 17:03:20 +0100158
Guido van Rossum305e5d01997-04-11 17:18:45 +0000159static void
Martin v. Löwis790465f2008-04-05 20:41:37 +0000160reduce(wchar_t *dir)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000161{
Martin v. Löwis790465f2008-04-05 20:41:37 +0000162 size_t i = wcslen(dir);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100163 while (i > 0 && dir[i] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000164 --i;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100165 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000166 dir[i] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +0000167}
Guido van Rossumd29806c1998-01-19 22:06:22 +0000168
Victor Stinner0327bde2017-11-23 17:03:20 +0100169
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100170/* Is file, not directory */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000171static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100172isfile(const wchar_t *filename)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000173{
Fred Drakeedabdc12000-07-08 06:16:37 +0000174 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100175 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000176 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100177 }
178 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000179 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100180 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000181 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000182}
183
184
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100185/* Is module -- check for .pyc too */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000186static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100187ismodule(wchar_t *filename, size_t filename_len)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000188{
Victor Stinner0327bde2017-11-23 17:03:20 +0100189 if (isfile(filename)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000190 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100191 }
Guido van Rossumd29806c1998-01-19 22:06:22 +0000192
Fred Drakeedabdc12000-07-08 06:16:37 +0000193 /* Check for the compiled version of prefix. */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100194 if (wcslen(filename) + 2 <= filename_len) {
Brett Cannonf299abd2015-04-13 14:21:02 -0400195 wcscat(filename, L"c");
Victor Stinner0327bde2017-11-23 17:03:20 +0100196 if (isfile(filename)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000197 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100198 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000199 }
200 return 0;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000201}
202
203
Victor Stinner0327bde2017-11-23 17:03:20 +0100204/* Is executable file */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000205static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100206isxfile(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000207{
Fred Drakeedabdc12000-07-08 06:16:37 +0000208 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100209 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000210 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100211 }
212 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000213 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100214 }
215 if ((buf.st_mode & 0111) == 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000216 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100217 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000218 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000219}
220
221
Victor Stinner0327bde2017-11-23 17:03:20 +0100222/* Is directory */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000223static int
Victor Stinner0327bde2017-11-23 17:03:20 +0100224isdir(wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000225{
Fred Drakeedabdc12000-07-08 06:16:37 +0000226 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100227 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000228 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100229 }
230 if (!S_ISDIR(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000231 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100232 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000233 return 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000234}
235
236
Tim Petersec8c5a92004-08-08 01:00:47 +0000237/* Add a path component, by appending stuff to buffer.
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100238 buflen: 'buffer' length in characters including trailing NUL. */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100239static _PyInitError
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100240joinpath(wchar_t *buffer, const wchar_t *stuff, size_t buflen)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000241{
Fred Drakeedabdc12000-07-08 06:16:37 +0000242 size_t n, k;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100243 if (stuff[0] != SEP) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000244 n = wcslen(buffer);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100245 if (n >= buflen) {
246 return PATHLEN_ERR();
247 }
248
249 if (n > 0 && buffer[n-1] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000250 buffer[n++] = SEP;
Victor Stinner0327bde2017-11-23 17:03:20 +0100251 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000252 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100253 else {
254 n = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100255 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100256
Martin v. Löwis790465f2008-04-05 20:41:37 +0000257 k = wcslen(stuff);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100258 if (n + k >= buflen) {
259 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100260 }
Martin v. Löwis790465f2008-04-05 20:41:37 +0000261 wcsncpy(buffer+n, stuff, k);
Fred Drakeedabdc12000-07-08 06:16:37 +0000262 buffer[n+k] = '\0';
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100263
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100264 return _Py_INIT_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000265}
266
Victor Stinner0327bde2017-11-23 17:03:20 +0100267
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100268static inline int
269safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
270{
271 size_t srclen = wcslen(src);
272 if (n <= srclen) {
273 dst[0] = L'\0';
274 return -1;
275 }
276 memcpy(dst, src, (srclen + 1) * sizeof(wchar_t));
277 return 0;
278}
279
280
Guido van Rossume296ced2001-09-28 20:00:29 +0000281/* copy_absolute requires that path be allocated at least
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100282 'pathlen' characters (including trailing NUL). */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100283static _PyInitError
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100284copy_absolute(wchar_t *path, const wchar_t *p, size_t pathlen)
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000285{
Victor Stinner0327bde2017-11-23 17:03:20 +0100286 if (p[0] == SEP) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100287 if (safe_wcscpy(path, p, pathlen) < 0) {
288 return PATHLEN_ERR();
289 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100290 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000291 else {
Victor Stinnerf4061da2010-10-14 12:37:19 +0000292 if (!_Py_wgetcwd(path, pathlen)) {
Victor Stinner4f3abb02010-10-07 23:29:18 +0000293 /* unable to get the current directory */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100294 if (safe_wcscpy(path, p, pathlen) < 0) {
295 return PATHLEN_ERR();
296 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100297 return _Py_INIT_OK();
Victor Stinner4f3abb02010-10-07 23:29:18 +0000298 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100299 if (p[0] == '.' && p[1] == SEP) {
Guido van Rossume296ced2001-09-28 20:00:29 +0000300 p += 2;
Victor Stinner0327bde2017-11-23 17:03:20 +0100301 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100302 _PyInitError err = joinpath(path, p, pathlen);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100303 if (_Py_INIT_FAILED(err)) {
304 return err;
305 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000306 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100307 return _Py_INIT_OK();
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000308}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000309
Victor Stinner0327bde2017-11-23 17:03:20 +0100310
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100311/* path_len: path length in characters including trailing NUL */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100312static _PyInitError
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100313absolutize(wchar_t *path, size_t path_len)
Guido van Rossume296ced2001-09-28 20:00:29 +0000314{
Victor Stinner0327bde2017-11-23 17:03:20 +0100315 if (path[0] == SEP) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100316 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100317 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100318
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100319 wchar_t abs_path[MAXPATHLEN+1];
320 _PyInitError err = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path));
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100321 if (_Py_INIT_FAILED(err)) {
322 return err;
323 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100324
325 if (safe_wcscpy(path, abs_path, path_len) < 0) {
326 return PATHLEN_ERR();
327 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100328 return _Py_INIT_OK();
Guido van Rossume296ced2001-09-28 20:00:29 +0000329}
330
Victor Stinner0327bde2017-11-23 17:03:20 +0100331
E. M. Bray7a7693e2018-10-05 13:38:50 +0200332#if defined(__CYGWIN__) || defined(__MINGW32__)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200333#ifndef EXE_SUFFIX
334#define EXE_SUFFIX L".exe"
335#endif
336
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100337/* pathlen: 'path' length in characters including trailing NUL */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100338static _PyInitError
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100339add_exe_suffix(wchar_t *progpath, size_t progpathlen)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200340{
341 /* Check for already have an executable suffix */
342 size_t n = wcslen(progpath);
343 size_t s = wcslen(EXE_SUFFIX);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100344 if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
345 return _Py_INIT_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200346 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100347
348 if (n + s >= progpathlen) {
349 return PATHLEN_ERR();
350 }
351 wcsncpy(progpath + n, EXE_SUFFIX, s);
352 progpath[n+s] = '\0';
353
354 if (!isxfile(progpath)) {
355 /* Path that added suffix is invalid: truncate (remove suffix) */
356 progpath[n] = '\0';
357 }
358
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100359 return _Py_INIT_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200360}
361#endif
362
363
Guido van Rossume296ced2001-09-28 20:00:29 +0000364/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000365 bytes long.
366*/
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100367static _PyInitError
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100368search_for_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate,
369 wchar_t *prefix, size_t prefix_len,
370 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000371{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100372 _PyInitError err;
Fred Drakeedabdc12000-07-08 06:16:37 +0000373 size_t n;
Martin v. Löwis790465f2008-04-05 20:41:37 +0000374 wchar_t *vpath;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000375
Fred Drakeedabdc12000-07-08 06:16:37 +0000376 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100377 if (core_config->home) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100378 if (safe_wcscpy(prefix, core_config->home, prefix_len) < 0) {
379 return PATHLEN_ERR();
380 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100381 wchar_t *delim = wcschr(prefix, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100382 if (delim) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000383 *delim = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100384 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100385 err = joinpath(prefix, calculate->lib_python, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100386 if (_Py_INIT_FAILED(err)) {
387 return err;
388 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100389 err = joinpath(prefix, LANDMARK, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100390 if (_Py_INIT_FAILED(err)) {
391 return err;
392 }
393 *found = 1;
394 return _Py_INIT_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 Stinnerfaddaed2019-03-19 02:58:14 +0100398 if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
399 return PATHLEN_ERR();
400 }
401 err = joinpath(prefix, L"Modules/Setup.local", prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100402 if (_Py_INIT_FAILED(err)) {
403 return err;
404 }
405
Victor Stinner9316ee42017-11-25 03:17:57 +0100406 if (isfile(prefix)) {
Neil Schemenauer6cf07022001-01-24 17:13:11 +0000407 /* Check VPATH to see if argv0_path is in the build directory. */
Victor Stinnerf6a271a2014-08-01 12:28:48 +0200408 vpath = Py_DecodeLocale(VPATH, NULL);
Victor Stinner21582312010-10-23 00:13:28 +0000409 if (vpath != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100410 if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
411 return PATHLEN_ERR();
412 }
413 err = joinpath(prefix, vpath, prefix_len);
Victor Stinner1a7425f2013-07-07 16:25:15 +0200414 PyMem_RawFree(vpath);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100415 if (_Py_INIT_FAILED(err)) {
416 return err;
417 }
418
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100419 err = joinpath(prefix, L"Lib", prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100420 if (_Py_INIT_FAILED(err)) {
421 return err;
422 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100423 err = joinpath(prefix, LANDMARK, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100424 if (_Py_INIT_FAILED(err)) {
425 return err;
426 }
427
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100428 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100429 *found = -1;
430 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100431 }
Victor Stinner21582312010-10-23 00:13:28 +0000432 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000433 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000434
Fred Drakeedabdc12000-07-08 06:16:37 +0000435 /* Search from argv0_path, until root is found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100436 err = copy_absolute(prefix, calculate->argv0_path, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100437 if (_Py_INIT_FAILED(err)) {
438 return err;
439 }
440
Fred Drakeedabdc12000-07-08 06:16:37 +0000441 do {
Victor Stinner9316ee42017-11-25 03:17:57 +0100442 n = wcslen(prefix);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100443 err = joinpath(prefix, calculate->lib_python, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100444 if (_Py_INIT_FAILED(err)) {
445 return err;
446 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100447 err = joinpath(prefix, LANDMARK, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100448 if (_Py_INIT_FAILED(err)) {
449 return err;
450 }
451
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100452 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100453 *found = 1;
454 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100455 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100456 prefix[n] = L'\0';
457 reduce(prefix);
458 } while (prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000459
Fred Drakeedabdc12000-07-08 06:16:37 +0000460 /* Look at configure's PREFIX */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100461 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
462 return PATHLEN_ERR();
463 }
464 err = joinpath(prefix, calculate->lib_python, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100465 if (_Py_INIT_FAILED(err)) {
466 return err;
467 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100468 err = joinpath(prefix, LANDMARK, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100469 if (_Py_INIT_FAILED(err)) {
470 return err;
471 }
472
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100473 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100474 *found = 1;
475 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100476 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000477
Fred Drakeedabdc12000-07-08 06:16:37 +0000478 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100479 *found = 0;
480 return _Py_INIT_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000481}
482
483
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100484static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100485calculate_prefix(const _PyCoreConfig *core_config,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100486 PyCalculatePath *calculate, wchar_t *prefix, size_t prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100487{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100488 _PyInitError err;
489
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100490 err = search_for_prefix(core_config, calculate, prefix, prefix_len,
491 &calculate->prefix_found);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100492 if (_Py_INIT_FAILED(err)) {
493 return err;
494 }
495
Victor Stinner0327bde2017-11-23 17:03:20 +0100496 if (!calculate->prefix_found) {
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200497 if (core_config->pathconfig_warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100498 fprintf(stderr,
499 "Could not find platform independent libraries <prefix>\n");
500 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100501 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
502 return PATHLEN_ERR();
503 }
504 err = joinpath(prefix, calculate->lib_python, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100505 if (_Py_INIT_FAILED(err)) {
506 return err;
507 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100508 }
509 else {
Victor Stinner9316ee42017-11-25 03:17:57 +0100510 reduce(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100511 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100512 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100513}
514
515
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100516static _PyInitError
517calculate_reduce_prefix(PyCalculatePath *calculate,
518 wchar_t *prefix, size_t prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100519{
520 /* Reduce prefix and exec_prefix to their essence,
521 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
522 * If we're loading relative to the build directory,
523 * return the compiled-in defaults instead.
524 */
525 if (calculate->prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100526 reduce(prefix);
527 reduce(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100528 /* The prefix is the root directory, but reduce() chopped
529 * off the "/". */
Victor Stinner9316ee42017-11-25 03:17:57 +0100530 if (!prefix[0]) {
531 wcscpy(prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100532 }
533 }
534 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100535 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
536 return PATHLEN_ERR();
537 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100538 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100539 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100540}
541
542
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000543/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000544 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000545*/
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100546static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100547search_for_exec_prefix(const _PyCoreConfig *core_config,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100548 PyCalculatePath *calculate,
549 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100550 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000551{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100552 _PyInitError err;
Fred Drakeedabdc12000-07-08 06:16:37 +0000553 size_t n;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000554
Fred Drakeedabdc12000-07-08 06:16:37 +0000555 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100556 if (core_config->home) {
557 wchar_t *delim = wcschr(core_config->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100558 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100559 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
560 return PATHLEN_ERR();
561 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100562 }
563 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100564 if (safe_wcscpy(exec_prefix, core_config->home, exec_prefix_len) < 0) {
565 return PATHLEN_ERR();
566 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100567 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100568 err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100569 if (_Py_INIT_FAILED(err)) {
570 return err;
571 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100572 err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100573 if (_Py_INIT_FAILED(err)) {
574 return err;
575 }
576 *found = 1;
577 return _Py_INIT_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000578 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000579
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000580 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
581 is written by setup.py and contains the relative path to the location
582 of shared library modules. */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100583 if (safe_wcscpy(exec_prefix, calculate->argv0_path, exec_prefix_len) < 0) {
584 return PATHLEN_ERR();
585 }
586 err = joinpath(exec_prefix, L"pybuilddir.txt", exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100587 if (_Py_INIT_FAILED(err)) {
588 return err;
589 }
590
Victor Stinner9316ee42017-11-25 03:17:57 +0100591 if (isfile(exec_prefix)) {
592 FILE *f = _Py_wfopen(exec_prefix, L"rb");
Victor Stinner0327bde2017-11-23 17:03:20 +0100593 if (f == NULL) {
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000594 errno = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100595 }
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000596 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100597 char buf[MAXPATHLEN + 1];
598 n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, f);
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000599 buf[n] = '\0';
600 fclose(f);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100601
Victor Stinner5f9cf232019-03-19 01:46:25 +0100602 wchar_t *pybuilddir;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100603 size_t dec_len;
Victor Stinner5f9cf232019-03-19 01:46:25 +0100604 pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
605 if (!pybuilddir) {
606 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000607 }
Victor Stinner5f9cf232019-03-19 01:46:25 +0100608
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100609 if (safe_wcscpy(exec_prefix, calculate->argv0_path, exec_prefix_len) < 0) {
610 return PATHLEN_ERR();
611 }
612 err = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
Victor Stinner5f9cf232019-03-19 01:46:25 +0100613 PyMem_RawFree(pybuilddir );
614 if (_Py_INIT_FAILED(err)) {
615 return err;
616 }
617
618 *found = -1;
619 return _Py_INIT_OK();
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000620 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000621 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000622
Fred Drakeedabdc12000-07-08 06:16:37 +0000623 /* Search from argv0_path, until root is found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100624 err = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100625 if (_Py_INIT_FAILED(err)) {
626 return err;
627 }
628
Fred Drakeedabdc12000-07-08 06:16:37 +0000629 do {
Victor Stinner9316ee42017-11-25 03:17:57 +0100630 n = wcslen(exec_prefix);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100631 err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100632 if (_Py_INIT_FAILED(err)) {
633 return err;
634 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100635 err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100636 if (_Py_INIT_FAILED(err)) {
637 return err;
638 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100639 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100640 *found = 1;
641 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100642 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100643 exec_prefix[n] = L'\0';
644 reduce(exec_prefix);
645 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000646
Fred Drakeedabdc12000-07-08 06:16:37 +0000647 /* Look at configure's EXEC_PREFIX */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100648 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
649 return PATHLEN_ERR();
650 }
651 err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100652 if (_Py_INIT_FAILED(err)) {
653 return err;
654 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100655 err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100656 if (_Py_INIT_FAILED(err)) {
657 return err;
658 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100659 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100660 *found = 1;
661 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100662 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000663
Fred Drakeedabdc12000-07-08 06:16:37 +0000664 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100665 *found = 0;
666 return _Py_INIT_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000667}
668
Guido van Rossum305e5d01997-04-11 17:18:45 +0000669
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100670static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100671calculate_exec_prefix(const _PyCoreConfig *core_config,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100672 PyCalculatePath *calculate,
673 wchar_t *exec_prefix, size_t exec_prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100674{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100675 _PyInitError err;
676
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100677 err = search_for_exec_prefix(core_config, calculate,
678 exec_prefix, exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100679 &calculate->exec_prefix_found);
680 if (_Py_INIT_FAILED(err)) {
681 return err;
682 }
683
Victor Stinner0327bde2017-11-23 17:03:20 +0100684 if (!calculate->exec_prefix_found) {
Victor Stinner9ef5dca2019-05-16 17:38:16 +0200685 if (core_config->pathconfig_warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100686 fprintf(stderr,
687 "Could not find platform dependent libraries <exec_prefix>\n");
688 }
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 }
692 err = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100693 if (_Py_INIT_FAILED(err)) {
694 return err;
695 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100696 }
697 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100698 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100699}
700
701
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100702static _PyInitError
703calculate_reduce_exec_prefix(PyCalculatePath *calculate,
704 wchar_t *exec_prefix, size_t exec_prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100705{
706 if (calculate->exec_prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100707 reduce(exec_prefix);
708 reduce(exec_prefix);
709 reduce(exec_prefix);
710 if (!exec_prefix[0]) {
711 wcscpy(exec_prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100712 }
713 }
714 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100715 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
716 return PATHLEN_ERR();
717 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100718 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100719 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100720}
721
722
Victor Stinner9316ee42017-11-25 03:17:57 +0100723static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100724calculate_program_full_path(const _PyCoreConfig *core_config,
Victor Stinner31a83932017-12-04 13:39:15 +0100725 PyCalculatePath *calculate, _PyPathConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +0100726{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100727 _PyInitError err;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100728 wchar_t program_full_path[MAXPATHLEN + 1];
729 const size_t program_full_path_len = Py_ARRAY_LENGTH(program_full_path);
Victor Stinnerb64de462017-12-01 18:27:09 +0100730 memset(program_full_path, 0, sizeof(program_full_path));
Victor Stinner9316ee42017-11-25 03:17:57 +0100731
Victor Stinnerb9197952017-11-23 19:02:04 +0100732#ifdef __APPLE__
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100733 char execpath[MAXPATHLEN + 1];
Victor Stinnerb9197952017-11-23 19:02:04 +0100734#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100735 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100736#else
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100737 unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100738#endif
Victor Stinnerb9197952017-11-23 19:02:04 +0100739#endif
740
Victor Stinner0327bde2017-11-23 17:03:20 +0100741 /* If there is no slash in the argv0 path, then we have to
742 * assume python is on the user's $PATH, since there's no
743 * other way to find a directory to start the search from. If
744 * $PATH isn't exported, you lose.
745 */
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100746 if (wcschr(core_config->program_name, SEP)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100747 if (safe_wcscpy(program_full_path, core_config->program_name,
748 program_full_path_len) < 0) {
749 return PATHLEN_ERR();
750 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100751 }
Jack Jansen1afd4802004-06-03 14:33:03 +0000752#ifdef __APPLE__
Jack Jansen1afd4802004-06-03 14:33:03 +0000753 /* On Mac OS X, if a script uses an interpreter of the form
754 * "#!/opt/python2.3/bin/python", the kernel only passes "python"
755 * as argv[0], which falls through to the $PATH search below.
756 * If /opt/python2.3/bin isn't in your path, or is near the end,
757 * this algorithm may incorrectly find /usr/bin/python. To work
758 * around this, we can use _NSGetExecutablePath to get a better
759 * hint of what the intended interpreter was, although this
760 * will fail if a relative path was used. but in that case,
761 * absolutize() should help us out below
762 */
Victor Stinnerf04ebe22017-11-25 00:01:23 +0100763 else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
764 execpath[0] == SEP)
765 {
Victor Stinner31a83932017-12-04 13:39:15 +0100766 size_t len;
767 wchar_t *path = Py_DecodeLocale(execpath, &len);
768 if (path == NULL) {
769 return DECODE_LOCALE_ERR("executable path", len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100771 if (safe_wcscpy(program_full_path, path, program_full_path_len) < 0) {
772 PyMem_RawFree(path);
773 return PATHLEN_ERR();
774 }
Victor Stinner31a83932017-12-04 13:39:15 +0100775 PyMem_RawFree(path);
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000776 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000777#endif /* __APPLE__ */
Victor Stinner0327bde2017-11-23 17:03:20 +0100778 else if (calculate->path_env) {
779 wchar_t *path = calculate->path_env;
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000780 while (1) {
781 wchar_t *delim = wcschr(path, DELIM);
Jack Jansen55070f52001-12-02 23:56:28 +0000782
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000783 if (delim) {
784 size_t len = delim - path;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100785 if (len >= program_full_path_len) {
786 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100787 }
Victor Stinnerb64de462017-12-01 18:27:09 +0100788 wcsncpy(program_full_path, path, len);
789 program_full_path[len] = '\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000790 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100791 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100792 if (safe_wcscpy(program_full_path, path,
793 program_full_path_len) < 0) {
794 return PATHLEN_ERR();
795 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100796 }
Jack Jansen55070f52001-12-02 23:56:28 +0000797
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100798 err = joinpath(program_full_path, core_config->program_name,
799 program_full_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100800 if (_Py_INIT_FAILED(err)) {
801 return err;
802 }
803
Victor Stinnerb64de462017-12-01 18:27:09 +0100804 if (isxfile(program_full_path)) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000805 break;
Victor Stinner0327bde2017-11-23 17:03:20 +0100806 }
Jack Jansen55070f52001-12-02 23:56:28 +0000807
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000808 if (!delim) {
Victor Stinnerb64de462017-12-01 18:27:09 +0100809 program_full_path[0] = L'\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000810 break;
811 }
812 path = delim + 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000813 }
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000814 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100815 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100816 program_full_path[0] = '\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100817 }
Victor Stinnerb64de462017-12-01 18:27:09 +0100818 if (program_full_path[0] != SEP && program_full_path[0] != '\0') {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100819 err = absolutize(program_full_path, program_full_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100820 if (_Py_INIT_FAILED(err)) {
821 return err;
822 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100823 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200824#if defined(__CYGWIN__) || defined(__MINGW32__)
825 /* For these platforms it is necessary to ensure that the .exe suffix
826 * is appended to the filename, otherwise there is potential for
827 * sys.executable to return the name of a directory under the same
828 * path (bpo-28441).
829 */
830 if (program_full_path[0] != '\0') {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100831 err = add_exe_suffix(program_full_path, program_full_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100832 if (_Py_INIT_FAILED(err)) {
833 return err;
834 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200835 }
836#endif
Victor Stinner9316ee42017-11-25 03:17:57 +0100837
Victor Stinnerb64de462017-12-01 18:27:09 +0100838 config->program_full_path = _PyMem_RawWcsdup(program_full_path);
839 if (config->program_full_path == NULL) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100840 return _Py_INIT_NO_MEMORY();
841 }
842 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100843}
844
845
Victor Stinner9316ee42017-11-25 03:17:57 +0100846static _PyInitError
Victor Stinnerb64de462017-12-01 18:27:09 +0100847calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path)
Victor Stinner0327bde2017-11-23 17:03:20 +0100848{
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100849 const size_t argv0_path_len = Py_ARRAY_LENGTH(calculate->argv0_path);
850 if (safe_wcscpy(calculate->argv0_path, program_full_path, argv0_path_len) < 0) {
851 return PATHLEN_ERR();
852 }
Jack Jansen55070f52001-12-02 23:56:28 +0000853
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000854#ifdef WITH_NEXT_FRAMEWORK
Victor Stinner0327bde2017-11-23 17:03:20 +0100855 NSModule pythonModule;
856
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000857 /* On Mac OS X we have a special case if we're running from a framework.
858 ** This is because the python home should be set relative to the library,
859 ** which is in the framework, not relative to the executable, which may
860 ** be outside of the framework. Except when we're in the build directory...
861 */
Fred Drakeedabdc12000-07-08 06:16:37 +0000862 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
863 /* Use dylib functions to find out where the framework was loaded from */
Victor Stinner0327bde2017-11-23 17:03:20 +0100864 const char* modPath = NSLibraryNameForModule(pythonModule);
Vinay Sajip90db6612012-07-17 17:33:46 +0100865 if (modPath != NULL) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000866 /* We're in a framework. */
Jack Jansene925faf2001-08-15 01:14:40 +0000867 /* See if we might be in the build directory. The framework in the
868 ** build directory is incomplete, it only has the .dylib and a few
869 ** needed symlinks, it doesn't have the Lib directories and such.
870 ** If we're running with the framework from the build directory we must
871 ** be running the interpreter in the build directory, so we use the
872 ** build-directory-specific logic to find Lib and such.
873 */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100874 _PyInitError err;
Victor Stinner9316ee42017-11-25 03:17:57 +0100875 size_t len;
876 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100877 if (wbuf == NULL) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100878 return DECODE_LOCALE_ERR("framework location", len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100879 }
880
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100881 if (safe_wcscpy(calculate->argv0_path, wbuf, argv0_path_len) < 0) {
882 return PATHLEN_ERR();
883 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100884 reduce(calculate->argv0_path);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100885 err = joinpath(calculate->argv0_path, calculate->lib_python, argv0_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100886 if (_Py_INIT_FAILED(err)) {
887 PyMem_RawFree(wbuf);
888 return err;
889 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100890 err = joinpath(calculate->argv0_path, LANDMARK, argv0_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100891 if (_Py_INIT_FAILED(err)) {
892 PyMem_RawFree(wbuf);
893 return err;
894 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100895 if (!ismodule(calculate->argv0_path,
896 Py_ARRAY_LENGTH(calculate->argv0_path))) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000897 /* We are in the build directory so use the name of the
898 executable - we know that the absolute path is passed */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100899 if (safe_wcscpy(calculate->argv0_path, program_full_path,
900 argv0_path_len) < 0) {
901 return PATHLEN_ERR();
902 }
Jack Jansene925faf2001-08-15 01:14:40 +0000903 }
904 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100905 /* Use the location of the library as the program_full_path */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100906 if (safe_wcscpy(calculate->argv0_path, wbuf, argv0_path_len) < 0) {
907 return PATHLEN_ERR();
908 }
Jack Jansene925faf2001-08-15 01:14:40 +0000909 }
Victor Stinner1a7425f2013-07-07 16:25:15 +0200910 PyMem_RawFree(wbuf);
Fred Drakeedabdc12000-07-08 06:16:37 +0000911 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000912#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000913
Guido van Rossum305e5d01997-04-11 17:18:45 +0000914#if HAVE_READLINK
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100915 wchar_t tmpbuffer[MAXPATHLEN + 1];
916 const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
917 int linklen = _Py_wreadlink(program_full_path, tmpbuffer, buflen);
Victor Stinner0327bde2017-11-23 17:03:20 +0100918 while (linklen != -1) {
919 if (tmpbuffer[0] == SEP) {
920 /* tmpbuffer should never be longer than MAXPATHLEN,
921 but extra check does not hurt */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100922 if (safe_wcscpy(calculate->argv0_path, tmpbuffer, argv0_path_len) < 0) {
923 return PATHLEN_ERR();
924 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000925 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100926 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100927 /* Interpret relative to program_full_path */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100928 _PyInitError err;
Victor Stinner0327bde2017-11-23 17:03:20 +0100929 reduce(calculate->argv0_path);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100930 err = joinpath(calculate->argv0_path, tmpbuffer, argv0_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100931 if (_Py_INIT_FAILED(err)) {
932 return err;
933 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100934 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100935 linklen = _Py_wreadlink(calculate->argv0_path, tmpbuffer, buflen);
Fred Drakeedabdc12000-07-08 06:16:37 +0000936 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000937#endif /* HAVE_READLINK */
938
Victor Stinner0327bde2017-11-23 17:03:20 +0100939 reduce(calculate->argv0_path);
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000940 /* At this point, argv0_path is guaranteed to be less than
Victor Stinner0327bde2017-11-23 17:03:20 +0100941 MAXPATHLEN bytes long. */
Victor Stinner9316ee42017-11-25 03:17:57 +0100942 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100943}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000944
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100945
Victor Stinner0327bde2017-11-23 17:03:20 +0100946/* Search for an "pyvenv.cfg" environment configuration file, first in the
947 executable's directory and then in the parent directory.
948 If found, open it for use when searching for prefixes.
949*/
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100950static _PyInitError
Victor Stinner0327bde2017-11-23 17:03:20 +0100951calculate_read_pyenv(PyCalculatePath *calculate)
952{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100953 _PyInitError err;
Victor Stinner0327bde2017-11-23 17:03:20 +0100954 wchar_t tmpbuffer[MAXPATHLEN+1];
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100955 const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
Victor Stinner0327bde2017-11-23 17:03:20 +0100956 wchar_t *env_cfg = L"pyvenv.cfg";
957 FILE *env_file;
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100958
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100959 if (safe_wcscpy(tmpbuffer, calculate->argv0_path, buflen) < 0) {
960 return PATHLEN_ERR();
961 }
Vinay Sajip90db6612012-07-17 17:33:46 +0100962
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100963 err = joinpath(tmpbuffer, env_cfg, buflen);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100964 if (_Py_INIT_FAILED(err)) {
965 return err;
966 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100967 env_file = _Py_wfopen(tmpbuffer, L"r");
968 if (env_file == NULL) {
969 errno = 0;
970
971 reduce(tmpbuffer);
972 reduce(tmpbuffer);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100973 err = joinpath(tmpbuffer, env_cfg, buflen);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100974 if (_Py_INIT_FAILED(err)) {
975 return err;
976 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100977
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100978 env_file = _Py_wfopen(tmpbuffer, L"r");
979 if (env_file == NULL) {
980 errno = 0;
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100981 }
982 }
983
Victor Stinner0327bde2017-11-23 17:03:20 +0100984 if (env_file == NULL) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100985 return _Py_INIT_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000986 }
Guido van Rossume296ced2001-09-28 20:00:29 +0000987
Victor Stinner0327bde2017-11-23 17:03:20 +0100988 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100989 if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, buflen)) {
990 if (safe_wcscpy(calculate->argv0_path, tmpbuffer,
991 Py_ARRAY_LENGTH(calculate->argv0_path)) < 0) {
992 return PATHLEN_ERR();
993 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000994 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100995 fclose(env_file);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100996 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100997}
Just van Rossum52e14d62002-12-30 22:08:05 +0000998
Guido van Rossum305e5d01997-04-11 17:18:45 +0000999
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001000static _PyInitError
Victor Stinner9316ee42017-11-25 03:17:57 +01001001calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +01001002{
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001003 _PyInitError err;
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001004 const size_t zip_path_len = Py_ARRAY_LENGTH(calculate->zip_path);
1005 if (safe_wcscpy(calculate->zip_path, prefix, zip_path_len) < 0) {
1006 return PATHLEN_ERR();
1007 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001008
Victor Stinner0327bde2017-11-23 17:03:20 +01001009 if (calculate->prefix_found > 0) {
1010 /* Use the reduced prefix returned by Py_GetPrefix() */
1011 reduce(calculate->zip_path);
1012 reduce(calculate->zip_path);
Victor Stinnerd4341102017-11-23 00:12:09 +01001013 }
1014 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001015 if (safe_wcscpy(calculate->zip_path, calculate->prefix, zip_path_len) < 0) {
1016 return PATHLEN_ERR();
1017 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001018 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001019 err = joinpath(calculate->zip_path, L"lib/python00.zip", zip_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001020 if (_Py_INIT_FAILED(err)) {
1021 return err;
1022 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001023
1024 /* Replace "00" with version */
1025 size_t bufsz = wcslen(calculate->zip_path);
1026 calculate->zip_path[bufsz - 6] = VERSION[0];
1027 calculate->zip_path[bufsz - 5] = VERSION[2];
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001028 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001029}
1030
1031
Victor Stinner9316ee42017-11-25 03:17:57 +01001032static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001033calculate_module_search_path(const _PyCoreConfig *core_config,
Victor Stinner31a83932017-12-04 13:39:15 +01001034 PyCalculatePath *calculate,
Victor Stinner9316ee42017-11-25 03:17:57 +01001035 const wchar_t *prefix, const wchar_t *exec_prefix,
Victor Stinnerb64de462017-12-01 18:27:09 +01001036 _PyPathConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001037{
1038 /* Calculate size of return buffer */
1039 size_t bufsz = 0;
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001040 if (core_config->module_search_path_env != NULL) {
1041 bufsz += wcslen(core_config->module_search_path_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001042 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001043
Victor Stinner0327bde2017-11-23 17:03:20 +01001044 wchar_t *defpath = calculate->pythonpath;
Victor Stinner9316ee42017-11-25 03:17:57 +01001045 size_t prefixsz = wcslen(prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001046 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001047 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001048
Victor Stinner0327bde2017-11-23 17:03:20 +01001049 if (defpath[0] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001050 /* Paths are relative to prefix */
1051 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001052 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001053
Victor Stinner0327bde2017-11-23 17:03:20 +01001054 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001055 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001056 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001057 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001058 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001059 break;
1060 }
1061 defpath = delim + 1;
1062 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001063
Victor Stinner0327bde2017-11-23 17:03:20 +01001064 bufsz += wcslen(calculate->zip_path) + 1;
Victor Stinner9316ee42017-11-25 03:17:57 +01001065 bufsz += wcslen(exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001066
Victor Stinner0327bde2017-11-23 17:03:20 +01001067 /* Allocate the buffer */
1068 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001069 if (buf == NULL) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001070 return _Py_INIT_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001071 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001072 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001073
Victor Stinner72967a42013-11-16 01:22:04 +01001074 /* Run-time value of $PYTHONPATH goes first */
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001075 if (core_config->module_search_path_env) {
1076 wcscpy(buf, core_config->module_search_path_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001077 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001078 }
Victor Stinner72967a42013-11-16 01:22:04 +01001079
1080 /* Next is the default zip path */
Victor Stinner0327bde2017-11-23 17:03:20 +01001081 wcscat(buf, calculate->zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001082 wcscat(buf, delimiter);
1083
1084 /* Next goes merge of compile-time $PYTHONPATH with
1085 * dynamically located prefix.
1086 */
Victor Stinner0327bde2017-11-23 17:03:20 +01001087 defpath = calculate->pythonpath;
Victor Stinner72967a42013-11-16 01:22:04 +01001088 while (1) {
1089 wchar_t *delim = wcschr(defpath, DELIM);
1090
1091 if (defpath[0] != SEP) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001092 wcscat(buf, prefix);
1093 if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001094 defpath[0] != (delim ? DELIM : L'\0'))
1095 {
1096 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001097 wcscat(buf, separator);
1098 }
Victor Stinner72967a42013-11-16 01:22:04 +01001099 }
1100
1101 if (delim) {
1102 size_t len = delim - defpath + 1;
1103 size_t end = wcslen(buf) + len;
1104 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001105 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001106 }
1107 else {
1108 wcscat(buf, defpath);
1109 break;
1110 }
1111 defpath = delim + 1;
1112 }
1113 wcscat(buf, delimiter);
1114
1115 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinner9316ee42017-11-25 03:17:57 +01001116 wcscat(buf, exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001117
Victor Stinner9316ee42017-11-25 03:17:57 +01001118 config->module_search_path = buf;
1119 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001120}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001121
Victor Stinner0327bde2017-11-23 17:03:20 +01001122
Victor Stinner0327bde2017-11-23 17:03:20 +01001123static _PyInitError
1124calculate_init(PyCalculatePath *calculate,
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001125 const _PyCoreConfig *core_config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001126{
Victor Stinner0327bde2017-11-23 17:03:20 +01001127 size_t len;
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001128 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001129 if (path) {
1130 calculate->path_env = Py_DecodeLocale(path, &len);
1131 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001132 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001133 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001134 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001135
Victor Stinner0327bde2017-11-23 17:03:20 +01001136 calculate->pythonpath = Py_DecodeLocale(PYTHONPATH, &len);
1137 if (!calculate->pythonpath) {
Victor Stinner46972b72017-11-24 22:55:40 +01001138 return DECODE_LOCALE_ERR("PYTHONPATH define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001139 }
1140 calculate->prefix = Py_DecodeLocale(PREFIX, &len);
1141 if (!calculate->prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001142 return DECODE_LOCALE_ERR("PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001143 }
1144 calculate->exec_prefix = Py_DecodeLocale(EXEC_PREFIX, &len);
1145 if (!calculate->prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001146 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001147 }
1148 calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
1149 if (!calculate->lib_python) {
Victor Stinner46972b72017-11-24 22:55:40 +01001150 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001151 }
1152 return _Py_INIT_OK();
1153}
1154
1155
1156static void
1157calculate_free(PyCalculatePath *calculate)
1158{
1159 PyMem_RawFree(calculate->pythonpath);
1160 PyMem_RawFree(calculate->prefix);
1161 PyMem_RawFree(calculate->exec_prefix);
1162 PyMem_RawFree(calculate->lib_python);
1163 PyMem_RawFree(calculate->path_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001164}
1165
1166
Victor Stinner9316ee42017-11-25 03:17:57 +01001167static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001168calculate_path_impl(const _PyCoreConfig *core_config,
Victor Stinner31a83932017-12-04 13:39:15 +01001169 PyCalculatePath *calculate, _PyPathConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001170{
Victor Stinner31a83932017-12-04 13:39:15 +01001171 _PyInitError err;
1172
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001173 err = calculate_program_full_path(core_config, calculate, config);
Victor Stinner9316ee42017-11-25 03:17:57 +01001174 if (_Py_INIT_FAILED(err)) {
1175 return err;
1176 }
1177
Victor Stinnerb64de462017-12-01 18:27:09 +01001178 err = calculate_argv0_path(calculate, config->program_full_path);
Victor Stinner9316ee42017-11-25 03:17:57 +01001179 if (_Py_INIT_FAILED(err)) {
1180 return err;
1181 }
1182
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001183 err = calculate_read_pyenv(calculate);
1184 if (_Py_INIT_FAILED(err)) {
1185 return err;
1186 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001187
1188 wchar_t prefix[MAXPATHLEN+1];
1189 memset(prefix, 0, sizeof(prefix));
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001190 err = calculate_prefix(core_config, calculate,
1191 prefix, Py_ARRAY_LENGTH(prefix));
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001192 if (_Py_INIT_FAILED(err)) {
1193 return err;
1194 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001195
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001196 err = calculate_zip_path(calculate, prefix);
1197 if (_Py_INIT_FAILED(err)) {
1198 return err;
1199 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001200
1201 wchar_t exec_prefix[MAXPATHLEN+1];
1202 memset(exec_prefix, 0, sizeof(exec_prefix));
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001203 err = calculate_exec_prefix(core_config, calculate,
1204 exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001205 if (_Py_INIT_FAILED(err)) {
1206 return err;
1207 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001208
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001209 if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
Victor Stinner9ef5dca2019-05-16 17:38:16 +02001210 core_config->pathconfig_warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001211 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001212 fprintf(stderr,
1213 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1214 }
1215
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001216 err = calculate_module_search_path(core_config, calculate,
Victor Stinner31a83932017-12-04 13:39:15 +01001217 prefix, exec_prefix, config);
Victor Stinner9316ee42017-11-25 03:17:57 +01001218 if (_Py_INIT_FAILED(err)) {
1219 return err;
1220 }
1221
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001222 err = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix));
1223 if (_Py_INIT_FAILED(err)) {
1224 return err;
1225 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001226
1227 config->prefix = _PyMem_RawWcsdup(prefix);
1228 if (config->prefix == NULL) {
1229 return _Py_INIT_NO_MEMORY();
1230 }
1231
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001232 err = calculate_reduce_exec_prefix(calculate,
1233 exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
1234 if (_Py_INIT_FAILED(err)) {
1235 return err;
1236 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001237
1238 config->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
1239 if (config->exec_prefix == NULL) {
1240 return _Py_INIT_NO_MEMORY();
1241 }
1242
1243 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001244}
1245
1246
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001247_PyInitError
Victor Stinnerb1147e42018-07-21 02:06:16 +02001248_PyPathConfig_Calculate_impl(_PyPathConfig *config, const _PyCoreConfig *core_config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001249{
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001250 _PyInitError err;
Victor Stinner0327bde2017-11-23 17:03:20 +01001251 PyCalculatePath calculate;
1252 memset(&calculate, 0, sizeof(calculate));
1253
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001254 err = calculate_init(&calculate, core_config);
Victor Stinner0327bde2017-11-23 17:03:20 +01001255 if (_Py_INIT_FAILED(err)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001256 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001257 }
1258
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001259 err = calculate_path_impl(core_config, &calculate, config);
Victor Stinner9316ee42017-11-25 03:17:57 +01001260 if (_Py_INIT_FAILED(err)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001261 goto done;
1262 }
1263
Victor Stinner9316ee42017-11-25 03:17:57 +01001264 err = _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001265
Victor Stinner9316ee42017-11-25 03:17:57 +01001266done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001267 calculate_free(&calculate);
Victor Stinner9316ee42017-11-25 03:17:57 +01001268 return err;
1269}
Victor Stinner46972b72017-11-24 22:55:40 +01001270
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001271#ifdef __cplusplus
1272}
1273#endif