Fix an amazing number of typos & malformed sentences reported by Detlef
[python/dscho.git] / PC / getpathp.c
blob80865d73d900d1b08ab06ee01020b89dc8018edf
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Return the initial module search path. */
33 /* Used by DOS, OS/2, Windows 3.1, Windows 95/98, Windows NT. */
35 #include "Python.h"
36 #include "osdefs.h"
38 #ifdef MS_WIN32
39 #include <windows.h>
40 extern BOOL PyWin_IsWin32s();
41 #endif
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <string.h>
47 #if HAVE_UNISTD_H
48 #include <unistd.h>
49 #endif /* HAVE_UNISTD_H */
51 /* Search in some common locations for the associated Python libraries.
53 * Py_GetPath() tries to return a sensible Python module search path.
55 * 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.
60 #ifndef LANDMARK
61 #define LANDMARK "lib\\string.py"
62 #endif
64 static char prefix[MAXPATHLEN+1];
65 static char progpath[MAXPATHLEN+1];
66 static char *module_search_path = NULL;
69 static int
70 is_sep(ch) /* determine if "ch" is a separator character */
71 char ch;
73 #ifdef ALTSEP
74 return ch == SEP || ch == ALTSEP;
75 #else
76 return ch == SEP;
77 #endif
81 static void
82 reduce(dir)
83 char *dir;
85 int i = strlen(dir);
86 while (i > 0 && !is_sep(dir[i]))
87 --i;
88 dir[i] = '\0';
92 static int
93 exists(filename)
94 char *filename;
96 struct stat buf;
97 return stat(filename, &buf) == 0;
101 static int
102 ismodule(filename) /* Is module -- check for .pyc/.pyo too */
103 char *filename;
105 if (exists(filename))
106 return 1;
108 /* Check for the compiled version of prefix. */
109 if (strlen(filename) < MAXPATHLEN) {
110 strcat(filename, Py_OptimizeFlag ? "o" : "c");
111 if (exists(filename))
112 return 1;
114 return 0;
118 static void
119 join(buffer, stuff)
120 char *buffer;
121 char *stuff;
123 int n, k;
124 if (is_sep(stuff[0]))
125 n = 0;
126 else {
127 n = strlen(buffer);
128 if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
129 buffer[n++] = SEP;
131 k = strlen(stuff);
132 if (n + k > MAXPATHLEN)
133 k = MAXPATHLEN - n;
134 strncpy(buffer+n, stuff, k);
135 buffer[n+k] = '\0';
139 static int
140 search_for_prefix(argv0_path, landmark)
141 char *argv0_path;
142 char *landmark;
144 int n;
146 /* Search from argv0_path, until root is found */
147 strcpy(prefix, argv0_path);
148 do {
149 n = strlen(prefix);
150 join(prefix, landmark);
151 if (ismodule(prefix)) {
152 prefix[n] = '\0';
153 return 1;
155 prefix[n] = '\0';
156 reduce(prefix);
157 } while (prefix[0]);
158 return 0;
161 #ifdef MS_WIN32
163 #ifndef BUILD_LANDMARK
164 #define BUILD_LANDMARK "PC\\getpathp.c"
165 #endif
167 #include "malloc.h" // for alloca - see comments below!
168 extern const char *PyWin_DLLVersionString; // a string loaded from the DLL at startup.
171 /* Load a PYTHONPATH value from the registry.
172 Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER.
174 Returns NULL, or a pointer that should be freed.
177 static char *
178 getpythonregpath(HKEY keyBase, BOOL bWin32s)
180 HKEY newKey = 0;
181 DWORD nameSize = 0;
182 DWORD dataSize = 0;
183 DWORD numEntries = 0;
184 LONG rc;
185 char *retval = NULL;
186 char *dataBuf;
187 const char keyPrefix[] = "Software\\Python\\PythonCore\\";
188 const char keySuffix[] = "\\PythonPath";
189 int versionLen;
190 char *keyBuf;
192 // Tried to use sysget("winver") but here is too early :-(
193 versionLen = strlen(PyWin_DLLVersionString);
194 // alloca == no free required, but memory only local to fn.
195 // also no heap fragmentation! Am I being silly?
196 keyBuf = alloca(sizeof(keyPrefix)-1 + versionLen + sizeof(keySuffix)); // chars only, plus 1 NULL.
197 // lots of constants here for the compiler to optimize away :-)
198 memcpy(keyBuf, keyPrefix, sizeof(keyPrefix)-1);
199 memcpy(keyBuf+sizeof(keyPrefix)-1, PyWin_DLLVersionString, versionLen);
200 memcpy(keyBuf+sizeof(keyPrefix)-1+versionLen, keySuffix, sizeof(keySuffix)); // NULL comes with this one!
202 rc=RegOpenKey(keyBase,
203 keyBuf,
204 &newKey);
205 if (rc==ERROR_SUCCESS) {
206 RegQueryInfoKey(newKey, NULL, NULL, NULL, NULL, NULL, NULL,
207 &numEntries, &nameSize, &dataSize, NULL, NULL);
209 if (bWin32s && numEntries==0 && dataSize==0) {
210 /* must hardcode for Win32s */
211 numEntries = 1;
212 dataSize = 511;
214 if (numEntries) {
215 /* Loop over all subkeys. */
216 /* Win32s doesnt know how many subkeys, so we do
217 it twice */
218 char keyBuf[MAX_PATH+1];
219 int index = 0;
220 int off = 0;
221 for(index=0;;index++) {
222 long reqdSize = 0;
223 DWORD rc = RegEnumKey(newKey,
224 index, keyBuf, MAX_PATH+1);
225 if (rc) break;
226 rc = RegQueryValue(newKey, keyBuf, NULL, &reqdSize);
227 if (rc) break;
228 if (bWin32s && reqdSize==0) reqdSize = 512;
229 dataSize += reqdSize + 1; /* 1 for the ";" */
231 dataBuf = malloc(dataSize+1);
232 if (dataBuf==NULL)
233 return NULL; /* pretty serious? Raise error? */
234 /* Now loop over, grabbing the paths.
235 Subkeys before main library */
236 for(index=0;;index++) {
237 int adjust;
238 long reqdSize = dataSize;
239 DWORD rc = RegEnumKey(newKey,
240 index, keyBuf,MAX_PATH+1);
241 if (rc) break;
242 rc = RegQueryValue(newKey,
243 keyBuf, dataBuf+off, &reqdSize);
244 if (rc) break;
245 if (reqdSize>1) {
246 /* If Nothing, or only '\0' copied. */
247 adjust = strlen(dataBuf+off);
248 dataSize -= adjust;
249 off += adjust;
250 dataBuf[off++] = ';';
251 dataBuf[off] = '\0';
252 dataSize--;
255 /* Additionally, win32s doesnt work as expected, so
256 the specific strlen() is required for 3.1. */
257 rc = RegQueryValue(newKey, "", dataBuf+off, &dataSize);
258 if (rc==ERROR_SUCCESS) {
259 if (strlen(dataBuf)==0)
260 free(dataBuf);
261 else
262 retval = dataBuf; /* caller will free */
264 else
265 free(dataBuf);
268 if (newKey)
269 RegCloseKey(newKey);
270 return retval;
272 #endif /* MS_WIN32 */
274 static void
275 get_progpath()
277 extern char *Py_GetProgramName();
278 char *path = getenv("PATH");
279 char *prog = Py_GetProgramName();
281 #ifdef MS_WIN32
282 if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
283 return;
284 #endif
285 if (prog == NULL || *prog == '\0')
286 prog = "python";
288 /* If there is no slash in the argv0 path, then we have to
289 * assume python is on the user's $PATH, since there's no
290 * other way to find a directory to start the search from. If
291 * $PATH isn't exported, you lose.
293 #ifdef ALTSEP
294 if (strchr(prog, SEP) || strchr(prog, ALTSEP))
295 #else
296 if (strchr(prog, SEP))
297 #endif
298 strcpy(progpath, prog);
299 else if (path) {
300 while (1) {
301 char *delim = strchr(path, DELIM);
303 if (delim) {
304 int len = delim - path;
305 strncpy(progpath, path, len);
306 *(progpath + len) = '\0';
308 else
309 strcpy(progpath, path);
311 join(progpath, prog);
312 if (exists(progpath))
313 break;
315 if (!delim) {
316 progpath[0] = '\0';
317 break;
319 path = delim + 1;
322 else
323 progpath[0] = '\0';
326 static void
327 calculate_path()
329 char argv0_path[MAXPATHLEN+1];
330 char *buf;
331 int bufsz;
332 char *pythonhome = Py_GetPythonHome();
333 char *envpath = getenv("PYTHONPATH");
335 #ifdef MS_WIN32
336 char *machinepath = NULL;
337 char *userpath = NULL;
338 #endif
340 get_progpath();
341 strcpy(argv0_path, progpath);
342 reduce(argv0_path);
343 if (pythonhome == NULL || *pythonhome == '\0') {
344 if (search_for_prefix(argv0_path, LANDMARK))
345 pythonhome = prefix;
346 else
347 pythonhome = NULL;
349 else
350 strcpy(prefix, pythonhome);
352 if (envpath && *envpath == '\0')
353 envpath = NULL;
355 #ifdef MS_WIN32
356 /* Are we running under Windows 3.1(1) Win32s? */
357 if (PyWin_IsWin32s()) {
358 /* Only CLASSES_ROOT is supported */
359 machinepath = getpythonregpath(HKEY_CLASSES_ROOT, TRUE);
360 userpath = NULL;
361 } else {
362 machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, FALSE);
363 userpath = getpythonregpath(HKEY_CURRENT_USER, FALSE);
365 #endif
367 /* We need to construct a path from the following parts.
368 (1) the PYTHONPATH environment variable, if set;
369 (2) for Win32, the machinepath and userpath, if set;
370 (3) the PYTHONPATH config macro, with the leading "."
371 of each component replaced with pythonhome, if set;
372 (4) the directory containing the executable (argv0_path).
373 The length calculation calculates #3 first.
374 Extra rules:
375 - If PYTHONHOME is set (in any way) item (2) is ignored.
376 - If registry values are used, (3) and (4) are ignored.
379 /* Calculate size of return buffer */
380 if (pythonhome != NULL) {
381 char *p;
382 bufsz = 1;
383 for (p = PYTHONPATH; *p; p++) {
384 if (*p == DELIM)
385 bufsz++; /* number of DELIM plus one */
387 bufsz *= strlen(pythonhome);
389 else
390 bufsz = 0;
391 bufsz += strlen(PYTHONPATH) + 1;
392 bufsz += strlen(argv0_path) + 1;
393 #ifdef MS_WIN32
394 if (userpath)
395 bufsz += strlen(userpath) + 1;
396 if (machinepath)
397 bufsz += strlen(machinepath) + 1;
398 #endif
399 if (envpath != NULL)
400 bufsz += strlen(envpath) + 1;
402 module_search_path = buf = malloc(bufsz);
403 if (buf == NULL) {
404 /* We can't exit, so print a warning and limp along */
405 fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
406 if (envpath) {
407 fprintf(stderr, "Using default static $PYTHONPATH.\n");
408 module_search_path = envpath;
410 else {
411 fprintf(stderr, "Using environment $PYTHONPATH.\n");
412 module_search_path = PYTHONPATH;
414 #ifdef MS_WIN32
415 if (machinepath)
416 free(machinepath);
417 if (userpath)
418 free(userpath);
419 #endif /* MS_WIN32 */
420 return;
423 if (envpath) {
424 strcpy(buf, envpath);
425 buf = strchr(buf, '\0');
426 *buf++ = DELIM;
428 #ifdef MS_WIN32
429 if (userpath) {
430 strcpy(buf, userpath);
431 buf = strchr(buf, '\0');
432 *buf++ = DELIM;
433 free(userpath);
435 if (machinepath) {
436 strcpy(buf, machinepath);
437 buf = strchr(buf, '\0');
438 *buf++ = DELIM;
439 free(machinepath);
441 #endif
442 if (pythonhome == NULL) {
443 strcpy(buf, PYTHONPATH);
444 buf = strchr(buf, '\0');
446 else {
447 char *p = PYTHONPATH;
448 char *q;
449 int n;
450 for (;;) {
451 q = strchr(p, DELIM);
452 if (q == NULL)
453 n = strlen(p);
454 else
455 n = q-p;
456 if (p[0] == '.' && is_sep(p[1])) {
457 strcpy(buf, pythonhome);
458 buf = strchr(buf, '\0');
459 p++;
460 n--;
462 strncpy(buf, p, n);
463 buf += n;
464 if (q == NULL)
465 break;
466 *buf++ = DELIM;
467 p = q+1;
470 if (argv0_path) {
471 *buf++ = DELIM;
472 strcpy(buf, argv0_path);
473 buf = strchr(buf, '\0');
475 *buf = '\0';
479 /* External interface */
481 char *
482 Py_GetPath()
484 if (!module_search_path)
485 calculate_path();
486 return module_search_path;
489 char *
490 Py_GetPrefix()
492 if (!module_search_path)
493 calculate_path();
494 return prefix;
497 char *
498 Py_GetExecPrefix()
500 return Py_GetPrefix();
503 char *
504 Py_GetProgramFullPath()
506 if (!module_search_path)
507 calculate_path();
508 return progpath;