X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2F3dengfx%2Fsrc%2Fcommon%2Flocator.c;fp=src%2F3dengfx%2Fsrc%2Fcommon%2Flocator.c;h=79f37321d0c53aa60cf037d6655ad17f36088242;hb=6e23259dbabaeb1711a2a5ca25b9cb421f693759;hp=0000000000000000000000000000000000000000;hpb=fe068fa879814784c45e0cb2e65dac489e8f5594;p=summerhack diff --git a/src/3dengfx/src/common/locator.c b/src/3dengfx/src/common/locator.c new file mode 100644 index 0000000..79f3732 --- /dev/null +++ b/src/3dengfx/src/common/locator.c @@ -0,0 +1,172 @@ +/* +This is a small cross-platform resource file locator library. +Author: John Tsiombikas 2004 + +This library is public domain, you are free to do whatever you like with it, +NO WARANTY whatsoever is provided with this library, use it at your own risk. +*/ + +#include +#include +#include +#include "locator.h" + +#ifdef HAVE_CONFIG +#include "config.h" +#endif /* HAVE_CONFIG */ + +#ifdef __unix__ +#define __USE_BSD /* to include readlink() prototype */ +#include + +#define DIR_SEP '/' +#define HOME_ENV "HOME" + +#else /* assume WIN32 */ +#include + +#define DIR_SEP '\\' +#define HOME_ENV "USERPROFILE" + +#endif /* __unix__ */ + + +#ifndef PREFIX +#define PREFIX "" +#endif /* PREFIX */ + +#define MAX_PATH 1024 +#define CONF_ENV "NLOC_CONFIG_PATH" +#define DATA_ENV "NLOC_DATA_PATH" +#define LOC_FUNC_COUNT 2 + +typedef const char *(*loc_func_type)(const char*); + +static const char *locate_config(const char *file); +static const char *locate_data(const char *file); +static const char *exec_path(void); + +static char path[MAX_PATH]; +static loc_func_type loc_func[LOC_FUNC_COUNT] = {locate_config, locate_data}; + +const char *loc_get_path(const char *file, enum loc_file_type file_type) { + if(file_type >= LOC_FUNC_COUNT) return 0; + return loc_func[file_type](file); +} + +static const char *locate_config(const char *file) { + FILE *fp; + char *env, *pptr = path; + const char *ex_path, *fptr = file; + + /* first try $NLOC_CONFIG_PATH/file */ + env = getenv(CONF_ENV); + if(env) { + while(*env) *pptr++ = *env++; + if(*(env - 1) != DIR_SEP) *pptr++ = DIR_SEP; + while(*fptr) *pptr++ = *fptr++; + *pptr++ = 0; + + fprintf(stderr, "trying: %s\n", path); + if((fp = fopen(path, "r"))) { + fclose(fp); + return path; + } + } + + /* then try $HOME/.file */ + pptr = path; + fptr = file; + env = getenv(HOME_ENV); + if(env) { + while(*env) *pptr++ = *env++; + if(*(env - 1) != DIR_SEP) *pptr++ = DIR_SEP; +#ifdef __unix__ + *pptr++ = '.'; +#endif /* __unix__ */ + while(*fptr) *pptr++ = *fptr++; + *pptr++ = 0; + + fprintf(stderr, "trying: %s\n", path); + if((fp = fopen(path, "r"))) { + fclose(fp); + return path; + } + } + +#ifdef __unix__ + /* then PREFIX/etc/file */ + strcpy(path, PREFIX); + strcat(path, "/etc/"); + strcat(path, file); + + fprintf(stderr, "trying: %s\n", path); + if((fp = fopen(path, "r"))) { + fclose(fp); + return path; + } +#else + /* or something similar on win32 */ + env = getenv("ALLUSERSPROFILE"); + if(env) { + strcpy(path, env); + strcat(path, "\\"); + strcat(path, file); + + fprintf(stderr, "trying: %s\n", path); + if((fp = fopen(path, "r"))) { + fclose(fp); + return path; + } + } +#endif /* __unix__ */ + + + /* finally as a last resort try the executable directory, this may not work */ + if((ex_path = exec_path())) { + strcpy(path, ex_path); + strcat(path, file); + + fprintf(stderr, "trying: %s\n", path); + if((fp = fopen(path, "r"))) { + fclose(fp); + return path; + } + } + + return 0; +} + +/* TODO: not implemented yet */ +static const char *locate_data(const char *file) { + return 0; +} + +static const char *exec_path(void) { + static char path[MAX_PATH]; + int ccount = 0; + char *ptr; + +#ifdef __linux__ + ccount = readlink("/proc/self/exe", path, MAX_PATH - 1); +#endif /* __linux__ */ + +#ifdef __FreeBSD__ + ccount = readlink("/proc/curproc/file", path, MAX_PATH - 1); +#endif /* __FreeBSD__ */ + +#ifdef WIN32 + ccount = GetModuleFileName(0, path, MAX_PATH - 1); +#endif /* WIN32 */ + + if(!ccount) return 0; + + path[ccount] = 0; + + ptr = strrchr(path, DIR_SEP); + if(!ptr) return 0; + + *(ptr + 1) = 0; + + return path; +}