| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 1 | /*********************************************************** | 
| Guido van Rossum | fd71b9e | 2000-06-30 23:50:40 +0000 | [diff] [blame] | 2 | Copyright (c) 2000, BeOpen.com. | 
|  | 3 | Copyright (c) 1995-2000, Corporation for National Research Initiatives. | 
|  | 4 | Copyright (c) 1990-1995, Stichting Mathematisch Centrum. | 
|  | 5 | All rights reserved. | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 6 |  | 
| Guido van Rossum | fd71b9e | 2000-06-30 23:50:40 +0000 | [diff] [blame] | 7 | See the file "Misc/COPYRIGHT" for information on usage and | 
|  | 8 | redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 9 | ******************************************************************/ | 
|  | 10 |  | 
|  | 11 | /* Return the initial module search path. */ | 
| Guido van Rossum | c499572 | 1998-08-08 20:05:31 +0000 | [diff] [blame] | 12 | /* Used by DOS, OS/2, Windows 3.1, Windows 95/98, Windows NT. */ | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 13 |  | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 14 | /* ---------------------------------------------------------------- | 
|  | 15 | PATH RULES FOR WINDOWS: | 
|  | 16 | This describes how sys.path is formed on Windows.  It describes the | 
|  | 17 | functionality, not the implementation (ie, the order in which these | 
|  | 18 | are actually fetched is different) | 
|  | 19 |  | 
|  | 20 | * Python always adds an empty entry at the start, which corresponds | 
|  | 21 | to the current directory. | 
|  | 22 |  | 
|  | 23 | * If the PYTHONPATH env. var. exists, it's entries are added next. | 
|  | 24 |  | 
|  | 25 | * We look in the registry for "application paths" - that is, sub-keys | 
|  | 26 | under the main PythonPath registry key.  These are added next (the | 
|  | 27 | order of sub-key processing is undefined). | 
|  | 28 | HKEY_CURRENT_USER is searched and added first. | 
|  | 29 | HKEY_LOCAL_MACHINE is searched and added next. | 
|  | 30 | (Note that all known installers only use HKLM, so HKCU is typically | 
|  | 31 | empty) | 
|  | 32 |  | 
|  | 33 | * We attempt to locate the "Python Home" - if the PYTHONHOME env var | 
|  | 34 | is set, we believe it.  Otherwise, we use the path of our host .EXE's | 
| Jeremy Hylton | 847a996 | 2000-05-26 21:49:07 +0000 | [diff] [blame] | 35 | to try and locate our "landmark" (lib\\os.py) and deduce our home. | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 36 | - If we DO have a Python Home: The relevant sub-directories (Lib, | 
|  | 37 | plat-win, lib-tk, etc) are based on the Python Home | 
|  | 38 | - If we DO NOT have a Python Home, the core Python Path is | 
|  | 39 | loaded from the registry.  This is the main PythonPath key, | 
|  | 40 | and both HKLM and HKCU are combined to form the path) | 
|  | 41 |  | 
|  | 42 | * Iff - we can not locate the Python Home, have not had a PYTHONPATH | 
|  | 43 | specified, and can't locate any Registry entries (ie, we have _nothing_ | 
|  | 44 | we can assume is a good path), a default path with relative entries is | 
|  | 45 | used (eg. .\Lib;.\plat-win, etc) | 
|  | 46 |  | 
|  | 47 |  | 
|  | 48 | The end result of all this is: | 
|  | 49 | * When running python.exe, or any other .exe in the main Python directory | 
|  | 50 | (either an installed version, or directly from the PCbuild directory), | 
|  | 51 | the core path is deduced, and the core paths in the registry are | 
|  | 52 | ignored.  Other "application paths" in the registry are always read. | 
|  | 53 |  | 
|  | 54 | * When Python is hosted in another exe (different directory, embedded via | 
|  | 55 | COM, etc), the Python Home will not be deduced, so the core path from | 
|  | 56 | the registry is used.  Other "application paths "in the registry are | 
|  | 57 | always read. | 
|  | 58 |  | 
|  | 59 | * If Python can't find its home and there is no registry (eg, frozen | 
|  | 60 | exe, some very strange installation setup) you get a path with | 
|  | 61 | some default, but relative, paths. | 
|  | 62 |  | 
|  | 63 | ---------------------------------------------------------------- */ | 
|  | 64 |  | 
|  | 65 |  | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 66 | #include "Python.h" | 
|  | 67 | #include "osdefs.h" | 
|  | 68 |  | 
| Guido van Rossum | 8f1b651 | 1997-08-13 19:55:43 +0000 | [diff] [blame] | 69 | #ifdef MS_WIN32 | 
|  | 70 | #include <windows.h> | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 71 | #include <tchar.h> | 
| Guido van Rossum | 8f1b651 | 1997-08-13 19:55:43 +0000 | [diff] [blame] | 72 | #endif | 
|  | 73 |  | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 74 | #include <sys/types.h> | 
|  | 75 | #include <sys/stat.h> | 
|  | 76 | #include <string.h> | 
|  | 77 |  | 
|  | 78 | #if HAVE_UNISTD_H | 
|  | 79 | #include <unistd.h> | 
|  | 80 | #endif /* HAVE_UNISTD_H */ | 
|  | 81 |  | 
|  | 82 | /* Search in some common locations for the associated Python libraries. | 
|  | 83 | * | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 84 | * Py_GetPath() tries to return a sensible Python module search path. | 
|  | 85 | * | 
| Guido van Rossum | 42a9744 | 1998-02-19 21:00:45 +0000 | [diff] [blame] | 86 | * The approach is an adaptation for Windows of the strategy used in | 
|  | 87 | * ../Modules/getpath.c; it uses the Windows Registry as one of its | 
|  | 88 | * information sources. | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 89 | */ | 
|  | 90 |  | 
|  | 91 | #ifndef LANDMARK | 
| Jeremy Hylton | 847a996 | 2000-05-26 21:49:07 +0000 | [diff] [blame] | 92 | #define LANDMARK "lib\\os.py" | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 93 | #endif | 
|  | 94 |  | 
|  | 95 | static char prefix[MAXPATHLEN+1]; | 
|  | 96 | static char progpath[MAXPATHLEN+1]; | 
|  | 97 | static char *module_search_path = NULL; | 
|  | 98 |  | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 99 |  | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 100 | static int | 
|  | 101 | is_sep(ch)	/* determine if "ch" is a separator character */ | 
|  | 102 | char ch; | 
|  | 103 | { | 
|  | 104 | #ifdef ALTSEP | 
|  | 105 | return ch == SEP || ch == ALTSEP; | 
|  | 106 | #else | 
|  | 107 | return ch == SEP; | 
|  | 108 | #endif | 
|  | 109 | } | 
|  | 110 |  | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 111 |  | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 112 | static void | 
|  | 113 | reduce(dir) | 
|  | 114 | char *dir; | 
|  | 115 | { | 
| Guido van Rossum | 1c44e28 | 2000-06-28 22:20:06 +0000 | [diff] [blame] | 116 | size_t i = strlen(dir); | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 117 | while (i > 0 && !is_sep(dir[i])) | 
|  | 118 | --i; | 
|  | 119 | dir[i] = '\0'; | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 |  | 
|  | 123 | static int | 
|  | 124 | exists(filename) | 
|  | 125 | char *filename; | 
|  | 126 | { | 
|  | 127 | struct stat buf; | 
|  | 128 | return stat(filename, &buf) == 0; | 
|  | 129 | } | 
|  | 130 |  | 
|  | 131 |  | 
| Guido van Rossum | 43ff114 | 1998-08-08 23:40:40 +0000 | [diff] [blame] | 132 | static int | 
|  | 133 | ismodule(filename)	/* Is module -- check for .pyc/.pyo too */ | 
|  | 134 | char *filename; | 
|  | 135 | { | 
|  | 136 | if (exists(filename)) | 
|  | 137 | return 1; | 
|  | 138 |  | 
|  | 139 | /* Check for the compiled version of prefix. */ | 
|  | 140 | if (strlen(filename) < MAXPATHLEN) { | 
|  | 141 | strcat(filename, Py_OptimizeFlag ? "o" : "c"); | 
|  | 142 | if (exists(filename)) | 
|  | 143 | return 1; | 
|  | 144 | } | 
|  | 145 | return 0; | 
|  | 146 | } | 
|  | 147 |  | 
|  | 148 |  | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 149 | static void | 
|  | 150 | join(buffer, stuff) | 
|  | 151 | char *buffer; | 
|  | 152 | char *stuff; | 
|  | 153 | { | 
| Guido van Rossum | 1c44e28 | 2000-06-28 22:20:06 +0000 | [diff] [blame] | 154 | size_t n, k; | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 155 | if (is_sep(stuff[0])) | 
|  | 156 | n = 0; | 
|  | 157 | else { | 
|  | 158 | n = strlen(buffer); | 
|  | 159 | if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN) | 
|  | 160 | buffer[n++] = SEP; | 
|  | 161 | } | 
|  | 162 | k = strlen(stuff); | 
|  | 163 | if (n + k > MAXPATHLEN) | 
|  | 164 | k = MAXPATHLEN - n; | 
|  | 165 | strncpy(buffer+n, stuff, k); | 
|  | 166 | buffer[n+k] = '\0'; | 
|  | 167 | } | 
|  | 168 |  | 
|  | 169 |  | 
|  | 170 | static int | 
| Guido van Rossum | e02e48b | 2000-03-29 01:49:47 +0000 | [diff] [blame] | 171 | gotlandmark(landmark) | 
|  | 172 | char *landmark; | 
|  | 173 | { | 
|  | 174 | int n, ok; | 
|  | 175 |  | 
|  | 176 | n = strlen(prefix); | 
|  | 177 | join(prefix, landmark); | 
|  | 178 | ok = ismodule(prefix); | 
|  | 179 | prefix[n] = '\0'; | 
|  | 180 | return ok; | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 |  | 
|  | 184 | static int | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 185 | search_for_prefix(argv0_path, landmark) | 
|  | 186 | char *argv0_path; | 
|  | 187 | char *landmark; | 
|  | 188 | { | 
| Guido van Rossum | e02e48b | 2000-03-29 01:49:47 +0000 | [diff] [blame] | 189 | /* Search from argv0_path, until landmark is found */ | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 190 | strcpy(prefix, argv0_path); | 
|  | 191 | do { | 
| Guido van Rossum | e02e48b | 2000-03-29 01:49:47 +0000 | [diff] [blame] | 192 | if (gotlandmark(landmark)) | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 193 | return 1; | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 194 | reduce(prefix); | 
|  | 195 | } while (prefix[0]); | 
|  | 196 | return 0; | 
|  | 197 | } | 
|  | 198 |  | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 199 | #ifdef MS_WIN32 | 
| Guido van Rossum | 43ff114 | 1998-08-08 23:40:40 +0000 | [diff] [blame] | 200 |  | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 201 | /* a string loaded from the DLL at startup.*/ | 
|  | 202 | extern const char *PyWin_DLLVersionString; | 
| Guido van Rossum | 271f977 | 1997-09-29 23:39:31 +0000 | [diff] [blame] | 203 |  | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 204 |  | 
|  | 205 | /* Load a PYTHONPATH value from the registry. | 
|  | 206 | Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER. | 
|  | 207 |  | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 208 | Works in both Unicode and 8bit environments.  Only uses the | 
|  | 209 | Ex family of functions so it also works with Windows CE. | 
|  | 210 |  | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 211 | Returns NULL, or a pointer that should be freed. | 
|  | 212 | */ | 
|  | 213 |  | 
|  | 214 | static char * | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 215 | getpythonregpath(HKEY keyBase, int skipcore) | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 216 | { | 
|  | 217 | HKEY newKey = 0; | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 218 | DWORD dataSize = 0; | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 219 | DWORD numKeys = 0; | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 220 | LONG rc; | 
|  | 221 | char *retval = NULL; | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 222 | TCHAR *dataBuf = NULL; | 
|  | 223 | static const TCHAR keyPrefix[] = _T("Software\\Python\\PythonCore\\"); | 
|  | 224 | static const TCHAR keySuffix[] = _T("\\PythonPath"); | 
| Guido van Rossum | 1c44e28 | 2000-06-28 22:20:06 +0000 | [diff] [blame] | 225 | size_t versionLen; | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 226 | DWORD index; | 
|  | 227 | TCHAR *keyBuf = NULL; | 
|  | 228 | TCHAR *keyBufPtr; | 
|  | 229 | TCHAR **ppPaths = NULL; | 
| Guido van Rossum | 271f977 | 1997-09-29 23:39:31 +0000 | [diff] [blame] | 230 |  | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 231 | /* Tried to use sysget("winver") but here is too early :-( */ | 
|  | 232 | versionLen = _tcslen(PyWin_DLLVersionString); | 
|  | 233 | /* Space for all the chars, plus one \0 */ | 
|  | 234 | keyBuf = keyBufPtr = malloc(sizeof(keyPrefix) + | 
|  | 235 | sizeof(TCHAR)*(versionLen-1) + | 
|  | 236 | sizeof(keySuffix)); | 
|  | 237 | if (keyBuf==NULL) goto done; | 
| Guido van Rossum | 271f977 | 1997-09-29 23:39:31 +0000 | [diff] [blame] | 238 |  | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 239 | memcpy(keyBufPtr, keyPrefix, sizeof(keyPrefix)-sizeof(TCHAR)); | 
|  | 240 | keyBufPtr += sizeof(keyPrefix)/sizeof(TCHAR) - 1; | 
|  | 241 | memcpy(keyBufPtr, PyWin_DLLVersionString, versionLen * sizeof(TCHAR)); | 
|  | 242 | keyBufPtr += versionLen; | 
|  | 243 | /* NULL comes with this one! */ | 
|  | 244 | memcpy(keyBufPtr, keySuffix, sizeof(keySuffix)); | 
|  | 245 | /* Open the root Python key */ | 
|  | 246 | rc=RegOpenKeyEx(keyBase, | 
|  | 247 | keyBuf, /* subkey */ | 
|  | 248 | 0, /* reserved */ | 
|  | 249 | KEY_READ, | 
|  | 250 | &newKey); | 
|  | 251 | if (rc!=ERROR_SUCCESS) goto done; | 
|  | 252 | /* Find out how big our core buffer is, and how many subkeys we have */ | 
|  | 253 | rc = RegQueryInfoKey(newKey, NULL, NULL, NULL, &numKeys, NULL, NULL, | 
|  | 254 | NULL, NULL, &dataSize, NULL, NULL); | 
|  | 255 | if (rc!=ERROR_SUCCESS) goto done; | 
|  | 256 | if (skipcore) dataSize = 0; /* Only count core ones if we want them! */ | 
|  | 257 | /* Allocate a temp array of char buffers, so we only need to loop | 
|  | 258 | reading the registry once | 
|  | 259 | */ | 
|  | 260 | ppPaths = malloc( sizeof(TCHAR *) * numKeys ); | 
|  | 261 | if (ppPaths==NULL) goto done; | 
|  | 262 | memset(ppPaths, 0, sizeof(TCHAR *) * numKeys); | 
|  | 263 | /* Loop over all subkeys, allocating a temp sub-buffer. */ | 
|  | 264 | for(index=0;index<numKeys;index++) { | 
|  | 265 | TCHAR keyBuf[MAX_PATH+1]; | 
|  | 266 | HKEY subKey = 0; | 
|  | 267 | DWORD reqdSize = MAX_PATH+1; | 
|  | 268 | /* Get the sub-key name */ | 
|  | 269 | DWORD rc = RegEnumKeyEx(newKey, index, keyBuf, &reqdSize, | 
|  | 270 | NULL, NULL, NULL, NULL ); | 
|  | 271 | if (rc!=ERROR_SUCCESS) goto done; | 
|  | 272 | /* Open the sub-key */ | 
|  | 273 | rc=RegOpenKeyEx(newKey, | 
|  | 274 | keyBuf, /* subkey */ | 
|  | 275 | 0, /* reserved */ | 
|  | 276 | KEY_READ, | 
|  | 277 | &subKey); | 
|  | 278 | if (rc!=ERROR_SUCCESS) goto done; | 
|  | 279 | /* Find the value of the buffer size, malloc, then read it */ | 
|  | 280 | RegQueryValueEx(subKey, NULL, 0, NULL, NULL, &reqdSize); | 
|  | 281 | if (reqdSize) { | 
|  | 282 | ppPaths[index] = malloc(reqdSize); | 
|  | 283 | if (ppPaths[index]) { | 
|  | 284 | RegQueryValueEx(subKey, NULL, 0, NULL, (LPBYTE)ppPaths[index], &reqdSize); | 
|  | 285 | dataSize += reqdSize + 1; /* 1 for the ";" */ | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 286 | } | 
|  | 287 | } | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 288 | RegCloseKey(subKey); | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 289 | } | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 290 | dataBuf = malloc((dataSize+1) * sizeof(TCHAR)); | 
|  | 291 | if (dataBuf) { | 
|  | 292 | TCHAR *szCur = dataBuf; | 
|  | 293 | DWORD reqdSize = dataSize; | 
|  | 294 | /* Copy our collected strings */ | 
|  | 295 | for (index=0;index<numKeys;index++) { | 
|  | 296 | int len; | 
|  | 297 | if (index > 0) { | 
|  | 298 | *(szCur++) = _T(';'); | 
|  | 299 | dataSize--; | 
|  | 300 | } | 
|  | 301 | len = _tcslen(ppPaths[index]); | 
|  | 302 | _tcsncpy(szCur, ppPaths[index], len); | 
|  | 303 | szCur += len; | 
|  | 304 | dataSize -= len; | 
|  | 305 | } | 
|  | 306 | if (skipcore) | 
|  | 307 | *szCur = '\0'; | 
|  | 308 | else { | 
|  | 309 | *(szCur++) = _T(';'); | 
|  | 310 | dataSize--; | 
|  | 311 | /* Now append the core path entries - this will include the NULL */ | 
|  | 312 | rc = RegQueryValueEx(newKey, NULL, 0, NULL, (LPBYTE)szCur, &dataSize); | 
|  | 313 | } | 
|  | 314 | /* And set the result - caller must free | 
|  | 315 | If MBCS, it is fine as is.  If Unicode, allocate new | 
|  | 316 | buffer and convert. | 
|  | 317 | */ | 
|  | 318 | #ifdef UNICODE | 
|  | 319 | retval = (char *)malloc(reqdSize+1); | 
|  | 320 | if (retval) | 
|  | 321 | WideCharToMultiByte(CP_ACP, 0, | 
|  | 322 | dataBuf, -1, /* source */ | 
|  | 323 | retval, dataSize+1, /* dest */ | 
|  | 324 | NULL, NULL); | 
|  | 325 | free(dataBuf); | 
|  | 326 | #else | 
|  | 327 | retval = dataBuf; | 
|  | 328 | #endif | 
|  | 329 | } | 
|  | 330 | done: | 
|  | 331 | /* Loop freeing my temp buffers */ | 
|  | 332 | if (ppPaths) { | 
|  | 333 | for(index=0;index<numKeys;index++) | 
|  | 334 | if (ppPaths[index]) free(ppPaths[index]); | 
|  | 335 | free(ppPaths); | 
|  | 336 | } | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 337 | if (newKey) | 
|  | 338 | RegCloseKey(newKey); | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 339 | if (keyBuf) | 
|  | 340 | free(keyBuf); | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 341 | return retval; | 
|  | 342 | } | 
|  | 343 | #endif /* MS_WIN32 */ | 
|  | 344 |  | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 345 | static void | 
|  | 346 | get_progpath() | 
|  | 347 | { | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 348 | extern char *Py_GetProgramName(); | 
|  | 349 | char *path = getenv("PATH"); | 
|  | 350 | char *prog = Py_GetProgramName(); | 
|  | 351 |  | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 352 | #ifdef MS_WIN32 | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 353 | #ifdef UNICODE | 
|  | 354 | WCHAR wprogpath[MAXPATHLEN+1]; | 
|  | 355 | if (GetModuleFileName(NULL, wprogpath, MAXPATHLEN)) { | 
|  | 356 | WideCharToMultiByte(CP_ACP, 0, wprogpath, -1, progpath, MAXPATHLEN+1, NULL, NULL); | 
|  | 357 | return; | 
|  | 358 | } | 
|  | 359 | #else | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 360 | if (GetModuleFileName(NULL, progpath, MAXPATHLEN)) | 
|  | 361 | return; | 
|  | 362 | #endif | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 363 | #endif | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 364 | if (prog == NULL || *prog == '\0') | 
|  | 365 | prog = "python"; | 
|  | 366 |  | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 367 | /* If there is no slash in the argv0 path, then we have to | 
|  | 368 | * assume python is on the user's $PATH, since there's no | 
|  | 369 | * other way to find a directory to start the search from.  If | 
|  | 370 | * $PATH isn't exported, you lose. | 
|  | 371 | */ | 
|  | 372 | #ifdef ALTSEP | 
|  | 373 | if (strchr(prog, SEP) || strchr(prog, ALTSEP)) | 
|  | 374 | #else | 
|  | 375 | if (strchr(prog, SEP)) | 
|  | 376 | #endif | 
|  | 377 | strcpy(progpath, prog); | 
|  | 378 | else if (path) { | 
|  | 379 | while (1) { | 
|  | 380 | char *delim = strchr(path, DELIM); | 
|  | 381 |  | 
|  | 382 | if (delim) { | 
| Guido van Rossum | 1c44e28 | 2000-06-28 22:20:06 +0000 | [diff] [blame] | 383 | size_t len = delim - path; | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 384 | strncpy(progpath, path, len); | 
|  | 385 | *(progpath + len) = '\0'; | 
|  | 386 | } | 
|  | 387 | else | 
|  | 388 | strcpy(progpath, path); | 
|  | 389 |  | 
|  | 390 | join(progpath, prog); | 
|  | 391 | if (exists(progpath)) | 
|  | 392 | break; | 
|  | 393 |  | 
|  | 394 | if (!delim) { | 
|  | 395 | progpath[0] = '\0'; | 
|  | 396 | break; | 
|  | 397 | } | 
|  | 398 | path = delim + 1; | 
|  | 399 | } | 
|  | 400 | } | 
|  | 401 | else | 
|  | 402 | progpath[0] = '\0'; | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 403 | } | 
|  | 404 |  | 
|  | 405 | static void | 
|  | 406 | calculate_path() | 
|  | 407 | { | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 408 | char argv0_path[MAXPATHLEN+1]; | 
|  | 409 | char *buf; | 
| Guido van Rossum | 1c44e28 | 2000-06-28 22:20:06 +0000 | [diff] [blame] | 410 | size_t bufsz; | 
| Guido van Rossum | 8b2b3ce | 1998-07-27 13:48:07 +0000 | [diff] [blame] | 411 | char *pythonhome = Py_GetPythonHome(); | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 412 | char *envpath = getenv("PYTHONPATH"); | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 413 |  | 
| Guido van Rossum | 43ff114 | 1998-08-08 23:40:40 +0000 | [diff] [blame] | 414 | #ifdef MS_WIN32 | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 415 | int skiphome, skipdefault; | 
| Guido van Rossum | 43ff114 | 1998-08-08 23:40:40 +0000 | [diff] [blame] | 416 | char *machinepath = NULL; | 
|  | 417 | char *userpath = NULL; | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 418 | #endif | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 419 |  | 
|  | 420 | get_progpath(); | 
|  | 421 | strcpy(argv0_path, progpath); | 
|  | 422 | reduce(argv0_path); | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 423 | if (pythonhome == NULL || *pythonhome == '\0') { | 
|  | 424 | if (search_for_prefix(argv0_path, LANDMARK)) | 
|  | 425 | pythonhome = prefix; | 
| Guido van Rossum | 43ff114 | 1998-08-08 23:40:40 +0000 | [diff] [blame] | 426 | else | 
|  | 427 | pythonhome = NULL; | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 428 | } | 
|  | 429 | else | 
|  | 430 | strcpy(prefix, pythonhome); | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 431 |  | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 432 | if (envpath && *envpath == '\0') | 
|  | 433 | envpath = NULL; | 
|  | 434 |  | 
| Guido van Rossum | e02e48b | 2000-03-29 01:49:47 +0000 | [diff] [blame] | 435 |  | 
| Guido van Rossum | 43ff114 | 1998-08-08 23:40:40 +0000 | [diff] [blame] | 436 | #ifdef MS_WIN32 | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 437 | skiphome = pythonhome==NULL ? 0 : 1; | 
|  | 438 | machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome); | 
|  | 439 | userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome); | 
|  | 440 | /* We only use the default relative PYTHONPATH if we havent | 
|  | 441 | anything better to use! */ | 
|  | 442 | skipdefault = envpath!=NULL || pythonhome!=NULL || \ | 
|  | 443 | machinepath!=NULL || userpath!=NULL; | 
| Guido van Rossum | 43ff114 | 1998-08-08 23:40:40 +0000 | [diff] [blame] | 444 | #endif | 
|  | 445 |  | 
|  | 446 | /* We need to construct a path from the following parts. | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 447 | (1) the PYTHONPATH environment variable, if set; | 
|  | 448 | (2) for Win32, the machinepath and userpath, if set; | 
|  | 449 | (3) the PYTHONPATH config macro, with the leading "." | 
|  | 450 | of each component replaced with pythonhome, if set; | 
|  | 451 | (4) the directory containing the executable (argv0_path). | 
|  | 452 | The length calculation calculates #3 first. | 
| Guido van Rossum | 43ff114 | 1998-08-08 23:40:40 +0000 | [diff] [blame] | 453 | Extra rules: | 
|  | 454 | - If PYTHONHOME is set (in any way) item (2) is ignored. | 
|  | 455 | - If registry values are used, (3) and (4) are ignored. | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 456 | */ | 
|  | 457 |  | 
|  | 458 | /* Calculate size of return buffer */ | 
|  | 459 | if (pythonhome != NULL) { | 
|  | 460 | char *p; | 
|  | 461 | bufsz = 1; | 
|  | 462 | for (p = PYTHONPATH; *p; p++) { | 
|  | 463 | if (*p == DELIM) | 
|  | 464 | bufsz++; /* number of DELIM plus one */ | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 465 | } | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 466 | bufsz *= strlen(pythonhome); | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 467 | } | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 468 | else | 
|  | 469 | bufsz = 0; | 
| Guido van Rossum | 691d2ad | 1997-12-11 02:32:43 +0000 | [diff] [blame] | 470 | bufsz += strlen(PYTHONPATH) + 1; | 
| Guido van Rossum | 8f1b651 | 1997-08-13 19:55:43 +0000 | [diff] [blame] | 471 | bufsz += strlen(argv0_path) + 1; | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 472 | #ifdef MS_WIN32 | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 473 | if (userpath) | 
|  | 474 | bufsz += strlen(userpath) + 1; | 
| Guido van Rossum | 67ab672 | 1998-08-08 19:58:59 +0000 | [diff] [blame] | 475 | if (machinepath) | 
|  | 476 | bufsz += strlen(machinepath) + 1; | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 477 | #endif | 
| Guido van Rossum | 67ab672 | 1998-08-08 19:58:59 +0000 | [diff] [blame] | 478 | if (envpath != NULL) | 
|  | 479 | bufsz += strlen(envpath) + 1; | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 480 |  | 
|  | 481 | module_search_path = buf = malloc(bufsz); | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 482 | if (buf == NULL) { | 
|  | 483 | /* We can't exit, so print a warning and limp along */ | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 484 | fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n"); | 
|  | 485 | if (envpath) { | 
| Guido van Rossum | e02e48b | 2000-03-29 01:49:47 +0000 | [diff] [blame] | 486 | fprintf(stderr, "Using environment $PYTHONPATH.\n"); | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 487 | module_search_path = envpath; | 
|  | 488 | } | 
|  | 489 | else { | 
| Guido van Rossum | e02e48b | 2000-03-29 01:49:47 +0000 | [diff] [blame] | 490 | fprintf(stderr, "Using default static path.\n"); | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 491 | module_search_path = PYTHONPATH; | 
|  | 492 | } | 
| Guido van Rossum | 42a9744 | 1998-02-19 21:00:45 +0000 | [diff] [blame] | 493 | #ifdef MS_WIN32 | 
|  | 494 | if (machinepath) | 
|  | 495 | free(machinepath); | 
|  | 496 | if (userpath) | 
|  | 497 | free(userpath); | 
|  | 498 | #endif /* MS_WIN32 */ | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 499 | return; | 
|  | 500 | } | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 501 |  | 
|  | 502 | if (envpath) { | 
|  | 503 | strcpy(buf, envpath); | 
|  | 504 | buf = strchr(buf, '\0'); | 
|  | 505 | *buf++ = DELIM; | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 506 | } | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 507 | #ifdef MS_WIN32 | 
| Guido van Rossum | 67ab672 | 1998-08-08 19:58:59 +0000 | [diff] [blame] | 508 | if (userpath) { | 
|  | 509 | strcpy(buf, userpath); | 
|  | 510 | buf = strchr(buf, '\0'); | 
|  | 511 | *buf++ = DELIM; | 
|  | 512 | free(userpath); | 
|  | 513 | } | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 514 | if (machinepath) { | 
|  | 515 | strcpy(buf, machinepath); | 
|  | 516 | buf = strchr(buf, '\0'); | 
|  | 517 | *buf++ = DELIM; | 
| Guido van Rossum | 42a9744 | 1998-02-19 21:00:45 +0000 | [diff] [blame] | 518 | free(machinepath); | 
| Guido van Rossum | e02e48b | 2000-03-29 01:49:47 +0000 | [diff] [blame] | 519 | } | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 520 | if (pythonhome == NULL) { | 
|  | 521 | if (!skipdefault) { | 
|  | 522 | strcpy(buf, PYTHONPATH); | 
|  | 523 | buf = strchr(buf, '\0'); | 
|  | 524 | } | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 525 | } | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 526 | #else | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 527 | if (pythonhome == NULL) { | 
|  | 528 | strcpy(buf, PYTHONPATH); | 
|  | 529 | buf = strchr(buf, '\0'); | 
|  | 530 | } | 
| Guido van Rossum | 88716bb | 2000-03-30 19:45:39 +0000 | [diff] [blame] | 531 | #endif /* MS_WIN32 */ | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 532 | else { | 
|  | 533 | char *p = PYTHONPATH; | 
|  | 534 | char *q; | 
| Guido van Rossum | 1c44e28 | 2000-06-28 22:20:06 +0000 | [diff] [blame] | 535 | size_t n; | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 536 | for (;;) { | 
|  | 537 | q = strchr(p, DELIM); | 
|  | 538 | if (q == NULL) | 
|  | 539 | n = strlen(p); | 
|  | 540 | else | 
|  | 541 | n = q-p; | 
|  | 542 | if (p[0] == '.' && is_sep(p[1])) { | 
|  | 543 | strcpy(buf, pythonhome); | 
|  | 544 | buf = strchr(buf, '\0'); | 
|  | 545 | p++; | 
|  | 546 | n--; | 
|  | 547 | } | 
|  | 548 | strncpy(buf, p, n); | 
|  | 549 | buf += n; | 
|  | 550 | if (q == NULL) | 
|  | 551 | break; | 
|  | 552 | *buf++ = DELIM; | 
|  | 553 | p = q+1; | 
|  | 554 | } | 
|  | 555 | } | 
|  | 556 | if (argv0_path) { | 
|  | 557 | *buf++ = DELIM; | 
|  | 558 | strcpy(buf, argv0_path); | 
|  | 559 | buf = strchr(buf, '\0'); | 
|  | 560 | } | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 561 | *buf = '\0'; | 
|  | 562 | } | 
|  | 563 |  | 
|  | 564 |  | 
|  | 565 | /* External interface */ | 
|  | 566 |  | 
|  | 567 | char * | 
|  | 568 | Py_GetPath() | 
|  | 569 | { | 
|  | 570 | if (!module_search_path) | 
|  | 571 | calculate_path(); | 
|  | 572 | return module_search_path; | 
|  | 573 | } | 
|  | 574 |  | 
|  | 575 | char * | 
|  | 576 | Py_GetPrefix() | 
|  | 577 | { | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 578 | if (!module_search_path) | 
|  | 579 | calculate_path(); | 
|  | 580 | return prefix; | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 581 | } | 
|  | 582 |  | 
|  | 583 | char * | 
|  | 584 | Py_GetExecPrefix() | 
|  | 585 | { | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 586 | return Py_GetPrefix(); | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 587 | } | 
|  | 588 |  | 
|  | 589 | char * | 
| Guido van Rossum | eea1449 | 1997-08-13 21:30:44 +0000 | [diff] [blame] | 590 | Py_GetProgramFullPath() | 
| Guido van Rossum | 1aa7e3a | 1997-05-19 14:16:21 +0000 | [diff] [blame] | 591 | { | 
|  | 592 | if (!module_search_path) | 
|  | 593 | calculate_path(); | 
|  | 594 | return progpath; | 
|  | 595 | } |