blob: 69e38cb814f0499652286ad20e9df873e0dbb5e7 [file] [log] [blame]
Guido van Rossum50d4cc21997-11-22 21:59:45 +00001/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
32/* Return the initial module search path. */
33/* Used by DOS, OS/2, Windows 3.1. Works on NT too. */
34
35#include "Python.h"
36#include "osdefs.h"
37
38#ifdef MS_WIN32
39#include <windows.h>
40extern BOOL PyWin_IsWin32s();
41#endif
42
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <string.h>
46
47#if HAVE_UNISTD_H
48#include <unistd.h>
49#endif /* HAVE_UNISTD_H */
50
51/* Search in some common locations for the associated Python libraries.
52 *
Guido van Rossuma34c3131997-12-05 22:07:14 +000053 * Two directories must be found, the platform independent directory
54 * (prefix), containing the common .py and .pyc files, and the platform
55 * dependent directory (exec_prefix), containing the shared library
56 * modules. Note that prefix and exec_prefix can be the same directory,
57 * but for some installations, they are different.
Guido van Rossum50d4cc21997-11-22 21:59:45 +000058 *
59 * Py_GetPath() tries to return a sensible Python module search path.
60 *
61 * First, we look to see if the executable is in a subdirectory of
62 * the Python build directory. We calculate the full path of the
63 * directory containing the executable as progpath. We work backwards
64 * along progpath and look for $dir/Modules/Setup.in, a distinctive
65 * landmark. If found, we use $dir/Lib as $root. The returned
66 * Python path is the compiled #define PYTHONPATH with all the initial
67 * "./lib" replaced by $root.
68 *
69 * Otherwise, if there is a PYTHONPATH environment variable, we return that.
70 *
71 * Otherwise we try to find $progpath/lib/string.py, and if found, then
72 * root is $progpath/lib, and we return Python path as compiled PYTHONPATH
73 * with all "./lib" replaced by $root (as above).
74 *
75 */
76
77#ifndef LANDMARK
78#define LANDMARK "lib\\string.py"
79#endif
80
81static char prefix[MAXPATHLEN+1];
Guido van Rossuma34c3131997-12-05 22:07:14 +000082static char exec_prefix[MAXPATHLEN+1];
Guido van Rossum50d4cc21997-11-22 21:59:45 +000083static char progpath[MAXPATHLEN+1];
84static char *module_search_path = NULL;
85
86
87static int
88is_sep(ch) /* determine if "ch" is a separator character */
89 char ch;
90{
91#ifdef ALTSEP
92 return ch == SEP || ch == ALTSEP;
93#else
94 return ch == SEP;
95#endif
96}
97
98
99static void
100reduce(dir)
101 char *dir;
102{
103 int i = strlen(dir);
104 while (i > 0 && !is_sep(dir[i]))
105 --i;
106 dir[i] = '\0';
107}
108
109
110static int
111exists(filename)
112 char *filename;
113{
114 struct stat buf;
115 return stat(filename, &buf) == 0;
116}
117
118
119static void
120join(buffer, stuff)
121 char *buffer;
122 char *stuff;
123{
124 int n, k;
125 if (is_sep(stuff[0]))
126 n = 0;
127 else {
128 n = strlen(buffer);
129 if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
130 buffer[n++] = SEP;
131 }
132 k = strlen(stuff);
133 if (n + k > MAXPATHLEN)
134 k = MAXPATHLEN - n;
135 strncpy(buffer+n, stuff, k);
136 buffer[n+k] = '\0';
137}
138
139
140static int
141search_for_prefix(argv0_path, landmark)
142 char *argv0_path;
143 char *landmark;
144{
145 int n;
146
147 /* Search from argv0_path, until root is found */
148 strcpy(prefix, argv0_path);
149 do {
150 n = strlen(prefix);
151 join(prefix, landmark);
152 if (exists(prefix)) {
153 prefix[n] = '\0';
154 return 1;
155 }
156 prefix[n] = '\0';
157 reduce(prefix);
158 } while (prefix[0]);
159 return 0;
160}
161
162#ifdef MS_WIN32
163#include "malloc.h" // for alloca - see comments below!
164extern const char *PyWin_DLLVersionString; // a string loaded from the DLL at startup.
165
166
167/* Load a PYTHONPATH value from the registry.
168 Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER.
169
170 Returns NULL, or a pointer that should be freed.
171*/
172
173static char *
174getpythonregpath(HKEY keyBase, BOOL bWin32s)
175{
176 HKEY newKey = 0;
177 DWORD nameSize = 0;
178 DWORD dataSize = 0;
179 DWORD numEntries = 0;
180 LONG rc;
181 char *retval = NULL;
182 char *dataBuf;
183 const char keyPrefix[] = "Software\\Python\\PythonCore\\";
184 const char keySuffix[] = "\\PythonPath";
185 int versionLen;
186 char *keyBuf;
187
188 // Tried to use sysget("winver") but here is too early :-(
189 versionLen = strlen(PyWin_DLLVersionString);
190 // alloca == no free required, but memory only local to fn.
191 // also no heap fragmentation! Am I being silly?
192 keyBuf = alloca(sizeof(keyPrefix)-1 + versionLen + sizeof(keySuffix)); // chars only, plus 1 NULL.
193 // lots of constants here for the compiler to optimize away :-)
194 memcpy(keyBuf, keyPrefix, sizeof(keyPrefix)-1);
195 memcpy(keyBuf+sizeof(keyPrefix)-1, PyWin_DLLVersionString, versionLen);
196 memcpy(keyBuf+sizeof(keyPrefix)-1+versionLen, keySuffix, sizeof(keySuffix)); // NULL comes with this one!
197
198 rc=RegOpenKey(keyBase,
199 keyBuf,
200 &newKey);
201 if (rc==ERROR_SUCCESS) {
202 RegQueryInfoKey(newKey, NULL, NULL, NULL, NULL, NULL, NULL,
203 &numEntries, &nameSize, &dataSize, NULL, NULL);
204 }
205 if (bWin32s && numEntries==0 && dataSize==0) {
206 /* must hardcode for Win32s */
207 numEntries = 1;
208 dataSize = 511;
209 }
210 if (numEntries) {
211 /* Loop over all subkeys. */
212 /* Win32s doesnt know how many subkeys, so we do
213 it twice */
214 char keyBuf[MAX_PATH+1];
215 int index = 0;
216 int off = 0;
217 for(index=0;;index++) {
218 long reqdSize = 0;
219 DWORD rc = RegEnumKey(newKey,
220 index, keyBuf, MAX_PATH+1);
221 if (rc) break;
222 rc = RegQueryValue(newKey, keyBuf, NULL, &reqdSize);
223 if (rc) break;
224 if (bWin32s && reqdSize==0) reqdSize = 512;
225 dataSize += reqdSize + 1; /* 1 for the ";" */
226 }
227 dataBuf = malloc(dataSize+1);
228 if (dataBuf==NULL)
229 return NULL; /* pretty serious? Raise error? */
230 /* Now loop over, grabbing the paths.
231 Subkeys before main library */
232 for(index=0;;index++) {
233 int adjust;
234 long reqdSize = dataSize;
235 DWORD rc = RegEnumKey(newKey,
236 index, keyBuf,MAX_PATH+1);
237 if (rc) break;
238 rc = RegQueryValue(newKey,
239 keyBuf, dataBuf+off, &reqdSize);
240 if (rc) break;
241 if (reqdSize>1) {
242 /* If Nothing, or only '\0' copied. */
243 adjust = strlen(dataBuf+off);
244 dataSize -= adjust;
245 off += adjust;
246 dataBuf[off++] = ';';
247 dataBuf[off] = '\0';
248 dataSize--;
249 }
250 }
251 /* Additionally, win32s doesnt work as expected, so
252 the specific strlen() is required for 3.1. */
253 rc = RegQueryValue(newKey, "", dataBuf+off, &dataSize);
254 if (rc==ERROR_SUCCESS) {
255 if (strlen(dataBuf)==0)
256 free(dataBuf);
257 else
258 retval = dataBuf; /* caller will free */
259 }
260 else
261 free(dataBuf);
262 }
263
264 if (newKey)
265 RegCloseKey(newKey);
266 return retval;
267}
268#endif /* MS_WIN32 */
269
270static void
271get_progpath()
272{
273 extern char *Py_GetProgramName();
274 char *path = getenv("PATH");
275 char *prog = Py_GetProgramName();
276
277#ifdef MS_WIN32
278 if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
279 return;
280#endif
281 if (prog == NULL || *prog == '\0')
282 prog = "python";
283
284 /* If there is no slash in the argv0 path, then we have to
285 * assume python is on the user's $PATH, since there's no
286 * other way to find a directory to start the search from. If
287 * $PATH isn't exported, you lose.
288 */
289#ifdef ALTSEP
290 if (strchr(prog, SEP) || strchr(prog, ALTSEP))
291#else
292 if (strchr(prog, SEP))
293#endif
294 strcpy(progpath, prog);
295 else if (path) {
296 while (1) {
297 char *delim = strchr(path, DELIM);
298
299 if (delim) {
300 int len = delim - path;
301 strncpy(progpath, path, len);
302 *(progpath + len) = '\0';
303 }
304 else
305 strcpy(progpath, path);
306
307 join(progpath, prog);
308 if (exists(progpath))
309 break;
310
311 if (!delim) {
312 progpath[0] = '\0';
313 break;
314 }
315 path = delim + 1;
316 }
317 }
318 else
319 progpath[0] = '\0';
320}
321
322static void
323calculate_path()
324{
325 char argv0_path[MAXPATHLEN+1];
326 char *buf;
327 int bufsz;
328 char *pythonhome = getenv("PYTHONHOME");
329 char *envpath = getenv("PYTHONPATH");
330#ifdef MS_WIN32
331 char *machinepath, *userpath;
332
333 /* Are we running under Windows 3.1(1) Win32s? */
334 if (PyWin_IsWin32s()) {
335 /* Only CLASSES_ROOT is supported */
336 machinepath = getpythonregpath(HKEY_CLASSES_ROOT, TRUE);
337 userpath = NULL;
338 } else {
339 machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, FALSE);
340 userpath = getpythonregpath(HKEY_CURRENT_USER, FALSE);
341 }
342#endif
343
344 get_progpath();
345 strcpy(argv0_path, progpath);
346 reduce(argv0_path);
347 if (pythonhome == NULL || *pythonhome == '\0') {
348 if (search_for_prefix(argv0_path, LANDMARK))
349 pythonhome = prefix;
350 else
351 pythonhome = NULL;
352 }
Guido van Rossuma34c3131997-12-05 22:07:14 +0000353 else {
354 char *delim;
355
Guido van Rossum50d4cc21997-11-22 21:59:45 +0000356 strcpy(prefix, pythonhome);
357
Guido van Rossuma34c3131997-12-05 22:07:14 +0000358 /* Extract Any Optional Trailing EXEC_PREFIX */
359 /* e.g. PYTHONHOME=<prefix>:<exec_prefix> */
360 delim = strchr(prefix, DELIM);
361 if (delim) {
362 *delim = '\0';
363 strcpy(exec_prefix, delim+1);
364 } else
365 strcpy(exec_prefix, EXEC_PREFIX);
366 }
367
Guido van Rossum50d4cc21997-11-22 21:59:45 +0000368 if (envpath && *envpath == '\0')
369 envpath = NULL;
370
371 /* We need to construct a path from the following parts:
372 (1) the PYTHONPATH environment variable, if set;
373 (2) for Win32, the machinepath and userpath, if set;
374 (3) the PYTHONPATH config macro, with the leading "."
375 of each component replaced with pythonhome, if set;
376 (4) the directory containing the executable (argv0_path).
377 The length calculation calculates #3 first.
378 */
379
380 /* Calculate size of return buffer */
381 if (pythonhome != NULL) {
382 char *p;
383 bufsz = 1;
384 for (p = PYTHONPATH; *p; p++) {
385 if (*p == DELIM)
386 bufsz++; /* number of DELIM plus one */
387 }
388 bufsz *= strlen(pythonhome);
389 }
390 else
391 bufsz = 0;
392 bufsz += strlen(PYTHONPATH);
393 if (envpath != NULL)
394 bufsz += strlen(envpath) + 1;
395 bufsz += strlen(argv0_path) + 1;
396#ifdef MS_WIN32
397 if (machinepath)
398 bufsz += strlen(machinepath) + 1;
399 if (userpath)
400 bufsz += strlen(userpath) + 1;
401#endif
402
403 module_search_path = buf = malloc(bufsz);
404 if (buf == NULL) {
405 /* We can't exit, so print a warning and limp along */
406 fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
407 if (envpath) {
408 fprintf(stderr, "Using default static $PYTHONPATH.\n");
409 module_search_path = envpath;
410 }
411 else {
412 fprintf(stderr, "Using environment $PYTHONPATH.\n");
413 module_search_path = PYTHONPATH;
414 }
415 return;
416 }
417
418 if (envpath) {
419 strcpy(buf, envpath);
420 buf = strchr(buf, '\0');
421 *buf++ = DELIM;
422 }
423#ifdef MS_WIN32
424 if (machinepath) {
425 strcpy(buf, machinepath);
426 buf = strchr(buf, '\0');
427 *buf++ = DELIM;
428 }
429 if (userpath) {
430 strcpy(buf, userpath);
431 buf = strchr(buf, '\0');
432 *buf++ = DELIM;
433 }
434#endif
435 if (pythonhome == NULL) {
436 strcpy(buf, PYTHONPATH);
437 buf = strchr(buf, '\0');
438 }
439 else {
440 char *p = PYTHONPATH;
441 char *q;
442 int n;
443 for (;;) {
444 q = strchr(p, DELIM);
445 if (q == NULL)
446 n = strlen(p);
447 else
448 n = q-p;
449 if (p[0] == '.' && is_sep(p[1])) {
450 strcpy(buf, pythonhome);
451 buf = strchr(buf, '\0');
452 p++;
453 n--;
454 }
455 strncpy(buf, p, n);
456 buf += n;
457 if (q == NULL)
458 break;
459 *buf++ = DELIM;
460 p = q+1;
461 }
462 }
463 if (argv0_path) {
464 *buf++ = DELIM;
465 strcpy(buf, argv0_path);
466 buf = strchr(buf, '\0');
467 }
468 *buf = '\0';
469}
470
471
472/* External interface */
473
474char *
475Py_GetPath()
476{
477 if (!module_search_path)
478 calculate_path();
479
480 return module_search_path;
481}
482
483char *
484Py_GetPrefix()
485{
486 if (!module_search_path)
487 calculate_path();
488
489 return prefix;
490}
491
492char *
493Py_GetExecPrefix()
494{
Guido van Rossuma34c3131997-12-05 22:07:14 +0000495 if (!module_search_path)
496 calculate_path();
497
498 return exec_prefix;
Guido van Rossum50d4cc21997-11-22 21:59:45 +0000499}
500
501char *
502Py_GetProgramFullPath()
503{
504 if (!module_search_path)
505 calculate_path();
506
507 return progpath;
508}