PageRenderTime 1119ms CodeModel.GetById 181ms app.highlight 775ms RepoModel.GetById 144ms app.codeStats 1ms

/PC/os2vacpp/getpathp.c

http://unladen-swallow.googlecode.com/
C | 482 lines | 417 code | 23 blank | 42 comment | 16 complexity | 21bccf9374282acfc988ba2af8d5927a MD5 | raw file
  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
 58is_sep(char ch)	/* determine if "ch" is a separator character */
 59{
 60#ifdef ALTSEP
 61	return ch == SEP || ch == ALTSEP;
 62#else
 63	return ch == SEP;
 64#endif
 65}
 66
 67
 68static void
 69reduce(char *dir)
 70{
 71	int i = strlen(dir);
 72	while (i > 0 && !is_sep(dir[i]))
 73		--i;
 74	dir[i] = '\0';
 75}
 76	
 77
 78static int
 79exists(char *filename)
 80{
 81	struct stat buf;
 82	return stat(filename, &buf) == 0;
 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{
 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';
113}
114
115
116static int
117search_for_prefix(char *argv0_path, char *landmark)
118{
119	int n;
120
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;
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{
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;
161
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!
171
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	}
237
238	if (newKey)
239		RegCloseKey(newKey);
240	return retval;
241}
242#endif /* MS_WIN32 */
243
244static void
245get_progpath(void)
246{
247	extern char *Py_GetProgramName(void);
248	char *path = getenv("PATH");
249	char *prog = Py_GetProgramName();
250
251#ifdef MS_WIN32
252	if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
253		return;
254#endif
255	if (prog == NULL || *prog == '\0')
256		prog = "python";
257
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	 */
263#ifdef ALTSEP
264	if (strchr(prog, SEP) || strchr(prog, ALTSEP))
265#else
266	if (strchr(prog, SEP))
267#endif
268		strcpy(progpath, prog);
269	else if (path) {
270		while (1) {
271			char *delim = strchr(path, DELIM);
272
273			if (delim) {
274				int len = delim - path;
275				strncpy(progpath, path, len);
276				*(progpath + len) = '\0';
277			}
278			else
279				strcpy(progpath, path);
280
281			join(progpath, prog);
282			if (exists(progpath))
283				break;
284
285			if (!delim) {
286				progpath[0] = '\0';
287				break;
288			}
289			path = delim + 1;
290		}
291	}
292	else
293		progpath[0] = '\0';
294}
295
296static void
297calculate_path(void)
298{
299	char argv0_path[MAXPATHLEN+1];
300	char *buf;
301	int bufsz;
302	char *pythonhome = Py_GetPythonHome();
303	char *envpath = Py_GETENV("PYTHONPATH");
304#ifdef MS_WIN32
305	char *machinepath, *userpath;
306
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	}
316#endif
317
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;
329
330		strcpy(prefix, pythonhome);
331
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);
340    }
341
342	if (envpath && *envpath == '\0')
343		envpath = NULL;
344
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	*/
353
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;
370#ifdef MS_WIN32
371	if (machinepath)
372		bufsz += strlen(machinepath) + 1;
373	if (userpath)
374		bufsz += strlen(userpath) + 1;
375#endif
376
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	}
391
392	if (envpath) {
393		strcpy(buf, envpath);
394		buf = strchr(buf, '\0');
395		*buf++ = DELIM;
396	}
397#ifdef MS_WIN32
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	}
408#endif
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';
443}
444
445
446/* External interface */
447
448char *
449Py_GetPath(void)
450{
451	if (!module_search_path)
452		calculate_path();
453
454	return module_search_path;
455}
456
457char *
458Py_GetPrefix(void)
459{
460	if (!module_search_path)
461		calculate_path();
462
463	return prefix;
464}
465
466char *
467Py_GetExecPrefix(void)
468{
469	if (!module_search_path)
470		calculate_path();
471
472	return exec_prefix;
473}
474
475char *
476Py_GetProgramFullPath(void)
477{
478	if (!module_search_path)
479		calculate_path();
480
481	return progpath;
482}