blob: 993276fdc27d0ca7baedf51cb9614e91e3feb424 [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 Stinner331a6a52019-05-27 16:39:22 +02004#include "pycore_initconfig.h"
Guido van Rossum667d7041995-08-04 04:20:48 +00005#include "osdefs.h"
Victor Stinner9fc57a32018-11-07 00:44:03 +01006#include "pycore_fileutils.h"
Victor Stinnera1c249c2018-11-01 03:15:58 +01007#include "pycore_pathconfig.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01008#include "pycore_pystate.h"
Guido van Rossum667d7041995-08-04 04:20:48 +00009
Guido van Rossum305e5d01997-04-11 17:18:45 +000010#include <sys/types.h>
Guido van Rossum21f84971997-06-02 22:18:31 +000011#include <string.h>
Guido van Rossum667d7041995-08-04 04:20:48 +000012
Brett Cannonf6af76d2004-06-26 04:03:06 +000013#ifdef __APPLE__
Victor Stinner0327bde2017-11-23 17:03:20 +010014# include <mach-o/dyld.h>
Guido van Rossum54ecc3d1999-01-27 17:53:11 +000015#endif
16
Guido van Rossum305e5d01997-04-11 17:18:45 +000017/* Search in some common locations for the associated Python libraries.
18 *
19 * Two directories must be found, the platform independent directory
Barry Warsaw90126031997-04-11 20:27:03 +000020 * (prefix), containing the common .py and .pyc files, and the platform
21 * dependent directory (exec_prefix), containing the shared library
22 * modules. Note that prefix and exec_prefix can be the same directory,
23 * but for some installations, they are different.
Guido van Rossum305e5d01997-04-11 17:18:45 +000024 *
Barry Warsaw90126031997-04-11 20:27:03 +000025 * Py_GetPath() carries out separate searches for prefix and exec_prefix.
26 * Each search tries a number of different locations until a ``landmark''
27 * file or directory is found. If no prefix or exec_prefix is found, a
28 * warning message is issued and the preprocessor defined PREFIX and
29 * EXEC_PREFIX are used (even though they will not work); python carries on
30 * as best as is possible, but most imports will fail.
Guido van Rossum305e5d01997-04-11 17:18:45 +000031 *
32 * Before any searches are done, the location of the executable is
Guido van Rossumd8faa362007-04-27 19:54:29 +000033 * determined. If argv[0] has one or more slashes in it, it is used
Barry Warsaw90126031997-04-11 20:27:03 +000034 * unchanged. Otherwise, it must have been invoked from the shell's path,
35 * so we search $PATH for the named executable and use that. If the
36 * executable was not found on $PATH (or there was no $PATH environment
37 * variable), the original argv[0] string is used.
Guido van Rossum305e5d01997-04-11 17:18:45 +000038 *
Barry Warsaw90126031997-04-11 20:27:03 +000039 * Next, the executable location is examined to see if it is a symbolic
40 * link. If so, the link is chased (correctly interpreting a relative
41 * pathname if one is found) and the directory of the link target is used.
Guido van Rossum305e5d01997-04-11 17:18:45 +000042 *
Barry Warsaw90126031997-04-11 20:27:03 +000043 * Finally, argv0_path is set to the directory containing the executable
44 * (i.e. the last component is stripped).
Guido van Rossum305e5d01997-04-11 17:18:45 +000045 *
Barry Warsaw90126031997-04-11 20:27:03 +000046 * With argv0_path in hand, we perform a number of steps. The same steps
47 * are performed for prefix and for exec_prefix, but with a different
48 * landmark.
Guido van Rossum305e5d01997-04-11 17:18:45 +000049 *
50 * Step 1. Are we running python out of the build directory? This is
51 * checked by looking for a different kind of landmark relative to
Barry Warsaw90126031997-04-11 20:27:03 +000052 * argv0_path. For prefix, the landmark's path is derived from the VPATH
53 * preprocessor variable (taking into account that its value is almost, but
54 * not quite, what we need). For exec_prefix, the landmark is
Antoine Pitroueba57b62010-08-14 12:33:18 +000055 * pybuilddir.txt. If the landmark is found, we're done.
Guido van Rossum305e5d01997-04-11 17:18:45 +000056 *
57 * For the remaining steps, the prefix landmark will always be
Jeremy Hylton847a9962000-05-26 21:49:07 +000058 * lib/python$VERSION/os.py and the exec_prefix will always be
Guido van Rossum266033e1997-10-20 23:20:32 +000059 * lib/python$VERSION/lib-dynload, where $VERSION is Python's version
Barry Warsaw90126031997-04-11 20:27:03 +000060 * number as supplied by the Makefile. Note that this means that no more
61 * build directory checking is performed; if the first step did not find
62 * the landmarks, the assumption is that python is running from an
63 * installed setup.
Guido van Rossum305e5d01997-04-11 17:18:45 +000064 *
65 * Step 2. See if the $PYTHONHOME environment variable points to the
Barry Warsaw90126031997-04-11 20:27:03 +000066 * installed location of the Python libraries. If $PYTHONHOME is set, then
67 * it points to prefix and exec_prefix. $PYTHONHOME can be a single
68 * directory, which is used for both, or the prefix and exec_prefix
69 * directories separated by a colon.
Guido van Rossum305e5d01997-04-11 17:18:45 +000070 *
71 * Step 3. Try to find prefix and exec_prefix relative to argv0_path,
Barry Warsaw90126031997-04-11 20:27:03 +000072 * backtracking up the path until it is exhausted. This is the most common
73 * step to succeed. Note that if prefix and exec_prefix are different,
74 * exec_prefix is more likely to be found; however if exec_prefix is a
75 * subdirectory of prefix, both will be found.
Guido van Rossum305e5d01997-04-11 17:18:45 +000076 *
Barry Warsaw90126031997-04-11 20:27:03 +000077 * Step 4. Search the directories pointed to by the preprocessor variables
78 * PREFIX and EXEC_PREFIX. These are supplied by the Makefile but can be
79 * passed in as options to the configure script.
Guido van Rossum305e5d01997-04-11 17:18:45 +000080 *
Barry Warsaw90126031997-04-11 20:27:03 +000081 * That's it!
82 *
83 * Well, almost. Once we have determined prefix and exec_prefix, the
Thomas Wouters7e474022000-07-16 12:04:32 +000084 * preprocessor variable PYTHONPATH is used to construct a path. Each
Barry Warsaw90126031997-04-11 20:27:03 +000085 * relative path on PYTHONPATH is prefixed with prefix. Then the directory
86 * containing the shared library modules is appended. The environment
87 * variable $PYTHONPATH is inserted in front of it all. Finally, the
88 * prefix and exec_prefix globals are tweaked so they reflect the values
89 * expected by other code, by stripping the "lib/python$VERSION/..." stuff
90 * off. If either points to the build directory, the globals are reset to
91 * the corresponding preprocessor variables (so sys.prefix will reflect the
92 * installation location, even though sys.path points into the build
93 * directory). This seems to make more sense given that currently the only
94 * known use of sys.prefix and sys.exec_prefix is for the ILU installation
95 * process to find the installed Python tree.
Antoine Pitroueba57b62010-08-14 12:33:18 +000096 *
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000097 * An embedding application can use Py_SetPath() to override all of
Min ho Kimc4cacc82019-07-31 08:16:13 +100098 * these automatic path computations.
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000099 *
Antoine Pitroueba57b62010-08-14 12:33:18 +0000100 * NOTE: Windows MSVC builds use PC/getpathp.c instead!
Barry Warsaw90126031997-04-11 20:27:03 +0000101 */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000102
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000103#ifdef __cplusplus
Victor Stinner0327bde2017-11-23 17:03:20 +0100104extern "C" {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000105#endif
106
107
Benjamin Petersonf5854142016-06-02 12:41:35 -0700108#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH)
109#error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000110#endif
Guido van Rossum667d7041995-08-04 04:20:48 +0000111
Guido van Rossum305e5d01997-04-11 17:18:45 +0000112#ifndef LANDMARK
Martin v. Löwis790465f2008-04-05 20:41:37 +0000113#define LANDMARK L"os.py"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000114#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000115
Victor 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
133 wchar_t *lib_python; /* "lib/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;
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200140
141 wchar_t *argv0_path;
142 wchar_t *zip_path;
143 wchar_t *prefix;
144 wchar_t *exec_prefix;
Victor Stinner0327bde2017-11-23 17:03:20 +0100145} PyCalculatePath;
146
147static const wchar_t delimiter[2] = {DELIM, '\0'};
148static const wchar_t separator[2] = {SEP, '\0'};
Victor Stinner0327bde2017-11-23 17:03:20 +0100149
Martin v. Löwis790465f2008-04-05 20:41:37 +0000150
Victor Stinner91afbb62015-03-24 12:16:28 +0100151/* Get file status. Encode the path to the locale encoding. */
Victor Stinner91afbb62015-03-24 12:16:28 +0100152static int
153_Py_wstat(const wchar_t* path, struct stat *buf)
154{
155 int err;
156 char *fname;
Victor Stinner9dd76202017-12-21 16:20:32 +0100157 fname = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner91afbb62015-03-24 12:16:28 +0100158 if (fname == NULL) {
159 errno = EINVAL;
160 return -1;
161 }
162 err = stat(fname, buf);
Victor Stinner9dd76202017-12-21 16:20:32 +0100163 PyMem_RawFree(fname);
Victor Stinner91afbb62015-03-24 12:16:28 +0100164 return err;
165}
166
Victor Stinner0327bde2017-11-23 17:03:20 +0100167
Guido van Rossum305e5d01997-04-11 17:18:45 +0000168static void
Martin v. Löwis790465f2008-04-05 20:41:37 +0000169reduce(wchar_t *dir)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000170{
Martin v. Löwis790465f2008-04-05 20:41:37 +0000171 size_t i = wcslen(dir);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100172 while (i > 0 && dir[i] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000173 --i;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100174 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000175 dir[i] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +0000176}
Guido van Rossumd29806c1998-01-19 22:06:22 +0000177
Victor Stinner0327bde2017-11-23 17:03:20 +0100178
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100179/* Is file, not directory */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000180static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100181isfile(const wchar_t *filename)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000182{
Fred Drakeedabdc12000-07-08 06:16:37 +0000183 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100184 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000185 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100186 }
187 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000188 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100189 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000190 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000191}
192
193
Victor Stinner0327bde2017-11-23 17:03:20 +0100194/* Is executable file */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000195static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100196isxfile(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000197{
Fred Drakeedabdc12000-07-08 06:16:37 +0000198 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100199 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000200 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100201 }
202 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000203 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100204 }
205 if ((buf.st_mode & 0111) == 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000206 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100207 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000208 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000209}
210
211
Victor Stinner0327bde2017-11-23 17:03:20 +0100212/* Is directory */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000213static int
Victor Stinnerf0c85792019-10-04 03:53:26 +0200214isdir(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000215{
Fred Drakeedabdc12000-07-08 06:16:37 +0000216 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100217 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000218 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100219 }
220 if (!S_ISDIR(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000221 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100222 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000223 return 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000224}
225
226
Tim Petersec8c5a92004-08-08 01:00:47 +0000227/* Add a path component, by appending stuff to buffer.
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200228 buflen: 'buffer' length in characters including trailing NUL.
229
230 If path2 is empty:
231
232 - if path doesn't end with SEP and is not empty, add SEP to path
233 - otherwise, do nothing. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200234static PyStatus
Victor Stinnerf0c85792019-10-04 03:53:26 +0200235joinpath(wchar_t *path, const wchar_t *path2, size_t path_len)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000236{
Victor Stinnerf0c85792019-10-04 03:53:26 +0200237 size_t n;
238 if (!_Py_isabs(path2)) {
239 n = wcslen(path);
240 if (n >= path_len) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100241 return PATHLEN_ERR();
242 }
243
Victor Stinnerf0c85792019-10-04 03:53:26 +0200244 if (n > 0 && path[n-1] != SEP) {
245 path[n++] = SEP;
Victor Stinner0327bde2017-11-23 17:03:20 +0100246 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000247 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100248 else {
249 n = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100250 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100251
Victor Stinnerf0c85792019-10-04 03:53:26 +0200252 size_t k = wcslen(path2);
253 if (n + k >= path_len) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100254 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100255 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200256 wcsncpy(path + n, path2, k);
257 path[n + k] = '\0';
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100258
Victor Stinner331a6a52019-05-27 16:39:22 +0200259 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000260}
261
Victor Stinner0327bde2017-11-23 17:03:20 +0100262
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200263static wchar_t*
264substring(const wchar_t *str, size_t len)
265{
266 wchar_t *substr = PyMem_RawMalloc((len + 1) * sizeof(wchar_t));
267 if (substr == NULL) {
268 return NULL;
269 }
270
271 if (len) {
272 memcpy(substr, str, len * sizeof(wchar_t));
273 }
274 substr[len] = L'\0';
275 return substr;
276}
277
278
279static wchar_t*
280joinpath2(const wchar_t *path, const wchar_t *path2)
281{
282 if (_Py_isabs(path2)) {
283 return _PyMem_RawWcsdup(path2);
284 }
285
286 size_t len = wcslen(path);
287 int add_sep = (len > 0 && path[len - 1] != SEP);
288 len += add_sep;
289 len += wcslen(path2);
290
291 wchar_t *new_path = PyMem_RawMalloc((len + 1) * sizeof(wchar_t));
292 if (new_path == NULL) {
293 return NULL;
294 }
295
296 wcscpy(new_path, path);
297 if (add_sep) {
298 wcscat(new_path, separator);
299 }
300 wcscat(new_path, path2);
301 return new_path;
302}
303
304
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100305static inline int
306safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
307{
308 size_t srclen = wcslen(src);
309 if (n <= srclen) {
310 dst[0] = L'\0';
311 return -1;
312 }
313 memcpy(dst, src, (srclen + 1) * sizeof(wchar_t));
314 return 0;
315}
316
317
Guido van Rossume296ced2001-09-28 20:00:29 +0000318/* copy_absolute requires that path be allocated at least
Victor Stinnerf0c85792019-10-04 03:53:26 +0200319 'abs_path_len' characters (including trailing NUL). */
Victor Stinner331a6a52019-05-27 16:39:22 +0200320static PyStatus
Victor Stinnerf0c85792019-10-04 03:53:26 +0200321copy_absolute(wchar_t *abs_path, const wchar_t *path, size_t abs_path_len)
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000322{
Victor Stinnerf0c85792019-10-04 03:53:26 +0200323 if (_Py_isabs(path)) {
324 if (safe_wcscpy(abs_path, path, abs_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100325 return PATHLEN_ERR();
326 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100327 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000328 else {
Victor Stinnerf0c85792019-10-04 03:53:26 +0200329 if (!_Py_wgetcwd(abs_path, abs_path_len)) {
Victor Stinner4f3abb02010-10-07 23:29:18 +0000330 /* unable to get the current directory */
Victor Stinnerf0c85792019-10-04 03:53:26 +0200331 if (safe_wcscpy(abs_path, path, abs_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100332 return PATHLEN_ERR();
333 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200334 return _PyStatus_OK();
Victor Stinner4f3abb02010-10-07 23:29:18 +0000335 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200336 if (path[0] == '.' && path[1] == SEP) {
337 path += 2;
Victor Stinner0327bde2017-11-23 17:03:20 +0100338 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200339 PyStatus status = joinpath(abs_path, path, abs_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200340 if (_PyStatus_EXCEPTION(status)) {
341 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100342 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000343 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200344 return _PyStatus_OK();
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000345}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000346
Victor Stinner0327bde2017-11-23 17:03:20 +0100347
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100348/* path_len: path length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200349static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200350absolutize(wchar_t **path_p)
Guido van Rossume296ced2001-09-28 20:00:29 +0000351{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200352 assert(!_Py_isabs(*path_p));
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100353
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100354 wchar_t abs_path[MAXPATHLEN+1];
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200355 wchar_t *path = *path_p;
356
Victor Stinner331a6a52019-05-27 16:39:22 +0200357 PyStatus status = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path));
358 if (_PyStatus_EXCEPTION(status)) {
359 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100360 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100361
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200362 PyMem_RawFree(*path_p);
363 *path_p = _PyMem_RawWcsdup(abs_path);
364 if (*path_p == NULL) {
365 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100366 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200367 return _PyStatus_OK();
Guido van Rossume296ced2001-09-28 20:00:29 +0000368}
369
Victor Stinner0327bde2017-11-23 17:03:20 +0100370
Victor Stinnerf0c85792019-10-04 03:53:26 +0200371/* Is module -- check for .pyc too */
372static PyStatus
373ismodule(const wchar_t *path, int *result)
374{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200375 wchar_t *filename = joinpath2(path, LANDMARK);
376 if (filename == NULL) {
377 return _PyStatus_NO_MEMORY();
Victor Stinnerf0c85792019-10-04 03:53:26 +0200378 }
379
380 if (isfile(filename)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200381 PyMem_RawFree(filename);
Victor Stinnerf0c85792019-10-04 03:53:26 +0200382 *result = 1;
383 return _PyStatus_OK();
384 }
385
386 /* Check for the compiled version of prefix. */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200387 size_t len = wcslen(filename);
388 wchar_t *pyc = PyMem_RawMalloc((len + 2) * sizeof(wchar_t));
389 if (pyc == NULL) {
390 PyMem_RawFree(filename);
391 return _PyStatus_NO_MEMORY();
Victor Stinnerf0c85792019-10-04 03:53:26 +0200392 }
393
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200394 memcpy(pyc, filename, len * sizeof(wchar_t));
395 pyc[len] = L'c';
396 pyc[len + 1] = L'\0';
397 *result = isfile(pyc);
398
399 PyMem_RawFree(filename);
400 PyMem_RawFree(pyc);
401
Victor Stinnerf0c85792019-10-04 03:53:26 +0200402 return _PyStatus_OK();
403}
404
405
E. M. Bray7a7693e2018-10-05 13:38:50 +0200406#if defined(__CYGWIN__) || defined(__MINGW32__)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200407#ifndef EXE_SUFFIX
408#define EXE_SUFFIX L".exe"
409#endif
410
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100411/* pathlen: 'path' length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200412static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200413add_exe_suffix(wchar_t **progpath_p)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200414{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200415 wchar_t *progpath = *progpath_p;
416
E. M. Bray7a7693e2018-10-05 13:38:50 +0200417 /* Check for already have an executable suffix */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200418 size_t n = wcslen(progpath);
E. M. Bray7a7693e2018-10-05 13:38:50 +0200419 size_t s = wcslen(EXE_SUFFIX);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200420 if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200421 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200422 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100423
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200424 wchar_t *progpath2 = PyMem_RawMalloc((n + s + 1) * sizeof(wchar_t));
425 if (progpath2 == NULL) {
426 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100427 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100428
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200429 memcpy(progpath2, progpath, n * sizeof(wchar_t));
430 memcpy(progpath2 + n, EXE_SUFFIX, s * sizeof(wchar_t));
431 progpath2[n+s] = L'\0';
432
433 if (isxfile(progpath2)) {
434 PyMem_RawFree(*progpath_p);
435 *progpath_p = progpath2;
436 }
437 else {
438 PyMem_RawFree(progpath2);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100439 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200440 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200441}
442#endif
443
444
Guido van Rossume296ced2001-09-28 20:00:29 +0000445/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000446 bytes long.
447*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200448static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200449search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
450 wchar_t *prefix, size_t prefix_len, int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000451{
Victor Stinner331a6a52019-05-27 16:39:22 +0200452 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000453
Fred Drakeedabdc12000-07-08 06:16:37 +0000454 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200455 if (pathconfig->home) {
Victor Stinner221fd842019-09-25 02:54:25 +0200456 /* Path: <home> / <lib_python> */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200457 if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100458 return PATHLEN_ERR();
459 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100460 wchar_t *delim = wcschr(prefix, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100461 if (delim) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000462 *delim = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100463 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200464 status = joinpath(prefix, calculate->lib_python, prefix_len);
465 if (_PyStatus_EXCEPTION(status)) {
466 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100467 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100468 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200469 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000470 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000471
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200472 /* Check to see if argv0_path is in the build directory
473
474 Path: <argv0_path> / <BUILD_LANDMARK define> */
475 wchar_t *path = joinpath2(calculate->argv0_path, BUILD_LANDMARK);
476 if (path == NULL) {
477 return _PyStatus_NO_MEMORY();
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100478 }
479
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200480 int is_build_dir = isfile(path);
481 PyMem_RawFree(path);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100482
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200483 if (is_build_dir) {
484 /* argv0_path is the build directory (BUILD_LANDMARK exists),
485 now also check LANDMARK using ismodule(). */
Victor Stinnerf0c85792019-10-04 03:53:26 +0200486
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200487 /* Path: <argv0_path> / <VPATH macro> / Lib */
488 /* or if VPATH is empty: <argv0_path> / Lib */
489 if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
490 return PATHLEN_ERR();
491 }
492
493 status = joinpath(prefix, calculate->vpath_macro, prefix_len);
494 if (_PyStatus_EXCEPTION(status)) {
495 return status;
496 }
497
498 status = joinpath(prefix, L"Lib", prefix_len);
499 if (_PyStatus_EXCEPTION(status)) {
500 return status;
501 }
502
503 int module;
504 status = ismodule(prefix, &module);
505 if (_PyStatus_EXCEPTION(status)) {
506 return status;
507 }
508 if (module) {
509 /* BUILD_LANDMARK and LANDMARK found */
510 *found = -1;
511 return _PyStatus_OK();
Victor Stinner21582312010-10-23 00:13:28 +0000512 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000513 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000514
Fred Drakeedabdc12000-07-08 06:16:37 +0000515 /* Search from argv0_path, until root is found */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200516 status = copy_absolute(prefix, calculate->argv0_path, prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200517 if (_PyStatus_EXCEPTION(status)) {
518 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100519 }
520
Fred Drakeedabdc12000-07-08 06:16:37 +0000521 do {
Victor Stinner221fd842019-09-25 02:54:25 +0200522 /* Path: <argv0_path or substring> / <lib_python> / LANDMARK */
523 size_t n = wcslen(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200524 status = joinpath(prefix, calculate->lib_python, prefix_len);
525 if (_PyStatus_EXCEPTION(status)) {
526 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100527 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200528
529 int module;
530 status = ismodule(prefix, &module);
Victor Stinner331a6a52019-05-27 16:39:22 +0200531 if (_PyStatus_EXCEPTION(status)) {
532 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100533 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200534 if (module) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100535 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200536 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100537 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100538 prefix[n] = L'\0';
539 reduce(prefix);
540 } while (prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000541
Victor Stinner221fd842019-09-25 02:54:25 +0200542 /* Look at configure's PREFIX.
543 Path: <PREFIX macro> / <lib_python> / LANDMARK */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200544 if (safe_wcscpy(prefix, calculate->prefix_macro, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100545 return PATHLEN_ERR();
546 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200547 status = joinpath(prefix, calculate->lib_python, prefix_len);
548 if (_PyStatus_EXCEPTION(status)) {
549 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100550 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200551
552 int module;
553 status = ismodule(prefix, &module);
Victor Stinner331a6a52019-05-27 16:39:22 +0200554 if (_PyStatus_EXCEPTION(status)) {
555 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100556 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200557 if (module) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100558 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200559 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100560 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000561
Fred Drakeedabdc12000-07-08 06:16:37 +0000562 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100563 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200564 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000565}
566
567
Victor Stinner331a6a52019-05-27 16:39:22 +0200568static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200569calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100570{
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200571 wchar_t prefix[MAXPATHLEN+1];
572 memset(prefix, 0, sizeof(prefix));
573 size_t prefix_len = Py_ARRAY_LENGTH(prefix);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100574
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200575 PyStatus status;
576 status = search_for_prefix(calculate, pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200577 prefix, prefix_len,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200578 &calculate->prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200579 if (_PyStatus_EXCEPTION(status)) {
580 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100581 }
582
Victor Stinner0327bde2017-11-23 17:03:20 +0100583 if (!calculate->prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200584 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100585 fprintf(stderr,
586 "Could not find platform independent libraries <prefix>\n");
587 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200588
589 calculate->prefix = joinpath2(calculate->prefix_macro,
590 calculate->lib_python);
591 }
592 else {
593 calculate->prefix = _PyMem_RawWcsdup(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100594 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200595
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200596 if (calculate->prefix == NULL) {
597 return _PyStatus_NO_MEMORY();
598 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200599 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100600}
601
602
Victor Stinner331a6a52019-05-27 16:39:22 +0200603static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200604calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100605{
606 /* Reduce prefix and exec_prefix to their essence,
607 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
608 * If we're loading relative to the build directory,
609 * return the compiled-in defaults instead.
610 */
611 if (calculate->prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200612 wchar_t *prefix = _PyMem_RawWcsdup(calculate->prefix);
613 if (prefix == NULL) {
614 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100615 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200616
617 reduce(prefix);
618 reduce(prefix);
619 if (prefix[0]) {
620 pathconfig->prefix = prefix;
621 }
622 else {
623 PyMem_RawFree(prefix);
624
625 /* The prefix is the root directory, but reduce() chopped
626 off the "/". */
627 pathconfig->prefix = _PyMem_RawWcsdup(separator);
628 if (pathconfig->prefix == NULL) {
629 return _PyStatus_NO_MEMORY();
630 }
631 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100632 }
633 else {
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200634 pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200635 if (pathconfig->prefix == NULL) {
636 return _PyStatus_NO_MEMORY();
637 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100638 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200639 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100640}
641
642
Victor Stinner221fd842019-09-25 02:54:25 +0200643static PyStatus
644calculate_pybuilddir(const wchar_t *argv0_path,
645 wchar_t *exec_prefix, size_t exec_prefix_len,
646 int *found)
647{
648 PyStatus status;
649
Victor Stinner221fd842019-09-25 02:54:25 +0200650 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
651 is written by setup.py and contains the relative path to the location
652 of shared library modules.
653
654 Filename: <argv0_path> / "pybuilddir.txt" */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200655 wchar_t *filename = joinpath2(argv0_path, L"pybuilddir.txt");
656 if (filename == NULL) {
657 return _PyStatus_NO_MEMORY();
Victor Stinner221fd842019-09-25 02:54:25 +0200658 }
659
660 if (!isfile(filename)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200661 PyMem_RawFree(filename);
Victor Stinner221fd842019-09-25 02:54:25 +0200662 return _PyStatus_OK();
663 }
664
665 FILE *fp = _Py_wfopen(filename, L"rb");
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200666 PyMem_RawFree(filename);
Victor Stinner221fd842019-09-25 02:54:25 +0200667 if (fp == NULL) {
668 errno = 0;
669 return _PyStatus_OK();
670 }
671
672 char buf[MAXPATHLEN + 1];
673 size_t n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, fp);
674 buf[n] = '\0';
675 fclose(fp);
676
677 size_t dec_len;
678 wchar_t *pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
679 if (!pybuilddir) {
680 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
681 }
682
683 /* Path: <argv0_path> / <pybuilddir content> */
684 if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) {
685 PyMem_RawFree(pybuilddir);
686 return PATHLEN_ERR();
687 }
688 status = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
689 PyMem_RawFree(pybuilddir);
690 if (_PyStatus_EXCEPTION(status)) {
691 return status;
692 }
693
694 *found = -1;
695 return _PyStatus_OK();
696}
697
698
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000699/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000700 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000701*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200702static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200703search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100704 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100705 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000706{
Victor Stinner331a6a52019-05-27 16:39:22 +0200707 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000708
Fred Drakeedabdc12000-07-08 06:16:37 +0000709 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200710 if (pathconfig->home) {
Victor Stinner221fd842019-09-25 02:54:25 +0200711 /* Path: <home> / <lib_python> / "lib-dynload" */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200712 wchar_t *delim = wcschr(pathconfig->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100713 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100714 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
715 return PATHLEN_ERR();
716 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100717 }
718 else {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200719 if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100720 return PATHLEN_ERR();
721 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100722 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200723 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
724 if (_PyStatus_EXCEPTION(status)) {
725 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100726 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200727 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
728 if (_PyStatus_EXCEPTION(status)) {
729 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100730 }
731 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200732 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000733 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000734
Victor Stinner221fd842019-09-25 02:54:25 +0200735 /* Check for pybuilddir.txt */
736 assert(*found == 0);
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200737 status = calculate_pybuilddir(calculate->argv0_path,
738 exec_prefix, exec_prefix_len, found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200739 if (_PyStatus_EXCEPTION(status)) {
740 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100741 }
Victor Stinner221fd842019-09-25 02:54:25 +0200742 if (*found) {
743 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000744 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000745
Fred Drakeedabdc12000-07-08 06:16:37 +0000746 /* Search from argv0_path, until root is found */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200747 status = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200748 if (_PyStatus_EXCEPTION(status)) {
749 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100750 }
751
Fred Drakeedabdc12000-07-08 06:16:37 +0000752 do {
Victor Stinner221fd842019-09-25 02:54:25 +0200753 /* Path: <argv0_path or substring> / <lib_python> / "lib-dynload" */
754 size_t n = wcslen(exec_prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200755 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
756 if (_PyStatus_EXCEPTION(status)) {
757 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100758 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200759 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
760 if (_PyStatus_EXCEPTION(status)) {
761 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100762 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100763 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100764 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200765 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100766 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100767 exec_prefix[n] = L'\0';
768 reduce(exec_prefix);
769 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000770
Victor Stinner221fd842019-09-25 02:54:25 +0200771 /* Look at configure's EXEC_PREFIX.
772
773 Path: <EXEC_PREFIX macro> / <lib_python> / "lib-dynload" */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200774 if (safe_wcscpy(exec_prefix, calculate->exec_prefix_macro, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100775 return PATHLEN_ERR();
776 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200777 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
778 if (_PyStatus_EXCEPTION(status)) {
779 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100780 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200781 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
782 if (_PyStatus_EXCEPTION(status)) {
783 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100784 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100785 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100786 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200787 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100788 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000789
Fred Drakeedabdc12000-07-08 06:16:37 +0000790 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100791 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200792 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000793}
794
Guido van Rossum305e5d01997-04-11 17:18:45 +0000795
Victor Stinner331a6a52019-05-27 16:39:22 +0200796static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200797calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100798{
Victor Stinner331a6a52019-05-27 16:39:22 +0200799 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200800 wchar_t exec_prefix[MAXPATHLEN+1];
801 memset(exec_prefix, 0, sizeof(exec_prefix));
802 size_t exec_prefix_len = Py_ARRAY_LENGTH(exec_prefix);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100803
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200804 status = search_for_exec_prefix(calculate, pathconfig,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200805 exec_prefix, exec_prefix_len,
806 &calculate->exec_prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200807 if (_PyStatus_EXCEPTION(status)) {
808 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100809 }
810
Victor Stinner0327bde2017-11-23 17:03:20 +0100811 if (!calculate->exec_prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200812 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100813 fprintf(stderr,
814 "Could not find platform dependent libraries <exec_prefix>\n");
815 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200816
817 calculate->exec_prefix = joinpath2(calculate->exec_prefix_macro,
818 L"lib/lib-dynload");
819 if (calculate->exec_prefix == NULL) {
820 return _PyStatus_NO_MEMORY();
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100821 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100822 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200823 else {
824 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
825 calculate->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
826 if (calculate->exec_prefix == NULL) {
827 return _PyStatus_NO_MEMORY();
828 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200829 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200830 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100831}
832
833
Victor Stinner331a6a52019-05-27 16:39:22 +0200834static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200835calculate_set_exec_prefix(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200836 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100837{
838 if (calculate->exec_prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200839 wchar_t *exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix);
840 if (exec_prefix == NULL) {
841 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100842 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200843
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200844 reduce(exec_prefix);
845 reduce(exec_prefix);
846 reduce(exec_prefix);
847
848 if (exec_prefix[0]) {
849 pathconfig->exec_prefix = exec_prefix;
850 }
851 else {
852 /* empty string: use SEP instead */
853 PyMem_RawFree(exec_prefix);
854
855 /* The exec_prefix is the root directory, but reduce() chopped
856 off the "/". */
857 pathconfig->exec_prefix = _PyMem_RawWcsdup(separator);
858 if (pathconfig->exec_prefix == NULL) {
859 return _PyStatus_NO_MEMORY();
860 }
861 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100862 }
863 else {
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200864 pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200865 if (pathconfig->exec_prefix == NULL) {
866 return _PyStatus_NO_MEMORY();
867 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100868 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200869 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100870}
871
872
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200873/* Similar to shutil.which().
874 If found, write the path into *abs_path_p. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200875static PyStatus
Victor Stinner03a8a562019-10-04 02:22:39 +0200876calculate_which(const wchar_t *path_env, wchar_t *program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200877 wchar_t **abs_path_p)
Victor Stinner0327bde2017-11-23 17:03:20 +0100878{
Victor Stinner03a8a562019-10-04 02:22:39 +0200879 while (1) {
880 wchar_t *delim = wcschr(path_env, DELIM);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200881 wchar_t *abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200882
883 if (delim) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200884 wchar_t *path = substring(path_env, delim - path_env);
885 if (path == NULL) {
886 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +0200887 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200888 abs_path = joinpath2(path, program_name);
889 PyMem_RawFree(path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200890 }
891 else {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200892 abs_path = joinpath2(path_env, program_name);
Victor Stinner03a8a562019-10-04 02:22:39 +0200893 }
894
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200895 if (abs_path == NULL) {
896 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +0200897 }
898
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200899 if (isxfile(abs_path)) {
900 *abs_path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200901 return _PyStatus_OK();
902 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200903 PyMem_RawFree(abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200904
905 if (!delim) {
906 break;
907 }
908 path_env = delim + 1;
909 }
910
911 /* not found */
912 return _PyStatus_OK();
913}
914
Victor Stinner9316ee42017-11-25 03:17:57 +0100915
Victor Stinnerb9197952017-11-23 19:02:04 +0100916#ifdef __APPLE__
Victor Stinner03a8a562019-10-04 02:22:39 +0200917static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200918calculate_program_macos(wchar_t **abs_path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +0200919{
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100920 char execpath[MAXPATHLEN + 1];
Victor Stinnerb9197952017-11-23 19:02:04 +0100921#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100922 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100923#else
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100924 unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100925#endif
Victor Stinner03a8a562019-10-04 02:22:39 +0200926
927 /* On Mac OS X, if a script uses an interpreter of the form
928 "#!/opt/python2.3/bin/python", the kernel only passes "python"
929 as argv[0], which falls through to the $PATH search below.
930 If /opt/python2.3/bin isn't in your path, or is near the end,
931 this algorithm may incorrectly find /usr/bin/python. To work
932 around this, we can use _NSGetExecutablePath to get a better
933 hint of what the intended interpreter was, although this
934 will fail if a relative path was used. but in that case,
935 absolutize() should help us out below
936 */
937 if (_NSGetExecutablePath(execpath, &nsexeclength) != 0
938 || (wchar_t)execpath[0] != SEP)
939 {
940 /* _NSGetExecutablePath() failed or the path is relative */
941 return _PyStatus_OK();
942 }
943
944 size_t len;
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200945 *abs_path_p = Py_DecodeLocale(execpath, &len);
946 if (*abs_path_p == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +0200947 return DECODE_LOCALE_ERR("executable path", len);
948 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200949 return _PyStatus_OK();
950}
951#endif /* __APPLE__ */
952
953
954static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200955calculate_program_impl(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +0200956{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200957 assert(pathconfig->program_full_path == NULL);
958
Victor Stinner03a8a562019-10-04 02:22:39 +0200959 PyStatus status;
Victor Stinnerb9197952017-11-23 19:02:04 +0100960
Victor Stinner0327bde2017-11-23 17:03:20 +0100961 /* If there is no slash in the argv0 path, then we have to
962 * assume python is on the user's $PATH, since there's no
963 * other way to find a directory to start the search from. If
964 * $PATH isn't exported, you lose.
965 */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200966 if (wcschr(pathconfig->program_name, SEP)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200967 pathconfig->program_full_path = _PyMem_RawWcsdup(pathconfig->program_name);
968 if (pathconfig->program_full_path == NULL) {
969 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100970 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200971 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100972 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200973
Jack Jansen1afd4802004-06-03 14:33:03 +0000974#ifdef __APPLE__
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200975 wchar_t *abs_path = NULL;
976 status = calculate_program_macos(&abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200977 if (_PyStatus_EXCEPTION(status)) {
978 return status;
979 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200980 if (abs_path) {
981 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200982 return _PyStatus_OK();
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000983 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000984#endif /* __APPLE__ */
Jack Jansen55070f52001-12-02 23:56:28 +0000985
Victor Stinner03a8a562019-10-04 02:22:39 +0200986 if (calculate->path_env) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200987 wchar_t *abs_path = NULL;
Victor Stinner03a8a562019-10-04 02:22:39 +0200988 status = calculate_which(calculate->path_env, pathconfig->program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200989 &abs_path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200990 if (_PyStatus_EXCEPTION(status)) {
991 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100992 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200993 if (abs_path) {
994 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200995 return _PyStatus_OK();
996 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100997 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200998
999 /* In the last resort, use an empty string */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001000 pathconfig->program_full_path = _PyMem_RawWcsdup(L"");
1001 if (pathconfig->program_full_path == NULL) {
1002 return _PyStatus_NO_MEMORY();
1003 }
Victor Stinner03a8a562019-10-04 02:22:39 +02001004 return _PyStatus_OK();
1005}
1006
1007
1008/* Calculate pathconfig->program_full_path */
1009static PyStatus
1010calculate_program(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
1011{
1012 PyStatus status;
Victor Stinner03a8a562019-10-04 02:22:39 +02001013
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001014 status = calculate_program_impl(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001015 if (_PyStatus_EXCEPTION(status)) {
1016 return status;
1017 }
1018
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001019 if (pathconfig->program_full_path[0] != '\0') {
Victor Stinner03a8a562019-10-04 02:22:39 +02001020 /* program_full_path is not empty */
1021
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001022 /* Make sure that program_full_path is an absolute path */
1023 if (!_Py_isabs(pathconfig->program_full_path)) {
1024 status = absolutize(&pathconfig->program_full_path);
Victor Stinner03a8a562019-10-04 02:22:39 +02001025 if (_PyStatus_EXCEPTION(status)) {
1026 return status;
1027 }
1028 }
1029
1030#if defined(__CYGWIN__) || defined(__MINGW32__)
1031 /* For these platforms it is necessary to ensure that the .exe suffix
1032 * is appended to the filename, otherwise there is potential for
1033 * sys.executable to return the name of a directory under the same
1034 * path (bpo-28441).
1035 */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001036 status = add_exe_suffix(&pathconfig->program_full_path);
Victor Stinner331a6a52019-05-27 16:39:22 +02001037 if (_PyStatus_EXCEPTION(status)) {
1038 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001039 }
E. M. Bray7a7693e2018-10-05 13:38:50 +02001040#endif
Victor Stinner03a8a562019-10-04 02:22:39 +02001041 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001042 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001043}
1044
1045
Victor Stinner03a8a562019-10-04 02:22:39 +02001046#if HAVE_READLINK
Victor Stinner331a6a52019-05-27 16:39:22 +02001047static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001048resolve_symlinks(wchar_t **path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +02001049{
1050 wchar_t new_path[MAXPATHLEN + 1];
1051 const size_t new_path_len = Py_ARRAY_LENGTH(new_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001052 unsigned int nlink = 0;
Victor Stinner03a8a562019-10-04 02:22:39 +02001053
1054 while (1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001055 int linklen = _Py_wreadlink(*path_p, new_path, new_path_len);
Victor Stinner03a8a562019-10-04 02:22:39 +02001056 if (linklen == -1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001057 /* not a symbolic link: we are done */
Victor Stinner03a8a562019-10-04 02:22:39 +02001058 break;
1059 }
1060
1061 if (_Py_isabs(new_path)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001062 PyMem_RawFree(*path_p);
1063 *path_p = _PyMem_RawWcsdup(new_path);
1064 if (*path_p == NULL) {
1065 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001066 }
1067 }
1068 else {
1069 /* new_path is relative to path */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001070 reduce(*path_p);
1071
1072 wchar_t *abs_path = joinpath2(*path_p, new_path);
1073 if (abs_path == NULL) {
1074 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001075 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001076
1077 PyMem_RawFree(*path_p);
1078 *path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +02001079 }
1080
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001081 nlink++;
Victor Stinner03a8a562019-10-04 02:22:39 +02001082 /* 40 is the Linux kernel 4.2 limit */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001083 if (nlink >= 40) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001084 return _PyStatus_ERR("maximum number of symbolic links reached");
1085 }
1086 }
1087 return _PyStatus_OK();
1088}
1089#endif /* HAVE_READLINK */
1090
1091
1092#ifdef WITH_NEXT_FRAMEWORK
1093static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001094calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +02001095{
1096 NSModule pythonModule;
1097
1098 /* On Mac OS X we have a special case if we're running from a framework.
1099 This is because the python home should be set relative to the library,
1100 which is in the framework, not relative to the executable, which may
1101 be outside of the framework. Except when we're in the build
1102 directory... */
1103 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
1104
1105 /* Use dylib functions to find out where the framework was loaded from */
1106 const char* modPath = NSLibraryNameForModule(pythonModule);
1107 if (modPath == NULL) {
1108 return _PyStatus_OK();
1109 }
1110
1111 /* We're in a framework.
1112 See if we might be in the build directory. The framework in the
1113 build directory is incomplete, it only has the .dylib and a few
1114 needed symlinks, it doesn't have the Lib directories and such.
1115 If we're running with the framework from the build directory we must
1116 be running the interpreter in the build directory, so we use the
1117 build-directory-specific logic to find Lib and such. */
1118 size_t len;
1119 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
1120 if (wbuf == NULL) {
1121 return DECODE_LOCALE_ERR("framework location", len);
1122 }
1123
1124 /* Path: reduce(modPath) / lib_python / LANDMARK */
1125 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001126
1127 wchar_t *parent = _PyMem_RawWcsdup(wbuf);
1128 if (parent == NULL) {
1129 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001130 goto done;
1131 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001132
1133 reduce(parent);
1134 wchar_t *lib_python = joinpath2(path, calculate->lib_python);
1135 PyMem_RawFree(parent);
1136
1137 if (lib_python == NULL) {
1138 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001139 goto done;
1140 }
Victor Stinnerf0c85792019-10-04 03:53:26 +02001141
1142 int module;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001143 status = ismodule(lib_python, &module);
1144 PyMem_RawFree(lib_python);
1145
Victor Stinner03a8a562019-10-04 02:22:39 +02001146 if (_PyStatus_EXCEPTION(status)) {
1147 goto done;
1148 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001149 if (!module) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001150 /* We are in the build directory so use the name of the
1151 executable - we know that the absolute path is passed */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001152 PyMem_RawFree(*calculate->argv0_path);
1153 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1154 if (calculate->argv0_path == NULL) {
1155 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001156 goto done;
1157 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001158
1159 status = _PyStatus_OK();
1160 goto done;
Victor Stinner03a8a562019-10-04 02:22:39 +02001161 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001162
1163 /* Use the location of the library as argv0_path */
1164 PyMem_RawFree(*calculate->argv0_path);
1165 calculate->argv0_path = wbuf
1166 return _PyStatus_OK();
Victor Stinner03a8a562019-10-04 02:22:39 +02001167
1168done:
1169 PyMem_RawFree(wbuf);
1170 return status;
1171}
1172#endif
1173
1174
1175static PyStatus
1176calculate_argv0_path(PyCalculatePath *calculate,
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001177 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001178{
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001179 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001180
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001181 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1182 if (calculate->argv0_path == NULL) {
1183 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001184 }
Jack Jansen55070f52001-12-02 23:56:28 +00001185
Guido van Rossum54ecc3d1999-01-27 17:53:11 +00001186#ifdef WITH_NEXT_FRAMEWORK
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001187 status = calculate_argv0_path_framework(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001188 if (_PyStatus_EXCEPTION(status)) {
1189 return status;
Fred Drakeedabdc12000-07-08 06:16:37 +00001190 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +00001191#endif
Guido van Rossume296ced2001-09-28 20:00:29 +00001192
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001193 status = resolve_symlinks(&calculate->argv0_path);
1194 if (_PyStatus_EXCEPTION(status)) {
1195 return status;
1196 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001197
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001198 reduce(calculate->argv0_path);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001199
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001200 return _PyStatus_OK();
1201}
1202
1203
1204static PyStatus
1205calculate_open_pyenv(PyCalculatePath *calculate, FILE **env_file_p)
1206{
1207 *env_file_p = NULL;
1208
1209 const wchar_t *env_cfg = L"pyvenv.cfg";
1210
1211 /* Filename: <argv0_path> / "pyvenv.cfg" */
1212 wchar_t *filename = joinpath2(calculate->argv0_path, env_cfg);
1213 if (filename == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001214 return _PyStatus_NO_MEMORY();
1215 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001216
1217 *env_file_p = _Py_wfopen(filename, L"r");
1218 PyMem_RawFree(filename);
1219
1220 if (*env_file_p != NULL) {
1221 return _PyStatus_OK();
1222
1223 }
1224
1225 /* fopen() failed: reset errno */
1226 errno = 0;
1227
1228 /* Path: <basename(argv0_path)> / "pyvenv.cfg" */
1229 wchar_t *parent = _PyMem_RawWcsdup(calculate->argv0_path);
1230 if (parent == NULL) {
1231 return _PyStatus_NO_MEMORY();
1232 }
1233 reduce(parent);
1234
1235 filename = joinpath2(parent, env_cfg);
1236 PyMem_RawFree(parent);
1237 if (filename == NULL) {
1238 return _PyStatus_NO_MEMORY();
1239 }
1240
1241 *env_file_p = _Py_wfopen(filename, L"r");
1242 PyMem_RawFree(filename);
1243
1244 if (*env_file_p == NULL) {
1245 /* fopen() failed: reset errno */
1246 errno = 0;
1247 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001248 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001249}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001250
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001251
Victor Stinner0327bde2017-11-23 17:03:20 +01001252/* Search for an "pyvenv.cfg" environment configuration file, first in the
1253 executable's directory and then in the parent directory.
1254 If found, open it for use when searching for prefixes.
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001255
1256 Write the 'home' variable of pyvenv.cfg into calculate->argv0_path. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001257static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001258calculate_read_pyenv(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001259{
Victor Stinner331a6a52019-05-27 16:39:22 +02001260 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001261 FILE *env_file = NULL;
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001262
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001263 status = calculate_open_pyenv(calculate, &env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001264 if (_PyStatus_EXCEPTION(status)) {
1265 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001266 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001267 if (env_file == NULL) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001268 /* pyvenv.cfg not found */
1269 return _PyStatus_OK();
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001270 }
1271
Victor Stinner0327bde2017-11-23 17:03:20 +01001272 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001273 wchar_t *home = NULL;
1274 status = _Py_FindEnvConfigValue(env_file, L"home", &home);
1275 if (_PyStatus_EXCEPTION(status)) {
1276 fclose(env_file);
1277 return status;
1278 }
Victor Stinner221fd842019-09-25 02:54:25 +02001279
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001280 if (home) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001281 PyMem_RawFree(calculate->argv0_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001282 calculate->argv0_path = home;
Just van Rossum52e14d62002-12-30 22:08:05 +00001283 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001284 fclose(env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001285 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001286}
Just van Rossum52e14d62002-12-30 22:08:05 +00001287
Guido van Rossum305e5d01997-04-11 17:18:45 +00001288
Victor Stinner331a6a52019-05-27 16:39:22 +02001289static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001290calculate_zip_path(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001291{
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001292 const wchar_t *lib_python = L"lib/python00.zip";
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001293
Victor Stinner0327bde2017-11-23 17:03:20 +01001294 if (calculate->prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001295 /* Use the reduced prefix returned by Py_GetPrefix()
1296
1297 Path: <basename(basename(prefix))> / <lib_python> */
1298 wchar_t *parent = _PyMem_RawWcsdup(calculate->prefix);
1299 if (parent == NULL) {
1300 return _PyStatus_NO_MEMORY();
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001301 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001302 reduce(parent);
1303 reduce(parent);
1304 calculate->zip_path = joinpath2(parent, lib_python);
1305 PyMem_RawFree(parent);
Victor Stinnerd4341102017-11-23 00:12:09 +01001306 }
1307 else {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001308 calculate->zip_path = joinpath2(calculate->prefix_macro, lib_python);
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001309 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001310
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001311 if (calculate->zip_path == NULL) {
1312 return _PyStatus_NO_MEMORY();
1313 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001314
1315 /* Replace "00" with version */
1316 size_t len = wcslen(calculate->zip_path);
1317 calculate->zip_path[len - 6] = VERSION[0];
1318 calculate->zip_path[len - 5] = VERSION[2];
1319
Victor Stinner331a6a52019-05-27 16:39:22 +02001320 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001321}
1322
1323
Victor Stinner331a6a52019-05-27 16:39:22 +02001324static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001325calculate_module_search_path(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001326 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001327{
1328 /* Calculate size of return buffer */
1329 size_t bufsz = 0;
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001330 if (calculate->pythonpath_env != NULL) {
1331 bufsz += wcslen(calculate->pythonpath_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001332 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001333
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001334 wchar_t *defpath = calculate->pythonpath_macro;
1335 size_t prefixsz = wcslen(calculate->prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001336 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001337 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001338
Victor Stinner3939c322019-06-25 15:02:43 +02001339 if (!_Py_isabs(defpath)) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001340 /* Paths are relative to prefix */
1341 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001342 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001343
Victor Stinner0327bde2017-11-23 17:03:20 +01001344 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001345 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001346 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001347 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001348 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001349 break;
1350 }
1351 defpath = delim + 1;
1352 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001353
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001354 bufsz += wcslen(calculate->zip_path) + 1;
1355 bufsz += wcslen(calculate->exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001356
Victor Stinner0327bde2017-11-23 17:03:20 +01001357 /* Allocate the buffer */
1358 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001359 if (buf == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +02001360 return _PyStatus_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001361 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001362 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001363
Victor Stinner72967a42013-11-16 01:22:04 +01001364 /* Run-time value of $PYTHONPATH goes first */
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001365 if (calculate->pythonpath_env) {
1366 wcscpy(buf, calculate->pythonpath_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001367 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001368 }
Victor Stinner72967a42013-11-16 01:22:04 +01001369
1370 /* Next is the default zip path */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001371 wcscat(buf, calculate->zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001372 wcscat(buf, delimiter);
1373
1374 /* Next goes merge of compile-time $PYTHONPATH with
1375 * dynamically located prefix.
1376 */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001377 defpath = calculate->pythonpath_macro;
Victor Stinner72967a42013-11-16 01:22:04 +01001378 while (1) {
1379 wchar_t *delim = wcschr(defpath, DELIM);
1380
Victor Stinner3939c322019-06-25 15:02:43 +02001381 if (!_Py_isabs(defpath)) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001382 wcscat(buf, calculate->prefix);
1383 if (prefixsz >= 2 && calculate->prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001384 defpath[0] != (delim ? DELIM : L'\0'))
1385 {
1386 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001387 wcscat(buf, separator);
1388 }
Victor Stinner72967a42013-11-16 01:22:04 +01001389 }
1390
1391 if (delim) {
1392 size_t len = delim - defpath + 1;
1393 size_t end = wcslen(buf) + len;
1394 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001395 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001396 }
1397 else {
1398 wcscat(buf, defpath);
1399 break;
1400 }
1401 defpath = delim + 1;
1402 }
1403 wcscat(buf, delimiter);
1404
1405 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001406 wcscat(buf, calculate->exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001407
Victor Stinner331a6a52019-05-27 16:39:22 +02001408 pathconfig->module_search_path = buf;
1409 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001410}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001411
Victor Stinner0327bde2017-11-23 17:03:20 +01001412
Victor Stinner331a6a52019-05-27 16:39:22 +02001413static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +02001414calculate_init(PyCalculatePath *calculate, const PyConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001415{
Victor Stinner0327bde2017-11-23 17:03:20 +01001416 size_t len;
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001417 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001418 if (path) {
1419 calculate->path_env = Py_DecodeLocale(path, &len);
1420 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001421 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001422 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001423 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001424
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001425 /* Decode macros */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001426 calculate->pythonpath_macro = Py_DecodeLocale(PYTHONPATH, &len);
1427 if (!calculate->pythonpath_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001428 return DECODE_LOCALE_ERR("PYTHONPATH macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001429 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001430 calculate->prefix_macro = Py_DecodeLocale(PREFIX, &len);
1431 if (!calculate->prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001432 return DECODE_LOCALE_ERR("PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001433 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001434 calculate->exec_prefix_macro = Py_DecodeLocale(EXEC_PREFIX, &len);
1435 if (!calculate->exec_prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001436 return DECODE_LOCALE_ERR("EXEC_PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001437 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001438 calculate->vpath_macro = Py_DecodeLocale(VPATH, &len);
1439 if (!calculate->vpath_macro) {
1440 return DECODE_LOCALE_ERR("VPATH macro", len);
1441 }
1442
Victor Stinner0327bde2017-11-23 17:03:20 +01001443 calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
1444 if (!calculate->lib_python) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001445 return DECODE_LOCALE_ERR("EXEC_PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001446 }
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001447
1448 calculate->warnings = config->pathconfig_warnings;
1449 calculate->pythonpath_env = config->pythonpath_env;
1450
Victor Stinner331a6a52019-05-27 16:39:22 +02001451 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001452}
1453
1454
1455static void
1456calculate_free(PyCalculatePath *calculate)
1457{
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001458 PyMem_RawFree(calculate->pythonpath_macro);
1459 PyMem_RawFree(calculate->prefix_macro);
1460 PyMem_RawFree(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001461 PyMem_RawFree(calculate->vpath_macro);
Victor Stinner0327bde2017-11-23 17:03:20 +01001462 PyMem_RawFree(calculate->lib_python);
1463 PyMem_RawFree(calculate->path_env);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001464 PyMem_RawFree(calculate->zip_path);
1465 PyMem_RawFree(calculate->argv0_path);
1466 PyMem_RawFree(calculate->prefix);
1467 PyMem_RawFree(calculate->exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +01001468}
1469
1470
Victor Stinner331a6a52019-05-27 16:39:22 +02001471static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001472calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001473{
Victor Stinner331a6a52019-05-27 16:39:22 +02001474 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +01001475
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001476 if (pathconfig->program_full_path == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001477 status = calculate_program(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001478 if (_PyStatus_EXCEPTION(status)) {
1479 return status;
1480 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001481 }
1482
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001483 status = calculate_argv0_path(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001484 if (_PyStatus_EXCEPTION(status)) {
1485 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001486 }
1487
Victor Stinner221fd842019-09-25 02:54:25 +02001488 /* If a pyvenv.cfg configure file is found,
1489 argv0_path is overriden with its 'home' variable. */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001490 status = calculate_read_pyenv(calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001491 if (_PyStatus_EXCEPTION(status)) {
1492 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001493 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001494
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001495 status = calculate_prefix(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001496 if (_PyStatus_EXCEPTION(status)) {
1497 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001498 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001499
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001500 status = calculate_zip_path(calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001501 if (_PyStatus_EXCEPTION(status)) {
1502 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001503 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001504
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001505 status = calculate_exec_prefix(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001506 if (_PyStatus_EXCEPTION(status)) {
1507 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001508 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001509
Victor Stinner03a8a562019-10-04 02:22:39 +02001510 if ((!calculate->prefix_found || !calculate->exec_prefix_found)
1511 && calculate->warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001512 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001513 fprintf(stderr,
1514 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1515 }
1516
Victor Stinnere2677932019-09-21 01:50:16 +02001517 if (pathconfig->module_search_path == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001518 status = calculate_module_search_path(calculate, pathconfig);
Victor Stinnere2677932019-09-21 01:50:16 +02001519 if (_PyStatus_EXCEPTION(status)) {
1520 return status;
1521 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001522 }
1523
Victor Stinner331a6a52019-05-27 16:39:22 +02001524 if (pathconfig->prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001525 status = calculate_set_prefix(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001526 if (_PyStatus_EXCEPTION(status)) {
1527 return status;
1528 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001529 }
1530
Victor Stinner331a6a52019-05-27 16:39:22 +02001531 if (pathconfig->exec_prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001532 status = calculate_set_exec_prefix(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001533 if (_PyStatus_EXCEPTION(status)) {
1534 return status;
1535 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001536 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001537 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001538}
1539
1540
Victor Stinner85ce0a72019-09-24 00:55:48 +02001541/* Calculate the Python path configuration.
1542
1543 Inputs:
1544
1545 - PATH environment variable
1546 - Macros: PYTHONPATH, PREFIX, EXEC_PREFIX, VERSION (ex: "3.9").
1547 PREFIX and EXEC_PREFIX are generated by the configure script.
1548 PYTHONPATH macro is the default search path.
1549 - pybuilddir.txt file
1550 - pyvenv.cfg configuration file
1551 - PyConfig fields ('config' function argument):
1552
1553 - pathconfig_warnings
1554 - pythonpath_env (PYTHONPATH environment variable)
1555
1556 - _PyPathConfig fields ('pathconfig' function argument):
1557
1558 - program_name: see config_init_program_name()
1559 - home: Py_SetPythonHome() or PYTHONHOME environment variable
1560
1561 - current working directory: see copy_absolute()
1562
1563 Outputs, 'pathconfig' fields:
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001564
1565 - program_full_path
1566 - module_search_path
1567 - prefix
1568 - exec_prefix
1569
Victor Stinner85ce0a72019-09-24 00:55:48 +02001570 If a field is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001571PyStatus
1572_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001573{
Victor Stinner331a6a52019-05-27 16:39:22 +02001574 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001575 PyCalculatePath calculate;
1576 memset(&calculate, 0, sizeof(calculate));
1577
Victor Stinner331a6a52019-05-27 16:39:22 +02001578 status = calculate_init(&calculate, config);
1579 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001580 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001581 }
1582
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001583 status = calculate_path(&calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001584 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001585 goto done;
1586 }
1587
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001588 /* program_full_path must an either an empty string or an absolute path */
1589 assert(wcslen(pathconfig->program_full_path) == 0
1590 || _Py_isabs(pathconfig->program_full_path));
1591
Victor Stinner331a6a52019-05-27 16:39:22 +02001592 status = _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001593
Victor Stinner9316ee42017-11-25 03:17:57 +01001594done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001595 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001596 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001597}
Victor Stinner46972b72017-11-24 22:55:40 +01001598
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001599#ifdef __cplusplus
1600}
1601#endif