blob: 48912f505ac564dd4899b9c36d87998d2c329070 [file] [log] [blame]
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +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
Guido van Rossum8f1b6511997-08-13 19:55:43 +000038#ifdef MS_WIN32
39#include <windows.h>
Guido van Rossumeea14491997-08-13 21:30:44 +000040extern BOOL PyWin_IsWin32s();
Guido van Rossum8f1b6511997-08-13 19:55:43 +000041#endif
42
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +000043#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 Rossum1aa7e3a1997-05-19 14:16:21 +000053 * Py_GetPath() tries to return a sensible Python module search path.
54 *
Guido van Rossum42a97441998-02-19 21:00:45 +000055 * The approach is an adaptation for Windows of the strategy used in
56 * ../Modules/getpath.c; it uses the Windows Registry as one of its
57 * information sources.
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +000058 */
59
60#ifndef LANDMARK
Guido van Rossumeea14491997-08-13 21:30:44 +000061#define LANDMARK "lib\\string.py"
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +000062#endif
63
64static char prefix[MAXPATHLEN+1];
65static char progpath[MAXPATHLEN+1];
66static char *module_search_path = NULL;
67
Guido van Rossumeea14491997-08-13 21:30:44 +000068
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +000069static int
70is_sep(ch) /* determine if "ch" is a separator character */
71 char ch;
72{
73#ifdef ALTSEP
74 return ch == SEP || ch == ALTSEP;
75#else
76 return ch == SEP;
77#endif
78}
79
Guido van Rossumeea14491997-08-13 21:30:44 +000080
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +000081static void
82reduce(dir)
83 char *dir;
84{
85 int i = strlen(dir);
86 while (i > 0 && !is_sep(dir[i]))
87 --i;
88 dir[i] = '\0';
89}
90
91
92static int
93exists(filename)
94 char *filename;
95{
96 struct stat buf;
97 return stat(filename, &buf) == 0;
98}
99
100
101static void
102join(buffer, stuff)
103 char *buffer;
104 char *stuff;
105{
106 int n, k;
107 if (is_sep(stuff[0]))
108 n = 0;
109 else {
110 n = strlen(buffer);
111 if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
112 buffer[n++] = SEP;
113 }
114 k = strlen(stuff);
115 if (n + k > MAXPATHLEN)
116 k = MAXPATHLEN - n;
117 strncpy(buffer+n, stuff, k);
118 buffer[n+k] = '\0';
119}
120
121
122static int
123search_for_prefix(argv0_path, landmark)
124 char *argv0_path;
125 char *landmark;
126{
127 int n;
128
129 /* Search from argv0_path, until root is found */
130 strcpy(prefix, argv0_path);
131 do {
132 n = strlen(prefix);
133 join(prefix, landmark);
Guido van Rossumeea14491997-08-13 21:30:44 +0000134 if (exists(prefix)) {
135 prefix[n] = '\0';
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000136 return 1;
Guido van Rossumeea14491997-08-13 21:30:44 +0000137 }
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000138 prefix[n] = '\0';
139 reduce(prefix);
140 } while (prefix[0]);
141 return 0;
142}
143
Guido van Rossumeea14491997-08-13 21:30:44 +0000144#ifdef MS_WIN32
Guido van Rossum271f9771997-09-29 23:39:31 +0000145#include "malloc.h" // for alloca - see comments below!
146extern const char *PyWin_DLLVersionString; // a string loaded from the DLL at startup.
147
Guido van Rossumeea14491997-08-13 21:30:44 +0000148
149/* Load a PYTHONPATH value from the registry.
150 Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER.
151
152 Returns NULL, or a pointer that should be freed.
153*/
154
155static char *
156getpythonregpath(HKEY keyBase, BOOL bWin32s)
157{
158 HKEY newKey = 0;
159 DWORD nameSize = 0;
160 DWORD dataSize = 0;
161 DWORD numEntries = 0;
162 LONG rc;
163 char *retval = NULL;
164 char *dataBuf;
Guido van Rossum271f9771997-09-29 23:39:31 +0000165 const char keyPrefix[] = "Software\\Python\\PythonCore\\";
166 const char keySuffix[] = "\\PythonPath";
167 int versionLen;
168 char *keyBuf;
169
170 // Tried to use sysget("winver") but here is too early :-(
171 versionLen = strlen(PyWin_DLLVersionString);
172 // alloca == no free required, but memory only local to fn.
173 // also no heap fragmentation! Am I being silly?
174 keyBuf = alloca(sizeof(keyPrefix)-1 + versionLen + sizeof(keySuffix)); // chars only, plus 1 NULL.
175 // lots of constants here for the compiler to optimize away :-)
176 memcpy(keyBuf, keyPrefix, sizeof(keyPrefix)-1);
177 memcpy(keyBuf+sizeof(keyPrefix)-1, PyWin_DLLVersionString, versionLen);
178 memcpy(keyBuf+sizeof(keyPrefix)-1+versionLen, keySuffix, sizeof(keySuffix)); // NULL comes with this one!
179
Guido van Rossumeea14491997-08-13 21:30:44 +0000180 rc=RegOpenKey(keyBase,
Guido van Rossum271f9771997-09-29 23:39:31 +0000181 keyBuf,
Guido van Rossumeea14491997-08-13 21:30:44 +0000182 &newKey);
183 if (rc==ERROR_SUCCESS) {
184 RegQueryInfoKey(newKey, NULL, NULL, NULL, NULL, NULL, NULL,
185 &numEntries, &nameSize, &dataSize, NULL, NULL);
186 }
187 if (bWin32s && numEntries==0 && dataSize==0) {
188 /* must hardcode for Win32s */
189 numEntries = 1;
190 dataSize = 511;
191 }
192 if (numEntries) {
193 /* Loop over all subkeys. */
194 /* Win32s doesnt know how many subkeys, so we do
195 it twice */
196 char keyBuf[MAX_PATH+1];
197 int index = 0;
198 int off = 0;
199 for(index=0;;index++) {
200 long reqdSize = 0;
201 DWORD rc = RegEnumKey(newKey,
202 index, keyBuf, MAX_PATH+1);
203 if (rc) break;
204 rc = RegQueryValue(newKey, keyBuf, NULL, &reqdSize);
205 if (rc) break;
206 if (bWin32s && reqdSize==0) reqdSize = 512;
207 dataSize += reqdSize + 1; /* 1 for the ";" */
208 }
209 dataBuf = malloc(dataSize+1);
210 if (dataBuf==NULL)
211 return NULL; /* pretty serious? Raise error? */
212 /* Now loop over, grabbing the paths.
213 Subkeys before main library */
214 for(index=0;;index++) {
215 int adjust;
216 long reqdSize = dataSize;
217 DWORD rc = RegEnumKey(newKey,
218 index, keyBuf,MAX_PATH+1);
219 if (rc) break;
220 rc = RegQueryValue(newKey,
221 keyBuf, dataBuf+off, &reqdSize);
222 if (rc) break;
223 if (reqdSize>1) {
224 /* If Nothing, or only '\0' copied. */
225 adjust = strlen(dataBuf+off);
226 dataSize -= adjust;
227 off += adjust;
228 dataBuf[off++] = ';';
229 dataBuf[off] = '\0';
230 dataSize--;
231 }
232 }
233 /* Additionally, win32s doesnt work as expected, so
234 the specific strlen() is required for 3.1. */
235 rc = RegQueryValue(newKey, "", dataBuf+off, &dataSize);
236 if (rc==ERROR_SUCCESS) {
237 if (strlen(dataBuf)==0)
238 free(dataBuf);
239 else
240 retval = dataBuf; /* caller will free */
241 }
242 else
243 free(dataBuf);
244 }
245
246 if (newKey)
247 RegCloseKey(newKey);
248 return retval;
249}
250#endif /* MS_WIN32 */
251
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000252static void
253get_progpath()
254{
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000255 extern char *Py_GetProgramName();
256 char *path = getenv("PATH");
257 char *prog = Py_GetProgramName();
258
Guido van Rossumeea14491997-08-13 21:30:44 +0000259#ifdef MS_WIN32
260 if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
261 return;
262#endif
263 if (prog == NULL || *prog == '\0')
264 prog = "python";
265
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000266 /* If there is no slash in the argv0 path, then we have to
267 * assume python is on the user's $PATH, since there's no
268 * other way to find a directory to start the search from. If
269 * $PATH isn't exported, you lose.
270 */
271#ifdef ALTSEP
272 if (strchr(prog, SEP) || strchr(prog, ALTSEP))
273#else
274 if (strchr(prog, SEP))
275#endif
276 strcpy(progpath, prog);
277 else if (path) {
278 while (1) {
279 char *delim = strchr(path, DELIM);
280
281 if (delim) {
282 int len = delim - path;
283 strncpy(progpath, path, len);
284 *(progpath + len) = '\0';
285 }
286 else
287 strcpy(progpath, path);
288
289 join(progpath, prog);
290 if (exists(progpath))
291 break;
292
293 if (!delim) {
294 progpath[0] = '\0';
295 break;
296 }
297 path = delim + 1;
298 }
299 }
300 else
301 progpath[0] = '\0';
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000302}
303
304static void
305calculate_path()
306{
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000307 char argv0_path[MAXPATHLEN+1];
308 char *buf;
309 int bufsz;
Guido van Rossumeea14491997-08-13 21:30:44 +0000310 char *pythonhome = getenv("PYTHONHOME");
311 char *envpath = getenv("PYTHONPATH");
312#ifdef MS_WIN32
313 char *machinepath, *userpath;
314
315 /* Are we running under Windows 3.1(1) Win32s? */
316 if (PyWin_IsWin32s()) {
317 /* Only CLASSES_ROOT is supported */
318 machinepath = getpythonregpath(HKEY_CLASSES_ROOT, TRUE);
319 userpath = NULL;
320 } else {
321 machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, FALSE);
322 userpath = getpythonregpath(HKEY_CURRENT_USER, FALSE);
323 }
324#endif
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000325
326 get_progpath();
327 strcpy(argv0_path, progpath);
328 reduce(argv0_path);
Guido van Rossumeea14491997-08-13 21:30:44 +0000329 if (pythonhome == NULL || *pythonhome == '\0') {
330 if (search_for_prefix(argv0_path, LANDMARK))
331 pythonhome = prefix;
332 else
333 pythonhome = NULL;
334 }
335 else
336 strcpy(prefix, pythonhome);
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000337
Guido van Rossumeea14491997-08-13 21:30:44 +0000338 if (envpath && *envpath == '\0')
339 envpath = NULL;
340
341 /* We need to construct a path from the following parts:
342 (1) the PYTHONPATH environment variable, if set;
343 (2) for Win32, the machinepath and userpath, if set;
344 (3) the PYTHONPATH config macro, with the leading "."
345 of each component replaced with pythonhome, if set;
346 (4) the directory containing the executable (argv0_path).
347 The length calculation calculates #3 first.
348 */
349
350 /* Calculate size of return buffer */
351 if (pythonhome != NULL) {
352 char *p;
353 bufsz = 1;
354 for (p = PYTHONPATH; *p; p++) {
355 if (*p == DELIM)
356 bufsz++; /* number of DELIM plus one */
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000357 }
Guido van Rossumeea14491997-08-13 21:30:44 +0000358 bufsz *= strlen(pythonhome);
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000359 }
Guido van Rossumeea14491997-08-13 21:30:44 +0000360 else
361 bufsz = 0;
Guido van Rossum691d2ad1997-12-11 02:32:43 +0000362 bufsz += strlen(PYTHONPATH) + 1;
Guido van Rossumeea14491997-08-13 21:30:44 +0000363 if (envpath != NULL)
364 bufsz += strlen(envpath) + 1;
Guido van Rossum8f1b6511997-08-13 19:55:43 +0000365 bufsz += strlen(argv0_path) + 1;
Guido van Rossumeea14491997-08-13 21:30:44 +0000366#ifdef MS_WIN32
367 if (machinepath)
368 bufsz += strlen(machinepath) + 1;
369 if (userpath)
370 bufsz += strlen(userpath) + 1;
371#endif
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000372
373 module_search_path = buf = malloc(bufsz);
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000374 if (buf == NULL) {
375 /* We can't exit, so print a warning and limp along */
Guido van Rossumeea14491997-08-13 21:30:44 +0000376 fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
377 if (envpath) {
378 fprintf(stderr, "Using default static $PYTHONPATH.\n");
379 module_search_path = envpath;
380 }
381 else {
382 fprintf(stderr, "Using environment $PYTHONPATH.\n");
383 module_search_path = PYTHONPATH;
384 }
Guido van Rossum42a97441998-02-19 21:00:45 +0000385#ifdef MS_WIN32
386 if (machinepath)
387 free(machinepath);
388 if (userpath)
389 free(userpath);
390#endif /* MS_WIN32 */
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000391 return;
392 }
Guido van Rossumeea14491997-08-13 21:30:44 +0000393
394 if (envpath) {
395 strcpy(buf, envpath);
396 buf = strchr(buf, '\0');
397 *buf++ = DELIM;
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000398 }
Guido van Rossumeea14491997-08-13 21:30:44 +0000399#ifdef MS_WIN32
400 if (machinepath) {
401 strcpy(buf, machinepath);
402 buf = strchr(buf, '\0');
403 *buf++ = DELIM;
Guido van Rossum42a97441998-02-19 21:00:45 +0000404 free(machinepath);
Guido van Rossumeea14491997-08-13 21:30:44 +0000405 }
406 if (userpath) {
407 strcpy(buf, userpath);
408 buf = strchr(buf, '\0');
409 *buf++ = DELIM;
Guido van Rossum42a97441998-02-19 21:00:45 +0000410 free(userpath);
Guido van Rossumeea14491997-08-13 21:30:44 +0000411 }
412#endif
413 if (pythonhome == NULL) {
414 strcpy(buf, PYTHONPATH);
415 buf = strchr(buf, '\0');
416 }
417 else {
418 char *p = PYTHONPATH;
419 char *q;
420 int n;
421 for (;;) {
422 q = strchr(p, DELIM);
423 if (q == NULL)
424 n = strlen(p);
425 else
426 n = q-p;
427 if (p[0] == '.' && is_sep(p[1])) {
428 strcpy(buf, pythonhome);
429 buf = strchr(buf, '\0');
430 p++;
431 n--;
432 }
433 strncpy(buf, p, n);
434 buf += n;
435 if (q == NULL)
436 break;
437 *buf++ = DELIM;
438 p = q+1;
439 }
440 }
441 if (argv0_path) {
442 *buf++ = DELIM;
443 strcpy(buf, argv0_path);
444 buf = strchr(buf, '\0');
445 }
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000446 *buf = '\0';
447}
448
449
450/* External interface */
451
452char *
453Py_GetPath()
454{
455 if (!module_search_path)
456 calculate_path();
457 return module_search_path;
458}
459
460char *
461Py_GetPrefix()
462{
Guido van Rossumeea14491997-08-13 21:30:44 +0000463 if (!module_search_path)
464 calculate_path();
465 return prefix;
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000466}
467
468char *
469Py_GetExecPrefix()
470{
Guido van Rossumeea14491997-08-13 21:30:44 +0000471 return Py_GetPrefix();
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000472}
473
474char *
Guido van Rossumeea14491997-08-13 21:30:44 +0000475Py_GetProgramFullPath()
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000476{
477 if (!module_search_path)
478 calculate_path();
479 return progpath;
480}