1 /* Return the initial module search path. */
2 
3 #include "Python.h"
4 #include "osdefs.h"
5 
6 #include <sys/types.h>
7 #include <string.h>
8 
9 #ifdef __APPLE__
10 #include <mach-o/dyld.h>
11 #endif
12 
13 /* Search in some common locations for the associated Python libraries.
14  *
15  * Two directories must be found, the platform independent directory
16  * (prefix), containing the common .py and .pyc files, and the platform
17  * dependent directory (exec_prefix), containing the shared library
18  * modules.  Note that prefix and exec_prefix can be the same directory,
19  * but for some installations, they are different.
20  *
21  * Py_GetPath() carries out separate searches for prefix and exec_prefix.
22  * Each search tries a number of different locations until a ``landmark''
23  * file or directory is found.  If no prefix or exec_prefix is found, a
24  * warning message is issued and the preprocessor defined PREFIX and
25  * EXEC_PREFIX are used (even though they will not work); python carries on
26  * as best as is possible, but most imports will fail.
27  *
28  * Before any searches are done, the location of the executable is
29  * determined.  If argv[0] has one or more slashes in it, it is used
30  * unchanged.  Otherwise, it must have been invoked from the shell's path,
31  * so we search $PATH for the named executable and use that.  If the
32  * executable was not found on $PATH (or there was no $PATH environment
33  * variable), the original argv[0] string is used.
34  *
35  * Next, the executable location is examined to see if it is a symbolic
36  * link.  If so, the link is chased (correctly interpreting a relative
37  * pathname if one is found) and the directory of the link target is used.
38  *
39  * Finally, argv0_path is set to the directory containing the executable
40  * (i.e. the last component is stripped).
41  *
42  * With argv0_path in hand, we perform a number of steps.  The same steps
43  * are performed for prefix and for exec_prefix, but with a different
44  * landmark.
45  *
46  * Step 1. Are we running python out of the build directory?  This is
47  * checked by looking for a different kind of landmark relative to
48  * argv0_path.  For prefix, the landmark's path is derived from the VPATH
49  * preprocessor variable (taking into account that its value is almost, but
50  * not quite, what we need).  For exec_prefix, the landmark is
51  * Modules/Setup.  If the landmark is found, we're done.
52  *
53  * For the remaining steps, the prefix landmark will always be
54  * lib/python$VERSION/os.py and the exec_prefix will always be
55  * lib/python$VERSION/lib-dynload, where $VERSION is Python's version
56  * number as supplied by the Makefile.  Note that this means that no more
57  * build directory checking is performed; if the first step did not find
58  * the landmarks, the assumption is that python is running from an
59  * installed setup.
60  *
61  * Step 2. See if the $PYTHONHOME environment variable points to the
62  * installed location of the Python libraries.  If $PYTHONHOME is set, then
63  * it points to prefix and exec_prefix.  $PYTHONHOME can be a single
64  * directory, which is used for both, or the prefix and exec_prefix
65  * directories separated by a colon.
66  *
67  * Step 3. Try to find prefix and exec_prefix relative to argv0_path,
68  * backtracking up the path until it is exhausted.  This is the most common
69  * step to succeed.  Note that if prefix and exec_prefix are different,
70  * exec_prefix is more likely to be found; however if exec_prefix is a
71  * subdirectory of prefix, both will be found.
72  *
73  * Step 4. Search the directories pointed to by the preprocessor variables
74  * PREFIX and EXEC_PREFIX.  These are supplied by the Makefile but can be
75  * passed in as options to the configure script.
76  *
77  * That's it!
78  *
79  * Well, almost.  Once we have determined prefix and exec_prefix, the
80  * preprocessor variable PYTHONPATH is used to construct a path.  Each
81  * relative path on PYTHONPATH is prefixed with prefix.  Then the directory
82  * containing the shared library modules is appended.  The environment
83  * variable $PYTHONPATH is inserted in front of it all.  Finally, the
84  * prefix and exec_prefix globals are tweaked so they reflect the values
85  * expected by other code, by stripping the "lib/python$VERSION/..." stuff
86  * off.  If either points to the build directory, the globals are reset to
87  * the corresponding preprocessor variables (so sys.prefix will reflect the
88  * installation location, even though sys.path points into the build
89  * directory).  This seems to make more sense given that currently the only
90  * known use of sys.prefix and sys.exec_prefix is for the ILU installation
91  * process to find the installed Python tree.
92  */
93 
94 #ifdef __cplusplus
95  extern "C" {
96 #endif
97 
98 
99 #if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH)
100 #error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined"
101 #endif
102 
103 #ifndef LANDMARK
104 #define LANDMARK "os.py"
105 #endif
106 
107 static char prefix[MAXPATHLEN+1];
108 static char exec_prefix[MAXPATHLEN+1];
109 static char progpath[MAXPATHLEN+1];
110 static char *module_search_path = NULL;
111 #ifdef ANDROID_LIB_PYTHON_PATH
112 static char lib_python[] = ANDROID_LIB_PYTHON_PATH;
113 #else
114 static char lib_python[] = "lib/python" VERSION;
115 #endif
116 
117 static void
reduce(char * dir)118 reduce(char *dir)
119 {
120     size_t i = strlen(dir);
121     while (i > 0 && dir[i] != SEP)
122         --i;
123     dir[i] = '\0';
124 }
125 
126 
127 static int
isfile(char * filename)128 isfile(char *filename)          /* Is file, not directory */
129 {
130     struct stat buf;
131     if (stat(filename, &buf) != 0)
132         return 0;
133     if (!S_ISREG(buf.st_mode))
134         return 0;
135     return 1;
136 }
137 
138 
139 static int
ismodule(char * filename)140 ismodule(char *filename)        /* Is module -- check for .pyc/.pyo too */
141 {
142     if (isfile(filename))
143         return 1;
144 
145     /* Check for the compiled version of prefix. */
146     if (strlen(filename) < MAXPATHLEN) {
147         strcat(filename, Py_OptimizeFlag ? "o" : "c");
148         if (isfile(filename))
149             return 1;
150     }
151     return 0;
152 }
153 
154 
155 static int
isxfile(char * filename)156 isxfile(char *filename)         /* Is executable file */
157 {
158     struct stat buf;
159     if (stat(filename, &buf) != 0)
160         return 0;
161     if (!S_ISREG(buf.st_mode))
162         return 0;
163     if ((buf.st_mode & 0111) == 0)
164         return 0;
165     return 1;
166 }
167 
168 
169 static int
isdir(char * filename)170 isdir(char *filename)                   /* Is directory */
171 {
172     struct stat buf;
173     if (stat(filename, &buf) != 0)
174         return 0;
175     if (!S_ISDIR(buf.st_mode))
176         return 0;
177     return 1;
178 }
179 
180 
181 /* Add a path component, by appending stuff to buffer.
182    buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
183    NUL-terminated string with no more than MAXPATHLEN characters (not counting
184    the trailing NUL).  It's a fatal error if it contains a string longer than
185    that (callers must be careful!).  If these requirements are met, it's
186    guaranteed that buffer will still be a NUL-terminated string with no more
187    than MAXPATHLEN characters at exit.  If stuff is too long, only as much of
188    stuff as fits will be appended.
189 */
190 static void
joinpath(char * buffer,char * stuff)191 joinpath(char *buffer, char *stuff)
192 {
193     size_t n, k;
194     if (stuff[0] == SEP)
195         n = 0;
196     else {
197         n = strlen(buffer);
198         if (n > 0 && buffer[n-1] != SEP && n < MAXPATHLEN)
199             buffer[n++] = SEP;
200     }
201     if (n > MAXPATHLEN)
202         Py_FatalError("buffer overflow in getpath.c's joinpath()");
203     k = strlen(stuff);
204     if (n + k > MAXPATHLEN)
205         k = MAXPATHLEN - n;
206     strncpy(buffer+n, stuff, k);
207     buffer[n+k] = '\0';
208 }
209 
210 /* copy_absolute requires that path be allocated at least
211    MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes. */
212 static void
copy_absolute(char * path,char * p)213 copy_absolute(char *path, char *p)
214 {
215     if (p[0] == SEP)
216         strcpy(path, p);
217     else {
218         if (!getcwd(path, MAXPATHLEN)) {
219             /* unable to get the current directory */
220             strcpy(path, p);
221             return;
222         }
223         if (p[0] == '.' && p[1] == SEP)
224             p += 2;
225         joinpath(path, p);
226     }
227 }
228 
229 /* absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes. */
230 static void
absolutize(char * path)231 absolutize(char *path)
232 {
233     char buffer[MAXPATHLEN + 1];
234 
235     if (path[0] == SEP)
236         return;
237     copy_absolute(buffer, path);
238     strcpy(path, buffer);
239 }
240 
241 /* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
242    bytes long.
243 */
244 static int
search_for_prefix(char * argv0_path,char * home)245 search_for_prefix(char *argv0_path, char *home)
246 {
247     size_t n;
248     char *vpath;
249 
250     /* If PYTHONHOME is set, we believe it unconditionally */
251     if (home) {
252         char *delim;
253         strncpy(prefix, home, MAXPATHLEN);
254         delim = strchr(prefix, DELIM);
255         if (delim)
256             *delim = '\0';
257         joinpath(prefix, lib_python);
258         joinpath(prefix, LANDMARK);
259         return 1;
260     }
261 
262     /* Check to see if argv[0] is in the build directory */
263     strcpy(prefix, argv0_path);
264     joinpath(prefix, "Modules/Setup");
265     if (isfile(prefix)) {
266         /* Check VPATH to see if argv0_path is in the build directory. */
267         vpath = VPATH;
268         strcpy(prefix, argv0_path);
269         joinpath(prefix, vpath);
270         joinpath(prefix, "Lib");
271         joinpath(prefix, LANDMARK);
272         if (ismodule(prefix))
273             return -1;
274     }
275 
276     /* Search from argv0_path, until root is found */
277     copy_absolute(prefix, argv0_path);
278     do {
279         n = strlen(prefix);
280         joinpath(prefix, lib_python);
281         joinpath(prefix, LANDMARK);
282         if (ismodule(prefix))
283             return 1;
284         prefix[n] = '\0';
285         reduce(prefix);
286     } while (prefix[0]);
287 
288     /* Look at configure's PREFIX */
289     strncpy(prefix, PREFIX, MAXPATHLEN);
290     joinpath(prefix, lib_python);
291     joinpath(prefix, LANDMARK);
292     if (ismodule(prefix))
293         return 1;
294 
295     /* Fail */
296     return 0;
297 }
298 
299 
300 /* search_for_exec_prefix requires that argv0_path be no more than
301    MAXPATHLEN bytes long.
302 */
303 static int
search_for_exec_prefix(char * argv0_path,char * home)304 search_for_exec_prefix(char *argv0_path, char *home)
305 {
306     size_t n;
307 
308     /* If PYTHONHOME is set, we believe it unconditionally */
309     if (home) {
310         char *delim;
311         delim = strchr(home, DELIM);
312         if (delim)
313             strncpy(exec_prefix, delim+1, MAXPATHLEN);
314         else
315             strncpy(exec_prefix, home, MAXPATHLEN);
316         joinpath(exec_prefix, lib_python);
317         joinpath(exec_prefix, "lib-dynload");
318         return 1;
319     }
320 
321     /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
322        is written by setup.py and contains the relative path to the location
323        of shared library modules. */
324     strcpy(exec_prefix, argv0_path);
325     joinpath(exec_prefix, "pybuilddir.txt");
326     if (isfile(exec_prefix)) {
327       FILE *f = fopen(exec_prefix, "r");
328       if (f == NULL)
329 	errno = 0;
330       else {
331 	char rel_builddir_path[MAXPATHLEN+1];
332 	size_t n;
333 	n = fread(rel_builddir_path, 1, MAXPATHLEN, f);
334 	rel_builddir_path[n] = '\0';
335 	fclose(f);
336 	strcpy(exec_prefix, argv0_path);
337 	joinpath(exec_prefix, rel_builddir_path);
338 	return -1;
339       }
340     }
341 
342     /* Search from argv0_path, until root is found */
343     copy_absolute(exec_prefix, argv0_path);
344     do {
345         n = strlen(exec_prefix);
346         joinpath(exec_prefix, lib_python);
347         joinpath(exec_prefix, "lib-dynload");
348         if (isdir(exec_prefix))
349             return 1;
350         exec_prefix[n] = '\0';
351         reduce(exec_prefix);
352     } while (exec_prefix[0]);
353 
354     /* Look at configure's EXEC_PREFIX */
355     strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
356     joinpath(exec_prefix, lib_python);
357     joinpath(exec_prefix, "lib-dynload");
358     if (isdir(exec_prefix))
359         return 1;
360 
361     /* Fail */
362     return 0;
363 }
364 
365 
366 static void
calculate_path(void)367 calculate_path(void)
368 {
369     extern char *Py_GetProgramName(void);
370 
371     static char delimiter[2] = {DELIM, '\0'};
372     static char separator[2] = {SEP, '\0'};
373     char *pythonpath = PYTHONPATH;
374     char *rtpypath = Py_GETENV("PYTHONPATH");
375     char *home = Py_GetPythonHome();
376     char *path = getenv("PATH");
377     char *prog = Py_GetProgramName();
378     char argv0_path[MAXPATHLEN+1];
379     char zip_path[MAXPATHLEN+1];
380     int pfound, efound; /* 1 if found; -1 if found build directory */
381     char *buf;
382     size_t bufsz;
383     size_t prefixsz;
384     char *defpath = pythonpath;
385 #ifdef WITH_NEXT_FRAMEWORK
386     NSModule pythonModule;
387 #endif
388 #ifdef __APPLE__
389 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
390     uint32_t nsexeclength = MAXPATHLEN;
391 #else
392     unsigned long nsexeclength = MAXPATHLEN;
393 #endif
394 #endif
395 
396         /* If there is no slash in the argv0 path, then we have to
397          * assume python is on the user's $PATH, since there's no
398          * other way to find a directory to start the search from.  If
399          * $PATH isn't exported, you lose.
400          */
401         if (strchr(prog, SEP))
402                 strncpy(progpath, prog, MAXPATHLEN);
403 #ifdef __APPLE__
404      /* On Mac OS X, if a script uses an interpreter of the form
405       * "#!/opt/python2.3/bin/python", the kernel only passes "python"
406       * as argv[0], which falls through to the $PATH search below.
407       * If /opt/python2.3/bin isn't in your path, or is near the end,
408       * this algorithm may incorrectly find /usr/bin/python. To work
409       * around this, we can use _NSGetExecutablePath to get a better
410       * hint of what the intended interpreter was, although this
411       * will fail if a relative path was used. but in that case,
412       * absolutize() should help us out below
413       */
414      else if(0 == _NSGetExecutablePath(progpath, &nsexeclength) && progpath[0] == SEP)
415        ;
416 #endif /* __APPLE__ */
417         else if (path) {
418                 while (1) {
419                         char *delim = strchr(path, DELIM);
420 
421                         if (delim) {
422                                 size_t len = delim - path;
423                                 if (len > MAXPATHLEN)
424                                         len = MAXPATHLEN;
425                                 strncpy(progpath, path, len);
426                                 *(progpath + len) = '\0';
427                         }
428                         else
429                                 strncpy(progpath, path, MAXPATHLEN);
430 
431                         joinpath(progpath, prog);
432                         if (isxfile(progpath))
433                                 break;
434 
435                         if (!delim) {
436                                 progpath[0] = '\0';
437                                 break;
438                         }
439                         path = delim + 1;
440                 }
441         }
442         else
443                 progpath[0] = '\0';
444         if (progpath[0] != SEP && progpath[0] != '\0')
445                 absolutize(progpath);
446         strncpy(argv0_path, progpath, MAXPATHLEN);
447         argv0_path[MAXPATHLEN] = '\0';
448 
449 #ifdef WITH_NEXT_FRAMEWORK
450         /* On Mac OS X we have a special case if we're running from a framework.
451         ** This is because the python home should be set relative to the library,
452         ** which is in the framework, not relative to the executable, which may
453         ** be outside of the framework. Except when we're in the build directory...
454         */
455     pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
456     /* Use dylib functions to find out where the framework was loaded from */
457     buf = (char *)NSLibraryNameForModule(pythonModule);
458     if (buf != NULL) {
459         /* We're in a framework. */
460         /* See if we might be in the build directory. The framework in the
461         ** build directory is incomplete, it only has the .dylib and a few
462         ** needed symlinks, it doesn't have the Lib directories and such.
463         ** If we're running with the framework from the build directory we must
464         ** be running the interpreter in the build directory, so we use the
465         ** build-directory-specific logic to find Lib and such.
466         */
467         strncpy(argv0_path, buf, MAXPATHLEN);
468         reduce(argv0_path);
469         joinpath(argv0_path, lib_python);
470         joinpath(argv0_path, LANDMARK);
471         if (!ismodule(argv0_path)) {
472                 /* We are in the build directory so use the name of the
473                    executable - we know that the absolute path is passed */
474                 strncpy(argv0_path, progpath, MAXPATHLEN);
475         }
476         else {
477                 /* Use the location of the library as the progpath */
478                 strncpy(argv0_path, buf, MAXPATHLEN);
479         }
480     }
481 #endif
482 
483 #if HAVE_READLINK
484     {
485         char tmpbuffer[MAXPATHLEN+1];
486         int linklen = readlink(progpath, tmpbuffer, MAXPATHLEN);
487         while (linklen != -1) {
488             /* It's not null terminated! */
489             tmpbuffer[linklen] = '\0';
490             if (tmpbuffer[0] == SEP)
491                 /* tmpbuffer should never be longer than MAXPATHLEN,
492                    but extra check does not hurt */
493                 strncpy(argv0_path, tmpbuffer, MAXPATHLEN);
494             else {
495                 /* Interpret relative to progpath */
496                 reduce(argv0_path);
497                 joinpath(argv0_path, tmpbuffer);
498             }
499             linklen = readlink(argv0_path, tmpbuffer, MAXPATHLEN);
500         }
501     }
502 #endif /* HAVE_READLINK */
503 
504     reduce(argv0_path);
505     /* At this point, argv0_path is guaranteed to be less than
506        MAXPATHLEN bytes long.
507     */
508 
509     if (!(pfound = search_for_prefix(argv0_path, home))) {
510         if (!Py_FrozenFlag)
511             fprintf(stderr,
512                 "Could not find platform independent libraries <prefix>\n");
513         strncpy(prefix, PREFIX, MAXPATHLEN);
514         joinpath(prefix, lib_python);
515     }
516     else
517         reduce(prefix);
518 
519     strncpy(zip_path, prefix, MAXPATHLEN);
520     zip_path[MAXPATHLEN] = '\0';
521     if (pfound > 0) { /* Use the reduced prefix returned by Py_GetPrefix() */
522         reduce(zip_path);
523         reduce(zip_path);
524     }
525     else
526         strncpy(zip_path, PREFIX, MAXPATHLEN);
527     joinpath(zip_path, "lib/python00.zip");
528     bufsz = strlen(zip_path);   /* Replace "00" with version */
529     zip_path[bufsz - 6] = VERSION[0];
530     zip_path[bufsz - 5] = VERSION[2];
531 
532     if (!(efound = search_for_exec_prefix(argv0_path, home))) {
533         if (!Py_FrozenFlag)
534             fprintf(stderr,
535                 "Could not find platform dependent libraries <exec_prefix>\n");
536         strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
537         joinpath(exec_prefix, "lib/lib-dynload");
538     }
539     /* If we found EXEC_PREFIX do *not* reduce it!  (Yet.) */
540 
541     if ((!pfound || !efound) && !Py_FrozenFlag)
542         fprintf(stderr,
543                 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
544 
545     /* Calculate size of return buffer.
546      */
547     bufsz = 0;
548 
549     if (rtpypath)
550         bufsz += strlen(rtpypath) + 1;
551 
552     prefixsz = strlen(prefix) + 1;
553 
554     while (1) {
555         char *delim = strchr(defpath, DELIM);
556 
557         if (defpath[0] != SEP)
558             /* Paths are relative to prefix */
559             bufsz += prefixsz;
560 
561         if (delim)
562             bufsz += delim - defpath + 1;
563         else {
564             bufsz += strlen(defpath) + 1;
565             break;
566         }
567         defpath = delim + 1;
568     }
569 
570 #ifndef ANDROID_SKIP_ZIP_PATH
571     bufsz += strlen(zip_path) + 1;
572 #endif
573 #ifndef ANDROID_SKIP_EXEC_PREFIX_PATH
574     bufsz += strlen(exec_prefix) + 1;
575 #endif
576 
577     /* This is the only malloc call in this file */
578     buf = (char *)PyMem_Malloc(bufsz);
579 
580     if (buf == NULL) {
581         /* We can't exit, so print a warning and limp along */
582         fprintf(stderr, "Not enough memory for dynamic PYTHONPATH.\n");
583         fprintf(stderr, "Using default static PYTHONPATH.\n");
584         module_search_path = PYTHONPATH;
585     }
586     else {
587         /* Run-time value of $PYTHONPATH goes first */
588         if (rtpypath) {
589             strcpy(buf, rtpypath);
590             strcat(buf, delimiter);
591         }
592         else
593             buf[0] = '\0';
594 
595         /* Next is the default zip path */
596 #ifndef ANDROID_SKIP_ZIP_PATH
597         strcat(buf, zip_path);
598         strcat(buf, delimiter);
599 #endif
600 
601         /* Next goes merge of compile-time $PYTHONPATH with
602          * dynamically located prefix.
603          */
604         defpath = pythonpath;
605         while (1) {
606             char *delim = strchr(defpath, DELIM);
607 
608             if (defpath[0] != SEP) {
609                 strcat(buf, prefix);
610                 if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP &&
611                     defpath[0] != (delim ? DELIM : L'\0')) {  /* not empty */
612                     strcat(buf, separator);
613                 }
614             }
615 
616             if (delim) {
617                 size_t len = delim - defpath + 1;
618                 size_t end = strlen(buf) + len;
619                 strncat(buf, defpath, len);
620                 *(buf + end) = '\0';
621             }
622             else {
623                 strcat(buf, defpath);
624                 break;
625             }
626             defpath = delim + 1;
627         }
628 #ifndef ANDROID_SKIP_EXEC_PREFIX_PATH
629         strcat(buf, delimiter);
630 
631         /* Finally, on goes the directory for dynamic-load modules */
632         strcat(buf, exec_prefix);
633 #endif
634 
635         /* And publish the results */
636         module_search_path = buf;
637     }
638 
639     /* Reduce prefix and exec_prefix to their essence,
640      * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
641      * If we're loading relative to the build directory,
642      * return the compiled-in defaults instead.
643      */
644     if (pfound > 0) {
645         reduce(prefix);
646         reduce(prefix);
647         /* The prefix is the root directory, but reduce() chopped
648          * off the "/". */
649         if (!prefix[0])
650                 strcpy(prefix, separator);
651     }
652     else
653         strncpy(prefix, PREFIX, MAXPATHLEN);
654 
655     if (efound > 0) {
656         reduce(exec_prefix);
657         reduce(exec_prefix);
658         reduce(exec_prefix);
659         if (!exec_prefix[0])
660                 strcpy(exec_prefix, separator);
661     }
662     else
663         strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
664 }
665 
666 
667 /* External interface */
668 
669 char *
Py_GetPath(void)670 Py_GetPath(void)
671 {
672     if (!module_search_path)
673         calculate_path();
674     return module_search_path;
675 }
676 
677 char *
Py_GetPrefix(void)678 Py_GetPrefix(void)
679 {
680     if (!module_search_path)
681         calculate_path();
682     return prefix;
683 }
684 
685 char *
Py_GetExecPrefix(void)686 Py_GetExecPrefix(void)
687 {
688     if (!module_search_path)
689         calculate_path();
690     return exec_prefix;
691 }
692 
693 char *
Py_GetProgramFullPath(void)694 Py_GetProgramFullPath(void)
695 {
696     if (!module_search_path)
697         calculate_path();
698     return progpath;
699 }
700 
701 
702 #ifdef __cplusplus
703 }
704 #endif
705 
706