/*=export_func optionMakePath * private: * * what: translate and construct a path * arg: + char * + p_buf + The result buffer + * arg: + int + b_sz + The size of this buffer + * arg: + char const * + fname + The input name + * arg: + char const * + prg_path + The full path of the current program + * * ret-type: bool * ret-desc: true if the name was handled, otherwise 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{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). =*/ bool optionMakePath(char * p_buf, int b_sz, char const * fname, char const * prg_path) { { size_t len = strlen(fname); if (((size_t)b_sz <= len) || (len == 0)) return false; } /* * IF not an environment variable, just copy the data */ if (*fname != '$') { char const * src = fname; char * dst = p_buf; int ct = b_sz; for (;;) { if ( (*(dst++) = *(src++)) == NUL) break; if (--ct <= 0) return 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 (fname[1]) { case NUL: return false; case '$': if (! add_prog_path(p_buf, b_sz, fname, prg_path)) return false; break; case '@': if (program_pkgdatadir[0] == NUL) return false; if (snprintf(p_buf, (size_t)b_sz, "%s%s", program_pkgdatadir, fname + 2) >= b_sz) return false; break; default: if (! add_env_val(p_buf, b_sz, fname)) return false; } return get_realpath(p_buf, b_sz); }
/*=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: bool * ret-desc: true if the name was handled, otherwise 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{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). =*/ bool optionMakePath(char * pzBuf, int bufSize, char const * pzName, char const * pzProgPath) { size_t name_len = strlen(pzName); if (((size_t)bufSize <= name_len) || (name_len == 0)) return 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 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 false; case '$': if (! add_prog_path(pzBuf, bufSize, pzName, pzProgPath)) return false; break; case '@': if (program_pkgdatadir[0] == NUL) return false; if (snprintf(pzBuf, bufSize, "%s%s", program_pkgdatadir, pzName + 2) >= bufSize) return false; break; default: if (! add_env_val(pzBuf, bufSize, pzName)) return false; } #if defined(HAVE_CANONICALIZE_FILE_NAME) { char * pz = canonicalize_file_name(pzBuf); if (pz == NULL) return false; name_len = strlen(pz); if (name_len >= (size_t)bufSize) { free(pz); return false; } memcpy(pzBuf, pz, name_len + 1); free(pz); } #elif defined(HAVE_REALPATH) { char z[PATH_MAX+1]; if (realpath(pzBuf, z) == NULL) return false; name_len = strlen(z); if (name_len >= bufSize) return false; memcpy(pzBuf, z, name_len + 1); } #endif return true; }