/*=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; }
/*=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; }