blob: ef6dd59a084d8de4dddfc193e0166b5d2f52a2f8 [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__
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
Min ho Kimc4cacc82019-07-31 08:16:13 +100097 * these automatic path computations.
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000098 *
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
Victor Stinner8510f432020-03-10 09:53:09 +0100107#if (!defined(PREFIX) || !defined(EXEC_PREFIX) \
Sandro Mani8f023a22020-06-08 17:28:11 +0200108 || !defined(VERSION) || !defined(VPATH))
109#error "PREFIX, EXEC_PREFIX, VERSION and VPATH macros must be defined"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000110#endif
Guido van Rossum667d7041995-08-04 04:20:48 +0000111
Guido van Rossum305e5d01997-04-11 17:18:45 +0000112#ifndef LANDMARK
Martin v. Löwis790465f2008-04-05 20:41:37 +0000113#define LANDMARK L"os.py"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000114#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000115
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200116#define BUILD_LANDMARK L"Modules/Setup.local"
117
Victor Stinner9316ee42017-11-25 03:17:57 +0100118#define DECODE_LOCALE_ERR(NAME, LEN) \
119 ((LEN) == (size_t)-2) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200120 ? _PyStatus_ERR("cannot decode " NAME) \
121 : _PyStatus_NO_MEMORY()
Victor Stinner9316ee42017-11-25 03:17:57 +0100122
Victor Stinner331a6a52019-05-27 16:39:22 +0200123#define PATHLEN_ERR() _PyStatus_ERR("path configuration: path too long")
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100124
Victor Stinner0327bde2017-11-23 17:03:20 +0100125typedef struct {
126 wchar_t *path_env; /* PATH environment variable */
Victor Stinner0327bde2017-11-23 17:03:20 +0100127
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200128 wchar_t *pythonpath_macro; /* PYTHONPATH macro */
129 wchar_t *prefix_macro; /* PREFIX macro */
130 wchar_t *exec_prefix_macro; /* EXEC_PREFIX macro */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200131 wchar_t *vpath_macro; /* VPATH macro */
Victor Stinner0327bde2017-11-23 17:03:20 +0100132
Victor Stinnerd72b9642020-06-11 17:28:52 +0200133 wchar_t *lib_python; /* <platlibdir> / "pythonX.Y" */
Victor Stinner0327bde2017-11-23 17:03:20 +0100134
135 int prefix_found; /* found platform independent libraries? */
136 int exec_prefix_found; /* found the platform dependent libraries? */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200137
138 int warnings;
139 const wchar_t *pythonpath_env;
Sandro Mani8f023a22020-06-08 17:28:11 +0200140 const wchar_t *platlibdir;
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200141
142 wchar_t *argv0_path;
143 wchar_t *zip_path;
144 wchar_t *prefix;
145 wchar_t *exec_prefix;
Victor Stinner0327bde2017-11-23 17:03:20 +0100146} PyCalculatePath;
147
148static const wchar_t delimiter[2] = {DELIM, '\0'};
149static const wchar_t separator[2] = {SEP, '\0'};
Victor Stinner0327bde2017-11-23 17:03:20 +0100150
Martin v. Löwis790465f2008-04-05 20:41:37 +0000151
Victor Stinner91afbb62015-03-24 12:16:28 +0100152/* Get file status. Encode the path to the locale encoding. */
Victor Stinner91afbb62015-03-24 12:16:28 +0100153static int
154_Py_wstat(const wchar_t* path, struct stat *buf)
155{
156 int err;
157 char *fname;
Victor Stinner9dd76202017-12-21 16:20:32 +0100158 fname = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner91afbb62015-03-24 12:16:28 +0100159 if (fname == NULL) {
160 errno = EINVAL;
161 return -1;
162 }
163 err = stat(fname, buf);
Victor Stinner9dd76202017-12-21 16:20:32 +0100164 PyMem_RawFree(fname);
Victor Stinner91afbb62015-03-24 12:16:28 +0100165 return err;
166}
167
Victor Stinner0327bde2017-11-23 17:03:20 +0100168
Guido van Rossum305e5d01997-04-11 17:18:45 +0000169static void
Martin v. Löwis790465f2008-04-05 20:41:37 +0000170reduce(wchar_t *dir)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000171{
Martin v. Löwis790465f2008-04-05 20:41:37 +0000172 size_t i = wcslen(dir);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100173 while (i > 0 && dir[i] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000174 --i;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100175 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000176 dir[i] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +0000177}
Guido van Rossumd29806c1998-01-19 22:06:22 +0000178
Victor Stinner0327bde2017-11-23 17:03:20 +0100179
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100180/* Is file, not directory */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000181static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100182isfile(const wchar_t *filename)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000183{
Fred Drakeedabdc12000-07-08 06:16:37 +0000184 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100185 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000186 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100187 }
188 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000189 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100190 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000191 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000192}
193
194
Victor Stinner0327bde2017-11-23 17:03:20 +0100195/* Is executable file */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000196static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100197isxfile(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000198{
Fred Drakeedabdc12000-07-08 06:16:37 +0000199 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100200 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000201 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100202 }
203 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000204 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100205 }
206 if ((buf.st_mode & 0111) == 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000207 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100208 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000209 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000210}
211
212
Victor Stinner0327bde2017-11-23 17:03:20 +0100213/* Is directory */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000214static int
Victor Stinnerf0c85792019-10-04 03:53:26 +0200215isdir(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000216{
Fred Drakeedabdc12000-07-08 06:16:37 +0000217 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100218 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000219 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100220 }
221 if (!S_ISDIR(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000222 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100223 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000224 return 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000225}
226
227
Tim Petersec8c5a92004-08-08 01:00:47 +0000228/* Add a path component, by appending stuff to buffer.
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200229 buflen: 'buffer' length in characters including trailing NUL.
230
231 If path2 is empty:
232
233 - if path doesn't end with SEP and is not empty, add SEP to path
234 - otherwise, do nothing. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200235static PyStatus
Victor Stinnerf0c85792019-10-04 03:53:26 +0200236joinpath(wchar_t *path, const wchar_t *path2, size_t path_len)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000237{
Victor Stinnerf0c85792019-10-04 03:53:26 +0200238 size_t n;
239 if (!_Py_isabs(path2)) {
240 n = wcslen(path);
241 if (n >= path_len) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100242 return PATHLEN_ERR();
243 }
244
Victor Stinnerf0c85792019-10-04 03:53:26 +0200245 if (n > 0 && path[n-1] != SEP) {
246 path[n++] = SEP;
Victor Stinner0327bde2017-11-23 17:03:20 +0100247 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000248 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100249 else {
250 n = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100251 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100252
Victor Stinnerf0c85792019-10-04 03:53:26 +0200253 size_t k = wcslen(path2);
254 if (n + k >= path_len) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100255 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100256 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200257 wcsncpy(path + n, path2, k);
258 path[n + k] = '\0';
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100259
Victor Stinner331a6a52019-05-27 16:39:22 +0200260 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000261}
262
Victor Stinner0327bde2017-11-23 17:03:20 +0100263
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200264static wchar_t*
265substring(const wchar_t *str, size_t len)
266{
267 wchar_t *substr = PyMem_RawMalloc((len + 1) * sizeof(wchar_t));
268 if (substr == NULL) {
269 return NULL;
270 }
271
272 if (len) {
273 memcpy(substr, str, len * sizeof(wchar_t));
274 }
275 substr[len] = L'\0';
276 return substr;
277}
278
279
280static wchar_t*
281joinpath2(const wchar_t *path, const wchar_t *path2)
282{
283 if (_Py_isabs(path2)) {
284 return _PyMem_RawWcsdup(path2);
285 }
286
287 size_t len = wcslen(path);
288 int add_sep = (len > 0 && path[len - 1] != SEP);
289 len += add_sep;
290 len += wcslen(path2);
291
292 wchar_t *new_path = PyMem_RawMalloc((len + 1) * sizeof(wchar_t));
293 if (new_path == NULL) {
294 return NULL;
295 }
296
297 wcscpy(new_path, path);
298 if (add_sep) {
299 wcscat(new_path, separator);
300 }
301 wcscat(new_path, path2);
302 return new_path;
303}
304
305
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100306static inline int
307safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
308{
309 size_t srclen = wcslen(src);
310 if (n <= srclen) {
311 dst[0] = L'\0';
312 return -1;
313 }
314 memcpy(dst, src, (srclen + 1) * sizeof(wchar_t));
315 return 0;
316}
317
318
Guido van Rossume296ced2001-09-28 20:00:29 +0000319/* copy_absolute requires that path be allocated at least
Victor Stinnerf0c85792019-10-04 03:53:26 +0200320 'abs_path_len' characters (including trailing NUL). */
Victor Stinner331a6a52019-05-27 16:39:22 +0200321static PyStatus
Victor Stinnerf0c85792019-10-04 03:53:26 +0200322copy_absolute(wchar_t *abs_path, const wchar_t *path, size_t abs_path_len)
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000323{
Victor Stinnerf0c85792019-10-04 03:53:26 +0200324 if (_Py_isabs(path)) {
325 if (safe_wcscpy(abs_path, path, abs_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100326 return PATHLEN_ERR();
327 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100328 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000329 else {
Victor Stinnerf0c85792019-10-04 03:53:26 +0200330 if (!_Py_wgetcwd(abs_path, abs_path_len)) {
Victor Stinner4f3abb02010-10-07 23:29:18 +0000331 /* unable to get the current directory */
Victor Stinnerf0c85792019-10-04 03:53:26 +0200332 if (safe_wcscpy(abs_path, path, abs_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100333 return PATHLEN_ERR();
334 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200335 return _PyStatus_OK();
Victor Stinner4f3abb02010-10-07 23:29:18 +0000336 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200337 if (path[0] == '.' && path[1] == SEP) {
338 path += 2;
Victor Stinner0327bde2017-11-23 17:03:20 +0100339 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200340 PyStatus status = joinpath(abs_path, path, abs_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200341 if (_PyStatus_EXCEPTION(status)) {
342 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100343 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000344 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200345 return _PyStatus_OK();
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000346}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000347
Victor Stinner0327bde2017-11-23 17:03:20 +0100348
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100349/* path_len: path length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200350static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200351absolutize(wchar_t **path_p)
Guido van Rossume296ced2001-09-28 20:00:29 +0000352{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200353 assert(!_Py_isabs(*path_p));
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100354
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100355 wchar_t abs_path[MAXPATHLEN+1];
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200356 wchar_t *path = *path_p;
357
Victor Stinner331a6a52019-05-27 16:39:22 +0200358 PyStatus status = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path));
359 if (_PyStatus_EXCEPTION(status)) {
360 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100361 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100362
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200363 PyMem_RawFree(*path_p);
364 *path_p = _PyMem_RawWcsdup(abs_path);
365 if (*path_p == NULL) {
366 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100367 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200368 return _PyStatus_OK();
Guido van Rossume296ced2001-09-28 20:00:29 +0000369}
370
Victor Stinner0327bde2017-11-23 17:03:20 +0100371
Victor Stinnerf0c85792019-10-04 03:53:26 +0200372/* Is module -- check for .pyc too */
373static PyStatus
374ismodule(const wchar_t *path, int *result)
375{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200376 wchar_t *filename = joinpath2(path, LANDMARK);
377 if (filename == NULL) {
378 return _PyStatus_NO_MEMORY();
Victor Stinnerf0c85792019-10-04 03:53:26 +0200379 }
380
381 if (isfile(filename)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200382 PyMem_RawFree(filename);
Victor Stinnerf0c85792019-10-04 03:53:26 +0200383 *result = 1;
384 return _PyStatus_OK();
385 }
386
387 /* Check for the compiled version of prefix. */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200388 size_t len = wcslen(filename);
389 wchar_t *pyc = PyMem_RawMalloc((len + 2) * sizeof(wchar_t));
390 if (pyc == NULL) {
391 PyMem_RawFree(filename);
392 return _PyStatus_NO_MEMORY();
Victor Stinnerf0c85792019-10-04 03:53:26 +0200393 }
394
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200395 memcpy(pyc, filename, len * sizeof(wchar_t));
396 pyc[len] = L'c';
397 pyc[len + 1] = L'\0';
398 *result = isfile(pyc);
399
400 PyMem_RawFree(filename);
401 PyMem_RawFree(pyc);
402
Victor Stinnerf0c85792019-10-04 03:53:26 +0200403 return _PyStatus_OK();
404}
405
406
E. M. Bray7a7693e2018-10-05 13:38:50 +0200407#if defined(__CYGWIN__) || defined(__MINGW32__)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200408#ifndef EXE_SUFFIX
409#define EXE_SUFFIX L".exe"
410#endif
411
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100412/* pathlen: 'path' length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200413static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200414add_exe_suffix(wchar_t **progpath_p)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200415{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200416 wchar_t *progpath = *progpath_p;
417
E. M. Bray7a7693e2018-10-05 13:38:50 +0200418 /* Check for already have an executable suffix */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200419 size_t n = wcslen(progpath);
E. M. Bray7a7693e2018-10-05 13:38:50 +0200420 size_t s = wcslen(EXE_SUFFIX);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200421 if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200422 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200423 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100424
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200425 wchar_t *progpath2 = PyMem_RawMalloc((n + s + 1) * sizeof(wchar_t));
426 if (progpath2 == NULL) {
427 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100428 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100429
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200430 memcpy(progpath2, progpath, n * sizeof(wchar_t));
431 memcpy(progpath2 + n, EXE_SUFFIX, s * sizeof(wchar_t));
432 progpath2[n+s] = L'\0';
433
434 if (isxfile(progpath2)) {
435 PyMem_RawFree(*progpath_p);
436 *progpath_p = progpath2;
437 }
438 else {
439 PyMem_RawFree(progpath2);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100440 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200441 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200442}
443#endif
444
445
Guido van Rossume296ced2001-09-28 20:00:29 +0000446/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000447 bytes long.
448*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200449static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200450search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
451 wchar_t *prefix, size_t prefix_len, int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000452{
Victor Stinner331a6a52019-05-27 16:39:22 +0200453 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000454
Fred Drakeedabdc12000-07-08 06:16:37 +0000455 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200456 if (pathconfig->home) {
Victor Stinner221fd842019-09-25 02:54:25 +0200457 /* Path: <home> / <lib_python> */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200458 if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100459 return PATHLEN_ERR();
460 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100461 wchar_t *delim = wcschr(prefix, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100462 if (delim) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000463 *delim = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100464 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200465 status = joinpath(prefix, calculate->lib_python, prefix_len);
466 if (_PyStatus_EXCEPTION(status)) {
467 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100468 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100469 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200470 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000471 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000472
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200473 /* Check to see if argv0_path is in the build directory
474
475 Path: <argv0_path> / <BUILD_LANDMARK define> */
476 wchar_t *path = joinpath2(calculate->argv0_path, BUILD_LANDMARK);
477 if (path == NULL) {
478 return _PyStatus_NO_MEMORY();
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100479 }
480
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200481 int is_build_dir = isfile(path);
482 PyMem_RawFree(path);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100483
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200484 if (is_build_dir) {
485 /* argv0_path is the build directory (BUILD_LANDMARK exists),
486 now also check LANDMARK using ismodule(). */
Victor Stinnerf0c85792019-10-04 03:53:26 +0200487
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200488 /* Path: <argv0_path> / <VPATH macro> / Lib */
489 /* or if VPATH is empty: <argv0_path> / Lib */
490 if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
491 return PATHLEN_ERR();
492 }
493
494 status = joinpath(prefix, calculate->vpath_macro, prefix_len);
495 if (_PyStatus_EXCEPTION(status)) {
496 return status;
497 }
498
499 status = joinpath(prefix, L"Lib", prefix_len);
500 if (_PyStatus_EXCEPTION(status)) {
501 return status;
502 }
503
504 int module;
505 status = ismodule(prefix, &module);
506 if (_PyStatus_EXCEPTION(status)) {
507 return status;
508 }
509 if (module) {
510 /* BUILD_LANDMARK and LANDMARK found */
511 *found = -1;
512 return _PyStatus_OK();
Victor Stinner21582312010-10-23 00:13:28 +0000513 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000514 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000515
Fred Drakeedabdc12000-07-08 06:16:37 +0000516 /* Search from argv0_path, until root is found */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200517 status = copy_absolute(prefix, calculate->argv0_path, prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200518 if (_PyStatus_EXCEPTION(status)) {
519 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100520 }
521
Fred Drakeedabdc12000-07-08 06:16:37 +0000522 do {
Victor Stinner221fd842019-09-25 02:54:25 +0200523 /* Path: <argv0_path or substring> / <lib_python> / LANDMARK */
524 size_t n = wcslen(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200525 status = joinpath(prefix, calculate->lib_python, prefix_len);
526 if (_PyStatus_EXCEPTION(status)) {
527 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100528 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200529
530 int module;
531 status = ismodule(prefix, &module);
Victor Stinner331a6a52019-05-27 16:39:22 +0200532 if (_PyStatus_EXCEPTION(status)) {
533 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100534 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200535 if (module) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100536 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200537 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100538 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100539 prefix[n] = L'\0';
540 reduce(prefix);
541 } while (prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000542
Victor Stinner221fd842019-09-25 02:54:25 +0200543 /* Look at configure's PREFIX.
544 Path: <PREFIX macro> / <lib_python> / LANDMARK */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200545 if (safe_wcscpy(prefix, calculate->prefix_macro, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100546 return PATHLEN_ERR();
547 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200548 status = joinpath(prefix, calculate->lib_python, prefix_len);
549 if (_PyStatus_EXCEPTION(status)) {
550 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100551 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200552
553 int module;
554 status = ismodule(prefix, &module);
Victor Stinner331a6a52019-05-27 16:39:22 +0200555 if (_PyStatus_EXCEPTION(status)) {
556 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100557 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200558 if (module) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100559 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200560 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100561 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000562
Fred Drakeedabdc12000-07-08 06:16:37 +0000563 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100564 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200565 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000566}
567
568
Victor Stinner331a6a52019-05-27 16:39:22 +0200569static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200570calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100571{
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200572 wchar_t prefix[MAXPATHLEN+1];
573 memset(prefix, 0, sizeof(prefix));
574 size_t prefix_len = Py_ARRAY_LENGTH(prefix);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100575
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200576 PyStatus status;
577 status = search_for_prefix(calculate, pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200578 prefix, prefix_len,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200579 &calculate->prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200580 if (_PyStatus_EXCEPTION(status)) {
581 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100582 }
583
Victor Stinner0327bde2017-11-23 17:03:20 +0100584 if (!calculate->prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200585 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100586 fprintf(stderr,
587 "Could not find platform independent libraries <prefix>\n");
588 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200589
590 calculate->prefix = joinpath2(calculate->prefix_macro,
591 calculate->lib_python);
592 }
593 else {
594 calculate->prefix = _PyMem_RawWcsdup(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100595 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200596
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200597 if (calculate->prefix == NULL) {
598 return _PyStatus_NO_MEMORY();
599 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200600 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100601}
602
603
Victor Stinner331a6a52019-05-27 16:39:22 +0200604static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200605calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100606{
607 /* Reduce prefix and exec_prefix to their essence,
608 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
609 * If we're loading relative to the build directory,
610 * return the compiled-in defaults instead.
611 */
612 if (calculate->prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200613 wchar_t *prefix = _PyMem_RawWcsdup(calculate->prefix);
614 if (prefix == NULL) {
615 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100616 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200617
618 reduce(prefix);
619 reduce(prefix);
620 if (prefix[0]) {
621 pathconfig->prefix = prefix;
622 }
623 else {
624 PyMem_RawFree(prefix);
625
626 /* The prefix is the root directory, but reduce() chopped
627 off the "/". */
628 pathconfig->prefix = _PyMem_RawWcsdup(separator);
629 if (pathconfig->prefix == NULL) {
630 return _PyStatus_NO_MEMORY();
631 }
632 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100633 }
634 else {
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200635 pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200636 if (pathconfig->prefix == NULL) {
637 return _PyStatus_NO_MEMORY();
638 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100639 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200640 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100641}
642
643
Victor Stinner221fd842019-09-25 02:54:25 +0200644static PyStatus
645calculate_pybuilddir(const wchar_t *argv0_path,
646 wchar_t *exec_prefix, size_t exec_prefix_len,
647 int *found)
648{
649 PyStatus status;
650
Victor Stinner221fd842019-09-25 02:54:25 +0200651 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
652 is written by setup.py and contains the relative path to the location
653 of shared library modules.
654
655 Filename: <argv0_path> / "pybuilddir.txt" */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200656 wchar_t *filename = joinpath2(argv0_path, L"pybuilddir.txt");
657 if (filename == NULL) {
658 return _PyStatus_NO_MEMORY();
Victor Stinner221fd842019-09-25 02:54:25 +0200659 }
660
Victor Stinner221fd842019-09-25 02:54:25 +0200661 FILE *fp = _Py_wfopen(filename, L"rb");
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200662 PyMem_RawFree(filename);
Victor Stinner221fd842019-09-25 02:54:25 +0200663 if (fp == NULL) {
664 errno = 0;
665 return _PyStatus_OK();
666 }
667
668 char buf[MAXPATHLEN + 1];
669 size_t n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, fp);
670 buf[n] = '\0';
671 fclose(fp);
672
673 size_t dec_len;
674 wchar_t *pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
675 if (!pybuilddir) {
676 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
677 }
678
679 /* Path: <argv0_path> / <pybuilddir content> */
680 if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) {
681 PyMem_RawFree(pybuilddir);
682 return PATHLEN_ERR();
683 }
684 status = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
685 PyMem_RawFree(pybuilddir);
686 if (_PyStatus_EXCEPTION(status)) {
687 return status;
688 }
689
690 *found = -1;
691 return _PyStatus_OK();
692}
693
694
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000695/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000696 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000697*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200698static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200699search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100700 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100701 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000702{
Victor Stinner331a6a52019-05-27 16:39:22 +0200703 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000704
Fred Drakeedabdc12000-07-08 06:16:37 +0000705 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200706 if (pathconfig->home) {
Victor Stinner221fd842019-09-25 02:54:25 +0200707 /* Path: <home> / <lib_python> / "lib-dynload" */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200708 wchar_t *delim = wcschr(pathconfig->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100709 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100710 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
711 return PATHLEN_ERR();
712 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100713 }
714 else {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200715 if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100716 return PATHLEN_ERR();
717 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100718 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200719 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
720 if (_PyStatus_EXCEPTION(status)) {
721 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100722 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200723 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
724 if (_PyStatus_EXCEPTION(status)) {
725 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100726 }
727 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200728 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000729 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000730
Victor Stinner221fd842019-09-25 02:54:25 +0200731 /* Check for pybuilddir.txt */
732 assert(*found == 0);
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200733 status = calculate_pybuilddir(calculate->argv0_path,
734 exec_prefix, exec_prefix_len, found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200735 if (_PyStatus_EXCEPTION(status)) {
736 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100737 }
Victor Stinner221fd842019-09-25 02:54:25 +0200738 if (*found) {
739 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000740 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000741
Fred Drakeedabdc12000-07-08 06:16:37 +0000742 /* Search from argv0_path, until root is found */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200743 status = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200744 if (_PyStatus_EXCEPTION(status)) {
745 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100746 }
747
Fred Drakeedabdc12000-07-08 06:16:37 +0000748 do {
Victor Stinner221fd842019-09-25 02:54:25 +0200749 /* Path: <argv0_path or substring> / <lib_python> / "lib-dynload" */
750 size_t n = wcslen(exec_prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200751 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
752 if (_PyStatus_EXCEPTION(status)) {
753 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100754 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200755 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
756 if (_PyStatus_EXCEPTION(status)) {
757 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100758 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100759 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100760 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200761 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100762 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100763 exec_prefix[n] = L'\0';
764 reduce(exec_prefix);
765 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000766
Victor Stinner221fd842019-09-25 02:54:25 +0200767 /* Look at configure's EXEC_PREFIX.
768
769 Path: <EXEC_PREFIX macro> / <lib_python> / "lib-dynload" */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200770 if (safe_wcscpy(exec_prefix, calculate->exec_prefix_macro, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100771 return PATHLEN_ERR();
772 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200773 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
774 if (_PyStatus_EXCEPTION(status)) {
775 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100776 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200777 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
778 if (_PyStatus_EXCEPTION(status)) {
779 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100780 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100781 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100782 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200783 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100784 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000785
Fred Drakeedabdc12000-07-08 06:16:37 +0000786 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100787 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200788 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000789}
790
Guido van Rossum305e5d01997-04-11 17:18:45 +0000791
Victor Stinner331a6a52019-05-27 16:39:22 +0200792static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200793calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100794{
Victor Stinner331a6a52019-05-27 16:39:22 +0200795 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200796 wchar_t exec_prefix[MAXPATHLEN+1];
797 memset(exec_prefix, 0, sizeof(exec_prefix));
798 size_t exec_prefix_len = Py_ARRAY_LENGTH(exec_prefix);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100799
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200800 status = search_for_exec_prefix(calculate, pathconfig,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200801 exec_prefix, exec_prefix_len,
802 &calculate->exec_prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200803 if (_PyStatus_EXCEPTION(status)) {
804 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100805 }
806
Victor Stinner0327bde2017-11-23 17:03:20 +0100807 if (!calculate->exec_prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200808 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100809 fprintf(stderr,
810 "Could not find platform dependent libraries <exec_prefix>\n");
811 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200812
Victor Stinnerd72b9642020-06-11 17:28:52 +0200813 /* <platlibdir> / "lib-dynload" */
Sandro Mani8f023a22020-06-08 17:28:11 +0200814 wchar_t *lib_dynload = joinpath2(calculate->platlibdir,
Victor Stinner8510f432020-03-10 09:53:09 +0100815 L"lib-dynload");
816 if (lib_dynload == NULL) {
817 return _PyStatus_NO_MEMORY();
818 }
819
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200820 calculate->exec_prefix = joinpath2(calculate->exec_prefix_macro,
Victor Stinner8510f432020-03-10 09:53:09 +0100821 lib_dynload);
822 PyMem_RawFree(lib_dynload);
823
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200824 if (calculate->exec_prefix == NULL) {
825 return _PyStatus_NO_MEMORY();
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100826 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100827 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200828 else {
829 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
830 calculate->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
831 if (calculate->exec_prefix == NULL) {
832 return _PyStatus_NO_MEMORY();
833 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200834 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200835 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100836}
837
838
Victor Stinner331a6a52019-05-27 16:39:22 +0200839static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200840calculate_set_exec_prefix(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200841 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100842{
843 if (calculate->exec_prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200844 wchar_t *exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix);
845 if (exec_prefix == NULL) {
846 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100847 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200848
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200849 reduce(exec_prefix);
850 reduce(exec_prefix);
851 reduce(exec_prefix);
852
853 if (exec_prefix[0]) {
854 pathconfig->exec_prefix = exec_prefix;
855 }
856 else {
857 /* empty string: use SEP instead */
858 PyMem_RawFree(exec_prefix);
859
860 /* The exec_prefix is the root directory, but reduce() chopped
861 off the "/". */
862 pathconfig->exec_prefix = _PyMem_RawWcsdup(separator);
863 if (pathconfig->exec_prefix == NULL) {
864 return _PyStatus_NO_MEMORY();
865 }
866 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100867 }
868 else {
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200869 pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200870 if (pathconfig->exec_prefix == NULL) {
871 return _PyStatus_NO_MEMORY();
872 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100873 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200874 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100875}
876
877
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200878/* Similar to shutil.which().
879 If found, write the path into *abs_path_p. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200880static PyStatus
Victor Stinner03a8a562019-10-04 02:22:39 +0200881calculate_which(const wchar_t *path_env, wchar_t *program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200882 wchar_t **abs_path_p)
Victor Stinner0327bde2017-11-23 17:03:20 +0100883{
Victor Stinner03a8a562019-10-04 02:22:39 +0200884 while (1) {
885 wchar_t *delim = wcschr(path_env, DELIM);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200886 wchar_t *abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200887
888 if (delim) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200889 wchar_t *path = substring(path_env, delim - path_env);
890 if (path == NULL) {
891 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +0200892 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200893 abs_path = joinpath2(path, program_name);
894 PyMem_RawFree(path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200895 }
896 else {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200897 abs_path = joinpath2(path_env, program_name);
Victor Stinner03a8a562019-10-04 02:22:39 +0200898 }
899
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200900 if (abs_path == NULL) {
901 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +0200902 }
903
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200904 if (isxfile(abs_path)) {
905 *abs_path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200906 return _PyStatus_OK();
907 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200908 PyMem_RawFree(abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200909
910 if (!delim) {
911 break;
912 }
913 path_env = delim + 1;
914 }
915
916 /* not found */
917 return _PyStatus_OK();
918}
919
Victor Stinner9316ee42017-11-25 03:17:57 +0100920
Victor Stinnerb9197952017-11-23 19:02:04 +0100921#ifdef __APPLE__
Victor Stinner03a8a562019-10-04 02:22:39 +0200922static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200923calculate_program_macos(wchar_t **abs_path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +0200924{
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100925 char execpath[MAXPATHLEN + 1];
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100926 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinner03a8a562019-10-04 02:22:39 +0200927
928 /* On Mac OS X, if a script uses an interpreter of the form
929 "#!/opt/python2.3/bin/python", the kernel only passes "python"
930 as argv[0], which falls through to the $PATH search below.
931 If /opt/python2.3/bin isn't in your path, or is near the end,
932 this algorithm may incorrectly find /usr/bin/python. To work
933 around this, we can use _NSGetExecutablePath to get a better
934 hint of what the intended interpreter was, although this
935 will fail if a relative path was used. but in that case,
936 absolutize() should help us out below
937 */
938 if (_NSGetExecutablePath(execpath, &nsexeclength) != 0
939 || (wchar_t)execpath[0] != SEP)
940 {
941 /* _NSGetExecutablePath() failed or the path is relative */
942 return _PyStatus_OK();
943 }
944
945 size_t len;
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200946 *abs_path_p = Py_DecodeLocale(execpath, &len);
947 if (*abs_path_p == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +0200948 return DECODE_LOCALE_ERR("executable path", len);
949 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200950 return _PyStatus_OK();
951}
952#endif /* __APPLE__ */
953
954
955static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200956calculate_program_impl(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +0200957{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200958 assert(pathconfig->program_full_path == NULL);
959
Victor Stinner03a8a562019-10-04 02:22:39 +0200960 PyStatus status;
Victor Stinnerb9197952017-11-23 19:02:04 +0100961
Victor Stinner0327bde2017-11-23 17:03:20 +0100962 /* If there is no slash in the argv0 path, then we have to
963 * assume python is on the user's $PATH, since there's no
964 * other way to find a directory to start the search from. If
965 * $PATH isn't exported, you lose.
966 */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200967 if (wcschr(pathconfig->program_name, SEP)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200968 pathconfig->program_full_path = _PyMem_RawWcsdup(pathconfig->program_name);
969 if (pathconfig->program_full_path == NULL) {
970 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100971 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200972 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100973 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200974
Jack Jansen1afd4802004-06-03 14:33:03 +0000975#ifdef __APPLE__
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200976 wchar_t *abs_path = NULL;
977 status = calculate_program_macos(&abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200978 if (_PyStatus_EXCEPTION(status)) {
979 return status;
980 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200981 if (abs_path) {
982 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200983 return _PyStatus_OK();
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000984 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000985#endif /* __APPLE__ */
Jack Jansen55070f52001-12-02 23:56:28 +0000986
Victor Stinner03a8a562019-10-04 02:22:39 +0200987 if (calculate->path_env) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200988 wchar_t *abs_path = NULL;
Victor Stinner03a8a562019-10-04 02:22:39 +0200989 status = calculate_which(calculate->path_env, pathconfig->program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200990 &abs_path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200991 if (_PyStatus_EXCEPTION(status)) {
992 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100993 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200994 if (abs_path) {
995 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200996 return _PyStatus_OK();
997 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100998 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200999
1000 /* In the last resort, use an empty string */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001001 pathconfig->program_full_path = _PyMem_RawWcsdup(L"");
1002 if (pathconfig->program_full_path == NULL) {
1003 return _PyStatus_NO_MEMORY();
1004 }
Victor Stinner03a8a562019-10-04 02:22:39 +02001005 return _PyStatus_OK();
1006}
1007
1008
1009/* Calculate pathconfig->program_full_path */
1010static PyStatus
1011calculate_program(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
1012{
1013 PyStatus status;
Victor Stinner03a8a562019-10-04 02:22:39 +02001014
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001015 status = calculate_program_impl(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001016 if (_PyStatus_EXCEPTION(status)) {
1017 return status;
1018 }
1019
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001020 if (pathconfig->program_full_path[0] != '\0') {
Victor Stinner03a8a562019-10-04 02:22:39 +02001021 /* program_full_path is not empty */
1022
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001023 /* Make sure that program_full_path is an absolute path */
1024 if (!_Py_isabs(pathconfig->program_full_path)) {
1025 status = absolutize(&pathconfig->program_full_path);
Victor Stinner03a8a562019-10-04 02:22:39 +02001026 if (_PyStatus_EXCEPTION(status)) {
1027 return status;
1028 }
1029 }
1030
1031#if defined(__CYGWIN__) || defined(__MINGW32__)
1032 /* For these platforms it is necessary to ensure that the .exe suffix
1033 * is appended to the filename, otherwise there is potential for
1034 * sys.executable to return the name of a directory under the same
1035 * path (bpo-28441).
1036 */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001037 status = add_exe_suffix(&pathconfig->program_full_path);
Victor Stinner331a6a52019-05-27 16:39:22 +02001038 if (_PyStatus_EXCEPTION(status)) {
1039 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001040 }
E. M. Bray7a7693e2018-10-05 13:38:50 +02001041#endif
Victor Stinner03a8a562019-10-04 02:22:39 +02001042 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001043 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001044}
1045
1046
Victor Stinner03a8a562019-10-04 02:22:39 +02001047#if HAVE_READLINK
Victor Stinner331a6a52019-05-27 16:39:22 +02001048static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001049resolve_symlinks(wchar_t **path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +02001050{
1051 wchar_t new_path[MAXPATHLEN + 1];
1052 const size_t new_path_len = Py_ARRAY_LENGTH(new_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001053 unsigned int nlink = 0;
Victor Stinner03a8a562019-10-04 02:22:39 +02001054
1055 while (1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001056 int linklen = _Py_wreadlink(*path_p, new_path, new_path_len);
Victor Stinner03a8a562019-10-04 02:22:39 +02001057 if (linklen == -1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001058 /* not a symbolic link: we are done */
Victor Stinner03a8a562019-10-04 02:22:39 +02001059 break;
1060 }
1061
1062 if (_Py_isabs(new_path)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001063 PyMem_RawFree(*path_p);
1064 *path_p = _PyMem_RawWcsdup(new_path);
1065 if (*path_p == NULL) {
1066 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001067 }
1068 }
1069 else {
1070 /* new_path is relative to path */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001071 reduce(*path_p);
1072
1073 wchar_t *abs_path = joinpath2(*path_p, new_path);
1074 if (abs_path == NULL) {
1075 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001076 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001077
1078 PyMem_RawFree(*path_p);
1079 *path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +02001080 }
1081
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001082 nlink++;
Victor Stinner03a8a562019-10-04 02:22:39 +02001083 /* 40 is the Linux kernel 4.2 limit */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001084 if (nlink >= 40) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001085 return _PyStatus_ERR("maximum number of symbolic links reached");
1086 }
1087 }
1088 return _PyStatus_OK();
1089}
1090#endif /* HAVE_READLINK */
1091
1092
1093#ifdef WITH_NEXT_FRAMEWORK
1094static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001095calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +02001096{
1097 NSModule pythonModule;
1098
1099 /* On Mac OS X we have a special case if we're running from a framework.
1100 This is because the python home should be set relative to the library,
1101 which is in the framework, not relative to the executable, which may
1102 be outside of the framework. Except when we're in the build
1103 directory... */
1104 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
1105
1106 /* Use dylib functions to find out where the framework was loaded from */
1107 const char* modPath = NSLibraryNameForModule(pythonModule);
1108 if (modPath == NULL) {
1109 return _PyStatus_OK();
1110 }
1111
1112 /* We're in a framework.
1113 See if we might be in the build directory. The framework in the
1114 build directory is incomplete, it only has the .dylib and a few
1115 needed symlinks, it doesn't have the Lib directories and such.
1116 If we're running with the framework from the build directory we must
1117 be running the interpreter in the build directory, so we use the
1118 build-directory-specific logic to find Lib and such. */
1119 size_t len;
1120 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
1121 if (wbuf == NULL) {
1122 return DECODE_LOCALE_ERR("framework location", len);
1123 }
1124
1125 /* Path: reduce(modPath) / lib_python / LANDMARK */
1126 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001127
1128 wchar_t *parent = _PyMem_RawWcsdup(wbuf);
1129 if (parent == NULL) {
1130 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001131 goto done;
1132 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001133
1134 reduce(parent);
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001135 wchar_t *lib_python = joinpath2(parent, calculate->lib_python);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001136 PyMem_RawFree(parent);
1137
1138 if (lib_python == NULL) {
1139 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001140 goto done;
1141 }
Victor Stinnerf0c85792019-10-04 03:53:26 +02001142
1143 int module;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001144 status = ismodule(lib_python, &module);
1145 PyMem_RawFree(lib_python);
1146
Victor Stinner03a8a562019-10-04 02:22:39 +02001147 if (_PyStatus_EXCEPTION(status)) {
1148 goto done;
1149 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001150 if (!module) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001151 /* We are in the build directory so use the name of the
1152 executable - we know that the absolute path is passed */
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001153 PyMem_RawFree(calculate->argv0_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001154 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1155 if (calculate->argv0_path == NULL) {
1156 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001157 goto done;
1158 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001159
1160 status = _PyStatus_OK();
1161 goto done;
Victor Stinner03a8a562019-10-04 02:22:39 +02001162 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001163
1164 /* Use the location of the library as argv0_path */
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001165 PyMem_RawFree(calculate->argv0_path);
1166 calculate->argv0_path = wbuf;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001167 return _PyStatus_OK();
Victor Stinner03a8a562019-10-04 02:22:39 +02001168
1169done:
1170 PyMem_RawFree(wbuf);
1171 return status;
1172}
1173#endif
1174
1175
1176static PyStatus
1177calculate_argv0_path(PyCalculatePath *calculate,
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001178 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001179{
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001180 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001181
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001182 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1183 if (calculate->argv0_path == NULL) {
1184 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001185 }
Jack Jansen55070f52001-12-02 23:56:28 +00001186
Guido van Rossum54ecc3d1999-01-27 17:53:11 +00001187#ifdef WITH_NEXT_FRAMEWORK
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001188 status = calculate_argv0_path_framework(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001189 if (_PyStatus_EXCEPTION(status)) {
1190 return status;
Fred Drakeedabdc12000-07-08 06:16:37 +00001191 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +00001192#endif
Guido van Rossume296ced2001-09-28 20:00:29 +00001193
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001194 status = resolve_symlinks(&calculate->argv0_path);
1195 if (_PyStatus_EXCEPTION(status)) {
1196 return status;
1197 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001198
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001199 reduce(calculate->argv0_path);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001200
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001201 return _PyStatus_OK();
1202}
1203
1204
1205static PyStatus
1206calculate_open_pyenv(PyCalculatePath *calculate, FILE **env_file_p)
1207{
1208 *env_file_p = NULL;
1209
1210 const wchar_t *env_cfg = L"pyvenv.cfg";
1211
1212 /* Filename: <argv0_path> / "pyvenv.cfg" */
1213 wchar_t *filename = joinpath2(calculate->argv0_path, env_cfg);
1214 if (filename == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001215 return _PyStatus_NO_MEMORY();
1216 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001217
1218 *env_file_p = _Py_wfopen(filename, L"r");
1219 PyMem_RawFree(filename);
1220
1221 if (*env_file_p != NULL) {
1222 return _PyStatus_OK();
1223
1224 }
1225
1226 /* fopen() failed: reset errno */
1227 errno = 0;
1228
1229 /* Path: <basename(argv0_path)> / "pyvenv.cfg" */
1230 wchar_t *parent = _PyMem_RawWcsdup(calculate->argv0_path);
1231 if (parent == NULL) {
1232 return _PyStatus_NO_MEMORY();
1233 }
1234 reduce(parent);
1235
1236 filename = joinpath2(parent, env_cfg);
1237 PyMem_RawFree(parent);
1238 if (filename == NULL) {
1239 return _PyStatus_NO_MEMORY();
1240 }
1241
1242 *env_file_p = _Py_wfopen(filename, L"r");
1243 PyMem_RawFree(filename);
1244
1245 if (*env_file_p == NULL) {
1246 /* fopen() failed: reset errno */
1247 errno = 0;
1248 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001249 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001250}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001251
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001252
Victor Stinner0327bde2017-11-23 17:03:20 +01001253/* Search for an "pyvenv.cfg" environment configuration file, first in the
1254 executable's directory and then in the parent directory.
1255 If found, open it for use when searching for prefixes.
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001256
1257 Write the 'home' variable of pyvenv.cfg into calculate->argv0_path. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001258static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001259calculate_read_pyenv(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001260{
Victor Stinner331a6a52019-05-27 16:39:22 +02001261 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001262 FILE *env_file = NULL;
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001263
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001264 status = calculate_open_pyenv(calculate, &env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001265 if (_PyStatus_EXCEPTION(status)) {
Miss Islington (bot)0e9af8c2021-06-02 16:50:38 -07001266 assert(env_file == NULL);
Victor Stinner331a6a52019-05-27 16:39:22 +02001267 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 Stinner221fd842019-09-25 02:54:25 +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 Stinnerd72b9642020-06-11 17:28:52 +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 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001303
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 Stinnerd72b9642020-06-11 17:28:52 +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 Stinnerbb6bf7d2019-09-24 18:21:02 +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 Stinner7b14f0c2019-03-18 23:54:59 +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 Stinnerabd7cd82019-10-04 15:25:50 +02001325 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001326
Victor Stinner8510f432020-03-10 09:53:09 +01001327 res = _PyStatus_OK();
1328
1329done:
1330 PyMem_RawFree(path);
1331 return res;
Victor Stinner0327bde2017-11-23 17:03:20 +01001332}
1333
1334
Victor Stinner331a6a52019-05-27 16:39:22 +02001335static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001336calculate_module_search_path(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001337 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001338{
1339 /* Calculate size of return buffer */
1340 size_t bufsz = 0;
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001341 if (calculate->pythonpath_env != NULL) {
1342 bufsz += wcslen(calculate->pythonpath_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001343 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001344
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001345 wchar_t *defpath = calculate->pythonpath_macro;
1346 size_t prefixsz = wcslen(calculate->prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001347 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001348 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001349
Victor Stinner3939c322019-06-25 15:02:43 +02001350 if (!_Py_isabs(defpath)) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001351 /* Paths are relative to prefix */
1352 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001353 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001354
Victor Stinner0327bde2017-11-23 17:03:20 +01001355 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001356 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001357 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001358 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001359 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001360 break;
1361 }
1362 defpath = delim + 1;
1363 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001364
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001365 bufsz += wcslen(calculate->zip_path) + 1;
1366 bufsz += wcslen(calculate->exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001367
Victor Stinner0327bde2017-11-23 17:03:20 +01001368 /* Allocate the buffer */
1369 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001370 if (buf == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +02001371 return _PyStatus_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001372 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001373 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001374
Victor Stinner72967a42013-11-16 01:22:04 +01001375 /* Run-time value of $PYTHONPATH goes first */
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001376 if (calculate->pythonpath_env) {
1377 wcscpy(buf, calculate->pythonpath_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001378 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001379 }
Victor Stinner72967a42013-11-16 01:22:04 +01001380
1381 /* Next is the default zip path */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001382 wcscat(buf, calculate->zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001383 wcscat(buf, delimiter);
1384
1385 /* Next goes merge of compile-time $PYTHONPATH with
1386 * dynamically located prefix.
1387 */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001388 defpath = calculate->pythonpath_macro;
Victor Stinner72967a42013-11-16 01:22:04 +01001389 while (1) {
1390 wchar_t *delim = wcschr(defpath, DELIM);
1391
Victor Stinner3939c322019-06-25 15:02:43 +02001392 if (!_Py_isabs(defpath)) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001393 wcscat(buf, calculate->prefix);
1394 if (prefixsz >= 2 && calculate->prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001395 defpath[0] != (delim ? DELIM : L'\0'))
1396 {
1397 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001398 wcscat(buf, separator);
1399 }
Victor Stinner72967a42013-11-16 01:22:04 +01001400 }
1401
1402 if (delim) {
1403 size_t len = delim - defpath + 1;
1404 size_t end = wcslen(buf) + len;
1405 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001406 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001407 }
1408 else {
1409 wcscat(buf, defpath);
1410 break;
1411 }
1412 defpath = delim + 1;
1413 }
1414 wcscat(buf, delimiter);
1415
1416 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001417 wcscat(buf, calculate->exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001418
Victor Stinner331a6a52019-05-27 16:39:22 +02001419 pathconfig->module_search_path = buf;
1420 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001421}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001422
Victor Stinner0327bde2017-11-23 17:03:20 +01001423
Victor Stinner331a6a52019-05-27 16:39:22 +02001424static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +02001425calculate_init(PyCalculatePath *calculate, const PyConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001426{
Victor Stinner0327bde2017-11-23 17:03:20 +01001427 size_t len;
Victor Stinnerd72b9642020-06-11 17:28:52 +02001428
1429 calculate->warnings = config->pathconfig_warnings;
1430 calculate->pythonpath_env = config->pythonpath_env;
1431 calculate->platlibdir = config->platlibdir;
1432
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001433 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001434 if (path) {
1435 calculate->path_env = Py_DecodeLocale(path, &len);
1436 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001437 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001438 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001439 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001440
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001441 /* Decode macros */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001442 calculate->pythonpath_macro = Py_DecodeLocale(PYTHONPATH, &len);
1443 if (!calculate->pythonpath_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001444 return DECODE_LOCALE_ERR("PYTHONPATH macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001445 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001446 calculate->prefix_macro = Py_DecodeLocale(PREFIX, &len);
1447 if (!calculate->prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001448 return DECODE_LOCALE_ERR("PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001449 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001450 calculate->exec_prefix_macro = Py_DecodeLocale(EXEC_PREFIX, &len);
1451 if (!calculate->exec_prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001452 return DECODE_LOCALE_ERR("EXEC_PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001453 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001454 calculate->vpath_macro = Py_DecodeLocale(VPATH, &len);
1455 if (!calculate->vpath_macro) {
1456 return DECODE_LOCALE_ERR("VPATH macro", len);
1457 }
1458
Victor Stinnerd72b9642020-06-11 17:28:52 +02001459 // <platlibdir> / "pythonX.Y"
1460 wchar_t *pyversion = Py_DecodeLocale("python" VERSION, &len);
1461 if (!pyversion) {
Victor Stinner8510f432020-03-10 09:53:09 +01001462 return DECODE_LOCALE_ERR("VERSION macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001463 }
Victor Stinnerd72b9642020-06-11 17:28:52 +02001464 calculate->lib_python = joinpath2(config->platlibdir, pyversion);
1465 PyMem_RawFree(pyversion);
1466 if (calculate->lib_python == NULL) {
1467 return _PyStatus_NO_MEMORY();
1468 }
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001469
Victor Stinner331a6a52019-05-27 16:39:22 +02001470 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001471}
1472
1473
1474static void
1475calculate_free(PyCalculatePath *calculate)
1476{
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001477 PyMem_RawFree(calculate->pythonpath_macro);
1478 PyMem_RawFree(calculate->prefix_macro);
1479 PyMem_RawFree(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001480 PyMem_RawFree(calculate->vpath_macro);
Victor Stinner0327bde2017-11-23 17:03:20 +01001481 PyMem_RawFree(calculate->lib_python);
1482 PyMem_RawFree(calculate->path_env);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001483 PyMem_RawFree(calculate->zip_path);
1484 PyMem_RawFree(calculate->argv0_path);
1485 PyMem_RawFree(calculate->prefix);
1486 PyMem_RawFree(calculate->exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +01001487}
1488
1489
Victor Stinner331a6a52019-05-27 16:39:22 +02001490static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001491calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001492{
Victor Stinner331a6a52019-05-27 16:39:22 +02001493 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +01001494
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001495 if (pathconfig->program_full_path == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001496 status = calculate_program(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001497 if (_PyStatus_EXCEPTION(status)) {
1498 return status;
1499 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001500 }
1501
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001502 status = calculate_argv0_path(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001503 if (_PyStatus_EXCEPTION(status)) {
1504 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001505 }
1506
Victor Stinner221fd842019-09-25 02:54:25 +02001507 /* If a pyvenv.cfg configure file is found,
Miss Islington (bot)5afc5bb2021-10-07 01:55:18 -07001508 argv0_path is overridden with its 'home' variable. */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001509 status = calculate_read_pyenv(calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001510 if (_PyStatus_EXCEPTION(status)) {
1511 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001512 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001513
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001514 status = calculate_prefix(calculate, pathconfig);
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_zip_path(calculate);
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_exec_prefix(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001525 if (_PyStatus_EXCEPTION(status)) {
1526 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001527 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001528
Victor Stinner03a8a562019-10-04 02:22:39 +02001529 if ((!calculate->prefix_found || !calculate->exec_prefix_found)
1530 && calculate->warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001531 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001532 fprintf(stderr,
1533 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1534 }
1535
Victor Stinnere2677932019-09-21 01:50:16 +02001536 if (pathconfig->module_search_path == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001537 status = calculate_module_search_path(calculate, pathconfig);
Victor Stinnere2677932019-09-21 01:50:16 +02001538 if (_PyStatus_EXCEPTION(status)) {
1539 return status;
1540 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001541 }
1542
Victor Stinner331a6a52019-05-27 16:39:22 +02001543 if (pathconfig->prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001544 status = calculate_set_prefix(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001545 if (_PyStatus_EXCEPTION(status)) {
1546 return status;
1547 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001548 }
1549
Victor Stinner331a6a52019-05-27 16:39:22 +02001550 if (pathconfig->exec_prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001551 status = calculate_set_exec_prefix(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001552 if (_PyStatus_EXCEPTION(status)) {
1553 return status;
1554 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001555 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001556 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001557}
1558
1559
Victor Stinner85ce0a72019-09-24 00:55:48 +02001560/* Calculate the Python path configuration.
1561
1562 Inputs:
1563
1564 - PATH environment variable
1565 - Macros: PYTHONPATH, PREFIX, EXEC_PREFIX, VERSION (ex: "3.9").
1566 PREFIX and EXEC_PREFIX are generated by the configure script.
1567 PYTHONPATH macro is the default search path.
1568 - pybuilddir.txt file
1569 - pyvenv.cfg configuration file
1570 - PyConfig fields ('config' function argument):
1571
1572 - pathconfig_warnings
1573 - pythonpath_env (PYTHONPATH environment variable)
1574
1575 - _PyPathConfig fields ('pathconfig' function argument):
1576
1577 - program_name: see config_init_program_name()
1578 - home: Py_SetPythonHome() or PYTHONHOME environment variable
1579
1580 - current working directory: see copy_absolute()
1581
1582 Outputs, 'pathconfig' fields:
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001583
1584 - program_full_path
1585 - module_search_path
1586 - prefix
1587 - exec_prefix
1588
Victor Stinner85ce0a72019-09-24 00:55:48 +02001589 If a field is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001590PyStatus
1591_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001592{
Victor Stinner331a6a52019-05-27 16:39:22 +02001593 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001594 PyCalculatePath calculate;
1595 memset(&calculate, 0, sizeof(calculate));
1596
Victor Stinner331a6a52019-05-27 16:39:22 +02001597 status = calculate_init(&calculate, config);
1598 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001599 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001600 }
1601
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001602 status = calculate_path(&calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001603 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001604 goto done;
1605 }
1606
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001607 /* program_full_path must an either an empty string or an absolute path */
1608 assert(wcslen(pathconfig->program_full_path) == 0
1609 || _Py_isabs(pathconfig->program_full_path));
1610
Victor Stinner331a6a52019-05-27 16:39:22 +02001611 status = _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001612
Victor Stinner9316ee42017-11-25 03:17:57 +01001613done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001614 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001615 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001616}
Victor Stinner46972b72017-11-24 22:55:40 +01001617
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001618#ifdef __cplusplus
1619}
1620#endif