blob: e97ea8b30799d1cb6de56186a6719b1ca15ddc58 [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
Victor Stinner8510f432020-03-10 09:53:09 +0100108#if (!defined(PREFIX) || !defined(EXEC_PREFIX) \
109 || !defined(VERSION) || !defined(VPATH) || !defined(PLATLIBDIR))
110#error "PREFIX, EXEC_PREFIX, VERSION, VPATH and PLATLIBDIR macros must be defined"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000111#endif
Guido van Rossum667d7041995-08-04 04:20:48 +0000112
Guido van Rossum305e5d01997-04-11 17:18:45 +0000113#ifndef LANDMARK
Martin v. Löwis790465f2008-04-05 20:41:37 +0000114#define LANDMARK L"os.py"
Guido van Rossum305e5d01997-04-11 17:18:45 +0000115#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000116
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200117#define BUILD_LANDMARK L"Modules/Setup.local"
118
Victor Stinner9316ee42017-11-25 03:17:57 +0100119#define DECODE_LOCALE_ERR(NAME, LEN) \
120 ((LEN) == (size_t)-2) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200121 ? _PyStatus_ERR("cannot decode " NAME) \
122 : _PyStatus_NO_MEMORY()
Victor Stinner9316ee42017-11-25 03:17:57 +0100123
Victor Stinner331a6a52019-05-27 16:39:22 +0200124#define PATHLEN_ERR() _PyStatus_ERR("path configuration: path too long")
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100125
Victor Stinner0327bde2017-11-23 17:03:20 +0100126typedef struct {
127 wchar_t *path_env; /* PATH environment variable */
Victor Stinner0327bde2017-11-23 17:03:20 +0100128
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200129 wchar_t *pythonpath_macro; /* PYTHONPATH macro */
130 wchar_t *prefix_macro; /* PREFIX macro */
131 wchar_t *exec_prefix_macro; /* EXEC_PREFIX macro */
Victor Stinner8510f432020-03-10 09:53:09 +0100132 wchar_t *platlibdir_macro; /* PLATLIBDIR macro */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200133 wchar_t *vpath_macro; /* VPATH macro */
Victor Stinner0327bde2017-11-23 17:03:20 +0100134
135 wchar_t *lib_python; /* "lib/pythonX.Y" */
Victor Stinner0327bde2017-11-23 17:03:20 +0100136
137 int prefix_found; /* found platform independent libraries? */
138 int exec_prefix_found; /* found the platform dependent libraries? */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200139
140 int warnings;
141 const wchar_t *pythonpath_env;
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200142
143 wchar_t *argv0_path;
144 wchar_t *zip_path;
145 wchar_t *prefix;
146 wchar_t *exec_prefix;
Victor Stinner0327bde2017-11-23 17:03:20 +0100147} PyCalculatePath;
148
149static const wchar_t delimiter[2] = {DELIM, '\0'};
150static const wchar_t separator[2] = {SEP, '\0'};
Victor Stinner0327bde2017-11-23 17:03:20 +0100151
Martin v. Löwis790465f2008-04-05 20:41:37 +0000152
Victor Stinner91afbb62015-03-24 12:16:28 +0100153/* Get file status. Encode the path to the locale encoding. */
Victor Stinner91afbb62015-03-24 12:16:28 +0100154static int
155_Py_wstat(const wchar_t* path, struct stat *buf)
156{
157 int err;
158 char *fname;
Victor Stinner9dd76202017-12-21 16:20:32 +0100159 fname = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner91afbb62015-03-24 12:16:28 +0100160 if (fname == NULL) {
161 errno = EINVAL;
162 return -1;
163 }
164 err = stat(fname, buf);
Victor Stinner9dd76202017-12-21 16:20:32 +0100165 PyMem_RawFree(fname);
Victor Stinner91afbb62015-03-24 12:16:28 +0100166 return err;
167}
168
Victor Stinner0327bde2017-11-23 17:03:20 +0100169
Guido van Rossum305e5d01997-04-11 17:18:45 +0000170static void
Martin v. Löwis790465f2008-04-05 20:41:37 +0000171reduce(wchar_t *dir)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000172{
Martin v. Löwis790465f2008-04-05 20:41:37 +0000173 size_t i = wcslen(dir);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100174 while (i > 0 && dir[i] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000175 --i;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100176 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000177 dir[i] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +0000178}
Guido van Rossumd29806c1998-01-19 22:06:22 +0000179
Victor Stinner0327bde2017-11-23 17:03:20 +0100180
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100181/* Is file, not directory */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000182static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100183isfile(const wchar_t *filename)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000184{
Fred Drakeedabdc12000-07-08 06:16:37 +0000185 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100186 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000187 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100188 }
189 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000190 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100191 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000192 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000193}
194
195
Victor Stinner0327bde2017-11-23 17:03:20 +0100196/* Is executable file */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000197static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100198isxfile(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000199{
Fred Drakeedabdc12000-07-08 06:16:37 +0000200 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100201 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000202 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100203 }
204 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000205 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100206 }
207 if ((buf.st_mode & 0111) == 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000208 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100209 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000210 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000211}
212
213
Victor Stinner0327bde2017-11-23 17:03:20 +0100214/* Is directory */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000215static int
Victor Stinnerf0c85792019-10-04 03:53:26 +0200216isdir(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000217{
Fred Drakeedabdc12000-07-08 06:16:37 +0000218 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100219 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000220 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100221 }
222 if (!S_ISDIR(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000223 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100224 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000225 return 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000226}
227
228
Tim Petersec8c5a92004-08-08 01:00:47 +0000229/* Add a path component, by appending stuff to buffer.
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200230 buflen: 'buffer' length in characters including trailing NUL.
231
232 If path2 is empty:
233
234 - if path doesn't end with SEP and is not empty, add SEP to path
235 - otherwise, do nothing. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200236static PyStatus
Victor Stinnerf0c85792019-10-04 03:53:26 +0200237joinpath(wchar_t *path, const wchar_t *path2, size_t path_len)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000238{
Victor Stinnerf0c85792019-10-04 03:53:26 +0200239 size_t n;
240 if (!_Py_isabs(path2)) {
241 n = wcslen(path);
242 if (n >= path_len) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100243 return PATHLEN_ERR();
244 }
245
Victor Stinnerf0c85792019-10-04 03:53:26 +0200246 if (n > 0 && path[n-1] != SEP) {
247 path[n++] = SEP;
Victor Stinner0327bde2017-11-23 17:03:20 +0100248 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000249 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100250 else {
251 n = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100252 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100253
Victor Stinnerf0c85792019-10-04 03:53:26 +0200254 size_t k = wcslen(path2);
255 if (n + k >= path_len) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100256 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100257 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200258 wcsncpy(path + n, path2, k);
259 path[n + k] = '\0';
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100260
Victor Stinner331a6a52019-05-27 16:39:22 +0200261 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000262}
263
Victor Stinner0327bde2017-11-23 17:03:20 +0100264
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200265static wchar_t*
266substring(const wchar_t *str, size_t len)
267{
268 wchar_t *substr = PyMem_RawMalloc((len + 1) * sizeof(wchar_t));
269 if (substr == NULL) {
270 return NULL;
271 }
272
273 if (len) {
274 memcpy(substr, str, len * sizeof(wchar_t));
275 }
276 substr[len] = L'\0';
277 return substr;
278}
279
280
281static wchar_t*
282joinpath2(const wchar_t *path, const wchar_t *path2)
283{
284 if (_Py_isabs(path2)) {
285 return _PyMem_RawWcsdup(path2);
286 }
287
288 size_t len = wcslen(path);
289 int add_sep = (len > 0 && path[len - 1] != SEP);
290 len += add_sep;
291 len += wcslen(path2);
292
293 wchar_t *new_path = PyMem_RawMalloc((len + 1) * sizeof(wchar_t));
294 if (new_path == NULL) {
295 return NULL;
296 }
297
298 wcscpy(new_path, path);
299 if (add_sep) {
300 wcscat(new_path, separator);
301 }
302 wcscat(new_path, path2);
303 return new_path;
304}
305
306
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100307static inline int
308safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
309{
310 size_t srclen = wcslen(src);
311 if (n <= srclen) {
312 dst[0] = L'\0';
313 return -1;
314 }
315 memcpy(dst, src, (srclen + 1) * sizeof(wchar_t));
316 return 0;
317}
318
319
Guido van Rossume296ced2001-09-28 20:00:29 +0000320/* copy_absolute requires that path be allocated at least
Victor Stinnerf0c85792019-10-04 03:53:26 +0200321 'abs_path_len' characters (including trailing NUL). */
Victor Stinner331a6a52019-05-27 16:39:22 +0200322static PyStatus
Victor Stinnerf0c85792019-10-04 03:53:26 +0200323copy_absolute(wchar_t *abs_path, const wchar_t *path, size_t abs_path_len)
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000324{
Victor Stinnerf0c85792019-10-04 03:53:26 +0200325 if (_Py_isabs(path)) {
326 if (safe_wcscpy(abs_path, path, abs_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100327 return PATHLEN_ERR();
328 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100329 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000330 else {
Victor Stinnerf0c85792019-10-04 03:53:26 +0200331 if (!_Py_wgetcwd(abs_path, abs_path_len)) {
Victor Stinner4f3abb02010-10-07 23:29:18 +0000332 /* unable to get the current directory */
Victor Stinnerf0c85792019-10-04 03:53:26 +0200333 if (safe_wcscpy(abs_path, path, abs_path_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100334 return PATHLEN_ERR();
335 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200336 return _PyStatus_OK();
Victor Stinner4f3abb02010-10-07 23:29:18 +0000337 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200338 if (path[0] == '.' && path[1] == SEP) {
339 path += 2;
Victor Stinner0327bde2017-11-23 17:03:20 +0100340 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200341 PyStatus status = joinpath(abs_path, path, abs_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200342 if (_PyStatus_EXCEPTION(status)) {
343 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100344 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000345 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200346 return _PyStatus_OK();
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000347}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000348
Victor Stinner0327bde2017-11-23 17:03:20 +0100349
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100350/* path_len: path length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200351static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200352absolutize(wchar_t **path_p)
Guido van Rossume296ced2001-09-28 20:00:29 +0000353{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200354 assert(!_Py_isabs(*path_p));
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100355
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100356 wchar_t abs_path[MAXPATHLEN+1];
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200357 wchar_t *path = *path_p;
358
Victor Stinner331a6a52019-05-27 16:39:22 +0200359 PyStatus status = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path));
360 if (_PyStatus_EXCEPTION(status)) {
361 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100362 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100363
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200364 PyMem_RawFree(*path_p);
365 *path_p = _PyMem_RawWcsdup(abs_path);
366 if (*path_p == NULL) {
367 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100368 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200369 return _PyStatus_OK();
Guido van Rossume296ced2001-09-28 20:00:29 +0000370}
371
Victor Stinner0327bde2017-11-23 17:03:20 +0100372
Victor Stinnerf0c85792019-10-04 03:53:26 +0200373/* Is module -- check for .pyc too */
374static PyStatus
375ismodule(const wchar_t *path, int *result)
376{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200377 wchar_t *filename = joinpath2(path, LANDMARK);
378 if (filename == NULL) {
379 return _PyStatus_NO_MEMORY();
Victor Stinnerf0c85792019-10-04 03:53:26 +0200380 }
381
382 if (isfile(filename)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200383 PyMem_RawFree(filename);
Victor Stinnerf0c85792019-10-04 03:53:26 +0200384 *result = 1;
385 return _PyStatus_OK();
386 }
387
388 /* Check for the compiled version of prefix. */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200389 size_t len = wcslen(filename);
390 wchar_t *pyc = PyMem_RawMalloc((len + 2) * sizeof(wchar_t));
391 if (pyc == NULL) {
392 PyMem_RawFree(filename);
393 return _PyStatus_NO_MEMORY();
Victor Stinnerf0c85792019-10-04 03:53:26 +0200394 }
395
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200396 memcpy(pyc, filename, len * sizeof(wchar_t));
397 pyc[len] = L'c';
398 pyc[len + 1] = L'\0';
399 *result = isfile(pyc);
400
401 PyMem_RawFree(filename);
402 PyMem_RawFree(pyc);
403
Victor Stinnerf0c85792019-10-04 03:53:26 +0200404 return _PyStatus_OK();
405}
406
407
E. M. Bray7a7693e2018-10-05 13:38:50 +0200408#if defined(__CYGWIN__) || defined(__MINGW32__)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200409#ifndef EXE_SUFFIX
410#define EXE_SUFFIX L".exe"
411#endif
412
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100413/* pathlen: 'path' length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200414static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200415add_exe_suffix(wchar_t **progpath_p)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200416{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200417 wchar_t *progpath = *progpath_p;
418
E. M. Bray7a7693e2018-10-05 13:38:50 +0200419 /* Check for already have an executable suffix */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200420 size_t n = wcslen(progpath);
E. M. Bray7a7693e2018-10-05 13:38:50 +0200421 size_t s = wcslen(EXE_SUFFIX);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200422 if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200423 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200424 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100425
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200426 wchar_t *progpath2 = PyMem_RawMalloc((n + s + 1) * sizeof(wchar_t));
427 if (progpath2 == NULL) {
428 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100429 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100430
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200431 memcpy(progpath2, progpath, n * sizeof(wchar_t));
432 memcpy(progpath2 + n, EXE_SUFFIX, s * sizeof(wchar_t));
433 progpath2[n+s] = L'\0';
434
435 if (isxfile(progpath2)) {
436 PyMem_RawFree(*progpath_p);
437 *progpath_p = progpath2;
438 }
439 else {
440 PyMem_RawFree(progpath2);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100441 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200442 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200443}
444#endif
445
446
Guido van Rossume296ced2001-09-28 20:00:29 +0000447/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000448 bytes long.
449*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200450static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200451search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
452 wchar_t *prefix, size_t prefix_len, int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000453{
Victor Stinner331a6a52019-05-27 16:39:22 +0200454 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000455
Fred Drakeedabdc12000-07-08 06:16:37 +0000456 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200457 if (pathconfig->home) {
Victor Stinner221fd842019-09-25 02:54:25 +0200458 /* Path: <home> / <lib_python> */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200459 if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100460 return PATHLEN_ERR();
461 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100462 wchar_t *delim = wcschr(prefix, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100463 if (delim) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000464 *delim = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100465 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200466 status = joinpath(prefix, calculate->lib_python, prefix_len);
467 if (_PyStatus_EXCEPTION(status)) {
468 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100469 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100470 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200471 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000472 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000473
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200474 /* Check to see if argv0_path is in the build directory
475
476 Path: <argv0_path> / <BUILD_LANDMARK define> */
477 wchar_t *path = joinpath2(calculate->argv0_path, BUILD_LANDMARK);
478 if (path == NULL) {
479 return _PyStatus_NO_MEMORY();
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100480 }
481
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200482 int is_build_dir = isfile(path);
483 PyMem_RawFree(path);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100484
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200485 if (is_build_dir) {
486 /* argv0_path is the build directory (BUILD_LANDMARK exists),
487 now also check LANDMARK using ismodule(). */
Victor Stinnerf0c85792019-10-04 03:53:26 +0200488
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200489 /* Path: <argv0_path> / <VPATH macro> / Lib */
490 /* or if VPATH is empty: <argv0_path> / Lib */
491 if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
492 return PATHLEN_ERR();
493 }
494
495 status = joinpath(prefix, calculate->vpath_macro, prefix_len);
496 if (_PyStatus_EXCEPTION(status)) {
497 return status;
498 }
499
500 status = joinpath(prefix, L"Lib", prefix_len);
501 if (_PyStatus_EXCEPTION(status)) {
502 return status;
503 }
504
505 int module;
506 status = ismodule(prefix, &module);
507 if (_PyStatus_EXCEPTION(status)) {
508 return status;
509 }
510 if (module) {
511 /* BUILD_LANDMARK and LANDMARK found */
512 *found = -1;
513 return _PyStatus_OK();
Victor Stinner21582312010-10-23 00:13:28 +0000514 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000515 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000516
Fred Drakeedabdc12000-07-08 06:16:37 +0000517 /* Search from argv0_path, until root is found */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200518 status = copy_absolute(prefix, calculate->argv0_path, prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200519 if (_PyStatus_EXCEPTION(status)) {
520 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100521 }
522
Fred Drakeedabdc12000-07-08 06:16:37 +0000523 do {
Victor Stinner221fd842019-09-25 02:54:25 +0200524 /* Path: <argv0_path or substring> / <lib_python> / LANDMARK */
525 size_t n = wcslen(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200526 status = joinpath(prefix, calculate->lib_python, prefix_len);
527 if (_PyStatus_EXCEPTION(status)) {
528 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100529 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200530
531 int module;
532 status = ismodule(prefix, &module);
Victor Stinner331a6a52019-05-27 16:39:22 +0200533 if (_PyStatus_EXCEPTION(status)) {
534 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100535 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200536 if (module) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100537 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200538 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100539 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100540 prefix[n] = L'\0';
541 reduce(prefix);
542 } while (prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000543
Victor Stinner221fd842019-09-25 02:54:25 +0200544 /* Look at configure's PREFIX.
545 Path: <PREFIX macro> / <lib_python> / LANDMARK */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200546 if (safe_wcscpy(prefix, calculate->prefix_macro, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100547 return PATHLEN_ERR();
548 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200549 status = joinpath(prefix, calculate->lib_python, prefix_len);
550 if (_PyStatus_EXCEPTION(status)) {
551 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100552 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200553
554 int module;
555 status = ismodule(prefix, &module);
Victor Stinner331a6a52019-05-27 16:39:22 +0200556 if (_PyStatus_EXCEPTION(status)) {
557 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100558 }
Victor Stinnerf0c85792019-10-04 03:53:26 +0200559 if (module) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100560 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200561 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100562 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000563
Fred Drakeedabdc12000-07-08 06:16:37 +0000564 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100565 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200566 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000567}
568
569
Victor Stinner331a6a52019-05-27 16:39:22 +0200570static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200571calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100572{
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200573 wchar_t prefix[MAXPATHLEN+1];
574 memset(prefix, 0, sizeof(prefix));
575 size_t prefix_len = Py_ARRAY_LENGTH(prefix);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100576
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200577 PyStatus status;
578 status = search_for_prefix(calculate, pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200579 prefix, prefix_len,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200580 &calculate->prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200581 if (_PyStatus_EXCEPTION(status)) {
582 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100583 }
584
Victor Stinner0327bde2017-11-23 17:03:20 +0100585 if (!calculate->prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200586 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100587 fprintf(stderr,
588 "Could not find platform independent libraries <prefix>\n");
589 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200590
591 calculate->prefix = joinpath2(calculate->prefix_macro,
592 calculate->lib_python);
593 }
594 else {
595 calculate->prefix = _PyMem_RawWcsdup(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100596 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200597
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200598 if (calculate->prefix == NULL) {
599 return _PyStatus_NO_MEMORY();
600 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200601 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100602}
603
604
Victor Stinner331a6a52019-05-27 16:39:22 +0200605static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200606calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100607{
608 /* Reduce prefix and exec_prefix to their essence,
609 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
610 * If we're loading relative to the build directory,
611 * return the compiled-in defaults instead.
612 */
613 if (calculate->prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200614 wchar_t *prefix = _PyMem_RawWcsdup(calculate->prefix);
615 if (prefix == NULL) {
616 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100617 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200618
619 reduce(prefix);
620 reduce(prefix);
621 if (prefix[0]) {
622 pathconfig->prefix = prefix;
623 }
624 else {
625 PyMem_RawFree(prefix);
626
627 /* The prefix is the root directory, but reduce() chopped
628 off the "/". */
629 pathconfig->prefix = _PyMem_RawWcsdup(separator);
630 if (pathconfig->prefix == NULL) {
631 return _PyStatus_NO_MEMORY();
632 }
633 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100634 }
635 else {
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200636 pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200637 if (pathconfig->prefix == NULL) {
638 return _PyStatus_NO_MEMORY();
639 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100640 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200641 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100642}
643
644
Victor Stinner221fd842019-09-25 02:54:25 +0200645static PyStatus
646calculate_pybuilddir(const wchar_t *argv0_path,
647 wchar_t *exec_prefix, size_t exec_prefix_len,
648 int *found)
649{
650 PyStatus status;
651
Victor Stinner221fd842019-09-25 02:54:25 +0200652 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
653 is written by setup.py and contains the relative path to the location
654 of shared library modules.
655
656 Filename: <argv0_path> / "pybuilddir.txt" */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200657 wchar_t *filename = joinpath2(argv0_path, L"pybuilddir.txt");
658 if (filename == NULL) {
659 return _PyStatus_NO_MEMORY();
Victor Stinner221fd842019-09-25 02:54:25 +0200660 }
661
Victor Stinner221fd842019-09-25 02:54:25 +0200662 FILE *fp = _Py_wfopen(filename, L"rb");
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200663 PyMem_RawFree(filename);
Victor Stinner221fd842019-09-25 02:54:25 +0200664 if (fp == NULL) {
665 errno = 0;
666 return _PyStatus_OK();
667 }
668
669 char buf[MAXPATHLEN + 1];
670 size_t n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, fp);
671 buf[n] = '\0';
672 fclose(fp);
673
674 size_t dec_len;
675 wchar_t *pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
676 if (!pybuilddir) {
677 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
678 }
679
680 /* Path: <argv0_path> / <pybuilddir content> */
681 if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) {
682 PyMem_RawFree(pybuilddir);
683 return PATHLEN_ERR();
684 }
685 status = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
686 PyMem_RawFree(pybuilddir);
687 if (_PyStatus_EXCEPTION(status)) {
688 return status;
689 }
690
691 *found = -1;
692 return _PyStatus_OK();
693}
694
695
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000696/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000697 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000698*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200699static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200700search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100701 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100702 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000703{
Victor Stinner331a6a52019-05-27 16:39:22 +0200704 PyStatus status;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000705
Fred Drakeedabdc12000-07-08 06:16:37 +0000706 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200707 if (pathconfig->home) {
Victor Stinner221fd842019-09-25 02:54:25 +0200708 /* Path: <home> / <lib_python> / "lib-dynload" */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200709 wchar_t *delim = wcschr(pathconfig->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100710 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100711 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
712 return PATHLEN_ERR();
713 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100714 }
715 else {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200716 if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100717 return PATHLEN_ERR();
718 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100719 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200720 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
721 if (_PyStatus_EXCEPTION(status)) {
722 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100723 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200724 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
725 if (_PyStatus_EXCEPTION(status)) {
726 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100727 }
728 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200729 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000730 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000731
Victor Stinner221fd842019-09-25 02:54:25 +0200732 /* Check for pybuilddir.txt */
733 assert(*found == 0);
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200734 status = calculate_pybuilddir(calculate->argv0_path,
735 exec_prefix, exec_prefix_len, found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200736 if (_PyStatus_EXCEPTION(status)) {
737 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100738 }
Victor Stinner221fd842019-09-25 02:54:25 +0200739 if (*found) {
740 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000741 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000742
Fred Drakeedabdc12000-07-08 06:16:37 +0000743 /* Search from argv0_path, until root is found */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200744 status = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200745 if (_PyStatus_EXCEPTION(status)) {
746 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100747 }
748
Fred Drakeedabdc12000-07-08 06:16:37 +0000749 do {
Victor Stinner221fd842019-09-25 02:54:25 +0200750 /* Path: <argv0_path or substring> / <lib_python> / "lib-dynload" */
751 size_t n = wcslen(exec_prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200752 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
753 if (_PyStatus_EXCEPTION(status)) {
754 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100755 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200756 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
757 if (_PyStatus_EXCEPTION(status)) {
758 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100759 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100760 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100761 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200762 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100763 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100764 exec_prefix[n] = L'\0';
765 reduce(exec_prefix);
766 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000767
Victor Stinner221fd842019-09-25 02:54:25 +0200768 /* Look at configure's EXEC_PREFIX.
769
770 Path: <EXEC_PREFIX macro> / <lib_python> / "lib-dynload" */
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200771 if (safe_wcscpy(exec_prefix, calculate->exec_prefix_macro, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100772 return PATHLEN_ERR();
773 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200774 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
775 if (_PyStatus_EXCEPTION(status)) {
776 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100777 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200778 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
779 if (_PyStatus_EXCEPTION(status)) {
780 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100781 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100782 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100783 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200784 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100785 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000786
Fred Drakeedabdc12000-07-08 06:16:37 +0000787 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100788 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200789 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000790}
791
Guido van Rossum305e5d01997-04-11 17:18:45 +0000792
Victor Stinner331a6a52019-05-27 16:39:22 +0200793static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200794calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100795{
Victor Stinner331a6a52019-05-27 16:39:22 +0200796 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200797 wchar_t exec_prefix[MAXPATHLEN+1];
798 memset(exec_prefix, 0, sizeof(exec_prefix));
799 size_t exec_prefix_len = Py_ARRAY_LENGTH(exec_prefix);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100800
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200801 status = search_for_exec_prefix(calculate, pathconfig,
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200802 exec_prefix, exec_prefix_len,
803 &calculate->exec_prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200804 if (_PyStatus_EXCEPTION(status)) {
805 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100806 }
807
Victor Stinner0327bde2017-11-23 17:03:20 +0100808 if (!calculate->exec_prefix_found) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200809 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100810 fprintf(stderr,
811 "Could not find platform dependent libraries <exec_prefix>\n");
812 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200813
Victor Stinner8510f432020-03-10 09:53:09 +0100814 /* <PLATLIBDIR> / "lib-dynload" */
815 wchar_t *lib_dynload = joinpath2(calculate->platlibdir_macro,
816 L"lib-dynload");
817 if (lib_dynload == NULL) {
818 return _PyStatus_NO_MEMORY();
819 }
820
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200821 calculate->exec_prefix = joinpath2(calculate->exec_prefix_macro,
Victor Stinner8510f432020-03-10 09:53:09 +0100822 lib_dynload);
823 PyMem_RawFree(lib_dynload);
824
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200825 if (calculate->exec_prefix == NULL) {
826 return _PyStatus_NO_MEMORY();
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100827 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100828 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200829 else {
830 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
831 calculate->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
832 if (calculate->exec_prefix == NULL) {
833 return _PyStatus_NO_MEMORY();
834 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200835 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200836 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100837}
838
839
Victor Stinner331a6a52019-05-27 16:39:22 +0200840static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200841calculate_set_exec_prefix(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200842 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100843{
844 if (calculate->exec_prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200845 wchar_t *exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix);
846 if (exec_prefix == NULL) {
847 return _PyStatus_NO_MEMORY();
Victor Stinner0327bde2017-11-23 17:03:20 +0100848 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200849
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200850 reduce(exec_prefix);
851 reduce(exec_prefix);
852 reduce(exec_prefix);
853
854 if (exec_prefix[0]) {
855 pathconfig->exec_prefix = exec_prefix;
856 }
857 else {
858 /* empty string: use SEP instead */
859 PyMem_RawFree(exec_prefix);
860
861 /* The exec_prefix is the root directory, but reduce() chopped
862 off the "/". */
863 pathconfig->exec_prefix = _PyMem_RawWcsdup(separator);
864 if (pathconfig->exec_prefix == NULL) {
865 return _PyStatus_NO_MEMORY();
866 }
867 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100868 }
869 else {
Victor Stinnerabd7cd82019-10-04 15:25:50 +0200870 pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200871 if (pathconfig->exec_prefix == NULL) {
872 return _PyStatus_NO_MEMORY();
873 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100874 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200875 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100876}
877
878
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200879/* Similar to shutil.which().
880 If found, write the path into *abs_path_p. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200881static PyStatus
Victor Stinner03a8a562019-10-04 02:22:39 +0200882calculate_which(const wchar_t *path_env, wchar_t *program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200883 wchar_t **abs_path_p)
Victor Stinner0327bde2017-11-23 17:03:20 +0100884{
Victor Stinner03a8a562019-10-04 02:22:39 +0200885 while (1) {
886 wchar_t *delim = wcschr(path_env, DELIM);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200887 wchar_t *abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200888
889 if (delim) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200890 wchar_t *path = substring(path_env, delim - path_env);
891 if (path == NULL) {
892 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +0200893 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200894 abs_path = joinpath2(path, program_name);
895 PyMem_RawFree(path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200896 }
897 else {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200898 abs_path = joinpath2(path_env, program_name);
Victor Stinner03a8a562019-10-04 02:22:39 +0200899 }
900
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200901 if (abs_path == NULL) {
902 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +0200903 }
904
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200905 if (isxfile(abs_path)) {
906 *abs_path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200907 return _PyStatus_OK();
908 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200909 PyMem_RawFree(abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200910
911 if (!delim) {
912 break;
913 }
914 path_env = delim + 1;
915 }
916
917 /* not found */
918 return _PyStatus_OK();
919}
920
Victor Stinner9316ee42017-11-25 03:17:57 +0100921
Victor Stinnerb9197952017-11-23 19:02:04 +0100922#ifdef __APPLE__
Victor Stinner03a8a562019-10-04 02:22:39 +0200923static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200924calculate_program_macos(wchar_t **abs_path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +0200925{
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100926 char execpath[MAXPATHLEN + 1];
Victor Stinnerb9197952017-11-23 19:02:04 +0100927#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100928 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100929#else
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100930 unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100931#endif
Victor Stinner03a8a562019-10-04 02:22:39 +0200932
933 /* On Mac OS X, if a script uses an interpreter of the form
934 "#!/opt/python2.3/bin/python", the kernel only passes "python"
935 as argv[0], which falls through to the $PATH search below.
936 If /opt/python2.3/bin isn't in your path, or is near the end,
937 this algorithm may incorrectly find /usr/bin/python. To work
938 around this, we can use _NSGetExecutablePath to get a better
939 hint of what the intended interpreter was, although this
940 will fail if a relative path was used. but in that case,
941 absolutize() should help us out below
942 */
943 if (_NSGetExecutablePath(execpath, &nsexeclength) != 0
944 || (wchar_t)execpath[0] != SEP)
945 {
946 /* _NSGetExecutablePath() failed or the path is relative */
947 return _PyStatus_OK();
948 }
949
950 size_t len;
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200951 *abs_path_p = Py_DecodeLocale(execpath, &len);
952 if (*abs_path_p == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +0200953 return DECODE_LOCALE_ERR("executable path", len);
954 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200955 return _PyStatus_OK();
956}
957#endif /* __APPLE__ */
958
959
960static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200961calculate_program_impl(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +0200962{
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200963 assert(pathconfig->program_full_path == NULL);
964
Victor Stinner03a8a562019-10-04 02:22:39 +0200965 PyStatus status;
Victor Stinnerb9197952017-11-23 19:02:04 +0100966
Victor Stinner0327bde2017-11-23 17:03:20 +0100967 /* If there is no slash in the argv0 path, then we have to
968 * assume python is on the user's $PATH, since there's no
969 * other way to find a directory to start the search from. If
970 * $PATH isn't exported, you lose.
971 */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200972 if (wcschr(pathconfig->program_name, SEP)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200973 pathconfig->program_full_path = _PyMem_RawWcsdup(pathconfig->program_name);
974 if (pathconfig->program_full_path == NULL) {
975 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100976 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200977 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100978 }
Victor Stinner03a8a562019-10-04 02:22:39 +0200979
Jack Jansen1afd4802004-06-03 14:33:03 +0000980#ifdef __APPLE__
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200981 wchar_t *abs_path = NULL;
982 status = calculate_program_macos(&abs_path);
Victor Stinner03a8a562019-10-04 02:22:39 +0200983 if (_PyStatus_EXCEPTION(status)) {
984 return status;
985 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200986 if (abs_path) {
987 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +0200988 return _PyStatus_OK();
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000989 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000990#endif /* __APPLE__ */
Jack Jansen55070f52001-12-02 23:56:28 +0000991
Victor Stinner03a8a562019-10-04 02:22:39 +0200992 if (calculate->path_env) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200993 wchar_t *abs_path = NULL;
Victor Stinner03a8a562019-10-04 02:22:39 +0200994 status = calculate_which(calculate->path_env, pathconfig->program_name,
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200995 &abs_path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200996 if (_PyStatus_EXCEPTION(status)) {
997 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100998 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200999 if (abs_path) {
1000 pathconfig->program_full_path = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +02001001 return _PyStatus_OK();
1002 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001003 }
Victor Stinner03a8a562019-10-04 02:22:39 +02001004
1005 /* In the last resort, use an empty string */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001006 pathconfig->program_full_path = _PyMem_RawWcsdup(L"");
1007 if (pathconfig->program_full_path == NULL) {
1008 return _PyStatus_NO_MEMORY();
1009 }
Victor Stinner03a8a562019-10-04 02:22:39 +02001010 return _PyStatus_OK();
1011}
1012
1013
1014/* Calculate pathconfig->program_full_path */
1015static PyStatus
1016calculate_program(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
1017{
1018 PyStatus status;
Victor Stinner03a8a562019-10-04 02:22:39 +02001019
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001020 status = calculate_program_impl(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001021 if (_PyStatus_EXCEPTION(status)) {
1022 return status;
1023 }
1024
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001025 if (pathconfig->program_full_path[0] != '\0') {
Victor Stinner03a8a562019-10-04 02:22:39 +02001026 /* program_full_path is not empty */
1027
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001028 /* Make sure that program_full_path is an absolute path */
1029 if (!_Py_isabs(pathconfig->program_full_path)) {
1030 status = absolutize(&pathconfig->program_full_path);
Victor Stinner03a8a562019-10-04 02:22:39 +02001031 if (_PyStatus_EXCEPTION(status)) {
1032 return status;
1033 }
1034 }
1035
1036#if defined(__CYGWIN__) || defined(__MINGW32__)
1037 /* For these platforms it is necessary to ensure that the .exe suffix
1038 * is appended to the filename, otherwise there is potential for
1039 * sys.executable to return the name of a directory under the same
1040 * path (bpo-28441).
1041 */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001042 status = add_exe_suffix(&pathconfig->program_full_path);
Victor Stinner331a6a52019-05-27 16:39:22 +02001043 if (_PyStatus_EXCEPTION(status)) {
1044 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001045 }
E. M. Bray7a7693e2018-10-05 13:38:50 +02001046#endif
Victor Stinner03a8a562019-10-04 02:22:39 +02001047 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001048 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001049}
1050
1051
Victor Stinner03a8a562019-10-04 02:22:39 +02001052#if HAVE_READLINK
Victor Stinner331a6a52019-05-27 16:39:22 +02001053static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001054resolve_symlinks(wchar_t **path_p)
Victor Stinner03a8a562019-10-04 02:22:39 +02001055{
1056 wchar_t new_path[MAXPATHLEN + 1];
1057 const size_t new_path_len = Py_ARRAY_LENGTH(new_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001058 unsigned int nlink = 0;
Victor Stinner03a8a562019-10-04 02:22:39 +02001059
1060 while (1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001061 int linklen = _Py_wreadlink(*path_p, new_path, new_path_len);
Victor Stinner03a8a562019-10-04 02:22:39 +02001062 if (linklen == -1) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001063 /* not a symbolic link: we are done */
Victor Stinner03a8a562019-10-04 02:22:39 +02001064 break;
1065 }
1066
1067 if (_Py_isabs(new_path)) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001068 PyMem_RawFree(*path_p);
1069 *path_p = _PyMem_RawWcsdup(new_path);
1070 if (*path_p == NULL) {
1071 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001072 }
1073 }
1074 else {
1075 /* new_path is relative to path */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001076 reduce(*path_p);
1077
1078 wchar_t *abs_path = joinpath2(*path_p, new_path);
1079 if (abs_path == NULL) {
1080 return _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001081 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001082
1083 PyMem_RawFree(*path_p);
1084 *path_p = abs_path;
Victor Stinner03a8a562019-10-04 02:22:39 +02001085 }
1086
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001087 nlink++;
Victor Stinner03a8a562019-10-04 02:22:39 +02001088 /* 40 is the Linux kernel 4.2 limit */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001089 if (nlink >= 40) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001090 return _PyStatus_ERR("maximum number of symbolic links reached");
1091 }
1092 }
1093 return _PyStatus_OK();
1094}
1095#endif /* HAVE_READLINK */
1096
1097
1098#ifdef WITH_NEXT_FRAMEWORK
1099static PyStatus
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001100calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner03a8a562019-10-04 02:22:39 +02001101{
1102 NSModule pythonModule;
1103
1104 /* On Mac OS X we have a special case if we're running from a framework.
1105 This is because the python home should be set relative to the library,
1106 which is in the framework, not relative to the executable, which may
1107 be outside of the framework. Except when we're in the build
1108 directory... */
1109 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
1110
1111 /* Use dylib functions to find out where the framework was loaded from */
1112 const char* modPath = NSLibraryNameForModule(pythonModule);
1113 if (modPath == NULL) {
1114 return _PyStatus_OK();
1115 }
1116
1117 /* We're in a framework.
1118 See if we might be in the build directory. The framework in the
1119 build directory is incomplete, it only has the .dylib and a few
1120 needed symlinks, it doesn't have the Lib directories and such.
1121 If we're running with the framework from the build directory we must
1122 be running the interpreter in the build directory, so we use the
1123 build-directory-specific logic to find Lib and such. */
1124 size_t len;
1125 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
1126 if (wbuf == NULL) {
1127 return DECODE_LOCALE_ERR("framework location", len);
1128 }
1129
1130 /* Path: reduce(modPath) / lib_python / LANDMARK */
1131 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001132
1133 wchar_t *parent = _PyMem_RawWcsdup(wbuf);
1134 if (parent == NULL) {
1135 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001136 goto done;
1137 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001138
1139 reduce(parent);
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001140 wchar_t *lib_python = joinpath2(parent, calculate->lib_python);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001141 PyMem_RawFree(parent);
1142
1143 if (lib_python == NULL) {
1144 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001145 goto done;
1146 }
Victor Stinnerf0c85792019-10-04 03:53:26 +02001147
1148 int module;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001149 status = ismodule(lib_python, &module);
1150 PyMem_RawFree(lib_python);
1151
Victor Stinner03a8a562019-10-04 02:22:39 +02001152 if (_PyStatus_EXCEPTION(status)) {
1153 goto done;
1154 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001155 if (!module) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001156 /* We are in the build directory so use the name of the
1157 executable - we know that the absolute path is passed */
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001158 PyMem_RawFree(calculate->argv0_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001159 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1160 if (calculate->argv0_path == NULL) {
1161 status = _PyStatus_NO_MEMORY();
Victor Stinner03a8a562019-10-04 02:22:39 +02001162 goto done;
1163 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001164
1165 status = _PyStatus_OK();
1166 goto done;
Victor Stinner03a8a562019-10-04 02:22:39 +02001167 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001168
1169 /* Use the location of the library as argv0_path */
Victor Stinnerb6e0fc72019-10-10 15:42:30 +02001170 PyMem_RawFree(calculate->argv0_path);
1171 calculate->argv0_path = wbuf;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001172 return _PyStatus_OK();
Victor Stinner03a8a562019-10-04 02:22:39 +02001173
1174done:
1175 PyMem_RawFree(wbuf);
1176 return status;
1177}
1178#endif
1179
1180
1181static PyStatus
1182calculate_argv0_path(PyCalculatePath *calculate,
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001183 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001184{
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001185 PyStatus status;
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001186
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001187 calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path);
1188 if (calculate->argv0_path == NULL) {
1189 return _PyStatus_NO_MEMORY();
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001190 }
Jack Jansen55070f52001-12-02 23:56:28 +00001191
Guido van Rossum54ecc3d1999-01-27 17:53:11 +00001192#ifdef WITH_NEXT_FRAMEWORK
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001193 status = calculate_argv0_path_framework(calculate, pathconfig);
Victor Stinner03a8a562019-10-04 02:22:39 +02001194 if (_PyStatus_EXCEPTION(status)) {
1195 return status;
Fred Drakeedabdc12000-07-08 06:16:37 +00001196 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +00001197#endif
Guido van Rossume296ced2001-09-28 20:00:29 +00001198
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001199 status = resolve_symlinks(&calculate->argv0_path);
1200 if (_PyStatus_EXCEPTION(status)) {
1201 return status;
1202 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001203
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001204 reduce(calculate->argv0_path);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001205
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001206 return _PyStatus_OK();
1207}
1208
1209
1210static PyStatus
1211calculate_open_pyenv(PyCalculatePath *calculate, FILE **env_file_p)
1212{
1213 *env_file_p = NULL;
1214
1215 const wchar_t *env_cfg = L"pyvenv.cfg";
1216
1217 /* Filename: <argv0_path> / "pyvenv.cfg" */
1218 wchar_t *filename = joinpath2(calculate->argv0_path, env_cfg);
1219 if (filename == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001220 return _PyStatus_NO_MEMORY();
1221 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001222
1223 *env_file_p = _Py_wfopen(filename, L"r");
1224 PyMem_RawFree(filename);
1225
1226 if (*env_file_p != NULL) {
1227 return _PyStatus_OK();
1228
1229 }
1230
1231 /* fopen() failed: reset errno */
1232 errno = 0;
1233
1234 /* Path: <basename(argv0_path)> / "pyvenv.cfg" */
1235 wchar_t *parent = _PyMem_RawWcsdup(calculate->argv0_path);
1236 if (parent == NULL) {
1237 return _PyStatus_NO_MEMORY();
1238 }
1239 reduce(parent);
1240
1241 filename = joinpath2(parent, env_cfg);
1242 PyMem_RawFree(parent);
1243 if (filename == NULL) {
1244 return _PyStatus_NO_MEMORY();
1245 }
1246
1247 *env_file_p = _Py_wfopen(filename, L"r");
1248 PyMem_RawFree(filename);
1249
1250 if (*env_file_p == NULL) {
1251 /* fopen() failed: reset errno */
1252 errno = 0;
1253 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001254 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001255}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001256
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001257
Victor Stinner0327bde2017-11-23 17:03:20 +01001258/* Search for an "pyvenv.cfg" environment configuration file, first in the
1259 executable's directory and then in the parent directory.
1260 If found, open it for use when searching for prefixes.
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001261
1262 Write the 'home' variable of pyvenv.cfg into calculate->argv0_path. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001263static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001264calculate_read_pyenv(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001265{
Victor Stinner331a6a52019-05-27 16:39:22 +02001266 PyStatus status;
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001267 FILE *env_file = NULL;
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001268
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001269 status = calculate_open_pyenv(calculate, &env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001270 if (_PyStatus_EXCEPTION(status)) {
1271 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001272 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001273 if (env_file == NULL) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001274 /* pyvenv.cfg not found */
1275 return _PyStatus_OK();
Vinay Sajip7ded1f02012-05-26 03:45:29 +01001276 }
1277
Victor Stinner0327bde2017-11-23 17:03:20 +01001278 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001279 wchar_t *home = NULL;
1280 status = _Py_FindEnvConfigValue(env_file, L"home", &home);
1281 if (_PyStatus_EXCEPTION(status)) {
1282 fclose(env_file);
1283 return status;
1284 }
Victor Stinner221fd842019-09-25 02:54:25 +02001285
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001286 if (home) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001287 PyMem_RawFree(calculate->argv0_path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001288 calculate->argv0_path = home;
Just van Rossum52e14d62002-12-30 22:08:05 +00001289 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001290 fclose(env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +02001291 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001292}
Just van Rossum52e14d62002-12-30 22:08:05 +00001293
Guido van Rossum305e5d01997-04-11 17:18:45 +00001294
Victor Stinner331a6a52019-05-27 16:39:22 +02001295static PyStatus
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001296calculate_zip_path(PyCalculatePath *calculate)
Victor Stinner0327bde2017-11-23 17:03:20 +01001297{
Victor Stinner8510f432020-03-10 09:53:09 +01001298 PyStatus res;
1299
1300 /* Path: <PLATLIBDIR> / "python00.zip" */
1301 wchar_t *path = joinpath2(calculate->platlibdir_macro, L"python00.zip");
1302 if (path == NULL) {
1303 return _PyStatus_NO_MEMORY();
1304 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001305
Victor Stinner0327bde2017-11-23 17:03:20 +01001306 if (calculate->prefix_found > 0) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001307 /* Use the reduced prefix returned by Py_GetPrefix()
1308
Victor Stinner8510f432020-03-10 09:53:09 +01001309 Path: <basename(basename(prefix))> / <PLATLIBDIR> / "python00.zip" */
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001310 wchar_t *parent = _PyMem_RawWcsdup(calculate->prefix);
1311 if (parent == NULL) {
Victor Stinner8510f432020-03-10 09:53:09 +01001312 res = _PyStatus_NO_MEMORY();
1313 goto done;
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001314 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001315 reduce(parent);
1316 reduce(parent);
Victor Stinner8510f432020-03-10 09:53:09 +01001317 calculate->zip_path = joinpath2(parent, path);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001318 PyMem_RawFree(parent);
Victor Stinnerd4341102017-11-23 00:12:09 +01001319 }
1320 else {
Victor Stinner8510f432020-03-10 09:53:09 +01001321 calculate->zip_path = joinpath2(calculate->prefix_macro, path);
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001322 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001323
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001324 if (calculate->zip_path == NULL) {
Victor Stinner8510f432020-03-10 09:53:09 +01001325 res = _PyStatus_NO_MEMORY();
1326 goto done;
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001327 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001328
1329 /* Replace "00" with version */
1330 size_t len = wcslen(calculate->zip_path);
1331 calculate->zip_path[len - 6] = VERSION[0];
1332 calculate->zip_path[len - 5] = VERSION[2];
1333
Victor Stinner8510f432020-03-10 09:53:09 +01001334 res = _PyStatus_OK();
1335
1336done:
1337 PyMem_RawFree(path);
1338 return res;
Victor Stinner0327bde2017-11-23 17:03:20 +01001339}
1340
1341
Victor Stinner331a6a52019-05-27 16:39:22 +02001342static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001343calculate_module_search_path(PyCalculatePath *calculate,
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001344 _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001345{
1346 /* Calculate size of return buffer */
1347 size_t bufsz = 0;
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001348 if (calculate->pythonpath_env != NULL) {
1349 bufsz += wcslen(calculate->pythonpath_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001350 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001351
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001352 wchar_t *defpath = calculate->pythonpath_macro;
1353 size_t prefixsz = wcslen(calculate->prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001354 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001355 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001356
Victor Stinner3939c322019-06-25 15:02:43 +02001357 if (!_Py_isabs(defpath)) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001358 /* Paths are relative to prefix */
1359 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001360 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001361
Victor Stinner0327bde2017-11-23 17:03:20 +01001362 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001363 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001364 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001365 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001366 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001367 break;
1368 }
1369 defpath = delim + 1;
1370 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001371
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001372 bufsz += wcslen(calculate->zip_path) + 1;
1373 bufsz += wcslen(calculate->exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001374
Victor Stinner0327bde2017-11-23 17:03:20 +01001375 /* Allocate the buffer */
1376 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001377 if (buf == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +02001378 return _PyStatus_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001379 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001380 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001381
Victor Stinner72967a42013-11-16 01:22:04 +01001382 /* Run-time value of $PYTHONPATH goes first */
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001383 if (calculate->pythonpath_env) {
1384 wcscpy(buf, calculate->pythonpath_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001385 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001386 }
Victor Stinner72967a42013-11-16 01:22:04 +01001387
1388 /* Next is the default zip path */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001389 wcscat(buf, calculate->zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001390 wcscat(buf, delimiter);
1391
1392 /* Next goes merge of compile-time $PYTHONPATH with
1393 * dynamically located prefix.
1394 */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001395 defpath = calculate->pythonpath_macro;
Victor Stinner72967a42013-11-16 01:22:04 +01001396 while (1) {
1397 wchar_t *delim = wcschr(defpath, DELIM);
1398
Victor Stinner3939c322019-06-25 15:02:43 +02001399 if (!_Py_isabs(defpath)) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001400 wcscat(buf, calculate->prefix);
1401 if (prefixsz >= 2 && calculate->prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001402 defpath[0] != (delim ? DELIM : L'\0'))
1403 {
1404 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001405 wcscat(buf, separator);
1406 }
Victor Stinner72967a42013-11-16 01:22:04 +01001407 }
1408
1409 if (delim) {
1410 size_t len = delim - defpath + 1;
1411 size_t end = wcslen(buf) + len;
1412 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001413 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001414 }
1415 else {
1416 wcscat(buf, defpath);
1417 break;
1418 }
1419 defpath = delim + 1;
1420 }
1421 wcscat(buf, delimiter);
1422
1423 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001424 wcscat(buf, calculate->exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001425
Victor Stinner331a6a52019-05-27 16:39:22 +02001426 pathconfig->module_search_path = buf;
1427 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001428}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001429
Victor Stinner0327bde2017-11-23 17:03:20 +01001430
Victor Stinner331a6a52019-05-27 16:39:22 +02001431static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +02001432calculate_init(PyCalculatePath *calculate, const PyConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001433{
Victor Stinner0327bde2017-11-23 17:03:20 +01001434 size_t len;
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001435 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001436 if (path) {
1437 calculate->path_env = Py_DecodeLocale(path, &len);
1438 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001439 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001440 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001441 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001442
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001443 /* Decode macros */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001444 calculate->pythonpath_macro = Py_DecodeLocale(PYTHONPATH, &len);
1445 if (!calculate->pythonpath_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001446 return DECODE_LOCALE_ERR("PYTHONPATH macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001447 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001448 calculate->prefix_macro = Py_DecodeLocale(PREFIX, &len);
1449 if (!calculate->prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001450 return DECODE_LOCALE_ERR("PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001451 }
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001452 calculate->exec_prefix_macro = Py_DecodeLocale(EXEC_PREFIX, &len);
1453 if (!calculate->exec_prefix_macro) {
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001454 return DECODE_LOCALE_ERR("EXEC_PREFIX macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001455 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001456 calculate->vpath_macro = Py_DecodeLocale(VPATH, &len);
1457 if (!calculate->vpath_macro) {
1458 return DECODE_LOCALE_ERR("VPATH macro", len);
1459 }
Victor Stinner8510f432020-03-10 09:53:09 +01001460 calculate->platlibdir_macro = Py_DecodeLocale(PLATLIBDIR, &len);
1461 if (!calculate->platlibdir_macro) {
1462 return DECODE_LOCALE_ERR("PLATLIBDIR macro", len);
1463 }
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001464
Victor Stinner8510f432020-03-10 09:53:09 +01001465 calculate->lib_python = Py_DecodeLocale(PLATLIBDIR "/python" VERSION, &len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001466 if (!calculate->lib_python) {
Victor Stinner8510f432020-03-10 09:53:09 +01001467 return DECODE_LOCALE_ERR("VERSION macro", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001468 }
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001469
1470 calculate->warnings = config->pathconfig_warnings;
1471 calculate->pythonpath_env = config->pythonpath_env;
1472
Victor Stinner331a6a52019-05-27 16:39:22 +02001473 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001474}
1475
1476
1477static void
1478calculate_free(PyCalculatePath *calculate)
1479{
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001480 PyMem_RawFree(calculate->pythonpath_macro);
1481 PyMem_RawFree(calculate->prefix_macro);
1482 PyMem_RawFree(calculate->exec_prefix_macro);
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001483 PyMem_RawFree(calculate->vpath_macro);
Victor Stinner8510f432020-03-10 09:53:09 +01001484 PyMem_RawFree(calculate->platlibdir_macro);
Victor Stinner0327bde2017-11-23 17:03:20 +01001485 PyMem_RawFree(calculate->lib_python);
1486 PyMem_RawFree(calculate->path_env);
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001487 PyMem_RawFree(calculate->zip_path);
1488 PyMem_RawFree(calculate->argv0_path);
1489 PyMem_RawFree(calculate->prefix);
1490 PyMem_RawFree(calculate->exec_prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +01001491}
1492
1493
Victor Stinner331a6a52019-05-27 16:39:22 +02001494static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001495calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001496{
Victor Stinner331a6a52019-05-27 16:39:22 +02001497 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +01001498
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001499 if (pathconfig->program_full_path == NULL) {
Victor Stinner03a8a562019-10-04 02:22:39 +02001500 status = calculate_program(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001501 if (_PyStatus_EXCEPTION(status)) {
1502 return status;
1503 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001504 }
1505
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001506 status = calculate_argv0_path(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001507 if (_PyStatus_EXCEPTION(status)) {
1508 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001509 }
1510
Victor Stinner221fd842019-09-25 02:54:25 +02001511 /* If a pyvenv.cfg configure file is found,
1512 argv0_path is overriden with its 'home' variable. */
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001513 status = calculate_read_pyenv(calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001514 if (_PyStatus_EXCEPTION(status)) {
1515 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001516 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001517
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001518 status = calculate_prefix(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001519 if (_PyStatus_EXCEPTION(status)) {
1520 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001521 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001522
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001523 status = calculate_zip_path(calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001524 if (_PyStatus_EXCEPTION(status)) {
1525 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001526 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001527
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001528 status = calculate_exec_prefix(calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001529 if (_PyStatus_EXCEPTION(status)) {
1530 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001531 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001532
Victor Stinner03a8a562019-10-04 02:22:39 +02001533 if ((!calculate->prefix_found || !calculate->exec_prefix_found)
1534 && calculate->warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001535 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001536 fprintf(stderr,
1537 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1538 }
1539
Victor Stinnere2677932019-09-21 01:50:16 +02001540 if (pathconfig->module_search_path == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001541 status = calculate_module_search_path(calculate, pathconfig);
Victor Stinnere2677932019-09-21 01:50:16 +02001542 if (_PyStatus_EXCEPTION(status)) {
1543 return status;
1544 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001545 }
1546
Victor Stinner331a6a52019-05-27 16:39:22 +02001547 if (pathconfig->prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001548 status = calculate_set_prefix(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001549 if (_PyStatus_EXCEPTION(status)) {
1550 return status;
1551 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001552 }
1553
Victor Stinner331a6a52019-05-27 16:39:22 +02001554 if (pathconfig->exec_prefix == NULL) {
Victor Stinnerabd7cd82019-10-04 15:25:50 +02001555 status = calculate_set_exec_prefix(calculate, pathconfig);
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001556 if (_PyStatus_EXCEPTION(status)) {
1557 return status;
1558 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001559 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001560 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001561}
1562
1563
Victor Stinner85ce0a72019-09-24 00:55:48 +02001564/* Calculate the Python path configuration.
1565
1566 Inputs:
1567
1568 - PATH environment variable
1569 - Macros: PYTHONPATH, PREFIX, EXEC_PREFIX, VERSION (ex: "3.9").
1570 PREFIX and EXEC_PREFIX are generated by the configure script.
1571 PYTHONPATH macro is the default search path.
1572 - pybuilddir.txt file
1573 - pyvenv.cfg configuration file
1574 - PyConfig fields ('config' function argument):
1575
1576 - pathconfig_warnings
1577 - pythonpath_env (PYTHONPATH environment variable)
1578
1579 - _PyPathConfig fields ('pathconfig' function argument):
1580
1581 - program_name: see config_init_program_name()
1582 - home: Py_SetPythonHome() or PYTHONHOME environment variable
1583
1584 - current working directory: see copy_absolute()
1585
1586 Outputs, 'pathconfig' fields:
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001587
1588 - program_full_path
1589 - module_search_path
1590 - prefix
1591 - exec_prefix
1592
Victor Stinner85ce0a72019-09-24 00:55:48 +02001593 If a field is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001594PyStatus
1595_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001596{
Victor Stinner331a6a52019-05-27 16:39:22 +02001597 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001598 PyCalculatePath calculate;
1599 memset(&calculate, 0, sizeof(calculate));
1600
Victor Stinner331a6a52019-05-27 16:39:22 +02001601 status = calculate_init(&calculate, config);
1602 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001603 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001604 }
1605
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001606 status = calculate_path(&calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001607 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001608 goto done;
1609 }
1610
Victor Stinnerc02b41b2019-10-04 19:53:43 +02001611 /* program_full_path must an either an empty string or an absolute path */
1612 assert(wcslen(pathconfig->program_full_path) == 0
1613 || _Py_isabs(pathconfig->program_full_path));
1614
Victor Stinner331a6a52019-05-27 16:39:22 +02001615 status = _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001616
Victor Stinner9316ee42017-11-25 03:17:57 +01001617done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001618 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001619 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001620}
Victor Stinner46972b72017-11-24 22:55:40 +01001621
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001622#ifdef __cplusplus
1623}
1624#endif