blob: 980874f36f52551f982559fd532bc6d866ca17b7 [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 Stinner9fc57a32018-11-07 00:44:03 +01004#include "pycore_fileutils.h"
Victor Stinnere5014be2020-04-14 17:52:15 +02005#include "pycore_initconfig.h"
Victor Stinnera1c249c2018-11-01 03:15:58 +01006#include "pycore_pathconfig.h"
Victor Stinner361dcdc2020-04-15 03:24:57 +02007#include "osdefs.h" // DELIM
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__
Dan Willemsen7af58832020-07-14 16:41:59 -070013# include <AvailabilityMacros.h>
Victor Stinner0327bde2017-11-23 17:03:20 +010014# include <mach-o/dyld.h>
Guido van Rossum54ecc3d1999-01-27 17:53:11 +000015#endif
16
Guido van Rossum305e5d01997-04-11 17:18:45 +000017/* Search in some common locations for the associated Python libraries.
18 *
19 * Two directories must be found, the platform independent directory
Barry Warsaw90126031997-04-11 20:27:03 +000020 * (prefix), containing the common .py and .pyc files, and the platform
21 * dependent directory (exec_prefix), containing the shared library
22 * modules. Note that prefix and exec_prefix can be the same directory,
23 * but for some installations, they are different.
Guido van Rossum305e5d01997-04-11 17:18:45 +000024 *
Barry Warsaw90126031997-04-11 20:27:03 +000025 * Py_GetPath() carries out separate searches for prefix and exec_prefix.
26 * Each search tries a number of different locations until a ``landmark''
27 * file or directory is found. If no prefix or exec_prefix is found, a
28 * warning message is issued and the preprocessor defined PREFIX and
29 * EXEC_PREFIX are used (even though they will not work); python carries on
30 * as best as is possible, but most imports will fail.
Guido van Rossum305e5d01997-04-11 17:18:45 +000031 *
32 * Before any searches are done, the location of the executable is
Guido van Rossumd8faa362007-04-27 19:54:29 +000033 * determined. If argv[0] has one or more slashes in it, it is used
Barry Warsaw90126031997-04-11 20:27:03 +000034 * unchanged. Otherwise, it must have been invoked from the shell's path,
35 * so we search $PATH for the named executable and use that. If the
36 * executable was not found on $PATH (or there was no $PATH environment
37 * variable), the original argv[0] string is used.
Guido van Rossum305e5d01997-04-11 17:18:45 +000038 *
Barry Warsaw90126031997-04-11 20:27:03 +000039 * Next, the executable location is examined to see if it is a symbolic
40 * link. If so, the link is chased (correctly interpreting a relative
41 * pathname if one is found) and the directory of the link target is used.
Guido van Rossum305e5d01997-04-11 17:18:45 +000042 *
Barry Warsaw90126031997-04-11 20:27:03 +000043 * Finally, argv0_path is set to the directory containing the executable
44 * (i.e. the last component is stripped).
Guido van Rossum305e5d01997-04-11 17:18:45 +000045 *
Barry Warsaw90126031997-04-11 20:27:03 +000046 * With argv0_path in hand, we perform a number of steps. The same steps
47 * are performed for prefix and for exec_prefix, but with a different
48 * landmark.
Guido van Rossum305e5d01997-04-11 17:18:45 +000049 *
50 * Step 1. Are we running python out of the build directory? This is
51 * checked by looking for a different kind of landmark relative to
Barry Warsaw90126031997-04-11 20:27:03 +000052 * argv0_path. For prefix, the landmark's path is derived from the VPATH
53 * preprocessor variable (taking into account that its value is almost, but
54 * not quite, what we need). For exec_prefix, the landmark is
Antoine Pitroueba57b62010-08-14 12:33:18 +000055 * pybuilddir.txt. If the landmark is found, we're done.
Guido van Rossum305e5d01997-04-11 17:18:45 +000056 *
57 * For the remaining steps, the prefix landmark will always be
Jeremy Hylton847a9962000-05-26 21:49:07 +000058 * lib/python$VERSION/os.py and the exec_prefix will always be
Guido van Rossum266033e1997-10-20 23:20:32 +000059 * lib/python$VERSION/lib-dynload, where $VERSION is Python's version
Barry Warsaw90126031997-04-11 20:27:03 +000060 * number as supplied by the Makefile. Note that this means that no more
61 * build directory checking is performed; if the first step did not find
62 * the landmarks, the assumption is that python is running from an
63 * installed setup.
Guido van Rossum305e5d01997-04-11 17:18:45 +000064 *
65 * Step 2. See if the $PYTHONHOME environment variable points to the
Barry Warsaw90126031997-04-11 20:27:03 +000066 * installed location of the Python libraries. If $PYTHONHOME is set, then
67 * it points to prefix and exec_prefix. $PYTHONHOME can be a single
68 * directory, which is used for both, or the prefix and exec_prefix
69 * directories separated by a colon.
Guido van Rossum305e5d01997-04-11 17:18:45 +000070 *
71 * Step 3. Try to find prefix and exec_prefix relative to argv0_path,
Barry Warsaw90126031997-04-11 20:27:03 +000072 * backtracking up the path until it is exhausted. This is the most common
73 * step to succeed. Note that if prefix and exec_prefix are different,
74 * exec_prefix is more likely to be found; however if exec_prefix is a
75 * subdirectory of prefix, both will be found.
Guido van Rossum305e5d01997-04-11 17:18:45 +000076 *
Barry Warsaw90126031997-04-11 20:27:03 +000077 * Step 4. Search the directories pointed to by the preprocessor variables
78 * PREFIX and EXEC_PREFIX. These are supplied by the Makefile but can be
79 * passed in as options to the configure script.
Guido van Rossum305e5d01997-04-11 17:18:45 +000080 *
Barry Warsaw90126031997-04-11 20:27:03 +000081 * That's it!
82 *
83 * Well, almost. Once we have determined prefix and exec_prefix, the
Thomas Wouters7e474022000-07-16 12:04:32 +000084 * preprocessor variable PYTHONPATH is used to construct a path. Each
Barry Warsaw90126031997-04-11 20:27:03 +000085 * relative path on PYTHONPATH is prefixed with prefix. Then the directory
86 * containing the shared library modules is appended. The environment
87 * variable $PYTHONPATH is inserted in front of it all. Finally, the
88 * prefix and exec_prefix globals are tweaked so they reflect the values
89 * expected by other code, by stripping the "lib/python$VERSION/..." stuff
90 * off. If either points to the build directory, the globals are reset to
91 * the corresponding preprocessor variables (so sys.prefix will reflect the
92 * installation location, even though sys.path points into the build
93 * directory). This seems to make more sense given that currently the only
94 * known use of sys.prefix and sys.exec_prefix is for the ILU installation
95 * process to find the installed Python tree.
Antoine Pitroueba57b62010-08-14 12:33:18 +000096 *
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000097 * An embedding application can use Py_SetPath() to override all of
Min ho Kimc4cacc82019-07-31 08:16:13 +100098 * these automatic path computations.
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000099 *
Antoine Pitroueba57b62010-08-14 12:33:18 +0000100 * NOTE: Windows MSVC builds use PC/getpathp.c instead!
Barry Warsaw90126031997-04-11 20:27:03 +0000101 */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000102
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000103#ifdef __cplusplus
Victor Stinner0327bde2017-11-23 17:03:20 +0100104extern "C" {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000105#endif
106
107
Victor Stinner8510f432020-03-10 09:53:09 +0100108#if (!defined(PREFIX) || !defined(EXEC_PREFIX) \
Victor Stinner81750642020-06-08 19:36:13 +0200109 || !defined(VERSION) || !defined(VPATH))
110#error "PREFIX, EXEC_PREFIX, VERSION and VPATH macros must be defined"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000111#endif
Guido van Rossum667d7041995-08-04 04:20:48 +0000112
Guido van Rossum305e5d01997-04-11 17:18:45 +0000113#ifndef LANDMARK
Martin v. Löwis790465f2008-04-05 20:41:37 +0000114#define LANDMARK L"os.py"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000115#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000116
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200117#define BUILD_LANDMARK L"Modules/Setup.local"
118
Victor Stinner9316ee42017-11-25 03:17:57 +0100119#define DECODE_LOCALE_ERR(NAME, LEN) \
120 ((LEN) == (size_t)-2) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200121 ? _PyStatus_ERR("cannot decode " NAME) \
122 : _PyStatus_NO_MEMORY()
Victor Stinner9316ee42017-11-25 03:17:57 +0100123
Victor Stinner331a6a52019-05-27 16:39:22 +0200124#define PATHLEN_ERR() _PyStatus_ERR("path configuration: path too long")
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100125
Victor Stinner0327bde2017-11-23 17:03:20 +0100126typedef struct {
127 wchar_t *path_env; /* PATH environment variable */
Victor Stinner0327bde2017-11-23 17:03:20 +0100128
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200129 wchar_t *pythonpath_macro; /* PYTHONPATH macro */
130 wchar_t *prefix_macro; /* PREFIX macro */
131 wchar_t *exec_prefix_macro; /* EXEC_PREFIX macro */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200132 wchar_t *vpath_macro; /* VPATH macro */
Victor Stinner0327bde2017-11-23 17:03:20 +0100133
Victor Stinnerdc401052020-06-11 18:27:00 +0200134 wchar_t *lib_python; /* <platlibdir> / "pythonX.Y" */
Victor Stinner0327bde2017-11-23 17:03:20 +0100135
136 int prefix_found; /* found platform independent libraries? */
137 int exec_prefix_found; /* found the platform dependent libraries? */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200138
139 int warnings;
140 const wchar_t *pythonpath_env;
Victor Stinner81750642020-06-08 19:36:13 +0200141 const wchar_t *platlibdir;
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200142
143 wchar_t *argv0_path;
144 wchar_t *zip_path;
145 wchar_t *prefix;
146 wchar_t *exec_prefix;
Victor Stinner0327bde2017-11-23 17:03:20 +0100147} PyCalculatePath;
148
149static const wchar_t delimiter[2] = {DELIM, '\0'};
150static const wchar_t separator[2] = {SEP, '\0'};
Victor Stinner0327bde2017-11-23 17:03:20 +0100151
Martin v. Löwis790465f2008-04-05 20:41:37 +0000152
Victor Stinner91afbb62015-03-24 12:16:28 +0100153/* Get file status. Encode the path to the locale encoding. */
Victor Stinner91afbb62015-03-24 12:16:28 +0100154static int
155_Py_wstat(const wchar_t* path, struct stat *buf)
156{
157 int err;
158 char *fname;
Victor Stinner9dd76202017-12-21 16:20:32 +0100159 fname = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner91afbb62015-03-24 12:16:28 +0100160 if (fname == NULL) {
161 errno = EINVAL;
162 return -1;
163 }
164 err = stat(fname, buf);
Victor Stinner9dd76202017-12-21 16:20:32 +0100165 PyMem_RawFree(fname);
Victor Stinner91afbb62015-03-24 12:16:28 +0100166 return err;
167}
168
Victor Stinner0327bde2017-11-23 17:03:20 +0100169
Guido van Rossum305e5d01997-04-11 17:18:45 +0000170static void
Martin v. Löwis790465f2008-04-05 20:41:37 +0000171reduce(wchar_t *dir)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000172{
Martin v. Löwis790465f2008-04-05 20:41:37 +0000173 size_t i = wcslen(dir);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100174 while (i > 0 && dir[i] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000175 --i;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100176 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000177 dir[i] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +0000178}
Guido van Rossumd29806c1998-01-19 22:06:22 +0000179
Victor Stinner0327bde2017-11-23 17:03:20 +0100180
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100181/* Is file, not directory */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000182static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100183isfile(const wchar_t *filename)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000184{
Fred Drakeedabdc12000-07-08 06:16:37 +0000185 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100186 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000187 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100188 }
189 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000190 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100191 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000192 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000193}
194
195
Victor Stinner0327bde2017-11-23 17:03:20 +0100196/* Is executable file */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000197static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100198isxfile(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000199{
Fred Drakeedabdc12000-07-08 06:16:37 +0000200 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100201 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000202 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100203 }
204 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000205 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100206 }
207 if ((buf.st_mode & 0111) == 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000208 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100209 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000210 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000211}
212
213
Victor Stinner0327bde2017-11-23 17:03:20 +0100214/* Is directory */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000215static int
Victor Stinnerf0c85792019-10-04 03:53:26 +0200216isdir(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000217{
Fred Drakeedabdc12000-07-08 06:16:37 +0000218 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100219 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000220 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100221 }
222 if (!S_ISDIR(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000223 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100224 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000225 return 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000226}
227
228
Tim Petersec8c5a92004-08-08 01:00:47 +0000229/* Add a path component, by appending stuff to buffer.
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200230 buflen: 'buffer' length in characters including trailing NUL.
231
232 If path2 is empty:
233
234 - if path doesn't end with SEP and is not empty, add SEP to path
235 - otherwise, do nothing. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200236static PyStatus
Victor Stinnerf0c85792019-10-04 03:53:26 +0200237joinpath(wchar_t *path, const wchar_t *path2, size_t path_len)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000238{
Victor Stinnerf0c85792019-10-04 03:53:26 +0200239 size_t n;
240 if (!_Py_isabs(path2)) {
241 n = wcslen(path);
242 if (n >= path_len) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100243 return PATHLEN_ERR();
244 }
245
Victor Stinnerf0c85792019-10-04 03:53:26 +0200246 if (n > 0 && path[n-1] != SEP) {
247 path[n++] = SEP;
Victor Stinner0327bde2017-11-23 17:03:20 +0100248 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000249 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100250 else {
251 n = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100252 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100253
Victor Stinnerf0c85792019-10-04 03:53:26 +0200254 size_t k = wcslen(path2);
255 if (n + k >= path_len) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100256 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100257 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200258 wcsncpy(path + n, path2, k);
259 path[n + k] = '\0';
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100260
Victor Stinner331a6a52019-05-27 16:39:22 +0200261 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000262}
263
Victor Stinner0327bde2017-11-23 17:03:20 +0100264
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200265static wchar_t*
266substring(const wchar_t *str, size_t len)
267{
268 wchar_t *substr = PyMem_RawMalloc((len + 1) * sizeof(wchar_t));
269 if (substr == NULL) {
270 return NULL;
271 }
272
273 if (len) {
274 memcpy(substr, str, len * sizeof(wchar_t));
275 }
276 substr[len] = L'\0';
277 return substr;
278}
279
280
281static wchar_t*
282joinpath2(const wchar_t *path, const wchar_t *path2)
283{
284 if (_Py_isabs(path2)) {
285 return _PyMem_RawWcsdup(path2);
286 }
287
288 size_t len = wcslen(path);
289 int add_sep = (len > 0 && path[len - 1] != SEP);
290 len += add_sep;
291 len += wcslen(path2);
292
293 wchar_t *new_path = PyMem_RawMalloc((len + 1) * sizeof(wchar_t));
294 if (new_path == NULL) {
295 return NULL;
296 }
297
298 wcscpy(new_path, path);
299 if (add_sep) {
300 wcscat(new_path, separator);
301 }
302 wcscat(new_path, path2);
303 return new_path;
304}
305
306
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100307static inline int
308safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
309{
310 size_t srclen = wcslen(src);
311 if (n <= srclen) {
312 dst[0] = L'\0';
313 return -1;
314 }
315 memcpy(dst, src, (srclen + 1) * sizeof(wchar_t));
316 return 0;
317}
318
319
Guido van Rossume296ced2001-09-28 20:00:29 +0000320/* copy_absolute requires that path be allocated at least
Victor Stinnerf0c85792019-10-04 03:53:26 +0200321 'abs_path_len' characters (including trailing NUL). */
Victor Stinner331a6a52019-05-27 16:39:22 +0200322static PyStatus
Victor Stinnerf0c85792019-10-04 03:53:26 +0200323copy_absolute(wchar_t *abs_path, const wchar_t *path, size_t abs_path_len)
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000324{
Victor Stinnerf0c85792019-10-04 03:53:26 +0200325 if (_Py_isabs(path)) {
326 if (safe_wcscpy(abs_path, path, abs_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100327 return PATHLEN_ERR();
328 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100329 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000330 else {
Victor Stinnerf0c85792019-10-04 03:53:26 +0200331 if (!_Py_wgetcwd(abs_path, abs_path_len)) {
Victor Stinner4f3abb02010-10-07 23:29:18 +0000332 /* unable to get the current directory */
Victor Stinnerf0c85792019-10-04 03:53:26 +0200333 if (safe_wcscpy(abs_path, path, abs_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100334 return PATHLEN_ERR();
335 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200336 return _PyStatus_OK();
Victor Stinner4f3abb02010-10-07 23:29:18 +0000337 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200338 if (path[0] == '.' && path[1] == SEP) {
339 path += 2;
Victor Stinner0327bde2017-11-23 17:03:20 +0100340 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200341 PyStatus status = joinpath(abs_path, path, abs_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200342 if (_PyStatus_EXCEPTION(status)) {
343 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100344 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000345 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200346 return _PyStatus_OK();
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000347}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000348
Victor Stinner0327bde2017-11-23 17:03:20 +0100349
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100350/* path_len: path length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200351static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200352absolutize(wchar_t **path_p)
Guido van Rossume296ced2001-09-28 20:00:29 +0000353{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200354 assert(!_Py_isabs(*path_p));
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100355
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100356 wchar_t abs_path[MAXPATHLEN+1];
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200357 wchar_t *path = *path_p;
358
Victor Stinner331a6a52019-05-27 16:39:22 +0200359 PyStatus status = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path));
360 if (_PyStatus_EXCEPTION(status)) {
361 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100362 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100363
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200364 PyMem_RawFree(*path_p);
365 *path_p = _PyMem_RawWcsdup(abs_path);
366 if (*path_p == NULL) {
367 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100368 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200369 return _PyStatus_OK();
Guido van Rossume296ced2001-09-28 20:00:29 +0000370}
371
Victor Stinner0327bde2017-11-23 17:03:20 +0100372
Victor Stinnerf0c85792019-10-04 03:53:26 +0200373/* Is module -- check for .pyc too */
374static PyStatus
375ismodule(const wchar_t *path, int *result)
376{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200377 wchar_t *filename = joinpath2(path, LANDMARK);
378 if (filename == NULL) {
379 return _PyStatus_NO_MEMORY();
Victor Stinnerf0c85792019-10-04 03:53:26 +0200380 }
381
382 if (isfile(filename)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200383 PyMem_RawFree(filename);
Victor Stinnerf0c85792019-10-04 03:53:26 +0200384 *result = 1;
385 return _PyStatus_OK();
386 }
387
388 /* Check for the compiled version of prefix. */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200389 size_t len = wcslen(filename);
390 wchar_t *pyc = PyMem_RawMalloc((len + 2) * sizeof(wchar_t));
391 if (pyc == NULL) {
392 PyMem_RawFree(filename);
393 return _PyStatus_NO_MEMORY();
Victor Stinnerf0c85792019-10-04 03:53:26 +0200394 }
395
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200396 memcpy(pyc, filename, len * sizeof(wchar_t));
397 pyc[len] = L'c';
398 pyc[len + 1] = L'\0';
399 *result = isfile(pyc);
400
401 PyMem_RawFree(filename);
402 PyMem_RawFree(pyc);
403
Victor Stinnerf0c85792019-10-04 03:53:26 +0200404 return _PyStatus_OK();
405}
406
407
E. M. Bray7a7693e2018-10-05 13:38:50 +0200408#if defined(__CYGWIN__) || defined(__MINGW32__)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200409#ifndef EXE_SUFFIX
410#define EXE_SUFFIX L".exe"
411#endif
412
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100413/* pathlen: 'path' length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200414static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200415add_exe_suffix(wchar_t **progpath_p)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200416{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200417 wchar_t *progpath = *progpath_p;
418
E. M. Bray7a7693e2018-10-05 13:38:50 +0200419 /* Check for already have an executable suffix */
420 size_t n = wcslen(progpath);
421 size_t s = wcslen(EXE_SUFFIX);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100422 if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200423 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200424 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100425
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200426 wchar_t *progpath2 = PyMem_RawMalloc((n + s + 1) * sizeof(wchar_t));
427 if (progpath2 == NULL) {
428 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100429 }
430
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200431 memcpy(progpath2, progpath, n * sizeof(wchar_t));
432 memcpy(progpath2 + n, EXE_SUFFIX, s * sizeof(wchar_t));
433 progpath2[n+s] = L'\0';
434
435 if (isxfile(progpath2)) {
436 PyMem_RawFree(*progpath_p);
437 *progpath_p = progpath2;
438 }
439 else {
440 PyMem_RawFree(progpath2);
E. M. Bray7a7693e2018-10-05 13:38:50 +0200441 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200442 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200443}
444#endif
445
446
Guido van Rossume296ced2001-09-28 20:00:29 +0000447/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000448 bytes long.
449*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200450static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200451search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
452 wchar_t *prefix, size_t prefix_len, int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000453{
Victor Stinner331a6a52019-05-27 16:39:22 +0200454 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000455
Fred Drakeedabdc12000-07-08 06:16:37 +0000456 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200457 if (pathconfig->home) {
Victor Stinner96c84752019-09-26 16:17:34 +0200458 /* Path: <home> / <lib_python> */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200459 if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100460 return PATHLEN_ERR();
461 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100462 wchar_t *delim = wcschr(prefix, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100463 if (delim) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000464 *delim = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100465 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200466 status = joinpath(prefix, calculate->lib_python, prefix_len);
467 if (_PyStatus_EXCEPTION(status)) {
468 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100469 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100470 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200471 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000472 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000473
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200474 /* Check to see if argv0_path is in the build directory
475
476 Path: <argv0_path> / <BUILD_LANDMARK define> */
477 wchar_t *path = joinpath2(calculate->argv0_path, BUILD_LANDMARK);
478 if (path == NULL) {
479 return _PyStatus_NO_MEMORY();
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100480 }
481
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200482 int is_build_dir = isfile(path);
483 PyMem_RawFree(path);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100484
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200485 if (is_build_dir) {
486 /* argv0_path is the build directory (BUILD_LANDMARK exists),
487 now also check LANDMARK using ismodule(). */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100488
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200489 /* Path: <argv0_path> / <VPATH macro> / Lib */
490 /* or if VPATH is empty: <argv0_path> / Lib */
491 if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
492 return PATHLEN_ERR();
493 }
494
495 status = joinpath(prefix, calculate->vpath_macro, prefix_len);
496 if (_PyStatus_EXCEPTION(status)) {
497 return status;
498 }
499
500 status = joinpath(prefix, L"Lib", prefix_len);
501 if (_PyStatus_EXCEPTION(status)) {
502 return status;
503 }
504
505 int module;
506 status = ismodule(prefix, &module);
507 if (_PyStatus_EXCEPTION(status)) {
508 return status;
509 }
510 if (module) {
511 /* BUILD_LANDMARK and LANDMARK found */
512 *found = -1;
513 return _PyStatus_OK();
Victor Stinner21582312010-10-23 00:13:28 +0000514 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000515 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000516
Fred Drakeedabdc12000-07-08 06:16:37 +0000517 /* Search from argv0_path, until root is found */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200518 status = copy_absolute(prefix, calculate->argv0_path, prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200519 if (_PyStatus_EXCEPTION(status)) {
520 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100521 }
522
Fred Drakeedabdc12000-07-08 06:16:37 +0000523 do {
Victor Stinner96c84752019-09-26 16:17:34 +0200524 /* Path: <argv0_path or substring> / <lib_python> / LANDMARK */
525 size_t n = wcslen(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200526 status = joinpath(prefix, calculate->lib_python, prefix_len);
527 if (_PyStatus_EXCEPTION(status)) {
528 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100529 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200530
531 int module;
532 status = ismodule(prefix, &module);
Victor Stinner331a6a52019-05-27 16:39:22 +0200533 if (_PyStatus_EXCEPTION(status)) {
534 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100535 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200536 if (module) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100537 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200538 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100539 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100540 prefix[n] = L'\0';
541 reduce(prefix);
542 } while (prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000543
Victor Stinner96c84752019-09-26 16:17:34 +0200544 /* Look at configure's PREFIX.
545 Path: <PREFIX macro> / <lib_python> / LANDMARK */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200546 if (safe_wcscpy(prefix, calculate->prefix_macro, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100547 return PATHLEN_ERR();
548 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200549 status = joinpath(prefix, calculate->lib_python, prefix_len);
550 if (_PyStatus_EXCEPTION(status)) {
551 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100552 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200553
554 int module;
555 status = ismodule(prefix, &module);
Victor Stinner331a6a52019-05-27 16:39:22 +0200556 if (_PyStatus_EXCEPTION(status)) {
557 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100558 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200559 if (module) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100560 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200561 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100562 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000563
Fred Drakeedabdc12000-07-08 06:16:37 +0000564 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100565 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200566 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000567}
568
569
Victor Stinner331a6a52019-05-27 16:39:22 +0200570static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200571calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100572{
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200573 wchar_t prefix[MAXPATHLEN+1];
574 memset(prefix, 0, sizeof(prefix));
575 size_t prefix_len = Py_ARRAY_LENGTH(prefix);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100576
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200577 PyStatus status;
578 status = search_for_prefix(calculate, pathconfig,
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700579 prefix, prefix_len,
Victor Stinner3f5409a2019-09-23 19:50:27 +0200580 &calculate->prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200581 if (_PyStatus_EXCEPTION(status)) {
582 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100583 }
584
Victor Stinner0327bde2017-11-23 17:03:20 +0100585 if (!calculate->prefix_found) {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200586 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100587 fprintf(stderr,
588 "Could not find platform independent libraries <prefix>\n");
589 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200590
591 calculate->prefix = joinpath2(calculate->prefix_macro,
592 calculate->lib_python);
593 }
594 else {
595 calculate->prefix = _PyMem_RawWcsdup(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100596 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200597
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200598 if (calculate->prefix == NULL) {
599 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100600 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200601 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100602}
603
604
Victor Stinner331a6a52019-05-27 16:39:22 +0200605static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200606calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100607{
608 /* Reduce prefix and exec_prefix to their essence,
609 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
610 * If we're loading relative to the build directory,
611 * return the compiled-in defaults instead.
612 */
613 if (calculate->prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200614 wchar_t *prefix = _PyMem_RawWcsdup(calculate->prefix);
615 if (prefix == NULL) {
616 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100617 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200618
619 reduce(prefix);
620 reduce(prefix);
621 if (prefix[0]) {
622 pathconfig->prefix = prefix;
623 }
624 else {
625 PyMem_RawFree(prefix);
626
627 /* The prefix is the root directory, but reduce() chopped
628 off the "/". */
629 pathconfig->prefix = _PyMem_RawWcsdup(separator);
630 if (pathconfig->prefix == NULL) {
631 return _PyStatus_NO_MEMORY();
632 }
633 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100634 }
635 else {
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200636 pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200637 if (pathconfig->prefix == NULL) {
638 return _PyStatus_NO_MEMORY();
639 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100640 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200641 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100642}
643
644
Victor Stinner96c84752019-09-26 16:17:34 +0200645static PyStatus
646calculate_pybuilddir(const wchar_t *argv0_path,
647 wchar_t *exec_prefix, size_t exec_prefix_len,
648 int *found)
649{
650 PyStatus status;
651
Victor Stinner96c84752019-09-26 16:17:34 +0200652 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
653 is written by setup.py and contains the relative path to the location
654 of shared library modules.
655
656 Filename: <argv0_path> / "pybuilddir.txt" */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200657 wchar_t *filename = joinpath2(argv0_path, L"pybuilddir.txt");
658 if (filename == NULL) {
659 return _PyStatus_NO_MEMORY();
Victor Stinner96c84752019-09-26 16:17:34 +0200660 }
661
662 FILE *fp = _Py_wfopen(filename, L"rb");
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200663 PyMem_RawFree(filename);
Victor Stinner96c84752019-09-26 16:17:34 +0200664 if (fp == NULL) {
665 errno = 0;
666 return _PyStatus_OK();
667 }
668
669 char buf[MAXPATHLEN + 1];
670 size_t n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, fp);
671 buf[n] = '\0';
672 fclose(fp);
673
674 size_t dec_len;
675 wchar_t *pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
676 if (!pybuilddir) {
677 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
678 }
679
680 /* Path: <argv0_path> / <pybuilddir content> */
681 if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) {
682 PyMem_RawFree(pybuilddir);
683 return PATHLEN_ERR();
684 }
685 status = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
686 PyMem_RawFree(pybuilddir);
687 if (_PyStatus_EXCEPTION(status)) {
688 return status;
689 }
690
691 *found = -1;
692 return _PyStatus_OK();
693}
694
695
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000696/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000697 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000698*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200699static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200700search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100701 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100702 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000703{
Victor Stinner331a6a52019-05-27 16:39:22 +0200704 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000705
Fred Drakeedabdc12000-07-08 06:16:37 +0000706 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200707 if (pathconfig->home) {
Victor Stinner96c84752019-09-26 16:17:34 +0200708 /* Path: <home> / <lib_python> / "lib-dynload" */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200709 wchar_t *delim = wcschr(pathconfig->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100710 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100711 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
712 return PATHLEN_ERR();
713 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100714 }
715 else {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200716 if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100717 return PATHLEN_ERR();
718 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100719 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200720 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
721 if (_PyStatus_EXCEPTION(status)) {
722 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100723 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200724 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
725 if (_PyStatus_EXCEPTION(status)) {
726 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100727 }
728 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200729 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000730 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000731
Victor Stinner96c84752019-09-26 16:17:34 +0200732 /* Check for pybuilddir.txt */
733 assert(*found == 0);
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200734 status = calculate_pybuilddir(calculate->argv0_path,
735 exec_prefix, exec_prefix_len, found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200736 if (_PyStatus_EXCEPTION(status)) {
737 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100738 }
Victor Stinner96c84752019-09-26 16:17:34 +0200739 if (*found) {
740 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000741 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000742
Fred Drakeedabdc12000-07-08 06:16:37 +0000743 /* Search from argv0_path, until root is found */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200744 status = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200745 if (_PyStatus_EXCEPTION(status)) {
746 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100747 }
748
Fred Drakeedabdc12000-07-08 06:16:37 +0000749 do {
Victor Stinner96c84752019-09-26 16:17:34 +0200750 /* Path: <argv0_path or substring> / <lib_python> / "lib-dynload" */
751 size_t n = wcslen(exec_prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200752 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
753 if (_PyStatus_EXCEPTION(status)) {
754 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100755 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200756 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
757 if (_PyStatus_EXCEPTION(status)) {
758 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100759 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100760 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100761 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200762 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100763 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100764 exec_prefix[n] = L'\0';
765 reduce(exec_prefix);
766 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000767
Victor Stinner96c84752019-09-26 16:17:34 +0200768 /* Look at configure's EXEC_PREFIX.
769
770 Path: <EXEC_PREFIX macro> / <lib_python> / "lib-dynload" */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200771 if (safe_wcscpy(exec_prefix, calculate->exec_prefix_macro, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100772 return PATHLEN_ERR();
773 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200774 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
775 if (_PyStatus_EXCEPTION(status)) {
776 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100777 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200778 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
779 if (_PyStatus_EXCEPTION(status)) {
780 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100781 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100782 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100783 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200784 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100785 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000786
Fred Drakeedabdc12000-07-08 06:16:37 +0000787 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100788 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200789 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000790}
791
Guido van Rossum305e5d01997-04-11 17:18:45 +0000792
Victor Stinner331a6a52019-05-27 16:39:22 +0200793static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200794calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100795{
Victor Stinner331a6a52019-05-27 16:39:22 +0200796 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200797 wchar_t exec_prefix[MAXPATHLEN+1];
798 memset(exec_prefix, 0, sizeof(exec_prefix));
799 size_t exec_prefix_len = Py_ARRAY_LENGTH(exec_prefix);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100800
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200801 status = search_for_exec_prefix(calculate, pathconfig,
Victor Stinner3f5409a2019-09-23 19:50:27 +0200802 exec_prefix, exec_prefix_len,
803 &calculate->exec_prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200804 if (_PyStatus_EXCEPTION(status)) {
805 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100806 }
807
Victor Stinner0327bde2017-11-23 17:03:20 +0100808 if (!calculate->exec_prefix_found) {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200809 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100810 fprintf(stderr,
811 "Could not find platform dependent libraries <exec_prefix>\n");
812 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200813
Victor Stinnerdc401052020-06-11 18:27:00 +0200814 /* <platlibdir> / "lib-dynload" */
Victor Stinner81750642020-06-08 19:36:13 +0200815 wchar_t *lib_dynload = joinpath2(calculate->platlibdir,
Victor Stinner8510f432020-03-10 09:53:09 +0100816 L"lib-dynload");
817 if (lib_dynload == NULL) {
818 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100819 }
Victor Stinner8510f432020-03-10 09:53:09 +0100820
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200821 calculate->exec_prefix = joinpath2(calculate->exec_prefix_macro,
Victor Stinner8510f432020-03-10 09:53:09 +0100822 lib_dynload);
823 PyMem_RawFree(lib_dynload);
824
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200825 if (calculate->exec_prefix == NULL) {
826 return _PyStatus_NO_MEMORY();
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100827 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100828 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200829 else {
830 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
831 calculate->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
832 if (calculate->exec_prefix == NULL) {
833 return _PyStatus_NO_MEMORY();
834 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200835 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200836 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100837}
838
839
Victor Stinner331a6a52019-05-27 16:39:22 +0200840static PyStatus
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700841calculate_set_exec_prefix(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200842 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100843{
844 if (calculate->exec_prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200845 wchar_t *exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix);
846 if (exec_prefix == NULL) {
847 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100848 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -0700849
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200850 reduce(exec_prefix);
851 reduce(exec_prefix);
852 reduce(exec_prefix);
853
854 if (exec_prefix[0]) {
855 pathconfig->exec_prefix = exec_prefix;
856 }
857 else {
858 /* empty string: use SEP instead */
859 PyMem_RawFree(exec_prefix);
860
861 /* The exec_prefix is the root directory, but reduce() chopped
862 off the "/". */
863 pathconfig->exec_prefix = _PyMem_RawWcsdup(separator);
864 if (pathconfig->exec_prefix == NULL) {
865 return _PyStatus_NO_MEMORY();
866 }
867 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100868 }
869 else {
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200870 pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200871 if (pathconfig->exec_prefix == NULL) {
872 return _PyStatus_NO_MEMORY();
873 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100874 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200875 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100876}
877
878
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200879/* Similar to shutil.which().
880 If found, write the path into *abs_path_p. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200881static PyStatus
Victor Stinner03a8a562019-10-04 02:22:39 +0200882calculate_which(const wchar_t *path_env, wchar_t *program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200883 wchar_t **abs_path_p)
Victor Stinner0327bde2017-11-23 17:03:20 +0100884{
Victor Stinner03a8a562019-10-04 02:22:39 +0200885 while (1) {
886 wchar_t *delim = wcschr(path_env, DELIM);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200887 wchar_t *abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200888
889 if (delim) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200890 wchar_t *path = substring(path_env, delim - path_env);
891 if (path == NULL) {
892 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +0200893 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200894 abs_path = joinpath2(path, program_name);
895 PyMem_RawFree(path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200896 }
897 else {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200898 abs_path = joinpath2(path_env, program_name);
Victor Stinner03a8a562019-10-04 02:22:39 +0200899 }
900
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200901 if (abs_path == NULL) {
902 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +0200903 }
904
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200905 if (isxfile(abs_path)) {
906 *abs_path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200907 return _PyStatus_OK();
908 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200909 PyMem_RawFree(abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200910
911 if (!delim) {
912 break;
913 }
914 path_env = delim + 1;
915 }
916
917 /* not found */
918 return _PyStatus_OK();
919}
920
Victor Stinner9316ee42017-11-25 03:17:57 +0100921
Victor Stinnerb9197952017-11-23 19:02:04 +0100922#ifdef __APPLE__
Victor Stinner03a8a562019-10-04 02:22:39 +0200923static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200924calculate_program_macos(wchar_t **abs_path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +0200925{
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100926 char execpath[MAXPATHLEN + 1];
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100927 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinner03a8a562019-10-04 02:22:39 +0200928
929 /* On Mac OS X, if a script uses an interpreter of the form
930 "#!/opt/python2.3/bin/python", the kernel only passes "python"
931 as argv[0], which falls through to the $PATH search below.
932 If /opt/python2.3/bin isn't in your path, or is near the end,
933 this algorithm may incorrectly find /usr/bin/python. To work
934 around this, we can use _NSGetExecutablePath to get a better
935 hint of what the intended interpreter was, although this
936 will fail if a relative path was used. but in that case,
937 absolutize() should help us out below
938 */
939 if (_NSGetExecutablePath(execpath, &nsexeclength) != 0
940 || (wchar_t)execpath[0] != SEP)
941 {
942 /* _NSGetExecutablePath() failed or the path is relative */
943 return _PyStatus_OK();
944 }
945
946 size_t len;
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200947 *abs_path_p = Py_DecodeLocale(execpath, &len);
948 if (*abs_path_p == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +0200949 return DECODE_LOCALE_ERR("executable path", len);
950 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200951 return _PyStatus_OK();
952}
953#endif /* __APPLE__ */
954
955
956static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200957calculate_program_impl(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +0200958{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200959 assert(pathconfig->program_full_path == NULL);
960
Victor Stinner03a8a562019-10-04 02:22:39 +0200961 PyStatus status;
Victor Stinnerb9197952017-11-23 19:02:04 +0100962
Victor Stinner0327bde2017-11-23 17:03:20 +0100963 /* If there is no slash in the argv0 path, then we have to
964 * assume python is on the user's $PATH, since there's no
965 * other way to find a directory to start the search from. If
966 * $PATH isn't exported, you lose.
967 */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200968 if (wcschr(pathconfig->program_name, SEP)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200969 pathconfig->program_full_path = _PyMem_RawWcsdup(pathconfig->program_name);
970 if (pathconfig->program_full_path == NULL) {
971 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100972 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200973 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100974 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200975
Jack Jansen1afd4802004-06-03 14:33:03 +0000976#ifdef __APPLE__
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200977 wchar_t *abs_path = NULL;
978 status = calculate_program_macos(&abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200979 if (_PyStatus_EXCEPTION(status)) {
980 return status;
981 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200982 if (abs_path) {
983 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200984 return _PyStatus_OK();
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000985 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000986#endif /* __APPLE__ */
Jack Jansen55070f52001-12-02 23:56:28 +0000987
Victor Stinner03a8a562019-10-04 02:22:39 +0200988 if (calculate->path_env) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200989 wchar_t *abs_path = NULL;
Victor Stinner03a8a562019-10-04 02:22:39 +0200990 status = calculate_which(calculate->path_env, pathconfig->program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200991 &abs_path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200992 if (_PyStatus_EXCEPTION(status)) {
993 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100994 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200995 if (abs_path) {
996 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200997 return _PyStatus_OK();
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100998 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200999 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001000
Victor Stinner03a8a562019-10-04 02:22:39 +02001001 /* In the last resort, use an empty string */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001002 pathconfig->program_full_path = _PyMem_RawWcsdup(L"");
Victor Stinner331a6a52019-05-27 16:39:22 +02001003 if (pathconfig->program_full_path == NULL) {
1004 return _PyStatus_NO_MEMORY();
Victor Stinner9316ee42017-11-25 03:17:57 +01001005 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001006 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001007}
1008
1009
Victor Stinner03a8a562019-10-04 02:22:39 +02001010/* Calculate pathconfig->program_full_path */
Victor Stinner331a6a52019-05-27 16:39:22 +02001011static PyStatus
Victor Stinner03a8a562019-10-04 02:22:39 +02001012calculate_program(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001013{
Victor Stinner03a8a562019-10-04 02:22:39 +02001014 PyStatus status;
Victor Stinner03a8a562019-10-04 02:22:39 +02001015
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001016 status = calculate_program_impl(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001017 if (_PyStatus_EXCEPTION(status)) {
1018 return status;
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001019 }
Jack Jansen55070f52001-12-02 23:56:28 +00001020
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001021 if (pathconfig->program_full_path[0] != '\0') {
Victor Stinner03a8a562019-10-04 02:22:39 +02001022 /* program_full_path is not empty */
Victor Stinner0327bde2017-11-23 17:03:20 +01001023
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001024 /* Make sure that program_full_path is an absolute path */
1025 if (!_Py_isabs(pathconfig->program_full_path)) {
1026 status = absolutize(&pathconfig->program_full_path);
Victor Stinner331a6a52019-05-27 16:39:22 +02001027 if (_PyStatus_EXCEPTION(status)) {
1028 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001029 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001030 }
Victor Stinner03a8a562019-10-04 02:22:39 +02001031
1032#if defined(__CYGWIN__) || defined(__MINGW32__)
1033 /* For these platforms it is necessary to ensure that the .exe suffix
1034 * is appended to the filename, otherwise there is potential for
1035 * sys.executable to return the name of a directory under the same
1036 * path (bpo-28441).
1037 */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001038 status = add_exe_suffix(&pathconfig->program_full_path);
Antoine Pitrou99773ac2010-08-14 12:34:41 +00001039 if (_PyStatus_EXCEPTION(status)) {
1040 return status;
1041 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001042#endif
Fred Drakeedabdc12000-07-08 06:16:37 +00001043 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001044 return _PyStatus_OK();
1045}
1046
1047
Victor Stinner03a8a562019-10-04 02:22:39 +02001048#if HAVE_READLINK
Guido van Rossum305e5d01997-04-11 17:18:45 +00001049static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001050resolve_symlinks(wchar_t **path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +02001051{
1052 wchar_t new_path[MAXPATHLEN + 1];
1053 const size_t new_path_len = Py_ARRAY_LENGTH(new_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001054 unsigned int nlink = 0;
Victor Stinner03a8a562019-10-04 02:22:39 +02001055
1056 while (1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001057 int linklen = _Py_wreadlink(*path_p, new_path, new_path_len);
Victor Stinner03a8a562019-10-04 02:22:39 +02001058 if (linklen == -1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001059 /* not a symbolic link: we are done */
Victor Stinner03a8a562019-10-04 02:22:39 +02001060 break;
1061 }
1062
1063 if (_Py_isabs(new_path)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001064 PyMem_RawFree(*path_p);
1065 *path_p = _PyMem_RawWcsdup(new_path);
1066 if (*path_p == NULL) {
1067 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001068 }
1069 }
1070 else {
1071 /* new_path is relative to path */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001072 reduce(*path_p);
1073
1074 wchar_t *abs_path = joinpath2(*path_p, new_path);
1075 if (abs_path == NULL) {
1076 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001077 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001078
1079 PyMem_RawFree(*path_p);
1080 *path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +02001081 }
1082
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001083 nlink++;
Victor Stinner03a8a562019-10-04 02:22:39 +02001084 /* 40 is the Linux kernel 4.2 limit */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001085 if (nlink >= 40) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001086 return _PyStatus_ERR("maximum number of symbolic links reached");
1087 }
1088 }
1089 return _PyStatus_OK();
1090}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001091#endif /* HAVE_READLINK */
1092
Victor Stinner03a8a562019-10-04 02:22:39 +02001093
1094#ifdef WITH_NEXT_FRAMEWORK
1095static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001096calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +02001097{
1098 NSModule pythonModule;
1099
1100 /* On Mac OS X we have a special case if we're running from a framework.
1101 This is because the python home should be set relative to the library,
1102 which is in the framework, not relative to the executable, which may
1103 be outside of the framework. Except when we're in the build
1104 directory... */
1105 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
1106
1107 /* Use dylib functions to find out where the framework was loaded from */
1108 const char* modPath = NSLibraryNameForModule(pythonModule);
1109 if (modPath == NULL) {
1110 return _PyStatus_OK();
1111 }
1112
1113 /* We're in a framework.
1114 See if we might be in the build directory. The framework in the
1115 build directory is incomplete, it only has the .dylib and a few
1116 needed symlinks, it doesn't have the Lib directories and such.
1117 If we're running with the framework from the build directory we must
1118 be running the interpreter in the build directory, so we use the
1119 build-directory-specific logic to find Lib and such. */
1120 size_t len;
1121 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
1122 if (wbuf == NULL) {
1123 return DECODE_LOCALE_ERR("framework location", len);
1124 }
1125
1126 /* Path: reduce(modPath) / lib_python / LANDMARK */
1127 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001128
1129 wchar_t *parent = _PyMem_RawWcsdup(wbuf);
1130 if (parent == NULL) {
1131 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001132 goto done;
1133 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001134
1135 reduce(parent);
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001136 wchar_t *lib_python = joinpath2(parent, calculate->lib_python);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001137 PyMem_RawFree(parent);
1138
1139 if (lib_python == NULL) {
1140 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001141 goto done;
1142 }
Victor Stinnerf0c85792019-10-04 03:53:26 +02001143
1144 int module;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001145 status = ismodule(lib_python, &module);
1146 PyMem_RawFree(lib_python);
1147
Victor Stinner03a8a562019-10-04 02:22:39 +02001148 if (_PyStatus_EXCEPTION(status)) {
1149 goto done;
1150 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001151 if (!module) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001152 /* We are in the build directory so use the name of the
1153 executable - we know that the absolute path is passed */
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001154 PyMem_RawFree(calculate->argv0_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001155 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1156 if (calculate->argv0_path == NULL) {
1157 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001158 goto done;
1159 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001160
1161 status = _PyStatus_OK();
1162 goto done;
Victor Stinner03a8a562019-10-04 02:22:39 +02001163 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001164
1165 /* Use the location of the library as argv0_path */
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001166 PyMem_RawFree(calculate->argv0_path);
1167 calculate->argv0_path = wbuf;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001168 return _PyStatus_OK();
Victor Stinner03a8a562019-10-04 02:22:39 +02001169
1170done:
1171 PyMem_RawFree(wbuf);
1172 return status;
1173}
1174#endif
1175
1176
1177static PyStatus
1178calculate_argv0_path(PyCalculatePath *calculate,
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001179 _PyPathConfig *pathconfig)
Guido van Rossum305e5d01997-04-11 17:18:45 +00001180{
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001181 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001182
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001183 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1184 if (calculate->argv0_path == NULL) {
1185 return _PyStatus_NO_MEMORY();
Guido van Rossum305e5d01997-04-11 17:18:45 +00001186 }
1187
1188#ifdef WITH_NEXT_FRAMEWORK
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001189 status = calculate_argv0_path_framework(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001190 if (_PyStatus_EXCEPTION(status)) {
1191 return status;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001192 }
1193#endif
1194
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001195 status = resolve_symlinks(&calculate->argv0_path);
1196 if (_PyStatus_EXCEPTION(status)) {
1197 return status;
1198 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001199
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001200 reduce(calculate->argv0_path);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001201
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001202 return _PyStatus_OK();
1203}
1204
1205
1206static PyStatus
1207calculate_open_pyenv(PyCalculatePath *calculate, FILE **env_file_p)
1208{
1209 *env_file_p = NULL;
1210
1211 const wchar_t *env_cfg = L"pyvenv.cfg";
1212
1213 /* Filename: <argv0_path> / "pyvenv.cfg" */
1214 wchar_t *filename = joinpath2(calculate->argv0_path, env_cfg);
1215 if (filename == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001216 return _PyStatus_NO_MEMORY();
1217 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001218
1219 *env_file_p = _Py_wfopen(filename, L"r");
1220 PyMem_RawFree(filename);
1221
1222 if (*env_file_p != NULL) {
1223 return _PyStatus_OK();
1224
1225 }
1226
1227 /* fopen() failed: reset errno */
1228 errno = 0;
1229
1230 /* Path: <basename(argv0_path)> / "pyvenv.cfg" */
1231 wchar_t *parent = _PyMem_RawWcsdup(calculate->argv0_path);
1232 if (parent == NULL) {
1233 return _PyStatus_NO_MEMORY();
1234 }
1235 reduce(parent);
1236
1237 filename = joinpath2(parent, env_cfg);
1238 PyMem_RawFree(parent);
1239 if (filename == NULL) {
1240 return _PyStatus_NO_MEMORY();
1241 }
1242
1243 *env_file_p = _Py_wfopen(filename, L"r");
1244 PyMem_RawFree(filename);
1245
1246 if (*env_file_p == NULL) {
1247 /* fopen() failed: reset errno */
1248 errno = 0;
1249 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001250 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001251}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001252
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001253
Victor Stinner0327bde2017-11-23 17:03:20 +01001254/* Search for an "pyvenv.cfg" environment configuration file, first in the
1255 executable's directory and then in the parent directory.
1256 If found, open it for use when searching for prefixes.
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001257
1258 Write the 'home' variable of pyvenv.cfg into calculate->argv0_path. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001259static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001260calculate_read_pyenv(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001261{
Victor Stinner331a6a52019-05-27 16:39:22 +02001262 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001263 FILE *env_file = NULL;
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001264
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001265 status = calculate_open_pyenv(calculate, &env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001266 if (_PyStatus_EXCEPTION(status)) {
1267 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001268 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001269 if (env_file == NULL) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001270 /* pyvenv.cfg not found */
1271 return _PyStatus_OK();
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001272 }
1273
Victor Stinner0327bde2017-11-23 17:03:20 +01001274 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001275 wchar_t *home = NULL;
1276 status = _Py_FindEnvConfigValue(env_file, L"home", &home);
1277 if (_PyStatus_EXCEPTION(status)) {
1278 fclose(env_file);
1279 return status;
1280 }
Victor Stinner96c84752019-09-26 16:17:34 +02001281
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001282 if (home) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001283 PyMem_RawFree(calculate->argv0_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001284 calculate->argv0_path = home;
Just van Rossum52e14d62002-12-30 22:08:05 +00001285 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001286 fclose(env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001287 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001288}
Just van Rossum52e14d62002-12-30 22:08:05 +00001289
Guido van Rossum305e5d01997-04-11 17:18:45 +00001290
Victor Stinner331a6a52019-05-27 16:39:22 +02001291static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001292calculate_zip_path(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001293{
Victor Stinner8510f432020-03-10 09:53:09 +01001294 PyStatus res;
1295
Victor Stinnerdc401052020-06-11 18:27:00 +02001296 /* Path: <platlibdir> / "pythonXY.zip" */
1297 wchar_t *path = joinpath2(calculate->platlibdir,
1298 L"python" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION)
1299 L".zip");
Victor Stinner8510f432020-03-10 09:53:09 +01001300 if (path == NULL) {
1301 return _PyStatus_NO_MEMORY();
1302 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001303
Victor Stinner0327bde2017-11-23 17:03:20 +01001304 if (calculate->prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001305 /* Use the reduced prefix returned by Py_GetPrefix()
1306
Victor Stinnerdc401052020-06-11 18:27:00 +02001307 Path: <basename(basename(prefix))> / <platlibdir> / "pythonXY.zip" */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001308 wchar_t *parent = _PyMem_RawWcsdup(calculate->prefix);
1309 if (parent == NULL) {
Victor Stinner8510f432020-03-10 09:53:09 +01001310 res = _PyStatus_NO_MEMORY();
1311 goto done;
Victor Stinner96c84752019-09-26 16:17:34 +02001312 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001313 reduce(parent);
1314 reduce(parent);
Victor Stinner8510f432020-03-10 09:53:09 +01001315 calculate->zip_path = joinpath2(parent, path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001316 PyMem_RawFree(parent);
Victor Stinnerd4341102017-11-23 00:12:09 +01001317 }
1318 else {
Victor Stinner8510f432020-03-10 09:53:09 +01001319 calculate->zip_path = joinpath2(calculate->prefix_macro, path);
Victor Stinner0327bde2017-11-23 17:03:20 +01001320 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001321
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001322 if (calculate->zip_path == NULL) {
Victor Stinner8510f432020-03-10 09:53:09 +01001323 res = _PyStatus_NO_MEMORY();
1324 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001325 }
1326
1327 /* Replace "00" with version */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001328 size_t len = wcslen(calculate->zip_path);
1329 calculate->zip_path[len - 6] = VERSION[0];
1330 calculate->zip_path[len - 5] = VERSION[2];
1331
Victor Stinner8510f432020-03-10 09:53:09 +01001332 res = _PyStatus_OK();
1333
1334done:
1335 PyMem_RawFree(path);
1336 return res;
Victor Stinner0327bde2017-11-23 17:03:20 +01001337}
1338
1339
Victor Stinner331a6a52019-05-27 16:39:22 +02001340static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +02001341calculate_module_search_path(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001342 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001343{
1344 /* Calculate size of return buffer */
1345 size_t bufsz = 0;
Victor Stinner3f5409a2019-09-23 19:50:27 +02001346 if (calculate->pythonpath_env != NULL) {
1347 bufsz += wcslen(calculate->pythonpath_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001348 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001349
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001350 wchar_t *defpath = calculate->pythonpath_macro;
1351 size_t prefixsz = wcslen(calculate->prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001352 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001353 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001354
Victor Stinner3939c322019-06-25 15:02:43 +02001355 if (!_Py_isabs(defpath)) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001356 /* Paths are relative to prefix */
1357 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001358 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001359
Victor Stinner0327bde2017-11-23 17:03:20 +01001360 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001361 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001362 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001363 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001364 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001365 break;
1366 }
1367 defpath = delim + 1;
1368 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001369
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001370 bufsz += wcslen(calculate->zip_path) + 1;
1371 bufsz += wcslen(calculate->exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001372
Victor Stinner0327bde2017-11-23 17:03:20 +01001373 /* Allocate the buffer */
1374 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001375 if (buf == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +02001376 return _PyStatus_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001377 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001378 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001379
Victor Stinner72967a42013-11-16 01:22:04 +01001380 /* Run-time value of $PYTHONPATH goes first */
Victor Stinner3f5409a2019-09-23 19:50:27 +02001381 if (calculate->pythonpath_env) {
1382 wcscpy(buf, calculate->pythonpath_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001383 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001384 }
Victor Stinner72967a42013-11-16 01:22:04 +01001385
1386 /* Next is the default zip path */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001387 wcscat(buf, calculate->zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001388 wcscat(buf, delimiter);
1389
1390 /* Next goes merge of compile-time $PYTHONPATH with
1391 * dynamically located prefix.
1392 */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001393 defpath = calculate->pythonpath_macro;
Victor Stinner72967a42013-11-16 01:22:04 +01001394 while (1) {
1395 wchar_t *delim = wcschr(defpath, DELIM);
1396
Victor Stinner3939c322019-06-25 15:02:43 +02001397 if (!_Py_isabs(defpath)) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001398 wcscat(buf, calculate->prefix);
1399 if (prefixsz >= 2 && calculate->prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001400 defpath[0] != (delim ? DELIM : L'\0'))
1401 {
1402 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001403 wcscat(buf, separator);
1404 }
Victor Stinner72967a42013-11-16 01:22:04 +01001405 }
1406
1407 if (delim) {
1408 size_t len = delim - defpath + 1;
1409 size_t end = wcslen(buf) + len;
1410 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001411 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001412 }
1413 else {
1414 wcscat(buf, defpath);
1415 break;
1416 }
1417 defpath = delim + 1;
1418 }
1419 wcscat(buf, delimiter);
1420
1421 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001422 wcscat(buf, calculate->exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001423
Victor Stinner331a6a52019-05-27 16:39:22 +02001424 pathconfig->module_search_path = buf;
1425 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001426}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001427
Victor Stinner0327bde2017-11-23 17:03:20 +01001428
Victor Stinner331a6a52019-05-27 16:39:22 +02001429static PyStatus
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001430calculate_init(PyCalculatePath *calculate, const PyConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001431{
Victor Stinner0327bde2017-11-23 17:03:20 +01001432 size_t len;
Victor Stinnerdc401052020-06-11 18:27:00 +02001433
1434 calculate->warnings = config->pathconfig_warnings;
1435 calculate->pythonpath_env = config->pythonpath_env;
1436 calculate->platlibdir = config->platlibdir;
1437
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001438 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001439 if (path) {
1440 calculate->path_env = Py_DecodeLocale(path, &len);
1441 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001442 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001443 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001444 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001445
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001446 /* Decode macros */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001447 calculate->pythonpath_macro = Py_DecodeLocale(PYTHONPATH, &len);
1448 if (!calculate->pythonpath_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001449 return DECODE_LOCALE_ERR("PYTHONPATH macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001450 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001451 calculate->prefix_macro = Py_DecodeLocale(PREFIX, &len);
1452 if (!calculate->prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001453 return DECODE_LOCALE_ERR("PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001454 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001455 calculate->exec_prefix_macro = Py_DecodeLocale(EXEC_PREFIX, &len);
1456 if (!calculate->exec_prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001457 return DECODE_LOCALE_ERR("EXEC_PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001458 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001459 calculate->vpath_macro = Py_DecodeLocale(VPATH, &len);
1460 if (!calculate->vpath_macro) {
1461 return DECODE_LOCALE_ERR("VPATH macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001462 }
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001463
Victor Stinnerdc401052020-06-11 18:27:00 +02001464 // <platlibdir> / "pythonX.Y"
1465 wchar_t *pyversion = Py_DecodeLocale("python" VERSION, &len);
1466 if (!pyversion) {
Victor Stinner8510f432020-03-10 09:53:09 +01001467 return DECODE_LOCALE_ERR("VERSION macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001468 }
Victor Stinnerdc401052020-06-11 18:27:00 +02001469 calculate->lib_python = joinpath2(config->platlibdir, pyversion);
1470 PyMem_RawFree(pyversion);
1471 if (calculate->lib_python == NULL) {
1472 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +01001473 }
Victor Stinner3f5409a2019-09-23 19:50:27 +02001474
Victor Stinner331a6a52019-05-27 16:39:22 +02001475 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001476}
1477
1478
1479static void
1480calculate_free(PyCalculatePath *calculate)
1481{
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001482 PyMem_RawFree(calculate->pythonpath_macro);
1483 PyMem_RawFree(calculate->prefix_macro);
1484 PyMem_RawFree(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001485 PyMem_RawFree(calculate->vpath_macro);
Victor Stinner0327bde2017-11-23 17:03:20 +01001486 PyMem_RawFree(calculate->lib_python);
1487 PyMem_RawFree(calculate->path_env);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001488 PyMem_RawFree(calculate->zip_path);
1489 PyMem_RawFree(calculate->argv0_path);
1490 PyMem_RawFree(calculate->prefix);
1491 PyMem_RawFree(calculate->exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +01001492}
1493
1494
Victor Stinner331a6a52019-05-27 16:39:22 +02001495static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +02001496calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001497{
Victor Stinner331a6a52019-05-27 16:39:22 +02001498 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +01001499
Victor Stinner3f5409a2019-09-23 19:50:27 +02001500 if (pathconfig->program_full_path == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001501 status = calculate_program(calculate, pathconfig);
Victor Stinner3f5409a2019-09-23 19:50:27 +02001502 if (_PyStatus_EXCEPTION(status)) {
1503 return status;
1504 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001505 }
1506
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001507 status = calculate_argv0_path(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001508 if (_PyStatus_EXCEPTION(status)) {
1509 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001510 }
1511
Victor Stinner96c84752019-09-26 16:17:34 +02001512 /* If a pyvenv.cfg configure file is found,
1513 argv0_path is overriden with its 'home' variable. */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001514 status = calculate_read_pyenv(calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001515 if (_PyStatus_EXCEPTION(status)) {
1516 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001517 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001518
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001519 status = calculate_prefix(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001520 if (_PyStatus_EXCEPTION(status)) {
1521 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001522 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001523
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001524 status = calculate_zip_path(calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001525 if (_PyStatus_EXCEPTION(status)) {
1526 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001527 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001528
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001529 status = calculate_exec_prefix(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001530 if (_PyStatus_EXCEPTION(status)) {
1531 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001532 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001533
Victor Stinner03a8a562019-10-04 02:22:39 +02001534 if ((!calculate->prefix_found || !calculate->exec_prefix_found)
1535 && calculate->warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001536 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001537 fprintf(stderr,
1538 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1539 }
1540
Victor Stinner9f3dcf82019-09-21 02:13:14 +02001541 if (pathconfig->module_search_path == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001542 status = calculate_module_search_path(calculate, pathconfig);
Victor Stinner9f3dcf82019-09-21 02:13:14 +02001543 if (_PyStatus_EXCEPTION(status)) {
1544 return status;
1545 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001546 }
1547
Victor Stinner331a6a52019-05-27 16:39:22 +02001548 if (pathconfig->prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001549 status = calculate_set_prefix(calculate, pathconfig);
Victor Stinner3f5409a2019-09-23 19:50:27 +02001550 if (_PyStatus_EXCEPTION(status)) {
1551 return status;
1552 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001553 }
1554
Victor Stinner331a6a52019-05-27 16:39:22 +02001555 if (pathconfig->exec_prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001556 status = calculate_set_exec_prefix(calculate, pathconfig);
Victor Stinner3f5409a2019-09-23 19:50:27 +02001557 if (_PyStatus_EXCEPTION(status)) {
1558 return status;
1559 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001560 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001561 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001562}
1563
1564
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001565/* Calculate the Python path configuration.
1566
1567 Inputs:
1568
1569 - PATH environment variable
1570 - Macros: PYTHONPATH, PREFIX, EXEC_PREFIX, VERSION (ex: "3.9").
1571 PREFIX and EXEC_PREFIX are generated by the configure script.
1572 PYTHONPATH macro is the default search path.
1573 - pybuilddir.txt file
1574 - pyvenv.cfg configuration file
1575 - PyConfig fields ('config' function argument):
1576
1577 - pathconfig_warnings
1578 - pythonpath_env (PYTHONPATH environment variable)
1579
1580 - _PyPathConfig fields ('pathconfig' function argument):
1581
1582 - program_name: see config_init_program_name()
1583 - home: Py_SetPythonHome() or PYTHONHOME environment variable
1584
1585 - current working directory: see copy_absolute()
1586
1587 Outputs, 'pathconfig' fields:
Victor Stinner3f5409a2019-09-23 19:50:27 +02001588
1589 - program_full_path
1590 - module_search_path
1591 - prefix
1592 - exec_prefix
1593
Miss Islington (bot)7f7cd892019-09-23 16:16:53 -07001594 If a field is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001595PyStatus
1596_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001597{
Victor Stinner331a6a52019-05-27 16:39:22 +02001598 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001599 PyCalculatePath calculate;
1600 memset(&calculate, 0, sizeof(calculate));
1601
Victor Stinner331a6a52019-05-27 16:39:22 +02001602 status = calculate_init(&calculate, config);
1603 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001604 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001605 }
1606
Victor Stinner3f5409a2019-09-23 19:50:27 +02001607 status = calculate_path(&calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001608 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001609 goto done;
1610 }
1611
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001612 /* program_full_path must an either an empty string or an absolute path */
1613 assert(wcslen(pathconfig->program_full_path) == 0
1614 || _Py_isabs(pathconfig->program_full_path));
1615
Victor Stinner331a6a52019-05-27 16:39:22 +02001616 status = _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001617
Victor Stinner9316ee42017-11-25 03:17:57 +01001618done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001619 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001620 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001621}
Victor Stinner46972b72017-11-24 22:55:40 +01001622
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001623#ifdef __cplusplus
1624}
1625#endif