PageRenderTime 493ms CodeModel.GetById 151ms app.highlight 108ms RepoModel.GetById 147ms app.codeStats 1ms

/PC/getpathp.c

http://unladen-swallow.googlecode.com/
C | 714 lines | 591 code | 27 blank | 96 comment | 19 complexity | 224416e8d3fe2d668437aa82bf664775 MD5 | raw file
  1
  2/* Return the initial module search path. */
  3/* Used by DOS, OS/2, Windows 3.1, Windows 95/98, Windows NT. */
  4
  5/* ----------------------------------------------------------------
  6   PATH RULES FOR WINDOWS:
  7   This describes how sys.path is formed on Windows.  It describes the 
  8   functionality, not the implementation (ie, the order in which these 
  9   are actually fetched is different)
 10
 11   * Python always adds an empty entry at the start, which corresponds
 12     to the current directory.
 13
 14   * If the PYTHONPATH env. var. exists, its entries are added next.
 15
 16   * We look in the registry for "application paths" - that is, sub-keys
 17     under the main PythonPath registry key.  These are added next (the
 18     order of sub-key processing is undefined).
 19     HKEY_CURRENT_USER is searched and added first.
 20     HKEY_LOCAL_MACHINE is searched and added next.
 21     (Note that all known installers only use HKLM, so HKCU is typically
 22     empty)
 23
 24   * We attempt to locate the "Python Home" - if the PYTHONHOME env var
 25     is set, we believe it.  Otherwise, we use the path of our host .EXE's
 26     to try and locate our "landmark" (lib\\os.py) and deduce our home.
 27     - If we DO have a Python Home: The relevant sub-directories (Lib, 
 28       plat-win, lib-tk, etc) are based on the Python Home
 29     - If we DO NOT have a Python Home, the core Python Path is
 30       loaded from the registry.  This is the main PythonPath key, 
 31       and both HKLM and HKCU are combined to form the path)
 32
 33   * Iff - we can not locate the Python Home, have not had a PYTHONPATH
 34     specified, and can't locate any Registry entries (ie, we have _nothing_
 35     we can assume is a good path), a default path with relative entries is 
 36     used (eg. .\Lib;.\plat-win, etc)
 37
 38
 39  The end result of all this is:
 40  * When running python.exe, or any other .exe in the main Python directory
 41    (either an installed version, or directly from the PCbuild directory),
 42    the core path is deduced, and the core paths in the registry are
 43    ignored.  Other "application paths" in the registry are always read.
 44
 45  * When Python is hosted in another exe (different directory, embedded via 
 46    COM, etc), the Python Home will not be deduced, so the core path from
 47    the registry is used.  Other "application paths" in the registry are 
 48    always read.
 49
 50  * If Python can't find its home and there is no registry (eg, frozen
 51    exe, some very strange installation setup) you get a path with
 52    some default, but relative, paths.
 53
 54   ---------------------------------------------------------------- */
 55
 56
 57#include "Python.h"
 58#include "osdefs.h"
 59
 60#ifdef MS_WINDOWS
 61#include <windows.h>
 62#include <tchar.h>
 63#endif
 64
 65#ifdef HAVE_SYS_TYPES_H
 66#include <sys/types.h>
 67#endif /* HAVE_SYS_TYPES_H */
 68
 69#ifdef HAVE_SYS_STAT_H
 70#include <sys/stat.h>
 71#endif /* HAVE_SYS_STAT_H */
 72
 73#include <string.h>
 74
 75/* Search in some common locations for the associated Python libraries.
 76 *
 77 * Py_GetPath() tries to return a sensible Python module search path.
 78 *
 79 * The approach is an adaptation for Windows of the strategy used in
 80 * ../Modules/getpath.c; it uses the Windows Registry as one of its
 81 * information sources.
 82 */
 83
 84#ifndef LANDMARK
 85#define LANDMARK "lib\\os.py"
 86#endif
 87
 88static char prefix[MAXPATHLEN+1];
 89static char progpath[MAXPATHLEN+1];
 90static char dllpath[MAXPATHLEN+1];
 91static char *module_search_path = NULL;
 92
 93
 94static int
 95is_sep(char ch)	/* determine if "ch" is a separator character */
 96{
 97#ifdef ALTSEP
 98	return ch == SEP || ch == ALTSEP;
 99#else
100	return ch == SEP;
101#endif
102}
103
104/* assumes 'dir' null terminated in bounds.  Never writes
105   beyond existing terminator.
106*/
107static void
108reduce(char *dir)
109{
110	size_t i = strlen(dir);
111	while (i > 0 && !is_sep(dir[i]))
112		--i;
113	dir[i] = '\0';
114}
115	
116
117static int
118exists(char *filename)
119{
120	struct stat buf;
121	return stat(filename, &buf) == 0;
122}
123
124/* Assumes 'filename' MAXPATHLEN+1 bytes long - 
125   may extend 'filename' by one character.
126*/
127static int
128ismodule(char *filename)	/* Is module -- check for .pyc/.pyo too */
129{
130	if (exists(filename))
131		return 1;
132
133	/* Check for the compiled version of prefix. */
134	if (strlen(filename) < MAXPATHLEN) {
135		strcat(filename, Py_OptimizeFlag ? "o" : "c");
136		if (exists(filename))
137			return 1;
138	}
139	return 0;
140}
141
142/* Add a path component, by appending stuff to buffer.
143   buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
144   NUL-terminated string with no more than MAXPATHLEN characters (not counting
145   the trailing NUL).  It's a fatal error if it contains a string longer than
146   that (callers must be careful!).  If these requirements are met, it's
147   guaranteed that buffer will still be a NUL-terminated string with no more
148   than MAXPATHLEN characters at exit.  If stuff is too long, only as much of
149   stuff as fits will be appended.
150*/
151static void
152join(char *buffer, char *stuff)
153{
154	size_t n, k;
155	if (is_sep(stuff[0]))
156		n = 0;
157	else {
158		n = strlen(buffer);
159		if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
160			buffer[n++] = SEP;
161	}
162	if (n > MAXPATHLEN)
163		Py_FatalError("buffer overflow in getpathp.c's joinpath()");
164	k = strlen(stuff);
165	if (n + k > MAXPATHLEN)
166		k = MAXPATHLEN - n;
167	strncpy(buffer+n, stuff, k);
168	buffer[n+k] = '\0';
169}
170
171/* gotlandmark only called by search_for_prefix, which ensures
172   'prefix' is null terminated in bounds.  join() ensures
173   'landmark' can not overflow prefix if too long.
174*/
175static int
176gotlandmark(char *landmark)
177{
178	int ok;
179	Py_ssize_t n;
180
181	n = strlen(prefix);
182	join(prefix, landmark);
183	ok = ismodule(prefix);
184	prefix[n] = '\0';
185	return ok;
186}
187
188/* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd. 
189   assumption provided by only caller, calculate_path() */
190static int
191search_for_prefix(char *argv0_path, char *landmark)
192{
193	/* Search from argv0_path, until landmark is found */
194	strcpy(prefix, argv0_path);
195	do {
196		if (gotlandmark(landmark))
197			return 1;
198		reduce(prefix);
199	} while (prefix[0]);
200	return 0;
201}
202
203#ifdef MS_WINDOWS
204#ifdef Py_ENABLE_SHARED
205
206/* a string loaded from the DLL at startup.*/
207extern const char *PyWin_DLLVersionString;
208
209
210/* Load a PYTHONPATH value from the registry.
211   Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER.
212
213   Works in both Unicode and 8bit environments.  Only uses the
214   Ex family of functions so it also works with Windows CE.
215
216   Returns NULL, or a pointer that should be freed.
217
218   XXX - this code is pretty strange, as it used to also
219   work on Win16, where the buffer sizes werent available
220   in advance.  It could be simplied now Win16/Win32s is dead!
221*/
222
223static char *
224getpythonregpath(HKEY keyBase, int skipcore)
225{
226	HKEY newKey = 0;
227	DWORD dataSize = 0;
228	DWORD numKeys = 0;
229	LONG rc;
230	char *retval = NULL;
231	TCHAR *dataBuf = NULL;
232	static const TCHAR keyPrefix[] = _T("Software\\Python\\PythonCore\\");
233	static const TCHAR keySuffix[] = _T("\\PythonPath");
234	size_t versionLen;
235	DWORD index;
236	TCHAR *keyBuf = NULL;
237	TCHAR *keyBufPtr;
238	TCHAR **ppPaths = NULL;
239
240	/* Tried to use sysget("winver") but here is too early :-( */
241	versionLen = _tcslen(PyWin_DLLVersionString);
242	/* Space for all the chars, plus one \0 */
243	keyBuf = keyBufPtr = malloc(sizeof(keyPrefix) + 
244		                    sizeof(TCHAR)*(versionLen-1) + 
245				    sizeof(keySuffix));
246	if (keyBuf==NULL) goto done;
247
248	memcpy(keyBufPtr, keyPrefix, sizeof(keyPrefix)-sizeof(TCHAR));
249	keyBufPtr += sizeof(keyPrefix)/sizeof(TCHAR) - 1;
250	memcpy(keyBufPtr, PyWin_DLLVersionString, versionLen * sizeof(TCHAR));
251	keyBufPtr += versionLen;
252	/* NULL comes with this one! */
253	memcpy(keyBufPtr, keySuffix, sizeof(keySuffix));
254	/* Open the root Python key */
255	rc=RegOpenKeyEx(keyBase,
256	                keyBuf, /* subkey */
257	                0, /* reserved */
258	                KEY_READ,
259	                &newKey);
260	if (rc!=ERROR_SUCCESS) goto done;
261	/* Find out how big our core buffer is, and how many subkeys we have */
262	rc = RegQueryInfoKey(newKey, NULL, NULL, NULL, &numKeys, NULL, NULL, 
263	                NULL, NULL, &dataSize, NULL, NULL);
264	if (rc!=ERROR_SUCCESS) goto done;
265	if (skipcore) dataSize = 0; /* Only count core ones if we want them! */
266	/* Allocate a temp array of char buffers, so we only need to loop 
267	   reading the registry once
268	*/
269	ppPaths = malloc( sizeof(TCHAR *) * numKeys );
270	if (ppPaths==NULL) goto done;
271	memset(ppPaths, 0, sizeof(TCHAR *) * numKeys);
272	/* Loop over all subkeys, allocating a temp sub-buffer. */
273	for(index=0;index<numKeys;index++) {
274		TCHAR keyBuf[MAX_PATH+1];
275		HKEY subKey = 0;
276		DWORD reqdSize = MAX_PATH+1;
277		/* Get the sub-key name */
278		DWORD rc = RegEnumKeyEx(newKey, index, keyBuf, &reqdSize,
279		                        NULL, NULL, NULL, NULL );
280		if (rc!=ERROR_SUCCESS) goto done;
281		/* Open the sub-key */
282		rc=RegOpenKeyEx(newKey,
283						keyBuf, /* subkey */
284						0, /* reserved */
285						KEY_READ,
286						&subKey);
287		if (rc!=ERROR_SUCCESS) goto done;
288		/* Find the value of the buffer size, malloc, then read it */
289		RegQueryValueEx(subKey, NULL, 0, NULL, NULL, &reqdSize);
290		if (reqdSize) {
291			ppPaths[index] = malloc(reqdSize);
292			if (ppPaths[index]) {
293				RegQueryValueEx(subKey, NULL, 0, NULL, 
294				                (LPBYTE)ppPaths[index], 
295				                &reqdSize);
296				dataSize += reqdSize + 1; /* 1 for the ";" */
297			}
298		}
299		RegCloseKey(subKey);
300	}
301
302	/* return null if no path to return */
303	if (dataSize == 0) goto done;
304
305	/* original datasize from RegQueryInfo doesn't include the \0 */
306	dataBuf = malloc((dataSize+1) * sizeof(TCHAR));
307	if (dataBuf) {
308		TCHAR *szCur = dataBuf;
309		DWORD reqdSize = dataSize;
310		/* Copy our collected strings */
311		for (index=0;index<numKeys;index++) {
312			if (index > 0) {
313				*(szCur++) = _T(';');
314				dataSize--;
315			}
316			if (ppPaths[index]) {
317				Py_ssize_t len = _tcslen(ppPaths[index]);
318				_tcsncpy(szCur, ppPaths[index], len);
319				szCur += len;
320				assert(dataSize > (DWORD)len);
321				dataSize -= (DWORD)len;
322			}
323		}
324		if (skipcore)
325			*szCur = '\0';
326		else {
327			/* If we have no values, we dont need a ';' */
328			if (numKeys) {
329				*(szCur++) = _T(';');
330				dataSize--;
331			}
332			/* Now append the core path entries - 
333			   this will include the NULL 
334			*/
335			rc = RegQueryValueEx(newKey, NULL, 0, NULL, 
336			                     (LPBYTE)szCur, &dataSize);
337		}
338		/* And set the result - caller must free 
339		   If MBCS, it is fine as is.  If Unicode, allocate new
340		   buffer and convert.
341		*/
342#ifdef UNICODE
343		retval = (char *)malloc(reqdSize+1);
344		if (retval)
345			WideCharToMultiByte(CP_ACP, 0, 
346					dataBuf, -1, /* source */ 
347					retval, reqdSize+1, /* dest */
348					NULL, NULL);
349		free(dataBuf);
350#else
351		retval = dataBuf;
352#endif
353	}
354done:
355	/* Loop freeing my temp buffers */
356	if (ppPaths) {
357		for(index=0;index<numKeys;index++)
358			if (ppPaths[index]) free(ppPaths[index]);
359		free(ppPaths);
360	}
361	if (newKey)
362		RegCloseKey(newKey);
363	if (keyBuf)
364		free(keyBuf);
365	return retval;
366}
367#endif /* Py_ENABLE_SHARED */
368#endif /* MS_WINDOWS */
369
370static void
371get_progpath(void)
372{
373	extern char *Py_GetProgramName(void);
374	char *path = getenv("PATH");
375	char *prog = Py_GetProgramName();
376
377#ifdef MS_WINDOWS
378	extern HANDLE PyWin_DLLhModule;
379#ifdef UNICODE
380	WCHAR wprogpath[MAXPATHLEN+1];
381	/* Windows documents that GetModuleFileName() will "truncate",
382	   but makes no mention of the null terminator.  Play it safe.
383	   PLUS Windows itself defines MAX_PATH as the same, but anyway...
384	*/
385#ifdef Py_ENABLE_SHARED
386	wprogpath[MAXPATHLEN]=_T('\0');
387	if (PyWin_DLLhModule &&
388	    GetModuleFileName(PyWin_DLLhModule, wprogpath, MAXPATHLEN)) {
389		WideCharToMultiByte(CP_ACP, 0, 
390		                    wprogpath, -1, 
391		                    dllpath, MAXPATHLEN+1, 
392		                    NULL, NULL);
393	}
394#else
395	dllpath[0] = 0;
396#endif
397	wprogpath[MAXPATHLEN]=_T('\0');
398	if (GetModuleFileName(NULL, wprogpath, MAXPATHLEN)) {
399		WideCharToMultiByte(CP_ACP, 0, 
400		                    wprogpath, -1, 
401		                    progpath, MAXPATHLEN+1, 
402		                    NULL, NULL);
403		return;
404	}
405#else
406	/* static init of progpath ensures final char remains \0 */
407#ifdef Py_ENABLE_SHARED
408	if (PyWin_DLLhModule)
409		if (!GetModuleFileName(PyWin_DLLhModule, dllpath, MAXPATHLEN))
410			dllpath[0] = 0;
411#else
412	dllpath[0] = 0;
413#endif
414	if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
415		return;
416#endif
417#endif
418	if (prog == NULL || *prog == '\0')
419		prog = "python";
420
421	/* If there is no slash in the argv0 path, then we have to
422	 * assume python is on the user's $PATH, since there's no
423	 * other way to find a directory to start the search from.  If
424	 * $PATH isn't exported, you lose.
425	 */
426#ifdef ALTSEP
427	if (strchr(prog, SEP) || strchr(prog, ALTSEP))
428#else
429	if (strchr(prog, SEP))
430#endif
431		strncpy(progpath, prog, MAXPATHLEN);
432	else if (path) {
433		while (1) {
434			char *delim = strchr(path, DELIM);
435
436			if (delim) {
437				size_t len = delim - path;
438				/* ensure we can't overwrite buffer */
439				len = min(MAXPATHLEN,len);
440				strncpy(progpath, path, len);
441				*(progpath + len) = '\0';
442			}
443			else
444				strncpy(progpath, path, MAXPATHLEN);
445
446			/* join() is safe for MAXPATHLEN+1 size buffer */
447			join(progpath, prog);
448			if (exists(progpath))
449				break;
450
451			if (!delim) {
452				progpath[0] = '\0';
453				break;
454			}
455			path = delim + 1;
456		}
457	}
458	else
459		progpath[0] = '\0';
460}
461
462static void
463calculate_path(void)
464{
465	char argv0_path[MAXPATHLEN+1];
466	char *buf;
467	size_t bufsz;
468	char *pythonhome = Py_GetPythonHome();
469	char *envpath = Py_GETENV("PYTHONPATH");
470
471#ifdef MS_WINDOWS
472	int skiphome, skipdefault;
473	char *machinepath = NULL;
474	char *userpath = NULL;
475	char zip_path[MAXPATHLEN+1];
476	size_t len;
477#endif
478
479	get_progpath();
480	/* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */
481	strcpy(argv0_path, progpath);
482	reduce(argv0_path);
483	if (pythonhome == NULL || *pythonhome == '\0') {
484		if (search_for_prefix(argv0_path, LANDMARK))
485			pythonhome = prefix;
486		else
487			pythonhome = NULL;
488	}
489	else
490		strncpy(prefix, pythonhome, MAXPATHLEN);
491
492	if (envpath && *envpath == '\0')
493		envpath = NULL;
494
495
496#ifdef MS_WINDOWS
497	/* Calculate zip archive path */
498	if (dllpath[0])		/* use name of python DLL */
499		strncpy(zip_path, dllpath, MAXPATHLEN);
500	else			/* use name of executable program */
501		strncpy(zip_path, progpath, MAXPATHLEN);
502	zip_path[MAXPATHLEN] = '\0';
503	len = strlen(zip_path);
504	if (len > 4) {
505		zip_path[len-3] = 'z';	/* change ending to "zip" */
506		zip_path[len-2] = 'i';
507		zip_path[len-1] = 'p';
508	}
509	else {
510		zip_path[0] = 0;
511	}
512 
513	skiphome = pythonhome==NULL ? 0 : 1;
514#ifdef Py_ENABLE_SHARED
515	machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome);
516	userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome);
517#endif
518	/* We only use the default relative PYTHONPATH if we havent
519	   anything better to use! */
520	skipdefault = envpath!=NULL || pythonhome!=NULL || \
521		      machinepath!=NULL || userpath!=NULL;
522#endif
523
524	/* We need to construct a path from the following parts.
525	   (1) the PYTHONPATH environment variable, if set;
526	   (2) for Win32, the zip archive file path;
527	   (3) for Win32, the machinepath and userpath, if set;
528	   (4) the PYTHONPATH config macro, with the leading "."
529	       of each component replaced with pythonhome, if set;
530	   (5) the directory containing the executable (argv0_path).
531	   The length calculation calculates #4 first.
532	   Extra rules:
533	   - If PYTHONHOME is set (in any way) item (3) is ignored.
534	   - If registry values are used, (4) and (5) are ignored.
535	*/
536
537	/* Calculate size of return buffer */
538	if (pythonhome != NULL) {
539		char *p;
540		bufsz = 1;	
541		for (p = PYTHONPATH; *p; p++) {
542			if (*p == DELIM)
543				bufsz++; /* number of DELIM plus one */
544		}
545		bufsz *= strlen(pythonhome);
546	}
547	else
548		bufsz = 0;
549	bufsz += strlen(PYTHONPATH) + 1;
550	bufsz += strlen(argv0_path) + 1;
551#ifdef MS_WINDOWS
552	if (userpath)
553		bufsz += strlen(userpath) + 1;
554	if (machinepath)
555		bufsz += strlen(machinepath) + 1;
556	bufsz += strlen(zip_path) + 1;
557#endif
558	if (envpath != NULL)
559		bufsz += strlen(envpath) + 1;
560
561	module_search_path = buf = malloc(bufsz);
562	if (buf == NULL) {
563		/* We can't exit, so print a warning and limp along */
564		fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
565		if (envpath) {
566			fprintf(stderr, "Using environment $PYTHONPATH.\n");
567			module_search_path = envpath;
568		}
569		else {
570			fprintf(stderr, "Using default static path.\n");
571			module_search_path = PYTHONPATH;
572		}
573#ifdef MS_WINDOWS
574		if (machinepath)
575			free(machinepath);
576		if (userpath)
577			free(userpath);
578#endif /* MS_WINDOWS */
579		return;
580	}
581
582	if (envpath) {
583		strcpy(buf, envpath);
584		buf = strchr(buf, '\0');
585		*buf++ = DELIM;
586	}
587#ifdef MS_WINDOWS
588	if (zip_path[0]) {
589		strcpy(buf, zip_path);
590		buf = strchr(buf, '\0');
591		*buf++ = DELIM;
592	}
593	if (userpath) {
594		strcpy(buf, userpath);
595		buf = strchr(buf, '\0');
596		*buf++ = DELIM;
597		free(userpath);
598	}
599	if (machinepath) {
600		strcpy(buf, machinepath);
601		buf = strchr(buf, '\0');
602		*buf++ = DELIM;
603		free(machinepath);
604	}
605	if (pythonhome == NULL) {
606		if (!skipdefault) {
607			strcpy(buf, PYTHONPATH);
608			buf = strchr(buf, '\0');
609		}
610	}
611#else
612	if (pythonhome == NULL) {
613		strcpy(buf, PYTHONPATH);
614		buf = strchr(buf, '\0');
615	}
616#endif /* MS_WINDOWS */
617	else {
618		char *p = PYTHONPATH;
619		char *q;
620		size_t n;
621		for (;;) {
622			q = strchr(p, DELIM);
623			if (q == NULL)
624				n = strlen(p);
625			else
626				n = q-p;
627			if (p[0] == '.' && is_sep(p[1])) {
628				strcpy(buf, pythonhome);
629				buf = strchr(buf, '\0');
630				p++;
631				n--;
632			}
633			strncpy(buf, p, n);
634			buf += n;
635			if (q == NULL)
636				break;
637			*buf++ = DELIM;
638			p = q+1;
639		}
640	}
641	if (argv0_path) {
642		*buf++ = DELIM;
643		strcpy(buf, argv0_path);
644		buf = strchr(buf, '\0');
645	}
646	*buf = '\0';
647	/* Now to pull one last hack/trick.  If sys.prefix is
648	   empty, then try and find it somewhere on the paths
649	   we calculated.  We scan backwards, as our general policy
650	   is that Python core directories are at the *end* of
651	   sys.path.  We assume that our "lib" directory is
652	   on the path, and that our 'prefix' directory is
653	   the parent of that.
654	*/
655	if (*prefix=='\0') {
656		char lookBuf[MAXPATHLEN+1];
657		char *look = buf - 1; /* 'buf' is at the end of the buffer */
658		while (1) {
659			Py_ssize_t nchars;
660			char *lookEnd = look;
661			/* 'look' will end up one character before the
662			   start of the path in question - even if this
663			   is one character before the start of the buffer
664			*/
665			while (look >= module_search_path && *look != DELIM)
666				look--;
667			nchars = lookEnd-look;
668			strncpy(lookBuf, look+1, nchars);
669			lookBuf[nchars] = '\0';
670			/* Up one level to the parent */
671			reduce(lookBuf);
672			if (search_for_prefix(lookBuf, LANDMARK)) {
673				break;
674			}
675			/* If we are out of paths to search - give up */
676			if (look < module_search_path)
677				break;
678			look--;
679		}
680	}
681}
682
683
684/* External interface */
685
686char *
687Py_GetPath(void)
688{
689	if (!module_search_path)
690		calculate_path();
691	return module_search_path;
692}
693
694char *
695Py_GetPrefix(void)
696{
697	if (!module_search_path)
698		calculate_path();
699	return prefix;
700}
701
702char *
703Py_GetExecPrefix(void)
704{
705	return Py_GetPrefix();
706}
707
708char *
709Py_GetProgramFullPath(void)
710{
711	if (!module_search_path)
712		calculate_path();
713	return progpath;
714}