blob: f7a6dd40443054b9ceb6991de5a4214c5912662d [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 Stinnerb9197952017-11-23 19:02:04 +0100926#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100927 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100928#else
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100929 unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100930#endif
Victor Stinner03a8a562019-10-04 02:22:39 +0200931
932 /* On Mac OS X, if a script uses an interpreter of the form
933 "#!/opt/python2.3/bin/python", the kernel only passes "python"
934 as argv[0], which falls through to the $PATH search below.
935 If /opt/python2.3/bin isn't in your path, or is near the end,
936 this algorithm may incorrectly find /usr/bin/python. To work
937 around this, we can use _NSGetExecutablePath to get a better
938 hint of what the intended interpreter was, although this
939 will fail if a relative path was used. but in that case,
940 absolutize() should help us out below
941 */
942 if (_NSGetExecutablePath(execpath, &nsexeclength) != 0
943 || (wchar_t)execpath[0] != SEP)
944 {
945 /* _NSGetExecutablePath() failed or the path is relative */
946 return _PyStatus_OK();
947 }
948
949 size_t len;
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200950 *abs_path_p = Py_DecodeLocale(execpath, &len);
951 if (*abs_path_p == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +0200952 return DECODE_LOCALE_ERR("executable path", len);
953 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200954 return _PyStatus_OK();
955}
956#endif /* __APPLE__ */
957
958
959static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200960calculate_program_impl(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +0200961{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200962 assert(pathconfig->program_full_path == NULL);
963
Victor Stinner03a8a562019-10-04 02:22:39 +0200964 PyStatus status;
Victor Stinnerb9197952017-11-23 19:02:04 +0100965
Victor Stinner0327bde2017-11-23 17:03:20 +0100966 /* If there is no slash in the argv0 path, then we have to
967 * assume python is on the user's $PATH, since there's no
968 * other way to find a directory to start the search from. If
969 * $PATH isn't exported, you lose.
970 */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200971 if (wcschr(pathconfig->program_name, SEP)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200972 pathconfig->program_full_path = _PyMem_RawWcsdup(pathconfig->program_name);
973 if (pathconfig->program_full_path == NULL) {
974 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100975 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200976 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100977 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200978
Jack Jansen1afd4802004-06-03 14:33:03 +0000979#ifdef __APPLE__
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200980 wchar_t *abs_path = NULL;
981 status = calculate_program_macos(&abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200982 if (_PyStatus_EXCEPTION(status)) {
983 return status;
984 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200985 if (abs_path) {
986 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200987 return _PyStatus_OK();
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000988 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000989#endif /* __APPLE__ */
Jack Jansen55070f52001-12-02 23:56:28 +0000990
Victor Stinner03a8a562019-10-04 02:22:39 +0200991 if (calculate->path_env) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200992 wchar_t *abs_path = NULL;
Victor Stinner03a8a562019-10-04 02:22:39 +0200993 status = calculate_which(calculate->path_env, pathconfig->program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200994 &abs_path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200995 if (_PyStatus_EXCEPTION(status)) {
996 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100997 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200998 if (abs_path) {
999 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +02001000 return _PyStatus_OK();
1001 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001002 }
Victor Stinner03a8a562019-10-04 02:22:39 +02001003
1004 /* In the last resort, use an empty string */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001005 pathconfig->program_full_path = _PyMem_RawWcsdup(L"");
1006 if (pathconfig->program_full_path == NULL) {
1007 return _PyStatus_NO_MEMORY();
1008 }
Victor Stinner03a8a562019-10-04 02:22:39 +02001009 return _PyStatus_OK();
1010}
1011
1012
1013/* Calculate pathconfig->program_full_path */
1014static PyStatus
1015calculate_program(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
1016{
1017 PyStatus status;
Victor Stinner03a8a562019-10-04 02:22:39 +02001018
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001019 status = calculate_program_impl(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001020 if (_PyStatus_EXCEPTION(status)) {
1021 return status;
1022 }
1023
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001024 if (pathconfig->program_full_path[0] != '\0') {
Victor Stinner03a8a562019-10-04 02:22:39 +02001025 /* program_full_path is not empty */
1026
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001027 /* Make sure that program_full_path is an absolute path */
1028 if (!_Py_isabs(pathconfig->program_full_path)) {
1029 status = absolutize(&pathconfig->program_full_path);
Victor Stinner03a8a562019-10-04 02:22:39 +02001030 if (_PyStatus_EXCEPTION(status)) {
1031 return status;
1032 }
1033 }
1034
1035#if defined(__CYGWIN__) || defined(__MINGW32__)
1036 /* For these platforms it is necessary to ensure that the .exe suffix
1037 * is appended to the filename, otherwise there is potential for
1038 * sys.executable to return the name of a directory under the same
1039 * path (bpo-28441).
1040 */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001041 status = add_exe_suffix(&pathconfig->program_full_path);
Victor Stinner331a6a52019-05-27 16:39:22 +02001042 if (_PyStatus_EXCEPTION(status)) {
1043 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001044 }
E. M. Bray7a7693e2018-10-05 13:38:50 +02001045#endif
Victor Stinner03a8a562019-10-04 02:22:39 +02001046 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001047 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001048}
1049
1050
Victor Stinner03a8a562019-10-04 02:22:39 +02001051#if HAVE_READLINK
Victor Stinner331a6a52019-05-27 16:39:22 +02001052static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001053resolve_symlinks(wchar_t **path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +02001054{
1055 wchar_t new_path[MAXPATHLEN + 1];
1056 const size_t new_path_len = Py_ARRAY_LENGTH(new_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001057 unsigned int nlink = 0;
Victor Stinner03a8a562019-10-04 02:22:39 +02001058
1059 while (1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001060 int linklen = _Py_wreadlink(*path_p, new_path, new_path_len);
Victor Stinner03a8a562019-10-04 02:22:39 +02001061 if (linklen == -1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001062 /* not a symbolic link: we are done */
Victor Stinner03a8a562019-10-04 02:22:39 +02001063 break;
1064 }
1065
1066 if (_Py_isabs(new_path)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001067 PyMem_RawFree(*path_p);
1068 *path_p = _PyMem_RawWcsdup(new_path);
1069 if (*path_p == NULL) {
1070 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001071 }
1072 }
1073 else {
1074 /* new_path is relative to path */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001075 reduce(*path_p);
1076
1077 wchar_t *abs_path = joinpath2(*path_p, new_path);
1078 if (abs_path == NULL) {
1079 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001080 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001081
1082 PyMem_RawFree(*path_p);
1083 *path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +02001084 }
1085
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001086 nlink++;
Victor Stinner03a8a562019-10-04 02:22:39 +02001087 /* 40 is the Linux kernel 4.2 limit */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001088 if (nlink >= 40) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001089 return _PyStatus_ERR("maximum number of symbolic links reached");
1090 }
1091 }
1092 return _PyStatus_OK();
1093}
1094#endif /* HAVE_READLINK */
1095
1096
1097#ifdef WITH_NEXT_FRAMEWORK
1098static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001099calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +02001100{
1101 NSModule pythonModule;
1102
1103 /* On Mac OS X we have a special case if we're running from a framework.
1104 This is because the python home should be set relative to the library,
1105 which is in the framework, not relative to the executable, which may
1106 be outside of the framework. Except when we're in the build
1107 directory... */
1108 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
1109
1110 /* Use dylib functions to find out where the framework was loaded from */
1111 const char* modPath = NSLibraryNameForModule(pythonModule);
1112 if (modPath == NULL) {
1113 return _PyStatus_OK();
1114 }
1115
1116 /* We're in a framework.
1117 See if we might be in the build directory. The framework in the
1118 build directory is incomplete, it only has the .dylib and a few
1119 needed symlinks, it doesn't have the Lib directories and such.
1120 If we're running with the framework from the build directory we must
1121 be running the interpreter in the build directory, so we use the
1122 build-directory-specific logic to find Lib and such. */
1123 size_t len;
1124 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
1125 if (wbuf == NULL) {
1126 return DECODE_LOCALE_ERR("framework location", len);
1127 }
1128
1129 /* Path: reduce(modPath) / lib_python / LANDMARK */
1130 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001131
1132 wchar_t *parent = _PyMem_RawWcsdup(wbuf);
1133 if (parent == NULL) {
1134 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001135 goto done;
1136 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001137
1138 reduce(parent);
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001139 wchar_t *lib_python = joinpath2(parent, calculate->lib_python);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001140 PyMem_RawFree(parent);
1141
1142 if (lib_python == NULL) {
1143 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001144 goto done;
1145 }
Victor Stinnerf0c85792019-10-04 03:53:26 +02001146
1147 int module;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001148 status = ismodule(lib_python, &module);
1149 PyMem_RawFree(lib_python);
1150
Victor Stinner03a8a562019-10-04 02:22:39 +02001151 if (_PyStatus_EXCEPTION(status)) {
1152 goto done;
1153 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001154 if (!module) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001155 /* We are in the build directory so use the name of the
1156 executable - we know that the absolute path is passed */
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001157 PyMem_RawFree(calculate->argv0_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001158 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1159 if (calculate->argv0_path == NULL) {
1160 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001161 goto done;
1162 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001163
1164 status = _PyStatus_OK();
1165 goto done;
Victor Stinner03a8a562019-10-04 02:22:39 +02001166 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001167
1168 /* Use the location of the library as argv0_path */
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001169 PyMem_RawFree(calculate->argv0_path);
1170 calculate->argv0_path = wbuf;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001171 return _PyStatus_OK();
Victor Stinner03a8a562019-10-04 02:22:39 +02001172
1173done:
1174 PyMem_RawFree(wbuf);
1175 return status;
1176}
1177#endif
1178
1179
1180static PyStatus
1181calculate_argv0_path(PyCalculatePath *calculate,
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001182 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001183{
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001184 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001185
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001186 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1187 if (calculate->argv0_path == NULL) {
1188 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001189 }
Jack Jansen55070f52001-12-02 23:56:28 +00001190
Guido van Rossum54ecc3d1999-01-27 17:53:11 +00001191#ifdef WITH_NEXT_FRAMEWORK
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001192 status = calculate_argv0_path_framework(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001193 if (_PyStatus_EXCEPTION(status)) {
1194 return status;
Fred Drakeedabdc12000-07-08 06:16:37 +00001195 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +00001196#endif
Guido van Rossume296ced2001-09-28 20:00:29 +00001197
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001198 status = resolve_symlinks(&calculate->argv0_path);
1199 if (_PyStatus_EXCEPTION(status)) {
1200 return status;
1201 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001202
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001203 reduce(calculate->argv0_path);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001204
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001205 return _PyStatus_OK();
1206}
1207
1208
1209static PyStatus
1210calculate_open_pyenv(PyCalculatePath *calculate, FILE **env_file_p)
1211{
1212 *env_file_p = NULL;
1213
1214 const wchar_t *env_cfg = L"pyvenv.cfg";
1215
1216 /* Filename: <argv0_path> / "pyvenv.cfg" */
1217 wchar_t *filename = joinpath2(calculate->argv0_path, env_cfg);
1218 if (filename == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001219 return _PyStatus_NO_MEMORY();
1220 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001221
1222 *env_file_p = _Py_wfopen(filename, L"r");
1223 PyMem_RawFree(filename);
1224
1225 if (*env_file_p != NULL) {
1226 return _PyStatus_OK();
1227
1228 }
1229
1230 /* fopen() failed: reset errno */
1231 errno = 0;
1232
1233 /* Path: <basename(argv0_path)> / "pyvenv.cfg" */
1234 wchar_t *parent = _PyMem_RawWcsdup(calculate->argv0_path);
1235 if (parent == NULL) {
1236 return _PyStatus_NO_MEMORY();
1237 }
1238 reduce(parent);
1239
1240 filename = joinpath2(parent, env_cfg);
1241 PyMem_RawFree(parent);
1242 if (filename == NULL) {
1243 return _PyStatus_NO_MEMORY();
1244 }
1245
1246 *env_file_p = _Py_wfopen(filename, L"r");
1247 PyMem_RawFree(filename);
1248
1249 if (*env_file_p == NULL) {
1250 /* fopen() failed: reset errno */
1251 errno = 0;
1252 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001253 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001254}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001255
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001256
Victor Stinner0327bde2017-11-23 17:03:20 +01001257/* Search for an "pyvenv.cfg" environment configuration file, first in the
1258 executable's directory and then in the parent directory.
1259 If found, open it for use when searching for prefixes.
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001260
1261 Write the 'home' variable of pyvenv.cfg into calculate->argv0_path. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001262static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001263calculate_read_pyenv(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001264{
Victor Stinner331a6a52019-05-27 16:39:22 +02001265 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001266 FILE *env_file = NULL;
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001267
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001268 status = calculate_open_pyenv(calculate, &env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001269 if (_PyStatus_EXCEPTION(status)) {
1270 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001271 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001272 if (env_file == NULL) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001273 /* pyvenv.cfg not found */
1274 return _PyStatus_OK();
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001275 }
1276
Victor Stinner0327bde2017-11-23 17:03:20 +01001277 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001278 wchar_t *home = NULL;
1279 status = _Py_FindEnvConfigValue(env_file, L"home", &home);
1280 if (_PyStatus_EXCEPTION(status)) {
1281 fclose(env_file);
1282 return status;
1283 }
Victor Stinner221fd842019-09-25 02:54:25 +02001284
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001285 if (home) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001286 PyMem_RawFree(calculate->argv0_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001287 calculate->argv0_path = home;
Just van Rossum52e14d62002-12-30 22:08:05 +00001288 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001289 fclose(env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001290 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001291}
Just van Rossum52e14d62002-12-30 22:08:05 +00001292
Guido van Rossum305e5d01997-04-11 17:18:45 +00001293
Victor Stinner331a6a52019-05-27 16:39:22 +02001294static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001295calculate_zip_path(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001296{
Victor Stinner8510f432020-03-10 09:53:09 +01001297 PyStatus res;
1298
Victor Stinnerd72b9642020-06-11 17:28:52 +02001299 /* Path: <platlibdir> / "pythonXY.zip" */
1300 wchar_t *path = joinpath2(calculate->platlibdir,
1301 L"python" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION)
1302 L".zip");
Victor Stinner8510f432020-03-10 09:53:09 +01001303 if (path == NULL) {
1304 return _PyStatus_NO_MEMORY();
1305 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001306
Victor Stinner0327bde2017-11-23 17:03:20 +01001307 if (calculate->prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001308 /* Use the reduced prefix returned by Py_GetPrefix()
1309
Victor Stinnerd72b9642020-06-11 17:28:52 +02001310 Path: <basename(basename(prefix))> / <platlibdir> / "pythonXY.zip" */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001311 wchar_t *parent = _PyMem_RawWcsdup(calculate->prefix);
1312 if (parent == NULL) {
Victor Stinner8510f432020-03-10 09:53:09 +01001313 res = _PyStatus_NO_MEMORY();
1314 goto done;
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001315 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001316 reduce(parent);
1317 reduce(parent);
Victor Stinner8510f432020-03-10 09:53:09 +01001318 calculate->zip_path = joinpath2(parent, path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001319 PyMem_RawFree(parent);
Victor Stinnerd4341102017-11-23 00:12:09 +01001320 }
1321 else {
Victor Stinner8510f432020-03-10 09:53:09 +01001322 calculate->zip_path = joinpath2(calculate->prefix_macro, path);
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001323 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001324
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001325 if (calculate->zip_path == NULL) {
Victor Stinner8510f432020-03-10 09:53:09 +01001326 res = _PyStatus_NO_MEMORY();
1327 goto done;
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001328 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001329
Victor Stinner8510f432020-03-10 09:53:09 +01001330 res = _PyStatus_OK();
1331
1332done:
1333 PyMem_RawFree(path);
1334 return res;
Victor Stinner0327bde2017-11-23 17:03:20 +01001335}
1336
1337
Victor Stinner331a6a52019-05-27 16:39:22 +02001338static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001339calculate_module_search_path(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001340 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001341{
1342 /* Calculate size of return buffer */
1343 size_t bufsz = 0;
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001344 if (calculate->pythonpath_env != NULL) {
1345 bufsz += wcslen(calculate->pythonpath_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001346 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001347
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001348 wchar_t *defpath = calculate->pythonpath_macro;
1349 size_t prefixsz = wcslen(calculate->prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001350 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001351 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001352
Victor Stinner3939c322019-06-25 15:02:43 +02001353 if (!_Py_isabs(defpath)) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001354 /* Paths are relative to prefix */
1355 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001356 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001357
Victor Stinner0327bde2017-11-23 17:03:20 +01001358 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001359 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001360 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001361 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001362 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001363 break;
1364 }
1365 defpath = delim + 1;
1366 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001367
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001368 bufsz += wcslen(calculate->zip_path) + 1;
1369 bufsz += wcslen(calculate->exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001370
Victor Stinner0327bde2017-11-23 17:03:20 +01001371 /* Allocate the buffer */
1372 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001373 if (buf == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +02001374 return _PyStatus_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001375 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001376 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001377
Victor Stinner72967a42013-11-16 01:22:04 +01001378 /* Run-time value of $PYTHONPATH goes first */
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001379 if (calculate->pythonpath_env) {
1380 wcscpy(buf, calculate->pythonpath_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001381 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001382 }
Victor Stinner72967a42013-11-16 01:22:04 +01001383
1384 /* Next is the default zip path */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001385 wcscat(buf, calculate->zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001386 wcscat(buf, delimiter);
1387
1388 /* Next goes merge of compile-time $PYTHONPATH with
1389 * dynamically located prefix.
1390 */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001391 defpath = calculate->pythonpath_macro;
Victor Stinner72967a42013-11-16 01:22:04 +01001392 while (1) {
1393 wchar_t *delim = wcschr(defpath, DELIM);
1394
Victor Stinner3939c322019-06-25 15:02:43 +02001395 if (!_Py_isabs(defpath)) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001396 wcscat(buf, calculate->prefix);
1397 if (prefixsz >= 2 && calculate->prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001398 defpath[0] != (delim ? DELIM : L'\0'))
1399 {
1400 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001401 wcscat(buf, separator);
1402 }
Victor Stinner72967a42013-11-16 01:22:04 +01001403 }
1404
1405 if (delim) {
1406 size_t len = delim - defpath + 1;
1407 size_t end = wcslen(buf) + len;
1408 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001409 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001410 }
1411 else {
1412 wcscat(buf, defpath);
1413 break;
1414 }
1415 defpath = delim + 1;
1416 }
1417 wcscat(buf, delimiter);
1418
1419 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001420 wcscat(buf, calculate->exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001421
Victor Stinner331a6a52019-05-27 16:39:22 +02001422 pathconfig->module_search_path = buf;
1423 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001424}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001425
Victor Stinner0327bde2017-11-23 17:03:20 +01001426
Victor Stinner331a6a52019-05-27 16:39:22 +02001427static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +02001428calculate_init(PyCalculatePath *calculate, const PyConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001429{
Victor Stinner0327bde2017-11-23 17:03:20 +01001430 size_t len;
Victor Stinnerd72b9642020-06-11 17:28:52 +02001431
1432 calculate->warnings = config->pathconfig_warnings;
1433 calculate->pythonpath_env = config->pythonpath_env;
1434 calculate->platlibdir = config->platlibdir;
1435
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001436 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001437 if (path) {
1438 calculate->path_env = Py_DecodeLocale(path, &len);
1439 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001440 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001441 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001442 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001443
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001444 /* Decode macros */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001445 calculate->pythonpath_macro = Py_DecodeLocale(PYTHONPATH, &len);
1446 if (!calculate->pythonpath_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001447 return DECODE_LOCALE_ERR("PYTHONPATH macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001448 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001449 calculate->prefix_macro = Py_DecodeLocale(PREFIX, &len);
1450 if (!calculate->prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001451 return DECODE_LOCALE_ERR("PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001452 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001453 calculate->exec_prefix_macro = Py_DecodeLocale(EXEC_PREFIX, &len);
1454 if (!calculate->exec_prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001455 return DECODE_LOCALE_ERR("EXEC_PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001456 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001457 calculate->vpath_macro = Py_DecodeLocale(VPATH, &len);
1458 if (!calculate->vpath_macro) {
1459 return DECODE_LOCALE_ERR("VPATH macro", len);
1460 }
1461
Victor Stinnerd72b9642020-06-11 17:28:52 +02001462 // <platlibdir> / "pythonX.Y"
1463 wchar_t *pyversion = Py_DecodeLocale("python" VERSION, &len);
1464 if (!pyversion) {
Victor Stinner8510f432020-03-10 09:53:09 +01001465 return DECODE_LOCALE_ERR("VERSION macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001466 }
Victor Stinnerd72b9642020-06-11 17:28:52 +02001467 calculate->lib_python = joinpath2(config->platlibdir, pyversion);
1468 PyMem_RawFree(pyversion);
1469 if (calculate->lib_python == NULL) {
1470 return _PyStatus_NO_MEMORY();
1471 }
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001472
Victor Stinner331a6a52019-05-27 16:39:22 +02001473 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001474}
1475
1476
1477static void
1478calculate_free(PyCalculatePath *calculate)
1479{
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001480 PyMem_RawFree(calculate->pythonpath_macro);
1481 PyMem_RawFree(calculate->prefix_macro);
1482 PyMem_RawFree(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001483 PyMem_RawFree(calculate->vpath_macro);
Victor Stinner0327bde2017-11-23 17:03:20 +01001484 PyMem_RawFree(calculate->lib_python);
1485 PyMem_RawFree(calculate->path_env);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001486 PyMem_RawFree(calculate->zip_path);
1487 PyMem_RawFree(calculate->argv0_path);
1488 PyMem_RawFree(calculate->prefix);
1489 PyMem_RawFree(calculate->exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +01001490}
1491
1492
Victor Stinner331a6a52019-05-27 16:39:22 +02001493static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001494calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001495{
Victor Stinner331a6a52019-05-27 16:39:22 +02001496 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +01001497
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001498 if (pathconfig->program_full_path == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001499 status = calculate_program(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001500 if (_PyStatus_EXCEPTION(status)) {
1501 return status;
1502 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001503 }
1504
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001505 status = calculate_argv0_path(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001506 if (_PyStatus_EXCEPTION(status)) {
1507 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001508 }
1509
Victor Stinner221fd842019-09-25 02:54:25 +02001510 /* If a pyvenv.cfg configure file is found,
1511 argv0_path is overriden with its 'home' variable. */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001512 status = calculate_read_pyenv(calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001513 if (_PyStatus_EXCEPTION(status)) {
1514 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001515 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001516
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001517 status = calculate_prefix(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001518 if (_PyStatus_EXCEPTION(status)) {
1519 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001520 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001521
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001522 status = calculate_zip_path(calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001523 if (_PyStatus_EXCEPTION(status)) {
1524 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001525 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001526
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001527 status = calculate_exec_prefix(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001528 if (_PyStatus_EXCEPTION(status)) {
1529 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001530 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001531
Victor Stinner03a8a562019-10-04 02:22:39 +02001532 if ((!calculate->prefix_found || !calculate->exec_prefix_found)
1533 && calculate->warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001534 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001535 fprintf(stderr,
1536 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1537 }
1538
Victor Stinnere2677932019-09-21 01:50:16 +02001539 if (pathconfig->module_search_path == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001540 status = calculate_module_search_path(calculate, pathconfig);
Victor Stinnere2677932019-09-21 01:50:16 +02001541 if (_PyStatus_EXCEPTION(status)) {
1542 return status;
1543 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001544 }
1545
Victor Stinner331a6a52019-05-27 16:39:22 +02001546 if (pathconfig->prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001547 status = calculate_set_prefix(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001548 if (_PyStatus_EXCEPTION(status)) {
1549 return status;
1550 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001551 }
1552
Victor Stinner331a6a52019-05-27 16:39:22 +02001553 if (pathconfig->exec_prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001554 status = calculate_set_exec_prefix(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001555 if (_PyStatus_EXCEPTION(status)) {
1556 return status;
1557 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001558 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001559 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001560}
1561
1562
Victor Stinner85ce0a72019-09-24 00:55:48 +02001563/* Calculate the Python path configuration.
1564
1565 Inputs:
1566
1567 - PATH environment variable
1568 - Macros: PYTHONPATH, PREFIX, EXEC_PREFIX, VERSION (ex: "3.9").
1569 PREFIX and EXEC_PREFIX are generated by the configure script.
1570 PYTHONPATH macro is the default search path.
1571 - pybuilddir.txt file
1572 - pyvenv.cfg configuration file
1573 - PyConfig fields ('config' function argument):
1574
1575 - pathconfig_warnings
1576 - pythonpath_env (PYTHONPATH environment variable)
1577
1578 - _PyPathConfig fields ('pathconfig' function argument):
1579
1580 - program_name: see config_init_program_name()
1581 - home: Py_SetPythonHome() or PYTHONHOME environment variable
1582
1583 - current working directory: see copy_absolute()
1584
1585 Outputs, 'pathconfig' fields:
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001586
1587 - program_full_path
1588 - module_search_path
1589 - prefix
1590 - exec_prefix
1591
Victor Stinner85ce0a72019-09-24 00:55:48 +02001592 If a field is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001593PyStatus
1594_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001595{
Victor Stinner331a6a52019-05-27 16:39:22 +02001596 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001597 PyCalculatePath calculate;
1598 memset(&calculate, 0, sizeof(calculate));
1599
Victor Stinner331a6a52019-05-27 16:39:22 +02001600 status = calculate_init(&calculate, config);
1601 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001602 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001603 }
1604
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001605 status = calculate_path(&calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001606 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001607 goto done;
1608 }
1609
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001610 /* program_full_path must an either an empty string or an absolute path */
1611 assert(wcslen(pathconfig->program_full_path) == 0
1612 || _Py_isabs(pathconfig->program_full_path));
1613
Victor Stinner331a6a52019-05-27 16:39:22 +02001614 status = _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001615
Victor Stinner9316ee42017-11-25 03:17:57 +01001616done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001617 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001618 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001619}
Victor Stinner46972b72017-11-24 22:55:40 +01001620
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001621#ifdef __cplusplus
1622}
1623#endif