getpath.c 23.3 KB
Newer Older
1 2
/* Return the initial module search path. */

Guido van Rossum's avatar
Guido van Rossum committed
3 4 5
#include "Python.h"
#include "osdefs.h"

6
#include <sys/types.h>
7
#include <string.h>
Guido van Rossum's avatar
Guido van Rossum committed
8

9
#ifdef __APPLE__
10 11 12
#include <mach-o/dyld.h>
#endif

13 14 15
/* Search in some common locations for the associated Python libraries.
 *
 * Two directories must be found, the platform independent directory
16 17 18 19
 * (prefix), containing the common .py and .pyc files, and the platform
 * dependent directory (exec_prefix), containing the shared library
 * modules.  Note that prefix and exec_prefix can be the same directory,
 * but for some installations, they are different.
20
 *
21 22 23 24 25 26
 * Py_GetPath() carries out separate searches for prefix and exec_prefix.
 * Each search tries a number of different locations until a ``landmark''
 * file or directory is found.  If no prefix or exec_prefix is found, a
 * warning message is issued and the preprocessor defined PREFIX and
 * EXEC_PREFIX are used (even though they will not work); python carries on
 * 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 31 32 33
 * unchanged.  Otherwise, it must have been invoked from the shell's path,
 * so we search $PATH for the named executable and use that.  If the
 * executable was not found on $PATH (or there was no $PATH environment
 * variable), the original argv[0] string is used.
34
 *
35 36 37
 * Next, the executable location is examined to see if it is a symbolic
 * link.  If so, the link is chased (correctly interpreting a relative
 * pathname if one is found) and the directory of the link target is used.
38
 *
39 40
 * Finally, argv0_path is set to the directory containing the executable
 * (i.e. the last component is stripped).
41
 *
42 43 44
 * With argv0_path in hand, we perform a number of steps.  The same steps
 * are performed for prefix and for exec_prefix, but with a different
 * landmark.
45 46 47
 *
 * Step 1. Are we running python out of the build directory?  This is
 * checked by looking for a different kind of landmark relative to
48 49 50 51
 * argv0_path.  For prefix, the landmark's path is derived from the VPATH
 * preprocessor variable (taking into account that its value is almost, but
 * not quite, what we need).  For exec_prefix, the landmark is
 * 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 57 58 59
 * number as supplied by the Makefile.  Note that this means that no more
 * build directory checking is performed; if the first step did not find
 * the landmarks, the assumption is that python is running from an
 * installed setup.
60 61
 *
 * Step 2. See if the $PYTHONHOME environment variable points to the
62 63 64 65
 * installed location of the Python libraries.  If $PYTHONHOME is set, then
 * it points to prefix and exec_prefix.  $PYTHONHOME can be a single
 * directory, which is used for both, or the prefix and exec_prefix
 * directories separated by a colon.
66 67
 *
 * Step 3. Try to find prefix and exec_prefix relative to argv0_path,
68 69 70 71
 * backtracking up the path until it is exhausted.  This is the most common
 * step to succeed.  Note that if prefix and exec_prefix are different,
 * exec_prefix is more likely to be found; however if exec_prefix is a
 * subdirectory of prefix, both will be found.
72
 *
73 74 75
 * Step 4. Search the directories pointed to by the preprocessor variables
 * PREFIX and EXEC_PREFIX.  These are supplied by the Makefile but can be
 * passed in as options to the configure script.
76
 *
77 78 79
 * That's it!
 *
 * Well, almost.  Once we have determined prefix and exec_prefix, the
80
 * preprocessor variable PYTHONPATH is used to construct a path.  Each
81 82 83 84 85 86 87 88 89 90 91 92
 * relative path on PYTHONPATH is prefixed with prefix.  Then the directory
 * containing the shared library modules is appended.  The environment
 * variable $PYTHONPATH is inserted in front of it all.  Finally, the
 * prefix and exec_prefix globals are tweaked so they reflect the values
 * expected by other code, by stripping the "lib/python$VERSION/..." stuff
 * off.  If either points to the build directory, the globals are reset to
 * the corresponding preprocessor variables (so sys.prefix will reflect the
 * installation location, even though sys.path points into the build
 * directory).  This seems to make more sense given that currently the only
 * known use of sys.prefix and sys.exec_prefix is for the ILU installation
 * process to find the installed Python tree.
 */
