Esempio n. 1
0
/*=export_func  optionMakePath
 * private:
 *
 * what:  translate and construct a path
 * arg:   + char*       + pzBuf      + The result buffer +
 * arg:   + int         + bufSize    + The size of this buffer +
 * arg:   + char const* + pzName     + The input name +
 * arg:   + char const* + pzProgPath + The full path of the current program +
 *
 * ret-type: ag_bool
 * ret-desc: AG_TRUE if the name was handled, otherwise AG_FALSE.
 *           If the name does not start with ``$'', then it is handled
 *           simply by copying the input name to the output buffer and
 *           resolving the name with either @code{canonicalize_file_name(3GLIBC)}
 *           or @code{realpath(3C)}.
 *
 * doc:
 *
 *  This routine will copy the @code{pzName} input name into the @code{pzBuf}
 *  output buffer, carefully not exceeding @code{bufSize} bytes.  If the
 *  first character of the input name is a @code{'$'} character, then there
 *  is special handling:
 *  @*
 *  @code{$$} is replaced with the directory name of the @code{pzProgPath},
 *  searching @code{$PATH} if necessary.
 *  @*
 *  @code{$@} is replaced with the AutoGen package data installation directory
 *  (aka @code{pkgdatadir}).
 *  @*
 *  @code{$NAME} is replaced by the contents of the @code{NAME} environment
 *  variable.  If not found, the search fails.
 *
 *  Please note: both @code{$$} and @code{$NAME} must be at the start of the
 *     @code{pzName} string and must either be the entire string or be followed
 *     by the @code{'/'} (backslash on windows) character.
 *
 * err:  @code{AG_FALSE} is returned if:
 *       @*
 *       @bullet{} The input name exceeds @code{bufSize} bytes.
 *       @*
 *       @bullet{} @code{$$}, @code{$@@} or @code{$NAME} is not the full string
 *                 and the next character is not '/'.
 *       @*
 *       @bullet{} libopts was built without PKGDATADIR defined and @code{$@@}
 *                 was specified.
 *       @*
 *       @bullet{} @code{NAME} is not a known environment variable
 *       @*
 *       @bullet{} @code{canonicalize_file_name} or @code{realpath} return
 *                 errors (cannot resolve the resulting path).
=*/
ag_bool
optionMakePath(
    char*   pzBuf,
    int     bufSize,
    tCC*    pzName,
    tCC*    pzProgPath )
{
    size_t  name_len = strlen( pzName );

#   ifndef PKGDATADIR
#     define PKGDATADIR ""
#   endif

    tSCC    pkgdatadir[] = PKGDATADIR;

    ag_bool res = AG_TRUE;

    if (bufSize <= name_len)
        return AG_FALSE;

    /*
     *  IF not an environment variable, just copy the data
     */
    if (*pzName != '$') {
        tCC*  pzS = pzName;
        char* pzD = pzBuf;
        int   ct  = bufSize;

        for (;;) {
            if ( (*(pzD++) = *(pzS++)) == NUL)
                break;
            if (--ct <= 0)
                return AG_FALSE;
        }
    }

    /*
     *  IF the name starts with "$$", then it must be "$$" or
     *  it must start with "$$/".  In either event, replace the "$$"
     *  with the path to the executable and append a "/" character.
     */
    else switch (pzName[1]) {
    case NUL:
        return AG_FALSE;

    case '$':
        res = insertProgramPath( pzBuf, bufSize, pzName, pzProgPath );
        break;

    case '@':
        if (pkgdatadir[0] == NUL)
            return AG_FALSE;

        if (name_len + sizeof (pkgdatadir) > bufSize)
            return AG_FALSE;

        strcpy(pzBuf, pkgdatadir);
        strcpy(pzBuf + sizeof(pkgdatadir) - 1, pzName + 2);
        break;

    default:
        res = insertEnvVal( pzBuf, bufSize, pzName, pzProgPath );
    }

    if (! res)
        return AG_FALSE;

#if defined(HAVE_CANONICALIZE_FILE_NAME)
    {
        char* pz = canonicalize_file_name(pzBuf);
        if (pz == NULL)
            return AG_FALSE;
        if (strlen(pz) < bufSize)
            strcpy(pzBuf, pz);
        free(pz);
    }

#elif defined(HAVE_REALPATH)
    {
        char z[ PATH_MAX+1 ];

        if (realpath( pzBuf, z ) == NULL)
            return AG_FALSE;

        if (strlen(z) < bufSize)
            strcpy( pzBuf, z );
    }
#endif

    return AG_TRUE;
}
Esempio n. 2
0
/*=export_func  optionMakePath
 * private:
 *
 * what:  translate and construct a path
 * arg:   + char*       + pzBuf      + The result buffer +
 * arg:   + int         + bufSize    + The size of this buffer +
 * arg:   + char const* + pzName     + The input name +
 * arg:   + char const* + pzProgPath + The full path of the current program +
 *
 * ret-type: ag_bool
 * ret-desc: AG_TRUE if the name was handled, otherwise AG_FALSE.
 *           If the name does not start with ``$'', then it is handled
 *           simply by copying the input name to the output buffer and
 *           resolving the name with either
 *           @code{canonicalize_file_name(3GLIBC)} or @code{realpath(3C)}.
 *
 * doc:
 *
 *  This routine will copy the @code{pzName} input name into the
 *  @code{pzBuf} output buffer, not exceeding @code{bufSize} bytes.  If the
 *  first character of the input name is a @code{'$'} character, then there
 *  is special handling:
 *  @*
 *  @code{$$} is replaced with the directory name of the @code{pzProgPath},
 *  searching @code{$PATH} if necessary.
 *  @*
 *  @code{$@} is replaced with the AutoGen package data installation directory
 *  (aka @code{pkgdatadir}).
 *  @*
 *  @code{$NAME} is replaced by the contents of the @code{NAME} environment
 *  variable.  If not found, the search fails.
 *
 *  Please note: both @code{$$} and @code{$NAME} must be at the start of the
 *     @code{pzName} string and must either be the entire string or be followed
 *     by the @code{'/'} (backslash on windows) character.
 *
 * err:  @code{AG_FALSE} is returned if:
 *       @*
 *       @bullet{} The input name exceeds @code{bufSize} bytes.
 *       @*
 *       @bullet{} @code{$$}, @code{$@@} or @code{$NAME} is not the full string
 *                 and the next character is not '/'.
 *       @*
 *       @bullet{} libopts was built without PKGDATADIR defined and @code{$@@}
 *                 was specified.
 *       @*
 *       @bullet{} @code{NAME} is not a known environment variable
 *       @*
 *       @bullet{} @code{canonicalize_file_name} or @code{realpath} return
 *                 errors (cannot resolve the resulting path).
=*/
ag_bool
optionMakePath(char * pzBuf, int bufSize, char const * pzName,
               char const * pzProgPath)
{
    size_t name_len = strlen(pzName);

    if ((bufSize <= name_len) || (name_len == 0))
        return AG_FALSE;

    /*
     *  IF not an environment variable, just copy the data
     */
    if (*pzName != '$') {
        char const*  pzS = pzName;
        char* pzD = pzBuf;
        int   ct  = bufSize;

        for (;;) {
            if ( (*(pzD++) = *(pzS++)) == NUL)
                break;
            if (--ct <= 0)
                return AG_FALSE;
        }
    }

    /*
     *  IF the name starts with "$$", then it must be "$$" or
     *  it must start with "$$/".  In either event, replace the "$$"
     *  with the path to the executable and append a "/" character.
     */
    else switch (pzName[1]) {
    case NUL:
        return AG_FALSE;

    case '$':
        if (! insertProgramPath(pzBuf, bufSize, pzName, pzProgPath))
            return AG_FALSE;
        break;

    case '@':
        if (program_pkgdatadir[0] == NUL)
            return AG_FALSE;

        if (snprintf(pzBuf, bufSize, "%s%s", program_pkgdatadir, pzName + 2)
            >= bufSize)
            return AG_FALSE;
        break;

    default:
        if (! insertEnvVal(pzBuf, bufSize, pzName, pzProgPath))
            return AG_FALSE;
    }

#if defined(HAVE_CANONICALIZE_FILE_NAME)
    {
        char * pz = canonicalize_file_name(pzBuf);
        if (pz == NULL)
            return AG_FALSE;

        name_len = strlen(pz);
        if (name_len >= bufSize) {
            free(pz);
            return AG_FALSE;
        }

        memcpy(pzBuf, pz, name_len + 1);
        free(pz);
    }

#elif defined(HAVE_REALPATH)
    {
        char z[PATH_MAX+1];

        if (realpath(pzBuf, z) == NULL)
            return AG_FALSE;

        name_len = strlen(z);
        if (name_len >= bufSize)
            return AG_FALSE;

        memcpy(pzBuf, z, name_len + 1);
    }
#endif

    return AG_TRUE;
}