blob: dd188c612893a9e839ff98ffae7906f99d34aaee [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"
4#include "osdefs.h"
Victor Stinner9fc57a32018-11-07 00:44:03 +01005#include "pycore_fileutils.h"
Victor Stinnera1c249c2018-11-01 03:15:58 +01006#include "pycore_pathconfig.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01007#include "pycore_pystate.h"
Guido van Rossum667d7041995-08-04 04:20:48 +00008
Guido van Rossum305e5d01997-04-11 17:18:45 +00009#include <sys/types.h>
Guido van Rossum21f84971997-06-02 22:18:31 +000010#include <string.h>
Guido van Rossum667d7041995-08-04 04:20:48 +000011
Brett Cannonf6af76d2004-06-26 04:03:06 +000012#ifdef __APPLE__
Victor Stinner0327bde2017-11-23 17:03:20 +010013# include <mach-o/dyld.h>
Guido van Rossum54ecc3d1999-01-27 17:53:11 +000014#endif
15
Guido van Rossum305e5d01997-04-11 17:18:45 +000016/* Search in some common locations for the associated Python libraries.
17 *
18 * Two directories must be found, the platform independent directory
Barry Warsaw90126031997-04-11 20:27:03 +000019 * (prefix), containing the common .py and .pyc files, and the platform
20 * dependent directory (exec_prefix), containing the shared library
21 * modules. Note that prefix and exec_prefix can be the same directory,
22 * but for some installations, they are different.
Guido van Rossum305e5d01997-04-11 17:18:45 +000023 *
Barry Warsaw90126031997-04-11 20:27:03 +000024 * Py_GetPath() carries out separate searches for prefix and exec_prefix.
25 * Each search tries a number of different locations until a ``landmark''
26 * file or directory is found. If no prefix or exec_prefix is found, a
27 * warning message is issued and the preprocessor defined PREFIX and
28 * EXEC_PREFIX are used (even though they will not work); python carries on
29 * as best as is possible, but most imports will fail.
Guido van Rossum305e5d01997-04-11 17:18:45 +000030 *
31 * Before any searches are done, the location of the executable is
Guido van Rossumd8faa362007-04-27 19:54:29 +000032 * determined. If argv[0] has one or more slashes in it, it is used
Barry Warsaw90126031997-04-11 20:27:03 +000033 * unchanged. Otherwise, it must have been invoked from the shell's path,
34 * so we search $PATH for the named executable and use that. If the
35 * executable was not found on $PATH (or there was no $PATH environment
36 * variable), the original argv[0] string is used.
Guido van Rossum305e5d01997-04-11 17:18:45 +000037 *
Barry Warsaw90126031997-04-11 20:27:03 +000038 * Next, the executable location is examined to see if it is a symbolic
39 * link. If so, the link is chased (correctly interpreting a relative
40 * pathname if one is found) and the directory of the link target is used.
Guido van Rossum305e5d01997-04-11 17:18:45 +000041 *
Barry Warsaw90126031997-04-11 20:27:03 +000042 * Finally, argv0_path is set to the directory containing the executable
43 * (i.e. the last component is stripped).
Guido van Rossum305e5d01997-04-11 17:18:45 +000044 *
Barry Warsaw90126031997-04-11 20:27:03 +000045 * With argv0_path in hand, we perform a number of steps. The same steps
46 * are performed for prefix and for exec_prefix, but with a different
47 * landmark.
Guido van Rossum305e5d01997-04-11 17:18:45 +000048 *
49 * Step 1. Are we running python out of the build directory? This is
50 * checked by looking for a different kind of landmark relative to
Barry Warsaw90126031997-04-11 20:27:03 +000051 * argv0_path. For prefix, the landmark's path is derived from the VPATH
52 * preprocessor variable (taking into account that its value is almost, but
53 * not quite, what we need). For exec_prefix, the landmark is
Antoine Pitroueba57b62010-08-14 12:33:18 +000054 * pybuilddir.txt. If the landmark is found, we're done.
Guido van Rossum305e5d01997-04-11 17:18:45 +000055 *
56 * For the remaining steps, the prefix landmark will always be
Jeremy Hylton847a9962000-05-26 21:49:07 +000057 * lib/python$VERSION/os.py and the exec_prefix will always be
Guido van Rossum266033e1997-10-20 23:20:32 +000058 * lib/python$VERSION/lib-dynload, where $VERSION is Python's version
Barry Warsaw90126031997-04-11 20:27:03 +000059 * number as supplied by the Makefile. Note that this means that no more
60 * build directory checking is performed; if the first step did not find
61 * the landmarks, the assumption is that python is running from an
62 * installed setup.
Guido van Rossum305e5d01997-04-11 17:18:45 +000063 *
64 * Step 2. See if the $PYTHONHOME environment variable points to the
Barry Warsaw90126031997-04-11 20:27:03 +000065 * installed location of the Python libraries. If $PYTHONHOME is set, then
66 * it points to prefix and exec_prefix. $PYTHONHOME can be a single
67 * directory, which is used for both, or the prefix and exec_prefix
68 * directories separated by a colon.
Guido van Rossum305e5d01997-04-11 17:18:45 +000069 *
70 * Step 3. Try to find prefix and exec_prefix relative to argv0_path,
Barry Warsaw90126031997-04-11 20:27:03 +000071 * backtracking up the path until it is exhausted. This is the most common
72 * step to succeed. Note that if prefix and exec_prefix are different,
73 * exec_prefix is more likely to be found; however if exec_prefix is a
74 * subdirectory of prefix, both will be found.
Guido van Rossum305e5d01997-04-11 17:18:45 +000075 *
Barry Warsaw90126031997-04-11 20:27:03 +000076 * Step 4. Search the directories pointed to by the preprocessor variables
77 * PREFIX and EXEC_PREFIX. These are supplied by the Makefile but can be
78 * passed in as options to the configure script.
Guido van Rossum305e5d01997-04-11 17:18:45 +000079 *
Barry Warsaw90126031997-04-11 20:27:03 +000080 * That's it!
81 *
82 * Well, almost. Once we have determined prefix and exec_prefix, the
Thomas Wouters7e474022000-07-16 12:04:32 +000083 * preprocessor variable PYTHONPATH is used to construct a path. Each
Barry Warsaw90126031997-04-11 20:27:03 +000084 * relative path on PYTHONPATH is prefixed with prefix. Then the directory
85 * containing the shared library modules is appended. The environment
86 * variable $PYTHONPATH is inserted in front of it all. Finally, the
87 * prefix and exec_prefix globals are tweaked so they reflect the values
88 * expected by other code, by stripping the "lib/python$VERSION/..." stuff
89 * off. If either points to the build directory, the globals are reset to
90 * the corresponding preprocessor variables (so sys.prefix will reflect the
91 * installation location, even though sys.path points into the build
92 * directory). This seems to make more sense given that currently the only
93 * known use of sys.prefix and sys.exec_prefix is for the ILU installation
94 * process to find the installed Python tree.
Antoine Pitroueba57b62010-08-14 12:33:18 +000095 *
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000096 * An embedding application can use Py_SetPath() to override all of
97 * these authomatic path computations.
98 *
Antoine Pitroueba57b62010-08-14 12:33:18 +000099 * NOTE: Windows MSVC builds use PC/getpathp.c instead!
Barry Warsaw90126031997-04-11 20:27:03 +0000100 */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000101
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000102#ifdef __cplusplus
Victor Stinner0327bde2017-11-23 17:03:20 +0100103extern "C" {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000104#endif
105
106
Benjamin Petersonf5854142016-06-02 12:41:35 -0700107#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH)
108#error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000109#endif
Guido van Rossum667d7041995-08-04 04:20:48 +0000110
Guido van Rossum305e5d01997-04-11 17:18:45 +0000111#ifndef LANDMARK
Martin v. Löwis790465f2008-04-05 20:41:37 +0000112#define LANDMARK L"os.py"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000113#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000114
Victor Stinner9316ee42017-11-25 03:17:57 +0100115#define DECODE_LOCALE_ERR(NAME, LEN) \
116 ((LEN) == (size_t)-2) \
Victor Stinner94540602017-12-16 04:54:22 +0100117 ? _Py_INIT_USER_ERR("cannot decode " NAME) \
Victor Stinner9316ee42017-11-25 03:17:57 +0100118 : _Py_INIT_NO_MEMORY()
119
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100120#define PATHLEN_ERR() _Py_INIT_USER_ERR("path configuration: path too long")
121
Victor Stinner0327bde2017-11-23 17:03:20 +0100122typedef struct {
123 wchar_t *path_env; /* PATH environment variable */
Victor Stinner0327bde2017-11-23 17:03:20 +0100124
Victor Stinner0327bde2017-11-23 17:03:20 +0100125 wchar_t *pythonpath; /* PYTHONPATH define */
126 wchar_t *prefix; /* PREFIX define */
127 wchar_t *exec_prefix; /* EXEC_PREFIX define */
128
129 wchar_t *lib_python; /* "lib/pythonX.Y" */
130 wchar_t argv0_path[MAXPATHLEN+1];
131 wchar_t zip_path[MAXPATHLEN+1]; /* ".../lib/pythonXY.zip" */
132
133 int prefix_found; /* found platform independent libraries? */
134 int exec_prefix_found; /* found the platform dependent libraries? */
135} PyCalculatePath;
136
137static const wchar_t delimiter[2] = {DELIM, '\0'};
138static const wchar_t separator[2] = {SEP, '\0'};
Victor Stinner0327bde2017-11-23 17:03:20 +0100139
Martin v. Löwis790465f2008-04-05 20:41:37 +0000140
Victor Stinner91afbb62015-03-24 12:16:28 +0100141/* Get file status. Encode the path to the locale encoding. */
Victor Stinner91afbb62015-03-24 12:16:28 +0100142static int
143_Py_wstat(const wchar_t* path, struct stat *buf)
144{
145 int err;
146 char *fname;
Victor Stinner9dd76202017-12-21 16:20:32 +0100147 fname = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner91afbb62015-03-24 12:16:28 +0100148 if (fname == NULL) {
149 errno = EINVAL;
150 return -1;
151 }
152 err = stat(fname, buf);
Victor Stinner9dd76202017-12-21 16:20:32 +0100153 PyMem_RawFree(fname);
Victor Stinner91afbb62015-03-24 12:16:28 +0100154 return err;
155}
156
Victor Stinner0327bde2017-11-23 17:03:20 +0100157
Guido van Rossum305e5d01997-04-11 17:18:45 +0000158static void
Martin v. Löwis790465f2008-04-05 20:41:37 +0000159reduce(wchar_t *dir)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000160{
Martin v. Löwis790465f2008-04-05 20:41:37 +0000161 size_t i = wcslen(dir);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100162 while (i > 0 && dir[i] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000163 --i;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100164 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000165 dir[i] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +0000166}
Guido van Rossumd29806c1998-01-19 22:06:22 +0000167
Victor Stinner0327bde2017-11-23 17:03:20 +0100168
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100169/* Is file, not directory */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000170static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100171isfile(const wchar_t *filename)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000172{
Fred Drakeedabdc12000-07-08 06:16:37 +0000173 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100174 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000175 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100176 }
177 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000178 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100179 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000180 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000181}
182
183
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100184/* Is module -- check for .pyc too */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000185static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100186ismodule(wchar_t *filename, size_t filename_len)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000187{
Victor Stinner0327bde2017-11-23 17:03:20 +0100188 if (isfile(filename)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000189 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100190 }
Guido van Rossumd29806c1998-01-19 22:06:22 +0000191
Fred Drakeedabdc12000-07-08 06:16:37 +0000192 /* Check for the compiled version of prefix. */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100193 if (wcslen(filename) + 2 <= filename_len) {
Brett Cannonf299abd2015-04-13 14:21:02 -0400194 wcscat(filename, L"c");
Victor Stinner0327bde2017-11-23 17:03:20 +0100195 if (isfile(filename)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000196 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100197 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000198 }
199 return 0;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000200}
201
202
Victor Stinner0327bde2017-11-23 17:03:20 +0100203/* Is executable file */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000204static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100205isxfile(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000206{
Fred Drakeedabdc12000-07-08 06:16:37 +0000207 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100208 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000209 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100210 }
211 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000212 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100213 }
214 if ((buf.st_mode & 0111) == 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000215 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100216 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000217 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000218}
219
220
Victor Stinner0327bde2017-11-23 17:03:20 +0100221/* Is directory */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000222static int
Victor Stinner0327bde2017-11-23 17:03:20 +0100223isdir(wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000224{
Fred Drakeedabdc12000-07-08 06:16:37 +0000225 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100226 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000227 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100228 }
229 if (!S_ISDIR(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000230 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100231 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000232 return 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000233}
234
235
Tim Petersec8c5a92004-08-08 01:00:47 +0000236/* Add a path component, by appending stuff to buffer.
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100237 buflen: 'buffer' length in characters including trailing NUL. */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100238static _PyInitError
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100239joinpath(wchar_t *buffer, const wchar_t *stuff, size_t buflen)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000240{
Fred Drakeedabdc12000-07-08 06:16:37 +0000241 size_t n, k;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100242 if (stuff[0] != SEP) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000243 n = wcslen(buffer);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100244 if (n >= buflen) {
245 return PATHLEN_ERR();
246 }
247
248 if (n > 0 && buffer[n-1] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000249 buffer[n++] = SEP;
Victor Stinner0327bde2017-11-23 17:03:20 +0100250 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000251 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100252 else {
253 n = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100254 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100255
Martin v. Löwis790465f2008-04-05 20:41:37 +0000256 k = wcslen(stuff);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100257 if (n + k >= buflen) {
258 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100259 }
Martin v. Löwis790465f2008-04-05 20:41:37 +0000260 wcsncpy(buffer+n, stuff, k);
Fred Drakeedabdc12000-07-08 06:16:37 +0000261 buffer[n+k] = '\0';
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100262
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100263 return _Py_INIT_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000264}
265
Victor Stinner0327bde2017-11-23 17:03:20 +0100266
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100267static inline int
268safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
269{
270 size_t srclen = wcslen(src);
271 if (n <= srclen) {
272 dst[0] = L'\0';
273 return -1;
274 }
275 memcpy(dst, src, (srclen + 1) * sizeof(wchar_t));
276 return 0;
277}
278
279
Guido van Rossume296ced2001-09-28 20:00:29 +0000280/* copy_absolute requires that path be allocated at least
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100281 'pathlen' characters (including trailing NUL). */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100282static _PyInitError
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100283copy_absolute(wchar_t *path, const wchar_t *p, size_t pathlen)
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000284{
Victor Stinner0327bde2017-11-23 17:03:20 +0100285 if (p[0] == SEP) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100286 if (safe_wcscpy(path, p, pathlen) < 0) {
287 return PATHLEN_ERR();
288 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100289 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000290 else {
Victor Stinnerf4061da2010-10-14 12:37:19 +0000291 if (!_Py_wgetcwd(path, pathlen)) {
Victor Stinner4f3abb02010-10-07 23:29:18 +0000292 /* unable to get the current directory */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100293 if (safe_wcscpy(path, p, pathlen) < 0) {
294 return PATHLEN_ERR();
295 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100296 return _Py_INIT_OK();
Victor Stinner4f3abb02010-10-07 23:29:18 +0000297 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100298 if (p[0] == '.' && p[1] == SEP) {
Guido van Rossume296ced2001-09-28 20:00:29 +0000299 p += 2;
Victor Stinner0327bde2017-11-23 17:03:20 +0100300 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100301 _PyInitError err = joinpath(path, p, pathlen);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100302 if (_Py_INIT_FAILED(err)) {
303 return err;
304 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000305 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100306 return _Py_INIT_OK();
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000307}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000308
Victor Stinner0327bde2017-11-23 17:03:20 +0100309
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100310/* path_len: path length in characters including trailing NUL */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100311static _PyInitError
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100312absolutize(wchar_t *path, size_t path_len)
Guido van Rossume296ced2001-09-28 20:00:29 +0000313{
Victor Stinner0327bde2017-11-23 17:03:20 +0100314 if (path[0] == SEP) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100315 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100316 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100317
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100318 wchar_t abs_path[MAXPATHLEN+1];
319 _PyInitError err = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path));
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100320 if (_Py_INIT_FAILED(err)) {
321 return err;
322 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100323
324 if (safe_wcscpy(path, abs_path, path_len) < 0) {
325 return PATHLEN_ERR();
326 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100327 return _Py_INIT_OK();
Guido van Rossume296ced2001-09-28 20:00:29 +0000328}
329
Victor Stinner0327bde2017-11-23 17:03:20 +0100330
E. M. Bray7a7693e2018-10-05 13:38:50 +0200331#if defined(__CYGWIN__) || defined(__MINGW32__)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200332#ifndef EXE_SUFFIX
333#define EXE_SUFFIX L".exe"
334#endif
335
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100336/* pathlen: 'path' length in characters including trailing NUL */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100337static _PyInitError
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100338add_exe_suffix(wchar_t *progpath, size_t progpathlen)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200339{
340 /* Check for already have an executable suffix */
341 size_t n = wcslen(progpath);
342 size_t s = wcslen(EXE_SUFFIX);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100343 if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
344 return _Py_INIT_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200345 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100346
347 if (n + s >= progpathlen) {
348 return PATHLEN_ERR();
349 }
350 wcsncpy(progpath + n, EXE_SUFFIX, s);
351 progpath[n+s] = '\0';
352
353 if (!isxfile(progpath)) {
354 /* Path that added suffix is invalid: truncate (remove suffix) */
355 progpath[n] = '\0';
356 }
357
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100358 return _Py_INIT_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200359}
360#endif
361
362
Guido van Rossume296ced2001-09-28 20:00:29 +0000363/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000364 bytes long.
365*/
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100366static _PyInitError
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100367search_for_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate,
368 wchar_t *prefix, size_t prefix_len,
369 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000370{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100371 _PyInitError err;
Fred Drakeedabdc12000-07-08 06:16:37 +0000372 size_t n;
Martin v. Löwis790465f2008-04-05 20:41:37 +0000373 wchar_t *vpath;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000374
Fred Drakeedabdc12000-07-08 06:16:37 +0000375 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100376 if (core_config->home) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100377 if (safe_wcscpy(prefix, core_config->home, prefix_len) < 0) {
378 return PATHLEN_ERR();
379 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100380 wchar_t *delim = wcschr(prefix, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100381 if (delim) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000382 *delim = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100383 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100384 err = joinpath(prefix, calculate->lib_python, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100385 if (_Py_INIT_FAILED(err)) {
386 return err;
387 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100388 err = joinpath(prefix, LANDMARK, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100389 if (_Py_INIT_FAILED(err)) {
390 return err;
391 }
392 *found = 1;
393 return _Py_INIT_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000394 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000395
Fred Drakeedabdc12000-07-08 06:16:37 +0000396 /* Check to see if argv[0] is in the build directory */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100397 if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
398 return PATHLEN_ERR();
399 }
400 err = joinpath(prefix, L"Modules/Setup.local", prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100401 if (_Py_INIT_FAILED(err)) {
402 return err;
403 }
404
Victor Stinner9316ee42017-11-25 03:17:57 +0100405 if (isfile(prefix)) {
Neil Schemenauer6cf07022001-01-24 17:13:11 +0000406 /* Check VPATH to see if argv0_path is in the build directory. */
Victor Stinnerf6a271a2014-08-01 12:28:48 +0200407 vpath = Py_DecodeLocale(VPATH, NULL);
Victor Stinner21582312010-10-23 00:13:28 +0000408 if (vpath != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100409 if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
410 return PATHLEN_ERR();
411 }
412 err = joinpath(prefix, vpath, prefix_len);
Victor Stinner1a7425f2013-07-07 16:25:15 +0200413 PyMem_RawFree(vpath);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100414 if (_Py_INIT_FAILED(err)) {
415 return err;
416 }
417
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100418 err = joinpath(prefix, L"Lib", prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100419 if (_Py_INIT_FAILED(err)) {
420 return err;
421 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100422 err = joinpath(prefix, LANDMARK, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100423 if (_Py_INIT_FAILED(err)) {
424 return err;
425 }
426
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100427 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100428 *found = -1;
429 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100430 }
Victor Stinner21582312010-10-23 00:13:28 +0000431 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000432 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000433
Fred Drakeedabdc12000-07-08 06:16:37 +0000434 /* Search from argv0_path, until root is found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100435 err = copy_absolute(prefix, calculate->argv0_path, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100436 if (_Py_INIT_FAILED(err)) {
437 return err;
438 }
439
Fred Drakeedabdc12000-07-08 06:16:37 +0000440 do {
Victor Stinner9316ee42017-11-25 03:17:57 +0100441 n = wcslen(prefix);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100442 err = joinpath(prefix, calculate->lib_python, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100443 if (_Py_INIT_FAILED(err)) {
444 return err;
445 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100446 err = joinpath(prefix, LANDMARK, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100447 if (_Py_INIT_FAILED(err)) {
448 return err;
449 }
450
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100451 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100452 *found = 1;
453 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100454 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100455 prefix[n] = L'\0';
456 reduce(prefix);
457 } while (prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000458
Fred Drakeedabdc12000-07-08 06:16:37 +0000459 /* Look at configure's PREFIX */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100460 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
461 return PATHLEN_ERR();
462 }
463 err = joinpath(prefix, calculate->lib_python, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100464 if (_Py_INIT_FAILED(err)) {
465 return err;
466 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100467 err = joinpath(prefix, LANDMARK, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100468 if (_Py_INIT_FAILED(err)) {
469 return err;
470 }
471
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100472 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100473 *found = 1;
474 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100475 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000476
Fred Drakeedabdc12000-07-08 06:16:37 +0000477 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100478 *found = 0;
479 return _Py_INIT_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000480}
481
482
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100483static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100484calculate_prefix(const _PyCoreConfig *core_config,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100485 PyCalculatePath *calculate, wchar_t *prefix, size_t prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100486{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100487 _PyInitError err;
488
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100489 err = search_for_prefix(core_config, calculate, prefix, prefix_len,
490 &calculate->prefix_found);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100491 if (_Py_INIT_FAILED(err)) {
492 return err;
493 }
494
Victor Stinner0327bde2017-11-23 17:03:20 +0100495 if (!calculate->prefix_found) {
Victor Stinnerb75d7e22018-08-01 02:13:04 +0200496 if (!core_config->_frozen) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100497 fprintf(stderr,
498 "Could not find platform independent libraries <prefix>\n");
499 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100500 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
501 return PATHLEN_ERR();
502 }
503 err = joinpath(prefix, calculate->lib_python, prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100504 if (_Py_INIT_FAILED(err)) {
505 return err;
506 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100507 }
508 else {
Victor Stinner9316ee42017-11-25 03:17:57 +0100509 reduce(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100510 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100511 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100512}
513
514
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100515static _PyInitError
516calculate_reduce_prefix(PyCalculatePath *calculate,
517 wchar_t *prefix, size_t prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100518{
519 /* Reduce prefix and exec_prefix to their essence,
520 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
521 * If we're loading relative to the build directory,
522 * return the compiled-in defaults instead.
523 */
524 if (calculate->prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100525 reduce(prefix);
526 reduce(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100527 /* The prefix is the root directory, but reduce() chopped
528 * off the "/". */
Victor Stinner9316ee42017-11-25 03:17:57 +0100529 if (!prefix[0]) {
530 wcscpy(prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100531 }
532 }
533 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100534 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
535 return PATHLEN_ERR();
536 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100537 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100538 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100539}
540
541
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000542/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000543 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000544*/
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100545static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100546search_for_exec_prefix(const _PyCoreConfig *core_config,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100547 PyCalculatePath *calculate,
548 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100549 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000550{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100551 _PyInitError err;
Fred Drakeedabdc12000-07-08 06:16:37 +0000552 size_t n;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000553
Fred Drakeedabdc12000-07-08 06:16:37 +0000554 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100555 if (core_config->home) {
556 wchar_t *delim = wcschr(core_config->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100557 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100558 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
559 return PATHLEN_ERR();
560 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100561 }
562 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100563 if (safe_wcscpy(exec_prefix, core_config->home, exec_prefix_len) < 0) {
564 return PATHLEN_ERR();
565 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100566 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100567 err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100568 if (_Py_INIT_FAILED(err)) {
569 return err;
570 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100571 err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100572 if (_Py_INIT_FAILED(err)) {
573 return err;
574 }
575 *found = 1;
576 return _Py_INIT_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000577 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000578
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000579 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
580 is written by setup.py and contains the relative path to the location
581 of shared library modules. */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100582 if (safe_wcscpy(exec_prefix, calculate->argv0_path, exec_prefix_len) < 0) {
583 return PATHLEN_ERR();
584 }
585 err = joinpath(exec_prefix, L"pybuilddir.txt", exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100586 if (_Py_INIT_FAILED(err)) {
587 return err;
588 }
589
Victor Stinner9316ee42017-11-25 03:17:57 +0100590 if (isfile(exec_prefix)) {
591 FILE *f = _Py_wfopen(exec_prefix, L"rb");
Victor Stinner0327bde2017-11-23 17:03:20 +0100592 if (f == NULL) {
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000593 errno = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100594 }
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000595 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100596 char buf[MAXPATHLEN + 1];
597 n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, f);
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000598 buf[n] = '\0';
599 fclose(f);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100600
Victor Stinner5f9cf232019-03-19 01:46:25 +0100601 wchar_t *pybuilddir;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100602 size_t dec_len;
Victor Stinner5f9cf232019-03-19 01:46:25 +0100603 pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
604 if (!pybuilddir) {
605 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000606 }
Victor Stinner5f9cf232019-03-19 01:46:25 +0100607
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100608 if (safe_wcscpy(exec_prefix, calculate->argv0_path, exec_prefix_len) < 0) {
609 return PATHLEN_ERR();
610 }
611 err = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
Victor Stinner5f9cf232019-03-19 01:46:25 +0100612 PyMem_RawFree(pybuilddir );
613 if (_Py_INIT_FAILED(err)) {
614 return err;
615 }
616
617 *found = -1;
618 return _Py_INIT_OK();
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000619 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000620 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000621
Fred Drakeedabdc12000-07-08 06:16:37 +0000622 /* Search from argv0_path, until root is found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100623 err = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100624 if (_Py_INIT_FAILED(err)) {
625 return err;
626 }
627
Fred Drakeedabdc12000-07-08 06:16:37 +0000628 do {
Victor Stinner9316ee42017-11-25 03:17:57 +0100629 n = wcslen(exec_prefix);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100630 err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100631 if (_Py_INIT_FAILED(err)) {
632 return err;
633 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100634 err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100635 if (_Py_INIT_FAILED(err)) {
636 return err;
637 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100638 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100639 *found = 1;
640 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100641 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100642 exec_prefix[n] = L'\0';
643 reduce(exec_prefix);
644 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000645
Fred Drakeedabdc12000-07-08 06:16:37 +0000646 /* Look at configure's EXEC_PREFIX */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100647 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
648 return PATHLEN_ERR();
649 }
650 err = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100651 if (_Py_INIT_FAILED(err)) {
652 return err;
653 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100654 err = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100655 if (_Py_INIT_FAILED(err)) {
656 return err;
657 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100658 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100659 *found = 1;
660 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100661 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000662
Fred Drakeedabdc12000-07-08 06:16:37 +0000663 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100664 *found = 0;
665 return _Py_INIT_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000666}
667
Guido van Rossum305e5d01997-04-11 17:18:45 +0000668
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100669static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100670calculate_exec_prefix(const _PyCoreConfig *core_config,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100671 PyCalculatePath *calculate,
672 wchar_t *exec_prefix, size_t exec_prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100673{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100674 _PyInitError err;
675
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100676 err = search_for_exec_prefix(core_config, calculate,
677 exec_prefix, exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100678 &calculate->exec_prefix_found);
679 if (_Py_INIT_FAILED(err)) {
680 return err;
681 }
682
Victor Stinner0327bde2017-11-23 17:03:20 +0100683 if (!calculate->exec_prefix_found) {
Victor Stinnerb75d7e22018-08-01 02:13:04 +0200684 if (!core_config->_frozen) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100685 fprintf(stderr,
686 "Could not find platform dependent libraries <exec_prefix>\n");
687 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100688 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
689 return PATHLEN_ERR();
690 }
691 err = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100692 if (_Py_INIT_FAILED(err)) {
693 return err;
694 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100695 }
696 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100697 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100698}
699
700
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100701static _PyInitError
702calculate_reduce_exec_prefix(PyCalculatePath *calculate,
703 wchar_t *exec_prefix, size_t exec_prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100704{
705 if (calculate->exec_prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100706 reduce(exec_prefix);
707 reduce(exec_prefix);
708 reduce(exec_prefix);
709 if (!exec_prefix[0]) {
710 wcscpy(exec_prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100711 }
712 }
713 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100714 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
715 return PATHLEN_ERR();
716 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100717 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100718 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100719}
720
721
Victor Stinner9316ee42017-11-25 03:17:57 +0100722static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100723calculate_program_full_path(const _PyCoreConfig *core_config,
Victor Stinner31a83932017-12-04 13:39:15 +0100724 PyCalculatePath *calculate, _PyPathConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +0100725{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100726 _PyInitError err;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100727 wchar_t program_full_path[MAXPATHLEN + 1];
728 const size_t program_full_path_len = Py_ARRAY_LENGTH(program_full_path);
Victor Stinnerb64de462017-12-01 18:27:09 +0100729 memset(program_full_path, 0, sizeof(program_full_path));
Victor Stinner9316ee42017-11-25 03:17:57 +0100730
Victor Stinnerb9197952017-11-23 19:02:04 +0100731#ifdef __APPLE__
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100732 char execpath[MAXPATHLEN + 1];
Victor Stinnerb9197952017-11-23 19:02:04 +0100733#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100734 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100735#else
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100736 unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100737#endif
Victor Stinnerb9197952017-11-23 19:02:04 +0100738#endif
739
Victor Stinner0327bde2017-11-23 17:03:20 +0100740 /* If there is no slash in the argv0 path, then we have to
741 * assume python is on the user's $PATH, since there's no
742 * other way to find a directory to start the search from. If
743 * $PATH isn't exported, you lose.
744 */
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +0100745 if (wcschr(core_config->program_name, SEP)) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100746 if (safe_wcscpy(program_full_path, core_config->program_name,
747 program_full_path_len) < 0) {
748 return PATHLEN_ERR();
749 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100750 }
Jack Jansen1afd4802004-06-03 14:33:03 +0000751#ifdef __APPLE__
Jack Jansen1afd4802004-06-03 14:33:03 +0000752 /* On Mac OS X, if a script uses an interpreter of the form
753 * "#!/opt/python2.3/bin/python", the kernel only passes "python"
754 * as argv[0], which falls through to the $PATH search below.
755 * If /opt/python2.3/bin isn't in your path, or is near the end,
756 * this algorithm may incorrectly find /usr/bin/python. To work
757 * around this, we can use _NSGetExecutablePath to get a better
758 * hint of what the intended interpreter was, although this
759 * will fail if a relative path was used. but in that case,
760 * absolutize() should help us out below
761 */
Victor Stinnerf04ebe22017-11-25 00:01:23 +0100762 else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
763 execpath[0] == SEP)
764 {
Victor Stinner31a83932017-12-04 13:39:15 +0100765 size_t len;
766 wchar_t *path = Py_DecodeLocale(execpath, &len);
767 if (path == NULL) {
768 return DECODE_LOCALE_ERR("executable path", len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100770 if (safe_wcscpy(program_full_path, path, program_full_path_len) < 0) {
771 PyMem_RawFree(path);
772 return PATHLEN_ERR();
773 }
Victor Stinner31a83932017-12-04 13:39:15 +0100774 PyMem_RawFree(path);
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000775 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000776#endif /* __APPLE__ */
Victor Stinner0327bde2017-11-23 17:03:20 +0100777 else if (calculate->path_env) {
778 wchar_t *path = calculate->path_env;
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000779 while (1) {
780 wchar_t *delim = wcschr(path, DELIM);
Jack Jansen55070f52001-12-02 23:56:28 +0000781
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000782 if (delim) {
783 size_t len = delim - path;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100784 if (len >= program_full_path_len) {
785 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100786 }
Victor Stinnerb64de462017-12-01 18:27:09 +0100787 wcsncpy(program_full_path, path, len);
788 program_full_path[len] = '\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000789 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100790 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100791 if (safe_wcscpy(program_full_path, path,
792 program_full_path_len) < 0) {
793 return PATHLEN_ERR();
794 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100795 }
Jack Jansen55070f52001-12-02 23:56:28 +0000796
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100797 err = joinpath(program_full_path, core_config->program_name,
798 program_full_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100799 if (_Py_INIT_FAILED(err)) {
800 return err;
801 }
802
Victor Stinnerb64de462017-12-01 18:27:09 +0100803 if (isxfile(program_full_path)) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000804 break;
Victor Stinner0327bde2017-11-23 17:03:20 +0100805 }
Jack Jansen55070f52001-12-02 23:56:28 +0000806
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000807 if (!delim) {
Victor Stinnerb64de462017-12-01 18:27:09 +0100808 program_full_path[0] = L'\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000809 break;
810 }
811 path = delim + 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000812 }
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000813 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100814 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100815 program_full_path[0] = '\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100816 }
Victor Stinnerb64de462017-12-01 18:27:09 +0100817 if (program_full_path[0] != SEP && program_full_path[0] != '\0') {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100818 err = absolutize(program_full_path, program_full_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100819 if (_Py_INIT_FAILED(err)) {
820 return err;
821 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100822 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200823#if defined(__CYGWIN__) || defined(__MINGW32__)
824 /* For these platforms it is necessary to ensure that the .exe suffix
825 * is appended to the filename, otherwise there is potential for
826 * sys.executable to return the name of a directory under the same
827 * path (bpo-28441).
828 */
829 if (program_full_path[0] != '\0') {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100830 err = add_exe_suffix(program_full_path, program_full_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100831 if (_Py_INIT_FAILED(err)) {
832 return err;
833 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200834 }
835#endif
Victor Stinner9316ee42017-11-25 03:17:57 +0100836
Victor Stinnerb64de462017-12-01 18:27:09 +0100837 config->program_full_path = _PyMem_RawWcsdup(program_full_path);
838 if (config->program_full_path == NULL) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100839 return _Py_INIT_NO_MEMORY();
840 }
841 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100842}
843
844
Victor Stinner9316ee42017-11-25 03:17:57 +0100845static _PyInitError
Victor Stinnerb64de462017-12-01 18:27:09 +0100846calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path)
Victor Stinner0327bde2017-11-23 17:03:20 +0100847{
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100848 const size_t argv0_path_len = Py_ARRAY_LENGTH(calculate->argv0_path);
849 if (safe_wcscpy(calculate->argv0_path, program_full_path, argv0_path_len) < 0) {
850 return PATHLEN_ERR();
851 }
Jack Jansen55070f52001-12-02 23:56:28 +0000852
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000853#ifdef WITH_NEXT_FRAMEWORK
Victor Stinner0327bde2017-11-23 17:03:20 +0100854 NSModule pythonModule;
855
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000856 /* On Mac OS X we have a special case if we're running from a framework.
857 ** This is because the python home should be set relative to the library,
858 ** which is in the framework, not relative to the executable, which may
859 ** be outside of the framework. Except when we're in the build directory...
860 */
Fred Drakeedabdc12000-07-08 06:16:37 +0000861 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
862 /* Use dylib functions to find out where the framework was loaded from */
Victor Stinner0327bde2017-11-23 17:03:20 +0100863 const char* modPath = NSLibraryNameForModule(pythonModule);
Vinay Sajip90db6612012-07-17 17:33:46 +0100864 if (modPath != NULL) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000865 /* We're in a framework. */
Jack Jansene925faf2001-08-15 01:14:40 +0000866 /* See if we might be in the build directory. The framework in the
867 ** build directory is incomplete, it only has the .dylib and a few
868 ** needed symlinks, it doesn't have the Lib directories and such.
869 ** If we're running with the framework from the build directory we must
870 ** be running the interpreter in the build directory, so we use the
871 ** build-directory-specific logic to find Lib and such.
872 */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100873 _PyInitError err;
Victor Stinner9316ee42017-11-25 03:17:57 +0100874 size_t len;
875 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100876 if (wbuf == NULL) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100877 return DECODE_LOCALE_ERR("framework location", len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100878 }
879
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100880 if (safe_wcscpy(calculate->argv0_path, wbuf, argv0_path_len) < 0) {
881 return PATHLEN_ERR();
882 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100883 reduce(calculate->argv0_path);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100884 err = joinpath(calculate->argv0_path, calculate->lib_python, argv0_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100885 if (_Py_INIT_FAILED(err)) {
886 PyMem_RawFree(wbuf);
887 return err;
888 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100889 err = joinpath(calculate->argv0_path, LANDMARK, argv0_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100890 if (_Py_INIT_FAILED(err)) {
891 PyMem_RawFree(wbuf);
892 return err;
893 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100894 if (!ismodule(calculate->argv0_path,
895 Py_ARRAY_LENGTH(calculate->argv0_path))) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000896 /* We are in the build directory so use the name of the
897 executable - we know that the absolute path is passed */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100898 if (safe_wcscpy(calculate->argv0_path, program_full_path,
899 argv0_path_len) < 0) {
900 return PATHLEN_ERR();
901 }
Jack Jansene925faf2001-08-15 01:14:40 +0000902 }
903 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100904 /* Use the location of the library as the program_full_path */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100905 if (safe_wcscpy(calculate->argv0_path, wbuf, argv0_path_len) < 0) {
906 return PATHLEN_ERR();
907 }
Jack Jansene925faf2001-08-15 01:14:40 +0000908 }
Victor Stinner1a7425f2013-07-07 16:25:15 +0200909 PyMem_RawFree(wbuf);
Fred Drakeedabdc12000-07-08 06:16:37 +0000910 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000911#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000912
Guido van Rossum305e5d01997-04-11 17:18:45 +0000913#if HAVE_READLINK
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100914 wchar_t tmpbuffer[MAXPATHLEN + 1];
915 const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
916 int linklen = _Py_wreadlink(program_full_path, tmpbuffer, buflen);
Victor Stinner0327bde2017-11-23 17:03:20 +0100917 while (linklen != -1) {
918 if (tmpbuffer[0] == SEP) {
919 /* tmpbuffer should never be longer than MAXPATHLEN,
920 but extra check does not hurt */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100921 if (safe_wcscpy(calculate->argv0_path, tmpbuffer, argv0_path_len) < 0) {
922 return PATHLEN_ERR();
923 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000924 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100925 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100926 /* Interpret relative to program_full_path */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100927 _PyInitError err;
Victor Stinner0327bde2017-11-23 17:03:20 +0100928 reduce(calculate->argv0_path);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100929 err = joinpath(calculate->argv0_path, tmpbuffer, argv0_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100930 if (_Py_INIT_FAILED(err)) {
931 return err;
932 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100933 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100934 linklen = _Py_wreadlink(calculate->argv0_path, tmpbuffer, buflen);
Fred Drakeedabdc12000-07-08 06:16:37 +0000935 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000936#endif /* HAVE_READLINK */
937
Victor Stinner0327bde2017-11-23 17:03:20 +0100938 reduce(calculate->argv0_path);
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000939 /* At this point, argv0_path is guaranteed to be less than
Victor Stinner0327bde2017-11-23 17:03:20 +0100940 MAXPATHLEN bytes long. */
Victor Stinner9316ee42017-11-25 03:17:57 +0100941 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100942}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000943
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100944
Victor Stinner0327bde2017-11-23 17:03:20 +0100945/* Search for an "pyvenv.cfg" environment configuration file, first in the
946 executable's directory and then in the parent directory.
947 If found, open it for use when searching for prefixes.
948*/
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100949static _PyInitError
Victor Stinner0327bde2017-11-23 17:03:20 +0100950calculate_read_pyenv(PyCalculatePath *calculate)
951{
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100952 _PyInitError err;
Victor Stinner0327bde2017-11-23 17:03:20 +0100953 wchar_t tmpbuffer[MAXPATHLEN+1];
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100954 const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
Victor Stinner0327bde2017-11-23 17:03:20 +0100955 wchar_t *env_cfg = L"pyvenv.cfg";
956 FILE *env_file;
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100957
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100958 if (safe_wcscpy(tmpbuffer, calculate->argv0_path, buflen) < 0) {
959 return PATHLEN_ERR();
960 }
Vinay Sajip90db6612012-07-17 17:33:46 +0100961
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100962 err = joinpath(tmpbuffer, env_cfg, buflen);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100963 if (_Py_INIT_FAILED(err)) {
964 return err;
965 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100966 env_file = _Py_wfopen(tmpbuffer, L"r");
967 if (env_file == NULL) {
968 errno = 0;
969
970 reduce(tmpbuffer);
971 reduce(tmpbuffer);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100972 err = joinpath(tmpbuffer, env_cfg, buflen);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100973 if (_Py_INIT_FAILED(err)) {
974 return err;
975 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100976
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100977 env_file = _Py_wfopen(tmpbuffer, L"r");
978 if (env_file == NULL) {
979 errno = 0;
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100980 }
981 }
982
Victor Stinner0327bde2017-11-23 17:03:20 +0100983 if (env_file == NULL) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100984 return _Py_INIT_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000985 }
Guido van Rossume296ced2001-09-28 20:00:29 +0000986
Victor Stinner0327bde2017-11-23 17:03:20 +0100987 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100988 if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, buflen)) {
989 if (safe_wcscpy(calculate->argv0_path, tmpbuffer,
990 Py_ARRAY_LENGTH(calculate->argv0_path)) < 0) {
991 return PATHLEN_ERR();
992 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000993 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100994 fclose(env_file);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100995 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100996}
Just van Rossum52e14d62002-12-30 22:08:05 +0000997
Guido van Rossum305e5d01997-04-11 17:18:45 +0000998
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100999static _PyInitError
Victor Stinner9316ee42017-11-25 03:17:57 +01001000calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +01001001{
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001002 _PyInitError err;
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001003 const size_t zip_path_len = Py_ARRAY_LENGTH(calculate->zip_path);
1004 if (safe_wcscpy(calculate->zip_path, prefix, zip_path_len) < 0) {
1005 return PATHLEN_ERR();
1006 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001007
Victor Stinner0327bde2017-11-23 17:03:20 +01001008 if (calculate->prefix_found > 0) {
1009 /* Use the reduced prefix returned by Py_GetPrefix() */
1010 reduce(calculate->zip_path);
1011 reduce(calculate->zip_path);
Victor Stinnerd4341102017-11-23 00:12:09 +01001012 }
1013 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001014 if (safe_wcscpy(calculate->zip_path, calculate->prefix, zip_path_len) < 0) {
1015 return PATHLEN_ERR();
1016 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001017 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001018 err = joinpath(calculate->zip_path, L"lib/python00.zip", zip_path_len);
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001019 if (_Py_INIT_FAILED(err)) {
1020 return err;
1021 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001022
1023 /* Replace "00" with version */
1024 size_t bufsz = wcslen(calculate->zip_path);
1025 calculate->zip_path[bufsz - 6] = VERSION[0];
1026 calculate->zip_path[bufsz - 5] = VERSION[2];
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001027 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001028}
1029
1030
Victor Stinner9316ee42017-11-25 03:17:57 +01001031static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001032calculate_module_search_path(const _PyCoreConfig *core_config,
Victor Stinner31a83932017-12-04 13:39:15 +01001033 PyCalculatePath *calculate,
Victor Stinner9316ee42017-11-25 03:17:57 +01001034 const wchar_t *prefix, const wchar_t *exec_prefix,
Victor Stinnerb64de462017-12-01 18:27:09 +01001035 _PyPathConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001036{
1037 /* Calculate size of return buffer */
1038 size_t bufsz = 0;
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001039 if (core_config->module_search_path_env != NULL) {
1040 bufsz += wcslen(core_config->module_search_path_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001041 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001042
Victor Stinner0327bde2017-11-23 17:03:20 +01001043 wchar_t *defpath = calculate->pythonpath;
Victor Stinner9316ee42017-11-25 03:17:57 +01001044 size_t prefixsz = wcslen(prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001045 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001046 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001047
Victor Stinner0327bde2017-11-23 17:03:20 +01001048 if (defpath[0] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001049 /* Paths are relative to prefix */
1050 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001051 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001052
Victor Stinner0327bde2017-11-23 17:03:20 +01001053 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001054 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001055 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001056 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001057 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001058 break;
1059 }
1060 defpath = delim + 1;
1061 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001062
Victor Stinner0327bde2017-11-23 17:03:20 +01001063 bufsz += wcslen(calculate->zip_path) + 1;
Victor Stinner9316ee42017-11-25 03:17:57 +01001064 bufsz += wcslen(exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001065
Victor Stinner0327bde2017-11-23 17:03:20 +01001066 /* Allocate the buffer */
1067 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001068 if (buf == NULL) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001069 return _Py_INIT_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001070 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001071 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001072
Victor Stinner72967a42013-11-16 01:22:04 +01001073 /* Run-time value of $PYTHONPATH goes first */
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001074 if (core_config->module_search_path_env) {
1075 wcscpy(buf, core_config->module_search_path_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001076 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001077 }
Victor Stinner72967a42013-11-16 01:22:04 +01001078
1079 /* Next is the default zip path */
Victor Stinner0327bde2017-11-23 17:03:20 +01001080 wcscat(buf, calculate->zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001081 wcscat(buf, delimiter);
1082
1083 /* Next goes merge of compile-time $PYTHONPATH with
1084 * dynamically located prefix.
1085 */
Victor Stinner0327bde2017-11-23 17:03:20 +01001086 defpath = calculate->pythonpath;
Victor Stinner72967a42013-11-16 01:22:04 +01001087 while (1) {
1088 wchar_t *delim = wcschr(defpath, DELIM);
1089
1090 if (defpath[0] != SEP) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001091 wcscat(buf, prefix);
1092 if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001093 defpath[0] != (delim ? DELIM : L'\0'))
1094 {
1095 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001096 wcscat(buf, separator);
1097 }
Victor Stinner72967a42013-11-16 01:22:04 +01001098 }
1099
1100 if (delim) {
1101 size_t len = delim - defpath + 1;
1102 size_t end = wcslen(buf) + len;
1103 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001104 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001105 }
1106 else {
1107 wcscat(buf, defpath);
1108 break;
1109 }
1110 defpath = delim + 1;
1111 }
1112 wcscat(buf, delimiter);
1113
1114 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinner9316ee42017-11-25 03:17:57 +01001115 wcscat(buf, exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001116
Victor Stinner9316ee42017-11-25 03:17:57 +01001117 config->module_search_path = buf;
1118 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001119}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001120
Victor Stinner0327bde2017-11-23 17:03:20 +01001121
Victor Stinner0327bde2017-11-23 17:03:20 +01001122static _PyInitError
1123calculate_init(PyCalculatePath *calculate,
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001124 const _PyCoreConfig *core_config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001125{
Victor Stinner0327bde2017-11-23 17:03:20 +01001126 size_t len;
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001127 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001128 if (path) {
1129 calculate->path_env = Py_DecodeLocale(path, &len);
1130 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001131 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001132 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001133 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001134
Victor Stinner0327bde2017-11-23 17:03:20 +01001135 calculate->pythonpath = Py_DecodeLocale(PYTHONPATH, &len);
1136 if (!calculate->pythonpath) {
Victor Stinner46972b72017-11-24 22:55:40 +01001137 return DECODE_LOCALE_ERR("PYTHONPATH define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001138 }
1139 calculate->prefix = Py_DecodeLocale(PREFIX, &len);
1140 if (!calculate->prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001141 return DECODE_LOCALE_ERR("PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001142 }
1143 calculate->exec_prefix = Py_DecodeLocale(EXEC_PREFIX, &len);
1144 if (!calculate->prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001145 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001146 }
1147 calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
1148 if (!calculate->lib_python) {
Victor Stinner46972b72017-11-24 22:55:40 +01001149 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001150 }
1151 return _Py_INIT_OK();
1152}
1153
1154
1155static void
1156calculate_free(PyCalculatePath *calculate)
1157{
1158 PyMem_RawFree(calculate->pythonpath);
1159 PyMem_RawFree(calculate->prefix);
1160 PyMem_RawFree(calculate->exec_prefix);
1161 PyMem_RawFree(calculate->lib_python);
1162 PyMem_RawFree(calculate->path_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001163}
1164
1165
Victor Stinner9316ee42017-11-25 03:17:57 +01001166static _PyInitError
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001167calculate_path_impl(const _PyCoreConfig *core_config,
Victor Stinner31a83932017-12-04 13:39:15 +01001168 PyCalculatePath *calculate, _PyPathConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001169{
Victor Stinner31a83932017-12-04 13:39:15 +01001170 _PyInitError err;
1171
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001172 err = calculate_program_full_path(core_config, calculate, config);
Victor Stinner9316ee42017-11-25 03:17:57 +01001173 if (_Py_INIT_FAILED(err)) {
1174 return err;
1175 }
1176
Victor Stinnerb64de462017-12-01 18:27:09 +01001177 err = calculate_argv0_path(calculate, config->program_full_path);
Victor Stinner9316ee42017-11-25 03:17:57 +01001178 if (_Py_INIT_FAILED(err)) {
1179 return err;
1180 }
1181
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001182 err = calculate_read_pyenv(calculate);
1183 if (_Py_INIT_FAILED(err)) {
1184 return err;
1185 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001186
1187 wchar_t prefix[MAXPATHLEN+1];
1188 memset(prefix, 0, sizeof(prefix));
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001189 err = calculate_prefix(core_config, calculate,
1190 prefix, Py_ARRAY_LENGTH(prefix));
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001191 if (_Py_INIT_FAILED(err)) {
1192 return err;
1193 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001194
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001195 err = calculate_zip_path(calculate, prefix);
1196 if (_Py_INIT_FAILED(err)) {
1197 return err;
1198 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001199
1200 wchar_t exec_prefix[MAXPATHLEN+1];
1201 memset(exec_prefix, 0, sizeof(exec_prefix));
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001202 err = calculate_exec_prefix(core_config, calculate,
1203 exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001204 if (_Py_INIT_FAILED(err)) {
1205 return err;
1206 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001207
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001208 if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
Victor Stinnerb75d7e22018-08-01 02:13:04 +02001209 !core_config->_frozen)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001210 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001211 fprintf(stderr,
1212 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1213 }
1214
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001215 err = calculate_module_search_path(core_config, calculate,
Victor Stinner31a83932017-12-04 13:39:15 +01001216 prefix, exec_prefix, config);
Victor Stinner9316ee42017-11-25 03:17:57 +01001217 if (_Py_INIT_FAILED(err)) {
1218 return err;
1219 }
1220
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001221 err = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix));
1222 if (_Py_INIT_FAILED(err)) {
1223 return err;
1224 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001225
1226 config->prefix = _PyMem_RawWcsdup(prefix);
1227 if (config->prefix == NULL) {
1228 return _Py_INIT_NO_MEMORY();
1229 }
1230
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001231 err = calculate_reduce_exec_prefix(calculate,
1232 exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
1233 if (_Py_INIT_FAILED(err)) {
1234 return err;
1235 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001236
1237 config->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
1238 if (config->exec_prefix == NULL) {
1239 return _Py_INIT_NO_MEMORY();
1240 }
1241
1242 return _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001243}
1244
1245
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001246_PyInitError
Victor Stinnerb1147e42018-07-21 02:06:16 +02001247_PyPathConfig_Calculate_impl(_PyPathConfig *config, const _PyCoreConfig *core_config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001248{
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001249 _PyInitError err;
Victor Stinner0327bde2017-11-23 17:03:20 +01001250 PyCalculatePath calculate;
1251 memset(&calculate, 0, sizeof(calculate));
1252
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001253 err = calculate_init(&calculate, core_config);
Victor Stinner0327bde2017-11-23 17:03:20 +01001254 if (_Py_INIT_FAILED(err)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001255 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001256 }
1257
Victor Stinnerb5fd9ad2017-12-14 02:20:52 +01001258 err = calculate_path_impl(core_config, &calculate, config);
Victor Stinner9316ee42017-11-25 03:17:57 +01001259 if (_Py_INIT_FAILED(err)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001260 goto done;
1261 }
1262
Victor Stinner9316ee42017-11-25 03:17:57 +01001263 err = _Py_INIT_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001264
Victor Stinner9316ee42017-11-25 03:17:57 +01001265done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001266 calculate_free(&calculate);
Victor Stinner9316ee42017-11-25 03:17:57 +01001267 return err;
1268}
Victor Stinner46972b72017-11-24 22:55:40 +01001269
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001270#ifdef __cplusplus
1271}
1272#endif