93

94 95 96 97 98
#ifdef __cplusplus
 extern "C" {
#endif


99
#ifndef VERSION
100
#define VERSION "2.1"
101 102 103 104
#endif

#ifndef VPATH
#define VPATH "."
Guido van Rossum's avatar
Guido van Rossum committed
105 106
#endif

107
#ifndef PREFIX
108 109 110 111 112
#  ifdef __VMS
#    define PREFIX ""
#  else
#    define PREFIX "/usr/local"
#  endif
113 114 115
#endif

#ifndef EXEC_PREFIX
116
#define EXEC_PREFIX PREFIX
117 118
#endif

119 120
#ifndef PYTHONPATH
#define PYTHONPATH PREFIX "/lib/python" VERSION ":" \
121
              EXEC_PREFIX "/lib/python" VERSION "/lib-dynload"
122
#endif
Guido van Rossum's avatar
Guido van Rossum committed
123

124
#ifndef LANDMARK
125
#define LANDMARK L"os.py"
126
#endif
127

128 129 130 131
static wchar_t prefix[MAXPATHLEN+1];
static wchar_t exec_prefix[MAXPATHLEN+1];
static wchar_t progpath[MAXPATHLEN+1];
static wchar_t *module_search_path = NULL;
132
static wchar_t *lib_python = L"lib/python" VERSION;
133 134 135 136 137 138 139 140 141 142 143 144

/* In principle, this should use HAVE__WSTAT, and _wstat
   should be detected by autoconf. However, no current
   POSIX system provides that function, so testing for
   it is pointless. */
#ifndef MS_WINDOWS
static int
_wstat(const wchar_t* path, struct stat *buf)
{
    char fname[PATH_MAX];
    size_t res = wcstombs(fname, path, sizeof(fname));
    if (res == (size_t)-1) {
145 146
        errno = EINVAL;
        return -1;
147 148 149 150 151 152 153 154 155 156 157
    }
    return stat(fname, buf);
}
#endif

#ifndef MS_WINDOWS
static wchar_t*
_wgetcwd(wchar_t *buf, size_t size)
{
    char fname[PATH_MAX];
    if (getcwd(fname, PATH_MAX) == NULL)
158
        return NULL;
159
    if (mbstowcs(buf, fname, size) >= size) {
160 161
        errno = ERANGE;
        return NULL;
162 163 164 165 166 167
    }
    return buf;
}
#endif

#ifdef HAVE_READLINK
168
int
169 170 171 172 173 174 175
_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
{
    char cbuf[PATH_MAX];
    char cpath[PATH_MAX];
    int res;
    size_t r1 = wcstombs(cpath, path, PATH_MAX);
    if (r1 == (size_t)-1 || r1 >= PATH_MAX) {
176 177
        errno = EINVAL;
        return -1;
178 179 180
    }
    res = (int)readlink(cpath, cbuf, PATH_MAX);
    if (res == -1)
181
        return -1;
182
    if (res == PATH_MAX) {
183 184
        errno = EINVAL;
        return -1;
185
    }
186
    cbuf[res] = '\0'; /* buf will be null terminated */
187 188
    r1 = mbstowcs(buf, cbuf, bufsiz);
    if (r1 == -1) {
189 190
        errno = EINVAL;
        return -1;
191 192
    }
    return (int)r1;
193

194 195
}
#endif
196 197

static void
198
reduce(wchar_t *dir)
199
{
200
    size_t i = wcslen(dir);
201 202 203
    while (i > 0 && dir[i] != SEP)
        --i;
    dir[i] = '\0';
204
}
205 206 207


static int
208
isfile(wchar_t *filename)          /* Is file, not directory */
209
{
210
    struct stat buf;
211
    if (_wstat(filename, &buf) != 0)
212 213 214 215
        return 0;
    if (!S_ISREG(buf.st_mode))
        return 0;
    return 1;
216 217 218 219
}


static int
220
ismodule(wchar_t *filename)        /* Is module -- check for .pyc/.pyo too */
221
{
222 223 224 225
    if (isfile(filename))
        return 1;

    /* Check for the compiled version of prefix. */
226 227
    if (wcslen(filename) < MAXPATHLEN) {
        wcscat(filename, Py_OptimizeFlag ? L"o" : L"c");
228 229 230 231
        if (isfile(filename))
            return 1;
    }
    return 0;
232 233 234 235
}


static int
236
isxfile(wchar_t *filename)         /* Is executable file */
237
{
238
    struct stat buf;
239
    if (_wstat(filename, &buf) != 0)
240 241 242 243 244 245
        return 0;
    if (!S_ISREG(buf.st_mode))
        return 0;
    if ((buf.st_mode & 0111) == 0)
        return 0;
    return 1;
246 247
}

248 249

static int
250
isdir(wchar_t *filename)                   /* Is directory */
251
{
252
    struct stat buf;
253
    if (_wstat(filename, &buf) != 0)
254 255 256 257
        return 0;
    if (!S_ISDIR(buf.st_mode))
        return 0;
    return 1;
258 259 260
}


261 262 263 264 265 266 267 268
/* Add a path component, by appending stuff to buffer.
   buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
   NUL-terminated string with no more than MAXPATHLEN characters (not counting
   the trailing NUL).  It's a fatal error if it contains a string longer than
   that (callers must be careful!).  If these requirements are met, it's
   guaranteed that buffer will still be a NUL-terminated string with no more
   than MAXPATHLEN characters at exit.  If stuff is too long, only as much of
   stuff as fits will be appended.
269
*/
270
static void
271
joinpath(wchar_t *buffer, wchar_t *stuff)
272
{
273 274 275 276
    size_t n, k;
    if (stuff[0] == SEP)
        n = 0;
    else {
277
        n = wcslen(buffer);
278 279 280
        if (n > 0 && buffer[n-1] != SEP && n < MAXPATHLEN)
            buffer[n++] = SEP;
    }
281
    if (n > MAXPATHLEN)
282
        Py_FatalError("buffer overflow in getpath.c's joinpath()");
283
    k = wcslen(stuff);
284 285
    if (n + k > MAXPATHLEN)
        k = MAXPATHLEN - n;
286
    wcsncpy(buffer+n, stuff, k);
287
    buffer[n+k] = '\0';
288 289
}

290 291
/* copy_absolute requires that path be allocated at least
   MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes. */
292
static void
293
copy_absolute(wchar_t *path, wchar_t *p)
294
{
295
    if (p[0] == SEP)
296
        wcscpy(path, p);
297
    else {
298
        _wgetcwd(path, MAXPATHLEN);
299 300 301
        if (p[0] == '.' && p[1] == SEP)
            p += 2;
        joinpath(path, p);
302 303
    }
}
304

305 306
/* absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes. */
static void
307
absolutize(wchar_t *path)
308
{
309
    wchar_t buffer[MAXPATHLEN + 1];
310 311 312 313

    if (path[0] == SEP)
        return;
    copy_absolute(buffer, path);
314
    wcscpy(path, buffer);
315 316 317
}

/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
318 319
   bytes long.
*/
320
static int
321
search_for_prefix(wchar_t *argv0_path, wchar_t *home)
322
{
323
    size_t n;
324
    wchar_t *vpath;
325 326 327

    /* If PYTHONHOME is set, we believe it unconditionally */
    if (home) {
328 329 330
        wchar_t *delim;
        wcsncpy(prefix, home, MAXPATHLEN);
        delim = wcschr(prefix, DELIM);
331
        if (delim)
332
            *delim = L'\0';
333 334 335 336 337 338
        joinpath(prefix, lib_python);
        joinpath(prefix, LANDMARK);
        return 1;
    }

    /* Check to see if argv[0] is in the build directory */
339 340
    wcscpy(prefix, argv0_path);
    joinpath(prefix, L"Modules/Setup");
341
    if (isfile(prefix)) {
342
        /* Check VPATH to see if argv0_path is in the build directory. */
343 344
        vpath = L"" VPATH;
        wcscpy(prefix, argv0_path);
345
        joinpath(prefix, vpath);
346
        joinpath(prefix, L"Lib");
347 348 349 350 351 352
        joinpath(prefix, LANDMARK);
        if (ismodule(prefix))
            return -1;
    }

    /* Search from argv0_path, until root is found */
353
    copy_absolute(prefix, argv0_path);
354
    do {
355
        n = wcslen(prefix);
356 357 358 359
        joinpath(prefix, lib_python);
        joinpath(prefix, LANDMARK);
        if (ismodule(prefix))
            return 1;
360
        prefix[n] = L'\0';
361 362 363 364
        reduce(prefix);
    } while (prefix[0]);

    /* Look at configure's PREFIX */
365
    wcsncpy(prefix, L"" PREFIX, MAXPATHLEN);
366 367 368 369 370 371 372
    joinpath(prefix, lib_python);
    joinpath(prefix, LANDMARK);
    if (ismodule(prefix))
        return 1;

    /* Fail */
    return 0;
373 374 375
}


376
/* search_for_exec_prefix requires that argv0_path be no more than
377
   MAXPATHLEN bytes long.
378
*/
379
static int
380
search_for_exec_prefix(wchar_t *argv0_path, wchar_t *home)
381
{
382 383 384 385
    size_t n;

    /* If PYTHONHOME is set, we believe it unconditionally */
    if (home) {
386 387
        wchar_t *delim;
        delim = wcschr(home, DELIM);
388
        if (delim)
389
            wcsncpy(exec_prefix, delim+1, MAXPATHLEN);
390
        else
391
            wcsncpy(exec_prefix, home, MAXPATHLEN);
392
        joinpath(exec_prefix, lib_python);
393
        joinpath(exec_prefix, L"lib-dynload");
394 395 396 397
        return 1;
    }

    /* Check to see if argv[0] is in the build directory */
398 399
    wcscpy(exec_prefix, argv0_path);
    joinpath(exec_prefix, L"Modules/Setup");
400 401 402 403 404 405
    if (isfile(exec_prefix)) {
        reduce(exec_prefix);
        return -1;
    }

    /* Search from argv0_path, until root is found */
406
    copy_absolute(exec_prefix, argv0_path);
407
    do {
408
        n = wcslen(exec_prefix);
409
        joinpath(exec_prefix, lib_python);
410
        joinpath(exec_prefix, L"lib-dynload");
411 412
        if (isdir(exec_prefix))
            return 1;
413
        exec_prefix[n] = L'\0';
414 415 416 417
        reduce(exec_prefix);
    } while (exec_prefix[0]);

    /* Look at configure's EXEC_PREFIX */
418
    wcsncpy(exec_prefix, L"" EXEC_PREFIX, MAXPATHLEN);
419
    joinpath(exec_prefix, lib_python);
420
    joinpath(exec_prefix, L"lib-dynload");
421 422 423 424 425
    if (isdir(exec_prefix))
        return 1;

    /* Fail */
    return 0;
426 427 428 429
}


static void
430
calculate_path(void)
Guido van Rossum's avatar
Guido van Rossum committed
431
{
432 433 434 435 436 437 438 439 440 441 442 443 444 445
    extern wchar_t *Py_GetProgramName(void);

    static wchar_t delimiter[2] = {DELIM, '\0'};
    static wchar_t separator[2] = {SEP, '\0'};
    wchar_t *pythonpath = L"" PYTHONPATH;
    char *_rtpypath = Py_GETENV("PYTHONPATH"); /* XXX use wide version on Windows */
    wchar_t rtpypath[MAXPATHLEN+1];
    wchar_t *home = Py_GetPythonHome();
    char *_path = getenv("PATH");
    wchar_t wpath[MAXPATHLEN+1];
    wchar_t *path = NULL;
    wchar_t *prog = Py_GetProgramName();
    wchar_t argv0_path[MAXPATHLEN+1];
    wchar_t zip_path[MAXPATHLEN+1];
446
    int pfound, efound; /* 1 if found; -1 if found build directory */
447
    wchar_t *buf;
448 449
    size_t bufsz;
    size_t prefixsz;
450
    wchar_t *defpath = pythonpath;
451
#ifdef WITH_NEXT_FRAMEWORK
452
    NSModule pythonModule;
453
#endif
454
#ifdef __APPLE__
455
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
456
    uint32_t nsexeclength = MAXPATHLEN;
457 458 459
#else
    unsigned long nsexeclength = MAXPATHLEN;
#endif
460
        char execpath[MAXPATHLEN+1];
461
#endif
462

463
    if (_path) {
464 465 466 467 468 469
            size_t r = mbstowcs(wpath, _path, MAXPATHLEN+1);
            path = wpath;
            if (r == (size_t)-1 || r > MAXPATHLEN) {
                    /* Could not convert PATH, or it's too long. */
                    path = NULL;
            }
470 471
    }

472 473 474 475 476 477 478
        /* If there is no slash in the argv0 path, then we have to
         * assume python is on the user's $PATH, since there's no
         * other way to find a directory to start the search from.  If
         * $PATH isn't exported, you lose.
         */
        if (wcschr(prog, SEP))
                wcsncpy(progpath, prog, MAXPATHLEN);
479 480 481 482 483 484 485 486 487 488 489
#ifdef __APPLE__
     /* On Mac OS X, if a script uses an interpreter of the form
      * "#!/opt/python2.3/bin/python", the kernel only passes "python"
      * as argv[0], which falls through to the $PATH search below.
      * If /opt/python2.3/bin isn't in your path, or is near the end,
      * this algorithm may incorrectly find /usr/bin/python. To work
      * around this, we can use _NSGetExecutablePath to get a better
      * hint of what the intended interpreter was, although this
      * will fail if a relative path was used. but in that case,
      * absolutize() should help us out below
      */
490 491 492 493 494 495 496
        else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && execpath[0] == SEP) {
                size_t r = mbstowcs(progpath, execpath, MAXPATHLEN+1);
                if (r == (size_t)-1 || r > MAXPATHLEN) {
                        /* Could not convert execpath, or it's too long. */
                        progpath[0] = '\0';
                }
        }
497
#endif /* __APPLE__ */
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
        else if (path) {
                while (1) {
                        wchar_t *delim = wcschr(path, DELIM);

                        if (delim) {
                                size_t len = delim - path;
                                if (len > MAXPATHLEN)
                                        len = MAXPATHLEN;
                                wcsncpy(progpath, path, len);
                                *(progpath + len) = '\0';
                        }
                        else
                                wcsncpy(progpath, path, MAXPATHLEN);

                        joinpath(progpath, prog);
                        if (isxfile(progpath))
                                break;

                        if (!delim) {
                                progpath[0] = L'\0';
                                break;
                        }
                        path = delim + 1;
                }
        }
        else
                progpath[0] = '\0';
        if (progpath[0] != SEP && progpath[0] != '\0')
                absolutize(progpath);
        wcsncpy(argv0_path, progpath, MAXPATHLEN);
        argv0_path[MAXPATHLEN] = '\0';
529

530
#ifdef WITH_NEXT_FRAMEWORK
531 532 533 534 535
        /* On Mac OS X we have a special case if we're running from a framework.
        ** This is because the python home should be set relative to the library,
        ** which is in the framework, not relative to the executable, which may
        ** be outside of the framework. Except when we're in the build directory...
        */
536 537
    pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
    /* Use dylib functions to find out where the framework was loaded from */
538
    buf = (wchar_t *)NSLibraryNameForModule(pythonModule);
539 540
    if (buf != NULL) {
        /* We're in a framework. */
541 542 543 544 545 546 547
        /* See if we might be in the build directory. The framework in the
        ** build directory is incomplete, it only has the .dylib and a few
        ** needed symlinks, it doesn't have the Lib directories and such.
        ** If we're running with the framework from the build directory we must
        ** be running the interpreter in the build directory, so we use the
        ** build-directory-specific logic to find Lib and such.
        */
548
        wcsncpy(argv0_path, buf, MAXPATHLEN);
549 550 551 552
        reduce(argv0_path);
        joinpath(argv0_path, lib_python);
        joinpath(argv0_path, LANDMARK);
        if (!ismodule(argv0_path)) {
553 554
                /* We are in the build directory so use the name of the
                   executable - we know that the absolute path is passed */
555
                wcsncpy(argv0_path, prog, MAXPATHLEN);
556 557
        }
        else {
558
                /* Use the location of the library as the progpath */
559
                wcsncpy(argv0_path, buf, MAXPATHLEN);
560
        }
561
    }
562
#endif
563 564

#if HAVE_READLINK
565
    {
566 567
        wchar_t tmpbuffer[MAXPATHLEN+1];
        int linklen = _Py_wreadlink(progpath, tmpbuffer, MAXPATHLEN);
568 569
        while (linklen != -1) {
            if (tmpbuffer[0] == SEP)
570 571
                /* tmpbuffer should never be longer than MAXPATHLEN,
                   but extra check does not hurt */
572
                wcsncpy(argv0_path, tmpbuffer, MAXPATHLEN);
573 574 575 576 577
            else {
                /* Interpret relative to progpath */
                reduce(argv0_path);
                joinpath(argv0_path, tmpbuffer);
            }
578
            linklen = _Py_wreadlink(argv0_path, tmpbuffer, MAXPATHLEN);
579 580
        }
    }
581 582
#endif /* HAVE_READLINK */

583
    reduce(argv0_path);
584 585 586
    /* At this point, argv0_path is guaranteed to be less than
       MAXPATHLEN bytes long.
    */
587 588 589 590

    if (!(pfound = search_for_prefix(argv0_path, home))) {
        if (!Py_FrozenFlag)
            fprintf(stderr,
591
                "Could not find platform independent libraries <prefix>\n");
592
        wcsncpy(prefix, L"" PREFIX, MAXPATHLEN);
593 594 595 596
        joinpath(prefix, lib_python);
    }
    else
        reduce(prefix);
597

598 599
    wcsncpy(zip_path, prefix, MAXPATHLEN);
    zip_path[MAXPATHLEN] = L'\0';
Just van Rossum's avatar
Just van Rossum committed
600 601 602 603 604
    if (pfound > 0) { /* Use the reduced prefix returned by Py_GetPrefix() */
        reduce(zip_path);
        reduce(zip_path);
    }
    else
605 606
        wcsncpy(zip_path, L"" PREFIX, MAXPATHLEN);
    joinpath(zip_path, L"lib/python00.zip");
607
    bufsz = wcslen(zip_path);   /* Replace "00" with version */
Just van Rossum's avatar
Just van Rossum committed
608 609 610
    zip_path[bufsz - 6] = VERSION[0];
    zip_path[bufsz - 5] = VERSION[2];

611 612 613
    if (!(efound = search_for_exec_prefix(argv0_path, home))) {
        if (!Py_FrozenFlag)
            fprintf(stderr,
614
                "Could not find platform dependent libraries <exec_prefix>\n");
615 616
        wcsncpy(exec_prefix, L"" EXEC_PREFIX, MAXPATHLEN);
        joinpath(exec_prefix, L"lib/lib-dynload");
617 618 619 620 621 622 623 624 625 626 627
    }
    /* If we found EXEC_PREFIX do *not* reduce it!  (Yet.) */

    if ((!pfound || !efound) && !Py_FrozenFlag)
        fprintf(stderr,
                "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");

    /* Calculate size of return buffer.
     */
    bufsz = 0;

628
    if (_rtpypath) {
629 630 631 632 633 634
        size_t s = mbstowcs(rtpypath, _rtpypath, sizeof(rtpypath)/sizeof(wchar_t));
        if (s == (size_t)-1 || s >=sizeof(rtpypath))
            /* XXX deal with errors more gracefully */
            _rtpypath = NULL;
        if (_rtpypath)
            bufsz += wcslen(rtpypath) + 1;
635
    }
636

637
    prefixsz = wcslen(prefix) + 1;
638 639

    while (1) {
640
        wchar_t *delim = wcschr(defpath, DELIM);
641 642 643 644 645 646 647 648

        if (defpath[0] != SEP)
            /* Paths are relative to prefix */
            bufsz += prefixsz;

        if (delim)
            bufsz += delim - defpath + 1;
        else {
649
            bufsz += wcslen(defpath) + 1;
650 651 652 653 654
            break;
        }
        defpath = delim + 1;
    }

655 656
    bufsz += wcslen(zip_path) + 1;
    bufsz += wcslen(exec_prefix) + 1;
657 658

    /* This is the only malloc call in this file */
659
    buf = (wchar_t *)PyMem_Malloc(bufsz*sizeof(wchar_t));
660 661 662 663 664

    if (buf == NULL) {
        /* We can't exit, so print a warning and limp along */
        fprintf(stderr, "Not enough memory for dynamic PYTHONPATH.\n");
        fprintf(stderr, "Using default static PYTHONPATH.\n");
665
        module_search_path = L"" PYTHONPATH;
666 667 668
    }
    else {
        /* Run-time value of $PYTHONPATH goes first */
669 670 671
        if (_rtpypath) {
            wcscpy(buf, rtpypath);
            wcscat(buf, delimiter);
672 673 674 675
        }
        else
            buf[0] = '\0';

Just van Rossum's avatar
Just van Rossum committed
676
        /* Next is the default zip path */
677 678
        wcscat(buf, zip_path);
        wcscat(buf, delimiter);
Just van Rossum's avatar
Just van Rossum committed
679

680 681 682 683 684
        /* Next goes merge of compile-time $PYTHONPATH with
         * dynamically located prefix.
         */
        defpath = pythonpath;
        while (1) {
685
            wchar_t *delim = wcschr(defpath, DELIM);
686 687

            if (defpath[0] != SEP) {
688 689
                wcscat(buf, prefix);
                wcscat(buf, separator);
690 691 692 693
            }

            if (delim) {
                size_t len = delim - defpath + 1;
694 695
                size_t end = wcslen(buf) + len;
                wcsncat(buf, defpath, len);
696 697 698
                *(buf + end) = '\0';
            }
            else {
699
                wcscat(buf, defpath);
700 701 702 703
                break;
            }
            defpath = delim + 1;
        }
704
        wcscat(buf, delimiter);
705 706

        /* Finally, on goes the directory for dynamic-load modules */
707
        wcscat(buf, exec_prefix);
708 709 710 711 712 713 714 715 716 717 718 719 720

        /* And publish the results */
        module_search_path = buf;
    }

    /* Reduce prefix and exec_prefix to their essence,
     * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
     * If we're loading relative to the build directory,
     * return the compiled-in defaults instead.
     */
    if (pfound > 0) {
        reduce(prefix);
        reduce(prefix);
721 722 723 724
        /* The prefix is the root directory, but reduce() chopped
         * off the "/". */
        if (!prefix[0])
                wcscpy(prefix, separator);
725 726
    }
    else
727
        wcsncpy(prefix, L"" PREFIX, MAXPATHLEN);
728 729 730 731 732

    if (efound > 0) {
        reduce(exec_prefix);
        reduce(exec_prefix);
        reduce(exec_prefix);
733 734
        if (!exec_prefix[0])
                wcscpy(exec_prefix, separator);
735 736
    }
    else
737
        wcsncpy(exec_prefix, L"" EXEC_PREFIX, MAXPATHLEN);
Guido van Rossum's avatar
Guido van Rossum committed
738
}
739 740


741 742
/* External interface */

743
wchar_t *
744
Py_GetPath(void)
745
{
746 747 748
    if (!module_search_path)
        calculate_path();
    return module_search_path;
749
}
750

751
wchar_t *
752
Py_GetPrefix(void)
753
{
754 755 756
    if (!module_search_path)
        calculate_path();
    return prefix;
757 758
}

759
wchar_t *
760
Py_GetExecPrefix(void)
761
{
762 763 764
    if (!module_search_path)
        calculate_path();
    return exec_prefix;
765
}
766

767
wchar_t *
768
Py_GetProgramFullPath(void)
769
{
770 771 772
    if (!module_search_path)
        calculate_path();
    return progpath;
773
}
774 775 776 777 778 779


#ifdef __cplusplus
}
#endif