source: python/trunk/PC/os2vacpp/getpathp.c

Last change on this file was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

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