blob: f60fe3c015bb0207a7d6886cd8a1f42dc778d5db [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
98 * these authomatic path computations.
99 *
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 Stinner9316ee42017-11-25 03:17:57 +0100116#define DECODE_LOCALE_ERR(NAME, LEN) \
117 ((LEN) == (size_t)-2) \
Victor Stinner331a6a52019-05-27 16:39:22 +0200118 ? _PyStatus_ERR("cannot decode " NAME) \
119 : _PyStatus_NO_MEMORY()
Victor Stinner9316ee42017-11-25 03:17:57 +0100120
Victor Stinner331a6a52019-05-27 16:39:22 +0200121#define PATHLEN_ERR() _PyStatus_ERR("path configuration: path too long")
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100122
Victor Stinner0327bde2017-11-23 17:03:20 +0100123typedef struct {
124 wchar_t *path_env; /* PATH environment variable */
Victor Stinner0327bde2017-11-23 17:03:20 +0100125
Victor Stinner0327bde2017-11-23 17:03:20 +0100126 wchar_t *pythonpath; /* PYTHONPATH define */
127 wchar_t *prefix; /* PREFIX define */
128 wchar_t *exec_prefix; /* EXEC_PREFIX define */
129
130 wchar_t *lib_python; /* "lib/pythonX.Y" */
131 wchar_t argv0_path[MAXPATHLEN+1];
132 wchar_t zip_path[MAXPATHLEN+1]; /* ".../lib/pythonXY.zip" */
133
134 int prefix_found; /* found platform independent libraries? */
135 int exec_prefix_found; /* found the platform dependent libraries? */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200136
137 int warnings;
138 const wchar_t *pythonpath_env;
Victor Stinner0327bde2017-11-23 17:03:20 +0100139} PyCalculatePath;
140
141static const wchar_t delimiter[2] = {DELIM, '\0'};
142static const wchar_t separator[2] = {SEP, '\0'};
Victor Stinner0327bde2017-11-23 17:03:20 +0100143
Martin v. Löwis790465f2008-04-05 20:41:37 +0000144
Victor Stinner91afbb62015-03-24 12:16:28 +0100145/* Get file status. Encode the path to the locale encoding. */
Victor Stinner91afbb62015-03-24 12:16:28 +0100146static int
147_Py_wstat(const wchar_t* path, struct stat *buf)
148{
149 int err;
150 char *fname;
Victor Stinner9dd76202017-12-21 16:20:32 +0100151 fname = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner91afbb62015-03-24 12:16:28 +0100152 if (fname == NULL) {
153 errno = EINVAL;
154 return -1;
155 }
156 err = stat(fname, buf);
Victor Stinner9dd76202017-12-21 16:20:32 +0100157 PyMem_RawFree(fname);
Victor Stinner91afbb62015-03-24 12:16:28 +0100158 return err;
159}
160
Victor Stinner0327bde2017-11-23 17:03:20 +0100161
Guido van Rossum305e5d01997-04-11 17:18:45 +0000162static void
Martin v. Löwis790465f2008-04-05 20:41:37 +0000163reduce(wchar_t *dir)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000164{
Martin v. Löwis790465f2008-04-05 20:41:37 +0000165 size_t i = wcslen(dir);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100166 while (i > 0 && dir[i] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000167 --i;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100168 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000169 dir[i] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +0000170}
Guido van Rossumd29806c1998-01-19 22:06:22 +0000171
Victor Stinner0327bde2017-11-23 17:03:20 +0100172
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100173/* Is file, not directory */
Guido van Rossum305e5d01997-04-11 17:18:45 +0000174static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100175isfile(const wchar_t *filename)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000176{
Fred Drakeedabdc12000-07-08 06:16:37 +0000177 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100178 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000179 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100180 }
181 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000182 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100183 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000184 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000185}
186
187
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100188/* Is module -- check for .pyc too */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000189static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100190ismodule(wchar_t *filename, size_t filename_len)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000191{
Victor Stinner0327bde2017-11-23 17:03:20 +0100192 if (isfile(filename)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000193 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100194 }
Guido van Rossumd29806c1998-01-19 22:06:22 +0000195
Fred Drakeedabdc12000-07-08 06:16:37 +0000196 /* Check for the compiled version of prefix. */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100197 if (wcslen(filename) + 2 <= filename_len) {
Brett Cannonf299abd2015-04-13 14:21:02 -0400198 wcscat(filename, L"c");
Victor Stinner0327bde2017-11-23 17:03:20 +0100199 if (isfile(filename)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000200 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100201 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000202 }
203 return 0;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000204}
205
206
Victor Stinner0327bde2017-11-23 17:03:20 +0100207/* Is executable file */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000208static int
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100209isxfile(const wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000210{
Fred Drakeedabdc12000-07-08 06:16:37 +0000211 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100212 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000213 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100214 }
215 if (!S_ISREG(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000216 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100217 }
218 if ((buf.st_mode & 0111) == 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000219 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100220 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000221 return 1;
Guido van Rossumd29806c1998-01-19 22:06:22 +0000222}
223
224
Victor Stinner0327bde2017-11-23 17:03:20 +0100225/* Is directory */
Guido van Rossumd29806c1998-01-19 22:06:22 +0000226static int
Victor Stinner0327bde2017-11-23 17:03:20 +0100227isdir(wchar_t *filename)
Guido van Rossumd29806c1998-01-19 22:06:22 +0000228{
Fred Drakeedabdc12000-07-08 06:16:37 +0000229 struct stat buf;
Victor Stinner0327bde2017-11-23 17:03:20 +0100230 if (_Py_wstat(filename, &buf) != 0) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000231 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100232 }
233 if (!S_ISDIR(buf.st_mode)) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000234 return 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100235 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000236 return 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000237}
238
239
Tim Petersec8c5a92004-08-08 01:00:47 +0000240/* Add a path component, by appending stuff to buffer.
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100241 buflen: 'buffer' length in characters including trailing NUL. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200242static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100243joinpath(wchar_t *buffer, const wchar_t *stuff, size_t buflen)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000244{
Fred Drakeedabdc12000-07-08 06:16:37 +0000245 size_t n, k;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100246 if (stuff[0] != SEP) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000247 n = wcslen(buffer);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100248 if (n >= buflen) {
249 return PATHLEN_ERR();
250 }
251
252 if (n > 0 && buffer[n-1] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000253 buffer[n++] = SEP;
Victor Stinner0327bde2017-11-23 17:03:20 +0100254 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000255 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100256 else {
257 n = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100258 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100259
Martin v. Löwis790465f2008-04-05 20:41:37 +0000260 k = wcslen(stuff);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100261 if (n + k >= buflen) {
262 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100263 }
Martin v. Löwis790465f2008-04-05 20:41:37 +0000264 wcsncpy(buffer+n, stuff, k);
Fred Drakeedabdc12000-07-08 06:16:37 +0000265 buffer[n+k] = '\0';
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100266
Victor Stinner331a6a52019-05-27 16:39:22 +0200267 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000268}
269
Victor Stinner0327bde2017-11-23 17:03:20 +0100270
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100271static inline int
272safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
273{
274 size_t srclen = wcslen(src);
275 if (n <= srclen) {
276 dst[0] = L'\0';
277 return -1;
278 }
279 memcpy(dst, src, (srclen + 1) * sizeof(wchar_t));
280 return 0;
281}
282
283
Guido van Rossume296ced2001-09-28 20:00:29 +0000284/* copy_absolute requires that path be allocated at least
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100285 'pathlen' characters (including trailing NUL). */
Victor Stinner331a6a52019-05-27 16:39:22 +0200286static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100287copy_absolute(wchar_t *path, const wchar_t *p, size_t pathlen)
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000288{
Victor Stinner0327bde2017-11-23 17:03:20 +0100289 if (p[0] == SEP) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100290 if (safe_wcscpy(path, p, pathlen) < 0) {
291 return PATHLEN_ERR();
292 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100293 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000294 else {
Victor Stinnerf4061da2010-10-14 12:37:19 +0000295 if (!_Py_wgetcwd(path, pathlen)) {
Victor Stinner4f3abb02010-10-07 23:29:18 +0000296 /* unable to get the current directory */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100297 if (safe_wcscpy(path, p, pathlen) < 0) {
298 return PATHLEN_ERR();
299 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200300 return _PyStatus_OK();
Victor Stinner4f3abb02010-10-07 23:29:18 +0000301 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100302 if (p[0] == '.' && p[1] == SEP) {
Guido van Rossume296ced2001-09-28 20:00:29 +0000303 p += 2;
Victor Stinner0327bde2017-11-23 17:03:20 +0100304 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200305 PyStatus status = joinpath(path, p, pathlen);
306 if (_PyStatus_EXCEPTION(status)) {
307 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100308 }
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000309 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200310 return _PyStatus_OK();
Jeremy Hylton7198ba92000-09-25 17:00:24 +0000311}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000312
Victor Stinner0327bde2017-11-23 17:03:20 +0100313
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100314/* path_len: path length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200315static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100316absolutize(wchar_t *path, size_t path_len)
Guido van Rossume296ced2001-09-28 20:00:29 +0000317{
Victor Stinner0327bde2017-11-23 17:03:20 +0100318 if (path[0] == SEP) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200319 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100320 }
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100321
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100322 wchar_t abs_path[MAXPATHLEN+1];
Victor Stinner331a6a52019-05-27 16:39:22 +0200323 PyStatus status = copy_absolute(abs_path, path, Py_ARRAY_LENGTH(abs_path));
324 if (_PyStatus_EXCEPTION(status)) {
325 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100326 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100327
328 if (safe_wcscpy(path, abs_path, path_len) < 0) {
329 return PATHLEN_ERR();
330 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200331 return _PyStatus_OK();
Guido van Rossume296ced2001-09-28 20:00:29 +0000332}
333
Victor Stinner0327bde2017-11-23 17:03:20 +0100334
E. M. Bray7a7693e2018-10-05 13:38:50 +0200335#if defined(__CYGWIN__) || defined(__MINGW32__)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200336#ifndef EXE_SUFFIX
337#define EXE_SUFFIX L".exe"
338#endif
339
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100340/* pathlen: 'path' length in characters including trailing NUL */
Victor Stinner331a6a52019-05-27 16:39:22 +0200341static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100342add_exe_suffix(wchar_t *progpath, size_t progpathlen)
E. M. Bray7a7693e2018-10-05 13:38:50 +0200343{
344 /* Check for already have an executable suffix */
345 size_t n = wcslen(progpath);
346 size_t s = wcslen(EXE_SUFFIX);
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100347 if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200348 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200349 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100350
351 if (n + s >= progpathlen) {
352 return PATHLEN_ERR();
353 }
354 wcsncpy(progpath + n, EXE_SUFFIX, s);
355 progpath[n+s] = '\0';
356
357 if (!isxfile(progpath)) {
358 /* Path that added suffix is invalid: truncate (remove suffix) */
359 progpath[n] = '\0';
360 }
361
Victor Stinner331a6a52019-05-27 16:39:22 +0200362 return _PyStatus_OK();
E. M. Bray7a7693e2018-10-05 13:38:50 +0200363}
364#endif
365
366
Guido van Rossume296ced2001-09-28 20:00:29 +0000367/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000368 bytes long.
369*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200370static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200371search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
372 wchar_t *prefix, size_t prefix_len, int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000373{
Victor Stinner331a6a52019-05-27 16:39:22 +0200374 PyStatus status;
Fred Drakeedabdc12000-07-08 06:16:37 +0000375 size_t n;
Martin v. Löwis790465f2008-04-05 20:41:37 +0000376 wchar_t *vpath;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000377
Fred Drakeedabdc12000-07-08 06:16:37 +0000378 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200379 if (pathconfig->home) {
380 if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100381 return PATHLEN_ERR();
382 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100383 wchar_t *delim = wcschr(prefix, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100384 if (delim) {
Martin v. Löwis790465f2008-04-05 20:41:37 +0000385 *delim = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100386 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200387 status = joinpath(prefix, calculate->lib_python, prefix_len);
388 if (_PyStatus_EXCEPTION(status)) {
389 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100390 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200391 status = joinpath(prefix, LANDMARK, prefix_len);
392 if (_PyStatus_EXCEPTION(status)) {
393 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100394 }
395 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200396 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000397 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000398
Fred Drakeedabdc12000-07-08 06:16:37 +0000399 /* Check to see if argv[0] is in the build directory */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100400 if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
401 return PATHLEN_ERR();
402 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200403 status = joinpath(prefix, L"Modules/Setup.local", prefix_len);
404 if (_PyStatus_EXCEPTION(status)) {
405 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100406 }
407
Victor Stinner9316ee42017-11-25 03:17:57 +0100408 if (isfile(prefix)) {
Neil Schemenauer6cf07022001-01-24 17:13:11 +0000409 /* Check VPATH to see if argv0_path is in the build directory. */
Victor Stinnerf6a271a2014-08-01 12:28:48 +0200410 vpath = Py_DecodeLocale(VPATH, NULL);
Victor Stinner21582312010-10-23 00:13:28 +0000411 if (vpath != NULL) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100412 if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) {
413 return PATHLEN_ERR();
414 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200415 status = joinpath(prefix, vpath, prefix_len);
Victor Stinner1a7425f2013-07-07 16:25:15 +0200416 PyMem_RawFree(vpath);
Victor Stinner331a6a52019-05-27 16:39:22 +0200417 if (_PyStatus_EXCEPTION(status)) {
418 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100419 }
420
Victor Stinner331a6a52019-05-27 16:39:22 +0200421 status = joinpath(prefix, L"Lib", prefix_len);
422 if (_PyStatus_EXCEPTION(status)) {
423 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100424 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200425 status = joinpath(prefix, LANDMARK, prefix_len);
426 if (_PyStatus_EXCEPTION(status)) {
427 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100428 }
429
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100430 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100431 *found = -1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200432 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100433 }
Victor Stinner21582312010-10-23 00:13:28 +0000434 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000435 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000436
Fred Drakeedabdc12000-07-08 06:16:37 +0000437 /* Search from argv0_path, until root is found */
Victor Stinner331a6a52019-05-27 16:39:22 +0200438 status = copy_absolute(prefix, calculate->argv0_path, prefix_len);
439 if (_PyStatus_EXCEPTION(status)) {
440 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100441 }
442
Fred Drakeedabdc12000-07-08 06:16:37 +0000443 do {
Victor Stinner9316ee42017-11-25 03:17:57 +0100444 n = wcslen(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200445 status = joinpath(prefix, calculate->lib_python, prefix_len);
446 if (_PyStatus_EXCEPTION(status)) {
447 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100448 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200449 status = joinpath(prefix, LANDMARK, prefix_len);
450 if (_PyStatus_EXCEPTION(status)) {
451 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100452 }
453
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100454 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100455 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200456 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100457 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100458 prefix[n] = L'\0';
459 reduce(prefix);
460 } while (prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000461
Fred Drakeedabdc12000-07-08 06:16:37 +0000462 /* Look at configure's PREFIX */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100463 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
464 return PATHLEN_ERR();
465 }
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 Stinner331a6a52019-05-27 16:39:22 +0200470 status = joinpath(prefix, LANDMARK, prefix_len);
471 if (_PyStatus_EXCEPTION(status)) {
472 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100473 }
474
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100475 if (ismodule(prefix, prefix_len)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100476 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200477 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100478 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000479
Fred Drakeedabdc12000-07-08 06:16:37 +0000480 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100481 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200482 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000483}
484
485
Victor Stinner331a6a52019-05-27 16:39:22 +0200486static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200487calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
488 wchar_t *prefix, size_t prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100489{
Victor Stinner331a6a52019-05-27 16:39:22 +0200490 PyStatus status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100491
Victor Stinner3f5409a2019-09-23 19:50:27 +0200492 status = search_for_prefix(calculate, pathconfig, prefix, prefix_len,
493 &calculate->prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200494 if (_PyStatus_EXCEPTION(status)) {
495 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100496 }
497
Victor Stinner0327bde2017-11-23 17:03:20 +0100498 if (!calculate->prefix_found) {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200499 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100500 fprintf(stderr,
501 "Could not find platform independent libraries <prefix>\n");
502 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100503 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
504 return PATHLEN_ERR();
505 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200506 status = joinpath(prefix, calculate->lib_python, prefix_len);
507 if (_PyStatus_EXCEPTION(status)) {
508 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100509 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100510 }
511 else {
Victor Stinner9316ee42017-11-25 03:17:57 +0100512 reduce(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100513 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200514 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100515}
516
517
Victor Stinner331a6a52019-05-27 16:39:22 +0200518static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100519calculate_reduce_prefix(PyCalculatePath *calculate,
520 wchar_t *prefix, size_t prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100521{
522 /* Reduce prefix and exec_prefix to their essence,
523 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
524 * If we're loading relative to the build directory,
525 * return the compiled-in defaults instead.
526 */
527 if (calculate->prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100528 reduce(prefix);
529 reduce(prefix);
Victor Stinner0327bde2017-11-23 17:03:20 +0100530 /* The prefix is the root directory, but reduce() chopped
531 * off the "/". */
Victor Stinner9316ee42017-11-25 03:17:57 +0100532 if (!prefix[0]) {
533 wcscpy(prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100534 }
535 }
536 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100537 if (safe_wcscpy(prefix, calculate->prefix, prefix_len) < 0) {
538 return PATHLEN_ERR();
539 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100540 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200541 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100542}
543
544
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000545/* search_for_exec_prefix requires that argv0_path be no more than
Guido van Rossume296ced2001-09-28 20:00:29 +0000546 MAXPATHLEN bytes long.
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000547*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200548static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200549search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100550 wchar_t *exec_prefix, size_t exec_prefix_len,
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100551 int *found)
Guido van Rossum305e5d01997-04-11 17:18:45 +0000552{
Victor Stinner331a6a52019-05-27 16:39:22 +0200553 PyStatus status;
Fred Drakeedabdc12000-07-08 06:16:37 +0000554 size_t n;
Guido van Rossum305e5d01997-04-11 17:18:45 +0000555
Fred Drakeedabdc12000-07-08 06:16:37 +0000556 /* If PYTHONHOME is set, we believe it unconditionally */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200557 if (pathconfig->home) {
558 wchar_t *delim = wcschr(pathconfig->home, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100559 if (delim) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100560 if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) {
561 return PATHLEN_ERR();
562 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100563 }
564 else {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200565 if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100566 return PATHLEN_ERR();
567 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100568 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200569 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
570 if (_PyStatus_EXCEPTION(status)) {
571 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100572 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200573 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
574 if (_PyStatus_EXCEPTION(status)) {
575 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100576 }
577 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200578 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000579 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000580
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000581 /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
582 is written by setup.py and contains the relative path to the location
583 of shared library modules. */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100584 if (safe_wcscpy(exec_prefix, calculate->argv0_path, exec_prefix_len) < 0) {
585 return PATHLEN_ERR();
586 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200587 status = joinpath(exec_prefix, L"pybuilddir.txt", exec_prefix_len);
588 if (_PyStatus_EXCEPTION(status)) {
589 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100590 }
591
Victor Stinner9316ee42017-11-25 03:17:57 +0100592 if (isfile(exec_prefix)) {
593 FILE *f = _Py_wfopen(exec_prefix, L"rb");
Victor Stinner0327bde2017-11-23 17:03:20 +0100594 if (f == NULL) {
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000595 errno = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100596 }
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000597 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100598 char buf[MAXPATHLEN + 1];
599 n = fread(buf, 1, Py_ARRAY_LENGTH(buf) - 1, f);
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000600 buf[n] = '\0';
601 fclose(f);
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100602
Victor Stinner5f9cf232019-03-19 01:46:25 +0100603 wchar_t *pybuilddir;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100604 size_t dec_len;
Victor Stinner5f9cf232019-03-19 01:46:25 +0100605 pybuilddir = _Py_DecodeUTF8_surrogateescape(buf, n, &dec_len);
606 if (!pybuilddir) {
607 return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len);
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000608 }
Victor Stinner5f9cf232019-03-19 01:46:25 +0100609
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100610 if (safe_wcscpy(exec_prefix, calculate->argv0_path, exec_prefix_len) < 0) {
611 return PATHLEN_ERR();
612 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200613 status = joinpath(exec_prefix, pybuilddir, exec_prefix_len);
Victor Stinner5f9cf232019-03-19 01:46:25 +0100614 PyMem_RawFree(pybuilddir );
Victor Stinner331a6a52019-05-27 16:39:22 +0200615 if (_PyStatus_EXCEPTION(status)) {
616 return status;
Victor Stinner5f9cf232019-03-19 01:46:25 +0100617 }
618
619 *found = -1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200620 return _PyStatus_OK();
Antoine Pitroue9b428f2010-08-13 22:25:01 +0000621 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000622 }
Jeremy Hylton847a9962000-05-26 21:49:07 +0000623
Fred Drakeedabdc12000-07-08 06:16:37 +0000624 /* Search from argv0_path, until root is found */
Victor Stinner331a6a52019-05-27 16:39:22 +0200625 status = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len);
626 if (_PyStatus_EXCEPTION(status)) {
627 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100628 }
629
Fred Drakeedabdc12000-07-08 06:16:37 +0000630 do {
Victor Stinner9316ee42017-11-25 03:17:57 +0100631 n = wcslen(exec_prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200632 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
633 if (_PyStatus_EXCEPTION(status)) {
634 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100635 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200636 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
637 if (_PyStatus_EXCEPTION(status)) {
638 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100639 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100640 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100641 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200642 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100643 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100644 exec_prefix[n] = L'\0';
645 reduce(exec_prefix);
646 } while (exec_prefix[0]);
Guido van Rossum305e5d01997-04-11 17:18:45 +0000647
Fred Drakeedabdc12000-07-08 06:16:37 +0000648 /* Look at configure's EXEC_PREFIX */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100649 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
650 return PATHLEN_ERR();
651 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200652 status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len);
653 if (_PyStatus_EXCEPTION(status)) {
654 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100655 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200656 status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len);
657 if (_PyStatus_EXCEPTION(status)) {
658 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100659 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100660 if (isdir(exec_prefix)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100661 *found = 1;
Victor Stinner331a6a52019-05-27 16:39:22 +0200662 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100663 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000664
Fred Drakeedabdc12000-07-08 06:16:37 +0000665 /* Fail */
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100666 *found = 0;
Victor Stinner331a6a52019-05-27 16:39:22 +0200667 return _PyStatus_OK();
Guido van Rossum305e5d01997-04-11 17:18:45 +0000668}
669
Guido van Rossum305e5d01997-04-11 17:18:45 +0000670
Victor Stinner331a6a52019-05-27 16:39:22 +0200671static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200672calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100673 wchar_t *exec_prefix, size_t exec_prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100674{
Victor Stinner331a6a52019-05-27 16:39:22 +0200675 PyStatus status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100676
Victor Stinner3f5409a2019-09-23 19:50:27 +0200677 status = search_for_exec_prefix(calculate, pathconfig,
678 exec_prefix, exec_prefix_len,
679 &calculate->exec_prefix_found);
Victor Stinner331a6a52019-05-27 16:39:22 +0200680 if (_PyStatus_EXCEPTION(status)) {
681 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100682 }
683
Victor Stinner0327bde2017-11-23 17:03:20 +0100684 if (!calculate->exec_prefix_found) {
Victor Stinner3f5409a2019-09-23 19:50:27 +0200685 if (calculate->warnings) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100686 fprintf(stderr,
687 "Could not find platform dependent libraries <exec_prefix>\n");
688 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100689 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
690 return PATHLEN_ERR();
691 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200692 status = joinpath(exec_prefix, L"lib/lib-dynload", exec_prefix_len);
693 if (_PyStatus_EXCEPTION(status)) {
694 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100695 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100696 }
697 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
Victor Stinner331a6a52019-05-27 16:39:22 +0200698 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100699}
700
701
Victor Stinner331a6a52019-05-27 16:39:22 +0200702static PyStatus
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100703calculate_reduce_exec_prefix(PyCalculatePath *calculate,
704 wchar_t *exec_prefix, size_t exec_prefix_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100705{
706 if (calculate->exec_prefix_found > 0) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100707 reduce(exec_prefix);
708 reduce(exec_prefix);
709 reduce(exec_prefix);
710 if (!exec_prefix[0]) {
711 wcscpy(exec_prefix, separator);
Victor Stinner0327bde2017-11-23 17:03:20 +0100712 }
713 }
714 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100715 if (safe_wcscpy(exec_prefix, calculate->exec_prefix, exec_prefix_len) < 0) {
716 return PATHLEN_ERR();
717 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100718 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200719 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100720}
721
722
Victor Stinner331a6a52019-05-27 16:39:22 +0200723static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +0200724calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100725{
Victor Stinner331a6a52019-05-27 16:39:22 +0200726 PyStatus status;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100727 wchar_t program_full_path[MAXPATHLEN + 1];
728 const size_t program_full_path_len = Py_ARRAY_LENGTH(program_full_path);
Victor Stinnerb64de462017-12-01 18:27:09 +0100729 memset(program_full_path, 0, sizeof(program_full_path));
Victor Stinner9316ee42017-11-25 03:17:57 +0100730
Victor Stinnerb9197952017-11-23 19:02:04 +0100731#ifdef __APPLE__
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100732 char execpath[MAXPATHLEN + 1];
Victor Stinnerb9197952017-11-23 19:02:04 +0100733#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100734 uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100735#else
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100736 unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
Victor Stinnerb9197952017-11-23 19:02:04 +0100737#endif
Victor Stinnerb9197952017-11-23 19:02:04 +0100738#endif
739
Victor Stinner0327bde2017-11-23 17:03:20 +0100740 /* If there is no slash in the argv0 path, then we have to
741 * assume python is on the user's $PATH, since there's no
742 * other way to find a directory to start the search from. If
743 * $PATH isn't exported, you lose.
744 */
Victor Stinner3f5409a2019-09-23 19:50:27 +0200745 if (wcschr(pathconfig->program_name, SEP)) {
746 if (safe_wcscpy(program_full_path, pathconfig->program_name,
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100747 program_full_path_len) < 0) {
748 return PATHLEN_ERR();
749 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100750 }
Jack Jansen1afd4802004-06-03 14:33:03 +0000751#ifdef __APPLE__
Jack Jansen1afd4802004-06-03 14:33:03 +0000752 /* On Mac OS X, if a script uses an interpreter of the form
753 * "#!/opt/python2.3/bin/python", the kernel only passes "python"
754 * as argv[0], which falls through to the $PATH search below.
755 * If /opt/python2.3/bin isn't in your path, or is near the end,
756 * this algorithm may incorrectly find /usr/bin/python. To work
757 * around this, we can use _NSGetExecutablePath to get a better
758 * hint of what the intended interpreter was, although this
759 * will fail if a relative path was used. but in that case,
760 * absolutize() should help us out below
761 */
Victor Stinnerf04ebe22017-11-25 00:01:23 +0100762 else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
763 execpath[0] == SEP)
764 {
Victor Stinner31a83932017-12-04 13:39:15 +0100765 size_t len;
766 wchar_t *path = Py_DecodeLocale(execpath, &len);
767 if (path == NULL) {
768 return DECODE_LOCALE_ERR("executable path", len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100770 if (safe_wcscpy(program_full_path, path, program_full_path_len) < 0) {
771 PyMem_RawFree(path);
772 return PATHLEN_ERR();
773 }
Victor Stinner31a83932017-12-04 13:39:15 +0100774 PyMem_RawFree(path);
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000775 }
Brett Cannon6cc48142004-06-24 00:48:44 +0000776#endif /* __APPLE__ */
Victor Stinner0327bde2017-11-23 17:03:20 +0100777 else if (calculate->path_env) {
778 wchar_t *path = calculate->path_env;
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000779 while (1) {
780 wchar_t *delim = wcschr(path, DELIM);
Jack Jansen55070f52001-12-02 23:56:28 +0000781
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000782 if (delim) {
783 size_t len = delim - path;
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100784 if (len >= program_full_path_len) {
785 return PATHLEN_ERR();
Victor Stinner0327bde2017-11-23 17:03:20 +0100786 }
Victor Stinnerb64de462017-12-01 18:27:09 +0100787 wcsncpy(program_full_path, path, len);
788 program_full_path[len] = '\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000789 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100790 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100791 if (safe_wcscpy(program_full_path, path,
792 program_full_path_len) < 0) {
793 return PATHLEN_ERR();
794 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100795 }
Jack Jansen55070f52001-12-02 23:56:28 +0000796
Victor Stinner3f5409a2019-09-23 19:50:27 +0200797 status = joinpath(program_full_path, pathconfig->program_name,
798 program_full_path_len);
Victor Stinner331a6a52019-05-27 16:39:22 +0200799 if (_PyStatus_EXCEPTION(status)) {
800 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100801 }
802
Victor Stinnerb64de462017-12-01 18:27:09 +0100803 if (isxfile(program_full_path)) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000804 break;
Victor Stinner0327bde2017-11-23 17:03:20 +0100805 }
Jack Jansen55070f52001-12-02 23:56:28 +0000806
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000807 if (!delim) {
Victor Stinnerb64de462017-12-01 18:27:09 +0100808 program_full_path[0] = L'\0';
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000809 break;
810 }
811 path = delim + 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000812 }
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000813 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100814 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100815 program_full_path[0] = '\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100816 }
Victor Stinnerb64de462017-12-01 18:27:09 +0100817 if (program_full_path[0] != SEP && program_full_path[0] != '\0') {
Victor Stinner331a6a52019-05-27 16:39:22 +0200818 status = absolutize(program_full_path, program_full_path_len);
819 if (_PyStatus_EXCEPTION(status)) {
820 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100821 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100822 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200823#if defined(__CYGWIN__) || defined(__MINGW32__)
824 /* For these platforms it is necessary to ensure that the .exe suffix
825 * is appended to the filename, otherwise there is potential for
826 * sys.executable to return the name of a directory under the same
827 * path (bpo-28441).
828 */
829 if (program_full_path[0] != '\0') {
Victor Stinner331a6a52019-05-27 16:39:22 +0200830 status = add_exe_suffix(program_full_path, program_full_path_len);
831 if (_PyStatus_EXCEPTION(status)) {
832 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100833 }
E. M. Bray7a7693e2018-10-05 13:38:50 +0200834 }
835#endif
Victor Stinner9316ee42017-11-25 03:17:57 +0100836
Victor Stinner331a6a52019-05-27 16:39:22 +0200837 pathconfig->program_full_path = _PyMem_RawWcsdup(program_full_path);
838 if (pathconfig->program_full_path == NULL) {
839 return _PyStatus_NO_MEMORY();
Victor Stinner9316ee42017-11-25 03:17:57 +0100840 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200841 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100842}
843
844
Victor Stinner331a6a52019-05-27 16:39:22 +0200845static PyStatus
Victor Stinnerb64de462017-12-01 18:27:09 +0100846calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path)
Victor Stinner0327bde2017-11-23 17:03:20 +0100847{
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100848 const size_t argv0_path_len = Py_ARRAY_LENGTH(calculate->argv0_path);
849 if (safe_wcscpy(calculate->argv0_path, program_full_path, argv0_path_len) < 0) {
850 return PATHLEN_ERR();
851 }
Jack Jansen55070f52001-12-02 23:56:28 +0000852
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000853#ifdef WITH_NEXT_FRAMEWORK
Victor Stinner0327bde2017-11-23 17:03:20 +0100854 NSModule pythonModule;
855
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000856 /* On Mac OS X we have a special case if we're running from a framework.
857 ** This is because the python home should be set relative to the library,
858 ** which is in the framework, not relative to the executable, which may
859 ** be outside of the framework. Except when we're in the build directory...
860 */
Fred Drakeedabdc12000-07-08 06:16:37 +0000861 pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
862 /* Use dylib functions to find out where the framework was loaded from */
Victor Stinner0327bde2017-11-23 17:03:20 +0100863 const char* modPath = NSLibraryNameForModule(pythonModule);
Vinay Sajip90db6612012-07-17 17:33:46 +0100864 if (modPath != NULL) {
Fred Drakeedabdc12000-07-08 06:16:37 +0000865 /* We're in a framework. */
Jack Jansene925faf2001-08-15 01:14:40 +0000866 /* See if we might be in the build directory. The framework in the
867 ** build directory is incomplete, it only has the .dylib and a few
868 ** needed symlinks, it doesn't have the Lib directories and such.
869 ** If we're running with the framework from the build directory we must
870 ** be running the interpreter in the build directory, so we use the
871 ** build-directory-specific logic to find Lib and such.
872 */
Victor Stinner331a6a52019-05-27 16:39:22 +0200873 PyStatus status;
Victor Stinner9316ee42017-11-25 03:17:57 +0100874 size_t len;
875 wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100876 if (wbuf == NULL) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100877 return DECODE_LOCALE_ERR("framework location", len);
Vinay Sajip90db6612012-07-17 17:33:46 +0100878 }
879
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100880 if (safe_wcscpy(calculate->argv0_path, wbuf, argv0_path_len) < 0) {
881 return PATHLEN_ERR();
882 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100883 reduce(calculate->argv0_path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200884 status = joinpath(calculate->argv0_path, calculate->lib_python, argv0_path_len);
885 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100886 PyMem_RawFree(wbuf);
Victor Stinner331a6a52019-05-27 16:39:22 +0200887 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100888 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200889 status = joinpath(calculate->argv0_path, LANDMARK, argv0_path_len);
890 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100891 PyMem_RawFree(wbuf);
Victor Stinner331a6a52019-05-27 16:39:22 +0200892 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100893 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100894 if (!ismodule(calculate->argv0_path,
895 Py_ARRAY_LENGTH(calculate->argv0_path))) {
Antoine Pitrou99773ac2010-08-14 12:34:41 +0000896 /* We are in the build directory so use the name of the
897 executable - we know that the absolute path is passed */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100898 if (safe_wcscpy(calculate->argv0_path, program_full_path,
899 argv0_path_len) < 0) {
900 return PATHLEN_ERR();
901 }
Jack Jansene925faf2001-08-15 01:14:40 +0000902 }
903 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100904 /* Use the location of the library as the program_full_path */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100905 if (safe_wcscpy(calculate->argv0_path, wbuf, argv0_path_len) < 0) {
906 return PATHLEN_ERR();
907 }
Jack Jansene925faf2001-08-15 01:14:40 +0000908 }
Victor Stinner1a7425f2013-07-07 16:25:15 +0200909 PyMem_RawFree(wbuf);
Fred Drakeedabdc12000-07-08 06:16:37 +0000910 }
Guido van Rossum54ecc3d1999-01-27 17:53:11 +0000911#endif
Guido van Rossume296ced2001-09-28 20:00:29 +0000912
Guido van Rossum305e5d01997-04-11 17:18:45 +0000913#if HAVE_READLINK
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100914 wchar_t tmpbuffer[MAXPATHLEN + 1];
915 const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
916 int linklen = _Py_wreadlink(program_full_path, tmpbuffer, buflen);
Victor Stinner0327bde2017-11-23 17:03:20 +0100917 while (linklen != -1) {
918 if (tmpbuffer[0] == SEP) {
919 /* tmpbuffer should never be longer than MAXPATHLEN,
920 but extra check does not hurt */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100921 if (safe_wcscpy(calculate->argv0_path, tmpbuffer, argv0_path_len) < 0) {
922 return PATHLEN_ERR();
923 }
Fred Drakeedabdc12000-07-08 06:16:37 +0000924 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100925 else {
Victor Stinnerb64de462017-12-01 18:27:09 +0100926 /* Interpret relative to program_full_path */
Victor Stinner331a6a52019-05-27 16:39:22 +0200927 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +0100928 reduce(calculate->argv0_path);
Victor Stinner331a6a52019-05-27 16:39:22 +0200929 status = joinpath(calculate->argv0_path, tmpbuffer, argv0_path_len);
930 if (_PyStatus_EXCEPTION(status)) {
931 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100932 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100933 }
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100934 linklen = _Py_wreadlink(calculate->argv0_path, tmpbuffer, buflen);
Fred Drakeedabdc12000-07-08 06:16:37 +0000935 }
Guido van Rossum305e5d01997-04-11 17:18:45 +0000936#endif /* HAVE_READLINK */
937
Victor Stinner0327bde2017-11-23 17:03:20 +0100938 reduce(calculate->argv0_path);
Jeremy Hylton6372fe12000-09-27 20:51:17 +0000939 /* At this point, argv0_path is guaranteed to be less than
Victor Stinner0327bde2017-11-23 17:03:20 +0100940 MAXPATHLEN bytes long. */
Victor Stinner331a6a52019-05-27 16:39:22 +0200941 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100942}
Guido van Rossum305e5d01997-04-11 17:18:45 +0000943
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100944
Victor Stinner0327bde2017-11-23 17:03:20 +0100945/* Search for an "pyvenv.cfg" environment configuration file, first in the
946 executable's directory and then in the parent directory.
947 If found, open it for use when searching for prefixes.
948*/
Victor Stinner331a6a52019-05-27 16:39:22 +0200949static PyStatus
Victor Stinner0327bde2017-11-23 17:03:20 +0100950calculate_read_pyenv(PyCalculatePath *calculate)
951{
Victor Stinner331a6a52019-05-27 16:39:22 +0200952 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +0100953 wchar_t tmpbuffer[MAXPATHLEN+1];
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100954 const size_t buflen = Py_ARRAY_LENGTH(tmpbuffer);
Victor Stinner0327bde2017-11-23 17:03:20 +0100955 wchar_t *env_cfg = L"pyvenv.cfg";
956 FILE *env_file;
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100957
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100958 if (safe_wcscpy(tmpbuffer, calculate->argv0_path, buflen) < 0) {
959 return PATHLEN_ERR();
960 }
Vinay Sajip90db6612012-07-17 17:33:46 +0100961
Victor Stinner331a6a52019-05-27 16:39:22 +0200962 status = joinpath(tmpbuffer, env_cfg, buflen);
963 if (_PyStatus_EXCEPTION(status)) {
964 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100965 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100966 env_file = _Py_wfopen(tmpbuffer, L"r");
967 if (env_file == NULL) {
968 errno = 0;
969
970 reduce(tmpbuffer);
971 reduce(tmpbuffer);
Victor Stinner331a6a52019-05-27 16:39:22 +0200972 status = joinpath(tmpbuffer, env_cfg, buflen);
973 if (_PyStatus_EXCEPTION(status)) {
974 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +0100975 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100976
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100977 env_file = _Py_wfopen(tmpbuffer, L"r");
978 if (env_file == NULL) {
979 errno = 0;
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100980 }
981 }
982
Victor Stinner0327bde2017-11-23 17:03:20 +0100983 if (env_file == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200984 return _PyStatus_OK();
Fred Drakeedabdc12000-07-08 06:16:37 +0000985 }
Guido van Rossume296ced2001-09-28 20:00:29 +0000986
Victor Stinner0327bde2017-11-23 17:03:20 +0100987 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinnerfaddaed2019-03-19 02:58:14 +0100988 if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, buflen)) {
989 if (safe_wcscpy(calculate->argv0_path, tmpbuffer,
990 Py_ARRAY_LENGTH(calculate->argv0_path)) < 0) {
991 return PATHLEN_ERR();
992 }
Just van Rossum52e14d62002-12-30 22:08:05 +0000993 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100994 fclose(env_file);
Victor Stinner331a6a52019-05-27 16:39:22 +0200995 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100996}
Just van Rossum52e14d62002-12-30 22:08:05 +0000997
Guido van Rossum305e5d01997-04-11 17:18:45 +0000998
Victor Stinner331a6a52019-05-27 16:39:22 +0200999static PyStatus
Victor Stinner9316ee42017-11-25 03:17:57 +01001000calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +01001001{
Victor Stinner331a6a52019-05-27 16:39:22 +02001002 PyStatus status;
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001003 const size_t zip_path_len = Py_ARRAY_LENGTH(calculate->zip_path);
1004 if (safe_wcscpy(calculate->zip_path, prefix, zip_path_len) < 0) {
1005 return PATHLEN_ERR();
1006 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001007
Victor Stinner0327bde2017-11-23 17:03:20 +01001008 if (calculate->prefix_found > 0) {
1009 /* Use the reduced prefix returned by Py_GetPrefix() */
1010 reduce(calculate->zip_path);
1011 reduce(calculate->zip_path);
Victor Stinnerd4341102017-11-23 00:12:09 +01001012 }
1013 else {
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001014 if (safe_wcscpy(calculate->zip_path, calculate->prefix, zip_path_len) < 0) {
1015 return PATHLEN_ERR();
1016 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001017 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001018 status = joinpath(calculate->zip_path, L"lib/python00.zip", zip_path_len);
1019 if (_PyStatus_EXCEPTION(status)) {
1020 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001021 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001022
1023 /* Replace "00" with version */
1024 size_t bufsz = wcslen(calculate->zip_path);
1025 calculate->zip_path[bufsz - 6] = VERSION[0];
1026 calculate->zip_path[bufsz - 5] = VERSION[2];
Victor Stinner331a6a52019-05-27 16:39:22 +02001027 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001028}
1029
1030
Victor Stinner331a6a52019-05-27 16:39:22 +02001031static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +02001032calculate_module_search_path(PyCalculatePath *calculate,
1033 _PyPathConfig *pathconfig,
1034 const wchar_t *prefix, const wchar_t *exec_prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +01001035{
1036 /* Calculate size of return buffer */
1037 size_t bufsz = 0;
Victor Stinner3f5409a2019-09-23 19:50:27 +02001038 if (calculate->pythonpath_env != NULL) {
1039 bufsz += wcslen(calculate->pythonpath_env) + 1;
Martin v. Löwis790465f2008-04-05 20:41:37 +00001040 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001041
Victor Stinner0327bde2017-11-23 17:03:20 +01001042 wchar_t *defpath = calculate->pythonpath;
Victor Stinner9316ee42017-11-25 03:17:57 +01001043 size_t prefixsz = wcslen(prefix) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001044 while (1) {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001045 wchar_t *delim = wcschr(defpath, DELIM);
Guido van Rossum305e5d01997-04-11 17:18:45 +00001046
Victor Stinner0327bde2017-11-23 17:03:20 +01001047 if (defpath[0] != SEP) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001048 /* Paths are relative to prefix */
1049 bufsz += prefixsz;
Victor Stinner0327bde2017-11-23 17:03:20 +01001050 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001051
Victor Stinner0327bde2017-11-23 17:03:20 +01001052 if (delim) {
Fred Drakeedabdc12000-07-08 06:16:37 +00001053 bufsz += delim - defpath + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001054 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001055 else {
Martin v. Löwis790465f2008-04-05 20:41:37 +00001056 bufsz += wcslen(defpath) + 1;
Fred Drakeedabdc12000-07-08 06:16:37 +00001057 break;
1058 }
1059 defpath = delim + 1;
1060 }
Guido van Rossum305e5d01997-04-11 17:18:45 +00001061
Victor Stinner0327bde2017-11-23 17:03:20 +01001062 bufsz += wcslen(calculate->zip_path) + 1;
Victor Stinner9316ee42017-11-25 03:17:57 +01001063 bufsz += wcslen(exec_prefix) + 1;
Guido van Rossum305e5d01997-04-11 17:18:45 +00001064
Victor Stinner0327bde2017-11-23 17:03:20 +01001065 /* Allocate the buffer */
1066 wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Fred Drakeedabdc12000-07-08 06:16:37 +00001067 if (buf == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +02001068 return _PyStatus_NO_MEMORY();
Fred Drakeedabdc12000-07-08 06:16:37 +00001069 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001070 buf[0] = '\0';
Guido van Rossum305e5d01997-04-11 17:18:45 +00001071
Victor Stinner72967a42013-11-16 01:22:04 +01001072 /* Run-time value of $PYTHONPATH goes first */
Victor Stinner3f5409a2019-09-23 19:50:27 +02001073 if (calculate->pythonpath_env) {
1074 wcscpy(buf, calculate->pythonpath_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001075 wcscat(buf, delimiter);
Fred Drakeedabdc12000-07-08 06:16:37 +00001076 }
Victor Stinner72967a42013-11-16 01:22:04 +01001077
1078 /* Next is the default zip path */
Victor Stinner0327bde2017-11-23 17:03:20 +01001079 wcscat(buf, calculate->zip_path);
Victor Stinner72967a42013-11-16 01:22:04 +01001080 wcscat(buf, delimiter);
1081
1082 /* Next goes merge of compile-time $PYTHONPATH with
1083 * dynamically located prefix.
1084 */
Victor Stinner0327bde2017-11-23 17:03:20 +01001085 defpath = calculate->pythonpath;
Victor Stinner72967a42013-11-16 01:22:04 +01001086 while (1) {
1087 wchar_t *delim = wcschr(defpath, DELIM);
1088
1089 if (defpath[0] != SEP) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001090 wcscat(buf, prefix);
1091 if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP &&
Victor Stinner0327bde2017-11-23 17:03:20 +01001092 defpath[0] != (delim ? DELIM : L'\0'))
1093 {
1094 /* not empty */
Serhiy Storchaka62e32d62016-11-11 12:05:01 +02001095 wcscat(buf, separator);
1096 }
Victor Stinner72967a42013-11-16 01:22:04 +01001097 }
1098
1099 if (delim) {
1100 size_t len = delim - defpath + 1;
1101 size_t end = wcslen(buf) + len;
1102 wcsncat(buf, defpath, len);
Victor Stinner9316ee42017-11-25 03:17:57 +01001103 buf[end] = '\0';
Victor Stinner72967a42013-11-16 01:22:04 +01001104 }
1105 else {
1106 wcscat(buf, defpath);
1107 break;
1108 }
1109 defpath = delim + 1;
1110 }
1111 wcscat(buf, delimiter);
1112
1113 /* Finally, on goes the directory for dynamic-load modules */
Victor Stinner9316ee42017-11-25 03:17:57 +01001114 wcscat(buf, exec_prefix);
Victor Stinner72967a42013-11-16 01:22:04 +01001115
Victor Stinner331a6a52019-05-27 16:39:22 +02001116 pathconfig->module_search_path = buf;
1117 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001118}
Guido van Rossum305e5d01997-04-11 17:18:45 +00001119
Victor Stinner0327bde2017-11-23 17:03:20 +01001120
Victor Stinner331a6a52019-05-27 16:39:22 +02001121static PyStatus
Victor Stinner0327bde2017-11-23 17:03:20 +01001122calculate_init(PyCalculatePath *calculate,
Victor Stinner331a6a52019-05-27 16:39:22 +02001123 const PyConfig *config)
Victor Stinner0327bde2017-11-23 17:03:20 +01001124{
Victor Stinner0327bde2017-11-23 17:03:20 +01001125 size_t len;
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +02001126 const char *path = getenv("PATH");
Victor Stinner0327bde2017-11-23 17:03:20 +01001127 if (path) {
1128 calculate->path_env = Py_DecodeLocale(path, &len);
1129 if (!calculate->path_env) {
Victor Stinner46972b72017-11-24 22:55:40 +01001130 return DECODE_LOCALE_ERR("PATH environment variable", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001131 }
Fred Drakeedabdc12000-07-08 06:16:37 +00001132 }
Victor Stinnerae4836d2010-11-08 23:49:47 +00001133
Victor Stinner0327bde2017-11-23 17:03:20 +01001134 calculate->pythonpath = Py_DecodeLocale(PYTHONPATH, &len);
1135 if (!calculate->pythonpath) {
Victor Stinner46972b72017-11-24 22:55:40 +01001136 return DECODE_LOCALE_ERR("PYTHONPATH define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001137 }
1138 calculate->prefix = Py_DecodeLocale(PREFIX, &len);
1139 if (!calculate->prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001140 return DECODE_LOCALE_ERR("PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001141 }
1142 calculate->exec_prefix = Py_DecodeLocale(EXEC_PREFIX, &len);
Miss Islington (bot)e8329632019-09-09 10:59:18 -07001143 if (!calculate->exec_prefix) {
Victor Stinner46972b72017-11-24 22:55:40 +01001144 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001145 }
1146 calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
1147 if (!calculate->lib_python) {
Victor Stinner46972b72017-11-24 22:55:40 +01001148 return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
Victor Stinner0327bde2017-11-23 17:03:20 +01001149 }
Victor Stinner3f5409a2019-09-23 19:50:27 +02001150
1151 calculate->warnings = config->pathconfig_warnings;
1152 calculate->pythonpath_env = config->pythonpath_env;
1153
Victor Stinner331a6a52019-05-27 16:39:22 +02001154 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001155}
1156
1157
1158static void
1159calculate_free(PyCalculatePath *calculate)
1160{
1161 PyMem_RawFree(calculate->pythonpath);
1162 PyMem_RawFree(calculate->prefix);
1163 PyMem_RawFree(calculate->exec_prefix);
1164 PyMem_RawFree(calculate->lib_python);
1165 PyMem_RawFree(calculate->path_env);
Victor Stinner0327bde2017-11-23 17:03:20 +01001166}
1167
1168
Victor Stinner331a6a52019-05-27 16:39:22 +02001169static PyStatus
Victor Stinner3f5409a2019-09-23 19:50:27 +02001170calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +01001171{
Victor Stinner331a6a52019-05-27 16:39:22 +02001172 PyStatus status;
Victor Stinner31a83932017-12-04 13:39:15 +01001173
Victor Stinner3f5409a2019-09-23 19:50:27 +02001174 if (pathconfig->program_full_path == NULL) {
1175 status = calculate_program_full_path(calculate, pathconfig);
1176 if (_PyStatus_EXCEPTION(status)) {
1177 return status;
1178 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001179 }
1180
Victor Stinner331a6a52019-05-27 16:39:22 +02001181 status = calculate_argv0_path(calculate, pathconfig->program_full_path);
1182 if (_PyStatus_EXCEPTION(status)) {
1183 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001184 }
1185
Victor Stinner331a6a52019-05-27 16:39:22 +02001186 status = calculate_read_pyenv(calculate);
1187 if (_PyStatus_EXCEPTION(status)) {
1188 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001189 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001190
1191 wchar_t prefix[MAXPATHLEN+1];
1192 memset(prefix, 0, sizeof(prefix));
Victor Stinner3f5409a2019-09-23 19:50:27 +02001193 status = calculate_prefix(calculate, pathconfig,
1194 prefix, Py_ARRAY_LENGTH(prefix));
Victor Stinner331a6a52019-05-27 16:39:22 +02001195 if (_PyStatus_EXCEPTION(status)) {
1196 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001197 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001198
Victor Stinner331a6a52019-05-27 16:39:22 +02001199 status = calculate_zip_path(calculate, prefix);
1200 if (_PyStatus_EXCEPTION(status)) {
1201 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001202 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001203
1204 wchar_t exec_prefix[MAXPATHLEN+1];
1205 memset(exec_prefix, 0, sizeof(exec_prefix));
Victor Stinner3f5409a2019-09-23 19:50:27 +02001206 status = calculate_exec_prefix(calculate, pathconfig,
1207 exec_prefix, Py_ARRAY_LENGTH(exec_prefix));
Victor Stinner331a6a52019-05-27 16:39:22 +02001208 if (_PyStatus_EXCEPTION(status)) {
1209 return status;
Victor Stinner7b14f0c2019-03-18 23:54:59 +01001210 }
Victor Stinner0327bde2017-11-23 17:03:20 +01001211
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001212 if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
Victor Stinner3f5409a2019-09-23 19:50:27 +02001213 calculate->warnings)
Victor Stinnerf04ebe22017-11-25 00:01:23 +01001214 {
Victor Stinner0327bde2017-11-23 17:03:20 +01001215 fprintf(stderr,
1216 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
1217 }
1218
Victor Stinner9f3dcf82019-09-21 02:13:14 +02001219 if (pathconfig->module_search_path == NULL) {
Victor Stinner3f5409a2019-09-23 19:50:27 +02001220 status = calculate_module_search_path(calculate, pathconfig,
1221 prefix, exec_prefix);
Victor Stinner9f3dcf82019-09-21 02:13:14 +02001222 if (_PyStatus_EXCEPTION(status)) {
1223 return status;
1224 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001225 }
1226
Victor Stinner331a6a52019-05-27 16:39:22 +02001227 if (pathconfig->prefix == NULL) {
Victor Stinner3f5409a2019-09-23 19:50:27 +02001228 status = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix));
1229 if (_PyStatus_EXCEPTION(status)) {
1230 return status;
1231 }
1232
1233 pathconfig->prefix = _PyMem_RawWcsdup(prefix);
1234 if (pathconfig->prefix == NULL) {
1235 return _PyStatus_NO_MEMORY();
1236 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001237 }
1238
Victor Stinner331a6a52019-05-27 16:39:22 +02001239 if (pathconfig->exec_prefix == NULL) {
Victor Stinner3f5409a2019-09-23 19:50:27 +02001240 status = calculate_reduce_exec_prefix(calculate,
1241 exec_prefix,
1242 Py_ARRAY_LENGTH(exec_prefix));
1243 if (_PyStatus_EXCEPTION(status)) {
1244 return status;
1245 }
1246
1247 pathconfig->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
1248 if (pathconfig->exec_prefix == NULL) {
1249 return _PyStatus_NO_MEMORY();
1250 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001251 }
1252
Victor Stinner331a6a52019-05-27 16:39:22 +02001253 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001254}
1255
1256
Victor Stinner3f5409a2019-09-23 19:50:27 +02001257/* Calculate 'pathconfig' attributes:
1258
1259 - program_full_path
1260 - module_search_path
1261 - prefix
1262 - exec_prefix
1263
1264 If an attribute is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001265PyStatus
1266_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001267{
Victor Stinner331a6a52019-05-27 16:39:22 +02001268 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001269 PyCalculatePath calculate;
1270 memset(&calculate, 0, sizeof(calculate));
1271
Victor Stinner331a6a52019-05-27 16:39:22 +02001272 status = calculate_init(&calculate, config);
1273 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001274 goto done;
Victor Stinner0327bde2017-11-23 17:03:20 +01001275 }
1276
Victor Stinner3f5409a2019-09-23 19:50:27 +02001277 status = calculate_path(&calculate, pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001278 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001279 goto done;
1280 }
1281
Victor Stinner331a6a52019-05-27 16:39:22 +02001282 status = _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +01001283
Victor Stinner9316ee42017-11-25 03:17:57 +01001284done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001285 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001286 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +01001287}
Victor Stinner46972b72017-11-24 22:55:40 +01001288
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001289#ifdef __cplusplus
1290}
1291#endif