Changeset 3903


Ignore:
Timestamp:
Oct 23, 2014, 10:26:55 PM (11 years ago)
Author:
bird
Message:

0.6: Safer and more generic _path and _searchenv functions, making the spawn code use for locating executables in a more flexible manner. Unix style search PATH separators are now honored. Fixes #180 and #308.

Location:
branches/libc-0.6/src/emx
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • branches/libc-0.6/src/emx/include/stdlib.h

    r3809 r3903  
    462462    const char *, const char *);
    463463int _path (char *, const char *);
     464int _path2(const char *pszName, const char *pszSuffixes, char *pszDst, size_t cbDst);
    464465int _read_kbd (int, int, int);
    465466void _remext (char *);
     
    468469void _scrsize (int *);
    469470void _searchenv (const char *, const char *, char *);
     471int _searchenv2(const char *pszEnvVar, const char *pszName, unsigned fFlags, const char *pszSuffixes,
     472                char *pszDst, size_t cbDst);
     473int _searchenv2_value(const char *pszSearchPath, const char *pszName, unsigned fFlags, const char *pszSuffixes,
     474                      char *pszDst, size_t cbDst);
     475int _searchenv2_has_suffix(const char *pszName, size_t cchName, const char *pszSuffixes);
     476int _searchenv2_one_file(char *pszDst, size_t cbDst, size_t cchName, unsigned fFlags, const char *pszSuffixes);
     477/** @name _SEARCHENV2_F_XXX - Flags for _searchenv2(), _searchenv2_value()
     478 *                            and _searchenv2_one_file().
     479 * @{ */
     480/** Indicates that we're searching for an executable file. */
     481#define _SEARCHENV2_F_EXEC_FILE     1
     482/** Indicates that we shouldn't explicitly check the current directory before
     483 * searching the search path. */
     484#define _SEARCHENV2_F_SKIP_CURDIR   2
     485/** @} */
     486
    470487void _sfnlwr (const char *);
    471488unsigned _sleep2 (unsigned);
  • branches/libc-0.6/src/emx/include/sys/cdefs.h

    r3738 r3903  
    627627#include <sys/gnu/cdefs.h>
    628628
     629/* bird: kLIBC specifics - start */
     630/** @def __KLIBC_PATH_SLASH
     631 * The default slash character (path component separator). */
     632/** @def __KLIBC_PATH_SLASH_ALT
     633 * Alternative slash character (path component separator). Optional. */
     634/** @def __KLIBC_PATH_HAVE_DRIVE_LETTERS
     635 * Defined if we have driver letters on this platform. */
     636/** @def __KLIBC_PATH_HAVE_DRIVES
     637 * Defined if we have UNC paths on this platform. */
     638#if defined(__OS2__) || defined(_WIN32) || defined(_WIN64) || defined(__NT__)
     639# define __KLIBC_PATH_SLASH         '\\'
     640# define __KLIBC_PATH_SLASH_ALT     '/'
     641# define __KLIBC_PATH_HAVE_DRIVE_LETTERS   1
     642# define __KLIBC_PATH_HAVE_UNC      1
     643#else
     644# define __KLIBC_PATH_SLASH         '/'
     645# undef  __KLIBC_PATH_SLASH_ALT
     646# undef  __KLIBC_PATH_HAVE_DRIVE_LETTERS
     647# undef  __KLIBC_PATH_HAVE_UNC
     648#endif
     649/** @def __KLIBC_PATH_IS_SLASH
     650 * Checks if @a a_ch is a slash character.
     651 * @param a_ch      The character. */
     652#ifdef __KLIBC_PATH_SLASH_ALT
     653# define __KLIBC_PATH_IS_SLASH(a_ch)    ((a_ch) == __KLIBC_PATH_SLASH || (a_ch) == __KLIBC_PATH_SLASH_ALT)
     654#else
     655# define __KLIBC_PATH_IS_SLASH(a_ch)    ((a_ch) == __KLIBC_PATH_SLASH)
     656#endif
     657/* bird: kLIBC specifics - end */
     658
    629659#endif /* !_SYS_CDEFS_H_ */
  • branches/libc-0.6/src/emx/src/lib/emxload/emxloadp.c

    r251 r3903  
    1010int _emxload_prog (const char *name, int seconds)
    1111{
    12   char buf1[MAXPATHLEN];
    1312  char buf2[MAXPATHLEN];
    1413
    1514  if (seconds != _EMXLOAD_INDEFINITE && seconds < 0)
    1615    return -1;
    17   _strncpy (buf1, name, sizeof (buf1));
    18   _defext (buf1, "exe");
    19   if (_path (buf2, buf1) != 0 || _abspath (buf2, buf2, sizeof (buf2)) != 0)
     16  if (   _path2 (name, ".exe", buf2, sizeof (buf2)) != 0
     17      || _abspath (buf2, buf2, sizeof (buf2)) != 0)
    2018    return -1;
    2119  return _emxload_request (_EMXLOAD_LOAD, buf2, seconds);
  • branches/libc-0.6/src/emx/src/lib/libc.def

    r3859 r3903  
    19671967    "___libc_Back_fsSymlinkOwnerSet" @1963
    19681968    "___libc_Back_processGetDefaultShell" @1964
    1969    
     1969    "__path2" @1965
     1970    "__searchenv2" @1966
     1971    "__searchenv2_has_suffix" @1967
     1972    "__searchenv2_one_file" @1968
     1973    "__searchenv2_value" @1969
     1974
  • branches/libc-0.6/src/emx/src/lib/misc/path.c

    r236 r3903  
    1 /* path.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
     1/* $Id: cabsl.c 3889 2014-06-28 16:06:20Z bird $ */
     2/** @file
     3 * kLibC - Implementation of _path() and _path2().
     4 *
     5 * @copyright   Copyright (C) 2014 knut st. osmundsen <bird-klibc-spam-xiv@anduin.net>
     6 * @licenses    MIT, BSD2, BSD3, BSD4, LGPLv2.1, LGPLv3, LGPLvFuture.
     7 */
    28
     9
     10/*******************************************************************************
     11* Header Files                                                                 *
     12*******************************************************************************/
    313#include "libc-alias.h"
     14#include <string.h>
    415#include <stdlib.h>
    5 #include <string.h>
    6 #include <io.h>
    716#include <errno.h>
     17#include <sys/cdefs.h>
     18#include <sys/syslimits.h>
    819
    9 int _path (char *dst, const char *name)
     20
     21/**
     22 * Find an executable file using the PATH variables.
     23 *
     24 * If the specified filename includes a volume or/and a path, the environment
     25 * variables will not be searched.  Instead the file name is taken as it is and
     26 * checked whether it is a file we can execute.
     27 *
     28 * If no volume or path is specified in the filename, the EMXPATH and PATH
     29 * environment variables will be searched.
     30 *
     31 * @returns 0 on success, -1 and errno (ENOENT, EISDIR, EINVAL, EOVERFLOW) on
     32 *          failure.
     33 * @param   pszName     The file to search for.
     34 * @param   pszSuffixes Semicolon separated list of suffixes to append to
     35 *                      the filename while searching.  Only done if the
     36 *                      specified filename does not already end with one of the
     37 *                      specified extensions.  Pass NULL to skip this feature.
     38 * @param   pszDst      Where to store the result if found.  This may be used
     39 *                      for temporary buffering while searching.  It will be an
     40 *                      empty string on failure.
     41 * @param   cbDst       The size of the destination buffer.
     42 *
     43 * @since   kLIBC v0.6.6
     44 */
     45int _path2(const char *pszName, const char *pszSuffixes, char *pszDst, size_t cbDst)
    1046{
    11   if (strpbrk (name, "/\\:") != NULL)
     47    int rc;
     48
     49    /*
     50     * Validate the input.
     51     */
     52    if (   cbDst > 1
     53        && pszDst
     54        && (!pszSuffixes || *pszSuffixes)
     55        && pszName)
    1256    {
    13       if (access (name, 4) == 0)
    14         strcpy (dst, name);
    15       else
    16         dst[0] = 0;
     57        /*
     58         * Path or volume specified?
     59         */
     60        size_t cchName = strlen(pszName);
     61        if (   memchr(pszName, __KLIBC_PATH_SLASH, cchName) != NULL
     62#ifdef __KLIBC_PATH_SLASH_ALT
     63            || memchr(pszName, __KLIBC_PATH_SLASH_ALT,  cchName) != NULL
     64#endif
     65#ifdef __KLIBC_PATH_HAVE_DRIVE_LETTERS
     66            || (cchName >= 2 && pszName[1] == ':')
     67#endif
     68           )
     69        {
     70            if (cchName < cbDst)
     71            {
     72                memcpy(pszDst, pszName, cchName + 1);
     73                rc = _searchenv2_one_file(pszDst, cbDst, cchName, _SEARCHENV2_F_EXEC_FILE,
     74                                          _searchenv2_has_suffix(pszName, cchName, pszSuffixes) ? NULL : pszSuffixes);
     75            }
     76            else
     77            {
     78                errno = EOVERFLOW;
     79                rc = -1;
     80            }
     81        }
     82        /*
     83         * No path or volume, search the environment variables.
     84         */
     85        else
     86        {
     87            rc = _searchenv2("EMXPATH", pszName, _SEARCHENV2_F_EXEC_FILE, pszSuffixes, pszDst, cbDst);
     88            if (rc == -1 && errno == ENOENT)
     89                rc = _searchenv2("PATH", pszName, _SEARCHENV2_F_EXEC_FILE | _SEARCHENV2_F_SKIP_CURDIR,
     90                                 pszSuffixes, pszDst, cbDst);
     91        }
    1792    }
    18   else
     93    else
    1994    {
    20       _searchenv (name, "EMXPATH", dst);
    21       if (dst[0] == 0)
    22         _searchenv (name, "PATH", dst);
     95        errno = EINVAL;
     96        rc = -1;
    2397    }
    24   if (dst[0] == 0)
    25     {
    26       errno = ENOENT;
    27       return -1;
    28     }
    29   return 0;
     98    return rc;
    3099}
     100
     101
     102/**
     103 * Find an executable file using the PATH variables (insane version).
     104 *
     105 * If the specified filename includes a volume or/and a path, the environment
     106 * variables will not be searched.  Instead the file name is taken as it is and
     107 * checked whether it is a file we can execute.
     108 *
     109 * If no volume or path is specified in the filename, the EMXPATH and PATH
     110 * environment variables will be searched.
     111 *
     112 * @returns 0 on success, -1 and errno (ENOENT, EISDIR, EOVERFLOW) on failure.
     113 * @param   pszDst      Where to store the result if found.  This may be used
     114 *                      for temporary buffering while searching.  It will be an
     115 *                      empty string on failure.  The length of the buffer is
     116 *                      assumed to be at least PATH_MAX.
     117 * @param   pszName     The file to search for.
     118 *
     119 * @since   The _path() function seems to be EMX specific.
     120 */
     121int _path(char *pszDst, const char *pszName)
     122{
     123    return _path2(pszName, NULL /*pszSuffixes*/, pszDst, PATH_MAX);
     124}
     125
  • branches/libc-0.6/src/emx/src/lib/misc/searchen.c

    r236 r3903  
    1 /* searchen.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
    2 
     1/* $Id: cabsl.c 3889 2014-06-28 16:06:20Z bird $ */
     2/** @file
     3 * kLibC - Implementation of _searchenv() and _searchenv2().
     4 *
     5 * @copyright   Copyright (C) 2014 knut st. osmundsen <bird-klibc-spam-xiv@anduin.net>
     6 * @licenses    MIT, BSD2, BSD3, BSD4, LGPLv2.1, LGPLv3, LGPLvFuture.
     7 */
     8
     9
     10/*******************************************************************************
     11* Header Files                                                                 *
     12*******************************************************************************/
    313#include "libc-alias.h"
     14#include <ctype.h>
     15#include <errno.h>
    416#include <stdlib.h>
    517#include <string.h>
    6 #include <io.h>
     18#include <unistd.h>
    719#include <emx/io.h>
    8 
    9 void _searchenv (const char *file, const char *var, char *path)
     20#include <sys/cdefs.h>
     21#include <sys/fcntl.h>
     22#include <sys/syslimits.h>
     23
     24
     25/**
     26 * Worker for _searchenv2_value() and _path2() that looks for a file in the
     27 * given path.
     28 *
     29 * @returns 0 on success. -1 is returned on failure together with errno and an
     30 *          empty string in @a pszDst (if possible).
     31 * @errno   ENOENT if not found
     32 * @errno   EISDIR if found but is directory or special file.
     33 * @errno   EOVERFLOW if any of the suffix combinations caused us to overlow
     34 *          (lower priority than EISDIR).
     35 *
     36 * @param   pszDst              The input / output buffer.  This contains a
     37 *                              filename of length @a cchName on input.  This
     38 *                              filename may have a suffix from @a pszSuffixes
     39 *                              appended on successful return.  On failure, it
     40 *                              will be set to an empty string (if there is room
     41 *                              for it).
     42 * @param   cbDst               The size of the buffer @a pszDst points to.
     43 * @param   cchName             The length of the incoming name.
     44 * @param   fFlags              The search flags, see _SEARCHENV2_F_XXX.
     45 * @param   pszSuffixes         Semicolon separated list of suffixes to append
     46 *                              to the filename.  Pass NULL if no suffixes
     47 *                              should be appended.
     48 *
     49 * @remarks The caller is expected to have used _searchenv2_has_suffix() to
     50 *          check if the input filename already has an extension.
     51 *
     52 * @since   kLIBC v0.6.6
     53 */
     54int _searchenv2_one_file(char *pszDst, size_t cbDst, size_t cchName, unsigned fFlags, const char *pszSuffixes)
    1055{
    11   char *list, *end;
    12   int i;
    13  
    14   strcpy (path, file);
    15   if (access (path, 4) == 0)
    16     return;
    17   list = getenv (var);
    18   if (list != NULL)
    19     for (;;)
    20       {
    21         while (*list == ' ' || *list == '\t') ++list;
    22         if (*list == 0) break;
    23         end = list;
    24         while (*end != 0 && *end != ';') ++end;
    25         i = end - list;
    26         while (i>0 && (list[i-1] == ' ' || list[i-1] == '\t')) --i;
    27         if (i != 0)
    28           {
    29             memcpy (path, list, i);
    30             if (!_trslash (list, i, 0))
    31               path[i++] = '\\';
    32             strcpy (path+i, file);
    33             if (access (path, 4) == 0)
    34               return;
    35           }
    36         if (*end == 0) break;
    37         list = end + 1;
    38       }
    39   path[0] = 0;
     56    int rc;
     57    if (   cchName > 0
     58        && cchName < cbDst)
     59    {
     60        int iRetErrno = ENOENT;
     61        for (;;)
     62        {
     63            /*
     64             * Check the accesss, making sure it's a regular file (no
     65             * directories or other weird files).
     66             */
     67            if (_STD(eaccess)(pszDst, fFlags & _SEARCHENV2_F_EXEC_FILE ? X_OK : R_OK) == 0)
     68            {
     69                struct stat St;
     70                rc = _STD(stat)(pszDst, &St);
     71                if (rc == 0 && S_ISREG(St.st_mode))
     72                    return 0;
     73                iRetErrno = EISDIR;
     74            }
     75
     76            /*
     77             * Try another suffix?
     78             */
     79            if (!pszSuffixes)
     80                break;
     81
     82            /* Find start and end of the next suffix (if there is one). */
     83            while (*pszSuffixes == ';')
     84                pszSuffixes++;
     85            if (!*pszSuffixes)
     86                break;
     87            const char *pszEnd = pszSuffixes;
     88            while (*pszEnd && *pszEnd != ';')
     89                pszEnd++;
     90
     91            /* Alter the filename. */
     92            size_t cchSuffix = pszEnd - pszSuffixes;
     93            if (cchSuffix + cchName < cbDst)
     94            {
     95                _STD(memcpy)(&pszDst[cchName], pszSuffixes, cchSuffix);
     96                pszDst[cchName + cchSuffix] = '\0';
     97            }
     98            /* Lazy bird: Retry with the same file name on overflow. */
     99            else if (iRetErrno == ENOENT)
     100                iRetErrno = EOVERFLOW;
     101
     102            /* Advance suffixes. */
     103            pszSuffixes = pszEnd;
     104        }
     105
     106        /* Failed. */
     107        *pszDst = '\0';
     108        errno = iRetErrno;
     109        rc = -1;
     110    }
     111    else
     112    {
     113        if (cbDst > 0 && pszDst)
     114            *pszDst = '\0';
     115        errno = ENOENT;
     116        rc = -1;
     117    }
     118
     119    return rc;
    40120}
     121
     122
     123/**
     124 * Checks if @a pszName already has a suffix from the @a pszSuffix list.
     125 *
     126 * @returns 1 if it has a suffix from the list, 0 if not.
     127 *
     128 * @param   pszName             The filename name.
     129 * @param   cchName             The length of the name.
     130 * @param   pszSuffixes         The semicolon separated list of suffixes.  Can
     131 *                              be NULL.
     132 * @since   kLIBC v0.6.6
     133 */
     134int _searchenv2_has_suffix(const char *pszName, size_t cchName, const char *pszSuffixes)
     135{
     136    /*
     137     * Enumerate the suffix list (if we have one).
     138     */
     139    if (pszSuffixes)
     140    {
     141        for (;;)
     142        {
     143            /*
     144             * Find the start and end of the next suffix.
     145             */
     146            while (*pszSuffixes == ';')
     147                pszSuffixes++;
     148            if (!*pszSuffixes)
     149                break;
     150
     151            const char *pszEnd = pszSuffixes;
     152            char ch;
     153            while ((ch = *pszEnd) != '\0' && ch != ';')
     154                pszEnd++;
     155
     156            /*
     157             * Check if the filename has this suffix.
     158             */
     159            size_t cchSuffix = pszEnd - pszSuffixes;
     160            if (   cchSuffix < cchName
     161                && _STD(strnicmp)(pszName + cchName - cchSuffix, pszSuffixes, cchSuffix) == 0)
     162            {
     163                /** @todo check that we didn't barge into a multibyte sequence! */
     164                return 1;
     165            }
     166
     167            /*
     168             * Next.
     169             */
     170            pszSuffixes = pszEnd;
     171        }
     172    }
     173    return 0;
     174}
     175
     176
     177/**
     178 * Search for a file (@a pszName) using an search path (@a pszSearchPath) and
     179 * optionally a list of suffixes.
     180 *
     181 * The search will first check the @a pszName without any path prepended, unless
     182 * _SEARCHENV2_F_SKIP_CURDIR is specified.  Then environment variable value will
     183 * be taken, split up into a list of paths on semicolon and colon (except drive
     184 * letters of course) boundraries, and each path is checked out individually in
     185 * the order they appear.
     186 *
     187 * @returns 0 on success. On failure -1 is returned together with errno and an
     188 *          empty return string.
     189 * @errno   EINVAL if @a pszName or @a pszDst is NULL.
     190 * @errno   ENOENT if not found or if @a pszName is an empty string.
     191 * @errno   EOVERFLOW if pszName and any suffix is longer than the buffer.
     192 *
     193 * @param   pszSearchPath       The search path.
     194 * @param   pszName             The name of the file we're searching for.
     195 * @param   fFlags              Search flags, see _SEARCHENV2_F_XXX.
     196 * @param   pszSuffixes         Semicolon separated list of suffixes to append
     197 *                              to @a pszName while searching.  If @a pszName
     198 *                              already include one of the suffixes in this list
     199 *                              (case insensitive check), no suffixes will be
     200 *                              appended.  Pass NULL to use @a pszName as it is.
     201 * @param   pszDst              Where to store the filename we find, set to empty string
     202 *                              if not found (errno set).
     203 * @param   cbDst               The size of the buffer @a pszDst points to.
     204 *
     205 *
     206 * @sa      _searchenv2()
     207 *
     208 * @since   kLIBC v0.6.6
     209 */
     210int _searchenv2_value(const char *pszSearchPath, const char *pszName, unsigned fFlags, const char *pszSuffixes,
     211                      char *pszDst, size_t cbDst)
     212{
     213    int rc;
     214
     215    /*
     216     * Validate input.
     217     */
     218    if (   pszName
     219        && *pszName
     220        && (!pszSuffixes || *pszSuffixes)
     221        && pszDst
     222        && cbDst > 0)
     223    {
     224        /*
     225         * If the filename already is using one of the specified suffixes, drop
     226         * the suffix search.  Quicker doing this up front than for each search
     227         * path member.
     228         */
     229        size_t const cchName = _STD(strlen)(pszName);
     230        if (_searchenv2_has_suffix(pszName, cchName, pszSuffixes))
     231            pszSuffixes = NULL;
     232
     233        /*
     234         * First try the file directly.  If it overflows, we won't bother
     235         * trying the search path since it'll just construct even longer names.
     236         */
     237        if (cchName < cbDst)
     238        {
     239            if (!(fFlags & _SEARCHENV2_F_SKIP_CURDIR))
     240            {
     241                _STD(memcpy)(pszDst, pszName, cchName + 1);
     242                rc = _searchenv2_one_file(pszDst, cbDst, cchName, fFlags, pszSuffixes);
     243            }
     244            else
     245            {
     246                errno = ENOENT;
     247                rc = -1;
     248            }
     249            if (   rc == -1
     250                && errno != EOVERFLOW
     251                && pszSearchPath)
     252            {
     253                /*
     254                 * Work the search path.  We respect both ';' and ':' as
     255                 * separators here.
     256                 */
     257                for (;;)
     258                {
     259                    /*
     260                     * Skip leading spaces and empty paths (we've already checked without
     261                     * a path above and if the caller used _SEARCHENV2_F_SKIP_CURDIR, we're
     262                     * still doing the correct thing as such).
     263                     */
     264                    char ch;
     265                    while (   (ch = *pszSearchPath) == ';'
     266                           || ch == ':'
     267                           || isblank(ch))
     268                        pszSearchPath++;
     269                    if (!ch)
     270                        break;
     271
     272                    /*
     273                     * Find the end of the current path, using both colon (unix) and
     274                     * semicolon (DOS) as separators.
     275                     *
     276                     * The first char will not be a separator. With the second character
     277                     * we have to be careful with colon on platforms with drive letters.
     278                     */
     279                    const char *pszStart = pszSearchPath;
     280                    const char *pszEnd = ++pszSearchPath;
     281                    ch = *pszSearchPath;
     282                    if (   ch != '\0'
     283                        && ch != ';'
     284#ifdef __KLIBC_PATH_HAVE_DRIVE_LETTERS
     285                        && (ch != ':' || isalpha(*pszStart))
     286#else
     287                        && ch != ':'
     288#endif
     289                       )
     290                    {
     291                        do
     292                            pszSearchPath++;
     293                        while ((ch = *pszSearchPath) != '\0' && ch != ';' && ch != ':');
     294                        pszEnd = pszSearchPath;
     295
     296                        /* Strip trailing blanks. */
     297                        while ((uintptr_t)pszEnd > (uintptr_t)pszStart && isblank(pszEnd[-1]))
     298                            pszEnd--;
     299                    }
     300
     301                    /*
     302                     * Try construct a new name.
     303                     */
     304                    size_t cchPath  = pszEnd - pszStart;
     305                    int    cchSlash = _trslash(pszStart, cchPath, 0) == 0;
     306                    if (cchPath + cchSlash + cchName < cbDst)
     307                    {
     308                        _STD(memcpy)(pszDst, pszStart, cchPath);
     309                        if (cchSlash)
     310                            pszDst[cchPath++] = __KLIBC_PATH_SLASH;
     311                        _STD(memcpy)(&pszDst[cchPath], pszName, cchName + 1);
     312
     313                        /*
     314                         * Test the filename + suffixes.
     315                         */
     316                        rc = _searchenv2_one_file(pszDst, cbDst, cchPath + cchName, fFlags, pszSuffixes);
     317                        if (!rc)
     318                            return rc;
     319                    }
     320                    /* else: we overflowed - ignore. */
     321                }
     322
     323                /* Not found.  We ignore EOVERFLOW and EISDIR errors here. */
     324                *pszDst = '\0';
     325                errno = ENOENT;
     326                rc = -1;
     327            }
     328            /* else: maybe we found it, maybe we overflowed. */
     329        }
     330        else
     331        {
     332            /* Buffer too small for the name. */
     333            *pszDst = '\0';
     334            errno = EOVERFLOW;
     335            rc = -1;
     336        }
     337    }
     338    else
     339    {
     340        /* Invalid parameter(s). */
     341        if (cbDst > 0 && pszDst)
     342            *pszDst = '\0';
     343        errno = pszName && !*pszName ? ENOENT : EINVAL;
     344        rc = -1;
     345    }
     346    return rc;
     347}
     348
     349
     350/**
     351 * Search for a file (@a pszName) using an environment variable (@a pszEnvVar)
     352 * and optionally a list of suffixes.
     353 *
     354 * The search will first check the @a pszName without any path prepended, unless
     355 * _SEARCHENV2_F_SKIP_CURDIR is specified.  Then environment variable value will
     356 * be taken, split up into a list of paths on semicolon and colon (except drive
     357 * letters of course) boundraries, and each path is checked out individually in
     358 * the order they appear.
     359 *
     360 * @returns 0 on success. On failure -1 is returned together with errno and an
     361 *          empty return string.
     362 * @errno   EINVAL if @a pszName or @a pszDst is NULL.
     363 * @errno   ENOENT if not found or if @a pszName is an empty string.
     364 * @errno   EOVERFLOW if pszName and any suffix is longer than the buffer.
     365 *
     366 * @param   pszEnvVar           The environment variable.
     367 * @param   pszName             The name of the file we're searching for.
     368 * @param   fFlags              Search flags, see _SEARCHENV2_F_XXX.
     369 * @param   pszSuffixes         Semicolon separated list of suffixes to append
     370 *                              to @a pszName while searching.  If @a pszName
     371 *                              already include one of the suffixes in this list
     372 *                              (case insensitive check), no suffixes will be
     373 *                              appended.  Pass NULL to use @a pszName as it is.
     374 * @param   pszDst              Where to store the filename we find, set to empty string
     375 *                              if not found (errno set).
     376 * @param   cbDst               The size of the buffer @a pszDst points to.
     377 *
     378 * @sa      _searchenv2_value()
     379 * @since   kLIBC v0.6.6
     380 */
     381int _searchenv2(const char *pszEnvVar, const char *pszName, unsigned fFlags, const char *pszSuffixes,
     382                 char *pszDst, size_t cbDst)
     383{
     384    return _searchenv2_value(_STD(getenv)(pszEnvVar), pszName, fFlags, pszSuffixes, pszDst, cbDst);
     385}
     386
     387
     388/**
     389 * Search for a file (@a pszName) using an environment variable (@a pszEnvVar),
     390 * insane version.
     391 *
     392 * @errno   EINVAL if @a pszName or @a pszDst is NULL.
     393 * @errno   ENOENT if not found or if @a pszName is an empty string.
     394 * @errno   EOVERFLOW if pszName and any suffix is longer than the buffer.
     395 *
     396 * @param   pszName     The name of the file we're searching for.
     397 * @param   pszEnvVar   The environment variable name.
     398 * @param   pszDst      Where to store the filename we find, set to empty string
     399 *                      if not found (errno set). This buffer must be able to
     400 *                      hold PATH_MAX chars (including the string terminator).
     401 *
     402 * @sa      _searchenv2(), _searchenv2_value()
     403 *
     404 * @since   The _searchenv() also exists in the microsoft runtime library and
     405 *          probably from the DOS days common to both OS/2 and windows
     406 *          compilers.
     407 */
     408void _searchenv(const char *pszName, const char *pszEnvVar, char *pszDst)
     409{
     410    _searchenv2(pszEnvVar, pszName, _SEARCHENV2_F_EXEC_FILE, NULL /*pszSuffixes*/, pszDst, PATH_MAX);
     411}
     412
  • branches/libc-0.6/src/emx/src/lib/process/spawnvpe.c

    r2254 r3903  
    1 /* spawnvpe.c (emx+gcc) -- Copyright (c) 1990-1996 by Eberhard Mattes */
     1/* $Id: cabsl.c 3889 2014-06-28 16:06:20Z bird $ */
     2/** @file
     3 * kLibC - Implementation of spawnvpe().
     4 *
     5 * @copyright   Copyright (C) 2014 knut st. osmundsen <bird-klibc-spam-xiv@anduin.net>
     6 * @licenses    MIT, BSD2, BSD3, BSD4, LGPLv2.1, LGPLv3, LGPLvFuture.
     7 */
    28
     9
     10/*******************************************************************************
     11* Header Files                                                                 *
     12*******************************************************************************/
     13#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_PROCESS
    314#include "libc-alias.h"
     15#include <InnoTekLIBC/logstrict.h>
    416#include <stdlib.h>
    517#include <process.h>
    6 #include <string.h>
    7 #include <errno.h>
    818#include <sys/syslimits.h>
    9 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_PROCESS
    10 #include <InnoTekLIBC/logstrict.h>
    1119
    12 int _STD(spawnvpe)(int mode, const char *name, char * const argv[], char * const envp[])
     20
     21int _STD(spawnvpe)(int fMode, const char *pszName, char * const *papszArgs, char * const *papszEnv)
    1322{
    14     LIBCLOG_ENTER("mode=%#x name=%s argv=%p envp=%p\n", mode, name, argv, envp);
    15     char    exe[PATH_MAX];
    16     char    path[PATH_MAX];
    17     int     rc;
     23    LIBCLOG_ENTER("fMode=%#x pszName=%s papszArgs=%p papszEnv=%p\n", fMode, pszName, papszArgs, papszEnv);
     24    char szResolvedName[PATH_MAX];
     25    if (_path2(pszName, ".exe", szResolvedName, sizeof(szResolvedName)) == 0)
     26    {
     27        int rc = spawnve(fMode, szResolvedName, papszArgs, papszEnv);
     28        LIBCLOG_MIX_RETURN_INT(rc);
     29    }
     30    LIBCLOG_ERROR_RETURN_INT(-1);
     31}
    1832
    19     if (strlen(name) >= sizeof(exe) - 4)
    20     {
    21         errno = ENAMETOOLONG;
    22         LIBCLOG_ERROR_RETURN(-1, "ret -1 - name is too long, %d bytes: %s\n", strlen(name), name);
    23     }
    24     strcpy(exe, name);
    25     _defext(exe, "exe");
    26     if (_path(path, exe))
    27         LIBCLOG_ERROR_RETURN_INT(-1);
    28     rc = spawnve(mode, path, argv, envp);
    29     LIBCLOG_RETURN_INT(rc);
    30 }
  • branches/libc-0.6/src/emx/src/lib/sys/__spawnve.c

    r3784 r3903  
    543543                /*
    544544                 * Resolve the interpreter name.
    545                  * If the specified name fails, we'll try search the path for it and
    546                  * also adding an .exe extension before we give up.
    547                  * We omit any specified path since we're frequently faced with path
    548                  * differences between OS/2 and the UNIX where the script originated.
     545                 * Try the unchanged name first, then the name with .exe suffix,
     546                 * then the PATH.  In the latter case we skip the directory path
     547                 * if given, since we're frequently faced with path differences
     548                 * between OS/2 and the UNIX where the script originated.
    549549                 */
    550550                rc = __libc_back_fsResolve(pszInterpreter, BACKFS_FLAGS_RESOLVE_FULL, &szNativePath[0], NULL);
    551551                if (rc)
    552552                {
    553                     psz = _getname(pszInterpreter);
    554                     char szPath[512];
    555                     _searchenv(psz, "PATH", szPath); /** @todo _searchenv is not safe, it can easily overflow szPath! */
    556                     if (!szPath[0])
    557                     {
    558                         cch = strlen(psz);
    559                         memcpy(szNativePath, psz, cch + 1);
    560                         _defext(szNativePath, "exe");
    561                         if (szNativePath[cch])
    562                             _searchenv(szNativePath, "PATH", szPath);
    563                     }
    564                     if (szPath[0])
     553                    char szPath[PATH_MAX];
     554                    if (   _path2(pszInterpreter, ".exe", szPath, sizeof(szPath)) == 0
     555                        || (   (psz = _getname(pszInterpreter)) != pszInterpreter
     556                            && _path2(psz, ".exe", szPath, sizeof(szPath)) == 0) )
    565557                        rc = __libc_back_fsResolve(szPath, BACKFS_FLAGS_RESOLVE_FULL, &szNativePath[0], NULL);
    566558                    if (rc)
Note: See TracChangeset for help on using the changeset viewer.