blob: 8632d1fe6d80f026e98dfaca136f6230f6cd96cc [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
Victor Stinner221fd842019-09-25 02:54:25 +0200660 FILE *fp = _Py_wfopen(filename, L"rb");
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200661 PyMem_RawFree(filename);
Victor Stinner221fd842019-09-25 02:54:25 +0200662 if (fp == NULL) {
663 errno = 0;
664 return _PyStatus_OK();
665 }
666
667 char buf[MAXPATHLEN + 1];
668 size_t n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, fp);
669 buf[n] = '\0';
670 fclose(fp);
671
672 size_t dec_len;
673 wchar_t *pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
674 if (!pybuilddir) {
675 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
676 }
677
678 /* Path: <argv0_path> / <pybuilddir content> */
679 if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) {
680 PyMem_RawFree(pybuilddir);
681 return PATHLEN_ERR();
682 }
683 status = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
684 PyMem_RawFree(pybuilddir);
685 if (_PyStatus_EXCEPTION(status)) {
686 return status;
687 }
688
689 *found = -1;
690 return _PyStatus_OK();
691}
692
693
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000694/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000695 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000696*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200697static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200698search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100699 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100700 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000701{
Victor Stinner331a6a52019-05-27 16:39:22 +0200702 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000703
Fred Drakeedabdc12000-07-08 06:16:37 +0000704 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200705 if (pathconfig->home) {
Victor Stinner221fd842019-09-25 02:54:25 +0200706 /* Path: <home> / <lib_python> / "lib-dynload" */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200707 wchar_t *delim = wcschr(pathconfig->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100708 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100709 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
710 return PATHLEN_ERR();
711 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100712 }
713 else {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200714 if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100715 return PATHLEN_ERR();
716 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100717 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200718 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
719 if (_PyStatus_EXCEPTION(status)) {
720 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100721 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200722 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
723 if (_PyStatus_EXCEPTION(status)) {
724 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100725 }
726 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200727 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000728 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000729
Victor Stinner221fd842019-09-25 02:54:25 +0200730 /* Check for pybuilddir.txt */
731 assert(*found == 0);
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200732 status = calculate_pybuilddir(calculate->argv0_path,
733 exec_prefix, exec_prefix_len, found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200734 if (_PyStatus_EXCEPTION(status)) {
735 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100736 }
Victor Stinner221fd842019-09-25 02:54:25 +0200737 if (*found) {
738 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000739 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000740
Fred Drakeedabdc12000-07-08 06:16:37 +0000741 /* Search from argv0_path, until root is found */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200742 status = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200743 if (_PyStatus_EXCEPTION(status)) {
744 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100745 }
746
Fred Drakeedabdc12000-07-08 06:16:37 +0000747 do {
Victor Stinner221fd842019-09-25 02:54:25 +0200748 /* Path: <argv0_path or substring> / <lib_python> / "lib-dynload" */
749 size_t n = wcslen(exec_prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200750 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
751 if (_PyStatus_EXCEPTION(status)) {
752 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100753 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200754 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
755 if (_PyStatus_EXCEPTION(status)) {
756 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100757 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100758 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100759 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200760 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100761 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100762 exec_prefix[n] = L'\0';
763 reduce(exec_prefix);
764 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000765
Victor Stinner221fd842019-09-25 02:54:25 +0200766 /* Look at configure's EXEC_PREFIX.
767
768 Path: <EXEC_PREFIX macro> / <lib_python> / "lib-dynload" */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200769 if (safe_wcscpy(exec_prefix, calculate->exec_prefix_macro, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100770 return PATHLEN_ERR();
771 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200772 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
773 if (_PyStatus_EXCEPTION(status)) {
774 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100775 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200776 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
777 if (_PyStatus_EXCEPTION(status)) {
778 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100779 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100780 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100781 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200782 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100783 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000784
Fred Drakeedabdc12000-07-08 06:16:37 +0000785 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100786 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200787 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000788}
789
Guido van Rossum305e5d01997-04-11 17:18:45 +0000790
Victor Stinner331a6a52019-05-27 16:39:22 +0200791static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200792calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100793{
Victor Stinner331a6a52019-05-27 16:39:22 +0200794 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200795 wchar_t exec_prefix[MAXPATHLEN+1];
796 memset(exec_prefix, 0, sizeof(exec_prefix));
797 size_t exec_prefix_len = Py_ARRAY_LENGTH(exec_prefix);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100798
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200799 status = search_for_exec_prefix(calculate, pathconfig,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200800 exec_prefix, exec_prefix_len,
801 &calculate->exec_prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200802 if (_PyStatus_EXCEPTION(status)) {
803 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100804 }
805
Victor Stinner0327bde2017-11-23 17:03:20 +0100806 if (!calculate->exec_prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200807 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100808 fprintf(stderr,
809 "Could not find platform dependent libraries <exec_prefix>\n");
810 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200811
812 calculate->exec_prefix = joinpath2(calculate->exec_prefix_macro,
813 L"lib/lib-dynload");
814 if (calculate->exec_prefix == NULL) {
815 return _PyStatus_NO_MEMORY();
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100816 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100817 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200818 else {
819 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
820 calculate->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
821 if (calculate->exec_prefix == NULL) {
822 return _PyStatus_NO_MEMORY();
823 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200824 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200825 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100826}
827
828
Victor Stinner331a6a52019-05-27 16:39:22 +0200829static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200830calculate_set_exec_prefix(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200831 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100832{
833 if (calculate->exec_prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200834 wchar_t *exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix);
835 if (exec_prefix == NULL) {
836 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100837 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200838
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200839 reduce(exec_prefix);
840 reduce(exec_prefix);
841 reduce(exec_prefix);
842
843 if (exec_prefix[0]) {
844 pathconfig->exec_prefix = exec_prefix;
845 }
846 else {
847 /* empty string: use SEP instead */
848 PyMem_RawFree(exec_prefix);
849
850 /* The exec_prefix is the root directory, but reduce() chopped
851 off the "/". */
852 pathconfig->exec_prefix = _PyMem_RawWcsdup(separator);
853 if (pathconfig->exec_prefix == NULL) {
854 return _PyStatus_NO_MEMORY();
855 }
856 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100857 }
858 else {
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200859 pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200860 if (pathconfig->exec_prefix == NULL) {
861 return _PyStatus_NO_MEMORY();
862 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100863 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200864 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100865}
866
867
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200868/* Similar to shutil.which().
869 If found, write the path into *abs_path_p. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200870static PyStatus
Victor Stinner03a8a562019-10-04 02:22:39 +0200871calculate_which(const wchar_t *path_env, wchar_t *program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200872 wchar_t **abs_path_p)
Victor Stinner0327bde2017-11-23 17:03:20 +0100873{
Victor Stinner03a8a562019-10-04 02:22:39 +0200874 while (1) {
875 wchar_t *delim = wcschr(path_env, DELIM);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200876 wchar_t *abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200877
878 if (delim) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200879 wchar_t *path = substring(path_env, delim - path_env);
880 if (path == NULL) {
881 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +0200882 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200883 abs_path = joinpath2(path, program_name);
884 PyMem_RawFree(path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200885 }
886 else {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200887 abs_path = joinpath2(path_env, program_name);
Victor Stinner03a8a562019-10-04 02:22:39 +0200888 }
889
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200890 if (abs_path == NULL) {
891 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +0200892 }
893
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200894 if (isxfile(abs_path)) {
895 *abs_path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200896 return _PyStatus_OK();
897 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200898 PyMem_RawFree(abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200899
900 if (!delim) {
901 break;
902 }
903 path_env = delim + 1;
904 }
905
906 /* not found */
907 return _PyStatus_OK();
908}
909
Victor Stinner9316ee42017-11-25 03:17:57 +0100910
Victor Stinnerb9197952017-11-23 19:02:04 +0100911#ifdef __APPLE__
Victor Stinner03a8a562019-10-04 02:22:39 +0200912static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200913calculate_program_macos(wchar_t **abs_path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +0200914{
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100915 char execpath[MAXPATHLEN + 1];
Victor Stinnerb9197952017-11-23 19:02:04 +0100916#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100917 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100918#else
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100919 unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100920#endif
Victor Stinner03a8a562019-10-04 02:22:39 +0200921
922 /* On Mac OS X, if a script uses an interpreter of the form
923 "#!/opt/python2.3/bin/python", the kernel only passes "python"
924 as argv[0], which falls through to the $PATH search below.
925 If /opt/python2.3/bin isn't in your path, or is near the end,
926 this algorithm may incorrectly find /usr/bin/python. To work
927 around this, we can use _NSGetExecutablePath to get a better
928 hint of what the intended interpreter was, although this
929 will fail if a relative path was used. but in that case,
930 absolutize() should help us out below
931 */
932 if (_NSGetExecutablePath(execpath, &nsexeclength) != 0
933 || (wchar_t)execpath[0] != SEP)
934 {
935 /* _NSGetExecutablePath() failed or the path is relative */
936 return _PyStatus_OK();
937 }
938
939 size_t len;
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200940 *abs_path_p = Py_DecodeLocale(execpath, &len);
941 if (*abs_path_p == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +0200942 return DECODE_LOCALE_ERR("executable path", len);
943 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200944 return _PyStatus_OK();
945}
946#endif /* __APPLE__ */
947
948
949static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200950calculate_program_impl(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +0200951{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200952 assert(pathconfig->program_full_path == NULL);
953
Victor Stinner03a8a562019-10-04 02:22:39 +0200954 PyStatus status;
Victor Stinnerb9197952017-11-23 19:02:04 +0100955
Victor Stinner0327bde2017-11-23 17:03:20 +0100956 /* If there is no slash in the argv0 path, then we have to
957 * assume python is on the user's $PATH, since there's no
958 * other way to find a directory to start the search from. If
959 * $PATH isn't exported, you lose.
960 */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200961 if (wcschr(pathconfig->program_name, SEP)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200962 pathconfig->program_full_path = _PyMem_RawWcsdup(pathconfig->program_name);
963 if (pathconfig->program_full_path == NULL) {
964 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100965 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200966 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100967 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200968
Jack Jansen1afd4802004-06-03 14:33:03 +0000969#ifdef __APPLE__
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200970 wchar_t *abs_path = NULL;
971 status = calculate_program_macos(&abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200972 if (_PyStatus_EXCEPTION(status)) {
973 return status;
974 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200975 if (abs_path) {
976 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200977 return _PyStatus_OK();
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000978 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000979#endif /* __APPLE__ */
Jack Jansen55070f52001-12-02 23:56:28 +0000980
Victor Stinner03a8a562019-10-04 02:22:39 +0200981 if (calculate->path_env) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200982 wchar_t *abs_path = NULL;
Victor Stinner03a8a562019-10-04 02:22:39 +0200983 status = calculate_which(calculate->path_env, pathconfig->program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200984 &abs_path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200985 if (_PyStatus_EXCEPTION(status)) {
986 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100987 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200988 if (abs_path) {
989 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200990 return _PyStatus_OK();
991 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100992 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200993
994 /* In the last resort, use an empty string */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200995 pathconfig->program_full_path = _PyMem_RawWcsdup(L"");
996 if (pathconfig->program_full_path == NULL) {
997 return _PyStatus_NO_MEMORY();
998 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200999 return _PyStatus_OK();
1000}
1001
1002
1003/* Calculate pathconfig->program_full_path */
1004static PyStatus
1005calculate_program(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
1006{
1007 PyStatus status;
Victor Stinner03a8a562019-10-04 02:22:39 +02001008
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001009 status = calculate_program_impl(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001010 if (_PyStatus_EXCEPTION(status)) {
1011 return status;
1012 }
1013
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001014 if (pathconfig->program_full_path[0] != '\0') {
Victor Stinner03a8a562019-10-04 02:22:39 +02001015 /* program_full_path is not empty */
1016
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001017 /* Make sure that program_full_path is an absolute path */
1018 if (!_Py_isabs(pathconfig->program_full_path)) {
1019 status = absolutize(&pathconfig->program_full_path);
Victor Stinner03a8a562019-10-04 02:22:39 +02001020 if (_PyStatus_EXCEPTION(status)) {
1021 return status;
1022 }
1023 }
1024
1025#if defined(__CYGWIN__) || defined(__MINGW32__)
1026 /* For these platforms it is necessary to ensure that the .exe suffix
1027 * is appended to the filename, otherwise there is potential for
1028 * sys.executable to return the name of a directory under the same
1029 * path (bpo-28441).
1030 */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001031 status = add_exe_suffix(&pathconfig->program_full_path);
Victor Stinner331a6a52019-05-27 16:39:22 +02001032 if (_PyStatus_EXCEPTION(status)) {
1033 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001034 }
E. M. Bray7a7693e2018-10-05 13:38:50 +02001035#endif
Victor Stinner03a8a562019-10-04 02:22:39 +02001036 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001037 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001038}
1039
1040
Victor Stinner03a8a562019-10-04 02:22:39 +02001041#if HAVE_READLINK
Victor Stinner331a6a52019-05-27 16:39:22 +02001042static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001043resolve_symlinks(wchar_t **path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +02001044{
1045 wchar_t new_path[MAXPATHLEN + 1];
1046 const size_t new_path_len = Py_ARRAY_LENGTH(new_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001047 unsigned int nlink = 0;
Victor Stinner03a8a562019-10-04 02:22:39 +02001048
1049 while (1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001050 int linklen = _Py_wreadlink(*path_p, new_path, new_path_len);
Victor Stinner03a8a562019-10-04 02:22:39 +02001051 if (linklen == -1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001052 /* not a symbolic link: we are done */
Victor Stinner03a8a562019-10-04 02:22:39 +02001053 break;
1054 }
1055
1056 if (_Py_isabs(new_path)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001057 PyMem_RawFree(*path_p);
1058 *path_p = _PyMem_RawWcsdup(new_path);
1059 if (*path_p == NULL) {
1060 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001061 }
1062 }
1063 else {
1064 /* new_path is relative to path */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001065 reduce(*path_p);
1066
1067 wchar_t *abs_path = joinpath2(*path_p, new_path);
1068 if (abs_path == NULL) {
1069 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001070 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001071
1072 PyMem_RawFree(*path_p);
1073 *path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +02001074 }
1075
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001076 nlink++;
Victor Stinner03a8a562019-10-04 02:22:39 +02001077 /* 40 is the Linux kernel 4.2 limit */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001078 if (nlink >= 40) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001079 return _PyStatus_ERR("maximum number of symbolic links reached");
1080 }
1081 }
1082 return _PyStatus_OK();
1083}
1084#endif /* HAVE_READLINK */
1085
1086
1087#ifdef WITH_NEXT_FRAMEWORK
1088static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001089calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +02001090{
1091 NSModule pythonModule;
1092
1093 /* On Mac OS X we have a special case if we're running from a framework.
1094 This is because the python home should be set relative to the library,
1095 which is in the framework, not relative to the executable, which may
1096 be outside of the framework. Except when we're in the build
1097 directory... */
1098 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
1099
1100 /* Use dylib functions to find out where the framework was loaded from */
1101 const char* modPath = NSLibraryNameForModule(pythonModule);
1102 if (modPath == NULL) {
1103 return _PyStatus_OK();
1104 }
1105
1106 /* We're in a framework.
1107 See if we might be in the build directory. The framework in the
1108 build directory is incomplete, it only has the .dylib and a few
1109 needed symlinks, it doesn't have the Lib directories and such.
1110 If we're running with the framework from the build directory we must
1111 be running the interpreter in the build directory, so we use the
1112 build-directory-specific logic to find Lib and such. */
1113 size_t len;
1114 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
1115 if (wbuf == NULL) {
1116 return DECODE_LOCALE_ERR("framework location", len);
1117 }
1118
1119 /* Path: reduce(modPath) / lib_python / LANDMARK */
1120 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001121
1122 wchar_t *parent = _PyMem_RawWcsdup(wbuf);
1123 if (parent == NULL) {
1124 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001125 goto done;
1126 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001127
1128 reduce(parent);
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001129 wchar_t *lib_python = joinpath2(parent, calculate->lib_python);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001130 PyMem_RawFree(parent);
1131
1132 if (lib_python == NULL) {
1133 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001134 goto done;
1135 }
Victor Stinnerf0c85792019-10-04 03:53:26 +02001136
1137 int module;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001138 status = ismodule(lib_python, &module);
1139 PyMem_RawFree(lib_python);
1140
Victor Stinner03a8a562019-10-04 02:22:39 +02001141 if (_PyStatus_EXCEPTION(status)) {
1142 goto done;
1143 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001144 if (!module) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001145 /* We are in the build directory so use the name of the
1146 executable - we know that the absolute path is passed */
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001147 PyMem_RawFree(calculate->argv0_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001148 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1149 if (calculate->argv0_path == NULL) {
1150 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001151 goto done;
1152 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001153
1154 status = _PyStatus_OK();
1155 goto done;
Victor Stinner03a8a562019-10-04 02:22:39 +02001156 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001157
1158 /* Use the location of the library as argv0_path */
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001159 PyMem_RawFree(calculate->argv0_path);
1160 calculate->argv0_path = wbuf;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001161 return _PyStatus_OK();
Victor Stinner03a8a562019-10-04 02:22:39 +02001162
1163done:
1164 PyMem_RawFree(wbuf);
1165 return status;
1166}
1167#endif
1168
1169
1170static PyStatus
1171calculate_argv0_path(PyCalculatePath *calculate,
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001172 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001173{
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001174 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001175
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001176 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1177 if (calculate->argv0_path == NULL) {
1178 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001179 }
Jack Jansen55070f52001-12-02 23:56:28 +00001180
Guido van Rossum54ecc3d1999-01-27 17:53:11 +00001181#ifdef WITH_NEXT_FRAMEWORK
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001182 status = calculate_argv0_path_framework(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001183 if (_PyStatus_EXCEPTION(status)) {
1184 return status;
Fred Drakeedabdc12000-07-08 06:16:37 +00001185 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +00001186#endif
Guido van Rossume296ced2001-09-28 20:00:29 +00001187
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001188 status = resolve_symlinks(&calculate->argv0_path);
1189 if (_PyStatus_EXCEPTION(status)) {
1190 return status;
1191 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001192
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001193 reduce(calculate->argv0_path);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001194
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001195 return _PyStatus_OK();
1196}
1197
1198
1199static PyStatus
1200calculate_open_pyenv(PyCalculatePath *calculate, FILE **env_file_p)
1201{
1202 *env_file_p = NULL;
1203
1204 const wchar_t *env_cfg = L"pyvenv.cfg";
1205
1206 /* Filename: <argv0_path> / "pyvenv.cfg" */
1207 wchar_t *filename = joinpath2(calculate->argv0_path, env_cfg);
1208 if (filename == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001209 return _PyStatus_NO_MEMORY();
1210 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001211
1212 *env_file_p = _Py_wfopen(filename, L"r");
1213 PyMem_RawFree(filename);
1214
1215 if (*env_file_p != NULL) {
1216 return _PyStatus_OK();
1217
1218 }
1219
1220 /* fopen() failed: reset errno */
1221 errno = 0;
1222
1223 /* Path: <basename(argv0_path)> / "pyvenv.cfg" */
1224 wchar_t *parent = _PyMem_RawWcsdup(calculate->argv0_path);
1225 if (parent == NULL) {
1226 return _PyStatus_NO_MEMORY();
1227 }
1228 reduce(parent);
1229
1230 filename = joinpath2(parent, env_cfg);
1231 PyMem_RawFree(parent);
1232 if (filename == NULL) {
1233 return _PyStatus_NO_MEMORY();
1234 }
1235
1236 *env_file_p = _Py_wfopen(filename, L"r");
1237 PyMem_RawFree(filename);
1238
1239 if (*env_file_p == NULL) {
1240 /* fopen() failed: reset errno */
1241 errno = 0;
1242 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001243 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001244}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001245
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001246
Victor Stinner0327bde2017-11-23 17:03:20 +01001247/* Search for an "pyvenv.cfg" environment configuration file, first in the
1248 executable's directory and then in the parent directory.
1249 If found, open it for use when searching for prefixes.
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001250
1251 Write the 'home' variable of pyvenv.cfg into calculate->argv0_path. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001252static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001253calculate_read_pyenv(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001254{
Victor Stinner331a6a52019-05-27 16:39:22 +02001255 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001256 FILE *env_file = NULL;
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001257
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001258 status = calculate_open_pyenv(calculate, &env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001259 if (_PyStatus_EXCEPTION(status)) {
1260 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001261 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001262 if (env_file == NULL) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001263 /* pyvenv.cfg not found */
1264 return _PyStatus_OK();
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001265 }
1266
Victor Stinner0327bde2017-11-23 17:03:20 +01001267 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001268 wchar_t *home = NULL;
1269 status = _Py_FindEnvConfigValue(env_file, L"home", &home);
1270 if (_PyStatus_EXCEPTION(status)) {
1271 fclose(env_file);
1272 return status;
1273 }
Victor Stinner221fd842019-09-25 02:54:25 +02001274
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001275 if (home) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001276 PyMem_RawFree(calculate->argv0_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001277 calculate->argv0_path = home;
Just van Rossum52e14d62002-12-30 22:08:05 +00001278 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001279 fclose(env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001280 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001281}
Just van Rossum52e14d62002-12-30 22:08:05 +00001282
Guido van Rossum305e5d01997-04-11 17:18:45 +00001283
Victor Stinner331a6a52019-05-27 16:39:22 +02001284static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001285calculate_zip_path(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001286{
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001287 const wchar_t *lib_python = L"lib/python00.zip";
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001288
Victor Stinner0327bde2017-11-23 17:03:20 +01001289 if (calculate->prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001290 /* Use the reduced prefix returned by Py_GetPrefix()
1291
1292 Path: <basename(basename(prefix))> / <lib_python> */
1293 wchar_t *parent = _PyMem_RawWcsdup(calculate->prefix);
1294 if (parent == NULL) {
1295 return _PyStatus_NO_MEMORY();
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001296 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001297 reduce(parent);
1298 reduce(parent);
1299 calculate->zip_path = joinpath2(parent, lib_python);
1300 PyMem_RawFree(parent);
Victor Stinnerd4341102017-11-23 00:12:09 +01001301 }
1302 else {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001303 calculate->zip_path = joinpath2(calculate->prefix_macro, lib_python);
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001304 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001305
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001306 if (calculate->zip_path == NULL) {
1307 return _PyStatus_NO_MEMORY();
1308 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001309
1310 /* Replace "00" with version */
1311 size_t len = wcslen(calculate->zip_path);
1312 calculate->zip_path[len - 6] = VERSION[0];
1313 calculate->zip_path[len - 5] = VERSION[2];
1314
Victor Stinner331a6a52019-05-27 16:39:22 +02001315 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001316}
1317
1318
Victor Stinner331a6a52019-05-27 16:39:22 +02001319static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001320calculate_module_search_path(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001321 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001322{
1323 /* Calculate size of return buffer */
1324 size_t bufsz = 0;
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001325 if (calculate->pythonpath_env != NULL) {
1326 bufsz += wcslen(calculate->pythonpath_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001327 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001328
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001329 wchar_t *defpath = calculate->pythonpath_macro;
1330 size_t prefixsz = wcslen(calculate->prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001331 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001332 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001333
Victor Stinner3939c322019-06-25 15:02:43 +02001334 if (!_Py_isabs(defpath)) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001335 /* Paths are relative to prefix */
1336 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001337 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001338
Victor Stinner0327bde2017-11-23 17:03:20 +01001339 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001340 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001341 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001342 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001343 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001344 break;
1345 }
1346 defpath = delim + 1;
1347 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001348
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001349 bufsz += wcslen(calculate->zip_path) + 1;
1350 bufsz += wcslen(calculate->exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001351
Victor Stinner0327bde2017-11-23 17:03:20 +01001352 /* Allocate the buffer */
1353 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001354 if (buf == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +02001355 return _PyStatus_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001356 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001357 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001358
Victor Stinner72967a42013-11-16 01:22:04 +01001359 /* Run-time value of $PYTHONPATH goes first */
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001360 if (calculate->pythonpath_env) {
1361 wcscpy(buf, calculate->pythonpath_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001362 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001363 }
Victor Stinner72967a42013-11-16 01:22:04 +01001364
1365 /* Next is the default zip path */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001366 wcscat(buf, calculate->zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001367 wcscat(buf, delimiter);
1368
1369 /* Next goes merge of compile-time $PYTHONPATH with
1370 * dynamically located prefix.
1371 */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001372 defpath = calculate->pythonpath_macro;
Victor Stinner72967a42013-11-16 01:22:04 +01001373 while (1) {
1374 wchar_t *delim = wcschr(defpath, DELIM);
1375
Victor Stinner3939c322019-06-25 15:02:43 +02001376 if (!_Py_isabs(defpath)) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001377 wcscat(buf, calculate->prefix);
1378 if (prefixsz >= 2 && calculate->prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001379 defpath[0] != (delim ? DELIM : L'\0'))
1380 {
1381 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001382 wcscat(buf, separator);
1383 }
Victor Stinner72967a42013-11-16 01:22:04 +01001384 }
1385
1386 if (delim) {
1387 size_t len = delim - defpath + 1;
1388 size_t end = wcslen(buf) + len;
1389 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001390 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001391 }
1392 else {
1393 wcscat(buf, defpath);
1394 break;
1395 }
1396 defpath = delim + 1;
1397 }
1398 wcscat(buf, delimiter);
1399
1400 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001401 wcscat(buf, calculate->exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001402
Victor Stinner331a6a52019-05-27 16:39:22 +02001403 pathconfig->module_search_path = buf;
1404 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001405}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001406
Victor Stinner0327bde2017-11-23 17:03:20 +01001407
Victor Stinner331a6a52019-05-27 16:39:22 +02001408static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +02001409calculate_init(PyCalculatePath *calculate, const PyConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001410{
Victor Stinner0327bde2017-11-23 17:03:20 +01001411 size_t len;
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001412 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001413 if (path) {
1414 calculate->path_env = Py_DecodeLocale(path, &len);
1415 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001416 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001417 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001418 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001419
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001420 /* Decode macros */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001421 calculate->pythonpath_macro = Py_DecodeLocale(PYTHONPATH, &len);
1422 if (!calculate->pythonpath_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001423 return DECODE_LOCALE_ERR("PYTHONPATH macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001424 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001425 calculate->prefix_macro = Py_DecodeLocale(PREFIX, &len);
1426 if (!calculate->prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001427 return DECODE_LOCALE_ERR("PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001428 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001429 calculate->exec_prefix_macro = Py_DecodeLocale(EXEC_PREFIX, &len);
1430 if (!calculate->exec_prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001431 return DECODE_LOCALE_ERR("EXEC_PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001432 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001433 calculate->vpath_macro = Py_DecodeLocale(VPATH, &len);
1434 if (!calculate->vpath_macro) {
1435 return DECODE_LOCALE_ERR("VPATH macro", len);
1436 }
1437
Victor Stinner0327bde2017-11-23 17:03:20 +01001438 calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
1439 if (!calculate->lib_python) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001440 return DECODE_LOCALE_ERR("EXEC_PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001441 }
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001442
1443 calculate->warnings = config->pathconfig_warnings;
1444 calculate->pythonpath_env = config->pythonpath_env;
1445
Victor Stinner331a6a52019-05-27 16:39:22 +02001446 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001447}
1448
1449
1450static void
1451calculate_free(PyCalculatePath *calculate)
1452{
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001453 PyMem_RawFree(calculate->pythonpath_macro);
1454 PyMem_RawFree(calculate->prefix_macro);
1455 PyMem_RawFree(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001456 PyMem_RawFree(calculate->vpath_macro);
Victor Stinner0327bde2017-11-23 17:03:20 +01001457 PyMem_RawFree(calculate->lib_python);
1458 PyMem_RawFree(calculate->path_env);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001459 PyMem_RawFree(calculate->zip_path);
1460 PyMem_RawFree(calculate->argv0_path);
1461 PyMem_RawFree(calculate->prefix);
1462 PyMem_RawFree(calculate->exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +01001463}
1464
1465
Victor Stinner331a6a52019-05-27 16:39:22 +02001466static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001467calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001468{
Victor Stinner331a6a52019-05-27 16:39:22 +02001469 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +01001470
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001471 if (pathconfig->program_full_path == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001472 status = calculate_program(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001473 if (_PyStatus_EXCEPTION(status)) {
1474 return status;
1475 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001476 }
1477
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001478 status = calculate_argv0_path(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001479 if (_PyStatus_EXCEPTION(status)) {
1480 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001481 }
1482
Victor Stinner221fd842019-09-25 02:54:25 +02001483 /* If a pyvenv.cfg configure file is found,
1484 argv0_path is overriden with its 'home' variable. */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001485 status = calculate_read_pyenv(calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001486 if (_PyStatus_EXCEPTION(status)) {
1487 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001488 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001489
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001490 status = calculate_prefix(calculate, pathconfig);
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_zip_path(calculate);
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_exec_prefix(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001501 if (_PyStatus_EXCEPTION(status)) {
1502 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001503 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001504
Victor Stinner03a8a562019-10-04 02:22:39 +02001505 if ((!calculate->prefix_found || !calculate->exec_prefix_found)
1506 && calculate->warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001507 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001508 fprintf(stderr,
1509 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1510 }
1511
Victor Stinnere2677932019-09-21 01:50:16 +02001512 if (pathconfig->module_search_path == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001513 status = calculate_module_search_path(calculate, pathconfig);
Victor Stinnere2677932019-09-21 01:50:16 +02001514 if (_PyStatus_EXCEPTION(status)) {
1515 return status;
1516 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001517 }
1518
Victor Stinner331a6a52019-05-27 16:39:22 +02001519 if (pathconfig->prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001520 status = calculate_set_prefix(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001521 if (_PyStatus_EXCEPTION(status)) {
1522 return status;
1523 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001524 }
1525
Victor Stinner331a6a52019-05-27 16:39:22 +02001526 if (pathconfig->exec_prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001527 status = calculate_set_exec_prefix(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001528 if (_PyStatus_EXCEPTION(status)) {
1529 return status;
1530 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001531 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001532 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001533}
1534
1535
Victor Stinner85ce0a72019-09-24 00:55:48 +02001536/* Calculate the Python path configuration.
1537
1538 Inputs:
1539
1540 - PATH environment variable
1541 - Macros: PYTHONPATH, PREFIX, EXEC_PREFIX, VERSION (ex: "3.9").
1542 PREFIX and EXEC_PREFIX are generated by the configure script.
1543 PYTHONPATH macro is the default search path.
1544 - pybuilddir.txt file
1545 - pyvenv.cfg configuration file
1546 - PyConfig fields ('config' function argument):
1547
1548 - pathconfig_warnings
1549 - pythonpath_env (PYTHONPATH environment variable)
1550
1551 - _PyPathConfig fields ('pathconfig' function argument):
1552
1553 - program_name: see config_init_program_name()
1554 - home: Py_SetPythonHome() or PYTHONHOME environment variable
1555
1556 - current working directory: see copy_absolute()
1557
1558 Outputs, 'pathconfig' fields:
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001559
1560 - program_full_path
1561 - module_search_path
1562 - prefix
1563 - exec_prefix
1564
Victor Stinner85ce0a72019-09-24 00:55:48 +02001565 If a field is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001566PyStatus
1567_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001568{
Victor Stinner331a6a52019-05-27 16:39:22 +02001569 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001570 PyCalculatePath calculate;
1571 memset(&calculate, 0, sizeof(calculate));
1572
Victor Stinner331a6a52019-05-27 16:39:22 +02001573 status = calculate_init(&calculate, config);
1574 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001575 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001576 }
1577
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001578 status = calculate_path(&calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001579 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001580 goto done;
1581 }
1582
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001583 /* program_full_path must an either an empty string or an absolute path */
1584 assert(wcslen(pathconfig->program_full_path) == 0
1585 || _Py_isabs(pathconfig->program_full_path));
1586
Victor Stinner331a6a52019-05-27 16:39:22 +02001587 status = _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001588
Victor Stinner9316ee42017-11-25 03:17:57 +01001589done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001590 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001591 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001592}
Victor Stinner46972b72017-11-24 22:55:40 +01001593
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001594#ifdef __cplusplus
1595}
1596#endif