Home | History | Annotate | Download | only in os2emx
      1 
      2 /* Return the initial module search path. */
      3 /* This version used by OS/2+EMX */
      4 
      5 /* ----------------------------------------------------------------
      6    PATH RULES FOR OS/2+EMX:
      7    This describes how sys.path is formed on OS/2+EMX.  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 attempt to locate the "Python Home" - if the PYTHONHOME env var
     17      is set, we believe it.  Otherwise, we use the path of our host .EXE's
     18      to try and locate our "landmark" (lib\\os.py) and deduce our home.
     19      - If we DO have a Python Home: The relevant sub-directories (Lib,
     20        plat-win, lib-tk, etc) are based on the Python Home
     21      - If we DO NOT have a Python Home, the core Python Path is
     22        loaded from the registry.  This is the main PythonPath key,
     23        and both HKLM and HKCU are combined to form the path)
     24 
     25    * Iff - we can not locate the Python Home, and have not had a PYTHONPATH
     26      specified (ie, we have _nothing_ we can assume is a good path), a
     27      default path with relative entries is used (eg. .\Lib;.\plat-win, etc)
     28 
     29 
     30   The end result of all this is:
     31   * When running python.exe, or any other .exe in the main Python directory
     32     (either an installed version, or directly from the PCbuild directory),
     33     the core path is deduced.
     34 
     35   * When Python is hosted in another exe (different directory, embedded via
     36     COM, etc), the Python Home will not be deduced, so the core path from
     37     the registry is used.  Other "application paths "in the registry are
     38     always read.
     39 
     40   * If Python can't find its home and there is no registry (eg, frozen
     41     exe, some very strange installation setup) you get a path with
     42     some default, but relative, paths.
     43 
     44    ---------------------------------------------------------------- */
     45 
     46 
     47 #include "Python.h"
     48 #include "osdefs.h"
     49 
     50 #ifndef PYOS_OS2
     51 #error This file only compilable on OS/2
     52 #endif
     53 
     54 #define INCL_DOS
     55 #include <os2.h>
     56 
     57 #include <sys/types.h>
     58 #include <sys/stat.h>
     59 #include <string.h>
     60 
     61 #if HAVE_UNISTD_H
     62 #include <unistd.h>
     63 #endif /* HAVE_UNISTD_H */
     64 
     65 /* Search in some common locations for the associated Python libraries.
     66  *
     67  * Py_GetPath() tries to return a sensible Python module search path.
     68  *
     69  * The approach is an adaptation for Windows of the strategy used in
     70  * ../Modules/getpath.c; it uses the Windows Registry as one of its
     71  * information sources.
     72  */
     73 
     74 #ifndef LANDMARK
     75 #if defined(PYCC_GCC)
     76 #define LANDMARK "lib/os.py"
     77 #else
     78 #define LANDMARK "lib\\os.py"
     79 #endif
     80 #endif
     81 
     82 static char prefix[MAXPATHLEN+1];
     83 static char progpath[MAXPATHLEN+1];
     84 static char *module_search_path = NULL;
     85 
     86 
     87 static int
     88 is_sep(char ch) /* determine if "ch" is a separator character */
     89 {
     90 #ifdef ALTSEP
     91     return ch == SEP || ch == ALTSEP;
     92 #else
     93     return ch == SEP;
     94 #endif
     95 }
     96 
     97 /* assumes 'dir' null terminated in bounds.
     98  * Never writes beyond existing terminator.
     99  */
    100 static void
    101 reduce(char *dir)
    102 {
    103     size_t i = strlen(dir);
    104     while (i > 0 && !is_sep(dir[i]))
    105         --i;
    106     dir[i] = '\0';
    107 }
    108 
    109 static int
    110 exists(char *filename)
    111 {
    112     struct stat buf;
    113     return stat(filename, &buf) == 0;
    114 }
    115 
    116 /* Is module  (check for .pyc/.pyo too)
    117  * Assumes 'filename' MAXPATHLEN+1 bytes long -
    118  * may extend 'filename' by one character.
    119  */
    120 static int
    121 ismodule(char *filename)
    122 {
    123     if (exists(filename))
    124         return 1;
    125 
    126     /* Check for the compiled version of prefix. */
    127     if (strlen(filename) < MAXPATHLEN) {
    128         strcat(filename, Py_OptimizeFlag ? "o" : "c");
    129         if (exists(filename))
    130             return 1;
    131     }
    132     return 0;
    133 }
    134 
    135 /* Add a path component, by appending stuff to buffer.
    136    buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
    137    NUL-terminated string with no more than MAXPATHLEN characters (not counting
    138    the trailing NUL).  It's a fatal error if it contains a string longer than
    139    that (callers must be careful!).  If these requirements are met, it's
    140    guaranteed that buffer will still be a NUL-terminated string with no more
    141    than MAXPATHLEN characters at exit.  If stuff is too long, only as much of
    142    stuff as fits will be appended.
    143 */
    144 
    145 static void
    146 join(char *buffer, char *stuff)
    147 {
    148     size_t n, k;
    149     if (is_sep(stuff[0]))
    150         n = 0;
    151     else {
    152         n = strlen(buffer);
    153         if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
    154             buffer[n++] = SEP;
    155     }
    156     if (n > MAXPATHLEN)
    157         Py_FatalError("buffer overflow in getpathp.c's joinpath()");
    158     k = strlen(stuff);
    159     if (n + k > MAXPATHLEN)
    160         k = MAXPATHLEN - n;
    161     strncpy(buffer+n, stuff, k);
    162     buffer[n+k] = '\0';
    163 }
    164 
    165 /* gotlandmark only called by search_for_prefix, which ensures
    166  * 'prefix' is null terminated in bounds.  join() ensures
    167  * 'landmark' can not overflow prefix if too long.
    168  */
    169 static int
    170 gotlandmark(char *landmark)
    171 {
    172     int n, ok;
    173 
    174     n = strlen(prefix);
    175     join(prefix, landmark);
    176     ok = ismodule(prefix);
    177     prefix[n] = '\0';
    178     return ok;
    179 }
    180 
    181 /* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd.
    182  * assumption provided by only caller, calculate_path()
    183  */
    184 static int
    185 search_for_prefix(char *argv0_path, char *landmark)
    186 {
    187     /* Search from argv0_path, until landmark is found */
    188     strcpy(prefix, argv0_path);
    189     do {
    190         if (gotlandmark(landmark))
    191             return 1;
    192         reduce(prefix);
    193     } while (prefix[0]);
    194     return 0;
    195 }
    196 
    197 
    198 static void
    199 get_progpath(void)
    200 {
    201     extern char *Py_GetProgramName(void);
    202     char *path = getenv("PATH");
    203     char *prog = Py_GetProgramName();
    204 
    205     PPIB pib;
    206     if ((DosGetInfoBlocks(NULL, &pib) == 0) &&
    207         (DosQueryModuleName(pib->pib_hmte, sizeof(progpath), progpath) == 0))
    208         return;
    209 
    210     if (prog == NULL || *prog == '\0')
    211         prog = "python";
    212 
    213     /* If there is no slash in the argv0 path, then we have to
    214      * assume python is on the user's $PATH, since there's no
    215      * other way to find a directory to start the search from.  If
    216      * $PATH isn't exported, you lose.
    217      */
    218 #ifdef ALTSEP
    219     if (strchr(prog, SEP) || strchr(prog, ALTSEP))
    220 #else
    221     if (strchr(prog, SEP))
    222 #endif
    223         strncpy(progpath, prog, MAXPATHLEN);
    224     else if (path) {
    225         while (1) {
    226             char *delim = strchr(path, DELIM);
    227 
    228             if (delim) {
    229                 size_t len = delim - path;
    230                 /* ensure we can't overwrite buffer */
    231 #if !defined(PYCC_GCC)
    232                 len = min(MAXPATHLEN,len);
    233 #else
    234                 len = MAXPATHLEN < len ? MAXPATHLEN : len;
    235 #endif
    236                 strncpy(progpath, path, len);
    237                 *(progpath + len) = '\0';
    238             }
    239             else
    240                 strncpy(progpath, path, MAXPATHLEN);
    241 
    242             /* join() is safe for MAXPATHLEN+1 size buffer */
    243             join(progpath, prog);
    244             if (exists(progpath))
    245                 break;
    246 
    247             if (!delim) {
    248                 progpath[0] = '\0';
    249                 break;
    250             }
    251             path = delim + 1;
    252         }
    253     }
    254     else
    255         progpath[0] = '\0';
    256 }
    257 
    258 static void
    259 calculate_path(void)
    260 {
    261     char argv0_path[MAXPATHLEN+1];
    262     char *buf;
    263     size_t bufsz;
    264     char *pythonhome = Py_GetPythonHome();
    265     char *envpath = getenv("PYTHONPATH");
    266     char zip_path[MAXPATHLEN+1];
    267     size_t len;
    268 
    269     get_progpath();
    270     /* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */
    271     strcpy(argv0_path, progpath);
    272     reduce(argv0_path);
    273     if (pythonhome == NULL || *pythonhome == '\0') {
    274         if (search_for_prefix(argv0_path, LANDMARK))
    275             pythonhome = prefix;
    276         else
    277             pythonhome = NULL;
    278     }
    279     else
    280         strncpy(prefix, pythonhome, MAXPATHLEN);
    281 
    282     if (envpath && *envpath == '\0')
    283         envpath = NULL;
    284 
    285     /* Calculate zip archive path */
    286     strncpy(zip_path, progpath, MAXPATHLEN);
    287     zip_path[MAXPATHLEN] = '\0';
    288     len = strlen(zip_path);
    289     if (len > 4) {
    290         zip_path[len-3] = 'z';  /* change ending to "zip" */
    291         zip_path[len-2] = 'i';
    292         zip_path[len-1] = 'p';
    293     }
    294     else {
    295         zip_path[0] = 0;
    296     }
    297 
    298     /* We need to construct a path from the following parts.
    299      * (1) the PYTHONPATH environment variable, if set;
    300      * (2) the zip archive file path;
    301      * (3) the PYTHONPATH config macro, with the leading "."
    302      *     of each component replaced with pythonhome, if set;
    303      * (4) the directory containing the executable (argv0_path).
    304      * The length calculation calculates #3 first.
    305      */
    306 
    307     /* Calculate size of return buffer */
    308     if (pythonhome != NULL) {
    309         char *p;
    310         bufsz = 1;
    311         for (p = PYTHONPATH; *p; p++) {
    312             if (*p == DELIM)
    313                 bufsz++; /* number of DELIM plus one */
    314         }
    315         bufsz *= strlen(pythonhome);
    316     }
    317     else
    318         bufsz = 0;
    319     bufsz += strlen(PYTHONPATH) + 1;
    320     bufsz += strlen(argv0_path) + 1;
    321     bufsz += strlen(zip_path) + 1;
    322     if (envpath != NULL)
    323         bufsz += strlen(envpath) + 1;
    324 
    325     module_search_path = buf = malloc(bufsz);
    326     if (buf == NULL) {
    327         /* We can't exit, so print a warning and limp along */
    328         fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
    329         if (envpath) {
    330             fprintf(stderr, "Using environment $PYTHONPATH.\n");
    331             module_search_path = envpath;
    332         }
    333         else {
    334             fprintf(stderr, "Using default static path.\n");
    335             module_search_path = PYTHONPATH;
    336         }
    337         return;
    338     }
    339 
    340     if (envpath) {
    341         strcpy(buf, envpath);
    342         buf = strchr(buf, '\0');
    343         *buf++ = DELIM;
    344     }
    345     if (zip_path[0]) {
    346         strcpy(buf, zip_path);
    347         buf = strchr(buf, '\0');
    348         *buf++ = DELIM;
    349     }
    350 
    351     if (pythonhome == NULL) {
    352         strcpy(buf, PYTHONPATH);
    353         buf = strchr(buf, '\0');
    354     }
    355     else {
    356         char *p = PYTHONPATH;
    357         char *q;
    358         size_t n;
    359         for (;;) {
    360             q = strchr(p, DELIM);
    361             if (q == NULL)
    362                 n = strlen(p);
    363             else
    364                 n = q-p;
    365             if (p[0] == '.' && is_sep(p[1])) {
    366                 strcpy(buf, pythonhome);
    367                 buf = strchr(buf, '\0');
    368                 p++;
    369                 n--;
    370             }
    371             strncpy(buf, p, n);
    372             buf += n;
    373             if (q == NULL)
    374                 break;
    375             *buf++ = DELIM;
    376             p = q+1;
    377         }
    378     }
    379     if (argv0_path) {
    380         *buf++ = DELIM;
    381         strcpy(buf, argv0_path);
    382         buf = strchr(buf, '\0');
    383     }
    384     *buf = '\0';
    385 }
    386 
    387 
    388 /* External interface */
    389 
    390 char *
    391 Py_GetPath(void)
    392 {
    393     if (!module_search_path)
    394         calculate_path();
    395     return module_search_path;
    396 }
    397 
    398 char *
    399 Py_GetPrefix(void)
    400 {
    401     if (!module_search_path)
    402         calculate_path();
    403     return prefix;
    404 }
    405 
    406 char *
    407 Py_GetExecPrefix(void)
    408 {
    409     return Py_GetPrefix();
    410 }
    411 
    412 char *
    413 Py_GetProgramFullPath(void)
    414 {
    415     if (!module_search_path)
    416         calculate_path();
    417     return progpath;
    418 }
    419