]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Efi/getpath.c
StdLib: Improve robustness of stat() and make basename() a public function.
[mirror_edk2.git] / AppPkg / Applications / Python / Efi / getpath.c
1 /** @file
2 Return the initial module search path.
3
4 Search in specified locations for the associated Python libraries.
5
6 Py_GetPath returns module_search_path.
7 Py_GetPrefix returns PREFIX
8 Py_GetExec_Prefix returns PREFIX
9 Py_GetProgramFullPath returns the full path to the python executable.
10
11 These are built dynamically so that the proper volume name can be prefixed
12 to the paths.
13
14 For the EDK II, UEFI, implementation of Python, PREFIX and EXEC_PREFIX
15 are set as follows:
16 PREFIX = /Efi/StdLib
17 EXEC_PREFIX = PREFIX
18
19 The following final paths are assumed:
20 /Efi/Tools/Python.efi The Python executable.
21 /Efi/StdLib/lib/python.VERSION The platform independent Python modules.
22 /Efi/StdLib/lib/python.VERSION/dynalib Dynamically loadable Python extension modules.
23
24 Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
25 This program and the accompanying materials are licensed and made available under
26 the terms and conditions of the BSD License that accompanies this distribution.
27 The full text of the license may be found at
28 http://opensource.org/licenses/bsd-license.
29
30 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
31 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
32 **/
33 #include <Python.h>
34 #include <osdefs.h>
35
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39
40 /* VERSION must be at least two characters long. */
41 #ifndef VERSION
42 #define VERSION "27"
43 #endif
44
45 #ifndef VPATH
46 #define VPATH "."
47 #endif
48
49 /* Search path entry delimiter */
50 #ifdef DELIM
51 #define sDELIM ";"
52 #endif
53
54 #ifndef PREFIX
55 #define PREFIX "/Efi/StdLib"
56 #endif
57
58 #ifndef EXEC_PREFIX
59 #define EXEC_PREFIX PREFIX
60 #endif
61
62 #ifndef LIBPYTHON
63 #define LIBPYTHON "lib/python." VERSION
64 #endif
65
66 #ifndef PYTHONPATH
67 //#define PYTHONPATH PREFIX LIBPYTHON sDELIM \
68 // EXEC_PREFIX LIBPYTHON "/lib-dynload"
69 #define PYTHONPATH LIBPYTHON // sDELIM
70 // LIBPYTHON "/lib-dynload"
71 #endif
72
73 #ifndef LANDMARK
74 #define LANDMARK "os.py"
75 #endif
76
77 static char prefix[MAXPATHLEN+1];
78 static char exec_prefix[MAXPATHLEN+1];
79 static char progpath[MAXPATHLEN+1];
80 static char *module_search_path = NULL;
81 static char lib_python[] = LIBPYTHON;
82 static char volume_name[32] = { 0 };
83
84 /** Determine if "ch" is a separator character.
85
86 @param[in] ch The character to test.
87
88 @retval TRUE ch is a separator character.
89 @retval FALSE ch is NOT a separator character.
90 **/
91 static int
92 is_sep(char ch)
93 {
94 #ifdef ALTSEP
95 return ch == SEP || ch == ALTSEP;
96 #else
97 return ch == SEP;
98 #endif
99 }
100
101 /** Reduce a path by its last element.
102
103 The last element (everything to the right of the last separator character)
104 in the path, dir, is removed from the path. Parameter dir is modified in place.
105
106 @param[in,out] dir Pointer to the path to modify.
107 **/
108 static void
109 reduce(char *dir)
110 {
111 size_t i = strlen(dir);
112 while (i > 0 && !is_sep(dir[i]))
113 --i;
114 dir[i] = '\0';
115 }
116
117 /** Does filename point to a file and not directory?
118
119 @param[in] filename The fully qualified path to the object to test.
120
121 @retval 0 Filename was not found, or is a directory.
122 @retval 1 Filename refers to a regular file.
123 **/
124 static int
125 isfile(char *filename)
126 {
127 struct stat buf;
128 if (stat(filename, &buf) != 0) {
129 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] Not Found: file = \"%s\"\n", __func__, __LINE__, filename);
130 return 0;
131 }
132 //if (!S_ISREG(buf.st_mode))
133 if (S_ISDIR(buf.st_mode)) {
134 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] Is DIR: file = \"%s\"\n", __func__, __LINE__, filename);
135 return 0;
136 }
137 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] SUCCESS: file = \"%s\"\n", __func__, __LINE__, filename);
138 return 1;
139 }
140
141 /** Determine if filename refers to a Python module.
142
143 A Python module is indicated if the file exists, or if the file with
144 'o' or 'c' appended exists.
145
146 @param[in] filename The fully qualified path to the object to test.
147
148 @retval 0
149 **/
150 static int
151 ismodule(char *filename)
152 {
153 if (isfile(filename)) {
154 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
155 return 1;
156 }
157
158 /* Check for the compiled version of prefix. */
159 if (strlen(filename) < MAXPATHLEN) {
160 strcat(filename, Py_OptimizeFlag ? "o" : "c");
161 if (isfile(filename)) {
162 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
163 return 1;
164 }
165 }
166 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] FAIL: file = \"%s\"\n", __func__, __LINE__, filename);
167 return 0;
168 }
169
170 /** Does filename point to a directory?
171
172 @param[in] filename The fully qualified path to the object to test.
173
174 @retval 0 Filename was not found, or is not a regular file.
175 @retval 1 Filename refers to a directory.
176 **/
177 static int
178 isdir(char *filename)
179 {
180 struct stat buf;
181
182 if (stat(filename, &buf) != 0)
183 return 0;
184
185 if (!S_ISDIR(buf.st_mode))
186 return 0;
187
188 return 1;
189 }
190
191 /** Determine if a path is absolute, or not.
192 An absolute path consists of a volume name, "VOL:", followed by a rooted path,
193 "/path/elements". If both of these components are present, the path is absolute.
194
195 Let P be a pointer to the path to test.
196 Let A be a pointer to the first ':' in P.
197 Let B be a pointer to the first '/' or '\\' in P.
198
199 If A and B are not NULL
200 If (A-P+1) == (B-P) then the path is absolute.
201 Otherwise, the path is NOT absolute.
202
203 @param[in] path The path to test.
204
205 @retval -1 Path is absolute but lacking volume name.
206 @retval 0 Path is NOT absolute.
207 @retval 1 Path is absolute.
208 */
209 static int
210 is_absolute(char *path)
211 {
212 char *A;
213 char *B;
214
215 A = strchr(path, ':');
216 B = strpbrk(path, "/\\");
217
218 if(B != NULL) {
219 if(A == NULL) {
220 if(B == path) {
221 return -1;
222 }
223 }
224 else {
225 if(((A - path) + 1) == (B - path)) {
226 return 1;
227 }
228 }
229 }
230 return 0;
231 }
232
233
234 /** Add a path component, by appending stuff to buffer.
235 buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
236 NUL-terminated string with no more than MAXPATHLEN characters (not counting
237 the trailing NUL). It's a fatal error if it contains a string longer than
238 that (callers must be careful!). If these requirements are met, it's
239 guaranteed that buffer will still be a NUL-terminated string with no more
240 than MAXPATHLEN characters at exit. If stuff is too long, only as much of
241 stuff as fits will be appended.
242
243 @param[in,out] buffer The path to be extended.
244 @param[in] stuff The stuff to join onto the path.
245 */
246 static void
247 joinpath(char *buffer, char *stuff)
248 {
249 size_t n, k;
250
251 k = 0;
252 if (is_absolute(stuff) == 1) {
253 n = 0;
254 }
255 else {
256 n = strlen(buffer);
257 if(n == 0) {
258 strncpy(buffer, volume_name, MAXPATHLEN);
259 n = strlen(buffer);
260 }
261 /* We must not use an else clause here because we want to test n again.
262 volume_name may have been empty.
263 */
264 if (n > 0 && n < MAXPATHLEN) {
265 if(!is_sep(buffer[n-1])) {
266 buffer[n++] = SEP;
267 }
268 if(is_sep(stuff[0])) ++stuff;
269 }
270 }
271 if (n > MAXPATHLEN)
272 Py_FatalError("buffer overflow in getpath.c's joinpath()");
273 k = strlen(stuff);
274 if (n + k > MAXPATHLEN)
275 k = MAXPATHLEN - n;
276 strncpy(buffer+n, stuff, k);
277 buffer[n+k] = '\0';
278 }
279
280 /** Is filename an executable file?
281
282 An executable file:
283 1) exists
284 2) is a file, not a directory
285 3) has a name ending with ".efi"
286 4) Only has a single '.' in the name.
287
288 If basename(filename) does not contain a '.', append ".efi" to filename
289 If filename ends in ".efi", it is executable, else it isn't.
290
291 This routine is used to when searching for the file named by argv[0].
292 As such, there is no need to search for extensions other than ".efi".
293
294 @param[in] filename The name of the file to test. It may, or may not, have an extension.
295
296 @retval 0 filename already has a path other than ".efi", or it doesn't exist, or is a directory.
297 @retval 1 filename refers to an executable file.
298 **/
299 static int
300 isxfile(char *filename)
301 {
302 struct stat buf;
303 char *bn;
304 char *newbn;
305 int bnlen;
306
307 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] ENTER: file = \"%s\"\n", __func__, __LINE__, filename);
308 bn = basename(filename); // Separate off the file name component
309 reduce(filename); // and isolate the path component
310 bnlen = strlen(bn);
311 newbn = strrchr(bn, '.'); // Does basename contain a period?
312 if(newbn == NULL) { // Does NOT contain a period.
313 newbn = &bn[bnlen];
314 strncpyX(newbn, ".efi", MAXPATHLEN - bnlen); // append ".efi" to basename
315 bnlen += 4;
316 }
317 else if(strcmp(newbn, ".efi") != 0) {
318 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Bad extension\n", __func__, __LINE__);
319 return 0; // File can not be executable.
320 }
321 joinpath(filename, bn); // Stitch path and file name back together
322 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
323
324 if (stat(filename, &buf) != 0) { // Now, verify that file exists
325 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Does not exist\n", __func__, __LINE__);
326 return 0;
327 }
328 if(S_ISDIR(buf.st_mode)) { // And it is not a directory.
329 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Is a directory\n", __func__, __LINE__);
330 return 0;
331 }
332
333 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] EXIT: file = \"%s\"\n", __func__, __LINE__, filename);
334 return 1;
335 }
336
337 /** Copy p into path, ensuring that the result is an absolute path.
338
339 copy_absolute requires that path be allocated at least
340 MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes.
341
342 @param[out] path Destination to receive the absolute path.
343 @param[in] p Path to be tested and possibly converted.
344 **/
345 static void
346 copy_absolute(char *path, char *p)
347 {
348 if (is_absolute(p) == 1)
349 strcpy(path, p);
350 else {
351 if (!getcwd(path, MAXPATHLEN)) {
352 /* unable to get the current directory */
353 if(volume_name[0] != 0) {
354 strcpy(path, volume_name);
355 joinpath(path, p);
356 }
357 else
358 strcpy(path, p);
359 return;
360 }
361 if (p[0] == '.' && is_sep(p[1]))
362 p += 2;
363 joinpath(path, p);
364 }
365 }
366
367 /** Modify path so that the result is an absolute path.
368 absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes.
369
370 @param[in,out] path The path to be made absolute.
371 */
372 static void
373 absolutize(char *path)
374 {
375 char buffer[MAXPATHLEN + 1];
376
377 if (is_absolute(path) == 1)
378 return;
379 copy_absolute(buffer, path);
380 strcpy(path, buffer);
381 }
382
383 /** Extract the volume name from a path.
384
385 @param[out] Dest Pointer to location in which to store the extracted volume name.
386 @param[in] path Pointer to the path to extract the volume name from.
387 **/
388 static void
389 set_volume(char *Dest, char *path)
390 {
391 size_t VolLen;
392
393 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] ENTER: path = \"%s\"\n", __func__, __LINE__, path);
394 if(is_absolute(path)) {
395 VolLen = strcspn(path, "/\\:");
396 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: VolLen = %d\n", __func__, __LINE__, VolLen);
397 if((VolLen != 0) && (path[VolLen] == ':')) {
398 (void) strncpyX(Dest, path, VolLen + 1);
399 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: VolLen = %d, Dest = \"%s\" path = \"%s\"\n",
400 // __func__, __LINE__, VolLen, Dest, path);
401 }
402 }
403 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] EXIT: Dest = \"%s\"\n", __func__, __LINE__, Dest);
404 }
405
406
407 /** Determine paths.
408
409 Two directories must be found, the platform independent directory
410 (prefix), containing the common .py and .pyc files, and the platform
411 dependent directory (exec_prefix), containing the shared library
412 modules. Note that prefix and exec_prefix are the same directory
413 for UEFI installations.
414
415 Separate searches are carried out for prefix and exec_prefix.
416 Each search tries a number of different locations until a ``landmark''
417 file or directory is found. If no prefix or exec_prefix is found, a
418 warning message is issued and the preprocessor defined PREFIX and
419 EXEC_PREFIX are used (even though they may not work); python carries on
420 as best as is possible, but some imports may fail.
421
422 Before any searches are done, the location of the executable is
423 determined. If argv[0] has one or more slashes in it, it is used
424 unchanged. Otherwise, it must have been invoked from the shell's path,
425 so we search %PATH% for the named executable and use that. If the
426 executable was not found on %PATH% (or there was no %PATH% environment
427 variable), the original argv[0] string is used.
428
429 Finally, argv0_path is set to the directory containing the executable
430 (i.e. the last component is stripped).
431
432 With argv0_path in hand, we perform a number of steps. The same steps
433 are performed for prefix and for exec_prefix, but with a different
434 landmark.
435
436 The prefix landmark will always be lib/python.VERSION/os.py and the
437 exec_prefix will always be lib/python.VERSION/dynaload, where VERSION
438 is Python's version number as defined at the beginning of this file.
439
440 First. See if the %PYTHONHOME% environment variable points to the
441 installed location of the Python libraries. If %PYTHONHOME% is set, then
442 it points to prefix and exec_prefix. %PYTHONHOME% can be a single
443 directory, which is used for both, or the prefix and exec_prefix
444 directories separated by the DELIM character.
445
446 Next. Search the directories pointed to by the preprocessor variables
447 PREFIX and EXEC_PREFIX. These paths are prefixed with the volume name
448 extracted from argv0_path. The volume names correspond to the UEFI
449 shell "map" names.
450
451 That's it!
452
453 Well, almost. Once we have determined prefix and exec_prefix, the
454 preprocessor variable PYTHONPATH is used to construct a path. Each
455 relative path on PYTHONPATH is prefixed with prefix. Then the directory
456 containing the shared library modules is appended. The environment
457 variable $PYTHONPATH is inserted in front of it all. Finally, the
458 prefix and exec_prefix globals are tweaked so they reflect the values
459 expected by other code, by stripping the "lib/python$VERSION/..." stuff
460 off. This seems to make more sense given that currently the only
461 known use of sys.prefix and sys.exec_prefix is for the ILU installation
462 process to find the installed Python tree.
463
464 The final, fully resolved, paths should look something like:
465 fs0:/Efi/Tools/python.efi
466 fs0:/Efi/StdLib/lib/python27
467 fs0:/Efi/StdLib/lib/python27/dynaload
468
469 **/
470 static void
471 calculate_path(void)
472 {
473 extern char *Py_GetProgramName(void);
474
475 static char delimiter[2] = {DELIM, '\0'};
476 static char separator[2] = {SEP, '\0'};
477 char *pythonpath = PYTHONPATH;
478 char *rtpypath = Py_GETENV("PYTHONPATH");
479 //char *home = Py_GetPythonHome();
480 char *path = getenv("PATH");
481 char *prog = Py_GetProgramName();
482 char argv0_path[MAXPATHLEN+1];
483 char zip_path[MAXPATHLEN+1];
484 //int pfound, efound; /* 1 if found; -1 if found build directory */
485 char *buf;
486 size_t bufsz;
487 size_t prefixsz;
488 char *defpath;
489 //uint32_t nsexeclength = MAXPATHLEN;
490
491 //unixify(path);
492 //unixify(rtpypath);
493 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]:\nENTER prog=\"%s\"\n path=\"%s\"\n", __func__, __LINE__, prog, path);
494
495
496 /* ###########################################################################
497 Determine path to the Python.efi binary.
498 Produces progpath, argv0_path, and volume_name.
499 ########################################################################### */
500
501 /* If there is no slash in the argv0 path, then we have to
502 * assume python is on the user's $PATH, since there's no
503 * other way to find a directory to start the search from. If
504 * $PATH isn't exported, you lose.
505 */
506 if (strchr(prog, SEP))
507 strncpy(progpath, prog, MAXPATHLEN);
508 else if (path) {
509 while (1) {
510 char *delim = strchr(path, DELIM);
511
512 if (delim) {
513 size_t len = delim - path;
514 if (len > MAXPATHLEN)
515 len = MAXPATHLEN;
516 strncpy(progpath, path, len);
517 *(progpath + len) = '\0';
518 }
519 else
520 strncpy(progpath, path, MAXPATHLEN);
521
522 joinpath(progpath, prog);
523 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__, __LINE__, progpath);
524 if (isxfile(progpath))
525 break;
526
527 if (!delim) {
528 progpath[0] = '\0';
529 break;
530 }
531 path = delim + 1;
532 }
533 }
534 else
535 progpath[0] = '\0';
536 if ( (!is_absolute(progpath)) && (progpath[0] != '\0') )
537 absolutize(progpath);
538 strncpy(argv0_path, progpath, MAXPATHLEN);
539 argv0_path[MAXPATHLEN] = '\0';
540 set_volume(volume_name, argv0_path);
541
542 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: volume_name = \"%s\"\n", __func__, __LINE__, volume_name);
543 reduce(argv0_path);
544 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__, __LINE__, progpath);
545 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: argv0_path = \"%s\"\n", __func__, __LINE__, argv0_path);
546 /* At this point, argv0_path is guaranteed to be less than
547 MAXPATHLEN bytes long.
548 */
549
550 /* ###########################################################################
551 Build the FULL prefix string, including volume name.
552 This is the full path to the platform independent libraries.
553 ########################################################################### */
554
555 //if (!(pfound = search_for_prefix(argv0_path, home))) {
556 // if (!Py_FrozenFlag)
557 // fprintf(stderr,
558 // "Could not find platform independent libraries <prefix>\n");
559 strncpy(prefix, volume_name, MAXPATHLEN);
560 joinpath(prefix, PREFIX);
561 joinpath(prefix, lib_python);
562 //}
563 //else
564 // reduce(prefix);
565 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: V = \"%s\", Prefix = \"%s\"\n", __func__, __LINE__, volume_name, prefix);
566
567 /* ###########################################################################
568 Build the FULL path to the zipped-up Python library.
569 ########################################################################### */
570
571 strncpy(zip_path, prefix, MAXPATHLEN);
572 zip_path[MAXPATHLEN] = '\0';
573 //if (pfound > 0) { /* Use the reduced prefix returned by Py_GetPrefix() */
574 reduce(zip_path);
575 //reduce(zip_path);
576 //}
577 //else
578 // strncpy(zip_path, PREFIX, MAXPATHLEN);
579 joinpath(zip_path, "python00.zip");
580 bufsz = strlen(zip_path); /* Replace "00" with version */
581 zip_path[bufsz - 6] = VERSION[0];
582 zip_path[bufsz - 5] = VERSION[1];
583 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Zip_path = \"%s\"\n", __func__, __LINE__, zip_path);
584
585 /* ###########################################################################
586 Build the FULL path to dynamically loadable libraries.
587 ########################################################################### */
588
589 //if (!(efound = search_for_exec_prefix(argv0_path, home))) {
590 // if (!Py_FrozenFlag)
591 // fprintf(stderr,
592 // "Could not find platform dependent libraries <exec_prefix>\n");
593 strncpy(exec_prefix, volume_name, MAXPATHLEN);
594 joinpath(exec_prefix, EXEC_PREFIX);
595 joinpath(exec_prefix, lib_python);
596 joinpath(exec_prefix, "dynaload");
597 //}
598 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
599 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Exec_prefix = \"%s\"\n", __func__, __LINE__, exec_prefix);
600
601 //if ((!pfound || !efound) && !Py_FrozenFlag)
602 // fprintf(stderr,
603 // "Consider setting $PYTHONHOME to <prefix>[%c<exec_prefix>]\n", DELIM);
604
605 /* ###########################################################################
606 Build the module search path.
607 ########################################################################### */
608
609 /* Reduce prefix and exec_prefix to their essence,
610 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
611 * If we're loading relative to the build directory,
612 * return the compiled-in defaults instead.
613 */
614 //if (pfound > 0) {
615 reduce(prefix);
616 reduce(prefix);
617 /* The prefix is the root directory, but reduce() chopped
618 * off the "/". */
619 if (!prefix[0]) {
620 strcpy(prefix, volume_name);
621 }
622 bufsz = strlen(prefix);
623 if(prefix[bufsz-1] == ':') {
624 prefix[bufsz] = SEP;
625 prefix[bufsz+1] = 0;
626 }
627 //}
628 //else
629 // strncpy(prefix, PREFIX, MAXPATHLEN);
630
631 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: prefix = \"%s\"\n", __func__, __LINE__, prefix);
632
633 /* Calculate size of return buffer.
634 */
635 defpath = pythonpath;
636 bufsz = 0;
637
638 if (rtpypath)
639 bufsz += strlen(rtpypath) + 1;
640
641 prefixsz = strlen(prefix) + 1;
642
643 while (1) {
644 char *delim = strchr(defpath, DELIM);
645
646 if (is_absolute(defpath) == 0)
647 /* Paths are relative to prefix */
648 bufsz += prefixsz;
649
650 if (delim)
651 bufsz += delim - defpath + 1;
652 else {
653 bufsz += strlen(defpath) + 1;
654 break;
655 }
656 defpath = delim + 1;
657 }
658 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: defpath = \"%s\"\n", __func__, __LINE__, defpath);
659
660 bufsz += strlen(zip_path) + 1;
661 bufsz += strlen(exec_prefix) + 1;
662
663 /* This is the only malloc call in this file */
664 buf = (char *)PyMem_Malloc(bufsz);
665
666 if (buf == NULL) {
667 /* We can't exit, so print a warning and limp along */
668 fprintf(stderr, "Not enough memory for dynamic PYTHONPATH.\n");
669 fprintf(stderr, "Using default static PYTHONPATH.\n");
670 module_search_path = PYTHONPATH;
671 }
672 else {
673 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]:\n", __func__, __LINE__);
674 /* Run-time value of $PYTHONPATH goes first */
675 if (rtpypath) {
676 strcpy(buf, rtpypath);
677 strcat(buf, delimiter);
678 }
679 else
680 buf[0] = '\0';
681 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: RTpath = \"%s\"\n", __func__, __LINE__, buf);
682
683 /* Next is the default zip path */
684 strcat(buf, zip_path);
685 strcat(buf, delimiter);
686 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: +Zip = \"%s\"\n", __func__, __LINE__, buf);
687
688 /* Next goes merge of compile-time $PYTHONPATH with
689 * dynamically located prefix.
690 */
691 defpath = pythonpath;
692 while (1) {
693 char *delim = strchr(defpath, DELIM);
694
695 if (is_absolute(defpath) != 1) {
696 strcat(buf, prefix);
697 strcat(buf, separator);
698 }
699
700 if (delim) {
701 size_t len = delim - defpath + 1;
702 size_t end = strlen(buf) + len;
703 strncat(buf, defpath, len);
704 *(buf + end) = '\0';
705 }
706 else {
707 strcat(buf, defpath);
708 break;
709 }
710 defpath = delim + 1;
711 }
712 strcat(buf, delimiter);
713 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: +Merge = \"%s\"\n", __func__, __LINE__, buf);
714
715 /* Finally, on goes the directory for dynamic-load modules */
716 strcat(buf, exec_prefix);
717
718 /* And publish the results */
719 module_search_path = buf;
720 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__, __LINE__, module_search_path);
721 }
722
723 //if (efound > 0) {
724 /* At this point, exec_prefix is set to VOL:/Efi/StdLib/lib/python.27/dynalib.
725 We want to get back to the root value, so we have to remove the final three
726 segments to get VOL:/Efi/StdLib. Because we don't know what VOL is, and
727 EXEC_PREFIX is also indeterminate, we just remove the three final segments.
728 */
729 reduce(exec_prefix);
730 reduce(exec_prefix);
731 reduce(exec_prefix);
732 if (!exec_prefix[0]) {
733 strcpy(exec_prefix, volume_name);
734 }
735 bufsz = strlen(exec_prefix);
736 if(exec_prefix[bufsz-1] == ':') {
737 exec_prefix[bufsz] = SEP;
738 exec_prefix[bufsz+1] = 0;
739 }
740 //}
741 //else
742 // strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
743 if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__, __LINE__, module_search_path);
744 if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: prefix = \"%s\"\n", __func__, __LINE__, prefix);
745 if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: exec_prefix = \"%s\"\n", __func__, __LINE__, exec_prefix);
746 if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__, __LINE__, progpath);
747 }
748
749
750 /* External interface */
751
752 char *
753 Py_GetPath(void)
754 {
755 if (!module_search_path)
756 calculate_path();
757 return module_search_path;
758 }
759
760 char *
761 Py_GetPrefix(void)
762 {
763 if (!module_search_path)
764 calculate_path();
765 return prefix;
766 }
767
768 char *
769 Py_GetExecPrefix(void)
770 {
771 if (!module_search_path)
772 calculate_path();
773 return exec_prefix;
774 }
775
776 char *
777 Py_GetProgramFullPath(void)
778 {
779 if (!module_search_path)
780 calculate_path();
781 return progpath;
782 }
783
784
785 #ifdef __cplusplus
786 }
787 #endif
788