diff options
Diffstat (limited to 'Python/pathconfig.c')
| -rw-r--r-- | Python/pathconfig.c | 98 | 
1 files changed, 98 insertions, 0 deletions
| diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 53ddfc997d..b17ae822a7 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -261,6 +261,104 @@ Py_GetProgramName(void)  } +#define _HAVE_SCRIPT_ARGUMENT(argc, argv) \ +  (argc > 0 && argv0 != NULL && \ +   wcscmp(argv0, L"-c") != 0 && wcscmp(argv0, L"-m") != 0) + +/* Compute argv[0] which will be prepended to sys.argv */ +PyObject* +_PyPathConfig_ComputeArgv0(int argc, wchar_t **argv) +{ +    wchar_t *argv0; +    wchar_t *p = NULL; +    Py_ssize_t n = 0; +#ifdef HAVE_READLINK +    wchar_t link[MAXPATHLEN+1]; +    wchar_t argv0copy[2*MAXPATHLEN+1]; +    int nr = 0; +#endif +#if defined(HAVE_REALPATH) +    wchar_t fullpath[MAXPATHLEN]; +#elif defined(MS_WINDOWS) +    wchar_t fullpath[MAX_PATH]; +#endif + + +    argv0 = argv[0]; + +#ifdef HAVE_READLINK +    if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) +        nr = _Py_wreadlink(argv0, link, MAXPATHLEN); +    if (nr > 0) { +        /* It's a symlink */ +        link[nr] = '\0'; +        if (link[0] == SEP) +            argv0 = link; /* Link to absolute path */ +        else if (wcschr(link, SEP) == NULL) +            ; /* Link without path */ +        else { +            /* Must join(dirname(argv0), link) */ +            wchar_t *q = wcsrchr(argv0, SEP); +            if (q == NULL) +                argv0 = link; /* argv0 without path */ +            else { +                /* Must make a copy, argv0copy has room for 2 * MAXPATHLEN */ +                wcsncpy(argv0copy, argv0, MAXPATHLEN); +                q = wcsrchr(argv0copy, SEP); +                wcsncpy(q+1, link, MAXPATHLEN); +                q[MAXPATHLEN + 1] = L'\0'; +                argv0 = argv0copy; +            } +        } +    } +#endif /* HAVE_READLINK */ + +#if SEP == '\\' +    /* Special case for Microsoft filename syntax */ +    if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { +        wchar_t *q; +#if defined(MS_WINDOWS) +        /* Replace the first element in argv with the full path. */ +        wchar_t *ptemp; +        if (GetFullPathNameW(argv0, +                           Py_ARRAY_LENGTH(fullpath), +                           fullpath, +                           &ptemp)) { +            argv0 = fullpath; +        } +#endif +        p = wcsrchr(argv0, SEP); +        /* Test for alternate separator */ +        q = wcsrchr(p ? p : argv0, '/'); +        if (q != NULL) +            p = q; +        if (p != NULL) { +            n = p + 1 - argv0; +            if (n > 1 && p[-1] != ':') +                n--; /* Drop trailing separator */ +        } +    } +#else /* All other filename syntaxes */ +    if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { +#if defined(HAVE_REALPATH) +        if (_Py_wrealpath(argv0, fullpath, Py_ARRAY_LENGTH(fullpath))) { +            argv0 = fullpath; +        } +#endif +        p = wcsrchr(argv0, SEP); +    } +    if (p != NULL) { +        n = p + 1 - argv0; +#if SEP == '/' /* Special case for Unix filename syntax */ +        if (n > 1) +            n--; /* Drop trailing separator */ +#endif /* Unix */ +    } +#endif /* All others */ + +    return PyUnicode_FromWideChar(argv0, n); +} +  #ifdef __cplusplus  }  #endif | 
